xuwenqiang1992 2 gadi atpakaļ
vecāks
revīzija
150730c1b5
100 mainītis faili ar 21628 papildinājumiem un 0 dzēšanām
  1. 16 0
      .hbuilderx/launch.json
  2. 21 0
      LICENSE
  3. 106 0
      README.md
  4. 184 0
      colorui/animation.css
  5. 65 0
      colorui/components/cu-custom.vue
  6. 1226 0
      colorui/icon.css
  7. 3922 0
      colorui/main.css
  8. 3625 0
      common/css/animate.css
  9. 117 0
      common/css/common.css
  10. 6 0
      common/css/icon.css
  11. 1458 0
      common/css/uni.css
  12. 813 0
      common/css/zcm-main-nvue.css
  13. 1153 0
      common/css/zcm-main.css
  14. 16 0
      common/filter/filters.js
  15. 187 0
      common/libs/request.js
  16. 133 0
      components/app-continue-scancode/app-continue-scancode.vue
  17. 910 0
      iconfont.css
  18. 141 0
      index.js
  19. 23 0
      index.scss
  20. 15 0
      libs/config/config.js
  21. 20 0
      libs/config/zIndex.js
  22. 155 0
      libs/css/color.scss
  23. 176 0
      libs/css/common.scss
  24. 7 0
      libs/css/style.components.scss
  25. 8 0
      libs/css/style.h5.scss
  26. 72 0
      libs/css/style.mp.scss
  27. 3 0
      libs/css/style.nvue.scss
  28. 175 0
      libs/css/style.vue.scss
  29. 18 0
      libs/function/$parent.js
  30. 8 0
      libs/function/addUnit.js
  31. 5 0
      libs/function/bem.js
  32. 37 0
      libs/function/color.js
  33. 134 0
      libs/function/colorGradient.js
  34. 29 0
      libs/function/debounce.js
  35. 23 0
      libs/function/deepClone.js
  36. 30 0
      libs/function/deepMerge.js
  37. 47 0
      libs/function/getParent.js
  38. 41 0
      libs/function/guid.js
  39. 385 0
      libs/function/md5.js
  40. 58 0
      libs/function/queryParams.js
  41. 10 0
      libs/function/random.js
  42. 7 0
      libs/function/randomArray.js
  43. 122 0
      libs/function/route.js
  44. 9 0
      libs/function/sys.js
  45. 232 0
      libs/function/test.js
  46. 32 0
      libs/function/throttle.js
  47. 51 0
      libs/function/timeFormat.js
  48. 47 0
      libs/function/timeFrom.js
  49. 9 0
      libs/function/toast.js
  50. 15 0
      libs/function/trim.js
  51. 35 0
      libs/function/type2icon.js
  52. 64 0
      libs/mixin/mixin.js
  53. 18 0
      libs/mixin/mpShare.js
  54. 169 0
      libs/request/index.js
  55. 19 0
      libs/store/index.js
  56. 1 0
      libs/util/area.js
  57. 1356 0
      libs/util/async-validator.js
  58. 1 0
      libs/util/city.js
  59. 51 0
      libs/util/emitter.js
  60. 1 0
      libs/util/province.js
  61. 31 0
      package.json
  62. 394 0
      pages/feedback/print.vue
  63. 193 0
      pages/feedback/scanOrderCode.vue
  64. 94 0
      pages/index/me.vue
  65. 22 0
      pages/index/order.vue
  66. 111 0
      pages/index/tabbar.vue
  67. 300 0
      pages/index/workTable.vue
  68. 236 0
      pages/login/login.vue
  69. BIN
      static/2.png
  70. BIN
      static/3.png
  71. 79 0
      static/iconfont/iconfont.css
  72. BIN
      static/iconfont/iconfont.ttf
  73. BIN
      static/iconfont/iconfont.woff
  74. BIN
      static/iconfont/iconfont.woff2
  75. BIN
      static/tabbar/me.png
  76. BIN
      static/tabbar/me_cur.png
  77. BIN
      static/tabbar/message.png
  78. BIN
      static/tabbar/message_cur.png
  79. BIN
      static/tabbar/order.png
  80. BIN
      static/tabbar/order_cur.png
  81. BIN
      static/tabbar/workTable.png
  82. BIN
      static/tabbar/workTable_cur.png
  83. BIN
      static/uni.ttf
  84. 38 0
      theme.scss
  85. 33 0
      uni_modules/uni-badge/changelog.md
  86. 268 0
      uni_modules/uni-badge/components/uni-badge/uni-badge.vue
  87. 85 0
      uni_modules/uni-badge/package.json
  88. 10 0
      uni_modules/uni-badge/readme.md
  89. 26 0
      uni_modules/uni-calendar/changelog.md
  90. 546 0
      uni_modules/uni-calendar/components/uni-calendar/calendar.js
  91. 12 0
      uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
  92. 8 0
      uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
  93. 12 0
      uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
  94. 12 0
      uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
  95. 187 0
      uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
  96. 566 0
      uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
  97. 360 0
      uni_modules/uni-calendar/components/uni-calendar/util.js
  98. 85 0
      uni_modules/uni-calendar/package.json
  99. 103 0
      uni_modules/uni-calendar/readme.md
  100. 0 0
      uni_modules/uni-card/changelog.md

+ 16 - 0
.hbuilderx/launch.json

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

+ 21 - 0
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
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应用到您的产品中。

+ 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>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1226 - 0
colorui/icon.css


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 3922 - 0
colorui/main.css


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 3625 - 0
common/css/animate.css


+ 117 - 0
common/css/common.css

@@ -0,0 +1,117 @@
+/* 设置全局样式 */
+/* (1) 页面高度100%,默认字体28upx,默认行高1.8,背景颜色 */
+page {
+	height: 100%;
+	font-size: 28upx;
+	line-height: 1.8;
+	background: #FFFFFF;
+}
+
+/* (2) 图片默认100%宽度 */
+image {
+	width: 100%;
+}
+
+::-webkit-scrollbar {
+	display: none;
+}
+
+/* 主色调 */
+/* 主背景颜色(橙色)*/
+.main-bg-color {
+	background-color: #FD6801;
+}
+
+/* 主点击背景颜色(淡橙色)*/
+.main-bg-hover-color {
+	background-color: rgba(253, 104, 1, 0.85);
+}
+
+/* 主字体颜色(橙色)*/
+.main-text-color {
+	color: #FD6801;
+}
+
+/* 主边框颜色 */
+.main-border-color {
+	border-color: #F1F1F1;
+}
+
+.home-icon {
+ 	width: 48px;
+ 	height: 48px;
+	align-items: center;
+ 	border-radius: 6px;
+ 	box-sizing: border-box;
+	display: flex;
+	justify-content: center;
+	color:#ffffff;
+	font-size: 26px;
+ }
+ .home-icon i{
+	font-size: 26px;
+ }
+.icon-color01{
+	 background: #ef8e35;
+	 border:1rpx solid #ef8e35;
+}
+.icon-color02{
+	 background-image: linear-gradient(0deg, #5a9aec, #84acf7);
+	 border:1rpx solid #6893d5;
+}
+.icon-color03{
+	 background-image: linear-gradient(0deg, #5fceb3, #61d2ba);
+	 border:1rpx solid #58c1ab;
+}
+.icon-color03{
+	 background-image: linear-gradient(0deg, #58ca93, #58ca93);
+	 border:1rpx solid #58c1ab;
+}
+.icon-color04{
+	 background-image: linear-gradient(0deg, #4f77ed, #4f77ed);
+	 border:1rpx solid #4f77ed;
+}
+.icon-color05{
+	 background-image: linear-gradient(0deg, #eb516b, #eb516c);
+	 border:1rpx solid #cc4962;
+}
+.icon-color06{
+	 background-image: linear-gradient(0deg, #F35643, #F35643);
+	 border:1rpx solid #F35643;
+}
+.icon-color07{
+	 background-image: linear-gradient(0deg, #4b86f6, #4b86f6);
+	 border:1rpx solid #4e7fd8;
+}
+.icon-color08{
+	 background-image: linear-gradient(0deg, #f2a953, #f2a953);
+	 border:1rpx solid #d2954c;
+}
+.icon-color09{
+	 background-image: linear-gradient(-30deg, #3b6eef, #3b6eef);
+	 border:1rpx solid #3663d1;
+}
+.icon-color10{
+	 background-image: linear-gradient(0deg, #59bef7, #58bcf6);
+	 border:1rpx solid #4ea6da;
+}
+.icon-color11{
+	 background:#ffffff;
+	 border:1rpx solid #ddddde;
+}
+.icon-color12{
+	 background-image: linear-gradient(0deg, #FFC60A, #FFC60A);
+	 border:1rpx solid #FFC60A;
+}
+.icon-color13{
+	 background:#f5f6f7;
+	 border:1rpx dashed #e1e1e3;
+}
+.home-icon{
+	position: relative;
+	.u-badge{
+		top:-8px!important;
+		right:-8px!important;
+		padding:1px 4px!important;
+	}
+}

+ 6 - 0
common/css/icon.css

@@ -0,0 +1,6 @@
+/* @font-face {
+  font-family: "iconfont";
+  src: url('~@/static/iconfont/iconfont.woff2?t=1642478325638') format('woff2'),
+       url('~@/static/iconfont/iconfont.woff?t=1642478325638') format('woff'),
+       url('~@/static/iconfont/iconfont.ttf?t=1642478325638') format('truetype');
+} */

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1458 - 0
common/css/uni.css


+ 813 - 0
common/css/zcm-main-nvue.css

@@ -0,0 +1,813 @@
+.scroll-row {
+	flex-direction: row;
+}
+
+/* 定位 */
+.position-absolute {
+	position: absolute;
+}
+
+.position-fixed {
+	position: fixed;
+}
+
+.position-relative {
+	position: relative;
+}
+
+.left-0 {
+	left: 0;
+}
+
+.top-0 {
+	top: 0;
+}
+
+.bottom-0 {
+	bottom: 0;
+}
+
+.right-0 {
+	right: 0;
+}
+
+/* 宽高 */
+.w-100 {
+	width: 750px;
+}
+
+.w-50 {
+	width: 375px;
+}
+
+.h-100 {
+	height: 1250px;
+}
+
+.h-50 {
+	width: 625px;
+}
+
+/* 字体 */
+.font {
+	font-size: 30rpx;
+}
+
+.font-sm {
+	font-size: 25rpx;
+}
+
+.font-md {
+	font-size: 35rpx !important;
+}
+
+.font-lg {
+	font-size: 40rpx;
+}
+
+.font-big {
+	font-size: 60rpx;
+}
+
+.font-weight {
+	font-weight: bold;
+}
+
+.font-weight-100 {
+	font-weight: 100 !important;
+}
+
+.line-through {
+	text-decoration: line-through;
+}
+
+
+/*  -- 栅格布局 -- */
+.row {
+	flex-direction: row;
+	flex-wrap: wrap;
+}
+
+.col-1 {
+	width: 62.5px;
+}
+
+.col-2 {
+	width: 125px;
+}
+
+.col-3 {
+	width: 187.5px;
+}
+
+.col-4 {
+	width: 250px;
+}
+
+.col-5 {
+	width: 312.5px;
+}
+
+.col-6 {
+	width: 375px;
+}
+
+.col-7 {
+	width: 437.5px;
+}
+
+.col-8 {
+	width: 500px;
+}
+
+.col-9 {
+	width: 562.5px;
+}
+
+.col-10 {
+	width: 625px;
+}
+
+.col-11 {
+	width: 687.5px;
+}
+
+.col-12 {
+	width: 750px;
+}
+
+/* flex布局 */
+.d-flex {
+	flex-direction: row;
+}
+
+.flex-1 {
+	flex: 1;
+}
+
+.flex-column {
+	flex-direction: column;
+}
+
+.flex-row {
+	flex-direction: row;
+}
+
+.flex-wrap {
+	flex-wrap: wrap;
+}
+
+.flex-nowrap {
+	flex-wrap: nowrap;
+}
+
+.j-start {
+	justify-content: flex-start;
+}
+
+.j-center {
+	justify-content: center;
+}
+
+.j-end {
+	justify-content: flex-end;
+}
+
+.j-sb {
+	justify-content: space-between;
+}
+
+.a-center {
+	align-items: center;
+}
+
+.a-start {
+	align-items: flex-start;
+}
+
+.a-end {
+	align-items: flex-end;
+}
+
+.a-stretch {
+	align-items: stretch;
+}
+
+/* Border */
+.border {
+	border-width: 1px;
+	border-style: solid;
+	border-color: #dee2e6;
+}
+
+.border-top {
+	border-top-width: 1px;
+	border-top-style: solid;
+	border-top-color: #dee2e6;
+}
+
+.border-right {
+	border-right-width: 1px;
+	border-right-style: solid;
+	border-right-color: #dee2e6;
+}
+
+.border-bottom {
+	border-bottom-width: 1px;
+	border-bottom-style: solid;
+	border-bottom-color: #dee2e6;
+}
+
+.border-left {
+	border-left-width: 1px;
+	border-left-style: solid;
+	border-left-color: #dee2e6;
+}
+
+.border-0 {
+	border-width: 0;
+}
+
+.border-top-0 {
+	border-top-width: 0;
+}
+
+.border-right-0 {
+	border-right-width: 0;
+}
+
+.border-bottom-0 {
+	border-bottom-width: 0;
+}
+
+.border-left-0 {
+	border-left-width: 0;
+}
+
+.border-primary {
+	border-color: #007bff
+}
+
+.border-secondary {
+	border-color: #6c757d
+}
+
+.border-success {
+	border-color: #6c757d
+}
+
+.border-danger {
+	border-color: #dc3545
+}
+
+.border-warning {
+	border-color: #ffc107
+}
+
+.border-info {
+	border-color: #17a2b8
+}
+
+.border-light {
+	border-color: #f8f9fa
+}
+
+.border-dark {
+	border-color: #343a40
+}
+
+.border-white {
+	border-color: #ffffff
+}
+
+.border-light-secondary {
+	border-color: #F1F1F1 !important;
+}
+
+.rounded {
+	border-radius: 5px;
+}
+
+.rounded-circle {
+	border-radius: 100%;
+}
+
+.rounded-0 {
+	border-radius: 0;
+}
+
+/* color */
+.text-primary {
+	color: #007bff;
+}
+
+.text-secondary {
+	color: #6c757d;
+}
+
+.text-success {
+	color: #6c757d;
+}
+
+.text-danger {
+	color: #dc3545;
+}
+
+.text-warning {
+	color: #ffc107;
+}
+
+.text-info {
+	color: #17a2b8;
+}
+
+.text-light {
+	color: #f8f9fa;
+}
+
+.text-dark {
+	color: #343a40;
+}
+
+.text-muted {
+	color: #6c757d;
+}
+
+.text-light-muted {
+	color: #B2B2B2 !important;
+}
+
+.text-white {
+	color: #ffffff;
+}
+
+.bg-primary {
+	background-color: #007bff;
+}
+
+.bg-secondary {
+	background-color: #6c757d;
+}
+
+.bg-success {
+	background-color: #6c757d;
+}
+
+.bg-danger {
+	background-color: #dc3545;
+}
+
+.bg-warning {
+	background-color: #ffc107;
+}
+
+.bg-info {
+	background-color: #17a2b8;
+}
+
+.bg-light {
+	background-color: #f8f9fa;
+}
+
+.bg-dark {
+	background-color: #343a40;
+}
+
+.bg-white {
+	background-color: #ffffff;
+}
+
+/*  -- 内外边距 -- */
+.m-0 {
+	margin: 0;
+}
+
+/* #ifndef APP-PLUS-NVUE */
+.m-auto {
+	margin: auto;
+}
+
+/* #endif */
+.m-1 {
+	margin: 10rpx;
+}
+
+.m-2 {
+	margin: 20rpx;
+}
+
+.m-3 {
+	margin: 30rpx;
+}
+
+.m-4 {
+	margin: 40rpx;
+}
+
+.m-5 {
+	margin: 50rpx;
+}
+
+.mt-0 {
+	margin-top: 0;
+}
+
+/* #ifndef APP-PLUS-NVUE */
+.mt-auto {
+	margin-top: auto;
+}
+
+/* #endif */
+.mt-1 {
+	margin-top: 10rpx;
+}
+
+.mt-2 {
+	margin-top: 20rpx;
+}
+
+.mt-3 {
+	margin-top: 30rpx;
+}
+
+.mt-4 {
+	margin-top: 40rpx;
+}
+
+.mt-5 {
+	margin-top: 50rpx;
+}
+
+.mb-0 {
+	margin-bottom: 0;
+}
+
+/* #ifndef APP-PLUS-NVUE */
+.mb-auto {
+	margin-bottom: auto;
+}
+
+/* #endif */
+.mb-1 {
+	margin-bottom: 10rpx;
+}
+
+.mb-2 {
+	margin-bottom: 20rpx;
+}
+
+.mb-3 {
+	margin-bottom: 30rpx;
+}
+
+.mb-4 {
+	margin-bottom: 40rpx;
+}
+
+.mb-5 {
+	margin-bottom: 50rpx;
+}
+
+.ml-0 {
+	margin-left: 0;
+}
+
+/* #ifndef APP-PLUS-NVUE */
+.ml-auto {
+	margin-left: auto;
+}
+
+/* #endif */
+.ml-1 {
+	margin-left: 10rpx;
+}
+
+.ml-2 {
+	margin-left: 20rpx;
+}
+
+.ml-3 {
+	margin-left: 30rpx;
+}
+
+.ml-4 {
+	margin-left: 40rpx;
+}
+
+.ml-5 {
+	margin-left: 50rpx;
+}
+
+.mr-0 {
+	margin-right: 0;
+}
+
+/* #ifndef APP-PLUS-NVUE */
+.mr-auto {
+	margin-right: auto;
+}
+
+/* #endif */
+.mr-1 {
+	margin-right: 10rpx;
+}
+
+.mr-2 {
+	margin-right: 20rpx;
+}
+
+.mr-3 {
+	margin-right: 30rpx;
+}
+
+.mr-4 {
+	margin-right: 40rpx;
+}
+
+.mr-5 {
+	margin-right: 50rpx;
+}
+
+.my-0 {
+	margin-top: 0;
+	margin-bottom: 0;
+}
+
+/* #ifndef APP-PLUS-NVUE */
+.my-auto {
+	margin-top: auto;
+	margin-bottom: auto;
+}
+
+/* #endif */
+.my-1 {
+	margin-top: 10rpx;
+	margin-bottom: 10rpx;
+}
+
+.my-2 {
+	margin-top: 20rpx;
+	margin-bottom: 20rpx;
+}
+
+.my-3 {
+	margin-top: 30rpx;
+	margin-bottom: 30rpx;
+}
+
+.my-4 {
+	margin-top: 40rpx;
+	margin-bottom: 40rpx;
+}
+
+.my-5 {
+	margin-top: 50rpx;
+	margin-bottom: 50rpx;
+}
+
+.mx-0 {
+	margin-left: 0;
+	margin-right: 0;
+}
+
+/* #ifndef APP-PLUS-NVUE */
+.mx-auto {
+	margin-left: auto;
+	margin-right: auto;
+}
+
+/* #endif */
+.mx-1 {
+	margin-left: 10rpx;
+	margin-right: 10rpx;
+}
+
+.mx-2 {
+	margin-left: 20rpx;
+	margin-right: 20rpx;
+}
+
+.mx-3 {
+	margin-left: 30rpx;
+	margin-right: 30rpx;
+}
+
+.mx-4 {
+	margin-left: 40rpx;
+	margin-right: 40rpx;
+}
+
+.mx-5 {
+	margin-left: 50rpx;
+	margin-right: 50rpx;
+}
+
+.p-0 {
+	padding: 0;
+}
+
+.p {
+	padding: 5rpx;
+}
+
+.p-1 {
+	padding: 10rpx;
+}
+
+.p-2 {
+	padding: 20rpx;
+}
+
+.p-3 {
+	padding: 30rpx;
+}
+
+.p-4 {
+	padding: 40rpx;
+}
+
+.p-5 {
+	padding: 50rpx;
+}
+
+.pt-0 {
+	padding-top: 0;
+}
+
+.pt {
+	padding-top: 5rpx;
+}
+
+.pt-1 {
+	padding-top: 10rpx;
+}
+
+.pt-2 {
+	padding-top: 20rpx;
+}
+
+.pt-3 {
+	padding-top: 30rpx;
+}
+
+.pt-4 {
+	padding-top: 40rpx;
+}
+
+.pt-5 {
+	padding-top: 50rpx;
+}
+
+.pb-0 {
+	padding-bottom: 0;
+}
+
+.pb-1 {
+	padding-bottom: 10rpx;
+}
+
+.pb {
+	padding-bottom: 5rpx;
+}
+
+.pb-2 {
+	padding-bottom: 20rpx;
+}
+
+.pb-3 {
+	padding-bottom: 30rpx;
+}
+
+.pb-4 {
+	padding-bottom: 40rpx;
+}
+
+.pb-5 {
+	padding-bottom: 50rpx;
+}
+
+.pl-0 {
+	padding-left: 0;
+}
+
+.pl {
+	padding-left: 5rpx;
+}
+
+.pl-1 {
+	padding-left: 10rpx;
+}
+
+.pl-2 {
+	padding-left: 20rpx;
+}
+
+.pl-3 {
+	padding-left: 30rpx;
+}
+
+.pl-4 {
+	padding-left: 40rpx;
+}
+
+.pl-5 {
+	padding-left: 50rpx;
+}
+
+.pr-0 {
+	padding-right: 0;
+}
+
+.pr {
+	padding-right: 5rpx;
+}
+
+.pr-1 {
+	padding-right: 10rpx;
+}
+
+.pr-2 {
+	padding-right: 20rpx;
+}
+
+.pr-3 {
+	padding-right: 30rpx;
+}
+
+.pr-4 {
+	padding-right: 40rpx;
+}
+
+.pr-5 {
+	padding-right: 50rpx;
+}
+
+.py-0 {
+	padding-top: 0;
+	padding-bottom: 0;
+}
+
+.py {
+	padding-top: 5rpx;
+	padding-bottom: 5rpx;
+}
+
+.py-1 {
+	padding-top: 10rpx;
+	padding-bottom: 10rpx;
+}
+
+.py-2 {
+	padding-top: 20rpx;
+	padding-bottom: 20rpx;
+}
+
+.py-3 {
+	padding-top: 30rpx;
+	padding-bottom: 30rpx;
+}
+
+.py-4 {
+	padding-top: 40rpx;
+	padding-bottom: 40rpx;
+}
+
+.py-5 {
+	padding-top: 50rpx;
+	padding-bottom: 50rpx;
+}
+
+.px-0 {
+	padding-left: 0;
+	padding-right: 0;
+}
+
+.px-1 {
+	padding-left: 10rpx;
+	padding-right: 10rpx;
+}
+
+.px {
+	padding-left: 5rpx;
+	padding-right: 5rpx;
+}
+
+.px-2 {
+	padding-left: 20rpx;
+	padding-right: 20rpx;
+}
+
+.px-3 {
+	padding-left: 30rpx;
+	padding-right: 30rpx;
+}
+
+.px-4 {
+	padding-left: 40rpx;
+	padding-right: 40rpx;
+}
+
+.px-5 {
+	padding-left: 50rpx;
+	padding-right: 50rpx;
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1153 - 0
common/css/zcm-main.css


+ 16 - 0
common/filter/filters.js

@@ -0,0 +1,16 @@
+export const fliters = {
+	getTime: time => {
+		if (time) {
+			var str = time.substring(0, 19)
+			return str
+		}
+	},
+	ignoreNull: src => {
+		// console.log(typeof(src));
+		// console.log(src);
+		if ((src) && (src != null) && (src != undefined)) {
+			return src;
+		}
+		return ""
+	}
+}

+ 187 - 0
common/libs/request.js

@@ -0,0 +1,187 @@
+const devBaseUrl = "http://192.168.1.17:8080";
+const proBaseUrl = "http://192.168.1.17:8080";
+//const proBaseUrl = "http://61.163.210.202:39510";
+// const devBaseUrl = "http://218.3.230.230:39510";
+// const proBaseUrl = "http://218.3.230.230:39510"; 
+
+
+const httpGet = (url, data, checkToken = true) => {
+	uni.onNetworkStatusChange(function(res) {
+		if (!res.isConnected) {
+			uni.showToast({
+				title: '网络连接不可用!',
+				icon: 'none'
+			});
+		}
+		return false
+	});
+
+	let token = uni.getStorageSync('erpToken');
+	if (checkToken) {
+		if (token == '' || token == undefined || token == null) {
+			uni.showToast({
+				title: '账号已过期,请重新登录',
+				icon: 'none',
+				complete: function() {
+					uni.reLaunch({
+						url: '/pages/login/index'
+					});
+				}
+			});
+		}
+	}
+
+	let baseUrl = devBaseUrl;
+	if (process.env.NODE_ENV === 'production') {
+		baseUrl = proBaseUrl
+	}
+	console.log(baseUrl);
+	let httpDefaultOpts = {
+		url:  baseUrl + url,
+		data: data,
+		method: 'GET',
+		header: {
+			'Access-Token': token,
+			'X-Requested-With': 'XMLHttpRequest',
+			"Accept": "application/json",
+			"Content-Type": "application/json; charset=UTF-8"
+		},
+		dataType: 'json',
+	}
+	let promise = new Promise(function(resolve, reject) {
+		uni.request(httpDefaultOpts).then(
+			res => {
+				resolve(res[1].data);
+			}
+		).catch(
+			(response) => {
+				reject(response)
+			}
+		)
+	})
+	return promise
+};
+
+const httpPost = (url, data, checkToken = true) => {
+	uni.onNetworkStatusChange(function(res) {
+		if (!res.isConnected) {
+			uni.showToast({
+				title: '网络连接不可用!',
+				icon: 'none'
+			});
+		}
+		return false
+	});
+
+	let token = uni.getStorageSync('erpToken');
+	if (checkToken) {
+		if (token == '' || token == undefined || token == null) {
+			uni.showToast({
+				title: '账号已过期,请重新登录',
+				icon: 'none',
+				complete: function() {
+					uni.reLaunch({
+						url: '/pages/login/login'
+					});
+				}
+			});
+		}
+	}
+
+	let baseUrl = devBaseUrl;
+	if (process.env.NODE_ENV === 'production') {
+		baseUrl = proBaseUrl
+	}
+	let httpDefaultOpts = {
+		url: baseUrl + url,
+		data: data,
+		method: 'POST',
+		header: {
+			'Access-Token': token,
+			'X-Requested-With': 'XMLHttpRequest',
+			"Accept": "application/json",
+			"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
+		},
+		dataType: 'json',
+	}
+	let promise = new Promise(function(resolve, reject) {
+		uni.request(httpDefaultOpts).then(
+			(res) => {
+				if (res[1].data.httpCode == 401) {
+					uni.reLaunch({
+						url: '/pages/login/login'
+					});
+				}
+				resolve(res[1].data);
+			}
+		).catch(
+			(response) => {
+				reject(response)
+			}
+		)
+	})
+	return promise
+};
+
+const httpPostBody = (url, data, checkToken = true) => {
+	uni.onNetworkStatusChange(function(res) {
+		if (!res.isConnected) {
+			uni.showToast({
+				title: '网络连接不可用!',
+				icon: 'none'
+			});
+		}
+		return false
+	});
+	let token = uni.getStorageSync('erpToken');
+	if (checkToken) {
+		if (token == '' || token == undefined || token == null) {
+			uni.showToast({
+				title: '账号已过期,请重新登录',
+				icon: 'none',
+				complete: function() {
+					uni.reLaunch({
+						url: '/pages/login/index'
+					});
+				}
+			});
+			return;
+		}
+	}
+
+
+	let baseUrl = devBaseUrl;
+	if (process.env.NODE_ENV === 'production') {
+		baseUrl = proBaseUrl
+	}
+	let httpDefaultOpts = {
+		url: baseUrl + url,
+		data: data,
+		method: 'POST',
+		header: {
+			'Access-Token': token,
+			'X-Requested-With': 'XMLHttpRequest',
+			"Accept": "application/json",
+			"Content-Type": "application/json; charset=UTF-8"
+		},
+		dataType: 'json',
+	}
+	let promise = new Promise(function(resolve, reject) {
+		uni.request(httpDefaultOpts).then(
+			(res) => {
+				resolve(res[1].data);
+			}
+		).catch(
+			(response) => {
+				reject(response)
+			}
+		)
+	})
+	return promise
+};
+
+export default {
+	httpGet,
+	httpPost,
+	httpPostBody
+}

+ 133 - 0
components/app-continue-scancode/app-continue-scancode.vue

@@ -0,0 +1,133 @@
+<template>
+	<view class="app-scan-container">
+
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "app-continue-scancode",
+		data() {
+			return {
+				value: '',
+				timer: null,
+				barcode: null,
+				scanCodes: [],
+				viewContent: null,
+				codeType: [
+					plus.barcode.CODE128,
+					plus.barcode.QR,
+					plus.barcode.EAN13,
+					plus.barcode.EAN8,
+					plus.barcode.UPCA,
+					plus.barcode.UPCE,
+					plus.barcode.CODABAR,
+					plus.barcode.CODE39,
+					plus.barcode.CODE93,
+					plus.barcode.ITF,
+				]
+			};
+		},
+		mounted() {
+			//使用H5+原生界面控件,参考https://ask.dcloud.net.cn/article/35036
+			const pages = getCurrentPages();
+			const page = pages[pages.length - 1];
+			// plus.navigator.setFullscreen(true); //全屏
+			const currentWebview = page.$getAppWebview();
+			this.initBarcode(currentWebview)
+			this.createView(currentWebview)
+		},
+		destroyed() {
+			this.closeBarcode()
+		},
+		methods: {
+			initBarcode(currentWebview) {
+				this.barcode = plus.barcode.create('barcode', this.codeType, {
+					top: '0px',
+					left: '0px',
+					width: '100%',
+					height: '300', //设置扫码框的高度
+					position: 'static',
+					scanbarColor: '#28E153',
+					frameColor: '#28E153'
+				});
+				this.barcode.onmarked = this.onmarked;
+				currentWebview.append(this.barcode);
+				const res = uni.getSystemInfoSync();
+				if (res.platform == 'android') {
+					//安卓机
+					this.barcode.start();
+				}
+			},
+			placeBeep() {
+				var innerAudioContext = uni.createInnerAudioContext();
+				innerAudioContext.autoplay = true;
+				innerAudioContext.src = 'http://61.163.210.202:10992/erp_updates/beep.mp3';
+				innerAudioContext.onPlay(() => {
+					console.log('开始播放');
+				});
+				innerAudioContext.onError((res) => {
+					console.log(res);
+					console.log(res.errMsg);
+					console.log(res.errCode);
+				});
+				// innerAudioContext.onEnded(() => {
+				//  innerAudioContext.destroy();
+				// });
+			},
+			async onmarked(type, result) {
+				//todo 播放音频
+				//this.placeBeep();
+				console.log('Success: type=' + type + ', result=' + result);
+				if (!result) return this.barcode && this.barcode.start();
+				this.timer = setTimeout(() => {
+					this.barcode && this.barcode.start();
+				}, 1000)
+				this.$emit('scanHitERPCode', {
+					code: result
+				})
+			},
+			closeBarcode() {
+				this.barcode && this.barcode.close();
+				this.viewContent && this.viewContent.close()
+				this.barcode = null
+				this.viewContent = null
+			},
+			// 创建展示类内容组件
+			createView(currentWebview) {
+				this.viewContent = new plus.nativeObj.View(
+					'content', {
+						top: '230px',
+						left: '0px',
+						height: '130px',
+						width: '100%'
+					},
+					[{
+						tag: 'font',
+						id: 'scanTips',
+						text: '将订单二维码放入框中进行扫描',
+						textStyles: {
+							size: '16px',
+							color: '#ffffff',
+							whiteSpace: 'normal'
+						},
+						position: {
+							top: '80px',
+							left: '10%',
+							width: '80%',
+							height: 'wrap_content'
+						}
+					}]
+				);
+				currentWebview.append(this.viewContent);
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.app-scan-container {
+		height: 100%;
+		overflow: hidden;
+	}
+</style>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 910 - 0
iconfont.css


+ 141 - 0
index.js

@@ -0,0 +1,141 @@
+// 引入全局mixin
+import mixin from './libs/mixin/mixin.js'
+// 引入关于是否mixin集成小程序分享的配置
+// import wxshare from './libs/mixin/mpShare.js'
+// 全局挂载引入http相关请求拦截插件
+import http from './libs/request'
+
+function wranning(str) {
+	// 开发环境进行信息输出,主要是一些报错信息
+	// 这个环境的来由是在程序编写时候,点击hx编辑器运行调试代码的时候,详见:
+	// 	https://uniapp.dcloud.io/frame?id=%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e5%92%8c%e7%94%9f%e4%ba%a7%e7%8e%af%e5%a2%83
+	if (process.env.NODE_ENV === 'development') {
+		console.warn(str)
+	}
+}
+
+// 尝试判断在根目录的/store中是否有$u.mixin.js,此文件uView默认为需要挂在到全局的vuex的state变量
+// HX2.6.11版本,放到try中,控制台依然会警告,暂时不用此方式,
+// let vuexStore = {};
+// try {
+// 	vuexStore = require("@/store/$u.mixin.js");
+// } catch (e) {
+// 	//TODO handle the exception
+// }
+
+// post类型对象参数转为get类型url参数
+import queryParams from './libs/function/queryParams.js'
+// 路由封装
+import route from './libs/function/route.js'
+// 时间格式化
+import timeFormat from './libs/function/timeFormat.js'
+// 时间戳格式化,返回多久之前
+import timeFrom from './libs/function/timeFrom.js'
+// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
+import colorGradient from './libs/function/colorGradient.js'
+// 生成全局唯一guid字符串
+import guid from './libs/function/guid.js'
+// 主题相关颜色,info|success|warning|primary|default|error,此颜色已在uview.scss中定义,但是为js中也能使用,故也定义一份
+import color from './libs/function/color.js'
+// 根据type获取图标名称
+import type2icon from './libs/function/type2icon.js'
+// 打乱数组的顺序
+import randomArray from './libs/function/randomArray.js'
+// 对象和数组的深度克隆
+import deepClone from './libs/function/deepClone.js'
+// 对象深度拷贝
+import deepMerge from './libs/function/deepMerge.js'
+// 添加单位
+import addUnit from './libs/function/addUnit.js'
+
+// 规则检验
+import test from './libs/function/test.js'
+// 随机数
+import random from './libs/function/random.js'
+// 去除空格
+import trim from './libs/function/trim.js'
+// toast提示,对uni.showToast的封装
+import toast from './libs/function/toast.js'
+// 获取父组件参数
+import getParent from './libs/function/getParent.js'
+// 获取整个父组件
+import $parent from './libs/function/$parent.js'
+// 获取sys()和os()工具方法
+// 获取设备信息,挂载到$u的sys()(system的缩写)属性中,
+// 同时把安卓和ios平台的名称"ios"和"android"挂到$u.os()中,方便取用
+import {sys, os} from './libs/function/sys.js'
+// 防抖方法
+import debounce from './libs/function/debounce.js'
+// 节流方法
+import throttle from './libs/function/throttle.js'
+
+
+// 配置信息
+import config from './libs/config/config.js'
+// 各个需要fixed的地方的z-index配置文件
+import zIndex from './libs/config/zIndex.js'
+
+const $u = {
+	queryParams: queryParams,
+	route: route,
+	timeFormat: timeFormat,
+	date: timeFormat, // 另名date
+	timeFrom,
+	colorGradient: colorGradient.colorGradient,
+	colorToRgba: colorGradient.colorToRgba,
+	guid,
+	color,
+	sys,
+	os,
+	type2icon,
+	randomArray,
+	wranning,
+	get: http.get,
+	post: http.post,
+	put: http.put,
+	'delete': http.delete,
+	hexToRgb: colorGradient.hexToRgb,
+	rgbToHex: colorGradient.rgbToHex,
+	test,
+	random,
+	deepClone,
+	deepMerge,
+	getParent,
+	$parent,
+	addUnit,
+	trim,
+	type: ['primary', 'success', 'error', 'warning', 'info'],
+	http,
+	toast,
+	config, // uView配置信息相关,比如版本号
+	zIndex,
+	debounce,
+	throttle,
+}
+
+// $u挂载到uni对象上
+uni.$u = $u
+
+const install = Vue => {
+	Vue.mixin(mixin) 
+	if (Vue.prototype.openShare) {
+		Vue.mixin(mpShare);
+	}
+	// Vue.mixin(vuexStore);
+	// 时间格式化,同时两个名称,date和timeFormat
+	Vue.filter('timeFormat', (timestamp, format) => {
+		return timeFormat(timestamp, format)
+	})
+	Vue.filter('date', (timestamp, format) => {
+		return timeFormat(timestamp, format)
+	})
+	// 将多久以前的方法,注入到全局过滤器
+	Vue.filter('timeFrom', (timestamp, format) => {
+		return timeFrom(timestamp, format)
+	})
+	Vue.prototype.$u = $u
+}
+
+export default {
+	install
+}

+ 23 - 0
index.scss

@@ -0,0 +1,23 @@
+// 引入公共基础类
+@import "./libs/css/common.scss";
+@import "./libs/css/color.scss";
+
+// 非nvue的样式
+/* #ifndef APP-NVUE */
+@import "./libs/css/style.vue.scss";
+/* #endif */
+
+// nvue的特有样式
+/* #ifdef APP-NVUE */
+@import "./libs/css/style.nvue.scss";
+/* #endif */
+
+// 小程序特有的样式
+/* #ifdef MP */
+@import "./libs/css/style.mp.scss";
+/* #endif */
+
+// H5特有的样式
+/* #ifdef H5 */
+@import "./libs/css/style.h5.scss";
+/* #endif */

+ 15 - 0
libs/config/config.js

@@ -0,0 +1,15 @@
+// 此版本发布于2022-04-19
+let version = '1.8.6';
+
+export default {
+	v: version,
+	version: version,
+	// 主题名称
+	type: [
+		'primary',
+		'success',
+		'info',
+		'error',
+		'warning'
+	]
+}

+ 20 - 0
libs/config/zIndex.js

@@ -0,0 +1,20 @@
+// uniapp在H5中各API的z-index值如下:
+/**
+ * actionsheet: 999
+ * modal: 999
+ * navigate: 998
+ * tabbar: 998
+ * toast: 999
+ */
+
+export default {
+	toast: 10090,
+	noNetwork: 10080,
+	// popup包含popup,actionsheet,keyboard,picker的值
+	popup: 10075,
+	mask: 10070,
+	navbar: 980,
+	topTips: 975,
+	sticky: 970,
+	indexListSticky: 965,
+}

+ 155 - 0
libs/css/color.scss

@@ -0,0 +1,155 @@
+.u-type-primary-light {
+	color: $u-type-primary-light;
+}
+
+.u-type-warning-light {
+	color: $u-type-warning-light;
+}
+
+.u-type-success-light {
+	color: $u-type-success-light;
+}
+
+.u-type-error-light {
+	color: $u-type-error-light;
+}
+
+.u-type-info-light {
+	color: $u-type-info-light;
+}
+
+.u-type-primary-light-bg {
+	background-color: $u-type-primary-light;
+}
+
+.u-type-warning-light-bg {
+	background-color: $u-type-warning-light;
+}
+
+.u-type-success-light-bg {
+	background-color: $u-type-success-light;
+}
+
+.u-type-error-light-bg {
+	background-color: $u-type-error-light;
+}
+
+.u-type-info-light-bg {
+	background-color: $u-type-info-light;
+}
+
+.u-type-primary-dark {
+	color: $u-type-primary-dark;
+}
+
+.u-type-warning-dark {
+	color: $u-type-warning-dark;
+}
+
+.u-type-success-dark {
+	color: $u-type-success-dark;
+}
+
+.u-type-error-dark {
+	color: $u-type-error-dark;
+}
+
+.u-type-info-dark {
+	color: $u-type-info-dark;
+}
+
+.u-type-primary-dark-bg {
+	background-color: $u-type-primary-dark;
+}
+
+.u-type-warning-dark-bg {
+	background-color: $u-type-warning-dark;
+}
+
+.u-type-success-dark-bg {
+	background-color: $u-type-success-dark;
+}
+
+.u-type-error-dark-bg {
+	background-color: $u-type-error-dark;
+}
+
+.u-type-info-dark-bg {
+	background-color: $u-type-info-dark;
+}
+
+.u-type-primary-disabled {
+	color: $u-type-primary-disabled;
+}
+
+.u-type-warning-disabled {
+	color: $u-type-warning-disabled;
+}
+
+.u-type-success-disabled {
+	color: $u-type-success-disabled;
+}
+
+.u-type-error-disabled {
+	color: $u-type-error-disabled;
+}
+
+.u-type-info-disabled {
+	color: $u-type-info-disabled;
+}
+
+.u-type-primary {
+	color: $u-type-primary;
+}
+
+.u-type-warning {
+	color: $u-type-warning;
+}
+
+.u-type-success {
+	color: $u-type-success;
+}
+
+.u-type-error {
+	color: $u-type-error;
+}
+
+.u-type-info {
+	color: $u-type-info;
+}
+
+.u-type-primary-bg {
+	background-color: $u-type-primary;
+}
+
+.u-type-warning-bg {
+	background-color: $u-type-warning;
+}
+
+.u-type-success-bg {
+	background-color: $u-type-success;
+}
+
+.u-type-error-bg {
+	background-color: $u-type-error;
+}
+
+.u-type-info-bg {
+	background-color: $u-type-info;
+}
+
+.u-main-color {
+	color: $u-main-color;
+}
+
+.u-content-color {
+	color: $u-content-color;
+}
+
+.u-tips-color {
+	color: $u-tips-color;
+}
+
+.u-light-color {
+	color: $u-light-color;
+}

+ 176 - 0
libs/css/common.scss

@@ -0,0 +1,176 @@
+.u-relative,
+.u-rela {
+	position: relative;
+}
+
+.u-absolute,
+.u-abso {
+	position: absolute;
+}
+
+// nvue不能用标签命名样式,不能放在微信组件中,否则微信开发工具会报警告,无法使用标签名当做选择器
+/* #ifndef APP-NVUE */
+image {
+	display: inline-block;
+}
+
+// 在weex,也即nvue中,所有元素默认为border-box
+view,
+text {
+	box-sizing: border-box;
+}
+/* #endif */
+
+.u-font-xs {
+	font-size: 22rpx;
+}
+
+.u-font-sm {
+	font-size: 26rpx;
+}
+
+.u-font-md {
+	font-size: 28rpx;
+}
+
+.u-font-lg {
+	font-size: 30rpx;
+}
+
+.u-font-xl {
+	font-size: 34rpx;
+}
+
+.u-flex {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: row;
+	align-items: center;
+}
+
+.u-flex-wrap {
+	flex-wrap: wrap;
+}
+
+.u-flex-nowrap {
+	flex-wrap: nowrap;
+}
+
+.u-col-center {
+	align-items: center;
+}
+
+.u-col-top {
+	align-items: flex-start;
+}
+
+.u-col-bottom {
+	align-items: flex-end;
+}
+
+.u-row-center {
+	justify-content: center;
+}
+
+.u-row-left {
+	justify-content: flex-start;
+}
+
+.u-row-right {
+	justify-content: flex-end;
+}
+
+.u-row-between {
+	justify-content: space-between;
+}
+
+.u-row-around {
+	justify-content: space-around;
+}
+
+.u-text-left {
+	text-align: left;
+}
+
+.u-text-center {
+	text-align: center;
+}
+
+.u-text-right {
+	text-align: right;
+}
+
+.u-flex-col {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: column;
+}
+
+// 定义flex等分
+@for $i from 0 through 12 {
+	.u-flex-#{$i} {
+		flex: $i;
+	}
+}
+
+// 定义字体(px)单位,小于20都为px单位字体
+@for $i from 9 to 20 {
+	.u-font-#{$i} {
+		font-size: $i + px;
+	}
+}
+
+// 定义字体(rpx)单位,大于或等于20的都为rpx单位字体
+@for $i from 20 through 40 {
+	.u-font-#{$i} {
+		font-size: $i + rpx;
+	}
+}
+
+// 定义内外边距,历遍1-80
+@for $i from 0 through 80 {
+	// 只要双数和能被5除尽的数
+	@if $i % 2 == 0 or $i % 5 == 0 {
+		// 得出:u-margin-30或者u-m-30
+		.u-margin-#{$i}, .u-m-#{$i} {
+			margin: $i + rpx!important;
+		}
+		
+		// 得出:u-padding-30或者u-p-30
+		.u-padding-#{$i}, .u-p-#{$i} {
+			padding: $i + rpx!important;
+		}
+		
+		@each $short, $long in l left, t top, r right, b bottom {
+			// 缩写版,结果如: u-m-l-30
+			// 定义外边距
+			.u-m-#{$short}-#{$i} {
+				margin-#{$long}: $i + rpx!important;
+			}
+			
+			// 定义内边距
+			.u-p-#{$short}-#{$i} {
+				padding-#{$long}: $i + rpx!important;
+			}
+			
+			// 完整版,结果如:u-margin-left-30
+			// 定义外边距
+			.u-margin-#{$long}-#{$i} {
+				margin-#{$long}: $i + rpx!important;
+			}
+			
+			// 定义内边距
+			.u-padding-#{$long}-#{$i} {
+				padding-#{$long}: $i + rpx!important;
+			}
+		}
+	}
+}
+
+// 重置nvue的默认关于flex的样式
+.u-reset-nvue {
+	flex-direction: row;
+	align-items: center;
+}

+ 7 - 0
libs/css/style.components.scss

@@ -0,0 +1,7 @@
+// 定义混入指令,用于在非nvue环境下的flex定义,因为nvue没有display属性,会报错
+@mixin vue-flex($direction: row) {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	flex-direction: $direction;
+	/* #endif */
+}

+ 8 - 0
libs/css/style.h5.scss

@@ -0,0 +1,8 @@
+/* H5的时候,隐藏滚动条 */
+::-webkit-scrollbar {
+	display: none;  
+	width: 0 !important;  
+	height: 0 !important;  
+	-webkit-appearance: none;  
+	background: transparent;  
+}

+ 72 - 0
libs/css/style.mp.scss

@@ -0,0 +1,72 @@
+/* start--微信小程序编译后页面有组件名的元素,特别处理--start */
+/* #ifdef MP-WEIXIN || MP-QQ */
+u-td, u-th {
+	flex: 1;
+	align-self: stretch;
+}
+
+.u-td {
+	height: 100%;
+}
+
+u-icon {
+	display: inline-flex;
+	align-items: center;
+}
+
+// 各家小程序宫格组件外层设置为100%,避免受到父元素display: flex;的影响
+u-grid {
+	width: 100%;
+	flex: 0 0 100%;
+}
+
+// 避免小程序线条组件因为父组件display: flex;而失效
+u-line {
+	flex: 1;
+}
+
+u-switch {
+	display: inline-flex;
+	align-items: center;
+}
+
+u-dropdown {
+	flex: 1;
+}
+/* #endif */
+/* end-微信小程序编译后页面有组件名的元素,特别处理--end */
+
+
+/* #ifdef MP-QQ || MP-TOUTIAO */
+// 需要做这一切额外的兼容,都是因为TX的无能
+u-icon {
+	line-height: 0;
+}
+/* #endif */
+
+/* start--头条小程序编译后页面有组件名的元素,特别处理--start */
+// 由于头条小程序不支持直接组件名形式写样式,目前只能在写组件的时候给组件加上对应的类名
+/* #ifdef MP-TOUTIAO */
+.u-td, .u-th, .u-tr {
+	flex: 1;
+	align-self: stretch;
+}
+
+.u-row, .u-col {
+	flex: 1;
+	align-self: stretch;
+}
+
+// 避免小程序线条组件因为父组件display: flex;而失效
+.u-line {
+	flex: 1;
+}
+
+.u-dropdown {
+	flex: 1;
+}
+/* #endif */
+/* end-头条小程序编译后页面有组件名的元素,特别处理--end */
+
+
+

+ 3 - 0
libs/css/style.nvue.scss

@@ -0,0 +1,3 @@
+.nvue {
+	font-size: 24rpx;
+}

+ 175 - 0
libs/css/style.vue.scss

@@ -0,0 +1,175 @@
+page {
+	color: $u-main-color;
+	font-size: 28rpx;
+}
+
+/* start--去除webkit的默认样式--start */
+.u-fix-ios-appearance {
+	-webkit-appearance:none;
+}
+/* end--去除webkit的默认样式--end */
+
+/* start--icon图标外层套一个view,让其达到更好的垂直居中的效果--start */
+.u-icon-wrap {
+	display: flex;
+	align-items: center;
+}
+/* end-icon图标外层套一个view,让其达到更好的垂直居中的效果--end */
+
+/* start--iPhoneX底部安全区定义--start */
+.safe-area-inset-bottom {
+  padding-bottom: 0;  
+  padding-bottom: constant(safe-area-inset-bottom);  
+  padding-bottom: env(safe-area-inset-bottom);  
+} 
+/* end-iPhoneX底部安全区定义--end */
+
+/* start--各种hover点击反馈相关的类名-start */
+.u-hover-class {
+	// background-color: #f7f8f9!important;
+	opacity: 0.6;
+}
+
+.u-cell-hover {
+	background-color: #f7f8f9!important;
+}
+/* end--各种hover点击反馈相关的类名--end */
+
+/* start--文本行数限制--start */
+.u-line-1 {
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+}
+
+.u-line-2 {
+    -webkit-line-clamp: 2;
+}
+
+.u-line-3 {
+    -webkit-line-clamp: 3;
+}
+
+.u-line-4 {
+    -webkit-line-clamp: 4;
+}
+
+.u-line-5 {
+    -webkit-line-clamp: 5;
+}
+
+.u-line-2, .u-line-3, .u-line-4, .u-line-5 {
+    overflow: hidden;
+	word-break: break-all;
+    text-overflow: ellipsis; 
+    display: -webkit-box; // 弹性伸缩盒
+    -webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式
+}
+
+/* end--文本行数限制--end */
+
+
+/* start--Retina 屏幕下的 1px 边框--start */
+.u-border,
+.u-border-bottom,
+.u-border-left,
+.u-border-right,
+.u-border-top,
+.u-border-top-bottom {
+	position: relative
+}
+
+.u-border-bottom:after,
+.u-border-left:after,
+.u-border-right:after,
+.u-border-top-bottom:after,
+.u-border-top:after,
+.u-border:after {
+	/* #ifndef APP-NVUE */
+	content: ' ';
+	/* #endif */
+	position: absolute;
+	left: 0;
+	top: 0;
+	pointer-events: none;
+	box-sizing: border-box;
+	-webkit-transform-origin: 0 0;
+	transform-origin: 0 0;
+	// 多加0.1%,能解决有时候边框缺失的问题
+	width: 199.8%;
+	height: 199.7%;
+	transform: scale(0.5, 0.5);
+	border: 0 solid $u-border-color;
+	z-index: 2;
+}
+
+.u-border-top:after {
+	border-top-width: 1px
+}
+
+.u-border-left:after {
+	border-left-width: 1px
+}
+
+.u-border-right:after {
+	border-right-width: 1px
+}
+
+.u-border-bottom:after {
+	border-bottom-width: 1px
+}
+
+.u-border-top-bottom:after {
+	border-width: 1px 0
+}
+
+.u-border:after {
+	border-width: 1px
+}
+/* end--Retina 屏幕下的 1px 边框--end */
+
+
+/* start--clearfix--start */
+.u-clearfix:after,
+.clearfix:after {
+	/* #ifndef APP-NVUE */
+	content: '';
+	/* #endif */
+	display: table;
+	clear: both
+}
+/* end--clearfix--end */
+
+/* start--高斯模糊tabbar底部处理--start */
+.u-blur-effect-inset {
+	width: 750rpx;  
+	height: var(--window-bottom);   
+	background-color: #FFFFFF;  
+}
+/* end--高斯模糊tabbar底部处理--end */
+
+/* start--提升H5端uni.toast()的层级,避免被uView的modal等遮盖--start */
+/* #ifdef H5 */
+uni-toast {
+    z-index: 10090;
+}
+uni-toast .uni-toast {
+   z-index: 10090;
+}
+/* #endif */
+/* end--提升H5端uni.toast()的层级,避免被uView的modal等遮盖--end */
+
+/* start--去除button的所有默认样式--start */
+.u-reset-button {
+	padding: 0;
+	font-size: inherit;
+	line-height: inherit;
+	background-color: transparent;
+	color: inherit;
+}
+
+.u-reset-button::after {
+   border: none;
+}
+/* end--去除button的所有默认样式--end */
+

+ 18 - 0
libs/function/$parent.js

@@ -0,0 +1,18 @@
+// 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
+// this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
+// 这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
+// 值(默认为undefined),就是查找最顶层的$parent
+export default function $parent(name = undefined) {
+	let parent = this.$parent;
+	// 通过while历遍,这里主要是为了H5需要多层解析的问题
+	while (parent) {
+		// 父组件
+		if (parent.$options && parent.$options.name !== name) {
+			// 如果组件的name不相等,继续上一级寻找
+			parent = parent.$parent;
+		} else {
+			return parent;
+		}
+	}
+	return false;
+}

+ 8 - 0
libs/function/addUnit.js

@@ -0,0 +1,8 @@
+import validation from './test.js';
+
+// 添加单位,如果有rpx,%,px等单位结尾或者值为auto,直接返回,否则加上rpx单位结尾
+export default function addUnit(value = 'auto', unit = 'rpx') {
+    value = String(value);
+	// 用uView内置验证规则中的number判断是否为数值
+    return validation.number(value) ? `${value}${unit}` : value;
+}

+ 5 - 0
libs/function/bem.js

@@ -0,0 +1,5 @@
+function bem(name, conf) {
+  
+}
+
+module.exports.bem = bem;

+ 37 - 0
libs/function/color.js

@@ -0,0 +1,37 @@
+// 为了让用户能够自定义主题,会逐步弃用此文件,各颜色通过css提供
+// 为了给某些特殊场景使用和向后兼容,无需删除此文件(2020-06-20)
+let color = {
+	primary: "#2979ff",
+	primaryDark: "#2b85e4",
+	primaryDisabled: "#a0cfff",
+	primaryLight: "#ecf5ff",
+	bgColor: "#f3f4f6",
+	
+	info: "#909399",
+	infoDark: "#82848a",
+	infoDisabled: "#c8c9cc",
+	infoLight: "#f4f4f5",
+	
+	warning: "#ff9900",
+	warningDark: "#f29100",
+	warningDisabled: "#fcbd71",
+	warningLight: "#fdf6ec",
+	
+	error: "#fa3534",
+	errorDark: "#dd6161",
+	errorDisabled: "#fab6b6",
+	errorLight: "#fef0f0",
+	
+	success: "#19be6b",
+	successDark: "#18b566",
+	successDisabled: "#71d5a1",
+	successLight: "#dbf1e1",
+	
+	mainColor: "#303133",
+	contentColor: "#606266",
+	tipsColor: "#909399",
+	lightColor: "#c0c4cc",
+	borderColor: "#e4e7ed"
+}
+
+export default color;

+ 134 - 0
libs/function/colorGradient.js

@@ -0,0 +1,134 @@
+/**
+ * 求两个颜色之间的渐变值
+ * @param {string} startColor 开始的颜色
+ * @param {string} endColor 结束的颜色
+ * @param {number} step 颜色等分的份额
+ * */
+function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
+	let startRGB = hexToRgb(startColor, false); //转换为rgb数组模式
+	let startR = startRGB[0];
+	let startG = startRGB[1];
+	let startB = startRGB[2];
+
+	let endRGB = hexToRgb(endColor, false);
+	let endR = endRGB[0];
+	let endG = endRGB[1];
+	let endB = endRGB[2];
+
+	let sR = (endR - startR) / step; //总差值
+	let sG = (endG - startG) / step;
+	let sB = (endB - startB) / step;
+	let colorArr = [];
+	for (let i = 0; i < step; i++) {
+		//计算每一步的hex值 
+		let hex = rgbToHex('rgb(' + Math.round((sR * i + startR)) + ',' + Math.round((sG * i + startG)) + ',' + Math.round((sB *
+			i + startB)) + ')');
+		colorArr.push(hex);
+	}
+	return colorArr;
+}
+
+// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
+function hexToRgb(sColor, str = true) {
+	let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
+	sColor = sColor.toLowerCase();
+	if (sColor && reg.test(sColor)) {
+		if (sColor.length === 4) {
+			let sColorNew = "#";
+			for (let i = 1; i < 4; i += 1) {
+				sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
+			}
+			sColor = sColorNew;
+		}
+		//处理六位的颜色值
+		let sColorChange = [];
+		for (let i = 1; i < 7; i += 2) {
+			sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
+		}
+		if(!str) {
+			return sColorChange;
+		} else {
+			return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`;
+		}
+	} else if (/^(rgb|RGB)/.test(sColor)) {
+		let arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",")
+		return arr.map(val => Number(val));
+	} else {
+		return sColor;
+	}
+};
+
+// 将rgb表示方式转换为hex表示方式
+function rgbToHex(rgb) {
+	let _this = rgb;
+	let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
+	if (/^(rgb|RGB)/.test(_this)) {
+		let aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
+		let strHex = "#";
+		for (let i = 0; i < aColor.length; i++) {
+			let hex = Number(aColor[i]).toString(16);
+			hex = String(hex).length == 1 ? 0 + '' + hex : hex; // 保证每个rgb的值为2位
+			if (hex === "0") {
+				hex += hex;
+			}
+			strHex += hex;
+		}
+		if (strHex.length !== 7) {
+			strHex = _this;
+		}
+		return strHex;
+	} else if (reg.test(_this)) {
+		let aNum = _this.replace(/#/, "").split("");
+		if (aNum.length === 6) {
+			return _this;
+		} else if (aNum.length === 3) {
+			let numHex = "#";
+			for (let i = 0; i < aNum.length; i += 1) {
+				numHex += (aNum[i] + aNum[i]);
+			}
+			return numHex;
+		}
+	} else {
+		return _this;
+	}
+}
+
+
+/**
+* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
+* sHex为传入的十六进制的色值
+* alpha为rgba的透明度
+*/
+function colorToRgba(color, alpha = 0.3) {
+	color = rgbToHex(color)
+	// 十六进制颜色值的正则表达式
+	var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
+	/* 16进制颜色转为RGB格式 */
+	let sColor = color.toLowerCase()
+	if (sColor && reg.test(sColor)) {
+		if (sColor.length === 4) {
+			var sColorNew = '#'
+			for (let i = 1; i < 4; i += 1) {
+				sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
+			}
+			sColor = sColorNew
+		}
+		// 处理六位的颜色值
+		var sColorChange = []
+		for (let i = 1; i < 7; i += 2) {
+			sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2)))
+		}
+		// return sColorChange.join(',')
+		return 'rgba(' + sColorChange.join(',') + ',' + alpha + ')'
+	} 
+	else {
+		return sColor
+	}
+}
+
+export default {
+	colorGradient,
+	hexToRgb,
+	rgbToHex,
+	colorToRgba
+}

+ 29 - 0
libs/function/debounce.js

@@ -0,0 +1,29 @@
+let timeout = null;
+
+/**
+ * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
+ * 
+ * @param {Function} func 要执行的回调函数 
+ * @param {Number} wait 延时的时间
+ * @param {Boolean} immediate 是否立即执行 
+ * @return null
+ */
+function debounce(func, wait = 500, immediate = false) {
+	// 清除定时器
+	if (timeout !== null) clearTimeout(timeout);
+	// 立即执行,此类情况一般用不到
+	if (immediate) {
+		var callNow = !timeout;
+		timeout = setTimeout(function() {
+			timeout = null;
+		}, wait);
+		if (callNow) typeof func === 'function' && func();
+	} else {
+		// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
+		timeout = setTimeout(function() {
+			typeof func === 'function' && func();
+		}, wait);
+	}
+}
+
+export default debounce

+ 23 - 0
libs/function/deepClone.js

@@ -0,0 +1,23 @@
+// 判断arr是否为一个数组,返回一个bool值
+function isArray (arr) {
+    return Object.prototype.toString.call(arr) === '[object Array]';
+}
+
+// 深度克隆
+function deepClone (obj) {
+	// 对常见的“非”值,直接返回原来值
+	if([null, undefined, NaN, false].includes(obj)) return obj;
+    if(typeof obj !== "object" && typeof obj !== 'function') {
+		//原始类型直接返回
+        return obj;
+    }
+    var o = isArray(obj) ? [] : {};
+    for(let i in obj) {
+        if(obj.hasOwnProperty(i)){
+            o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
+        }
+    }
+    return o;
+}
+
+export default deepClone;

+ 30 - 0
libs/function/deepMerge.js

@@ -0,0 +1,30 @@
+import deepClone from "./deepClone";
+
+// JS对象深度合并
+function deepMerge(target = {}, source = {}) {
+	target = deepClone(target);
+	if (typeof target !== 'object' || typeof source !== 'object') return false;
+	for (var prop in source) {
+		if (!source.hasOwnProperty(prop)) continue;
+		if (prop in target) {
+			if (typeof target[prop] !== 'object') {
+				target[prop] = source[prop];
+			} else {
+				if (typeof source[prop] !== 'object') {
+					target[prop] = source[prop];
+				} else {
+					if (target[prop].concat && source[prop].concat) {
+						target[prop] = target[prop].concat(source[prop]);
+					} else {
+						target[prop] = deepMerge(target[prop], source[prop]);
+					}
+				}
+			}
+		} else {
+			target[prop] = source[prop];
+		}
+	}
+	return target;
+}
+
+export default deepMerge;

+ 47 - 0
libs/function/getParent.js

@@ -0,0 +1,47 @@
+// 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
+// this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
+export default function getParent(name, keys) {
+	let parent = this.$parent;
+	// 通过while历遍,这里主要是为了H5需要多层解析的问题
+	while (parent) {
+		// 父组件
+		if (parent.$options.name !== name) {
+			// 如果组件的name不相等,继续上一级寻找
+			parent = parent.$parent;
+		} else {
+			let data = {};
+			// 判断keys是否数组,如果传过来的是一个数组,那么直接使用数组元素值当做键值去父组件寻找
+			if(Array.isArray(keys)) {
+				keys.map(val => {
+					data[val] = parent[val] ? parent[val] : '';
+				})
+			} else {
+				// 历遍传过来的对象参数
+				for(let i in keys) {
+					// 如果子组件有此值则用,无此值则用父组件的值
+					// 判断是否空数组,如果是,则用父组件的值,否则用子组件的值
+					if(Array.isArray(keys[i])) {
+						if(keys[i].length) {
+							data[i] = keys[i];
+						} else {
+							data[i] = parent[i];
+						}
+					} else if(keys[i].constructor === Object) {
+						// 判断是否对象,如果是对象,且有属性,那么使用子组件的值,否则使用父组件的值
+						if(Object.keys(keys[i]).length) {
+							data[i] = keys[i];
+						} else {
+							data[i] = parent[i];
+						}
+					} else {
+						// 只要子组件有传值,即使是false值,也是“传值”了,也需要覆盖父组件的同名参数
+						data[i] = (keys[i] || keys[i] === false) ? keys[i] : parent[i];
+					}
+				}
+			}
+			return data;
+		}
+	}
+
+	return {};
+}

+ 41 - 0
libs/function/guid.js

@@ -0,0 +1,41 @@
+/**
+ * 本算法来源于简书开源代码,详见:https://www.jianshu.com/p/fdbf293d0a85
+ * 全局唯一标识符(uuid,Globally Unique Identifier),也称作 uuid(Universally Unique IDentifier) 
+ * 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题
+ * 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱
+ * v-for的时候,推荐使用后端返回的id而不是循环的index
+ * @param {Number} len uuid的长度
+ * @param {Boolean} firstU 将返回的首字母置为"u"
+ * @param {Number} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
+ */
+function guid(len = 32, firstU = true, radix = null) {
+	let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
+	let uuid = [];
+	radix = radix || chars.length;
+
+	if (len) {
+		// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+		for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
+	} else {
+		let r;
+		// rfc4122标准要求返回的uuid中,某些位为固定的字符
+		uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
+		uuid[14] = '4';
+
+		for (let i = 0; i < 36; i++) {
+			if (!uuid[i]) {
+				r = 0 | Math.random() * 16;
+				uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
+			}
+		}
+	}
+	// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guid不能用作id或者class
+	if (firstU) {
+		uuid.shift();
+		return 'u' + uuid.join('');
+	} else {
+		return uuid.join('');
+	}
+}
+
+export default guid;

+ 385 - 0
libs/function/md5.js

@@ -0,0 +1,385 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;   /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = "";  /* base-64 pad character. "=" for strict RFC compliance   */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s)    { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
+function b64_md5(s)    { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
+function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
+function hex_hmac_md5(k, d)
+  { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function b64_hmac_md5(k, d)
+  { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function any_hmac_md5(k, d, e)
+  { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of a raw string
+ */
+function rstr_md5(s)
+{
+  return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data (raw strings)
+ */
+function rstr_hmac_md5(key, data)
+{
+  var bkey = rstr2binl(key);
+  if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
+  return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
+}
+
+/*
+ * Convert a raw string to a hex string
+ */
+function rstr2hex(input)
+{
+  try { hexcase } catch(e) { hexcase=0; }
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var output = "";
+  var x;
+  for(var i = 0; i < input.length; i++)
+  {
+    x = input.charCodeAt(i);
+    output += hex_tab.charAt((x >>> 4) & 0x0F)
+           +  hex_tab.charAt( x        & 0x0F);
+  }
+  return output;
+}
+
+/*
+ * Convert a raw string to a base-64 string
+ */
+function rstr2b64(input)
+{
+  try { b64pad } catch(e) { b64pad=''; }
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var output = "";
+  var len = input.length;
+  for(var i = 0; i < len; i += 3)
+  {
+    var triplet = (input.charCodeAt(i) << 16)
+                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
+                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
+      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+    }
+  }
+  return output;
+}
+
+/*
+ * Convert a raw string to an arbitrary string encoding
+ */
+function rstr2any(input, encoding)
+{
+  var divisor = encoding.length;
+  var i, j, q, x, quotient;
+
+  /* Convert to an array of 16-bit big-endian values, forming the dividend */
+  var dividend = Array(Math.ceil(input.length / 2));
+  for(i = 0; i < dividend.length; i++)
+  {
+    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
+  }
+
+  /*
+   * Repeatedly perform a long division. The binary array forms the dividend,
+   * the length of the encoding is the divisor. Once computed, the quotient
+   * forms the dividend for the next step. All remainders are stored for later
+   * use.
+   */
+  var full_length = Math.ceil(input.length * 8 /
+                                    (Math.log(encoding.length) / Math.log(2)));
+  var remainders = Array(full_length);
+  for(j = 0; j < full_length; j++)
+  {
+    quotient = Array();
+    x = 0;
+    for(i = 0; i < dividend.length; i++)
+    {
+      x = (x << 16) + dividend[i];
+      q = Math.floor(x / divisor);
+      x -= q * divisor;
+      if(quotient.length > 0 || q > 0)
+        quotient[quotient.length] = q;
+    }
+    remainders[j] = x;
+    dividend = quotient;
+  }
+
+  /* Convert the remainders to the output string */
+  var output = "";
+  for(i = remainders.length - 1; i >= 0; i--)
+    output += encoding.charAt(remainders[i]);
+
+  return output;
+}
+
+/*
+ * Encode a string as utf-8.
+ * For efficiency, this assumes the input is valid utf-16.
+ */
+function str2rstr_utf8(input)
+{
+  var output = "";
+  var i = -1;
+  var x, y;
+
+  while(++i < input.length)
+  {
+    /* Decode utf-16 surrogate pairs */
+    x = input.charCodeAt(i);
+    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
+    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
+    {
+      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
+      i++;
+    }
+
+    /* Encode output as utf-8 */
+    if(x <= 0x7F)
+      output += String.fromCharCode(x);
+    else if(x <= 0x7FF)
+      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0xFFFF)
+      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0x1FFFFF)
+      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
+                                    0x80 | ((x >>> 12) & 0x3F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+  }
+  return output;
+}
+
+/*
+ * Encode a string as utf-16
+ */
+function str2rstr_utf16le(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
+                                  (input.charCodeAt(i) >>> 8) & 0xFF);
+  return output;
+}
+
+function str2rstr_utf16be(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
+                                   input.charCodeAt(i)        & 0xFF);
+  return output;
+}
+
+/*
+ * Convert a raw string to an array of little-endian words
+ * Characters >255 have their high-byte silently ignored.
+ */
+function rstr2binl(input)
+{
+  var output = Array(input.length >> 2);
+  for(var i = 0; i < output.length; i++)
+    output[i] = 0;
+  for(var i = 0; i < input.length * 8; i += 8)
+    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
+  return output;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2rstr(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length * 32; i += 8)
+    output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
+  return output;
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length.
+ */
+function binl_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+module.exports = {
+	md5 : function(str){
+		return hex_md5(str);
+	}
+}

+ 58 - 0
libs/function/queryParams.js

@@ -0,0 +1,58 @@
+/**
+ * 对象转url参数
+ * @param {*} data,对象
+ * @param {*} isPrefix,是否自动加上"?"
+ */
+function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
+	let prefix = isPrefix ? '?' : ''
+	let _result = []
+	if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets';
+	for (let key in data) {
+		let value = data[key]
+		// 去掉为空的参数
+		if (['', undefined, null].indexOf(value) >= 0) {
+			continue;
+		}
+		// 如果值为数组,另行处理
+		if (value.constructor === Array) {
+			// e.g. {ids: [1, 2, 3]}
+			switch (arrayFormat) {
+				case 'indices':
+					// 结果: ids[0]=1&ids[1]=2&ids[2]=3
+					for (let i = 0; i < value.length; i++) {
+						_result.push(key + '[' + i + ']=' + value[i])
+					}
+					break;
+				case 'brackets':
+					// 结果: ids[]=1&ids[]=2&ids[]=3
+					value.forEach(_value => {
+						_result.push(key + '[]=' + _value)
+					})
+					break;
+				case 'repeat':
+					// 结果: ids=1&ids=2&ids=3
+					value.forEach(_value => {
+						_result.push(key + '=' + _value)
+					})
+					break;
+				case 'comma':
+					// 结果: ids=1,2,3
+					let commaStr = "";
+					value.forEach(_value => {
+						commaStr += (commaStr ? "," : "") + _value;
+					})
+					_result.push(key + '=' + commaStr)
+					break;
+				default:
+					value.forEach(_value => {
+						_result.push(key + '[]=' + _value)
+					})
+			}
+		} else {
+			_result.push(key + '=' + value)
+		}
+	}
+	return _result.length ? prefix + _result.join('&') : ''
+}
+
+export default queryParams;

+ 10 - 0
libs/function/random.js

@@ -0,0 +1,10 @@
+function random(min, max) {
+	if (min >= 0 && max > 0 && max >= min) {
+		let gab = max - min + 1;
+		return Math.floor(Math.random() * gab + min);
+	} else {
+		return 0;
+	}
+}
+
+export default random;

+ 7 - 0
libs/function/randomArray.js

@@ -0,0 +1,7 @@
+// 打乱数组
+function randomArray(array = []) {
+	// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
+	return array.sort(() => Math.random() - 0.5);
+}
+
+export default randomArray

+ 122 - 0
libs/function/route.js

@@ -0,0 +1,122 @@
+/**
+ * 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷
+ * 并且带有路由拦截功能
+ */
+
+class Router {
+	constructor() {
+		// 原始属性定义
+		this.config = {
+			type: 'navigateTo',
+			url: '',
+			delta: 1, // navigateBack页面后退时,回退的层数
+			params: {}, // 传递的参数
+			animationType: 'pop-in', // 窗口动画,只在APP有效
+			animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
+			intercept: false, // 是否需要拦截
+		}
+		// 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文
+		// 这里在构造函数中进行this绑定
+		this.route = this.route.bind(this)
+	}
+
+	// 判断url前面是否有"/",如果没有则加上,否则无法跳转
+	addRootPath(url) {
+		return url[0] === '/' ? url : `/${url}`
+	}
+
+	// 整合路由参数
+	mixinParam(url, params) {
+		url = url && this.addRootPath(url)
+		
+		// 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"
+		// 如果有url中有get参数,转换后无需带上"?"
+		let query = ''
+		if (/.*\/.*\?.*=.*/.test(url)) {
+			// object对象转为get类型的参数
+			query = uni.$u.queryParams(params, false);
+			// 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
+			return url += "&" + query
+		} else {
+			// 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号
+			query = uni.$u.queryParams(params);
+			return url += query
+		}
+	}
+
+	// 对外的方法名称
+	async route(options = {}, params = {}) {
+		// 合并用户的配置和内部的默认配置
+		let mergeConfig = {}
+
+		if (typeof options === 'string') {
+			// 如果options为字符串,则为route(url, params)的形式
+			mergeConfig.url = this.mixinParam(options, params)
+			mergeConfig.type = 'navigateTo'
+		} else {
+			mergeConfig = uni.$u.deepClone(options, this.config)
+			// 否则正常使用mergeConfig中的url和params进行拼接
+			mergeConfig.url = this.mixinParam(options.url, options.params)
+		}
+		
+		if(params.intercept) {
+			this.config.intercept = params.intercept
+		}
+		// params参数也带给拦截器
+		mergeConfig.params = params
+		// 合并内外部参数
+		mergeConfig = uni.$u.deepMerge(this.config, mergeConfig)
+		// 判断用户是否定义了拦截器
+		if (typeof uni.$u.routeIntercept === 'function') {
+			// 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转
+			const isNext = await new Promise((resolve, reject) => {
+				uni.$u.routeIntercept(mergeConfig, resolve)
+			})
+			// 如果isNext为true,则执行路由跳转
+			isNext && this.openPage(mergeConfig)
+		} else {
+			this.openPage(mergeConfig)
+		}
+	}
+
+	// 执行路由跳转
+	openPage(config) {
+		// 解构参数
+		const {
+			url,
+			type,
+			delta,
+			animationType,
+			animationDuration
+		} = config
+		if (config.type == 'navigateTo' || config.type == 'to') {
+			uni.navigateTo({
+				url,
+				animationType,
+				animationDuration
+			});
+		}
+		if (config.type == 'redirectTo' || config.type == 'redirect') {
+			uni.redirectTo({
+				url
+			});
+		}
+		if (config.type == 'switchTab' || config.type == 'tab') {
+			uni.switchTab({
+				url
+			});
+		}
+		if (config.type == 'reLaunch' || config.type == 'launch') {
+			uni.reLaunch({
+				url
+			});
+		}
+		if (config.type == 'navigateBack' || config.type == 'back') {
+			uni.navigateBack({
+				delta
+			});
+		}
+	}
+}
+
+export default (new Router()).route

+ 9 - 0
libs/function/sys.js

@@ -0,0 +1,9 @@
+export function os() {
+	return uni.getSystemInfoSync().platform;
+};
+
+export function sys() {
+	return uni.getSystemInfoSync();
+}
+
+

+ 232 - 0
libs/function/test.js

@@ -0,0 +1,232 @@
+/**
+ * 验证电子邮箱格式
+ */
+function email(value) {
+	return /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/.test(value);
+}
+
+/**
+ * 验证手机格式
+ */
+function mobile(value) {
+	return /^1[3-9]\d{9}$/.test(value)
+}
+
+/**
+ * 验证URL格式
+ */
+function url(value) {
+	return /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value)
+}
+
+/**
+ * 验证日期格式
+ */
+function date(value) {
+	return !/Invalid|NaN/.test(new Date(value).toString())
+}
+
+/**
+ * 验证ISO类型的日期格式
+ */
+function dateISO(value) {
+	return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
+}
+
+/**
+ * 验证十进制数字
+ */
+function number(value) {
+	return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
+}
+
+/**
+ * 验证整数
+ */
+function digits(value) {
+	return /^\d+$/.test(value)
+}
+
+/**
+ * 验证身份证号码
+ */
+function idCard(value) {
+	return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
+		value)
+}
+
+/**
+ * 是否车牌号
+ */
+function carNo(value) {
+	// 新能源车牌
+	const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
+	// 旧车牌
+	const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
+	if (value.length === 7) {
+		return creg.test(value);
+	} else if (value.length === 8) {
+		return xreg.test(value);
+	} else {
+		return false;
+	}
+}
+
+/**
+ * 金额,只允许2位小数
+ */
+function amount(value) {
+	//金额,只允许保留两位小数
+	return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value);
+}
+
+/**
+ * 中文
+ */
+function chinese(value) {
+	let reg = /^[\u4e00-\u9fa5]+$/gi;
+	return reg.test(value);
+}
+
+/**
+ * 只能输入字母
+ */
+function letter(value) {
+	return /^[a-zA-Z]*$/.test(value);
+}
+
+/**
+ * 只能是字母或者数字
+ */
+function enOrNum(value) {
+	//英文或者数字
+	let reg = /^[0-9a-zA-Z]*$/g;
+	return reg.test(value);
+}
+
+/**
+ * 验证是否包含某个值
+ */
+function contains(value, param) {
+	return value.indexOf(param) >= 0
+}
+
+/**
+ * 验证一个值范围[min, max]
+ */
+function range(value, param) {
+	return value >= param[0] && value <= param[1]
+}
+
+/**
+ * 验证一个长度范围[min, max]
+ */
+function rangeLength(value, param) {
+	return value.length >= param[0] && value.length <= param[1]
+}
+
+/**
+ * 是否固定电话
+ */
+function landline(value) {
+	let reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/;
+	return reg.test(value);
+}
+
+/**
+ * 判断是否为空
+ */
+function empty(value) {
+	switch (typeof value) {
+		case 'undefined':
+			return true;
+		case 'string':
+			if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
+			break;
+		case 'boolean':
+			if (!value) return true;
+			break;
+		case 'number':
+			if (0 === value || isNaN(value)) return true;
+			break;
+		case 'object':
+			if (null === value || value.length === 0) return true;
+			for (var i in value) {
+				return false;
+			}
+			return true;
+	}
+	return false;
+}
+
+/**
+ * 是否json字符串
+ */
+function jsonString(value) {
+	if (typeof value == 'string') {
+		try {
+			var obj = JSON.parse(value);
+			if (typeof obj == 'object' && obj) {
+				return true;
+			} else {
+				return false;
+			}
+		} catch (e) {
+			return false;
+		}
+	}
+	return false;
+}
+
+
+/**
+ * 是否数组
+ */
+function array(value) {
+	if (typeof Array.isArray === "function") {
+		return Array.isArray(value);
+	} else {
+		return Object.prototype.toString.call(value) === "[object Array]";
+	}
+}
+
+/**
+ * 是否对象
+ */
+function object(value) {
+	return Object.prototype.toString.call(value) === '[object Object]';
+}
+
+/**
+ * 是否短信验证码
+ */
+function code(value, len = 6) {
+	return new RegExp(`^\\d{${len}}$`).test(value);
+}
+
+
+export default {
+	email,
+	mobile,
+	url,
+	date,
+	dateISO,
+	number,
+	digits,
+	idCard,
+	carNo,
+	amount,
+	chinese,
+	letter,
+	enOrNum,
+	contains,
+	range,
+	rangeLength,
+	empty,
+	isEmpty: empty,
+	jsonString,
+	landline,
+	object,
+	array,
+	code
+}

+ 32 - 0
libs/function/throttle.js

@@ -0,0 +1,32 @@
+let timer, flag;
+/**
+ * 节流原理:在一定时间内,只能触发一次
+ * 
+ * @param {Function} func 要执行的回调函数 
+ * @param {Number} wait 延时的时间
+ * @param {Boolean} immediate 是否立即执行
+ * @return null
+ */
+function throttle(func, wait = 500, immediate = true) {
+	if (immediate) {
+		if (!flag) {
+			flag = true;
+			// 如果是立即执行,则在wait毫秒内开始时执行
+			typeof func === 'function' && func();
+			timer = setTimeout(() => {
+				flag = false;
+			}, wait);
+		}
+	} else {
+		if (!flag) {
+			flag = true
+			// 如果是非立即执行,则在wait毫秒内的结束处执行
+			timer = setTimeout(() => {
+				flag = false
+				typeof func === 'function' && func();
+			}, wait);
+		}
+		
+	}
+};
+export default throttle

+ 51 - 0
libs/function/timeFormat.js

@@ -0,0 +1,51 @@
+// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
+// 所以这里做一个兼容polyfill的兼容处理
+if (!String.prototype.padStart) {
+	// 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
+	String.prototype.padStart = function(maxLength, fillString = ' ') {
+		if (Object.prototype.toString.call(fillString) !== "[object String]") throw new TypeError(
+			'fillString must be String')
+		let str = this
+		// 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
+		if (str.length >= maxLength) return String(str)
+
+		let fillLength = maxLength - str.length,
+			times = Math.ceil(fillLength / fillString.length)
+		while (times >>= 1) {
+			fillString += fillString
+			if (times === 1) {
+				fillString += fillString
+			}
+		}
+		return fillString.slice(0, fillLength) + str;
+	}
+}
+
+// 其他更多是格式化有如下:
+// yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合
+function timeFormat(dateTime = null, fmt = 'yyyy-mm-dd') {
+	// 如果为null,则格式化当前时间
+	if (!dateTime) dateTime = Number(new Date());
+	// 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式
+	if (dateTime.toString().length == 10) dateTime *= 1000;
+	let date = new Date(dateTime);
+	let ret;
+	let opt = {
+		"y+": date.getFullYear().toString(), // 年
+		"m+": (date.getMonth() + 1).toString(), // 月
+		"d+": date.getDate().toString(), // 日
+		"h+": date.getHours().toString(), // 时
+		"M+": date.getMinutes().toString(), // 分
+		"s+": date.getSeconds().toString() // 秒
+		// 有其他格式化字符需求可以继续添加,必须转化成字符串
+	};
+	for (let k in opt) {
+		ret = new RegExp("(" + k + ")").exec(fmt);
+		if (ret) {
+			fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
+		};
+	};
+	return fmt;
+}
+
+export default timeFormat

+ 47 - 0
libs/function/timeFrom.js

@@ -0,0 +1,47 @@
+import timeFormat from '../../libs/function/timeFormat.js';
+
+/**
+ * 时间戳转为多久之前
+ * @param String timestamp 时间戳
+ * @param String | Boolean format 如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
+ * 如果为布尔值false,无论什么时间,都返回多久以前的格式
+ */
+function timeFrom(dateTime = null, format = 'yyyy-mm-dd') {
+	// 如果为null,则格式化当前时间
+	if (!dateTime) dateTime = Number(new Date());
+	// 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式
+	if (dateTime.toString().length == 10) dateTime *= 1000;
+	let timestamp = + new Date(Number(dateTime));
+
+	let timer = (Number(new Date()) - timestamp) / 1000;
+	// 如果小于5分钟,则返回"刚刚",其他以此类推
+	let tips = '';
+	switch (true) {
+		case timer < 300:
+			tips = '刚刚';
+			break;
+		case timer >= 300 && timer < 3600:
+			tips = parseInt(timer / 60) + '分钟前';
+			break;
+		case timer >= 3600 && timer < 86400:
+			tips = parseInt(timer / 3600) + '小时前';
+			break;
+		case timer >= 86400 && timer < 2592000:
+			tips = parseInt(timer / 86400) + '天前';
+			break;
+		default:
+			// 如果format为false,则无论什么时间戳,都显示xx之前
+			if(format === false) {
+				if(timer >= 2592000 && timer < 365 * 86400) {
+					tips = parseInt(timer / (86400 * 30)) + '个月前';
+				} else {
+					tips = parseInt(timer / (86400 * 365)) + '年前';
+				}
+			} else {
+				tips = timeFormat(timestamp, format);
+			}
+	}
+	return tips;
+}
+
+export default timeFrom;

+ 9 - 0
libs/function/toast.js

@@ -0,0 +1,9 @@
+function toast(title, duration = 1500) {
+	uni.showToast({
+		title: title,
+		icon: 'none',
+		duration: duration
+	})
+}
+
+export default toast

+ 15 - 0
libs/function/trim.js

@@ -0,0 +1,15 @@
+function trim(str, pos = 'both') {
+	if (pos == 'both') {
+		return str.replace(/^\s+|\s+$/g, "");
+	} else if (pos == "left") {
+		return str.replace(/^\s*/, '');
+	} else if (pos == 'right') {
+		return str.replace(/(\s*$)/g, "");
+	} else if (pos == 'all') {
+		return str.replace(/\s+/g, "");
+	} else {
+		return str;
+	}
+}
+
+export default trim

+ 35 - 0
libs/function/type2icon.js

@@ -0,0 +1,35 @@
+/**
+ * 根据主题type值,获取对应的图标
+ * @param String type 主题名称,primary|info|error|warning|success
+ * @param String fill 是否使用fill填充实体的图标  
+ */
+function type2icon(type = 'success', fill = false) {
+	// 如果非预置值,默认为success
+	if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success';
+	let iconName = '';
+	// 目前(2019-12-12),info和primary使用同一个图标
+	switch (type) {
+		case 'primary':
+			iconName = 'info-circle';
+			break;
+		case 'info':
+			iconName = 'info-circle';
+			break;
+		case 'error':
+			iconName = 'close-circle';
+			break;
+		case 'warning':
+			iconName = 'error-circle';
+			break;
+		case 'success':
+			iconName = 'checkmark-circle';
+			break;
+		default:
+			iconName = 'checkmark-circle';
+	}
+	// 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
+	if (fill) iconName += '-fill';
+	return iconName;
+}
+
+export default type2icon

+ 64 - 0
libs/mixin/mixin.js

@@ -0,0 +1,64 @@
+module.exports = {
+	data() {
+		return {}
+	},
+	onLoad() {
+		// getRect挂载到$u上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出
+		this.$u.getRect = this.$uGetRect
+	},
+	methods: {
+		// 查询节点信息
+		// 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21)
+		// 解决办法为在组件根部再套一个没有任何作用的view元素
+		$uGetRect(selector, all) {
+			return new Promise(resolve => {
+				uni.createSelectorQuery().
+				in(this)[all ? 'selectAll' : 'select'](selector)
+					.boundingClientRect(rect => {
+						if (all && Array.isArray(rect) && rect.length) {
+							resolve(rect)
+						}
+						if (!all && rect) {
+							resolve(rect)
+						}
+					})
+					.exec()
+			})
+		},
+		getParentData(parentName = '') {
+			// 避免在created中去定义parent变量
+			if(!this.parent) this.parent = false;
+			// 这里的本质原理是,通过获取父组件实例(也即u-radio-group的this)
+			// 将父组件this中对应的参数,赋值给本组件(u-radio的this)的parentData对象中对应的属性
+			// 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
+			this.parent = this.$u.$parent.call(this, parentName);
+			if(this.parent) {
+				// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
+				Object.keys(this.parentData).map(key => {
+					this.parentData[key] = this.parent[key];
+				});
+			}
+		},
+		// 阻止事件冒泡
+		preventEvent(e) {
+			e && e.stopPropagation && e.stopPropagation()
+		}
+	},
+	onReachBottom() {
+		uni.$emit('uOnReachBottom')
+	},
+	beforeDestroy() {
+		// 判断当前页面是否存在parent和children,一般在checkbox和checkbox-group父子联动的场景会有此情况
+		// 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱
+		if(this.parent && uni.$u.test.array(this.parent.children)) {
+			// 组件销毁时,移除父组件中的children数组中对应的实例
+			const childrenList = this.parent.children
+			childrenList.map((child, index) => {
+				// 如果相等,则移除
+				if(child === this) {
+					childrenList.splice(index, 1)
+				}
+			})
+		}
+	}
+}

+ 18 - 0
libs/mixin/mpShare.js

@@ -0,0 +1,18 @@
+module.exports = {
+	onLoad() {
+		// 设置默认的转发参数
+		this.$u.mpShare = {
+			title: '', // 默认为小程序名称
+			path: '', // 默认为当前页面路径
+			imageUrl: '' // 默认为当前页面的截图
+		}
+	},
+	onShareAppMessage() {
+		return this.$u.mpShare
+	},
+	// #ifdef MP-WEIXIN
+	onShareTimeline() {
+		return this.$u.mpShare
+	}
+	// #endif
+}

+ 169 - 0
libs/request/index.js

@@ -0,0 +1,169 @@
+import deepMerge from "../function/deepMerge";
+import validate from "../function/test";
+class Request {
+	// 设置全局默认配置
+	setConfig(customConfig) {
+		// 深度合并对象,否则会造成对象深层属性丢失
+		this.config = deepMerge(this.config, customConfig);
+	}
+
+	// 主要请求部分
+	request(options = {}) {
+		// 检查请求拦截
+		if (this.interceptor.request && typeof this.interceptor.request === 'function') {
+			let tmpConfig = {};
+			let interceptorRequest = this.interceptor.request(options);
+			if (interceptorRequest === false) {
+				// 返回一个处于pending状态中的Promise,来取消原promise,避免进入then()回调
+				return new Promise(()=>{});
+			}
+			this.options = interceptorRequest;
+		}
+		options.dataType = options.dataType || this.config.dataType;
+		options.responseType = options.responseType || this.config.responseType;
+		options.url = options.url || '';
+		options.params = options.params || {};
+		options.header = Object.assign({}, this.config.header, options.header);
+		options.method = options.method || this.config.method;
+
+		return new Promise((resolve, reject) => {
+			options.complete = (response) => {
+				// 请求返回后,隐藏loading(如果请求返回快的话,可能会没有loading)
+				uni.hideLoading();
+				// 清除定时器,如果请求回来了,就无需loading
+				clearTimeout(this.config.timer);
+				this.config.timer = null;
+				// 判断用户对拦截返回数据的要求,如果originalData为true,返回所有的数据(response)到拦截器,否则只返回response.data
+				if(this.config.originalData) {
+					// 判断是否存在拦截器
+					if (this.interceptor.response && typeof this.interceptor.response === 'function') {
+						let resInterceptors = this.interceptor.response(response);
+						// 如果拦截器不返回false,就将拦截器返回的内容给this.$u.post的then回调
+						if (resInterceptors !== false) {
+							resolve(resInterceptors);
+						} else {
+							// 如果拦截器返回false,意味着拦截器定义者认为返回有问题,直接接入catch回调
+							reject(response);
+						}
+					} else {
+						// 如果要求返回原始数据,就算没有拦截器,也返回最原始的数据
+						resolve(response);
+					}
+				} else {
+					if (response.statusCode == 200) {
+						if (this.interceptor.response && typeof this.interceptor.response === 'function') {
+							let resInterceptors = this.interceptor.response(response.data);
+							if (resInterceptors !== false) {
+								resolve(resInterceptors);
+							} else {
+								reject(response.data);
+							}
+						} else {
+							// 如果不是返回原始数据(originalData=false),且没有拦截器的情况下,返回纯数据给then回调
+							resolve(response.data);
+						}
+					} else {
+						// 不返回原始数据的情况下,服务器状态码不为200,modal弹框提示
+						// if(response.errMsg) {
+						// 	uni.showModal({
+						// 		title: response.errMsg
+						// 	});
+						// }
+						reject(response)
+					}
+				}
+			}
+
+			// 判断用户传递的URL是否/开头,如果不是,加上/,这里使用了uView的test.js验证库的url()方法
+			options.url = validate.url(options.url) ? options.url : (this.config.baseUrl + (options.url.indexOf('/') == 0 ?
+				options.url : '/' + options.url));
+			
+			// 是否显示loading
+			// 加一个是否已有timer定时器的判断,否则有两个同时请求的时候,后者会清除前者的定时器id
+			// 而没有清除前者的定时器,导致前者超时,一直显示loading
+			if(this.config.showLoading && !this.config.timer) {
+				this.config.timer = setTimeout(() => {
+					uni.showLoading({
+						title: this.config.loadingText,
+						mask: this.config.loadingMask
+					})
+					this.config.timer = null;
+				}, this.config.loadingTime);
+			}
+			uni.request(options);
+		})
+		// .catch(res => {
+		// 	// 如果返回reject(),不让其进入this.$u.post().then().catch()后面的catct()
+		// 	// 因为很多人都会忘了写后面的catch(),导致报错捕获不到catch
+		// 	return new Promise(()=>{});
+		// })
+	}
+
+	constructor() {
+		this.config = {
+			baseUrl: '', // 请求的根域名
+			// 默认的请求头
+			header: {},
+			method: 'POST',
+			// 设置为json,返回后uni.request会对数据进行一次JSON.parse
+			dataType: 'json',
+			// 此参数无需处理,因为5+和支付宝小程序不支持,默认为text即可
+			responseType: 'text',
+			showLoading: true, // 是否显示请求中的loading
+			loadingText: '请求中...',
+			loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms
+			timer: null, // 定时器
+			originalData: false, // 是否在拦截器中返回服务端的原始数据,见文档说明
+			loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
+		}
+	
+		// 拦截器
+		this.interceptor = {
+			// 请求前的拦截
+			request: null,
+			// 请求后的拦截
+			response: null
+		}
+
+		// get请求
+		this.get = (url, data = {}, header = {}) => {
+			return this.request({
+				method: 'GET',
+				url,
+				header,
+				data
+			})
+		}
+
+		// post请求
+		this.post = (url, data = {}, header = {}) => {
+			return this.request({
+				url,
+				method: 'POST',
+				header,
+				data
+			})
+		}
+		
+		// put请求,不支持支付宝小程序(HX2.6.15)
+		this.put = (url, data = {}, header = {}) => {
+			return this.request({
+				url,
+				method: 'PUT',
+				header,
+				data
+			})
+		}
+		
+		// delete请求,不支持支付宝和头条小程序(HX2.6.15)
+		this.delete = (url, data = {}, header = {}) => {
+			return this.request({
+				url,
+				method: 'DELETE',
+				header,
+				data
+			})
+		}
+	}
+}
+export default new Request

+ 19 - 0
libs/store/index.js

@@ -0,0 +1,19 @@
+// 暂时不用vuex模块方式实现,将该方法直接放入到/store/index.js中
+const module = {
+	actions: {
+		$uStore({rootState}, params) {
+			let nameArr = params.name.split('.');
+			if(nameArr.length >= 2) {
+				let obj = rootState[nameArr[0]];
+				for(let i = 1; i < nameArr.length - 1; i ++) {
+					obj = obj[nameArr[i]];
+				}
+				obj[nameArr[nameArr.length - 1]] = params.value;
+			} else {
+				rootState[params.name] = params.value;
+			}
+		}
+	}
+}
+
+export default module

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 0
libs/util/area.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1356 - 0
libs/util/async-validator.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 0
libs/util/city.js


+ 51 - 0
libs/util/emitter.js

@@ -0,0 +1,51 @@
+/**
+ * 递归使用 call 方式this指向
+ * @param componentName // 需要找的组件的名称
+ * @param eventName // 事件名称
+ * @param params // 需要传递的参数
+ */
+function broadcast(componentName, eventName, params) {
+    // 循环子节点找到名称一样的子节点 否则 递归 当前子节点
+    this.$children.map(child=>{
+        if (componentName===child.$options.name) {
+            child.$emit.apply(child,[eventName].concat(params))
+        }else {
+            broadcast.apply(child,[componentName,eventName].concat(params))
+        }
+    })
+}
+export default {
+    methods: {
+        /**
+         * 派发 (向上查找) (一个)
+         * @param componentName // 需要找的组件的名称
+         * @param eventName // 事件名称
+         * @param params // 需要传递的参数
+         */
+        dispatch(componentName, eventName, params) {
+            let parent = this.$parent || this.$root;//$parent 找到最近的父节点 $root 根节点
+            let name = parent.$options.name; // 获取当前组件实例的name
+            // 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点
+            // 循环出当前名称的一样的组件实例
+            while (parent && (!name||name!==componentName)) {
+                parent = parent.$parent;
+                if (parent) {
+                    name = parent.$options.name;
+                }
+            }
+            // 有节点表示当前找到了name一样的实例
+            if (parent) {
+                parent.$emit.apply(parent,[eventName].concat(params))
+            }
+        },
+        /**
+         * 广播 (向下查找) (广播多个)
+         * @param componentName // 需要找的组件的名称
+         * @param eventName // 事件名称
+         * @param params // 需要传递的参数
+         */
+        broadcast(componentName, eventName, params) {
+            broadcast.call(this,componentName, eventName, params)
+        }
+    }
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 0
libs/util/province.js


+ 31 - 0
package.json

@@ -0,0 +1,31 @@
+{
+    "name": "uView",
+    "version": "1.8.6",
+    "description": "",
+    "main": "index.js",
+    "keywords": [
+        "uview",
+        "ui",
+        "uni-app"
+    ],
+    "scripts": {
+        "test": "echo \"Error: no test specified\" && exit 1"
+    },
+    "repository": {
+        "type": "git",
+        "url": ""
+    },
+    "devDependencies": {
+        "node-sass": "^4.14.0",
+        "sass-loader": "^8.0.2"
+    },
+    "author": "uView",
+    "license": "MIT",
+    "id": "uview-v1",
+    "dcloudext": {
+        "category": [
+            "前端组件",
+            "通用组件"
+        ]
+    }
+}

+ 394 - 0
pages/feedback/print.vue

@@ -0,0 +1,394 @@
+<template>
+	<view>
+		<uni-list :border="false">
+			<uni-list-item v-for="(item,index) in breedTaskList" :key="item.id" :index="index" :threshold="0">
+				<template slot="body">
+					<uni-card :title="item.printBill.billCode" :subTitle="item.printBreed.breedName" :extra="parseBreedTaskStatus(item)">
+						<view class="uni-body">
+							<view>
+								<text class="textTitle">印品名称</text>
+								<text class="">{{item.printBill.billName}}</text>
+							</view>
+							<view v-show="item.showMore == true">
+								<view>
+									<text class="textTitle">印刷要求</text>
+									<text class="">{{item.printBreed.printRequire | ignoreNull}}</text>
+								</view>
+								<view>
+									<text class="textTitle">客户名称</text>
+									<text class="">{{item.printBill.clientName}}</text>
+								</view>
+								<view>
+									<text class="textTitle">产品类型</text>
+									<text class="">{{item.printBill.productName}}</text>
+								</view>
+								<view>
+									<text class="textTitle">用纸</text>
+									<text class="">{{item.printBreed.actualPaperName | ignoreNull}}</text>
+								</view>
+							</view>
+						</view>
+						<view slot="actions" class="card-actions">
+							<view class="card-actions-item" @click="viewBreedTaskMore(item)">
+								<uni-icons v-if="item.showMore == false" type="bottom" size="18" color="#999"></uni-icons>
+								<uni-icons v-if="item.showMore == true" type="top" size="18" color="#999"></uni-icons>
+								<text class="card-actions-item-text" v-if="item.showMore == false">展开</text>
+								<text class="card-actions-item-text" v-if="item.showMore == true">折叠</text>
+							</view>
+							<view class="card-actions-item" @click="viewBreedTaskDetail(item)">
+								<uni-icons type="info-filled" size="18" color="#999"></uni-icons>
+								<text class="card-actions-item-text">详情</text>
+							</view>
+							<view class="card-actions-item" @click="viewBreedTaskStep(item)">
+								<uni-icons type="tune" size="18" color="#999"></uni-icons>
+								<text class="card-actions-item-text">脚印</text>
+							</view>
+							<view class="card-actions-item" @click="feedBack(item)">
+								<uni-icons type="compose" size="18" color="#999"></uni-icons>
+								<text class="card-actions-item-text">反馈</text>
+							</view>
+						</view>
+					</uni-card>
+				</template>
+			</uni-list-item>
+		</uni-list>
+<!-- 		<view v-show="isLoadMore">
+			<uni-load-more :status="loadStatus" showIcon @clickLoadMore="loadMoreBill()"></uni-load-more>
+		</view> -->
+		
+		<u-popup :show="feedBackPopupShow" :overlay="true" mode="bottom" :closeable="true" :closeOnClickOverlay="true"
+			@close="feedBackPopupClose">
+			<view class="u-popup-slot">
+				<uni-section
+					:title="focuseTask.printBill.billCode + '(' + focuseTask.printBreed.breedName + ')'"
+					type="line"></uni-section>
+				<view>
+					<uni-forms ref="feedBackForm">
+						<uni-forms-item label="是否完成" required name="feedBackComplete">
+							<uni-data-checkbox v-model="feedBackData.feedBackComplete" :multiple="true" :localdata="feedBackCompleteStatus" />
+						</uni-forms-item>
+						<uni-forms-item label="反馈数量" required name="feedBackCount">
+							<uni-easyinput type="number" v-model="feedBackData.feedBackCount"
+								placeholder="请输入数量" />
+						</uni-forms-item>
+						<uni-forms-item label="反馈备注" name="feedBackMemo">
+							<uni-easyinput type="textarea" v-model="feedBackData.feedBackMemo" placeholder="请输入备注" />
+						</uni-forms-item>
+					</uni-forms>
+					<button type="primary" @click="submitFeedBackForm('feedBackForm')">提交</button>
+				</view>
+			</view>
+		</u-popup>
+		<view class="footer">
+			<view>
+				<view>
+					<text class="footer-text">总数:18</text><br>
+					<text style="margin-top: -10rpx;" class="footer-text">包数:26</text>
+				</view>
+			</view>
+			<view @click="confirmOrderCodes">确认交接</view>
+		</view>
+		
+		<uni-fab style="bottom: 100rpx;" ref="fab" :pattern="fabPattern" icon="scan" :popMenu="false" horizontal="right" vertical="bottom"
+			@fabClick="scanFabClick" />
+	</view>
+</template>
+
+<script>
+	import request from '@/common/libs/request.js';
+	export default {
+		data() {
+			return {
+				fabPattern: {
+					color: '#7A7E83',
+					backgroundColor: '#fff',
+					selectedColor: '#007AFF',
+					buttonColor: '#007AFF',
+					iconColor: '#fff'
+				},
+				idMachineInfo: 0,
+				breedTaskList: [],
+				feedBackPopupShow: false,
+				focuseTask: {
+					printBill:{},
+					printBreed:{}
+				},
+				feedBackData: {
+					feedBackCount: 0,
+					feedBackComplete:[1],
+					feedBackMemo: ''
+				},
+				feedBackCompleteStatus:[
+					{
+						text: '任务已完成',
+						value: 1
+					}
+				]
+			}
+		},
+		onLoad() {
+			// if (process.env.NODE_ENV === 'development') {
+			// 	this.fillBreedTaskByMachine(2, 1);
+			// }
+		},
+		methods: {
+			confirmOrderCodes(){
+				
+			},
+			searchPrintBreed() {
+				
+			},
+			scanFabClick() {
+				let _that = this;
+				uni.scanCode({
+					onlyFromCamera: true,
+					scanType: ['barCode', 'qrCode'],
+					success: function(res) {
+						if (res.result.match(new RegExp("^machine.*$"))) {
+							let idMachine = res.result.split("-")[1];
+							_that.idMachineInfo = idMachine;
+							_that.fillBreedTaskByMachine(idMachine, 1);
+						} else if (res.result.match(new RegExp("^printbill.*$"))) {
+							
+						}
+					}
+				})
+			},
+			fillBreedTaskByMachine(idMachine, pageIndex) {
+				let _that = this;
+				let listData = {
+					params: JSON.stringify({
+						idProcess: 5,
+						idMachineInfo: idMachine,
+						keyWord: ""
+					}),
+					page: JSON.stringify({
+						pageIndex: pageIndex,
+						pageSize: 20
+					})
+				}
+				
+				request.httpPost("/apis/printbill/queryBreedTasksToFeedback", listData, true).then(res => {
+					if (res.httpCode == 200) {
+						res.data.forEach(item => {
+							item.showMore = false
+						})
+						_that.breedTaskList = res.data;
+					}
+				});
+			},
+			parseBreedTaskStatus(task) {
+				if (task.pauseStatus == 0) {
+					if (task.taskStatus == 0) {
+						return "未开始";
+					} else if (task.taskStatus == 1) {
+						return "生产中";
+					} else if (task.taskStatus == 2) {
+						return "终止";
+					} else if (task.taskStatus == 5) {
+						return "完成";
+					} else if (task.taskStatus == 10) {
+						return "已完成";
+					}
+				} else {
+					return "暂停";
+				}
+			},
+			viewBreedTaskMore(task) {
+				task.showMore = !task.showMore
+			},
+			feedBack(task) {
+				let _that = this;
+				_that.focuseTask = task;
+				console.log(JSON.stringify(_that.feedBackData));
+				if (task.taskStatus == 0) {
+					//反馈开始
+					uni.showModal({
+					    title: '印刷反馈',
+					    content: '是否反馈任务开始?',
+					    success: function (resConfirm) {
+					        if (resConfirm.confirm) {
+					            let postData = {
+					            	item: JSON.stringify({
+					            		idTask: task.id,
+										taskStatus: 0,
+										isComplete: true,
+										feedbackCount: "",
+										memo: ""
+					            	})
+					            }
+					            request.httpPost("/apis/printbill/feedbackTask", postData, true).then(resFeedBack => {
+					            	if (resFeedBack.httpCode == 200) {
+										task.taskStatus = 1;
+					            		uni.showToast({
+					            			title:"反馈成功"
+					            		})
+					            	} else {
+										uni.showToast({
+											title: resFeedBack.msg
+										})
+									}
+					            });
+					        } else if (resConfirm.cancel) {
+					            console.log('用户点击取消');
+					        }
+					    }
+					});
+				} else if (task.taskStatus == 1) {
+					//反馈完成
+					_that.feedBackPopupShow = true;
+				}
+			},
+			feedBackPopupClose() {
+				this.feedBackPopupShow = false;
+				console.log(JSON.stringify(this.feedBackData));
+			},
+			submitFeedBackForm(ref) {
+				let _that = this;
+				let isComplete = true;
+				if (_that.feedBackData.feedBackComplete.length == 0) {
+					isComplete = false
+				}
+				let postData = {
+					item: JSON.stringify({
+						idTask: _that.focuseTask.id,
+						taskStatus: 1,
+						isComplete: isComplete,
+						feedbackCount:_that.feedBackData.feedBackCount,
+						memo: _that.feedBackData.feedBackMemo
+					})
+				}
+				request.httpPost("/apis/printbill/feedbackTask", postData, true).then(resFeedBack => {
+					if (resFeedBack.httpCode == 200) {
+						_that.focuseTask.taskStatus = 1;
+						uni.showToast({
+							title:"反馈成功"
+						})
+					} else {
+						uni.showToast({
+							title: resFeedBack.msg
+						})
+					}
+				});
+			},
+			viewBreedTaskDetail(task) {
+				uni.navigateTo({
+					url: "../printbill/detail?id=" + task.idPrintBill + "&billCode=" + task.printBill.billCode,
+					animationType: 'pop-in'
+				})
+			},
+			viewBreedTaskStep(task) {
+				uni.navigateTo({
+					url: "../printbill/step?id=" + task.idPrintBill + "&billCode=" + task.printBill.billCode,
+					animationType: 'pop-in'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+
+	/deep/ .uni-list-item__container {
+		padding: 0rpx;
+	}
+	
+	.card-actions {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-around;
+		align-items: center;
+		height: 45px;
+		border-top: 1px #eee solid;
+	}
+	
+	.card-actions-item {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+	}
+	
+	.card-actions-item-text {
+		font-size: 12px;
+		color: #666;
+		margin-left: 5px;
+	}
+	
+	.textTitle {
+		border-left: 0px solid #007AFF;
+		display: inline-block;
+		width: 180rpx;
+		text-align: left;
+		margin-bottom: 5px;
+		color: #8799a3;
+	}
+	
+	.u-popup-slot {
+		width: 750rpx;
+		height: 400px;
+		@include flex;
+		justify-content: center;
+		align-items: center;
+		padding: 20px;
+	}
+	.footer {
+		position: fixed;
+		bottom: 0;
+		z-index: 10;
+		display: flex;
+		justify-content: space-between;
+		width: 100%;
+		height: 108rpx;
+		background: #FFFFFF;
+		border-top: 1px solid #E8E8E8;
+	
+		>view {
+			width: 50%;
+			height: 100%;
+			font-size: 34rpx;
+			font-weight: 600;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+	
+			&:active {
+				opacity: 0.8;
+			}
+	
+			.cart {
+				width: 67rpx;
+				height: 67rpx;
+				margin-top: 10rpx;
+				margin-right: 25rpx;
+			}
+	
+			.amout {
+				font-size: 34rpx;
+	
+				>text {
+					font-size: 20rpx;
+				}
+			}
+	
+			.badge {
+				position: relative;
+	
+				>text {
+					position: absolute;
+					top: 2rpx;
+					right: 10rpx;
+					z-index: 10;
+					font-size: 22rpx;
+					background: #FF3D00;
+					border-radius: 50%;
+					color: #fff;
+					padding: 0 10rpx 2rpx;
+				}
+			}
+		}
+	
+		>view:last-child {
+			background: #FFD202;
+		}
+	}
+</style>

+ 193 - 0
pages/feedback/scanOrderCode.vue

@@ -0,0 +1,193 @@
+<template>
+	<view class="page-container">
+		<view>
+			<appScan ref="appScan" @scanHitERPCode="scanHitERPCode"></appScan>
+		</view>
+
+		<view class="codeList">
+			<view class="codeItem" v-for="(item,index) in hitOrders" :title="item.orderCode" :index="index" :threshold="0">
+				{{item.orderCode}}
+			</view>
+
+		</view>
+
+
+		<view class="footer">
+			<view>
+				<view>
+					<text>总数:18</text><br>
+					<text>包数:26</text>
+				</view>
+			</view>
+			<view @click="confirmOrderCodes">确认装车</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import appScan from "../../components/app-continue-scancode/app-continue-scancode.vue"
+	export default {
+		components: {
+			appScan
+		},
+		data() {
+			return {
+				totalCount: 0,
+				hitOrders: []
+			}
+		},
+		methods: {
+			scanHitERPCode(e) {
+				let _that = this;
+				console.log(e.code);
+				if (e.code.match(new RegExp("^printorder.*$"))) {
+					let ids = e.code.split("-");
+					if (!_that.checkCodeExists(ids[2])) {
+						_that.hitOrders.push({
+							id: ids[2],
+							orderCode: ids[1]
+						})
+						this.totalCount++
+					}
+				}
+			},
+			checkCodeExists(id) {
+				let _that = this;
+				let code = _that.hitOrders.find(function(v) {
+					return (v.id == id);
+				})
+				return ((code) && (code != null) && (code != undefined));
+			},
+			confirmOrderCodes() {
+				let _that = this;
+				if (_that.hitOrders.length > 0) {
+					uni.$emit('confirmHitERPCode', {
+						hits: _that.hitOrders
+					})
+					setTimeout(() => {
+						uni.navigateBack({})
+					}, 500)
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.footer-text{
+		line-height: 18rpx;
+	}
+	.page-container {
+		position: relative;
+		height: 100%;
+		overflow: hidden;
+		background-color: rgba(0, 0, 0, 0.6);
+
+		.input {
+			position: relative;
+			z-index: 20;
+			margin-top: 80rpx;
+			height: 70rpx;
+			padding: 0 80rpx;
+
+			/deep/ .search-input {
+				height: 70rpx;
+				color: #fff;
+				border-radius: 40rpx;
+				border: 1px solid #FFD202;
+			}
+		}
+	}
+
+	.wx-scan-container {
+		margin-top: 100rpx;
+		height: 450rpx;
+
+		.wx-tip {
+			font-size: 30rpx;
+			color: #FFFFFF;
+			text-align: center;
+			margin-top: 30rpx;
+		}
+	}
+
+	.codeList {
+		position: absolute;
+		display: flex;
+		flex-direction: row;
+		flex-wrap: wrap;
+		justify-content: space-between;
+		top: 340px;
+		bottom: 50px;
+		z-index: 10;
+		width: 100%;
+		background: #FFFFFF;
+		.codeItem {
+			width: 48%;
+			height: 30rpx;
+			border: 0px;
+			margin-top: 2rpx;
+		}
+	}
+
+	.footer {
+		position: fixed;
+		bottom: 0;
+		z-index: 10;
+		display: flex;
+		justify-content: space-between;
+		width: 100%;
+		height: 108rpx;
+		background: #FFFFFF;
+		border-top: 1px solid #E8E8E8;
+
+		>view {
+			width: 50%;
+			height: 100%;
+			font-size: 34rpx;
+			font-weight: 600;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+
+			&:active {
+				opacity: 0.8;
+			}
+
+			.cart {
+				width: 67rpx;
+				height: 67rpx;
+				margin-top: 10rpx;
+				margin-right: 25rpx;
+			}
+
+			.amout {
+				font-size: 34rpx;
+
+				>text {
+					font-size: 20rpx;
+				}
+			}
+
+			.badge {
+				position: relative;
+
+				>text {
+					position: absolute;
+					top: 2rpx;
+					right: 10rpx;
+					z-index: 10;
+					font-size: 22rpx;
+					background: #FF3D00;
+					border-radius: 50%;
+					color: #fff;
+					padding: 0 10rpx 2rpx;
+				}
+			}
+		}
+
+		>view:last-child {
+			background: #FFD202;
+		}
+	}
+</style>

+ 94 - 0
pages/index/me.vue

@@ -0,0 +1,94 @@
+<template>
+	<view class="w-h-100">
+		<view class="cu-bar">
+			<u-row gutter="20">
+				<u-col span="4">
+					<view><u-avatar :src="src"></u-avatar></view>
+				</u-col>
+				<u-col span="8">
+					<view class="avatar-txt">
+						<span>张某某(<b style="color: #e4493c;">未审核</b>)</span>
+						<span>豫A99uk68</span>
+					</view>
+				</u-col>
+			</u-row>
+		</view>
+		<view class="list-con">
+			<u-cell-group>
+				<u-cell
+					:isLink="true"
+					title="我的资料"
+					icon="account"
+				></u-cell>
+				<u-cell
+					:isLink="true"
+					title="我的车辆"
+					icon="car"
+				></u-cell>
+				<u-cell
+					:isLink="true"
+					title="已配送订单(当月)"
+					icon="order"
+				></u-cell>
+			</u-cell-group>
+		</view>
+
+		<view class="padding-lr padding-tb-xs">
+			
+			<button class="cu-btn block shadow bg-white margin text-red" @tap="logout">退出登录</button>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				src: 'http://dn-dounengyin.qbox.me/Fvz4y4_hhBt0CaY9_8PMm8IeXc8p',
+			}
+		},
+		methods: {
+			bluetoothSetting() {
+				uni.navigateTo({
+					url: "../userconfig/bluetoothPrintConfig"
+				});
+			},
+			logout() {
+				uni.removeStorageSync('erpToken');
+				uni.reLaunch({
+					url: '/pages/login/login'
+				});
+			}
+		}
+	}
+</script>
+
+<style>
+	.cu-bar{
+		padding-left: 60rpx;
+		padding-top: 30rpx;
+	}
+	.avatar-txt span{
+		display: block;
+		width: 100;
+	}
+	.list-con{
+		margin-top: 50rpx;
+	}
+	.w-h-100 {
+		height: 100%;
+		width: 100%;
+	}
+
+	.uni-row .flex-item-30 {
+		color: #8799a3;
+	}
+
+	.flex-item-30 {
+		flex-basis: 30%;
+	}
+
+	.flex-item-70 {
+		flex-basis: 70%;
+	}
+</style>

+ 22 - 0
pages/index/order.vue

@@ -0,0 +1,22 @@
+<template>
+	<view>
+		配送列表
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 111 - 0
pages/index/tabbar.vue

@@ -0,0 +1,111 @@
+<template>
+	<view>
+		<workTable ref="workTableRef" v-if="pageCurrent=='workTable'"></workTable>
+		<me v-if="pageCurrent=='me'"></me>
+		
+		<view class="box">
+			<view class="cu-bar tabbar bg-white shadow foot">
+				<view class="action" @click="navChange" data-cur="order">
+					<view class='cuIcon-cu-image'>
+						<image v-if="pageCurrent=='order'" src="../../static/tabbar/order_cur.png"></image>
+						<image v-if="pageCurrent != 'order'" src="../../static/tabbar/order.png"></image>
+					</view>
+					<view :class="pageCurrent=='order'?'color_main':'text-gray'">配送列表</view>
+				</view>
+				<view class="action" @click="navChange" data-cur="workTable">
+					<view class='cuIcon-cu-image'>
+						<image v-if="pageCurrent=='workTable'" src="../../static/tabbar/workTable_cur.png"></image>
+						<image v-if="pageCurrent != 'workTable'" src="../../static/tabbar/workTable.png"></image>
+					</view>
+					<view :class="pageCurrent=='workTable'?'color_main':'text-gray'">工作台</view>
+				</view>
+				
+<!-- 				<view @click="navChange" class="action text-gray add-action" data-cur="workTable">
+					<image class="logo_btn" mode="widthFix" src="../../static/logo.png"></image>
+					<view :class="pageCurrent=='workTable'?'color_main':'text-gray'">工作台</view>
+				</view> -->
+				
+				<view class="action" @click="navChange" data-cur="me">
+					<view class='cuIcon-cu-image'>
+						<view class="cu-tag badge">
+							<!-- 红点 -->
+						</view>
+						<image v-if="pageCurrent=='me'" src="../../static/tabbar/me_cur.png"></image>
+						<image v-if="pageCurrent != 'me'" src="../../static/tabbar/me.png"></image>
+					</view>
+					<view :class="pageCurrent=='me'?'color_main':'text-gray'">个人中心</view>
+				</view>
+
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import order from "./order.vue"; //消息
+	import workTable from "./workTable.vue"; //工作台
+	import me from "./me.vue"; //个人中心
+	export default {
+		components: {
+			order,
+			workTable,
+			me
+		},
+		data() {
+			return {
+				pageCurrent: 'workTable'
+			}
+		},
+		methods: {
+			navChange: function(e) {
+				console.log(e.currentTarget.dataset.cur);
+				this.pageCurrent = e.currentTarget.dataset.cur;
+			}
+		},
+		onLoad: function (options) {
+			//uni.startPullDownRefresh();
+			setTimeout(function () {
+					console.log('start pulldown');
+			}, 1500);
+			// uni.startPullDownRefresh();
+		},
+		onPullDownRefresh() {
+			// console.log('refresh');
+			// if (this.pageCurrent == 'workTable') {				
+			// 	this.$refs['workTableRef'].pullDownRefresh();
+			// 	setTimeout(function () {
+			// 		uni.stopPullDownRefresh();
+			// 	}, 1000);
+			// }
+		}
+		
+	}
+</script>
+
+<style>
+	.box {
+		margin: 20upx 0;
+	}
+
+	.box view.cu-bar {
+		margin-top: 20upx;
+	}
+	
+	.logo_btn{
+		width: 38*2rpx;
+		height: 38*2rpx;
+		position: absolute;
+		z-index: 2;
+		border: #09BB07;
+		border-radius: 50%;
+		top: -50rpx;
+		left: 0rpx;
+		right: 0;
+		margin: auto;
+		padding: 0;
+	}
+	
+	.cu-bar.tabbar .action.add-action {
+	    padding-top: 56rpx !important;
+	}
+</style>

+ 300 - 0
pages/index/workTable.vue

@@ -0,0 +1,300 @@
+<template>
+	<view class="wrap">
+		<view class="orderMonitor">
+			<u-row  class="userinfo-topbox" gutter="16" justify="center">
+				<u-col span="6" text-align="center" style="margin: 1px;">
+					<view style="color: #CCFFFF;">豫A99uk68</view>
+				</u-col>
+				<u-col span="6" text-align="center" style="margin: 1px;">
+					<view style="color: #CCFFFF;"></view>
+				</u-col>
+			</u-row>
+			<u-row style="margin-top: -25rpx;"  class="userinfo-topbox" gutter="16" justify="center">
+				<u-col span="6" text-align="center" style="margin: 1px;">
+					<view style="color: #CCFFFF;">未配送订单</view>
+					<view class="number">50</view>
+				</u-col>
+				<u-col span="6" text-align="center" style="margin: 1px;">
+					<view style="color: #CCFFFF;">已配送订单</view>
+					<view class="number">20</view>
+				</u-col>
+			</u-row>
+		</view>
+		<view class="workbench-title">常用应用</view>
+		<view class="toolbar">
+			<u-grid class="grid" :col="4" :border="false">
+				<u-grid-item @click="navTo('/pages/feedback/scanOrderCode')"  :index="0">
+						<view   class="home-icon icon-color02">
+							<i class="iconfont icon-cangpeitubiao_huanhuorukutuihuoruku"></i>
+						</view>
+						<view class="grid-text">扫码装车</view>
+				</u-grid-item>
+				<u-grid-item @click="navTo('/pages/feedback/print')"  :index="1">
+						<view class="home-icon icon-color02">
+							<i class="iconfont icon-fahuo"></i>
+						</view>
+						<view class="grid-text">支线交接</view>
+				</u-grid-item>
+				<u-grid-item @click="scanFabClick"  :index="2">
+						<view class="home-icon icon-color02">
+							<i class="iconfont icon-kechengfankui"></i>
+						</view>
+						<view class="grid-text">扫码签收</view>
+				</u-grid-item>
+			</u-grid>
+		</view>
+	</view>
+</template>
+
+<script>
+	import request from '@/common/libs/request.js';
+	export default {
+		
+		data() {
+			return {
+				orderData:[],
+				cardData: "",
+				listData: {
+					total: 0,
+					page: 1,
+					pageSize: 20
+				},
+			}
+		},
+		onLoad(){
+	
+		},
+		mounted: function(option) {
+			console.log("111111111111")
+			this.getCurrentItems();
+			//不再这里调用,由主页刷新获取
+			// this.getIndexCardPanelData();
+		},
+	
+		methods: {
+			navTo(url) {
+				uni.navigateTo({
+					url: url
+				});
+			},
+			scanClickCar(){
+				let _that = this;
+				console.log("1111")
+				uni.reLaunch({
+					url: '/pages/feedback/scanOrderCode',
+				})
+			},
+			scanFabClick(e) {
+			let _that = this;
+			//扫码
+			uni.scanCode({
+				onlyFromCamera: true,
+				scanType: ['barCode', 'qrCode'],
+				success: function(res) {
+					console.log("121221",res)
+					_that.billScanOrderCode(res.result)
+				
+				}
+			})
+
+
+		},
+		billScanOrderCode(idOrder) {
+			let _that = this;
+			let dataInfo = {
+				"idOrder": idOrder,
+			}
+			
+			request.httpPost("/apis/dnyDriver/scanOrderCode", dataInfo, true).then(res => {
+				if (res.httpCode == 200) {
+					console.log("3333",res)
+				}
+			});
+		},
+		getCurrentItems(){
+			const _that = this;
+			var page = {
+				pageIndex: _that.listData.page,
+				pageSize: _that.listData.pageSize
+			}
+			var data = {
+				"page": JSON.stringify(page)
+			}
+			request.httpPost("/apis/dnyDriver/showCurrentTransitioningItems", data, false).then(res => {
+				if (res.httpCode == 200) {
+					console.log("4444",res)
+					_that.orderData = res.data
+				}else {
+					uni.showToast({
+						title: res.msg,
+						icon: "error"
+					})
+				}
+				
+
+			})
+		},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.orderMonitor {
+		height: 190upx;
+		border-radius: 4upx;
+		color: #F0F0F0;
+		// background-image: linear-gradient(to right, #ffffff 0%, #ffffff 100%);
+		background-image: linear-gradient(to right, #006699 0%, #6699CC 100%);
+		border: #ffffff;
+		padding: 16upx;
+		margin: 16upx;
+		box-shadow: 4upx 4upx 6upx rgba(102, 153, 204, 0.4);
+	}
+
+.userinfo-topbox{
+	padding: 4px 8px;
+	color: #000000;
+	.number{
+		font-size: 14px;
+		font-weight: bold;
+		color: #FF9900;
+	}
+}
+.userinfo-infobox{
+	color: #000000;
+	background-image: linear-gradient(to right, #CCCCCC 0%, #CCCCCC 100%);
+	.number{
+		font-size: 12px;
+	}
+}
+
+	.wrap {
+		background: #FFFFFF;
+		.search {
+			padding: 20rpx 20rpx 0;
+			background: #f8f8f8;
+			height: 105rpx;
+		}
+
+		.scroll-list {
+			height: calc(100vh - var(--window-top) - var(--window-bottom) - 105rpx); // 105rpx 为 .search 的高度
+			width: 100%;
+
+			.loadmore {
+				padding: 30rpx;
+			}
+		}
+
+		.box {
+			padding-bottom: 10rpx;
+
+			.item {
+				margin: 0 20rpx 20rpx;
+				padding: 8rpx 20rpx;
+				border-radius: 20rpx;
+				box-sizing: border-box;
+				background-color: #fff;
+				font-size: 28rpx;
+
+				.title {
+					display: flex;
+					justify-content: space-between;
+					background-color: #fff;
+					padding-left: 15rpx;
+					align-items: center;
+
+					.text {
+						margin: 0 20rpx;
+						font-size: 35rpx;
+						font-weight: bold;
+					}
+
+				}
+			}
+
+		}
+
+		.list {
+
+			.u-cell-item-box {
+
+				.u-swipe-content {
+					width: 750rpx;
+				}
+
+				.u-cell_title {
+					overflow: hidden;
+					white-space: nowrap;
+					text-overflow: ellipsis;
+					min-width: 655rpx;
+				}
+
+				.u-border-bottom:last-child:after {
+					border-bottom: 0;
+				}
+			}
+		}
+
+		.form {
+			display: flex;
+			flex-direction: column;
+			padding: 20rpx 30rpx;
+
+			.u-cell-item-box {
+				border-radius: 20rpx;
+			}
+		}
+
+		.form-footer {
+			display: flex;
+			margin: 10rpx;
+			padding-bottom: 30rpx;
+
+			.btn {
+				flex: 1;
+				margin: 20rpx;
+			}
+		}
+
+		.u-cell-box {
+
+			.u-cell {
+				font-size: 30rpx;
+			}
+
+			.u-cell_title {
+				font-size: 30rpx;
+			}
+
+			.u-cell__left-icon-wrap {
+				margin-right: 18rpx;
+			}
+		}
+	}
+
+	.workbench-title {
+		font-size: 32rpx;
+		font-weight: bold;
+		color: #333333;
+		padding: 15px 30rpx;
+	}
+
+
+	.grid {
+
+		.grid-icon {
+			color: #666;
+		}
+
+		.grid-text {
+			font-size: 24rpx;
+			padding: 15rpx;
+			color: #202328;
+		}
+	}
+
+	.toolbar {
+
+		background-color: #fff;
+	}
+</style>

+ 236 - 0
pages/login/login.vue

@@ -0,0 +1,236 @@
+<template>
+	<view class="t-login">
+		<!-- 页面装饰图片 -->
+		<image class="img-a" src="/static/2.png"></image>
+		<image class="img-b" src="/static/3.png"></image>
+		<!-- 标题 -->
+		<view class="t-b">{{ title }}</view>
+		<form class="cl">
+			<view class="t-a">
+				<image class="text-center cuIcon cuIcon-people"></image>
+				<view class="line"></view>
+				<input type="text" placeholder="请输入账号" v-model="loginName" />
+			</view>
+			<view class="t-a">
+				<image :class="[!showPassword ? 'text-center cuIcon cuIcon-unlock' : 'text-center cuIcon cuIcon-lock']"
+					class="text-center cuIcon cuIcon-lock" @tap="showPwd()"></image>
+				<!-- <image src="/static/pwd.png"></image> -->
+				<view class="line"></view>
+				<input type="text" :password="showPassword" :focus="buttonFocused" placeholder="请输入密码" v-model="password" @confirm="startLogin()" />
+			</view>
+			<button @tap="startLogin()">登 录</button>
+		</form>
+	</view>
+</template>
+
+<script>
+	import request from '@/common/libs/request.js';
+	export default {
+		data() {
+			return {
+				title: "都能运",
+				supplierArray: [{
+					itemName: "",
+					id: -99
+				}],
+				supplierIndex: 0,
+				showPassword: true,
+				loginName: "",
+				password: "",
+				buttonFocused: false
+			}
+		},
+		methods: {
+			bindPickerChange: function(e) {
+				this.supplierIndex = e.detail.value
+				console.log(this.supplierArray[this.supplierIndex].id);
+			},
+			showPwd: function() {
+				this.showPassword = !this.showPassword;
+			},
+			startLogin: function() {
+				var user = {
+					loginName: this.loginName,
+					password: this.password
+				};
+				var userData = {
+					"user": JSON.stringify(user),
+					"supplierId":1
+				}
+				request.httpPost("/apis/dnyDriver/login", userData, false).then(res => {
+					console.log(res);
+
+					if (res.httpCode == 200) {
+						uni.setStorageSync("erpToken", res.data.accessToken);
+						uni.reLaunch({
+							url: '/pages/index/tabbar',
+						})
+					} else {
+						uni.showToast({
+							title: res.msg,
+							icon: "error"
+						})
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+	.img-a {
+		position: absolute;
+		width: 100%;
+		top: -150rpx;
+		right: 0;
+	}
+
+	.img-b {
+		position: absolute;
+		width: 50%;
+		bottom: 0;
+		left: -50rpx;
+		/* margin-bottom: -200rpx; */
+	}
+
+	.t-login {
+		width: 650rpx;
+		margin: 0 auto;
+		font-size: 28rpx;
+		color: #000;
+	}
+
+	.t-login button {
+		font-size: 28rpx;
+		background: #5677fc;
+		color: #fff;
+		height: 90rpx;
+		line-height: 90rpx;
+		border-radius: 50rpx;
+		box-shadow: 0 5px 7px 0 rgba(86, 119, 252, 0.2);
+	}
+
+	.t-login picker {
+		padding: 0 20rpx 0 120rpx;
+		height: 90rpx;
+		line-height: 90rpx;
+		margin-bottom: 50rpx;
+		background: #FFCC00;
+		border: 1px solid #e9e9e9;
+		font-size: 28rpx;
+		border-radius: 50rpx;
+		box-shadow: 0 5px 7px 0 rgba(86, 119, 252, 0.2);
+	}
+
+	.t-login input {
+		padding: 0 20rpx 0 120rpx;
+		height: 90rpx;
+		line-height: 90rpx;
+		margin-bottom: 50rpx;
+		background: #f8f7fc;
+		border: 1px solid #e9e9e9;
+		font-size: 28rpx;
+		border-radius: 50rpx;
+	}
+
+	.t-login .t-a {
+		position: relative;
+	}
+
+	.t-login .t-a image {
+		width: 40rpx;
+		height: 40rpx;
+		position: absolute;
+		left: 40rpx;
+		top: 28rpx;
+		/* border-right: 2rpx solid #dedede; */
+		margin-right: 20rpx;
+	}
+
+	.t-login .t-a .line {
+		width: 2rpx;
+		height: 40rpx;
+		background-color: #dedede;
+		position: absolute;
+		top: 28rpx;
+		left: 98rpx;
+	}
+
+	.t-login .t-b {
+		text-align: left;
+		font-size: 46rpx;
+		color: #000;
+		padding: 250rpx 0 30rpx 0;
+		font-weight: bold;
+	}
+
+	.t-login .t-b2 {
+		text-align: left;
+		font-size: 32rpx;
+		color: #aaaaaa;
+		padding: 0rpx 0 120rpx 0;
+	}
+
+	.t-login .t-c {
+		position: absolute;
+		right: 22rpx;
+		top: 22rpx;
+		background: #5677fc;
+		color: #fff;
+		font-size: 24rpx;
+		border-radius: 50rpx;
+		height: 50rpx;
+		line-height: 50rpx;
+		padding: 0 25rpx;
+	}
+
+	.t-login .t-d {
+		text-align: center;
+		color: #999;
+		margin: 80rpx 0;
+	}
+
+	.t-login .t-e {
+		text-align: center;
+		width: 250rpx;
+		margin: 80rpx auto 0;
+	}
+
+	.t-login .t-g {
+		float: left;
+		width: 50%;
+	}
+
+	.t-login .t-e image {
+		width: 50rpx;
+		height: 50rpx;
+	}
+
+	.t-login .t-f {
+		text-align: center;
+		margin: 200rpx 0 0 0;
+		color: #666;
+	}
+
+	.t-login .t-f text {
+		margin-left: 20rpx;
+		color: #aaaaaa;
+		font-size: 27rpx;
+	}
+
+	.t-login .uni-input-placeholder {
+		color: #000;
+	}
+
+	.cl {
+		zoom: 1;
+	}
+
+	.cl:after {
+		clear: both;
+		display: block;
+		visibility: hidden;
+		height: 0;
+		content: '\20';
+	}
+</style>

BIN
static/2.png


BIN
static/3.png


+ 79 - 0
static/iconfont/iconfont.css

@@ -0,0 +1,79 @@
+@font-face {
+  font-family: "iconfont";
+  src: url('~@/static/iconfont/iconfont.woff2?t=1642478325638') format('woff2'),
+       url('~@/static/iconfont/iconfont.woff?t=1642478325638') format('woff'),
+       url('~@/static/iconfont/iconfont.ttf?t=1642478325638') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-circle1:before {
+  content: "\e80c";
+}
+
+.icon-check-circle:before {
+  content: "\e77d";
+}
+
+.icon-circle:before {
+  content: "\e816";
+}
+
+.icon-tubiaozhizuomoban-82:before {
+  content: "\e602";
+}
+
+.icon-tongji:before {
+  content: "\e631";
+}
+
+.icon-fankuiyijian:before {
+  content: "\e649";
+}
+
+.icon-qitadingdan:before {
+  content: "\e89d";
+}
+
+.icon-tongji1:before {
+  content: "\e663";
+}
+
+.icon-fahuo:before {
+  content: "\e6b4";
+}
+
+.icon-kechengfankui:before {
+  content: "\e64b";
+}
+
+.icon-dabao:before {
+  content: "\e606";
+}
+
+.icon-tongji2:before {
+  content: "\e60c";
+}
+
+.icon-yijianfankui:before {
+  content: "\e635";
+}
+
+.icon-lishigongdan:before {
+  content: "\e7bc";
+}
+
+.icon-cangpeitubiao_huanhuorukutuihuoruku:before {
+  content: "\e60f";
+}
+
+.icon-dingdan-quanbudingdan:before {
+  content: "\e626";
+}
+

BIN
static/iconfont/iconfont.ttf


BIN
static/iconfont/iconfont.woff


BIN
static/iconfont/iconfont.woff2


BIN
static/tabbar/me.png


BIN
static/tabbar/me_cur.png


BIN
static/tabbar/message.png


BIN
static/tabbar/message_cur.png


BIN
static/tabbar/order.png


BIN
static/tabbar/order_cur.png


BIN
static/tabbar/workTable.png


BIN
static/tabbar/workTable_cur.png


BIN
static/uni.ttf


+ 38 - 0
theme.scss

@@ -0,0 +1,38 @@
+// 此文件为uView的主题变量,这些变量目前只能通过uni.scss引入才有效,另外由于
+// uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大,
+// 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入
+
+$u-main-color: #303133;
+$u-content-color: #606266;
+$u-tips-color: #909399;
+$u-light-color: #c0c4cc;
+$u-border-color: #e4e7ed;
+$u-bg-color: #f3f4f6;
+
+$u-type-primary: #2979ff;
+$u-type-primary-light: #ecf5ff;
+$u-type-primary-disabled: #a0cfff;
+$u-type-primary-dark: #2b85e4;
+
+$u-type-warning: #ff9900;
+$u-type-warning-disabled: #fcbd71;
+$u-type-warning-dark: #f29100;
+$u-type-warning-light: #fdf6ec;
+
+$u-type-success: #19be6b;
+$u-type-success-disabled: #71d5a1;
+$u-type-success-dark: #18b566;
+$u-type-success-light: #dbf1e1;
+
+$u-type-error: #fa3534;
+$u-type-error-disabled: #fab6b6;
+$u-type-error-dark: #dd6161;
+$u-type-error-light: #fef0f0;
+
+$u-type-info: #909399;
+$u-type-info-disabled: #c8c9cc;
+$u-type-info-dark: #82848a;
+$u-type-info-light: #f4f4f5;
+
+$u-form-item-height: 70rpx;
+$u-form-item-border-color: #dcdfe6;

+ 33 - 0
uni_modules/uni-badge/changelog.md

@@ -0,0 +1,33 @@
+## 1.2.2(2023-01-28)
+- 修复 运行/打包 控制台警告问题
+## 1.2.1(2022-09-05)
+- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
+## 1.1.7(2021-11-08)
+- 优化 升级ui
+- 修改 size 属性默认值调整为 small
+- 修改 type 属性,默认值调整为 error,info 替换 default
+## 1.1.6(2021-09-22)
+- 修复 在字节小程序上样式不生效的 bug
+## 1.1.5(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.4(2021-07-29)
+- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
+## 1.1.3(2021-06-24)
+- 优化 示例项目
+## 1.1.1(2021-05-12)
+- 新增 组件示例地址
+## 1.1.0(2021-05-12)
+- 新增 uni-badge 的 absolute 属性,支持定位
+- 新增 uni-badge 的 offset 属性,支持定位偏移
+- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
+- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
+- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
+## 1.0.7(2021-05-07)
+- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
+- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
+- 新增 uni-badge 属性 custom-style, 支持自定义样式
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范

+ 268 - 0
uni_modules/uni-badge/components/uni-badge/uni-badge.vue

@@ -0,0 +1,268 @@
+<template>
+	<view class="uni-badge--x">
+		<slot />
+		<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
+			class="uni-badge" @click="onClick()">{{displayValue}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Badge 数字角标
+	 * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=21
+	 * @property {String} text 角标内容
+	 * @property {String} size = [normal|small] 角标内容
+	 * @property {String} type = [info|primary|success|warning|error] 颜色类型
+	 * 	@value info 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * @property {String} inverted = [true|false] 是否无需背景颜色
+	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
+	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
+	 * 	@value rightTop 右上
+	 * 	@value rightBottom 右下
+	 * 	@value leftTop 左上
+	 * 	@value leftBottom 左下
+	 * @property {Array[number]} offset	距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
+	 * @property {String} isDot = [true|false] 是否显示为一个小点
+	 * @event {Function} click 点击 Badge 触发事件
+	 * @example <uni-badge text="1"></uni-badge>
+	 */
+
+	export default {
+		name: 'UniBadge',
+		emits: ['click'],
+		props: {
+			type: {
+				type: String,
+				default: 'error'
+			},
+			inverted: {
+				type: Boolean,
+				default: false
+			},
+			isDot: {
+				type: Boolean,
+				default: false
+			},
+			maxNum: {
+				type: Number,
+				default: 99
+			},
+			absolute: {
+				type: String,
+				default: ''
+			},
+			offset: {
+				type: Array,
+				default () {
+					return [0, 0]
+				}
+			},
+			text: {
+				type: [String, Number],
+				default: ''
+			},
+			size: {
+				type: String,
+				default: 'small'
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {};
+		},
+		computed: {
+			width() {
+				return String(this.text).length * 8 + 12
+			},
+			classNames() {
+				const {
+					inverted,
+					type,
+					size,
+					absolute
+				} = this
+				return [
+					inverted ? 'uni-badge--' + type + '-inverted' : '',
+					'uni-badge--' + type,
+					'uni-badge--' + size,
+					absolute ? 'uni-badge--absolute' : ''
+				].join(' ')
+			},
+			positionStyle() {
+				if (!this.absolute) return {}
+				let w = this.width / 2,
+					h = 10
+				if (this.isDot) {
+					w = 5
+					h = 5
+				}
+				const x = `${- w  + this.offset[0]}px`
+				const y = `${- h + this.offset[1]}px`
+
+				const whiteList = {
+					rightTop: {
+						right: x,
+						top: y
+					},
+					rightBottom: {
+						right: x,
+						bottom: y
+					},
+					leftBottom: {
+						left: x,
+						bottom: y
+					},
+					leftTop: {
+						left: x,
+						top: y
+					}
+				}
+				const match = whiteList[this.absolute]
+				return match ? match : whiteList['rightTop']
+			},
+			dotStyle() {
+				if (!this.isDot) return {}
+				return {
+					width: '10px',
+					minWidth: '0',
+					height: '10px',
+					padding: '0',
+					borderRadius: '10px'
+				}
+			},
+			displayValue() {
+				const {
+					isDot,
+					text,
+					maxNum
+				} = this
+				return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit('click');
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-primary: #2979ff !default;
+	$uni-success: #4cd964 !default;
+	$uni-warning: #f0ad4e !default;
+	$uni-error: #dd524d !default;
+	$uni-info: #909399 !default;
+
+
+	$bage-size: 12px;
+	$bage-small: scale(0.8);
+
+	.uni-badge--x {
+		/* #ifdef APP-NVUE */
+		// align-self: flex-start;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-badge--absolute {
+		position: absolute;
+	}
+
+	.uni-badge--small {
+		transform: $bage-small;
+		transform-origin: center center;
+	}
+
+	.uni-badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		overflow: hidden;
+		box-sizing: border-box;
+		font-feature-settings: "tnum";
+		min-width: 20px;
+		/* #endif */
+		justify-content: center;
+		flex-direction: row;
+		height: 20px;
+		padding: 0 4px;
+		line-height: 18px;
+		color: #fff;
+		border-radius: 100px;
+		background-color: $uni-info;
+		background-color: transparent;
+		border: 1px solid #fff;
+		text-align: center;
+		font-family: 'Helvetica Neue', Helvetica, sans-serif;
+		font-size: $bage-size;
+		/* #ifdef H5 */
+		z-index: 999;
+		cursor: pointer;
+		/* #endif */
+
+		&--info {
+			color: #fff;
+			background-color: $uni-info;
+		}
+
+		&--primary {
+			background-color: $uni-primary;
+		}
+
+		&--success {
+			background-color: $uni-success;
+		}
+
+		&--warning {
+			background-color: $uni-warning;
+		}
+
+		&--error {
+			background-color: $uni-error;
+		}
+
+		&--inverted {
+			padding: 0 5px 0 0;
+			color: $uni-info;
+		}
+
+		&--info-inverted {
+			color: $uni-info;
+			background-color: transparent;
+		}
+
+		&--primary-inverted {
+			color: $uni-primary;
+			background-color: transparent;
+		}
+
+		&--success-inverted {
+			color: $uni-success;
+			background-color: transparent;
+		}
+
+		&--warning-inverted {
+			color: $uni-warning;
+			background-color: transparent;
+		}
+
+		&--error-inverted {
+			color: $uni-error;
+			background-color: transparent;
+		}
+
+	}
+</style>

+ 85 - 0
uni_modules/uni-badge/package.json

@@ -0,0 +1,85 @@
+{
+  "id": "uni-badge",
+  "displayName": "uni-badge 数字角标",
+  "version": "1.2.2",
+  "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
+  "keywords": [
+    "",
+    "badge",
+    "uni-ui",
+    "uniui",
+    "数字角标",
+    "徽章"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 10 - 0
uni_modules/uni-badge/readme.md

@@ -0,0 +1,10 @@
+## Badge 数字角标
+> **组件名:uni-badge**
+> 代码块: `uBadge`
+
+数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+

+ 26 - 0
uni_modules/uni-calendar/changelog.md

@@ -0,0 +1,26 @@
+## 1.4.10(2023-04-10)
+- 修复 某些情况 monthSwitch 未触发的Bug
+## 1.4.9(2023-02-02)
+- 修复 某些情况切换月份错误的Bug
+## 1.4.8(2023-01-30)
+- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964)
+## 1.4.7(2022-09-16)
+- 优化 支持使用 uni-scss 控制主题色
+## 1.4.6(2022-09-08)
+- 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug
+## 1.4.5(2022-02-25)
+- 修复 条件编译 nvue 不支持的 css 样式的Bug
+## 1.4.4(2022-02-25)
+- 修复 条件编译 nvue 不支持的 css 样式的Bug
+## 1.4.3(2021-09-22)
+- 修复 startDate、 endDate 属性失效的Bug
+## 1.4.2(2021-08-24)
+- 新增 支持国际化
+## 1.4.1(2021-08-05)
+- 修复 弹出层被 tabbar 遮盖的Bug
+## 1.4.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.3.16(2021-05-12)
+- 新增 组件示例地址
+## 1.3.15(2021-02-04)
+- 调整为uni_modules目录规范

+ 546 - 0
uni_modules/uni-calendar/components/uni-calendar/calendar.js

@@ -0,0 +1,546 @@
+/**
+* @1900-2100区间内的公历、农历互转
+* @charset UTF-8
+* @github  https://github.com/jjonline/calendar.js
+* @Author  Jea杨(JJonline@JJonline.Cn)
+* @Time    2014-7-21
+* @Time    2016-8-13 Fixed 2033hex、Attribution Annals
+* @Time    2016-9-25 Fixed lunar LeapMonth Param Bug
+* @Time    2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
+* @Version 1.0.3
+* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
+* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
+*/
+/* eslint-disable */
+var calendar = {
+
+  /**
+      * 农历1900-2100的润大小信息表
+      * @Array Of Property
+      * @return Hex
+      */
+  lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
+    0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
+    0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
+    0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
+    0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
+    0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
+    0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
+    0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
+    0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
+    0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
+    0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
+    0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
+    0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
+    0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
+    0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
+    /** Add By JJonline@JJonline.Cn**/
+    0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
+    0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
+    0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
+    0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
+    0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
+    0x0d520], // 2100
+
+  /**
+      * 公历每个月份的天数普通表
+      * @Array Of Property
+      * @return Number
+      */
+  solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
+
+  /**
+      * 天干地支之天干速查表
+      * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
+      * @return Cn string
+      */
+  Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
+
+  /**
+      * 天干地支之地支速查表
+      * @Array Of Property
+      * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
+      * @return Cn string
+      */
+  Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'],
+
+  /**
+      * 天干地支之地支速查表<=>生肖
+      * @Array Of Property
+      * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
+      * @return Cn string
+      */
+  Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'],
+
+  /**
+      * 24节气速查表
+      * @Array Of Property
+      * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
+      * @return Cn string
+      */
+  solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'],
+
+  /**
+      * 1900-2100各年的24节气日期速查表
+      * @Array Of Property
+      * @return 0x string For splice
+      */
+  sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
+    '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
+    'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
+    '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
+    '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
+    '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
+    '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
+    '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
+    '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+    '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+    '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
+    '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+    '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+    '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+    '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+    '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
+    '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
+    '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+    '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+    '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
+    '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
+    '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
+    '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
+    '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+    '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
+    '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
+    '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+    '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
+    '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
+    '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
+    '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
+    '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
+
+  /**
+      * 数字转中文速查表
+      * @Array Of Property
+      * @trans ['日','一','二','三','四','五','六','七','八','九','十']
+      * @return Cn string
+      */
+  nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'],
+
+  /**
+      * 日期转农历称呼速查表
+      * @Array Of Property
+      * @trans ['初','十','廿','卅']
+      * @return Cn string
+      */
+  nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
+
+  /**
+      * 月份转农历称呼速查表
+      * @Array Of Property
+      * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
+      * @return Cn string
+      */
+  nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'],
+
+  /**
+      * 返回农历y年一整年的总天数
+      * @param lunar Year
+      * @return Number
+      * @eg:var count = calendar.lYearDays(1987) ;//count=387
+      */
+  lYearDays: function (y) {
+    var i; var sum = 348
+    for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 }
+    return (sum + this.leapDays(y))
+  },
+
+  /**
+      * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0
+      * @param lunar Year
+      * @return Number (0-12)
+      * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
+      */
+  leapMonth: function (y) { // 闰字编码 \u95f0
+    return (this.lunarInfo[y - 1900] & 0xf)
+  },
+
+  /**
+      * 返回农历y年闰月的天数 若该年没有闰月则返回0
+      * @param lunar Year
+      * @return Number (0、29、30)
+      * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
+      */
+  leapDays: function (y) {
+    if (this.leapMonth(y)) {
+      return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
+    }
+    return (0)
+  },
+
+  /**
+      * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法
+      * @param lunar Year
+      * @return Number (-1、29、30)
+      * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
+      */
+  monthDays: function (y, m) {
+    if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1
+    return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
+  },
+
+  /**
+      * 返回公历(!)y年m月的天数
+      * @param solar Year
+      * @return Number (-1、28、29、30、31)
+      * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
+      */
+  solarDays: function (y, m) {
+    if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
+    var ms = m - 1
+    if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
+      return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
+    } else {
+      return (this.solarMonth[ms])
+    }
+  },
+
+  /**
+     * 农历年份转换为干支纪年
+     * @param  lYear 农历年的年份数
+     * @return Cn string
+     */
+  toGanZhiYear: function (lYear) {
+    var ganKey = (lYear - 3) % 10
+    var zhiKey = (lYear - 3) % 12
+    if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干
+    if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支
+    return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
+  },
+
+  /**
+     * 公历月、日判断所属星座
+     * @param  cMonth [description]
+     * @param  cDay [description]
+     * @return Cn string
+     */
+  toAstro: function (cMonth, cDay) {
+    var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
+    var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
+    return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座
+  },
+
+  /**
+      * 传入offset偏移量返回干支
+      * @param offset 相对甲子的偏移量
+      * @return Cn string
+      */
+  toGanZhi: function (offset) {
+    return this.Gan[offset % 10] + this.Zhi[offset % 12]
+  },
+
+  /**
+      * 传入公历(!)y年获得该年第n个节气的公历日期
+      * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起
+      * @return day Number
+      * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
+      */
+  getTerm: function (y, n) {
+    if (y < 1900 || y > 2100) { return -1 }
+    if (n < 1 || n > 24) { return -1 }
+    var _table = this.sTermInfo[y - 1900]
+    var _info = [
+      parseInt('0x' + _table.substr(0, 5)).toString(),
+      parseInt('0x' + _table.substr(5, 5)).toString(),
+      parseInt('0x' + _table.substr(10, 5)).toString(),
+      parseInt('0x' + _table.substr(15, 5)).toString(),
+      parseInt('0x' + _table.substr(20, 5)).toString(),
+      parseInt('0x' + _table.substr(25, 5)).toString()
+    ]
+    var _calday = [
+      _info[0].substr(0, 1),
+      _info[0].substr(1, 2),
+      _info[0].substr(3, 1),
+      _info[0].substr(4, 2),
+
+      _info[1].substr(0, 1),
+      _info[1].substr(1, 2),
+      _info[1].substr(3, 1),
+      _info[1].substr(4, 2),
+
+      _info[2].substr(0, 1),
+      _info[2].substr(1, 2),
+      _info[2].substr(3, 1),
+      _info[2].substr(4, 2),
+
+      _info[3].substr(0, 1),
+      _info[3].substr(1, 2),
+      _info[3].substr(3, 1),
+      _info[3].substr(4, 2),
+
+      _info[4].substr(0, 1),
+      _info[4].substr(1, 2),
+      _info[4].substr(3, 1),
+      _info[4].substr(4, 2),
+
+      _info[5].substr(0, 1),
+      _info[5].substr(1, 2),
+      _info[5].substr(3, 1),
+      _info[5].substr(4, 2)
+    ]
+    return parseInt(_calday[n - 1])
+  },
+
+  /**
+      * 传入农历数字月份返回汉语通俗表示法
+      * @param lunar month
+      * @return Cn string
+      * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
+      */
+  toChinaMonth: function (m) { // 月 => \u6708
+    if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
+    var s = this.nStr3[m - 1]
+    s += '\u6708'// 加上月字
+    return s
+  },
+
+  /**
+      * 传入农历日期数字返回汉字表示法
+      * @param lunar day
+      * @return Cn string
+      * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
+      */
+  toChinaDay: function (d) { // 日 => \u65e5
+    var s
+    switch (d) {
+      case 10:
+        s = '\u521d\u5341'; break
+      case 20:
+        s = '\u4e8c\u5341'; break
+        break
+      case 30:
+        s = '\u4e09\u5341'; break
+        break
+      default :
+        s = this.nStr2[Math.floor(d / 10)]
+        s += this.nStr1[d % 10]
+    }
+    return (s)
+  },
+
+  /**
+      * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
+      * @param y year
+      * @return Cn string
+      * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
+      */
+  getAnimal: function (y) {
+    return this.Animals[(y - 4) % 12]
+  },
+
+  /**
+      * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
+      * @param y  solar year
+      * @param m  solar month
+      * @param d  solar day
+      * @return JSON object
+      * @eg:console.log(calendar.solar2lunar(1987,11,01));
+      */
+  solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31
+    // 年份限定、上限
+    if (y < 1900 || y > 2100) {
+      return -1// undefined转换为数字变为NaN
+    }
+    // 公历传参最下限
+    if (y == 1900 && m == 1 && d < 31) {
+      return -1
+    }
+    // 未传参  获得当天
+    if (!y) {
+      var objDate = new Date()
+    } else {
+      var objDate = new Date(y, parseInt(m) - 1, d)
+    }
+    var i; var leap = 0; var temp = 0
+    // 修正ymd参数
+    var y = objDate.getFullYear()
+    var m = objDate.getMonth() + 1
+    var d = objDate.getDate()
+    var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000
+    for (i = 1900; i < 2101 && offset > 0; i++) {
+      temp = this.lYearDays(i)
+      offset -= temp
+    }
+    if (offset < 0) {
+      offset += temp; i--
+    }
+
+    // 是否今天
+    var isTodayObj = new Date()
+    var isToday = false
+    if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
+      isToday = true
+    }
+    // 星期几
+    var nWeek = objDate.getDay()
+    var cWeek = this.nStr1[nWeek]
+    // 数字表示周几顺应天朝周一开始的惯例
+    if (nWeek == 0) {
+      nWeek = 7
+    }
+    // 农历年
+    var year = i
+    var leap = this.leapMonth(i) // 闰哪个月
+    var isLeap = false
+
+    // 效验闰月
+    for (i = 1; i < 13 && offset > 0; i++) {
+      // 闰月
+      if (leap > 0 && i == (leap + 1) && isLeap == false) {
+        --i
+        isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数
+      } else {
+        temp = this.monthDays(year, i)// 计算农历普通月天数
+      }
+      // 解除闰月
+      if (isLeap == true && i == (leap + 1)) { isLeap = false }
+      offset -= temp
+    }
+    // 闰月导致数组下标重叠取反
+    if (offset == 0 && leap > 0 && i == leap + 1) {
+      if (isLeap) {
+        isLeap = false
+      } else {
+        isLeap = true; --i
+      }
+    }
+    if (offset < 0) {
+      offset += temp; --i
+    }
+    // 农历月
+    var month = i
+    // 农历日
+    var day = offset + 1
+    // 天干地支处理
+    var sm = m - 1
+    var gzY = this.toGanZhiYear(year)
+
+    // 当月的两个节气
+    // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
+    var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始
+    var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始
+
+    // 依据12节气修正干支月
+    var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
+    if (d >= firstNode) {
+      gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
+    }
+
+    // 传入的日期的节气与否
+    var isTerm = false
+    var Term = null
+    if (firstNode == d) {
+      isTerm = true
+      Term = this.solarTerm[m * 2 - 2]
+    }
+    if (secondNode == d) {
+      isTerm = true
+      Term = this.solarTerm[m * 2 - 1]
+    }
+    // 日柱 当月一日与 1900/1/1 相差天数
+    var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
+    var gzD = this.toGanZhi(dayCyclical + d - 1)
+    // 该日期所属的星座
+    var astro = this.toAstro(m, d)
+
+    return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro }
+  },
+
+  /**
+      * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
+      * @param y  lunar year
+      * @param m  lunar month
+      * @param d  lunar day
+      * @param isLeapMonth  lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
+      * @return JSON object
+      * @eg:console.log(calendar.lunar2solar(1987,9,10));
+      */
+  lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
+    var isLeapMonth = !!isLeapMonth
+    var leapOffset = 0
+    var leapMonth = this.leapMonth(y)
+    var leapDay = this.leapDays(y)
+    if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
+    if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值
+    var day = this.monthDays(y, m)
+    var _day = day
+    // bugFix 2016-9-25
+    // if month is leap, _day use leapDays method
+    if (isLeapMonth) {
+      _day = this.leapDays(y, m)
+    }
+    if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验
+
+    // 计算农历的时间差
+    var offset = 0
+    for (var i = 1900; i < y; i++) {
+      offset += this.lYearDays(i)
+    }
+    var leap = 0; var isAdd = false
+    for (var i = 1; i < m; i++) {
+      leap = this.leapMonth(y)
+      if (!isAdd) { // 处理闰月
+        if (leap <= i && leap > 0) {
+          offset += this.leapDays(y); isAdd = true
+        }
+      }
+      offset += this.monthDays(y, i)
+    }
+    // 转换闰月农历 需补充该年闰月的前一个月的时差
+    if (isLeapMonth) { offset += day }
+    // 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
+    var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
+    var calObj = new Date((offset + d - 31) * 86400000 + stmap)
+    var cY = calObj.getUTCFullYear()
+    var cM = calObj.getUTCMonth() + 1
+    var cD = calObj.getUTCDate()
+
+    return this.solar2lunar(cY, cM, cD)
+  }
+}
+
+export default calendar

+ 12 - 0
uni_modules/uni-calendar/components/uni-calendar/i18n/en.json

@@ -0,0 +1,12 @@
+{
+	"uni-calender.ok": "ok",
+	"uni-calender.cancel": "cancel",
+	"uni-calender.today": "today",
+	"uni-calender.MON": "MON",
+	"uni-calender.TUE": "TUE",
+	"uni-calender.WED": "WED",
+	"uni-calender.THU": "THU",
+	"uni-calender.FRI": "FRI",
+	"uni-calender.SAT": "SAT",
+	"uni-calender.SUN": "SUN"
+}

+ 8 - 0
uni_modules/uni-calendar/components/uni-calendar/i18n/index.js

@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}

+ 12 - 0
uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json

@@ -0,0 +1,12 @@
+{
+	"uni-calender.ok": "确定",
+	"uni-calender.cancel": "取消",
+	"uni-calender.today": "今日",
+	"uni-calender.SUN": "日",
+	"uni-calender.MON": "一",
+	"uni-calender.TUE": "二",
+	"uni-calender.WED": "三",
+	"uni-calender.THU": "四",
+	"uni-calender.FRI": "五",
+	"uni-calender.SAT": "六"
+}

+ 12 - 0
uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json

@@ -0,0 +1,12 @@
+{
+	"uni-calender.ok": "確定",
+	"uni-calender.cancel": "取消",
+	"uni-calender.today": "今日",
+	"uni-calender.SUN": "日",
+	"uni-calender.MON": "一",
+	"uni-calender.TUE": "二",
+	"uni-calender.WED": "三",
+	"uni-calender.THU": "四",
+	"uni-calender.FRI": "五",
+	"uni-calender.SAT": "六"
+}

+ 187 - 0
uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue

@@ -0,0 +1,187 @@
+<template>
+	<view class="uni-calendar-item__weeks-box" :class="{
+		'uni-calendar-item--disable':weeks.disable,
+		'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+		'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
+		'uni-calendar-item--before-checked':weeks.beforeMultiple,
+		'uni-calendar-item--multiple': weeks.multiple,
+		'uni-calendar-item--after-checked':weeks.afterMultiple,
+		}"
+	 @click="choiceDate(weeks)">
+		<view class="uni-calendar-item__weeks-box-item">
+			<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
+			<text class="uni-calendar-item__weeks-box-text" :class="{
+				'uni-calendar-item--isDay-text': weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.date}}</text>
+			<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				}">{{todayText}}</text>
+			<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
+			<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--extra':weeks.extraInfo.info,
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.extraInfo.info}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { initVueI18n } from '@dcloudio/uni-i18n'
+	import i18nMessages from './i18n/index.js'
+	const {	t	} = initVueI18n(i18nMessages)
+
+	export default {
+		emits:['change'],
+		props: {
+			weeks: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			calendar: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			},
+			selected: {
+				type: Array,
+				default: () => {
+					return []
+				}
+			},
+			lunar: {
+				type: Boolean,
+				default: false
+			}
+		},
+		computed: {
+			todayText() {
+				return t("uni-calender.today")
+			},
+		},
+		methods: {
+			choiceDate(weeks) {
+				this.$emit('change', weeks)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	$uni-font-size-base:14px;
+	$uni-text-color:#333;
+	$uni-font-size-sm:12px;
+	$uni-color-error: #e43d33;
+	$uni-opacity-disabled: 0.3;
+	$uni-text-color-disable:#c0c0c0;
+	$uni-primary: #2979ff !default;
+	.uni-calendar-item__weeks-box {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-calendar-item__weeks-box-text {
+		font-size: $uni-font-size-base;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar-item__weeks-lunar-text {
+		font-size: $uni-font-size-sm;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar-item__weeks-box-item {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		width: 100rpx;
+		height: 100rpx;
+	}
+
+	.uni-calendar-item__weeks-box-circle {
+		position: absolute;
+		top: 5px;
+		right: 5px;
+		width: 8px;
+		height: 8px;
+		border-radius: 8px;
+		background-color: $uni-color-error;
+
+	}
+
+	.uni-calendar-item--disable {
+		background-color: rgba(249, 249, 249, $uni-opacity-disabled);
+		color: $uni-text-color-disable;
+	}
+
+	.uni-calendar-item--isDay-text {
+		color: $uni-primary;
+	}
+
+	.uni-calendar-item--isDay {
+		background-color: $uni-primary;
+		opacity: 0.8;
+		color: #fff;
+	}
+
+	.uni-calendar-item--extra {
+		color: $uni-color-error;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--checked {
+		background-color: $uni-primary;
+		color: #fff;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--multiple {
+		background-color: $uni-primary;
+		color: #fff;
+		opacity: 0.8;
+	}
+	.uni-calendar-item--before-checked {
+		background-color: #ff5a5f;
+		color: #fff;
+	}
+	.uni-calendar-item--after-checked {
+		background-color: #ff5a5f;
+		color: #fff;
+	}
+</style>

+ 566 - 0
uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue

@@ -0,0 +1,566 @@
+<template>
+	<view class="uni-calendar">
+		<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view>
+		<view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
+			<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
+				<view class="uni-calendar__header-btn-box" @click="close">
+					<text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text>
+				</view>
+				<view class="uni-calendar__header-btn-box" @click="confirm">
+					<text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text>
+				</view>
+			</view>
+			<view class="uni-calendar__header">
+				<view class="uni-calendar__header-btn-box" @click.stop="pre">
+					<view class="uni-calendar__header-btn uni-calendar--left"></view>
+				</view>
+				<picker mode="date" :value="date" fields="month" @change="bindDateChange">
+					<text class="uni-calendar__header-text">{{ (nowDate.year||'') +' / '+( nowDate.month||'')}}</text>
+				</picker>
+				<view class="uni-calendar__header-btn-box" @click.stop="next">
+					<view class="uni-calendar__header-btn uni-calendar--right"></view>
+				</view>
+				<text class="uni-calendar__backtoday" @click="backToday">{{todayText}}</text>
+
+			</view>
+			<view class="uni-calendar__box">
+				<view v-if="showMonth" class="uni-calendar__box-bg">
+					<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
+				</view>
+				<view class="uni-calendar__weeks">
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{monText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
+					</view>
+				</view>
+				<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
+					<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
+						<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import Calendar from './util.js';
+	import CalendarItem from './uni-calendar-item.vue'
+
+	import { initVueI18n } from '@dcloudio/uni-i18n'
+	import i18nMessages from './i18n/index.js'
+	const {	t	} = initVueI18n(i18nMessages)
+
+	/**
+	 * Calendar 日历
+	 * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=56
+	 * @property {String} date 自定义当前时间,默认为今天
+	 * @property {Boolean} lunar 显示农历
+	 * @property {String} startDate 日期选择范围-开始日期
+	 * @property {String} endDate 日期选择范围-结束日期
+	 * @property {Boolean} range 范围选择
+	 * @property {Boolean} insert = [true|false] 插入模式,默认为false
+	 * 	@value true 弹窗模式
+	 * 	@value false 插入模式
+	 * @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
+	 * @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
+	 * @property {Boolean} showMonth 是否选择月份为背景
+	 * @event {Function} change 日期改变,`insert :ture` 时生效
+	 * @event {Function} confirm 确认选择`insert :false` 时生效
+	 * @event {Function} monthSwitch 切换月份时触发
+	 * @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
+	 */
+	export default {
+		components: {
+			CalendarItem
+		},
+		emits:['close','confirm','change','monthSwitch'],
+		props: {
+			date: {
+				type: String,
+				default: ''
+			},
+			selected: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			lunar: {
+				type: Boolean,
+				default: false
+			},
+			startDate: {
+				type: String,
+				default: ''
+			},
+			endDate: {
+				type: String,
+				default: ''
+			},
+			range: {
+				type: Boolean,
+				default: false
+			},
+			insert: {
+				type: Boolean,
+				default: true
+			},
+			showMonth: {
+				type: Boolean,
+				default: true
+			},
+			clearDate: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				show: false,
+				weeks: [],
+				calendar: {},
+				nowDate: '',
+				aniMaskShow: false
+			}
+		},
+		computed:{
+			/**
+			 * for i18n
+			 */
+
+			okText() {
+				return t("uni-calender.ok")
+			},
+			cancelText() {
+				return t("uni-calender.cancel")
+			},
+			todayText() {
+				return t("uni-calender.today")
+			},
+			monText() {
+				return t("uni-calender.MON")
+			},
+			TUEText() {
+				return t("uni-calender.TUE")
+			},
+			WEDText() {
+				return t("uni-calender.WED")
+			},
+			THUText() {
+				return t("uni-calender.THU")
+			},
+			FRIText() {
+				return t("uni-calender.FRI")
+			},
+			SATText() {
+				return t("uni-calender.SAT")
+			},
+			SUNText() {
+				return t("uni-calender.SUN")
+			},
+		},
+		watch: {
+			date(newVal) {
+				// this.cale.setDate(newVal)
+				this.init(newVal)
+			},
+			startDate(val){
+				this.cale.resetSatrtDate(val)
+				this.cale.setDate(this.nowDate.fullDate)
+				this.weeks = this.cale.weeks
+			},
+			endDate(val){
+				this.cale.resetEndDate(val)
+				this.cale.setDate(this.nowDate.fullDate)
+				this.weeks = this.cale.weeks
+			},
+			selected(newVal) {
+				this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
+				this.weeks = this.cale.weeks
+			}
+		},
+		created() {
+			this.cale = new Calendar({
+				selected: this.selected,
+				startDate: this.startDate,
+				endDate: this.endDate,
+				range: this.range,
+			})
+			this.init(this.date)
+		},
+		methods: {
+			// 取消穿透
+			clean() {},
+			bindDateChange(e) {
+				const value = e.detail.value + '-1'
+				this.setDate(value)
+
+				const { year,month } = this.cale.getDate(value)
+        this.$emit('monthSwitch', {
+            year,
+            month
+        })
+			},
+			/**
+			 * 初始化日期显示
+			 * @param {Object} date
+			 */
+			init(date) {
+				this.cale.setDate(date)
+				this.weeks = this.cale.weeks
+				this.nowDate = this.calendar = this.cale.getInfo(date)
+			},
+			/**
+			 * 打开日历弹窗
+			 */
+			open() {
+				// 弹窗模式并且清理数据
+				if (this.clearDate && !this.insert) {
+					this.cale.cleanMultipleStatus()
+					// this.cale.setDate(this.date)
+					this.init(this.date)
+				}
+				this.show = true
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this.aniMaskShow = true
+					}, 50)
+				})
+			},
+			/**
+			 * 关闭日历弹窗
+			 */
+			close() {
+				this.aniMaskShow = false
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this.show = false
+						this.$emit('close')
+					}, 300)
+				})
+			},
+			/**
+			 * 确认按钮
+			 */
+			confirm() {
+				this.setEmit('confirm')
+				this.close()
+			},
+			/**
+			 * 变化触发
+			 */
+			change() {
+				if (!this.insert) return
+				this.setEmit('change')
+			},
+			/**
+			 * 选择月份触发
+			 */
+			monthSwitch() {
+				let {
+					year,
+					month
+				} = this.nowDate
+				this.$emit('monthSwitch', {
+					year,
+					month: Number(month)
+				})
+			},
+			/**
+			 * 派发事件
+			 * @param {Object} name
+			 */
+			setEmit(name) {
+				let {
+					year,
+					month,
+					date,
+					fullDate,
+					lunar,
+					extraInfo
+				} = this.calendar
+				this.$emit(name, {
+					range: this.cale.multipleStatus,
+					year,
+					month,
+					date,
+					fulldate: fullDate,
+					lunar,
+					extraInfo: extraInfo || {}
+				})
+			},
+			/**
+			 * 选择天触发
+			 * @param {Object} weeks
+			 */
+			choiceDate(weeks) {
+				if (weeks.disable) return
+				this.calendar = weeks
+				// 设置多选
+				this.cale.setMultiple(this.calendar.fullDate)
+				this.weeks = this.cale.weeks
+				this.change()
+			},
+			/**
+			 * 回到今天
+			 */
+			backToday() {
+				const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}`
+				const date = this.cale.getDate(new Date())
+        const todayYearMonth = `${date.year}-${date.month}`
+
+        if(nowYearMonth !== todayYearMonth) {
+          this.monthSwitch()
+        }
+
+				this.init(date.fullDate)
+				this.change()
+			},
+			/**
+			 * 上个月
+			 */
+			pre() {
+				const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
+				this.setDate(preDate)
+				this.monthSwitch()
+
+			},
+			/**
+			 * 下个月
+			 */
+			next() {
+				const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
+				this.setDate(nextDate)
+				this.monthSwitch()
+			},
+			/**
+			 * 设置日期
+			 * @param {Object} date
+			 */
+			setDate(date) {
+				this.cale.setDate(date)
+				this.weeks = this.cale.weeks
+				this.nowDate = this.cale.getInfo(date)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	$uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4);
+	$uni-border-color: #EDEDED;
+	$uni-text-color: #333;
+	$uni-bg-color-hover:#f1f1f1;
+	$uni-font-size-base:14px;
+	$uni-text-color-placeholder: #808080;
+	$uni-color-subtitle: #555555;
+	$uni-text-color-grey:#999;
+	.uni-calendar {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-calendar__mask {
+		position: fixed;
+		bottom: 0;
+		top: 0;
+		left: 0;
+		right: 0;
+		background-color: $uni-bg-color-mask;
+		transition-property: opacity;
+		transition-duration: 0.3s;
+		opacity: 0;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-calendar--mask-show {
+		opacity: 1
+	}
+
+	.uni-calendar--fixed {
+		position: fixed;
+		/* #ifdef APP-NVUE */
+		bottom: 0;
+		/* #endif */
+		left: 0;
+		right: 0;
+		transition-property: transform;
+		transition-duration: 0.3s;
+		transform: translateY(460px);
+		/* #ifndef APP-NVUE */
+		bottom: calc(var(--window-bottom));
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-calendar--ani-show {
+		transform: translateY(0);
+	}
+
+	.uni-calendar__content {
+		background-color: #fff;
+	}
+
+	.uni-calendar__header {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 50px;
+		border-bottom-color: $uni-border-color;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+	}
+
+	.uni-calendar--fixed-top {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-calendar--fixed-width {
+		width: 50px;
+	}
+
+	.uni-calendar__backtoday {
+		position: absolute;
+		right: 0;
+		top: 25rpx;
+		padding: 0 5px;
+		padding-left: 10px;
+		height: 25px;
+		line-height: 25px;
+		font-size: 12px;
+		border-top-left-radius: 25px;
+		border-bottom-left-radius: 25px;
+		color: $uni-text-color;
+		background-color: $uni-bg-color-hover;
+	}
+
+	.uni-calendar__header-text {
+		text-align: center;
+		width: 100px;
+		font-size: $uni-font-size-base;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar__header-btn-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: 50px;
+		height: 50px;
+	}
+
+	.uni-calendar__header-btn {
+		width: 10px;
+		height: 10px;
+		border-left-color: $uni-text-color-placeholder;
+		border-left-style: solid;
+		border-left-width: 2px;
+		border-top-color: $uni-color-subtitle;
+		border-top-style: solid;
+		border-top-width: 2px;
+	}
+
+	.uni-calendar--left {
+		transform: rotate(-45deg);
+	}
+
+	.uni-calendar--right {
+		transform: rotate(135deg);
+	}
+
+
+	.uni-calendar__weeks {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-calendar__weeks-item {
+		flex: 1;
+	}
+
+	.uni-calendar__weeks-day {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		height: 45px;
+		border-bottom-color: #F5F5F5;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+	}
+
+	.uni-calendar__weeks-day-text {
+		font-size: 14px;
+	}
+
+	.uni-calendar__box {
+		position: relative;
+	}
+
+	.uni-calendar__box-bg {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+	}
+
+	.uni-calendar__box-bg-text {
+		font-size: 200px;
+		font-weight: bold;
+		color: $uni-text-color-grey;
+		opacity: 0.1;
+		text-align: center;
+		/* #ifndef APP-NVUE */
+		line-height: 1;
+		/* #endif */
+	}
+</style>

+ 360 - 0
uni_modules/uni-calendar/components/uni-calendar/util.js

@@ -0,0 +1,360 @@
+import CALENDAR from './calendar.js'
+
+class Calendar {
+	constructor({
+		date,
+		selected,
+		startDate,
+		endDate,
+		range
+	} = {}) {
+		// 当前日期
+		this.date = this.getDate(new Date()) // 当前初入日期
+		// 打点信息
+		this.selected = selected || [];
+		// 范围开始
+		this.startDate = startDate
+		// 范围结束
+		this.endDate = endDate
+		this.range = range
+		// 多选状态
+		this.cleanMultipleStatus()
+		// 每周日期
+		this.weeks = {}
+		// this._getWeek(this.date.fullDate)
+	}
+	/**
+	 * 设置日期
+	 * @param {Object} date
+	 */
+	setDate(date) {
+		this.selectDate = this.getDate(date)
+		this._getWeek(this.selectDate.fullDate)
+	}
+
+	/**
+	 * 清理多选状态
+	 */
+	cleanMultipleStatus() {
+		this.multipleStatus = {
+			before: '',
+			after: '',
+			data: []
+		}
+	}
+
+	/**
+	 * 重置开始日期
+	 */
+	resetSatrtDate(startDate) {
+		// 范围开始
+		this.startDate = startDate
+
+	}
+
+	/**
+	 * 重置结束日期
+	 */
+	resetEndDate(endDate) {
+		// 范围结束
+		this.endDate = endDate
+	}
+
+	/**
+	 * 获取任意时间
+	 */
+	getDate(date, AddDayCount = 0, str = 'day') {
+		if (!date) {
+			date = new Date()
+		}
+		if (typeof date !== 'object') {
+			date = date.replace(/-/g, '/')
+		}
+		const dd = new Date(date)
+		switch (str) {
+			case 'day':
+				dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
+				break
+			case 'month':
+				if (dd.getDate() === 31 && AddDayCount>0) {
+					dd.setDate(dd.getDate() + AddDayCount)
+				} else {
+					const preMonth = dd.getMonth()
+					dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
+					const nextMonth = dd.getMonth()
+					// 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
+					if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){
+						dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount))
+					}
+					// 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
+					if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){
+						dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount))
+					}
+				}
+				break
+			case 'year':
+				dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
+				break
+		}
+		const y = dd.getFullYear()
+		const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
+		const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
+		return {
+			fullDate: y + '-' + m + '-' + d,
+			year: y,
+			month: m,
+			date: d,
+			day: dd.getDay()
+		}
+	}
+
+
+	/**
+	 * 获取上月剩余天数
+	 */
+	_getLastMonthDays(firstDay, full) {
+		let dateArr = []
+		for (let i = firstDay; i > 0; i--) {
+			const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
+			dateArr.push({
+				date: beforeDate,
+				month: full.month - 1,
+				lunar: this.getlunar(full.year, full.month - 1, beforeDate),
+				disable: true
+			})
+		}
+		return dateArr
+	}
+	/**
+	 * 获取本月天数
+	 */
+	_currentMonthDys(dateData, full) {
+		let dateArr = []
+		let fullDate = this.date.fullDate
+		for (let i = 1; i <= dateData; i++) {
+			let nowDate = full.year + '-' + (full.month < 10 ?
+				full.month : full.month) + '-' + (i < 10 ?
+				'0' + i : i)
+			// 是否今天
+			let isDay = fullDate === nowDate
+			// 获取打点信息
+			let info = this.selected && this.selected.find((item) => {
+				if (this.dateEqual(nowDate, item.date)) {
+					return item
+				}
+			})
+
+			// 日期禁用
+			let disableBefore = true
+			let disableAfter = true
+			if (this.startDate) {
+				// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
+				// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
+				disableBefore = this.dateCompare(this.startDate, nowDate)
+			}
+
+			if (this.endDate) {
+				// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
+				// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
+				disableAfter = this.dateCompare(nowDate, this.endDate)
+			}
+			let multiples = this.multipleStatus.data
+			let checked = false
+			let multiplesStatus = -1
+			if (this.range) {
+				if (multiples) {
+					multiplesStatus = multiples.findIndex((item) => {
+						return this.dateEqual(item, nowDate)
+					})
+				}
+				if (multiplesStatus !== -1) {
+					checked = true
+				}
+			}
+			let data = {
+				fullDate: nowDate,
+				year: full.year,
+				date: i,
+				multiple: this.range ? checked : false,
+				beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
+				afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
+				month: full.month,
+				lunar: this.getlunar(full.year, full.month, i),
+				disable: !(disableBefore && disableAfter),
+				isDay
+			}
+			if (info) {
+				data.extraInfo = info
+			}
+
+			dateArr.push(data)
+		}
+		return dateArr
+	}
+	/**
+	 * 获取下月天数
+	 */
+	_getNextMonthDays(surplus, full) {
+		let dateArr = []
+		for (let i = 1; i < surplus + 1; i++) {
+			dateArr.push({
+				date: i,
+				month: Number(full.month) + 1,
+				lunar: this.getlunar(full.year, Number(full.month) + 1, i),
+				disable: true
+			})
+		}
+		return dateArr
+	}
+
+	/**
+	 * 获取当前日期详情
+	 * @param {Object} date
+	 */
+	getInfo(date) {
+		if (!date) {
+			date = new Date()
+		}
+		const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
+		return dateInfo
+	}
+
+	/**
+	 * 比较时间大小
+	 */
+	dateCompare(startDate, endDate) {
+		// 计算截止时间
+		startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+		// 计算详细项的截止时间
+		endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+		if (startDate <= endDate) {
+			return true
+		} else {
+			return false
+		}
+	}
+
+	/**
+	 * 比较时间是否相等
+	 */
+	dateEqual(before, after) {
+		// 计算截止时间
+		before = new Date(before.replace('-', '/').replace('-', '/'))
+		// 计算详细项的截止时间
+		after = new Date(after.replace('-', '/').replace('-', '/'))
+		if (before.getTime() - after.getTime() === 0) {
+			return true
+		} else {
+			return false
+		}
+	}
+
+
+	/**
+	 * 获取日期范围内所有日期
+	 * @param {Object} begin
+	 * @param {Object} end
+	 */
+	geDateAll(begin, end) {
+		var arr = []
+		var ab = begin.split('-')
+		var ae = end.split('-')
+		var db = new Date()
+		db.setFullYear(ab[0], ab[1] - 1, ab[2])
+		var de = new Date()
+		de.setFullYear(ae[0], ae[1] - 1, ae[2])
+		var unixDb = db.getTime() - 24 * 60 * 60 * 1000
+		var unixDe = de.getTime() - 24 * 60 * 60 * 1000
+		for (var k = unixDb; k <= unixDe;) {
+			k = k + 24 * 60 * 60 * 1000
+			arr.push(this.getDate(new Date(parseInt(k))).fullDate)
+		}
+		return arr
+	}
+	/**
+	 * 计算阴历日期显示
+	 */
+	getlunar(year, month, date) {
+		return CALENDAR.solar2lunar(year, month, date)
+	}
+	/**
+	 * 设置打点
+	 */
+	setSelectInfo(data, value) {
+		this.selected = value
+		this._getWeek(data)
+	}
+
+	/**
+	 *  获取多选状态
+	 */
+	setMultiple(fullDate) {
+		let {
+			before,
+			after
+		} = this.multipleStatus
+
+		if (!this.range) return
+		if (before && after) {
+			this.multipleStatus.before = ''
+			this.multipleStatus.after = ''
+			this.multipleStatus.data = []
+		} else {
+			if (!before) {
+				this.multipleStatus.before = fullDate
+			} else {
+				this.multipleStatus.after = fullDate
+				if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+					this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
+				} else {
+					this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
+				}
+			}
+		}
+		this._getWeek(fullDate)
+	}
+
+	/**
+	 * 获取每周数据
+	 * @param {Object} dateData
+	 */
+	_getWeek(dateData) {
+		const {
+			year,
+			month
+		} = this.getDate(dateData)
+		let firstDay = new Date(year, month - 1, 1).getDay()
+		let currentDay = new Date(year, month, 0).getDate()
+		let dates = {
+			lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
+			currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
+			nextMonthDays: [], // 下个月开始几天
+			weeks: []
+		}
+		let canlender = []
+		const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
+		dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
+		canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
+		let weeks = {}
+		// 拼接数组  上个月开始几天 + 本月天数+ 下个月开始几天
+		for (let i = 0; i < canlender.length; i++) {
+			if (i % 7 === 0) {
+				weeks[parseInt(i / 7)] = new Array(7)
+			}
+			weeks[parseInt(i / 7)][i % 7] = canlender[i]
+		}
+		this.canlender = canlender
+		this.weeks = weeks
+	}
+
+	//静态方法
+	// static init(date) {
+	// 	if (!this.instance) {
+	// 		this.instance = new Calendar(date);
+	// 	}
+	// 	return this.instance;
+	// }
+}
+
+
+export default Calendar

+ 85 - 0
uni_modules/uni-calendar/package.json

@@ -0,0 +1,85 @@
+{
+  "id": "uni-calendar",
+  "displayName": "uni-calendar 日历",
+  "version": "1.4.10",
+  "description": "日历组件",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "日历",
+    "",
+    "打卡",
+    "日历选择"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 103 - 0
uni_modules/uni-calendar/readme.md

@@ -0,0 +1,103 @@
+
+
+## Calendar 日历
+> **组件名:uni-calendar**
+> 代码块: `uCalendar`
+
+
+日历组件
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js)  
+> - 仅支持自定义组件模式
+> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date()
+> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意
+> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+<view>
+	<uni-calendar 
+	:insert="true"
+	:lunar="true" 
+	:start-date="'2019-3-2'"
+	:end-date="'2019-5-20'"
+	@change="change"
+	 />
+</view>
+```
+
+### 通过方法打开日历
+
+需要设置 `insert` 为 `false`
+
+```html
+<view>
+	<uni-calendar 
+	ref="calendar"
+	:insert="false"
+	@confirm="confirm"
+	 />
+	 <button @click="open">打开日历</button>
+</view>
+```
+
+```javascript
+
+export default {
+	data() {
+		return {};
+	},
+	methods: {
+		open(){
+			this.$refs.calendar.open();
+		},
+		confirm(e) {
+			console.log(e);
+		}
+	}
+};
+
+```
+
+
+## API
+
+### Calendar Props
+
+|  属性名	|    类型	| 默认值| 说明																													|
+| -	| -	| - | - |
+| date		| String	|-		| 自定义当前时间,默认为今天																							|
+| lunar		| Boolean	| false	| 显示农历																												|
+| startDate	| String	|-		| 日期选择范围-开始日期																									|
+| endDate	| String	|-		| 日期选择范围-结束日期																									|
+| range		| Boolean	| false	| 范围选择																												|
+| insert	| Boolean	| false	| 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式														|
+|clearDate	|Boolean	|true	|弹窗模式是否清空上次选择内容	|
+| selected	| Array		|-		| 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]	|
+|showMonth	| Boolean	| true	| 是否显示月份为背景																									|
+
+### Calendar Events
+
+|  事件名		| 说明								|返回值|
+| -	|	-	| -	|
+| open	| 弹出日历组件,`insert :false` 时生效|- 	|
+
+
+
+
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)

+ 0 - 0
uni_modules/uni-card/changelog.md


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels