Browse Source

修复h5因格式化造成的项目问题

qzyReal 3 years ago
parent
commit
147778cab5
100 changed files with 14925 additions and 0 deletions
  1. 9 0
      app-ui/.gitignore
  2. 42 0
      app-ui/App.vue
  3. 36 0
      app-ui/README.en.md
  4. 39 0
      app-ui/README.md
  5. 233 0
      app-ui/apis/api.js
  6. 91 0
      app-ui/common/common.scss
  7. 142 0
      app-ui/common/js/common.js
  8. 0 0
      app-ui/common/js/jweixin-1.6.0.js
  9. 0 0
      app-ui/components/jweixin-module/index.js
  10. 39 0
      app-ui/components/noData/noData.vue
  11. 274 0
      app-ui/components/slider-verify/slider-verify.vue
  12. 17 0
      app-ui/components/statusBar/statusBar.vue
  13. 14 0
      app-ui/index.html
  14. 27 0
      app-ui/main.js
  15. 93 0
      app-ui/manifest.json
  16. 11 0
      app-ui/package-lock.json
  17. 321 0
      app-ui/pages.json
  18. 68 0
      app-ui/pages/account/account-redirect.vue
  19. 174 0
      app-ui/pages/business-entering/business-detail.vue
  20. 771 0
      app-ui/pages/business-entering/business-edit.vue
  21. 772 0
      app-ui/pages/business-entering/business-entering.vue
  22. 222 0
      app-ui/pages/business-entering/declare-select.vue
  23. 247 0
      app-ui/pages/business-entering/item-select.vue
  24. 273 0
      app-ui/pages/business-item/item-detail.vue
  25. 317 0
      app-ui/pages/business-order/business-item.vue
  26. 351 0
      app-ui/pages/business-order/business-order.vue
  27. 164 0
      app-ui/pages/business-order/createOrder.vue
  28. 227 0
      app-ui/pages/business-order/partner-business-item.vue
  29. 211 0
      app-ui/pages/business-order/report.vue
  30. 86 0
      app-ui/pages/business-order/sureIn.vue
  31. 99 0
      app-ui/pages/business-order/sureOrder.vue
  32. 93 0
      app-ui/pages/business-order/sureOut.vue
  33. 151 0
      app-ui/pages/business-order/surePay.vue
  34. 85 0
      app-ui/pages/choose-business/choose-business.vue
  35. 165 0
      app-ui/pages/customer-management/customer-info.vue
  36. 78 0
      app-ui/pages/customer-management/customer-judge.vue
  37. 33 0
      app-ui/pages/customer-management/customer-list.vue
  38. 318 0
      app-ui/pages/customer-management/customer-management.vue
  39. 617 0
      app-ui/pages/declare/add.vue
  40. 63 0
      app-ui/pages/declare/addDeclareSuccess.vue
  41. 499 0
      app-ui/pages/disinfect/addDisinfect.vue
  42. 68 0
      app-ui/pages/disinfect/addDisinfectSuccess.vue
  43. 169 0
      app-ui/pages/enterprise-reg/enterprise-reg.vue
  44. 68 0
      app-ui/pages/home/home.vue
  45. 495 0
      app-ui/pages/index/index.vue
  46. 303 0
      app-ui/pages/inout-record/inout-record.vue
  47. 124 0
      app-ui/pages/login/login.vue
  48. 62 0
      app-ui/pages/ok/registerSuccess.vue
  49. 347 0
      app-ui/pages/onely-disinfect/Index.vue
  50. 89 0
      app-ui/pages/onely-disinfect/add-remark.vue
  51. 61 0
      app-ui/pages/onely-disinfect/addSuccess.vue
  52. 151 0
      app-ui/pages/onely-disinfect/car-manager.vue
  53. 84 0
      app-ui/pages/onely-disinfect/disinfect-Index.vue
  54. 626 0
      app-ui/pages/onely-disinfect/type-business-edit.vue
  55. 171 0
      app-ui/pages/onely-disinfect/type-business-info.vue
  56. 590 0
      app-ui/pages/onely-disinfect/type-business.vue
  57. 314 0
      app-ui/pages/partner/index.vue
  58. 198 0
      app-ui/pages/user/addUser.vue
  59. 57 0
      app-ui/pages/user/addUserSuccess.vue
  60. 66 0
      app-ui/pages/user/user-index.vue
  61. 317 0
      app-ui/pages/wx/account-pay.vue
  62. 70 0
      app-ui/pages/wx/index.vue
  63. 449 0
      app-ui/pages/wx/pay.vue
  64. 215 0
      app-ui/pages/wx/payOrder.vue
  65. 68 0
      app-ui/pages/wx/payOrderTemp.vue
  66. 32 0
      app-ui/pages/wx/remote-js.vue
  67. BIN
      app-ui/static/home-icon-01.png
  68. BIN
      app-ui/static/home-icon-02.png
  69. BIN
      app-ui/static/home-icon-03.png
  70. BIN
      app-ui/static/home-icon-04.png
  71. BIN
      app-ui/static/home-icon-05.png
  72. BIN
      app-ui/static/home-icon-06.jpg
  73. BIN
      app-ui/static/home-icon-07.jpg
  74. BIN
      app-ui/static/home-icon-charge.png
  75. BIN
      app-ui/static/login-bg.png
  76. BIN
      app-ui/static/logo.png
  77. BIN
      app-ui/static/noData.png
  78. BIN
      app-ui/static/qrcode.png
  79. BIN
      app-ui/static/slider-verify/1.jpg
  80. BIN
      app-ui/static/slider-verify/2.jpg
  81. BIN
      app-ui/static/slider-verify/3.jpg
  82. BIN
      app-ui/static/slider-verify/4.jpg
  83. BIN
      app-ui/static/slider-verify/5.jpg
  84. BIN
      app-ui/static/slider-verify/icon-button-normal.png
  85. BIN
      app-ui/static/user.png
  86. 79 0
      app-ui/uni.scss
  87. 29 0
      app-ui/uni_modules/uni-badge/changelog.md
  88. 268 0
      app-ui/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
  89. 88 0
      app-ui/uni_modules/uni-badge/package.json
  90. 10 0
      app-ui/uni_modules/uni-badge/readme.md
  91. 10 0
      app-ui/uni_modules/uni-calendar/changelog.md
  92. 546 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/calendar.js
  93. 12 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
  94. 8 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
  95. 12 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
  96. 12 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
  97. 188 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
  98. 555 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
  99. 354 0
      app-ui/uni_modules/uni-calendar/components/uni-calendar/util.js
  100. 88 0
      app-ui/uni_modules/uni-calendar/package.json

+ 9 - 0
app-ui/.gitignore

@@ -0,0 +1,9 @@
+node_modules/
+dist/**
+.project
+unpackage/
+.DS_Store
+wxcomponents/**/*.vue
+wxcomponents/**/*.css
+.hbuilderx/
+.idea

+ 42 - 0
app-ui/App.vue

@@ -0,0 +1,42 @@
+<script>
+	export default {
+		onLaunch: function() {
+		},
+		onShow: function() {
+			//this.getAuth();
+		},
+		onHide: function() {
+		},
+		methods:{
+			
+		}
+	}
+</script>
+
+<style lang="scss">
+	/*每个页面公共css */
+	
+	/* uView基础样式 */
+	@import "uview-ui/index.scss";
+	
+	
+	//全局页面背景色
+	page{
+		background-color: #f7f7f7;
+	}
+	
+	// 点击时背景灰色
+	.hover-class{
+		background-color: #f7f7f7!important;
+	}
+	//底部安全距离
+	.bottom-safety{
+		padding-bottom: constant(safe-area-inset-bottom);
+		padding-bottom: env(safe-area-inset-bottom);
+	}
+	
+	//全局白色背景
+	.bgc-f{
+		background-color: #ffffff;
+	}
+</style>

+ 36 - 0
app-ui/README.en.md

@@ -0,0 +1,36 @@
+# 场站管理系统-消杀-H5
+
+#### Description
+{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
+
+#### Software Architecture
+Software architecture description
+
+#### Installation
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Instructions
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Contribution
+
+1.  Fork the repository
+2.  Create Feat_xxx branch
+3.  Commit your code
+4.  Create Pull Request
+
+
+#### Gitee Feature
+
+1.  You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
+2.  Gitee blog [blog.gitee.com](https://blog.gitee.com)
+3.  Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
+4.  The most valuable open source project [GVP](https://gitee.com/gvp)
+5.  The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
+6.  The most popular members  [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 39 - 0
app-ui/README.md

@@ -0,0 +1,39 @@
+# 场站管理系统-消杀-H5
+
+#### 介绍
+{**以下是 Gitee 平台说明,您可以替换此简介**
+Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
+无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
+
+#### 软件架构
+软件架构说明
+
+
+#### 安装教程
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### 使用说明
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### 参与贡献
+
+1.  Fork 本仓库
+2.  新建 Feat_xxx 分支
+3.  提交代码
+4.  新建 Pull Request
+
+
+#### 特技
+
+1.  使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
+2.  Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
+3.  你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
+4.  [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
+5.  Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
+6.  Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 233 - 0
app-ui/apis/api.js

@@ -0,0 +1,233 @@
+import ajax from '../utils/request.js'
+
+
+export default {
+    doLogin(data) {
+        return ajax.postForm('/api/doLogin', data)
+    },
+    doLoginByOpenid(data) {
+        return ajax.postForm('/api/doLoginByOpenid', data)
+    },
+    register(data) {
+        return ajax.postForm('/api/register', data)
+    },
+    getItemList(data) {
+        return ajax.get('/TbItemType/getList', data)
+    },
+    getCustomerList(data) {
+    	return ajax.get('/TbCostomer/getList', data)
+    },
+    getCurrentAuthCode() {
+        return ajax.get('/admin/getCurrentAuthCode')
+    },
+    getCarList() {
+        return ajax.get('/TbCar/getList', {
+            pageNo: 1,
+            pageSize: 500
+        })
+    },
+    getDriverList() {
+        return ajax.get('/TbDriver/getList', {
+            pageNo: 1,
+            pageSize: 500
+        })
+    },
+    getGoodsList() {
+        return ajax.get('/TbGoods/getList', {
+            pageNo: 1,
+            pageSize: 50
+        })
+    },
+    getGoodsById(data) {
+        return ajax.get('/TbGoods/getById', data)
+    },
+    saveBusiness(data) {
+        return ajax.postForm('/TbBusiness/add', data)
+    },
+    getBusinessList(data) {
+        return ajax.get('/TbBusiness/getList', data)
+    },
+    adminConfirmPay(data) {
+        return ajax.postForm('/TbBusiness/adminConfirmPay', data)
+    },
+    adminConfirmIn(data) {
+        return ajax.postForm('/TbBusiness/adminConfirmIn', data)
+    },
+    getInOutRecord(data) {
+        //return ajax.get('/api/getInOutRecord', data)
+        return ajax.get('/TbBusinessCar/getList', data)
+    },
+    getCustomerList(data) {
+        return ajax.get('/api/getCustomerList', data)
+    },
+    getCarType() {
+        return ajax.get('/TbItem/getItemType')
+    },
+    getTypeByGoodsId(data) {
+        return ajax.get('/TbItemType/getTypeByGoodsId', data)
+    },
+    addOtherBusiness(data) {
+        return ajax.postForm('/TbBusiness/addOtherBusiness', data)
+    },
+    editOtherBusiness(data) {
+        return ajax.postForm('/TbBusiness/editOtherBusiness', data)
+    },
+    confirmCustomer(data) {
+        return ajax.postForm('/api/confirmCustomer', data)
+    },
+    deleteHsPeople(data) {
+        return ajax.postForm('/TbBusinessPeople/deleteById', data)
+    },
+    getCurrentPerCode() {
+        return ajax.get('/SpRolePermission/getPcodeByCurrRid')
+    },
+    getBusinessById(data) {
+        return ajax.get('/TbBusiness/getById', data)
+    },
+    confirmBusiness(data) {
+        return ajax.postForm('/TbBusiness/confirm', data)
+    },
+    confirmPay(data) {
+        return ajax.postForm('/TbBusiness/pay', data)
+    },
+    adminSetIn(data) {
+        return ajax.postForm('/TbBusiness/adminSetIn', data)
+    },
+    calJwPartMoney(data) {
+        return ajax.postForm('/TbBusiness/calJwPartMoney', data)
+    },
+    calChinaPartMoney(data) {
+        return ajax.postForm('/TbBusiness/calChinaPartMoney', data)
+    },
+    completeOrder(data) {
+        return ajax.postForm('/TbBusiness/complete', data)
+    },
+    adminSetOut(data) {
+        return ajax.postForm('/TbBusiness/adminOut', data)
+    },
+    deleteBusiness(data) {
+        return ajax.postForm('/TbBusiness/delete', data)
+    },
+    getBusinessPeople(data) {
+        return ajax.get('/TbBusinessPeople/getList', data)
+    },
+    getCustomerById(data) {
+        return ajax.get('/TbCostomer/getById', data)
+    },
+    editCustomer(data) {
+        return ajax.postForm('/TbCostomer/update', data)
+    },
+    judgeCustomer(data) {
+        return ajax.postForm('/TbCostomer/judge', data)
+    },
+    getUnitList() {
+        return ajax.get('/TbUnit/getList')
+    },
+    // getPrePay(data) {
+    // 	return ajax.get('/wx/pre-pay', data)
+    // },
+    getPrePay(data) {
+        return ajax.get('/jh/init-pay', data)
+    },
+    checkPayResult(data) {
+        return ajax.get('/jh/check-pay-result', data)
+    },
+    getRedirectUrl(data) {
+        return ajax.get('/wx/getRedirectUrl', data)
+    },
+    getOpenidByCode(data) {
+        return ajax.get('/wx/getOpenidByCode', data)
+    },
+    searchPartCar(data) {
+        return ajax.get('/api/searchPartCar', data)
+    },
+    getBusinessMoney(data) {
+        return ajax.get('/api/getBusinessMoney', data)
+    },
+
+    getWxConfig(data) {
+        return ajax.get('/wx/getWxConfig', data)
+    },
+    getPartCarByChannel(data) {
+        return ajax.get('/api/getPartCarByChannel', data)
+    },
+    addDeclare(data) {
+        return ajax.postJson('/api/addDeclare', data)
+    },
+    addDisinfect(data) {
+        return ajax.postJson('/api/addDisinfect', data)
+    },
+    uploadReport(data) {
+        return ajax.postJson('/TbBusiness/uploadReport', data)
+    },
+    getDeclareList(data) {
+        return ajax.get('/TbDeclare/getNotBindList', data)
+    },
+    getAccountInfo() {
+        return ajax.get('/api/getAccountInfo')
+    },
+    getDiscountInfo() {
+        return ajax.get('/api/getDiscountInfo')
+    },
+    getBusinessItem(data) {
+        return ajax.get('/api/getBusinessItem', data)
+    },
+    pickBusinessItem(data) {
+        return ajax.postForm('/api/pickBusinessItem', data)
+    },
+    confirmBusinessItem(data) {
+        return ajax.postForm('/api/confirmBusinessItem', data)
+    },
+    getPartnerBusinessItem(data) {
+        return ajax.get('/api/getPartnerBusinessItem', data)
+    },
+    checkUserType() {
+        return ajax.get('/api/checkUserType')
+    },
+    getRoleList(data) {
+        return ajax.get('/role/getCustomerRoleList', data)
+    },
+    getUserList(data) {
+        return ajax.get('/admin/getCustomerAdminList', data)
+    },
+    addCustomerAdmin(data) {
+        return ajax.postForm('/admin/addCustomerAdmin', data)
+    },
+    editCustomerAdmin(data) {
+        return ajax.postForm('/admin/editCustomerAdmin', data)
+    },
+    adminConfirm(data) {
+        return ajax.postForm('/TbBusiness/confirm', data)
+    },
+    addCarDisinfect(data) {
+        return ajax.postJson('/api/addCarDisinfect', data)
+    },
+    editCarDisinfect(data) {
+        return ajax.postJson('/api/editCarDisinfect', data)
+    },
+    getCarDisinFect(data) {
+        return ajax.get('/TbBusiness/getList', data)
+    },
+    getItemType(data) {
+        return ajax.get('/TbItemType/getItemTypeById', data);
+    },
+    getOtherBusinessById(data) {
+        return ajax.get('/TbBusiness/getOtherBusinessById', data)
+    },
+    deleteOtherBusiness(data) {
+        return ajax.postForm('/TbBusiness/deleteOtherBusiness', data)
+    },
+    getOtherBusiness(data) {
+        return ajax.get('/TbBusiness/getOtherBusiness', data)
+    },
+    getItemTypeList(data) {
+        return ajax.get('/TbItemType/getList', data)
+    },
+    getItemTypeEnum() {
+        return ajax.get('/TbItem/getItemType')
+    },
+    searchCar(data) {
+        return ajax.get('/TbBusinessCar/searchInNotOutCar', data)
+    }
+
+}

+ 91 - 0
app-ui/common/common.scss

@@ -0,0 +1,91 @@
+.box{
+		width: 100%;
+		.top{
+			width: 100%;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			background-color: #0080ff;
+			padding: 50rpx 0;
+			padding-top: 0;
+			margin-top: -1rpx;
+			//border-radius: 0 0 30rpx 30rpx;
+			.title{
+				font-size: 50rpx;
+				font-weight: bold;
+				color: #fff;
+			}
+		}
+		.item{
+			display: flex;
+			align-items: center;
+			margin: 0 60rpx;
+			padding: 10rpx 0;
+			min-height: 80rpx;
+			border-bottom: 1rpx solid #f5f5f5;
+			.l{
+				flex: 4;
+				display: flex;
+				align-items: center;
+				color: #191919;
+				padding-right: 10rpx;
+			}
+			.r{
+				flex: 10;
+				display: flex;
+				align-items: center;
+				.btn{
+					color: #0080ff;
+					font-size: 28rpx;
+				}
+				.unit{
+					color: #191919;
+					font-size: 28rpx;
+					border: 1rpx solid #eee;
+					padding: 10rpx 15rpx;
+					border-radius: 5rpx;
+				}
+				.img{
+					margin: 30rpx 0;
+				}
+				.p-picker{
+					width: 100%;
+					display: flex;
+					position: relative;
+					background-color: #f7f7f7;
+					padding: 20rpx;
+					border-radius: 5rpx;
+					.p-text{
+						color: #191919;
+					}
+					.p-icon{
+						position: absolute;
+						right: 20rpx;
+						top: 50%;
+						transform: translateY(-50%);
+					}
+				}
+			}
+		}
+	}
+	.common-btn,.common-btn2{
+		margin: 100rpx auto;
+		width: 400rpx;
+		height: 88rpx;
+		font-weight: bold;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		border-radius: 10rpx;
+	}
+	.common-btn{
+		color: #fff;
+		font-size: 32rpx;
+		background-color: #0080ff;
+	}
+	.common-btn2{
+		color: #191919;
+		font-size: 28rpx;
+		background-color: #fff;
+		border: 1px solid #eee;
+	}

+ 142 - 0
app-ui/common/js/common.js

@@ -0,0 +1,142 @@
+import ajax from '@/utils/request.js'
+export default {
+
+    getuid() {
+        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+            var r = Math.random() * 16 | 0,
+                v = c == 'x' ? r : (r & 0x3 | 0x8);
+            return v.toString(16);
+        });
+    },
+
+    // 提示信息
+    toast(msg, icon = 'none', duration = 2000, mask) {
+        uni.showToast({
+            "icon": icon,
+            "title": msg,
+            "mask": mask || false,
+            "duration": duration
+        })
+    },
+    showLoading(msg) {
+        uni.showLoading({
+            'title': msg,
+            'mask': true
+        })
+    },
+    hidingLoading() {
+        uni.hideLoading();
+    },
+    // 提示信息 底部
+    toastBottom(msg, icon = 'none', duration = 2000, mask = false) {
+        uni.showToast({
+            "icon": icon,
+            "title": msg,
+            "mask": mask,
+            "duration": duration,
+            "position": 'bottom'
+        })
+    },
+    // 路由跳转
+    to(url) {
+        uni.navigateTo({
+            url: url,
+            animationType: 'slide-in-right',
+            animationDuration: 300
+        })
+    },
+    toBar(url) {
+        uni.switchTab({
+            url: url
+        })
+    },
+    // 返回上一页
+    back() {
+        uni.navigateBack({
+            delta: 1,
+            animationType: 'pop-out',
+            animationDuration: 200
+        })
+    },
+    // 验证邮箱
+    isEmail(email) {
+        let reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
+        if (!reg.test(email)) {
+            this.$common.toast('请输入正确邮箱格式')
+        }
+        return reg.test(email)
+    },
+    // 正则验证是否为手机号
+    isPhone(str) {
+        str = str + '';
+        if ((/^1[3456789]\d{9}$/.test(str))) {
+            return true;
+        }
+        return false;
+    },
+    isNum(str) {
+        str = str + '';
+        if ((/^[0-9]*$/.test(str)) || (/^[0-9]+(.[0-9]{1})?$/.test(str))) {
+            return true;
+        }
+        return false;
+    },
+    isCarNo(str) {
+        str = str + '';
+        let reg =
+            /^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/
+        if (reg.test(str)) {
+            return true;
+        }
+        return false;
+    },
+    removeNull(obj) {
+        var newObj = {};
+        if (obj != undefined && obj != null) {
+            for (var key in obj) {
+                if (obj[key] === undefined || obj[key] === null || obj[key] === '') {
+                    //
+                } else {
+                    newObj[key] = obj[key];
+                }
+            }
+        }
+        return newObj;
+    },
+    isAuth(code) {
+        let list = uni.getStorageSync('perList');
+        return list.indexOf(code) !== -1;
+    },
+    // 将时间戳转化为指定时间
+    // way:方式(1=年月日,2=年月日时分秒)默认1,  也可以指定格式:yyyy-MM-dd HH:mm:ss
+    forDate(inputTime, way) {
+        var date = new Date(inputTime);
+        var y = date.getFullYear();
+        var m = date.getMonth() + 1;
+        m = m < 10 ? ('0' + m) : m;
+        var d = date.getDate();
+        d = d < 10 ? ('0' + d) : d;
+        var h = date.getHours();
+        h = h < 10 ? ('0' + h) : h;
+        var minute = date.getMinutes();
+        var second = date.getSeconds();
+        minute = minute < 10 ? ('0' + minute) : minute;
+        second = second < 10 ? ('0' + second) : second;
+        var ms = date.getMilliseconds();
+
+        way = way || 1;
+        // way == 1  年月日
+        if (way === 1) {
+            return y + '-' + m + '-' + d;
+        }
+        // way == 1  年月日时分秒
+        if (way === 2) {
+            return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
+        }
+        // way == 具体格式   标准格式: yyyy-MM-dd HH:mm:ss
+        if (typeof way == 'string') {
+            return way.replace("yyyy", y).replace("MM", m).replace("dd", d).replace("HH", h).replace("mm", minute).replace("ss", second).replace("ms", ms);
+        }
+        return y + '-' + m + '-' + d;
+    }
+}

File diff suppressed because it is too large
+ 0 - 0
app-ui/common/js/jweixin-1.6.0.js


File diff suppressed because it is too large
+ 0 - 0
app-ui/components/jweixin-module/index.js


+ 39 - 0
app-ui/components/noData/noData.vue

@@ -0,0 +1,39 @@
+<template>
+	<view>
+		<view class="nodata">
+			<image class="n-img" src="../../static/noData.png"></image>
+			<text class="n-text">暂无数据</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name:"noData",
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style lang="scss">
+	.nodata{
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		width: 100%;
+		height: 750rpx;
+		.n-img{
+			width: 300rpx;
+			height: 300rpx;
+		}
+		.n-text{
+			font-size: 28rpx;
+			color: #666;
+			margin-top: 20rpx;
+		}
+	}
+</style>

+ 274 - 0
app-ui/components/slider-verify/slider-verify.vue

@@ -0,0 +1,274 @@
+<template>
+	<view class="slider-verify-box" v-if="isShow">
+		<view class="verifyBox">
+			<view class="slider-title">图形验证</view>
+			<view class="slide-content">
+				<view class="slide-tips">拖动下方滑块完成拼图</view>
+				<view class="slider-pintu">
+					<!-- <image id="pintuImg" :src="'../../images/slider-verify/' + img + '.jpg'" class="pintu"></image> -->
+					<!-- <image id="pintuImg" :src="imgSrc" class="pintu"></image> -->
+					<image id="pintuImg" src="../../static/slider-verify/3.jpg" class="pintu"></image>
+					<view class="pintukuai" :style="{ top: top + 'px', left: oldx + 'px' }">
+						<!-- <image :src="'../../images/slider-verify/' + img + '.jpg'" :style="{ top: '-' + top + 'px', left: '-' + left + 'px'}"></image> -->
+						<image src="../../static/slider-verify/3.jpg" :style="{ top: '-' + top + 'px', left: '-' + left + 'px'}"></image>
+					</view>
+					<view class="yinying" :style="{ top: top + 'px', left: left + 'px' }"></view>
+				</view>
+
+				<view class="slider-movearea" @touchend="endTouchMove">
+					<movable-area :animation="true"><movable-view :x="x" direction="horizontal" @change="startMove"></movable-view></movable-area>
+
+					<view class="huadao">拖动左边滑块完成上方拼图</view>
+				</view>
+			</view>
+			
+			<view class="slider-btn-group">
+				<view class="slider-btn" @tap="closeSlider">关闭</view>
+				<view class="slider-btn slide-btn-refresh" @tap="refreshVerify">刷新</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'slider-verify',
+	props: {
+		isShow: true
+	},
+	data() {
+		return {
+			x: 0, //初始距离
+			oldx: 0, //移动的距离
+			img: 1, //显示哪张图片
+			left: 0, //随机拼图的最终X轴距离
+			top: 0, //拼图的top距离
+			//imgSrc: '@/static/slider-verify/1.jpg'
+			//imgSrc: '../../static/slider-verify/1.jpg'
+		};
+	},
+	watch: {
+		// 每次打开重新刷新拼图
+		isShow(newValue, oldValue) {
+			if(newValue){
+				this.refreshVerify();	//刷新
+			}
+		}
+	},
+	mounted() {
+		var that = this;
+		that.refreshVerify();
+	},
+	methods: {
+		//刷新验证
+		refreshVerify() {
+			var gl = Math.random().toFixed(2);
+			this.left = uni.upx2px(560) * gl > uni.upx2px(280) ? uni.upx2px(280) : uni.upx2px(560) * gl + uni.upx2px(150); //生成随机X轴最终距离
+			this.top = uni.upx2px(190) * gl; //生成随机Y轴初始距离
+			
+			if (gl <= 0.2) {
+				this.img = 1;
+			}
+			if (gl > 0.2 && gl <= 0.4) {
+				this.img = 2;
+			}
+			if (gl > 0.4 && gl <= 0.6) {
+				this.img = 3;
+			}
+			if (gl > 0.6 && gl <= 0.8) {
+				this.img = 4;
+			}
+			if (gl > 0.8 && gl <= 1) {
+				this.img = 5;
+			}
+			
+			this.resetMove();	//重置阴影位置
+		},
+
+		/* 滑动中 */
+		startMove(e) {
+			this.oldx = e.detail.x;
+		},
+
+		/* 滑动结束 */
+		endTouchMove() {
+			var that = this;
+
+			if (Math.abs(that.oldx - that.left) <= 5) {
+				uni.showToast({
+					title: '验证成功',
+					duration: 2500,
+					success() {
+						that.$emit('touchSliderResult', true);
+					}
+				});
+			} else {
+				that.refreshVerify();
+			}
+		},
+		
+		/* 重置阴影位置 */
+		resetMove() {
+			this.x = 1;
+			this.oldx = 1;
+			setTimeout(() => {
+				this.x = 0;
+				this.oldx = 0;
+			}, 300);
+		},
+		
+		// 关闭
+		closeSlider(){
+			this.$emit('touchSliderResult', false);
+		}	
+	}
+};
+</script>
+
+<style lang="less">
+.slider-verify-box {
+	position: fixed;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	background-color: rgba(0, 0, 0, 0.5);
+	z-index: 999;
+}
+.verifyBox {
+	position: absolute;
+	top: 50%;
+	left: 50%;
+	transform: translate(-50%, -50%);
+	// width: 85%;
+	background-color: #fff;
+	border-radius: 20upx;
+	box-shadow: 0 0 5upx rgba(0, 0, 0);
+
+	.slider-title {
+		font-size: 36upx;
+		text-align: center;
+		padding: 1em 0;
+		color: rgba(2, 20, 33, 0.85);
+		border-bottom: 1px solid rgba(2, 20, 33, 0.15);
+	}
+
+	.slide-content {
+		width: 560rpx;
+		padding: 0 1em;
+		margin: 0 auto;
+		.slide-tips {
+			font-size: 28rpx;
+			color: rgba(2, 20, 33, 0.45);
+			padding: 0.5em 0;
+		}
+
+		.slider-pintu {
+			position: relative;
+			width: 100%;
+			border-radius: 10rpx;
+			overflow: hidden;
+			.pintu {
+				width: 560rpx;
+				height: 315rpx;
+				display: block;
+				margin: 0 auto;
+			}
+
+			.pintukuai {
+				position: absolute;
+				top: 0;
+				left: 0;
+				width: 120rpx;
+				height: 120rpx;
+				z-index: 100;
+				box-shadow: 0 0 5upx rgba(0, 0, 0, 0.3);
+				overflow: hidden;
+
+				image {
+					display: block;
+					position: absolute;
+					top: 0;
+					left: 0;
+					width: 560rpx;
+					height: 315rpx;
+				}
+			}
+		}
+
+		.yinying {
+			position: absolute;
+			width: 120rpx;
+			height: 120rpx;
+			background-color: rgba(0, 0, 0, 0.7);
+			//background-color: #ccc;
+		}
+	}
+}
+
+.slider-movearea {
+	position: relative;
+	height: 80upx;
+	width: 100%;
+	margin: 25upx auto;
+
+	movable-area {
+		height: 80upx;
+		width: 100%;
+
+		movable-view {
+			width: 80upx;
+			height: 80upx;
+			border-radius: 50%;
+			background-color: #007cff;
+			background-image: url(../../static/slider-verify/icon-button-normal.png);
+			background-repeat: no-repeat;
+			background-size: auto 30upx;
+			background-position: center;
+			position: relative;
+			z-index: 100;
+		}
+	}
+}
+
+.huadao {
+	width: 100%;
+	height: 66upx;
+	line-height: 66upx;
+	background: #eee;
+	box-shadow: inset 0 0 5upx #ccc;
+	border-radius: 40rpx;
+	color: #999;
+	text-align: center;
+	box-sizing: border-box;
+	position: absolute;
+	top: 7rpx;
+	left: 0;
+	font-size: 28rpx;
+	z-index: 99;
+}
+
+.slider-btn-group{
+	width: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	border-top: 1px solid rgba(2, 20, 33, 0.15);
+	
+	.slider-btn{
+		flex: 1;
+		height: 100rpx;
+		line-height: 100rpx;
+		text-align: center;
+		font-size: 36rpx;
+		color:rgba(2,20,33,0.85);
+		&:active{
+			opacity: 0.8;
+		}
+	}
+	.slide-btn-refresh{
+		color:rgba(14,107,176,1);
+		border-left: 1px solid rgba(2, 20, 33, 0.15);
+	}	
+}
+</style>

+ 17 - 0
app-ui/components/statusBar/statusBar.vue

@@ -0,0 +1,17 @@
+<template>
+	<view :style="{height: SBH}"></view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				// 获取手机状态栏的高度,状态栏就是手机上面时间信号电池等那一栏,安卓苹果各不相同,所以得通过js获取系统信息进行计算
+				SBH: uni.getSystemInfoSync().statusBarHeight + 'px'
+			}
+		}
+	}
+</script>
+
+<style>
+</style>

+ 14 - 0
app-ui/index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
+    <title></title>
+    <!--preload-links-->
+    <!--app-context-->
+  </head>
+  <body>
+    <div id="app"><!--app-html--></div>
+    <script type="module" src="/main.js"></script>
+  </body>
+</html>

+ 27 - 0
app-ui/main.js

@@ -0,0 +1,27 @@
+import App from './App'
+import api from '@/apis/api.js'
+import common from '@/common/js/common.js'
+import uView from "uview-ui";
+
+Vue.use(uView);
+// #ifndef VUE3
+import Vue from 'vue'
+Vue.config.productionTip = false
+App.mpType = 'app'
+Vue.prototype.$api = api
+Vue.prototype.$common = common
+const app = new Vue({
+    ...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+import { createSSRApp } from 'vue'
+export function createApp() {
+  const app = createSSRApp(App)
+  return {
+    app
+  }
+}
+// #endif

+ 93 - 0
app-ui/manifest.json

@@ -0,0 +1,93 @@
+{
+    "name" : "防疫管理系统",
+    "appid" : "__UNI__8AC923A",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "payment" : {
+                    "weixin" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appid" : "",
+                        "UniversalLinks" : ""
+                    }
+                }
+            }
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "wxfdde9c84718dc481",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true,
+        "permission" : {}
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "2",
+    "h5" : {
+        "router" : {
+            "base" : "/h5/",
+            "mode" : "history"
+        },
+        "devServer" : {
+            "https" : true
+        }
+    }
+}

+ 11 - 0
app-ui/package-lock.json

@@ -0,0 +1,11 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "uview-ui": {
+      "version": "2.0.19",
+      "resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-2.0.19.tgz",
+      "integrity": "sha512-ddZiaP7R9wsUxMzAuhuXgh5OswgCm2lKuulTqjnRXFr0uUWsgL1iBifU3GbOwpwP0LtTHKJOo9rYv1LP0WXmzA=="
+    }
+  }
+}

+ 321 - 0
app-ui/pages.json

@@ -0,0 +1,321 @@
+{
+  "easycom": {
+    "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
+  },
+  "pages": [
+    //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+    {
+      "path": "pages/index/index",
+      "style": {
+        "navigationBarTitleText": ""
+        //首页
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/enterprise-reg/enterprise-reg",
+      "style": {
+        "navigationBarTitleText": ""
+        //企业注册
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/home/home",
+      "style": {
+        "navigationBarTitleText": ""
+        //跳转页
+      }
+    },
+    {
+      "path": "pages/login/login",
+      "style": {
+        "navigationBarTitleText": ""
+        //登录
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/business-entering/business-entering",
+      "style": {
+        "navigationBarTitleText": ""
+        //业务录入
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/business-entering/business-edit",
+      "style": {
+        "navigationBarTitleText": ""
+        //业务录入
+      }
+    },
+    {
+      "path": "pages/business-entering/business-detail",
+      "style": {
+        "navigationBarTitleText": ""
+        //业务录入
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/customer-management/customer-list",
+      "style": {
+        "navigationBarTitleText": ""
+        //业务录入
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/business-order/business-order",
+      "style": {
+        "navigationBarTitleText": ""
+        //业务订单
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/customer-management/customer-management",
+      "style": {
+        "navigationBarTitleText": ""
+        //客户管理
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/inout-record/inout-record",
+      "style": {
+        "navigationBarTitleText": ""
+        //出入记录
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/choose-business/choose-business",
+      "style": {
+        "navigationBarTitleText": ""
+        //选择业务
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/ok/registerSuccess",
+      "style": {
+        "navigationBarTitleText": ""
+        //注册成功
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/business-order/sureOrder",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/business-order/report",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/business-order/surePay",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/business-order/sureOut",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/business-order/sureIn",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/business-order/createOrder",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/customer-management/customer-judge",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/wx/index",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/wx/pay",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/wx/payOrderTemp",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/wx/payOrder",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/declare/add",
+      "style": {
+        "navigationBarTitleText": ""
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/declare/addDeclareSuccess",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/disinfect/addDisinfect",
+      "style": {
+        "navigationBarTitleText": ""
+        //"navigationStyle":"custom"
+      }
+    },
+    {
+      "path": "pages/disinfect/addDisinfectSuccess",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/wx/account-pay",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/business-entering/declare-select",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/account/account-redirect",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/business-item/item-detail",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/business-order/business-item",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/partner/index",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/user/user-index",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/user/addUser",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/user/addUserSuccess",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/business-order/partner-business-item",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/disinfect-Index",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/addSuccess",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/Index",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/type-business",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/add-remark",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/type-business-info",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/type-business-edit",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/onely-disinfect/car-manager",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    }
+  ],
+  "globalStyle": {
+    "navigationBarTextStyle": "white",
+    "navigationBarTitleText": "uni-app",
+    "navigationBarBackgroundColor": "#0080ff",
+    "backgroundColor": "#F8F8F8"
+  }
+}

+ 68 - 0
app-ui/pages/account/account-redirect.vue

@@ -0,0 +1,68 @@
+<template>
+  <view class="box">
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: ''
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  created() {
+    this.$common.showLoading('正在加载...')
+  },
+  mounted() {
+    this.getRedirectUri();
+  },
+  beforeDestroy() {
+    this.$common.hidingLoading()
+  },
+  methods: {
+    getRedirectUri() {
+      this.$api.getRedirectUrl({path: '/pages/wx/account-pay', state: this.id}).then(resp => {
+        window.location.href = resp.data;
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    flex: 1;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+
+    text {
+      margin-left: 20rpx;
+    }
+  }
+}
+</style>

+ 174 - 0
app-ui/pages/business-entering/business-detail.vue

@@ -0,0 +1,174 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务详情</text>
+      </view>
+      <view class="item">
+        <view class="l">企业名称:</view>
+        <view class="r">
+          {{ form.customerName }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">货物:</view>
+        <view class="r">
+          {{ form.goodsName }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">货重:</view>
+        <view class="r">
+          {{ form.netWeight }}(kg)
+        </view>
+      </view>
+      <view class="item-line">
+        车辆
+      </view>
+      <view v-for="item in form.cars" :key="item.id" style="border-bottom: 1px solid #E5E5E5;">
+        <view class="item">
+          <view class="l">车牌号:</view>
+          <view class="r">
+            {{ item.carNo }}
+          </view>
+        </view>
+        <view class="item">
+          <view class="l">规格:</view>
+          <view class="r">
+            {{ item.carSize }} (米)
+          </view>
+        </view>
+        <view class="item" v-if="item.realInTime">
+          <view class="l">入场时间:</view>
+          <view class="r">
+            {{ item.realInTime }}
+          </view>
+        </view>
+        <view class="item" v-if="item.realOutTime">
+          <view class="l">离场时间:</view>
+          <view class="r">
+            {{ item.realOutTime }} (米)
+          </view>
+        </view>
+        <view class="item" v-if="item.driverName">
+          <view class="l">联系人:</view>
+          <view class="r">
+            {{ item.driverName }}
+          </view>
+        </view>
+        <view class="item" v-if="item.driverPhone">
+          <view class="l">联系号码:</view>
+          <view class="r">
+            {{ item.driverPhone }}
+          </view>
+        </view>
+      </view>
+
+      <view class="item-line">
+        业务项
+      </view>
+      <view class="item" v-for="item in form.items" :key="item.id">
+        <view class="l" style="flex: 7;">{{ item.itemTypeName }}:</view>
+        <view class="r">
+          {{ item.itemName }}({{ item.itemPrice }}x{{ item.num }}={{ item.total }}元)
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">业务费:</view>
+        <view class="r">
+          {{ form.itemPrice }}
+          <text>(元)</text>
+        </view>
+      </view>
+      <view class="item">
+        <text class="p1">订单状态:</text>
+        <text class="p2">
+          <text v-if="form.confirmInput==0">未确认</text>
+          <text v-else>已确认</text>
+        </text>
+      </view>
+      <view class="item">
+        <text class="p1">支付状态:</text>
+        <text class="p2">
+          <text v-if="form.payStatus==1">未支付</text>
+          <text v-if="form.payStatus==2">已支付(未确认)</text>
+          <text v-if="form.payStatus==3">已支付(已确认)</text>
+        </text>
+      </view>
+      <view class="hj">
+        总费用:{{ form.totalMoney }}元
+      </view>
+      <u-button type="primary" text="返回" @click="backFn"></u-button>
+      <view style="height: 80rpx;"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      form: {}
+    }
+  },
+  onShow() {
+  },
+
+  onLoad(options) {
+    this.id = options.id;
+  },
+  onShow() {
+    this.getBusinessById();
+  },
+  methods: {
+    backFn() {
+      this.$common.back();
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+      })
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 30rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 771 - 0
app-ui/pages/business-entering/business-edit.vue

@@ -0,0 +1,771 @@
+<template>
+  <view>
+    <view class="box" v-show="hs.visible">
+      <view class="top">
+        <text class="title">录入核酸人员</text>
+      </view>
+      <view style="display: flex;margin-top: 40rpx;">
+        <u-button type="primary" @click="hs.visible=false" text="返回" style="width: 20px;" size="mini"/>
+        <u-button type="primary" @click="showHsModal" text="添加" v-show="hs.num>hs.list.length" icon="plus"
+                  style="width: 20px;" size="mini"/>
+      </view>
+      <u-row style="margin-top: 70rpx;">
+        <u-col span="4" style="text-align: center;">姓名</u-col>
+        <u-col span="4" style="text-align: center;">联系号码</u-col>
+        <u-col span="4" style="text-align: center;">操作</u-col>
+      </u-row>
+      <u-row v-for="item in hs.list" style="margin-top: 40rpx;">
+        <u-col span="4" style="text-align: center;">{{ item.name }}</u-col>
+        <u-col span="4" style="text-align: center;">{{ item.phone }}</u-col>
+        <u-col span="4" style="text-align: center;">
+          <u-row>
+            <u-col span="6">
+              <u-button type="primary" text="编辑" style="width: 20px;" @click="editFn(item)" size="mini">
+              </u-button>
+            </u-col>
+            <u-col span="6">
+              <u-button type="error" style="width: 20px;" text="删除" @click="deleteFn(item)" size="mini">
+              </u-button>
+            </u-col>
+          </u-row>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="box" v-show="china.visible">
+      <view class="top">
+        <text class="title">中国车录入</text>
+      </view>
+      <view style="display: flex;margin-top: 40rpx;">
+        <u-button type="primary" @click="china.visible=false" text="返回" style="width: 20px;" size="mini"/>
+        <u-button type="primary" @click="showChinaModal" text="添加" icon="plus" style="width: 20px;"
+                  size="mini"/>
+      </view>
+      <u-row style="margin-top: 70rpx;">
+        <u-col span="3" style="text-align: center;">车牌号</u-col>
+        <u-col span="3" style="text-align: center;">联系人</u-col>
+        <u-col span="3" style="text-align: center;">联系号码</u-col>
+        <u-col span="3" style="text-align: center;">操作</u-col>
+      </u-row>
+      <u-row v-for="(item,index) in china.list" style="margin-top: 40rpx;">
+        <u-col span="3" style="text-align: center;">{{ item.carNo }}</u-col>
+        <u-col span="3" style="text-align: center;">{{ item.driverName }}</u-col>
+        <u-col span="3" style="text-align: center;">{{ item.driverPhone }}</u-col>
+        <u-col span="3" style="text-align: center;">
+          <u-row>
+            <u-col span="6">
+              <u-button type="primary" text="编辑" style="width: 20px;" @click="editChinaCar(item,index)"
+                        size="mini">
+              </u-button>
+            </u-col>
+            <u-col span="6">
+              <u-button type="error" style="width: 20px;" text="删除" @click="deleteChinaCar(item,index)"
+                        size="mini">
+              </u-button>
+            </u-col>
+          </u-row>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="box" v-show="!hs.visible&&!china.visible">
+      <view class="top">
+        <text class="title">业务录入</text>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报单号:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报订单号" v-model="form.declareNo" clearable readonly>
+            <text slot="suffix" style="font-size: 50rpx;" @click="selectDeclare">+</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">申报单位:</view>
+        <view class="r">
+          <u-input placeholder="申报单位" disabled v-model="form.customerName">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报单号:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报订单号" v-model="form.declareNo" clearable readonly>
+            <text slot="suffix" style="font-size: 50rpx;" @click="selectDeclare">+</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          货物:
+        </view>
+        <view class="r">
+          <picker v-if="goods.goodsList.length>0" class="p-picker" id="hw" @change="whChange($event)"
+                  :value="goods.index" :range="goods.goodsList" range-key="name">
+            <text class="p-text">{{ goods.goodsList[goods.index].name }}</text>
+            <u-icon class="p-icon" name="arrow-down-fill" size="20"></u-icon>
+          </picker>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          载重:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入载重" v-model="form.netWeight">
+            <text slot="suffix">kg</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          境外车牌:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入车牌号" v-model="form.cardNo"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          境外车规格:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入车辆规格" v-model="form.cardSize">
+            <text slot="suffix">米</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">中国车:</view>
+        <view class="r">
+          <u-input placeholder="中国车" v-model="china.list.map(obj=>obj.carNo).join('、')" readonly>
+            <text slot="suffix" style="font-size: 50rpx;" @click="addCar">+</text>
+          </u-input>
+        </view>
+      </view>
+
+      <view class="item-line">
+        业务项
+      </view>
+      <view class="item" v-for="item in filterItemList" :key="item.id" v-if="item.items.length>0">
+        <view class="l">
+          <text v-if="needTypeId.indexOf(item.id)!==-1" style="color: red;">*</text>
+          {{ item.name }}:
+        </view>
+        <view class="r">
+          <view @click="selectItemFn(item)" style="width: 150px;">
+            <u-input placeholder="请选择" v-model="item.itemName" readonly clearable>
+              <u-icon name="close" v-if="item.itemName" slot="suffix" color="#E5E5E5;" size="5"
+                      @click="cleanItemSelect(item)"></u-icon>
+            </u-input>
+          </view>
+          <view style="width: 20px;margin-left: 10rpx;">
+            <u-input placeholder="数量" :disabled="item.inc==0" border="surround" v-model="item.num"
+                     type="number" style="width: 15px;" v-if="item.itemName"></u-input>
+          </view>
+          <view style="margin-left:30rpx;color: red;" v-if="item.itemName">
+            {{ item.items.filter(obj => obj.itemName == item.itemName)[0].price * item.num }}元
+          </view>
+          <u-icon name="plus" style="position: absolute;right: 10rpx;"
+                  v-if="item.itemName&&item.name.indexOf('人')!==-1&&item.name.indexOf('核酸')!==-1"
+                  @click="addHsFn(item.num,true)"></u-icon>
+        </view>
+      </view>
+      <view class="hj" v-show="totalPrice>0">
+        合计:{{ totalPrice }}元
+      </view>
+    </view>
+    <u-button type="primary" text="确定" @click="saveFn"
+              v-if="(!hs.visible&&!china.visible)&&perList.indexOf('tb-business-edit')!==-1"></u-button>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+    <u-popup :show="car.carInput" :overlay="false" @close="car.carInput=false" borderRadius="10">
+      <view style="padding: 40rpx;line-height: 60rpx;text-align: center;">
+        <view v-for="item in filterUnitList" :id="item.id"
+              style="margin-bottom: 20rpx;border-bottom: 1rpx solid #E5E5E5;" @click="selectCarSize(item)">
+          {{ item.unit }}
+        </view>
+      </view>
+    </u-popup>
+    <u-popup :show="driver.show" :overlay="false" @close="driver.show=false" borderRadius="10">
+      <view style="padding: 40rpx;line-height: 60rpx;text-align: center;">
+        <view v-for="item in driver.filterList" :id="item.id"
+              style="margin-bottom: 20rpx;border-bottom: 1rpx solid #E5E5E5;" @click="selectDriverFn(item)">
+          {{ item.name }}({{ item.idCard }})
+        </view>
+      </view>
+    </u-popup>
+    <u-popup :show="show" closeable closeOnClickOverlay @close="show=false">
+      <view style="padding: 40rpx;">
+        <u-radio-group @change="itemSelectFn" placement="column" v-model="item.itemName">
+          <u-radio v-for="item in item.items" :key="item.id" :label="item.itemName" :name="item.itemName"
+                   v-if="form.netWeight >= item.minWeight
+					&& form.netWeight < item.maxWeight
+					&&form.cardSize<=item.carLength
+					&&form.cardSize>=item.minLength" style="margin-top: 30rpx;">
+          </u-radio>
+        </u-radio-group>
+      </view>
+    </u-popup>
+    <u-modal :show="modal.visible" showCancelButton closeOnClickOverlay @cancel="modal.visible=false"
+             @confirm="addHsPeopleFn">
+      <view style="">
+        <u--input placeholder="姓名" border="surround" v-model="modal.form.name"></u--input>
+        <u--input style="margin-top: 20rpx;" placeholder="联系号码" border="surround" v-model="modal.form.phone">
+        </u--input>
+      </view>
+    </u-modal>
+    <u-modal :show="chinaAddModal.visible" title="中国车" @confirm="sureCarFn" @cancel="chinaAddModal.visible=false"
+             showCancelButton cancelText="关闭">
+      <view class="slot-content">
+        <u-row>
+          <u-col span="4">车牌号</u-col>
+          <u-col span="8">
+            <u--input placeholder="车牌号" v-model="chinaAddModal.form.carNo"></u--input>
+          </u-col>
+        </u-row>
+        <u-row>
+          <u-col span="4">联系人</u-col>
+          <u-col span="8">
+            <u--input placeholder="联系人" v-model="chinaAddModal.form.driverName"></u--input>
+          </u-col>
+        </u-row>
+        <u-row>
+          <u-col span="4">联系号码</u-col>
+          <u-col span="8">
+            <u--input placeholder="联系号码" v-model="chinaAddModal.form.driverPhone"></u--input>
+          </u-col>
+        </u-row>
+      </view>
+    </u-modal>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      car: {
+        carInput: false,
+        filterList: [],
+      },
+      driver: {
+        show: false,
+        filterList: [],
+      },
+      customerId: '1',
+      exprctStart: new Date().getTime(),
+      itemList: [],
+      filterItemList: [],
+      needTypeId: [],
+      form: {
+        customerId: '',
+        customerIndex: 0,
+        countryIndex: 0,
+        goodsIndex: 0,
+        cardNo: '',
+        cardSize: '',
+        goodsName: '',
+        netWeight: '',
+        chinaCarNo: '',
+        driverName: '',
+        driverPhone: '',
+        expectInDay: ''
+      },
+      show: false,
+      item: {
+        items: []
+      },
+      customer: {
+        index: 0,
+        customerList: [],
+      },
+      carList: [],
+      driverList: [],
+      unitList: [],
+      filterUnitList: [],
+      country: {
+        index: 0,
+        list: ['越南车', '中国车']
+      },
+      goods: {
+        index: 0,
+        goodsList: []
+      },
+      hs: {
+        visible: false,
+        num: 1,
+        list: []
+      },
+      modal: {
+        visible: false,
+        form: {
+          name: '',
+          phone: ''
+        }
+      },
+      china: {
+        visible: false,
+        index: -1,
+        list: []
+      },
+      chinaAddModal: {
+        visible: false,
+        form: {
+          carNo: '',
+          driverName: '',
+          driverPhone: ''
+        }
+      },
+      checkItem: '',
+      chinaCarPrefix: "浙粤京津冀晋蒙辽黑沪吉苏皖赣鲁豫鄂湘桂琼渝川贵云藏陕甘青宁",
+      perList: []
+    }
+  },
+  onShow() {
+    this.customerId = uni.getStorageSync('customerId');
+    this.perList = uni.getStorageSync('perList')
+  },
+  onLoad(options) {
+    this.form.id = options.id;
+    this.getBusinessPeople();
+    this.getGoodsList();
+    this.getUnit();
+    let that = this;
+    uni.$on('getSelectDeclare', declare => {
+      that.$nextTick(() => {
+        that.form.declareNo = declare.declareNo;
+        that.form.cardNo = declare.carNo;
+        that.form.chinaCarNo = declare.chinaCarNo;
+        that.form.netWeight = declare.grossWeight;
+        that.form.customerId = declare.customerId;
+        that.form.customerName = declare.customerName;
+        let chinaCarNo = declare.chinaCarNo;
+        if (chinaCarNo) {
+          let list = [];
+          chinaCarNo.replace(",", ",").split(",").forEach(carNo => {
+            let obj = {
+              carNo: carNo
+            }
+            list.push(obj);
+            that.china.list = list;
+          })
+        } else {
+          that.china.list = [];
+        }
+      })
+    })
+  },
+  computed: {
+    totalPrice() {
+      let itemList = this.itemList.filter(obj => obj.itemName);
+      let price = 0;
+      for (let i in itemList) {
+        let type = itemList[i];
+        let items = type.items;
+        for (let j in items) {
+          let item = items[j];
+          if (item.itemName == type.itemName) {
+            price += item.price;
+            break;
+          }
+        }
+      }
+      return price;
+    }
+  },
+  created() {
+
+  },
+  methods: {
+    selectDeclare() {
+      this.$common.to('/pages/business-entering/declare-select?declareNo=' + this.form.declareNo + '&businessId=' + this.form.id)
+    },
+    addCar() {
+      this.china.visible = true;
+    },
+    showChinaModal() {
+      Object.assign(this.chinaAddModal, {
+        visible: true,
+        index: -1,
+        form: {
+          carNo: '',
+          driverName: '',
+          driverPhone: ''
+        }
+      })
+    },
+    sureCarFn() {
+      let form = this.chinaAddModal.form;
+      let carNo = form.carNo;
+      let phone = form.driverPhone;
+      if (carNo && !this.$common.isCarNo(carNo)) {
+        this.$common.toast('请输入正确的车牌号')
+        return;
+      }
+      if (phone && !this.$common.isPhone(phone)) {
+        this.$common.toast('请输入正确的手机号')
+        return;
+      }
+      let list = this.china.list;
+      let index = this.chinaAddModal.index;
+      if (index > -1) {
+        list.splice(index, 1)
+      }
+      list.push(form)
+      this.chinaAddModal.visible = false;
+    },
+    deleteChinaCar(item, index) {
+      this.china.list.splice(index, 1);
+    },
+    editChinaCar(item, index) {
+      Object.assign(this.chinaAddModal, {
+        visible: true,
+        index: index,
+        form: item
+      })
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.form.id
+      }).then(resp => {
+        let data = resp.data;
+        this.form = data;
+        let list = this.chinaCarPrefix;
+        this.china.list = data.cars.filter(obj => {
+          return list.indexOf(obj.carNo.substr(0, 1)) !== -1
+        });
+        console.log(this.china.list)
+        let goodsName = data.goodsName;
+        this.customer.index = this.customer.customerList.map(obj => obj.name).indexOf(data
+            .customerName);
+        this.goods.index = this.goods.goodsList.map(o => o.name).indexOf(goodsName);
+        let goods = this.goods.goodsList[this.goods.index];
+        let items = data.items;
+        let noNeedIds = goods.noNeedIds.split(',');
+        let itemTypeList = this.itemList.filter(obj => noNeedIds.indexOf(obj.id) == -1);
+        this.filterItemList = itemTypeList;
+        for (let i in itemTypeList) {
+          let type = itemTypeList[i];
+          for (let j in items) {
+            let item = items[j];
+            if (item.itemTypeId == type.id) {
+              type.itemName = item.itemName;
+              let typeName = type.name;
+              type.num = item.num
+              break;
+            }
+          }
+        }
+        setTimeout(() => {
+          this.car.carInput = false;
+        }, 30)
+      })
+    },
+    getBusinessPeople() {
+      this.$api.getBusinessPeople({
+        businessId: this.form.id
+      }).then(resp => {
+        let list = resp.data;
+        let index = 0;
+        let r = [];
+        for (let i in list) {
+          r.push({
+            name: list[i].name,
+            phone: list[i].phone,
+            index: index,
+            id: list[i].id
+          })
+          index++;
+        }
+        this.hs.list = r;
+      })
+    },
+    whChange(event) {
+      let index = event.detail.value; //当前picker选中的值
+      this.goods.index = index;
+      let goods = this.goods.goodsList[index];
+      let noNeedIds = goods.noNeedIds.split(',');
+      this.needTypeId = goods.needIds.split(',')
+      this.filterItemList = this.itemList.filter(obj => noNeedIds.indexOf(obj.id) == -1);
+    },
+    carSizeInput() {
+      let carSize = this.form.cardSize;
+      let filterUnitList = this.unitList.filter(obj => obj.unit.indexOf(carSize) !== -1);
+      this.car.carInput = filterUnitList.length > 0;
+      this.filterUnitList = filterUnitList;
+    },
+    getUnit() {
+      this.$api.getUnitList().then(resp => {
+        this.unitList = resp.data;
+      })
+    },
+    selectCarSize(data) {
+      this.form.cardSize = data.unit;
+      this.car.carInput = false;
+    },
+    expectDayChange(date) {
+      this.form.expectInDay = date;
+    },
+    addHsFn(num, show) {
+      this.hs.num = num;
+      this.hs.visible = show;
+    },
+    showHsModal() {
+      Object.assign(this.modal, {
+        visible: true,
+        form: {
+          name: '',
+          phone: '',
+          index: -1
+        }
+      });
+    },
+    addHsPeopleFn() {
+      if (!this.modal.form.name) {
+        this.$common.toast('请输入名称');
+        return;
+      }
+      if (this.modal.form.phone && !this.$common.isPhone(this.modal.form.phone)) {
+        this.$common.toast('联系号码不正确');
+        return;
+      }
+      let dbIndex = this.modal.form.index;
+      if (dbIndex >= 0) {
+        this.hs.list[dbIndex].name = this.modal.form.name;
+        this.hs.list[dbIndex].phone = this.modal.form.phone;
+      } else {
+        this.modal.form.index = this.hs.list.length;
+        this.hs.list.push(this.modal.form);
+      }
+      this.modal.visible = false;
+
+    },
+    editFn(data) {
+      Object.assign(this.modal, {
+        visible: true,
+        form: data
+      })
+    },
+    deleteFn(data) {
+      this.hs.list.splice(data.index, 1);
+      if (data.id) {
+        this.$api.deleteHsPeople({
+          id: data.id
+        });
+      }
+    },
+    getGoodsList() {
+      this.$api.getGoodsList().then(resp => {
+        this.goods.goodsList = resp.data;
+        this.getItemList();
+      })
+    },
+    getItemList() {
+      this.$api.getItemList({
+        business: 1
+      }).then(resp => {
+        this.itemList = resp.data;
+        this.getBusinessById();
+      })
+    },
+    handlerTypeItem(goods) {
+
+    },
+    idCardInput() {
+      let val = this.form.driverIdCard;
+      let list = this.driverList.filter(obj => obj.idCard.indexOf(val) !== -1);
+      if (list.length > 0 && val) {
+        this.driver.show = true;
+        this.driver.filterList = list;
+      } else {
+        this.driver.show = false;
+      }
+    },
+    selectDriverFn(item) {
+      this.form.driverIdCard = item.idCard;
+      this.form.driverName = item.name;
+      this.form.driverPhone = item.phone
+      let that = this;
+      setTimeout(() => {
+        that.driver.show = false;
+      }, 150)
+    },
+    selectCarNo(item) {
+      this.form.cardNo = item.cardNo;
+      this.form.cardSize = item.cardSize;
+      this.form.netWeight = item.lastNetWeight;
+      let names = this.goods.goodsList.map(obj => obj.name);
+      let index = names.indexOf(item.lastGoodsName);
+      this.goods.index = index == -1 ? 0 : index;
+      this.country.index = this.country.list.indexOf(item.countryName)
+      let that = this;
+      setTimeout(() => {
+        this.car.carInput = false;
+      }, 150)
+
+    },
+
+    selectItemFn(item) {
+      let typeName = item.name;
+      let checkItem = this.checkItem;
+
+      this.item = item;
+      this.show = true;
+
+    },
+    cleanItemSelect(item) {
+      item.itemName = '';
+      setTimeout(() => {
+        this.show = false;
+        this.checkItem = ''
+      }, 80)
+    },
+    itemSelectFn(data) {
+      this.show = false;
+      this.item.itemName = data;
+    },
+    check() {
+      if (!this.form.cardNo) {
+        this.$common.toast('请录入境外车牌号')
+        return false;
+      }
+      if (!this.$common.isNum(this.form.cardSize)) {
+        this.$common.toast('车辆规格请录入数字')
+        return false;
+      }
+      if (!this.form.netWeight || !this.$common.isNum(this.form.netWeight)) {
+        this.$common.toast('载重必须输入数字')
+        return false;
+      }
+      let typeList = this.filterItemList.filter(obj => obj.itemName);
+      if (typeList.length == 0) {
+        this.$common.toast('至少选择一项业务项')
+        return false;
+      }
+      let filterItemList = this.filterItemList;
+      let needIds = this.needTypeId;
+      console.log(needIds);
+      console.log(typeList);
+      for (let i in needIds) {
+        if (typeList.map(obj => obj.id).indexOf(needIds[i]) == -1) {
+          this.$common.toast('缺少必选业务');
+          return false;
+        }
+      }
+      let peopleList = this.hs.list;
+      if (typeList.filter(obj => obj.name.indexOf('人') !== -1 &&
+              obj.name.indexOf('核酸') !== -1).length > 0 &&
+          peopleList.length == 0) {
+        this.$common.toast('录入核酸检测人员')
+        return false;
+      }
+      let list = [];
+      for (let i in typeList) {
+        let type = typeList[i];
+        type.num = 1;
+        for (let j in type.items) {
+          let item = type.items[j];
+          if (type.itemName == item.itemName) {
+            type.itemId = item.id;
+            break;
+          }
+        }
+        list.push({
+          itemId: type.itemId,
+          num: type.num
+        })
+      }
+      this.form.itemJson = JSON.stringify(list);
+      this.form.peopleJson = JSON.stringify(peopleList);
+      this.form.carJson = JSON.stringify(this.china.list);
+      this.form.items = null;
+      this.form.cars = null;
+      if (this.customerId == '1') {
+      } else {
+        this.form.customerId = this.customerId;
+      }
+      this.form.goodsName = this.goods.goodsList[this.goods.index].name;
+
+      return true;
+    },
+    saveFn() {
+      if (this.check()) {
+
+        let obj = this.$common.removeNull(this.form);
+        this.$api.saveBusiness(obj).then(resp => {
+          if (resp.code == 200) {
+            uni.removeStorageSync('business_' + this.customerId);
+            this.$common.toast('修改成功');
+            this.hs.list = [];
+            setTimeout(() => {
+              this.$common.to('/pages/business-order/business-order')
+            }, 1000)
+          }
+        })
+      }
+    },
+    bindPickerChange(e) {
+      var nowId = e.target.id; //当前picker的ID id需要自己设置 在picker中
+      var value = e.detail.value; //当前picker选中的值
+      switch (nowId) { //根据ID判断是哪个picker
+        case "qy": //picker的ID
+          this.customer.index = value;
+          break;
+        case "hw": //picker的ID
+          this.goods.index = value;
+          break;
+        case "gj": //picker的ID
+          this.country.index = value;
+          break;
+      }
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 772 - 0
app-ui/pages/business-entering/business-entering.vue

@@ -0,0 +1,772 @@
+<template>
+  <view>
+    <view class="box" v-show="hs.visible">
+      <view class="top">
+        <text class="title">录入核酸人员</text>
+      </view>
+      <view style="display: flex;margin-top: 40rpx;">
+        <u-button type="primary" @click="hs.visible=false" text="返回" style="width: 20px;" size="mini"/>
+        <u-button type="primary" @click="showHsModal" text="添加" v-show="hs.num>hs.list.length" icon="plus"
+                  style="width: 20px;" size="mini"/>
+      </view>
+      <u-row style="margin-top: 70rpx;">
+        <u-col span="4" style="text-align: center;">姓名</u-col>
+        <u-col span="4" style="text-align: center;">联系号码</u-col>
+        <u-col span="4" style="text-align: center;">操作</u-col>
+      </u-row>
+      <u-row v-for="item in hs.list" style="margin-top: 40rpx;">
+        <u-col span="4" style="text-align: center;">{{ item.name }}</u-col>
+        <u-col span="4" style="text-align: center;">{{ item.phone }}</u-col>
+        <u-col span="4" style="text-align: center;">
+          <u-row>
+            <u-col span="6">
+              <u-button type="primary" text="编辑" style="width: 20px;" @click="editFn(item)" size="mini">
+              </u-button>
+            </u-col>
+            <u-col span="6">
+              <u-button type="error" style="width: 20px;" text="删除" @click="deleteFn(item)" size="mini">
+              </u-button>
+            </u-col>
+          </u-row>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="box" v-show="china.visible">
+      <view class="top">
+        <text class="title">中国车录入</text>
+      </view>
+      <view style="display: flex;margin-top: 40rpx;">
+        <u-button type="primary" @click="china.visible=false" text="返回" style="width: 20px;" size="mini"/>
+        <u-button type="primary" @click="showChinaModal" text="添加" icon="plus" style="width: 20px;"
+                  size="mini"/>
+      </view>
+      <u-row style="margin-top: 70rpx;">
+        <u-col span="3" style="text-align: center;">车牌号</u-col>
+        <u-col span="3" style="text-align: center;">联系人</u-col>
+        <u-col span="3" style="text-align: center;">联系号码</u-col>
+        <u-col span="3" style="text-align: center;">操作</u-col>
+      </u-row>
+      <u-row v-for="(item,index) in china.list" style="margin-top: 40rpx;">
+        <u-col span="3" style="text-align: center;">{{ item.carNo }}</u-col>
+        <u-col span="3" style="text-align: center;">{{ item.driverName }}</u-col>
+        <u-col span="3" style="text-align: center;">{{ item.driverPhone }}</u-col>
+        <u-col span="3" style="text-align: center;">
+          <u-row>
+            <u-col span="6">
+              <u-button type="primary" text="编辑" style="width: 20px;" @click="editChinaCar(item,index)"
+                        size="mini">
+              </u-button>
+            </u-col>
+            <u-col span="6">
+              <u-button type="error" style="width: 20px;" text="删除" @click="deleteChinaCar(item,index)"
+                        size="mini">
+              </u-button>
+            </u-col>
+          </u-row>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="box" v-show="!hs.visible&&!china.visible">
+      <view class="top">
+        <text class="title">整车录入</text>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报单号:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报订单号" v-model="form.declareNo" clearable readonly>
+            <text slot="suffix" style="font-size: 50rpx;" @click="selectDeclare">+</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">申报单位:</view>
+        <view class="r">
+          <u-input placeholder="申报单位" disabled @input="handler()" v-model="form.customerName">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          货物:
+        </view>
+        <view class="r">
+          <picker v-if="goods.goodsList.length>0" class="p-picker" id="hw" @change="whChange($event)"
+                  :value="goods.index" :range="goods.goodsList" range-key="name">
+            <text class="p-text">{{ goods.goodsList[goods.index].name }}</text>
+            <u-icon class="p-icon" name="arrow-down-fill" size="20"></u-icon>
+          </picker>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          载重:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入载重" @input="handler()" v-model="form.netWeight">
+            <text slot="suffix">kg</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          境外车牌:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入车牌号" @input="handler()" v-model="form.cardNo"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          境外车规格:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入车辆规格" @input="handler()" v-model="form.cardSize">
+            <text slot="suffix">米</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">中国车:</view>
+        <view class="r">
+          <u-input placeholder="中国车" v-model="china.list.map(obj=>obj.carNo).join('、')" readonly>
+            <text slot="suffix" style="font-size: 50rpx;" @click="addCar">+</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item-line">
+        业务项
+      </view>
+      <view class="item" v-for="item in filterItemList" :key="item.id" v-if="item.items.length>0">
+        <view class="l">
+          <text v-if="needTypeId.indexOf(item.id)!==-1" style="color: red;">*</text>
+          {{ item.name }}:
+        </view>
+        <view class="r">
+          <view @click="selectItemFn(item)">
+            <u-input placeholder="请选择" v-model="item.itemName" readonly clearable style="width: 120px;">
+              <u-icon name="close" v-if="item.itemName" slot="suffix" color="#E5E5E5;" size="5"
+                      @click="cleanItemSelect(item)"></u-icon>
+            </u-input>
+          </view>
+          <u-input placeholder="数量" :disabled="item.inc==0" border="surround" v-model="item.num" type="number"
+                   style="width: 10px;" v-if="item.itemName"></u-input>
+          <view style="margin-left: 20rpx;color: red;" v-if="item.itemName">
+            {{ item.items.filter(obj => obj.itemName == item.itemName)[0].price * item.num }}元
+          </view>
+          <u-icon name="plus" style="position: absolute;right: 10rpx;"
+                  v-if="item.itemName&&item.name.indexOf('人')!==-1&&item.name.indexOf('核酸')!==-1"
+                  @click="addHsFn(item.itemName,item.num)"></u-icon>
+        </view>
+      </view>
+      <view class="hj" v-show="totalPrice>0">
+        合计:{{ totalPrice }}元
+      </view>
+    </view>
+    <u-button type="primary" text="确定" @click="saveFn"
+              v-show="(!hs.visible&&!china.visible)&&perList.indexOf('tb-business-add')!==-1"></u-button>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+    <u-popup :show="car.carInput" :overlay="false" @close="car.carInput=false" borderRadius="10">
+      <view style="padding: 40rpx;line-height: 60rpx;text-align: center;">
+        <view v-for="item in filterUnitList" :id="item.id"
+              style="margin-bottom: 20rpx;border-bottom: 1rpx solid #E5E5E5;" @click="selectCarSize(item)">
+          {{ item.unit }}
+        </view>
+      </view>
+    </u-popup>
+    <u-popup :show="driver.show" :overlay="false" @close="driver.show=false" borderRadius="10">
+      <view style="padding: 40rpx;line-height: 60rpx;text-align: center;">
+        <view v-for="item in driver.filterList" :id="item.id"
+              style="margin-bottom: 20rpx;border-bottom: 1rpx solid #E5E5E5;" @click="selectDriverFn(item)">
+          {{ item.name }}({{ item.idCard }})
+        </view>
+      </view>
+    </u-popup>
+    <u-popup :show="show" closeable closeOnClickOverlay @close="show=false">
+      <view style="padding: 40rpx;">
+        <u-radio-group @change="itemSelectFn" placement="column" v-model="item.itemName">
+          <u-radio v-for="item in item.items" :key="item.id" :label="item.itemName" :name="item.itemName"
+                   v-if="form.netWeight >= item.minWeight
+						&& form.netWeight < item.maxWeight
+						&&form.cardSize<=item.carLength
+						&&form.cardSize>=item.minLength" style="margin-top: 30rpx;">
+          </u-radio>
+        </u-radio-group>
+      </view>
+    </u-popup>
+    <u-modal :show="modal.visible" showCancelButton closeOnClickOverlay @cancel="modal.visible=false"
+             @confirm="addHsPeopleFn">
+      <view style="">
+        <u--input placeholder="姓名" border="surround" v-model="modal.form.name"></u--input>
+        <u--input style="margin-top: 20rpx;" placeholder="联系号码" border="surround" v-model="modal.form.phone">
+        </u--input>
+      </view>
+    </u-modal>
+    <u-modal :show="chinaAddModal.visible" title="中国车" @confirm="sureCarFn" @cancel="chinaAddModal.visible=false"
+             showCancelButton cancelText="关闭">
+      <view class="slot-content">
+        <u-row>
+          <u-col span="4">车牌号</u-col>
+          <u-col span="8">
+            <u--input placeholder="车牌号" v-model="chinaAddModal.form.carNo"></u--input>
+          </u-col>
+        </u-row>
+        <u-row>
+          <u-col span="4">联系人</u-col>
+          <u-col span="8">
+            <u--input placeholder="联系人" v-model="chinaAddModal.form.driverName"></u--input>
+          </u-col>
+        </u-row>
+        <u-row>
+          <u-col span="4">联系号码</u-col>
+          <u-col span="8">
+            <u--input placeholder="联系号码" v-model="chinaAddModal.form.driverPhone"></u--input>
+          </u-col>
+        </u-row>
+      </view>
+    </u-modal>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      car: {
+        carInput: false,
+        filterList: [],
+      },
+      driver: {
+        show: false,
+        filterList: [],
+      },
+      customerId: '1',
+      exprctStart: new Date().getTime(),
+      itemList: [],
+      filterItemList: [],
+      needTypeId: [],
+      noNeedIds: [],
+      form: {
+        customerId: '',
+        customerIndex: 0,
+        declareNo: '',
+        countryIndex: 0,
+        goodsIndex: 0,
+        cardNo: '',
+        cardSize: '',
+        goodsName: '',
+        netWeight: '',
+        driverName: '',
+        driverPhone: '',
+        expectInDay: ''
+      },
+      show: false,
+      item: {
+        items: []
+      },
+      customer: {
+        index: 0,
+        customerList: [],
+      },
+      carList: [],
+      driverList: [],
+      unitList: [],
+      filterUnitList: [],
+      country: {
+        index: 0,
+        list: ['越南车', '中国车']
+      },
+      goods: {
+        index: 0,
+        goodsList: []
+      },
+      hs: {
+        visible: false,
+        num: 1,
+        list: []
+      },
+      modal: {
+        visible: false,
+        form: {
+          name: '',
+          phone: ''
+        }
+      },
+      china: {
+        visible: false,
+        index: -1,
+        list: []
+      },
+      chinaAddModal: {
+        visible: false,
+        form: {
+          carNo: '',
+          driverName: '',
+          driverPhone: ''
+        }
+      },
+      checkItem: '',
+      perList: []
+    }
+  },
+  onShow() {
+    this.customerId = uni.getStorageSync('customerId');
+    this.perList = uni.getStorageSync('perList')
+  },
+  computed: {
+    totalPrice() {
+      let itemList = this.itemList.filter(obj => obj.itemName);
+      let price = 0;
+      for (let i in itemList) {
+        let type = itemList[i];
+        let items = type.items;
+        for (let j in items) {
+          let item = items[j];
+          if (item.itemName == type.itemName) {
+            price += item.price;
+            break;
+          }
+        }
+      }
+      return price;
+    },
+  },
+  created() {
+    this.getGoodsList();
+    this.getUnit();
+  },
+  onLoad(options) {
+    let that = this;
+    uni.$on('getSelectDeclare', declare => {
+      that.$nextTick(() => {
+        that.form.declareNo = declare.declareNo;
+        that.form.cardNo = declare.carNo;
+        that.form.chinaCarNo = declare.chinaCarNo;
+        that.form.netWeight = declare.grossWeight;
+        that.form.customerId = declare.customerId;
+        that.form.customerName = declare.customerName;
+        let chinaCarNo = declare.chinaCarNo;
+        if (chinaCarNo) {
+          let list = [];
+          chinaCarNo.replace(",", ",").split(",").forEach(carNo => {
+            let obj = {
+              carNo: carNo
+            }
+            list.push(obj);
+            that.china.list = list;
+          })
+        } else {
+          that.china.list = [];
+        }
+        that.handler();
+      })
+    })
+  },
+  methods: {
+    selectDeclare() {
+      this.$common.to('/pages/business-entering/declare-select?declareNo=' + this.form.declareNo)
+    },
+    addCar() {
+      this.china.visible = true;
+    },
+    showChinaModal() {
+      Object.assign(this.chinaAddModal, {
+        visible: true,
+        index: -1,
+        form: {
+          carNo: '',
+          driverName: '',
+          driverPhone: ''
+        }
+      })
+    },
+    sureCarFn() {
+      let form = this.chinaAddModal.form;
+      let carNo = form.carNo;
+      let phone = form.driverPhone;
+      if (carNo && !this.$common.isCarNo(carNo)) {
+        this.$common.toast('请输入正确的车牌号')
+        return;
+      }
+      if (phone && !this.$common.isPhone(phone)) {
+        this.$common.toast('请输入正确的手机号')
+        return;
+      }
+      let list = this.china.list;
+      let index = this.chinaAddModal.index;
+      if (index > -1) {
+        list.splice(index, 1)
+      }
+      list.push(form)
+      this.chinaAddModal.visible = false;
+    },
+    deleteChinaCar(item, index) {
+      this.china.list.splice(index, 1);
+    },
+    editChinaCar(item, index) {
+      Object.assign(this.chinaAddModal, {
+        visible: true,
+        index: index,
+        form: item
+      })
+    },
+    whChange(event) {
+      let index = event.detail.value; //当前picker选中的值
+      this.goods.index = index;
+      let goods = this.goods.goodsList[index];
+      let noNeedIds = goods.noNeedIds.split(',');
+      this.needTypeId = goods.needIds.split(',');
+      this.noNeedIds = goods.noNeedIds.split(',')
+      this.filterItemList = this.itemList.filter(obj => noNeedIds.indexOf(obj.id) == -1);
+      this.handler();
+    },
+    carSizeInput() {
+      let carSize = this.form.cardSize;
+      let filterUnitList = this.unitList.filter(obj => obj.unit.indexOf(carSize) !== -1);
+      this.car.carInput = filterUnitList.length > 0;
+      this.filterUnitList = filterUnitList;
+      this.handler();
+    },
+    getUnit() {
+      this.$api.getUnitList().then(resp => {
+        this.unitList = resp.data;
+      })
+    },
+    selectCarSize(data) {
+      this.form.cardSize = data.unit;
+      this.car.carInput = false;
+      this.handler();
+    },
+    expectDayChange(date) {
+      this.form.expectInDay = date;
+      this.handler();
+    },
+    addHsFn(itemName, num) {
+      this.hs.visible = true;
+      this.hs.num = num;
+    },
+    showHsModal() {
+      Object.assign(this.modal, {
+        visible: true,
+        form: {
+          name: '',
+          phone: '',
+          index: -1
+        }
+      });
+    },
+    addHsPeopleFn() {
+      if (!this.modal.form.name) {
+        this.$common.toast('请输入名称');
+        return;
+      }
+      if (this.modal.form.phone && !this.$common.isPhone(this.modal.form.phone)) {
+        this.$common.toast('联系号码不正确');
+        return;
+      }
+      let dbIndex = this.modal.form.index;
+      if (dbIndex >= 0) {
+        this.hs.list[dbIndex].name = this.modal.form.name;
+        this.hs.list[dbIndex].phone = this.modal.form.phone;
+      } else {
+        this.modal.form.index = this.hs.list.length;
+        this.hs.list.push(this.modal.form);
+      }
+      this.modal.visible = false;
+      this.handler();
+    },
+    editFn(data) {
+      Object.assign(this.modal, {
+        visible: true,
+        form: data
+      })
+    },
+    deleteFn(data) {
+      this.hs.list.splice(data.index, 1);
+      if (data.id) {
+        this.$api.deleteHsPeople({
+          id: data.id
+        });
+      }
+    },
+    getGoodsList() {
+      this.$api.getGoodsList().then(resp => {
+        this.goods.goodsList = resp.data;
+        let goods = resp.data[0];
+        let noNeedIds = goods.noNeedIds.split(',');
+        this.needTypeId = goods.needIds.split(',')
+        this.noNeedIds = goods.noNeedIds.split(',')
+        this.$api.getItemList({business: 1}).then(resp => {
+          let list = resp.data;
+          this.itemList = list;
+          this.filterItemList = list.filter(obj => noNeedIds.indexOf(obj.id) == -1);
+          this.checkStore();
+        })
+      })
+    },
+    handlerTypeItem(goods) {
+
+    },
+    idCardInput() {
+      let val = this.form.driverIdCard;
+      let list = this.driverList.filter(obj => obj.idCard.indexOf(val) !== -1);
+      if (list.length > 0 && val) {
+        this.driver.show = true;
+        this.driver.filterList = list;
+      } else {
+        this.driver.show = false;
+      }
+    },
+    selectDriverFn(item) {
+      this.form.driverIdCard = item.idCard;
+      this.form.driverName = item.name;
+      this.form.driverPhone = item.phone
+      let that = this;
+      setTimeout(() => {
+        that.driver.show = false;
+      }, 150)
+    },
+    carInputFn() {
+      this.handler();
+    },
+    selectCarNo(item) {
+      this.form.cardNo = item.cardNo;
+      this.form.cardSize = item.cardSize;
+      this.form.netWeight = item.lastNetWeight;
+      let names = this.goods.goodsList.map(obj => obj.name);
+      let index = names.indexOf(item.lastGoodsName);
+      this.goods.index = index == -1 ? 0 : index;
+      this.country.index = this.country.list.indexOf(item.countryName)
+      let that = this;
+      this.handler();
+      setTimeout(() => {
+        this.car.carInput = false;
+      }, 150)
+
+    },
+    selectItemFn(item) {
+      this.item = item;
+      this.show = true;
+    },
+    cleanItemSelect(item) {
+      item.itemName = '';
+      setTimeout(() => {
+        this.show = false;
+        this.checkItem = ''
+      }, 80)
+    },
+    itemSelectFn(data) {
+      this.show = false;
+      this.item.itemName = data;
+      this.handler();
+    },
+    handler() {
+      let goodsIndex = this.goods.index;
+      let countryIndex = this.country.index;
+      this.form.goodsName = this.goods.goodsList[goodsIndex].name;
+      this.form.countryName = this.country.list[countryIndex];
+      this.form.goodsIndex = goodsIndex;
+      this.form.countryIndex = countryIndex;
+      this.form.peopleJson = JSON.stringify(this.hs.list);
+      this.form.carJson = JSON.stringify(this.china.list);
+      let customerId = this.customerId;
+      let inputItem = this.filterItemList
+          .filter(obj => obj.itemName).map(o => {
+            return {
+              typeId: o.id,
+              itemName: o.itemName,
+              num: o.num
+            }
+          });
+      this.form.inputItemJson = JSON.stringify(inputItem);
+      let that = this;
+      uni.setStorage({
+        key: 'business_' + customerId,
+        data: that.form
+      })
+    },
+    checkStore() {
+      let customerId = this.customerId;
+      let data = uni.getStorageSync('business_' + customerId)
+      if (data) {
+        let that = this;
+        uni.showModal({
+          title: '提示',
+          content: '您上次录入数据未提交,是否继续?',
+          cancelText: '重新录入',
+          confirmText: '继续',
+          success(res) {
+            if (res.confirm) {
+              that.rebackStore(data);
+            } else {
+              uni.removeStorageSync('business_' + customerId)
+            }
+          }
+        })
+      }
+    },
+    rebackStore(data) {
+      this.form = data;
+      this.goods.index = data.goodsIndex ? data.goodsIndex : 0;
+      this.hs.list = data.peopleJson ? JSON.parse(data.peopleJson) : [];
+      this.china.list = data.carJson ? JSON.parse(data.carJson) : [];
+      if (data.inputItemJson) {
+        let inputItemList = JSON.parse(data.inputItemJson);
+        let filterList = this.filterItemList;
+        for (let i in filterList) {
+          let type = filterList[i];
+          for (let j in inputItemList) {
+            let s = inputItemList[j];
+            if (type.id == s.typeId) {
+              type.itemName = s.itemName;
+              type.num = s.num;
+              break;
+            }
+          }
+        }
+      }
+      setTimeout(() => {
+        this.car.carInput = false;
+      }, 100)
+    },
+    check() {
+      this.handler();
+      if (!this.form.cardNo) {
+        this.$common.toast('请录入境外车牌号')
+        return false;
+      }
+      if (!this.$common.isNum(this.form.cardSize)) {
+        this.$common.toast('车辆规格请录入数字')
+        return false;
+      }
+      if (!this.form.netWeight || !this.$common.isNum(this.form.netWeight)) {
+        this.$common.toast('载重必须输入数字')
+        return false;
+      }
+      let typeList = this.filterItemList.filter(obj => obj.itemName);
+      if (typeList.length == 0) {
+        this.$common.toast('至少选择一项业务项')
+        return false;
+      }
+      let noNeedIds = this.noNeedIds;
+      let needIds = this.needTypeId;
+      for (let i in needIds) {
+        if (typeList.map(obj => obj.id).indexOf(needIds[i]) == -1) {
+          this.$common.toast('缺少必选业务');
+          return false;
+        }
+      }
+      let peopleList = this.hs.list;
+      if (typeList.filter(obj => obj.name.indexOf('人') !== -1 &&
+              obj.name.indexOf('核酸') !== -1).length > 0 &&
+          peopleList.length == 0) {
+        this.$common.toast('录入核酸检测人员')
+        return false;
+      }
+      let list = [];
+      for (let i in typeList) {
+        let type = typeList[i];
+        type.num = 1;
+        for (let j in type.items) {
+          let item = type.items[j];
+          if (type.itemName == item.itemName) {
+            type.itemId = item.id;
+            break;
+          }
+        }
+        list.push({
+          itemId: type.itemId,
+          num: type.num
+        })
+      }
+      this.form.itemJson = JSON.stringify(list);
+      this.form.peopleJson = JSON.stringify(peopleList);
+      this.form.carJson = JSON.stringify(this.china.list);
+      this.form.items = null;
+      if (this.customerId == '1') {
+      } else {
+        this.form.customerId = this.customerId;
+      }
+      this.form.goodsName = this.goods.goodsList[this.goods.index].name;
+
+      return true;
+    },
+    saveFn() {
+      if (this.check()) {
+        let obj = this.$common.removeNull(this.form);
+        this.$api.saveBusiness(obj).then(resp => {
+          if (resp.code == 200) {
+            uni.removeStorageSync('business_' + this.customerId);
+            this.$common.toast('录入成功');
+            this.hs.list = [];
+            setTimeout(() => {
+              this.$common.to('/pages/business-order/business-order')
+            }, 1000)
+          }
+        })
+      }
+    },
+    bindPickerChange(e) {
+      var nowId = e.target.id; //当前picker的ID id需要自己设置 在picker中
+      var value = e.detail.value; //当前picker选中的值
+      switch (nowId) { //根据ID判断是哪个picker
+        case "qy": //picker的ID
+          this.customer.index = value;
+          break;
+        case "hw": //picker的ID
+          this.goods.index = value;
+          break;
+        case "gj": //picker的ID
+          this.country.index = value;
+          break;
+      }
+      this.handler();
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 222 - 0
app-ui/pages/business-entering/declare-select.vue

@@ -0,0 +1,222 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">申报记录</text>
+      </view>
+    </view>
+    <u-search v-if="recordItemList.length>0" placeholder="申报人" shape="square" v-model="p.declarePeople"
+              @search="getDeclareList()" @change="getDeclareList"
+              :height="80" style="margin: 30rpx;">
+    </u-search>
+    <view class="card-box">
+      <u-radio-group v-model="p.declareNo" placement="column" @change="onSelect">
+        <view class="card" v-for="(recordItem,index) in recordItemList" :key="index">
+          <view class="c">
+            <view class="item car-num-item">
+              <text class="car-num">企业:{{ recordItem.customerName }}</text>
+            </view>
+            <view class="item car-num-item">
+              <text class="p1">申报人:</text>
+              <text class="p2">{{ recordItem.declarePeople }}</text>
+            </view>
+            <view class="item car-num-item">
+              <text class="p1">产品学名:</text>
+              <text class="p2">{{ recordItem.goodsName }}</text>
+            </view>
+            <view class="item car-num-item">
+              <text class="p1">越南车牌:</text>
+              <text class="p2">{{ recordItem.carNo }}</text>
+            </view>
+            <view class="item car-num-item">
+              <text class="p1">申报时间:</text>
+              <text class="p2">{{ recordItem.createTime }}</text>
+            </view>
+
+          </view>
+          <view class="b">
+            <u-radio :key="index" :name="recordItem.declareNo" label="选择">
+            </u-radio>
+          </view>
+        </view>
+
+      </u-radio-group>
+    </view>
+    <!-- 没有数据时显示noData -->
+    <noData v-if="recordItemList.length==0"></noData>
+    <view style="text-align: center;margin: 20rpx 0 50rpx 0;color: #007AFF;" @click="toDeclare">前往添加</view>
+    <u-loadmore v-if="recordItemList.length>0" style="margin: 30rpx;" :status="status"/>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      p: {
+        pageNo: 1,
+        pageSize: 10,
+        dataCount: 0,
+        declareNo: '1',
+      },
+      status: 'loadmore',
+      recordItemList: [],
+    }
+  },
+  onLoad(options) {
+    let declareNo = options.declareNo;
+    if (declareNo) {
+      this.p.declareNo = declareNo;
+    }
+  },
+  methods: {
+    toDeclare() {
+      this.$common.to('/pages/declare/add');
+    },
+    onSelect() {
+      let select = this.p.declareNo;
+      let declare = this.recordItemList.filter(obj => obj.declareNo == select).pop();
+      uni.navigateBack({
+        delta: 1,
+        success: function (resp) {
+          uni.$emit('getSelectDeclare', declare) //触发事件
+        }
+      })
+    },
+    getDeclareList() {
+      if (!this.p.declareNo) {
+        this.p.declareNo = '1'
+      }
+      this.$api.getDeclareList(this.p).then(resp => {
+        this.status = 'loadmore';
+        let recordList = resp.data;
+        this.p.dataCount = resp.dataCount;
+        this.p.pageNo = resp.pageNo;
+        this.recordItemList = recordList;
+        if (this.dataCount < this.pageSize * this.pageNo) this.status = 'nomore';
+      })
+    },
+    //------------------------------------------
+    //上拉加载更多,分页模拟数据
+    onReachBottom() {
+      this.status = 'loading';
+      if (this.p.dataCount > this.p.pageSize * this.p.pageNo) {
+        this.p.pageSize = parseInt(this.p.pageSize) + 3;
+        this.getDeclareList();
+      } else {
+        this.status = 'nomore';
+      }
+    }
+  },
+  onShow() {
+    this.getDeclareList();
+  },
+}
+</script>
+
+<style lang="scss">
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 30rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 0 0;
+      display: flex;
+      flex-wrap: wrap;
+
+      //border-bottom: 1rpx solid #f5f5f5;
+      .item {
+        width: 50%;
+        padding: 20rpx 0;
+        display: flex;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 30rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+          flex: 5;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+          flex: 7;
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      margin-top: 20rpx;
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+    }
+  }
+}
+
+.t-btn {
+  width: 400rpx;
+  margin: 0 auto 80rpx auto;
+  height: 88rpx;
+  font-weight: bold;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 10rpx;
+  color: #191919;
+  font-size: 28rpx;
+  background-color: #fff;
+  border: 1px solid #eee;
+}
+
+@import '@/common/common.scss'
+</style>

+ 247 - 0
app-ui/pages/business-entering/item-select.vue

@@ -0,0 +1,247 @@
+<template>
+  <view>
+    <view class="input-box">
+      <view class="uni-input">
+        <input class="input" confirm-type="search" @input="getBaseGoods()" v-model="p.name"
+               @confirm="getBaseGoods()" placeholder="输入关键字搜索"/>
+        <view class="clear" @click="clear()">
+          <u-icon name="close-circle-fill" color="#ccc" size="38"></u-icon>
+        </view>
+      </view>
+      <view class="btn" @click="getBaseGoods()">搜索</view>
+    </view>
+    <view class="box pay-way">
+
+      <view class="pay-way-box" style="height: auto;">
+        <radio-group @change="radioChange">
+          <view class="item" v-for="(item,index) in goodsList" :key="item.id">
+            <label>
+              <image class="icon" :src="item.avatar"></image>
+              <view class="text">
+                <text class="title">{{ item.name }}</text>
+                <text class="p">编号:{{ item.code }}</text>
+              </view>
+              <radio class="pay-radio" :value="item.id"/>
+            </label>
+          </view>
+        </radio-group>
+      </view>
+
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      p: { // 查询参数
+        status: '1', // 描述
+        pageNo: 1, // 当前页
+        pageSize: 10, // 页大小
+        sortType: 0, // 排序方式
+        dataCount: 0,// 排序方式
+        name: ''
+      },
+      goodsList: []
+    }
+  },
+  onLoad() {
+
+  },
+  onShow() {
+    this.getBaseGoods();
+  },
+  methods: {
+    isInput() {
+
+    }, clear() {
+
+    },
+    getBaseGoods() {
+      this.$api.getBaseGoods(this.p).then(resp => {
+        this.goodsList = resp.data;
+        this.p.dataCount = resp.dataCount;
+      })
+    },
+    radioChange(event) {
+      let that = this;
+      uni.navigateBack({
+        data: 1,
+        url: '/pages/business-entering/business-entering',
+        success: function (resp) {
+          uni.$emit('getGoods', {goodsId: event.detail.value}) //触发事件
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.input-box {
+  display: flex;
+  align-items: center;
+  width: 100%;
+  padding: 20rpx 30rpx;
+  padding-right: 0;
+  box-sizing: border-box;
+  background-color: #fff;
+  position: fixed;
+  z-index: 9;
+  top: 0;
+  left: 0;
+  /*#ifdef H5*/
+  top: 45px;
+
+  /*#endif*/
+  .uni-input {
+    background-color: #f7f7f7;
+    height: 80rpx;
+    line-height: 80rpx;
+    padding: 0 80rpx 0 30rpx;
+    box-sizing: border-box;
+    flex: 1;
+    border-radius: 10rpx;
+    display: flex;
+    align-items: center;
+    position: relative;
+
+    .input {
+      flex: 1;
+      height: 100%;
+    }
+
+    .clear {
+      width: 80rpx;
+      height: 80rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      position: absolute;
+      right: 0;
+    }
+  }
+
+  .icon {
+    width: 40rpx;
+    height: 40rpx;
+    position: absolute;
+    background-color: #ddd;
+    right: 210rpx;
+    border-radius: 50%;
+  }
+
+  .btn {
+    width: 130rpx;
+    height: 80rpx;
+    color: #191919;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 0 10rpx 10rpx 0;
+    font-size: 32rpx;
+  }
+}
+
+.box {
+  display: flex;
+  margin: 20rpx;
+  border-radius: 20rpx;
+  flex: 1;
+
+  box-sizing: border-box;
+  flex-wrap: wrap;
+}
+
+.pay-way {
+  margin-bottom: 20rpx;
+  margin-top: 130rpx;
+
+  .top {
+    display: flex;
+    width: 100%;
+    align-items: center;
+    margin: 0 30rpx;
+    padding: 30rpx 0;
+
+    .title {
+      font-size: 34rpx;
+      font-weight: bold;
+    }
+  }
+
+  .pay-way-box {
+    width: 100%;
+    overflow: hidden;
+  }
+
+  .s-H {
+    height: 120rpx;
+  }
+
+  .e-H {
+    height: auto;
+  }
+
+  .tab-show {
+    width: 100%;
+    height: 88rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    text {
+      font-size: 30rpx;
+      color: #999;
+      margin-right: 20rpx;
+    }
+  }
+
+  radio-group {
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .item {
+    border-radius: 10rpx;
+    margin-top: 5rpx;
+    background-color: #fff;
+
+    label {
+      display: flex;
+      flex: 1;
+      align-items: center;
+      margin: 0 30rpx;
+      min-height: 120rpx;
+    }
+
+    .icon {
+      width: 60rpx;
+      height: 60rpx;
+    }
+
+    .text {
+      flex: 1;
+      margin-left: 20rpx;
+      display: flex;
+      flex-direction: column;
+
+      .title {
+        font-size: 30rpx;
+        color: #191919;
+      }
+
+      .p {
+        font-size: 24rpx;
+        color: #999;
+      }
+    }
+
+    .pay-radio {
+      margin-left: auto;
+    }
+  }
+}
+</style>

+ 273 - 0
app-ui/pages/business-item/item-detail.vue

@@ -0,0 +1,273 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务详情</text>
+      </view>
+    </view>
+    <view class="card-box">
+      <view class="card">
+        <view class="t">
+          订单号:
+          <text class="title">{{ businessItem.no }}</text>
+        </view>
+        <view class="c">
+          <view class="item car-num-item">
+            <text class="car-num">{{ businessItem.goodsName }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">类型:</text>
+            <text class="p2">{{ businessItem.itemTypeName }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">作业项:</text>
+            <text class="p2">{{ businessItem.itemName }}</text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.cardNo">
+          <view class="item">
+            <text class="p1">越南车:</text>
+            <text class="p2">{{ businessItem.cardNo }}</text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.chinaCarNo">
+          <view class="item">
+            <text class="p1">中国车:</text>
+            <text class="p2">{{ businessItem.chinaCarNo }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">录入时间:</text>
+            <text class="p2">{{ businessItem.createTime }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">状态:</text>
+            <text class="p2">
+              <text v-if="businessItem.pick==1">已接单</text>
+              <text v-else>未接单</text>
+            </text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item" v-if="businessItem.pickTime">
+            <text class="p1">接单时间:</text>
+            <text class="p2">
+              <text>{{ businessItem.pickTime }}</text>
+            </text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.pick==1">
+          <view class="item">
+            <text class="p1">确认状态:</text>
+            <text class="p2">
+              <text v-if="businessItem.confirm==1">已确认</text>
+              <text v-else>未确认</text>
+            </text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.confirm==1">
+          <view class="item">
+            <text class="p1">确认时间:</text>
+            <text class="p2">
+              <text>{{ businessItem.confirmTime }}</text>
+            </text>
+          </view>
+        </view>
+        <view class="b">
+          <view class="btn b3" v-if="businessItem.pick==0" @click="pickFn">
+            接单
+          </view>
+        </view>
+      </view>
+    </view>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      openid: '',
+      businessItem: {}
+    }
+  },
+  onLoad(option) {
+    this.businessItem.id = option.itemId;
+    this.openid = option.openid;
+    this.getBusinessItem();
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index')
+    return true;
+  },
+  methods: {
+    getBusinessItem() {
+      this.$api.getBusinessItem({
+        id: this.businessItem.id
+      }).then(resp => {
+        let data = resp.data;
+        if (!data) {
+          this.$common.toast('该业务已取消或删除');
+          setTimeout(() => {
+            this.$common.to('/pages/index/index')
+          }, 2000)
+          return;
+        }
+        this.businessItem = resp.data;
+      })
+    },
+    pickFn() {
+      let that = this;
+      uni.showModal({
+        title: '提示',
+        content: '是否确认接单?',
+        success(resp) {
+          if (resp.confirm) {
+            that.surePick();
+          }
+        }
+      })
+    },
+    surePick() {
+      let obj = {
+        openid: this.openid,
+        id: this.businessItem.id
+      };
+      this.$api.pickBusinessItem(obj).then(resp => {
+        if (resp.code == 200) {
+          this.$common.toast('已接单');
+          this.getBusinessItem();
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 35rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 30rpx 0;
+      display: flex;
+      flex-wrap: wrap;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .item {
+        padding: 20rpx 0;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 38rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+
+      .btn {
+        height: 70rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: calc(100% - 15rpx);
+        margin: 30rpx 0 0 0;
+        border-radius: 10rpx;
+        border-width: 1rpx;
+        box-sizing: border-box;
+      }
+
+      .b1 {
+        background-color: #0080ff;
+        color: #fff;
+      }
+
+      .b2 {
+        background-color: #f7f7f7;
+        color: #191919;
+      }
+
+      .b3 {
+        background-color: #fff;
+        color: #0080ff;
+        border: 1rpx solid #0080ff;
+      }
+
+      .b4 {
+        background-color: #ff0000;
+        color: #fff;
+      }
+    }
+  }
+}
+
+@import '@/common/common.scss'
+</style>

+ 317 - 0
app-ui/pages/business-order/business-item.vue

@@ -0,0 +1,317 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务详情</text>
+      </view>
+    </view>
+    <view class="card-box">
+      <view class="card" v-for="(businessItem,index) in items" :key="businessItem.id">
+        <view class="t">
+          订单号:
+          <text class="title">{{ businessItem.no }}</text>
+        </view>
+        <view class="c">
+          <view class="item car-num-item">
+            <text class="car-num">{{ businessItem.goodsName }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">类型:</text>
+            <text class="p2">{{ businessItem.itemTypeName }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">作业项:</text>
+            <text class="p2">{{ businessItem.itemName }}</text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.cardNo">
+          <view class="item">
+            <text class="p1">越南车:</text>
+            <text class="p2">{{ businessItem.cardNo }}</text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.chinaCarNo">
+          <view class="item">
+            <text class="p1">中国车:</text>
+            <text class="p2">{{ businessItem.chinaCarNo }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">录入时间:</text>
+            <text class="p2">{{ businessItem.createTime }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">状态:</text>
+            <text class="p2">
+              <text v-if="businessItem.pick==1">已接单</text>
+              <text v-else>未接单</text>
+            </text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item" v-if="businessItem.pickTime">
+            <text class="p1">接单时间:</text>
+            <text class="p2">
+              <text>{{ businessItem.pickTime }}</text>
+            </text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item" v-if="businessItem.pickCustomerName">
+            <text class="p1">接单企业:</text>
+            <text class="p2">
+              <text>{{ businessItem.pickCustomerName }}</text>
+            </text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.pick==1">
+          <view class="item">
+            <text class="p1">确认状态:</text>
+            <text class="p2">
+              <text v-if="businessItem.confirm==1">已确认</text>
+              <text v-else>未确认</text>
+            </text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.confirm==1">
+          <view class="item">
+            <text class="p1">确认时间:</text>
+            <text class="p2">
+              <text>{{ businessItem.confirmTime }}</text>
+            </text>
+          </view>
+        </view>
+        <view class="b" v-if="customerId=='1'&&businessItem.pick==1&&businessItem.confirm!=1">
+          <view class="btn b3" @click="pickFn(businessItem.id)">
+            确认
+          </view>
+        </view>
+      </view>
+    </view>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      customerId: '',
+      openid: '',
+      form: {},
+      items: [],
+      itemId: '',
+    }
+  },
+  onLoad(options) {
+    this.form.id = options.id;
+    this.itemId = options.itemId;
+    this.openid = options.openid;
+    this.checkLogin();
+  },
+  onShow() {
+    this.customerId = uni.getStorageSync('customerId')
+    if (this.itemId) {
+      this.getBusinessItem()
+    } else {
+      this.getBusinessById();
+    }
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index')
+    return true;
+  },
+  methods: {
+    getBusinessItem() {
+      this.$api.getBusinessItem({
+        id: this.itemId
+      }).then(resp => {
+        let data = resp.data;
+        if (!data) {
+          this.$common.toast('该业务已取消或删除');
+          setTimeout(() => {
+            this.$common.to('/pages/index/index')
+          }, 2000)
+          return;
+        }
+        this.items = [resp.data];
+      })
+    },
+    checkLogin() {
+      let token = uni.getStorageSync('token');
+      if (this.openid && !token) {
+        this.$api.doLoginByOpenid({
+          openid: this.openid
+        }).then(resp => {
+          let data = resp.data;
+          if (data.tokenInfo) {
+            uni.setStorageSync('token', data.tokenInfo.tokenValue);
+            uni.setStorageSync('customerId', data.admin.customerId)
+            uni.setStorageSync('info', data.admin)
+            uni.setStorageSync('perList', data.per_list)
+          } else {
+            this.$common.toast(resp.msg);
+          }
+        })
+      }
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.form.id
+      }).then(resp => {
+        let data = resp.data;
+        this.items = resp.data.items.filter(obj => obj.businessType !== 0);
+      })
+    },
+    pickFn(id) {
+      let that = this;
+      uni.showModal({
+        title: '提示',
+        content: '是否确认该业务项?',
+        success(resp) {
+          if (resp.confirm) {
+            that.surePick(id);
+          }
+        }
+      })
+    },
+    surePick(id) {
+      this.$api.confirmBusinessItem({
+        id: id
+      }).then(resp => {
+        if (resp.code == 200) {
+          this.$common.toast('已确认');
+          this.getBusinessById();
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 35rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 30rpx 0;
+      display: flex;
+      flex-wrap: wrap;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .item {
+        padding: 20rpx 0;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 38rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+
+      .btn {
+        height: 70rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: calc(100% - 15rpx);
+        margin: 30rpx 0 0 0;
+        border-radius: 10rpx;
+        border-width: 1rpx;
+        box-sizing: border-box;
+      }
+
+      .b1 {
+        background-color: #0080ff;
+        color: #fff;
+      }
+
+      .b2 {
+        background-color: #f7f7f7;
+        color: #191919;
+      }
+
+      .b3 {
+        background-color: #fff;
+        color: #0080ff;
+        border: 1rpx solid #0080ff;
+      }
+
+      .b4 {
+        background-color: #ff0000;
+        color: #fff;
+      }
+    }
+  }
+}
+
+@import '@/common/common.scss'
+</style>

+ 351 - 0
app-ui/pages/business-order/business-order.vue

@@ -0,0 +1,351 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务订单</text>
+      </view>
+    </view>
+    <!-- 		<u-sticky offset-top="0">
+      <u-tabs :list="tabs" @change="change" :current="current" :is-scroll="false"></u-tabs>
+    </u-sticky> -->
+    <view class="card-box">
+      <view class="card" v-for="(businessItem,index) in businessItemList" :key="index">
+        <view class="t">
+          <image class="icon" src="../../static/home-icon-01.png"></image>
+          <text class="title">{{ businessItem.customerName }}</text>
+        </view>
+        <view style="line-height: 60rpx;">
+          <view class="title">录入时间:{{ businessItem.createTime }}</view>
+          <view class="title">订单号:{{ businessItem.no }}</view>
+        </view>
+
+        <view class="c">
+          <view class="item car-num-item">
+            <text class="car-num">{{ businessItem.cardNo }}</text>
+          </view>
+
+          <view class="item">
+            <text class="p1">车型:</text>
+            <text class="p2">{{ businessItem.cardSize }}(米)</text>
+          </view>
+          <view class="item">
+            <text class="p1">载重:</text>
+            <text class="p2">{{ businessItem.netWeight }}(kg)</text>
+          </view>
+          <view class="item">
+            <text class="p1">账单确认:</text>
+            <text class="p2">
+              <text v-if="businessItem.confirmInput==0">未确认</text>
+              <text v-else>已确认</text>
+            </text>
+          </view>
+          <view class="item">
+            <text class="p1">支付状态:</text>
+            <text class="p2">
+              <text v-if="businessItem.payStatus==1">未支付</text>
+              <!-- <text v-if="businessItem.payStatus==2">已支付(未确认)</text> -->
+              <text v-if="businessItem.payStatus==3">已支付</text>
+            </text>
+          </view>
+        </view>
+        <view class="b">
+          <view class="btn b3" v-if="customemrId=='1'&&perList.indexOf('tb-business-item')!==-1"
+                @click="businessFn(businessItem)">
+            作业订单
+          </view>
+          <view class="btn b3" v-if="businessItem.payStatus==1
+								&&perList.indexOf('tb-business-confirm')!=-1"
+                @click="sureZdFn(businessItem)">
+            账单
+          </view>
+          <view class="btn b3" v-if="customemrId!=='1'" @click="fkFn(businessItem)">
+            证明
+          </view>
+          <view class="btn b3" @click="toDetail(businessItem)">详情</view>
+          <view class="btn b1" v-if="businessItem.adminConfirmInput==0&&perList.indexOf('tb-business-edit')!==-1"
+                @click="editFn(businessItem)">修改
+          </view>
+          <view class="btn b4" v-if="businessItem.payStatus==1
+								&&businessItem.adminConfirmInput==0
+								&&perList.indexOf('tb-business-del')!==-1" @click="deleteFn(businessItem)">删除
+          </view>
+        </view>
+      </view>
+    </view>
+    <noData v-if="businessItemList.length==0"></noData>
+    <u-loadmore style="margin: 30rpx;" :status="status"/>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      p: {
+        pageNo: 1,
+        pageSize: 3,
+        dataCount: 0
+      },
+      customemrId: '1',
+      fk: {
+        ids: '',
+      },
+      rc: {
+        id: '',
+        inChannel: '',
+        showTime: false,
+        visible: false,
+        realInTime: ''
+      },
+      current: 0,
+      status: 'loadmore',
+      page: 0,
+      tabs: [{
+        name: '进场',
+      }, {
+        name: '出场',
+      }],
+      businessItemList: [],
+      perList: []
+    }
+  },
+  onShow() {
+    this.customemrId = uni.getStorageSync('customerId')
+    this.getBusinessList();
+    this.perList = uni.getStorageSync('perList')
+  },
+  mounted() {
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index')
+    return true;
+  },
+  methods: {
+    businessFn(data) {
+      this.$common.to('/pages/business-order/business-item?id=' + data.id)
+    },
+    toDetail(data) {
+      this.$common.to('/pages/business-entering/business-detail?id=' + data.id)
+    },
+    editFn(data) {
+      this.$common.to('/pages/business-entering/business-edit?id=' + data.id)
+    },
+    deleteFn(data) {
+      let that = this;
+      uni.showModal({
+        title: "警告",
+        content: "是否删除该业务?",
+        success(res) {
+          if (res.confirm) {
+            that.$api.deleteBusiness({
+              id: data.id
+            }).then(resp => {
+              that.$common.toast('已删除');
+              that.getBusinessList();
+            })
+          }
+        }
+      })
+    },
+    completeFn(data) {
+      this.$common.to('/pages/business-order/createOrder?id=' + data.id)
+    },
+    sureZdFn(data) {
+      this.$common.to('/pages/wx/payOrderTemp?id=' + data.id)
+    },
+    fkFn(data) {
+      this.$common.to('/pages/business-order/report?id=' + data.id)
+    },
+    rcFn(data) {
+      this.$common.to('/pages/business-order/sureIn?id=' + data.id)
+    },
+    cc(data) {
+      this.$common.to('/pages/business-order/sureOut?id=' + data.id)
+    },
+    getBusinessList() {
+      this.p.isCar = 0;
+      this.$api.getBusinessList(this.p).then(resp => {
+        this.status = 'loadmore';
+        this.p.pageNo = resp.pageNo;
+        this.p.pageSize = resp.pageSize;
+        this.p.dataCount = resp.dataCount;
+        this.businessItemList = resp.data;
+      })
+    },
+    //点击上方切换栏,根据点击项重新加载数据
+    change(index) {
+      this.current = index;
+      if (index == 0) {
+        //只加载进场订单
+      }
+      if (index == 1) {
+        //只加载出场订单
+      }
+    },
+    //点击按钮
+    //------------------------------------------
+
+    fkconfirm() {
+      this.$api.adminConfirmPay(this.fk).then(resp => {
+        this.$refs.fkpopup.close();
+        this.getBusinessList();
+      })
+    },
+
+    rcconfirm() {
+      if (!this.rc.inChannel) {
+        this.$common.toast('请填写入场通道');
+        return false;
+      }
+      this.$api.adminConfirmIn(this.rc).then(resp => {
+        this.$refs.rcpopup.close();
+        this.getBusinessList();
+      })
+    },
+
+    ccconfirm(index) {
+      this.$refs.ccpopup.close()
+    },
+    zd() {
+      this.$refs.zdpopup.open('center')
+    },
+    zdconfirm(index) {
+      this.$refs.zdpopup.close()
+    },
+    //------------------------------------------
+    //上拉加载更多,分页模拟数据
+    onReachBottom() {
+      if (parseInt(this.p.dataCount) > parseInt(this.p.pageSize) * parseInt(this.p.pageNo)) {
+        this.status = 'loading';
+        this.p.pageSize += 5;
+        this.getBusinessList();
+      } else {
+        this.status = 'nomore';
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 30rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 30rpx 0;
+      display: flex;
+      flex-wrap: wrap;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .item {
+        width: 50%;
+        padding: 20rpx 0;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 44rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+          letter-spacing: 20rpx;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+
+      .btn {
+        height: 70rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: calc(50% - 15rpx);
+        margin: 30rpx 0 0 0;
+        border-radius: 10rpx;
+        border-width: 1rpx;
+        box-sizing: border-box;
+      }
+
+      .b1 {
+        background-color: #0080ff;
+        color: #fff;
+      }
+
+      .b2 {
+        background-color: #f7f7f7;
+        color: #191919;
+      }
+
+      .b3 {
+        background-color: #fff;
+        color: #0080ff;
+        border: 1rpx solid #0080ff;
+      }
+
+      .b4 {
+        background-color: #ff0000;
+        color: #fff;
+      }
+    }
+  }
+}
+
+@import '@/common/common.scss'
+</style>

+ 164 - 0
app-ui/pages/business-order/createOrder.vue

@@ -0,0 +1,164 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="item">
+        <view class="l">客户名称:</view>
+        <view class="r">
+          {{ form.customerName }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">订单号:</view>
+        <view class="r">
+          {{ form.no }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">业务费用:</view>
+        <view class="r">
+          {{ form.itemPrice }}元
+
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">境外车入场:</view>
+        <view class="r">
+          {{ form.realInTime }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          境外车预计离场:
+        </view>
+        <view class="r">
+          <uni-datetime-picker placeholder="离场时间" :start="new Date().getTime()" type="datetime"
+                               @change="jwCaroTimeChange"
+                               v-model="form.outDayTime"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">停车费用:</view>
+        <view class="r">
+          {{ form.partMoney }}
+          <text v-if="form.partMoney">元</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">中国车入场:</view>
+        <view class="r">
+          {{ form.chinaCarInTime }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          中国车预计离场:
+        </view>
+        <view class="r">
+          <uni-datetime-picker placeholder="离场时间" :start="new Date().getTime()" type="datetime"
+                               @change="chinaCaroTimeChange"
+                               v-model="form.chinaCarOutTime"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">停车费用:</view>
+        <view class="r">
+          {{ form.chinaPartMoney }}
+          <text v-if="form.chinaPartMoney">元</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">总计费用:</view>
+        <view class="r">
+          {{ form.totalMoney }}
+        </view>
+      </view>
+    </view>
+    <u-button type="primary" @click="confirmFn">确认生成</u-button>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: '',
+      form: {
+        partMoney: 0,
+        outDayTime: '',
+        chinaCarOutTime: ''
+      },
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  onShow() {
+    this.getBusinessById();
+  },
+  methods: {
+    jwCaroTimeChange(date) {
+      if (!date || date.length <= 12) {
+        this.form.outDayTime = '';
+        this.form.partMoney = 0;
+        this.$common.toast('境外车离场时间不正确');
+        return;
+      }
+      this.form.outDayTime = date;
+      let o = Object.assign(this.form);
+      o.items = null;
+      o.outDayTime = date;
+      this.$api.calJwPartMoney(this.$common.removeNull(o)).then(resp => {
+        this.form = resp.data;
+      })
+    },
+    chinaCaroTimeChange(date) {
+      if (!date) {
+        this.form.chinaCarOutTime = '';
+        this.form.chinaPartMoney = 0;
+        this.$common.toast('请选择离场时间');
+        return;
+      }
+      if (date.length <= 12) {
+        this.$common.toast('请选择时间');
+        return;
+      }
+      this.form.chinaCarOutTime = date;
+      let o = Object.assign(this.form);
+      o.items = null;
+      this.$api.calChinaPartMoney(this.$common.removeNull(o)).then(resp => {
+        this.form = resp.data;
+      })
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+      })
+    },
+    confirmFn() {
+      if (!this.form.chinaCarOutTime || !this.form.outDayTime) {
+        this.$common.toast('请选择时间')
+        return;
+      }
+      this.form.items = null;
+      this.$api.completeOrder(this.$common.removeNull(this.form)).then(Resp => {
+        this.$common.toast('操作成功');
+        setTimeout(() => {
+          this.$common.back()
+        }, 500)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+@import '@/common/common.scss';
+</style>

+ 227 - 0
app-ui/pages/business-order/partner-business-item.vue

@@ -0,0 +1,227 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务详情</text>
+      </view>
+    </view>
+    <view class="card-box">
+      <view class="card" v-for="(businessItem,index) in items" :key="businessItem.id">
+        <view class="t">
+          <image class="icon" src="../../static/home-icon-01.png"></image>
+          <text class="title">{{ businessItem.itemTypeName }}</text>
+        </view>
+        <view class="c">
+          <view class="item car-num-item">
+            <text class="car-num">{{ businessItem.itemName }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">录入时间:</text>
+            <text class="p2">{{ businessItem.createTime }}</text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.cardNo">
+          <view class="item">
+            <text class="p1">车辆:</text>
+            <text class="p2">{{ businessItem.cardNo }}</text>
+          </view>
+        </view>
+        <view class="c">
+          <view class="item" v-if="businessItem.pickTime">
+            <text class="p1">接单时间:</text>
+            <text class="p2">
+              <text>{{ businessItem.pickTime }}</text>
+            </text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.pick==1">
+          <view class="item">
+            <text class="p1">客户确认:</text>
+            <text class="p2">
+              <text v-if="businessItem.confirm==1">已确认</text>
+              <text v-else>未确认</text>
+            </text>
+          </view>
+        </view>
+        <view class="c" v-if="businessItem.confirm==1">
+          <view class="item">
+            <text class="p1">确认时间:</text>
+            <text class="p2">
+              <text>{{ businessItem.confirmTime }}</text>
+            </text>
+          </view>
+        </view>
+      </view>
+    </view>
+    <noData v-if="items.length==0"></noData>
+    <u-loadmore style="margin: 30rpx;" :status="status"/>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      customerId: '',
+      form: {},
+      items: [],
+      status: 'loadmore',
+      p: {
+        pageNo: 1,
+        pageSize: 3,
+        dataCount: 0
+      },
+    }
+  },
+  onShow() {
+    this.getPartnerBusinessItem();
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index')
+    return true;
+  },
+  methods: {
+    getPartnerBusinessItem() {
+      this.$api.getPartnerBusinessItem(this.p).then(resp => {
+        this.status = 'loadmore';
+        this.p.pageNo = resp.pageNo;
+        this.p.pageSize = resp.pageSize;
+        this.p.dataCount = resp.dataCount;
+        this.items = resp.data;
+      })
+    },
+    //上拉加载更多,分页模拟数据
+    onReachBottom() {
+      if (parseInt(this.p.dataCount) > parseInt(this.p.pageSize) * parseInt(this.p.pageNo)) {
+        this.status = 'loading';
+        this.p.pageSize += 5;
+        this.getPartnerBusinessItem();
+      } else {
+        this.status = 'nomore';
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 35rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 30rpx 0;
+      display: flex;
+      flex-wrap: wrap;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .item {
+        padding: 20rpx 0;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 38rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+
+      .btn {
+        height: 70rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: calc(100% - 15rpx);
+        margin: 30rpx 0 0 0;
+        border-radius: 10rpx;
+        border-width: 1rpx;
+        box-sizing: border-box;
+      }
+
+      .b1 {
+        background-color: #0080ff;
+        color: #fff;
+      }
+
+      .b2 {
+        background-color: #f7f7f7;
+        color: #191919;
+      }
+
+      .b3 {
+        background-color: #fff;
+        color: #0080ff;
+        border: 1rpx solid #0080ff;
+      }
+
+      .b4 {
+        background-color: #ff0000;
+        color: #fff;
+      }
+    }
+  }
+}
+
+@import '@/common/common.scss'
+</style>

+ 211 - 0
app-ui/pages/business-order/report.vue

@@ -0,0 +1,211 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">证明上传</text>
+      </view>
+      <view class="item">
+        <view class="l">核酸证明:</view>
+        <view class="r">
+          <view class="img">
+            <uni-file-picker v-model="nucleicReport" fileMediatype="image" mode="grid" limit="1"
+                             @select="nucleicSelect" @delete="form.nucleicReport=''" :image-styles="imageStyles"/>
+          </view>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">消杀合格证明:</view>
+        <view class="r">
+          <view class="img">
+            <uni-file-picker v-model="disinfectReport" fileMediatype="image" mode="grid" limit="1"
+                             @select="disinfectSelect" @delete="form.disinfectReport=''" :image-styles="imageStyles"/>
+          </view>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">检验检疫证:</view>
+        <view class="r">
+          <view class="img">
+            <uni-file-picker ref="checkReport" v-model="checkReport" fileMediatype="image" mode="grid"
+                             limit="1" @select="checkSelect" @delete="form.checkReport=''" :image-styles="imageStyles"/>
+          </view>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">签发出库证明:</view>
+        <view class="r">
+          <view class="img">
+            <uni-file-picker v-model="outReport" fileMediatype="image" mode="grid" limit="1"
+                             @select="outSelect" @delete="form.outReport=''" :image-styles="imageStyles"/>
+          </view>
+        </view>
+      </view>
+    </view>
+    <u-button type="primary" @click="confirmFn">保存</u-button>
+  </view>
+</template>
+
+<script>
+import request from '../../utils/request.js'
+
+export default {
+  data() {
+    return {
+      id: '',
+      form: {
+        partMoney: 0
+      },
+      imgList: [],
+      outReport: [],
+      checkReport: [],
+      disinfectReport: [],
+      nucleicReport: [],
+      imageStyles: {
+        width: 150,
+        height: 100,
+        border: {
+          color: "#eee",
+          width: 1,
+          style: 'dashed',
+          radius: '5px'
+        }
+      },
+      uploadImageUrl: request.server + '/upload/image',
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+    this.getBusinessById();
+  },
+
+  methods: {
+    toast() {
+      let obj = {
+        outReport: this.form.outReport,
+        checkReport: this.form.checkReport,
+        disinfectReport: this.form.disinfectReport,
+        nucleicReport: this.form.nucleicReport,
+      }
+      this.$common.toast(JSON.stringify(obj))
+    },
+    outSelect(e) {
+      let that = this;
+      uni.uploadFile({
+        url: that.uploadImageUrl,
+        filePath: e.tempFilePaths[0],
+        name: 'file',
+        success: (resp => {
+          that.form.outReport = JSON.parse(resp.data).data;
+        })
+      })
+    },
+    checkSelect(e) {
+      let that = this;
+      uni.uploadFile({
+        url: that.uploadImageUrl,
+        filePath: e.tempFilePaths[0],
+        name: 'file',
+        success: (resp => {
+          that.form.checkReport = JSON.parse(resp.data).data;
+        })
+      })
+    },
+    disinfectSelect(e) {
+      let that = this;
+      uni.uploadFile({
+        url: that.uploadImageUrl,
+        filePath: e.tempFilePaths[0],
+        name: 'file',
+        success: (resp => {
+          that.form.disinfectReport = JSON.parse(resp.data).data;
+        })
+      })
+    },
+    nucleicSelect(e) {
+      let that = this;
+      uni.uploadFile({
+        url: that.uploadImageUrl,
+        filePath: e.tempFilePaths[0],
+        name: 'file',
+        success: (resp => {
+          that.form.nucleicReport = JSON.parse(resp.data).data;
+        })
+      })
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+        if (this.form.nucleicReport) {
+          this.nucleicReport = [{
+            'name': 'payTicket.png',
+            'extname': '.png',
+            'url': this.form.nucleicReport
+          }]
+        }
+        if (this.form.disinfectReport) {
+          this.disinfectReport = [{
+            'name': 'payTicket.png',
+            'extname': '.png',
+            'url': this.form.disinfectReport
+          }]
+        }
+        if (this.form.checkReport) {
+          this.checkReport = [{
+            'name': 'payTicket.png',
+            'extname': '.png',
+            'url': this.form.checkReport
+          }]
+        }
+        if (this.form.outReport) {
+          this.outReport = [{
+            'name': 'payTicket.png',
+            'extname': '.png',
+            'url': this.form.outReport
+          }]
+        }
+      })
+    },
+    confirmFn() {
+      console.log(this.form)
+      if (!this.form.nucleicReport) {
+        this.$common.toast('请上传核酸报告');
+        return;
+      }
+      if (!this.form.disinfectReport) {
+        this.$common.toast('请上传消杀合格证明');
+        return;
+      }
+      if (!this.form.checkReport) {
+        this.$common.toast('请上传入关检验检疫证');
+        return;
+      }
+      if (!this.form.outReport) {
+        this.$common.toast('请上传签发出库证明');
+        return;
+      }
+      this.$api.uploadReport(this.form).then(Resp => {
+        this.$common.toast('上传成功');
+        setTimeout(() => {
+          this.$common.back()
+        }, 500)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+@import '@/common/common.scss'
+</style>

+ 86 - 0
app-ui/pages/business-order/sureIn.vue

@@ -0,0 +1,86 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="item">
+        <view class="l">订单号:</view>
+        <view class="r">
+          {{ form.no }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          境外车入场时间:
+        </view>
+        <view class="r">
+          <uni-datetime-picker placeholder="入场时间" type="datetime" v-model="form.realInTime"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          中国车入场时间:
+        </view>
+        <view class="r">
+          <uni-datetime-picker placeholder="入场时间" type="datetime" v-model="form.chinaCarInTime"/>
+        </view>
+      </view>
+    </view>
+    <u-button type="primary" @click="confirmFn">确认</u-button>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: '',
+      form: {
+        realInTime: new Date(),
+        chinaCarInTime: new Date()
+      },
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  onShow() {
+    this.getBusinessById();
+  },
+  methods: {
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+      })
+    },
+    confirmFn() {
+      let realInTime = this.form.realInTime;
+      let chinaCarInTime = this.form.chinaCarInTime;
+      if (!realInTime || realInTime.length <= 12) {
+        this.$common.toast('境外车入场时间不正确')
+        return;
+      }
+      if (!chinaCarInTime || chinaCarInTime.length <= 12) {
+        this.$common.toast('中国车入场时间不正确')
+        return;
+      }
+      this.$api.adminSetIn(this.form).then(Resp => {
+        this.$common.toast('操作成功');
+        setTimeout(() => {
+          this.$common.back()
+        }, 500)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+@import '@/common/common.scss'
+</style>

+ 99 - 0
app-ui/pages/business-order/sureOrder.vue

@@ -0,0 +1,99 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="item">
+        <view class="l">订单号:</view>
+        <view class="r">
+          {{ form.no }}
+        </view>
+      </view>
+      <view class="item-line">
+        业务项
+      </view>
+      <view class="item" v-for="item in form.items" :key="item.id">
+        <view class="l" style="flex: 7;">{{ item.itemTypeName }}:</view>
+        <view class="r">
+          {{ item.itemName }}({{ item.itemPrice }}x{{ item.num }}={{ item.total }}元)
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">业务费:</view>
+        <view class="r">
+          {{ form.itemPrice }}
+          <text>(元)</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">境外车停车费:</view>
+        <view class="r">
+          {{ form.partMoney }}
+          <text>(元)</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">中国车停车费:</view>
+        <view class="r">
+          {{ form.chinaPartMoney }}
+          <text>(元)</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">合计费用:</view>
+        <view class="r">
+          {{ form.totalMoney }}元
+        </view>
+      </view>
+    </view>
+    <u-button type="primary" @click="confirmFn">马上支付</u-button>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: '',
+      form: {
+        partMoney: 0
+      },
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  onShow() {
+    this.getBusinessById();
+  },
+  methods: {
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+      })
+    },
+    confirmFn() {
+      this.$api.confirmBusiness({ids: this.form.id}).then(Resp => {
+        this.$common.toast('已确认');
+        setTimeout(() => {
+          this.$common.back()
+        }, 500)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+@import '@/common/common.scss'
+</style>

+ 93 - 0
app-ui/pages/business-order/sureOut.vue

@@ -0,0 +1,93 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="item">
+        <view class="l">客户名称:</view>
+        <view class="r">
+          {{ form.customerName }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">订单号:</view>
+        <view class="r">
+          {{ form.no }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          境外车离场:
+        </view>
+        <view class="r">
+          <uni-datetime-picker placeholder="离场时间" :start="new Date().getTime()" type="datetime"
+                               v-model="form.outDayTime"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          中国车离场:
+        </view>
+        <view class="r">
+          <uni-datetime-picker placeholder="离场时间" :start="new Date().getTime()" type="datetime"
+                               v-model="form.chinaCarOutTime"/>
+        </view>
+      </view>
+    </view>
+    <u-button type="primary" @click="confirmFn">确认</u-button>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: '',
+      form: {
+        partMoney: 0
+      },
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  onShow() {
+    this.getBusinessById();
+  },
+  methods: {
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+        this.form.outDayTime = '';
+        this.form.chinaCarOutTime = '';
+      })
+    },
+    confirmFn() {
+      if (!this.form.outDayTime || this.form.outDayTime.length <= 12) {
+        this.$common.toast('请选择境外车出场时间')
+        return;
+      }
+      if (!this.form.chinaCarOutTime || this.form.chinaCarOutTime.length <= 12) {
+        this.$common.toast('请选择中国车出场时间')
+        return;
+      }
+      this.$api.adminSetOut(this.form).then(Resp => {
+        this.$common.toast('操作成功');
+        setTimeout(() => {
+          this.$common.back()
+        }, 500)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+@import '@/common/common.scss'
+</style>

+ 151 - 0
app-ui/pages/business-order/surePay.vue

@@ -0,0 +1,151 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="item">
+        <view class="l">订单号:</view>
+        <view class="r">
+          {{ form.no }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">业务费用:</view>
+        <view class="r">
+          {{ form.itemPrice }}元
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">停车费用:</view>
+        <view class="r">
+          <text>{{ form.partMoney + form.chinaPartMoney }}元</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">合计费用:</view>
+        <view class="r">
+          {{ form.totalMoney }}元
+        </view>
+      </view>
+      <view class="item">
+        <u-radio-group v-model="form.payType" placement="column" @change="groupChange">
+          <u-radio :customStyle="{marginBottom: '8px'}" v-for="(item, index) in payTypeList" :key="index"
+                   :label="item.name" :name="item.value" @change="radioChange">
+          </u-radio>
+        </u-radio-group>
+      </view>
+      <!-- 	<view class="item">
+        <view class="l">支付凭据:</view>
+        <view class="r">
+          <view class="img">
+            <uni-file-picker v-model="imageValue" fileMediatype="image" mode="grid" limit="1"
+              @select="select" @progress="progress" @success="success" @fail="fail"
+              @delete="form.payTicket=''" :image-styles="imageStyles" />
+          </view>
+        </view>
+      </view> -->
+    </view>
+    <u-button type="primary" @click="confirmFn">确认支付</u-button>
+  </view>
+</template>
+
+<script>
+import request from '../../utils/request.js'
+
+export default {
+  data() {
+    return {
+      id: '',
+      imageValue: [],
+      imageStyles: {
+        width: 150,
+        height: 100,
+        border: {
+          color: "#eee",
+          width: 1,
+          style: 'dashed',
+          radius: '5px'
+        }
+      },
+      payTypeList: [{
+        name: '微信支付',
+        value: 3
+      }],
+      form: {
+        partMoney: 0,
+        payType: 3
+      },
+      imgList: [],
+      uploadImageUrl: request.server + '/upload/image',
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  onShow() {
+    this.getBusinessById();
+  },
+  methods: {
+    // 获取上传状态
+    select(e) {
+      let that = this;
+      uni.uploadFile({
+        url: that.uploadImageUrl,
+        filePath: e.tempFilePaths[0],
+        name: 'file',
+        success: (resp => {
+          that.form.payTicket = JSON.parse(resp.data).data;
+        })
+      })
+    },
+    deleteFn(v) {
+      console.log(v)
+    },
+    // 获取上传进度
+    progress(e) {
+      console.log('上传进度:', e)
+    },
+
+    // 上传成功
+    success(e) {
+      console.log('上传成功')
+    },
+
+    // 上传失败
+    fail(e) {
+      console.log('上传失败:', e)
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+        this.form.payType = 3
+        if (this.form.payTicket) {
+          this.imageValue = [{
+            'name': 'payTicket.png',
+            'extname': '.png',
+            'url': this.form.payTicket
+          }]
+        }
+      })
+    },
+    confirmFn() {
+      this.$api.getPrePay({
+        no: this.form.no
+      }).then(resp => {
+        if (resp.code != 200) {
+          this.$common.toast('支付异常');
+        }
+        window.location.href = resp.data.payUrl;
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+@import '@/common/common.scss'
+</style>

+ 85 - 0
app-ui/pages/choose-business/choose-business.vue

@@ -0,0 +1,85 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">选择业务</text>
+      </view>
+      <view v-for="(yewuItem,index) in yewuItemList" :key="index">
+        <label class="c-item">
+          <view class="l">
+            <checkbox class="cb" color="#0080ff"/>
+          </view>
+          <view class="c">{{ yewuItem.text1 }}</view>
+          <view class="r">{{ yewuItem.text2 }}</view>
+        </label>
+      </view>
+    </view>
+    <view class="common-btn">录入确认</view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      yewuItemList: [{
+        text1: '入场管理费用',
+        text2: '34元'
+      },
+        {
+          text1: '定车费用',
+          text2: '10元'
+        },
+        {
+          text1: '装卸费用',
+          text2: '52元'
+        },
+        {
+          text1: '核算费用',
+          text2: '42元'
+        },
+        {
+          text1: '吊装费用',
+          text2: '124元'
+        },
+      ]
+    }
+  },
+  methods: {}
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.c-item {
+  display: flex;
+  align-items: center;
+  margin: 15rpx 30rpx;
+  padding: 40rpx 30rpx;
+  border-radius: 10rpx;
+  background-color: #fff;
+  border: 1rpx solid #f5f5f5;
+
+  .l {
+  }
+
+  .c {
+    font-size: 30rpx;
+    color: #191919;
+    font-weight: bold;
+    margin-left: 20rpx;
+  }
+
+  .r {
+    font-size: 30rpx;
+    color: #ff4200;
+    font-weight: bold;
+    margin-left: auto;
+  }
+}
+
+@import '@/common/common.scss'
+</style>

+ 165 - 0
app-ui/pages/customer-management/customer-info.vue

@@ -0,0 +1,165 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">信息管理</text>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          企业名称:
+        </view>
+        <view class="r">
+          <u-input v-model="form.name" placeholder="输入企业名称"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          联系人:
+        </view>
+        <view class="r">
+          <u-input v-model="form.dutyPeople" placeholder="输入联系人"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          联系电话:
+        </view>
+        <view class="r">
+          <u-input maxlength="11" v-model="form.phone" placeholder="输入电话号码"/>
+        </view>
+      </view>
+      <view class="item" v-if="form.type==='0'">
+        <view class="l">结算方式:</view>
+        <view class="r">
+          <radio-group @change="payChange">
+            <label class="radio">
+              <radio value="1" :disabled="customerId!=='1'" :checked="form.payType==1"/>
+              现结
+            </label>
+            <label class="radio" style="margin-left: 20rpx;">
+              <radio value="2" :disabled="customerId!=='1'" :checked="form.payType==2"/>
+              月结
+            </label>
+          </radio-group>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">营业执照:</view>
+        <view class="r">
+          <view class="img">
+            <uni-file-picker v-model="imageValue" fileMediatype="image" mode="grid" limit="1"
+                             @select="select"
+                             @delete="form.businessLicence=''" :image-styles="imageStyles"/>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="common-btn" @click="confirm">确认</view>
+  </view>
+</template>
+
+<script>
+import request from '../../utils/request.js'
+
+export default {
+  data() {
+    return {
+      imgList: [],
+      imageValue: [],
+      imageStyles: {
+        width: 150,
+        height: 100,
+        border: {
+          color: "#eee",
+          width: 1,
+          style: 'dashed',
+          radius: '5px'
+        }
+      },
+      uploadImageUrl: request.server + '/upload/image',
+      form: {
+        name: '',
+        dutyPeople: '',
+        phone: '',
+        payType: '1',
+        businessLicence: ''
+      },
+      customerId: ''
+    }
+  },
+  mounted() {
+    let id = uni.getStorageSync('userInfo').customerId;
+    this.customerId = id;
+    this.getCustomerById(id);
+  },
+  methods: {
+    select(e) {
+      let that = this;
+      uni.uploadFile({
+        url: that.uploadImageUrl,
+        filePath: e.tempFilePaths[0],
+        name: 'file',
+        success: (resp => {
+          console.log(JSON.parse(resp.data).data)
+          that.form.businessLicence = JSON.parse(resp.data).data;
+        })
+      })
+    },
+    getCustomerById(id) {
+      this.$api.getCustomerById({
+        id: id
+      }).then(resp => {
+        this.form = resp.data;
+        if (this.form.businessLicence) {
+          this.imageValue = [{
+            'name': 'payTicket.png',
+            'extname': '.png',
+            'url': this.form.businessLicence
+          }]
+        }
+      })
+    },
+    payChange(e) {
+      this.form.payType = e.detail.value
+    },
+    check() {
+      if (!this.form.name) {
+        this.$common.toast('请录入名称');
+        return false;
+      }
+      if (!this.form.dutyPeople) {
+        this.$common.toast('请录入联系人');
+        return false;
+      }
+      if (!this.$common.isPhone(this.form.phone)) {
+        this.$common.toast('联系号码不正确');
+        return false;
+      }
+      return true;
+    },
+    confirm() {
+      if (this.check()) {
+        this.$api.editCustomer(this.$common.removeNull(this.form)).then(resp => {
+          if (resp.code == 200) {
+            this.$common.toast('修改成功');
+            setTimeout(() => {
+              this.$common.back();
+            }, 1000)
+          }
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+@import '@/common/common.scss'
+</style>

+ 78 - 0
app-ui/pages/customer-management/customer-judge.vue

@@ -0,0 +1,78 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">企业审核</text>
+      </view>
+      <view class="item">
+        <view class="l">企业名称:</view>
+        <view class="r">
+          {{ form.name }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">审核意见:</view>
+        <view class="r">
+          <u-input v-model="form.judgeContent" placeholder="输入审核意见"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">审核结果:</view>
+        <view class="r">
+          <radio-group @change="statusChange">
+            <label class="radio">
+              <radio value="2" checked/>
+              通过
+            </label>
+            <label class="radio" style="margin-left: 20rpx;">
+              <radio value="3"/>
+              不通过
+            </label>
+          </radio-group>
+        </view>
+      </view>
+    </view>
+    <view class="common-btn" @click="confirm">确认</view>
+  </view>
+</template>
+
+<script>
+
+export default {
+  data() {
+    return {
+      form: {
+        id: '',
+        name: '',
+        judgeContent: '',
+        judgeStatus: '2'
+      },
+    }
+  },
+  onLoad(options) {
+    this.form = options;
+    this.form.judgeStatus = 2;
+  },
+  methods: {
+    statusChange(val) {
+      this.form.judgeStatus = val.detail.value;
+    },
+    confirm() {
+      if (!this.form.judgeContent && this.form.judgeStatus == '3') {
+        this.$common.toast('请输入审核意见')
+      }
+      this.$api.judgeCustomer(this.form).then(resp => {
+        this.$common.back();
+      })
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+@import '@/common/common.scss'
+</style>

+ 33 - 0
app-ui/pages/customer-management/customer-list.vue

@@ -0,0 +1,33 @@
+<template>
+  <management v-if="customerId=='1'" ref="manage"></management>
+  <info v-else ref="sel"></info>
+</template>
+
+<script>
+import info from './customer-info.vue'
+import management from './customer-management.vue'
+
+export default {
+  components: {
+    info, management
+  },
+  data() {
+    return {
+      customerId: ''
+    }
+  },
+  onReachBottom() {
+    let customerId = this.customerId;
+    if (customerId == '1') {
+      this.$refs.manage.loadMore();
+    }
+  },
+  onShow() {
+    this.customerId = uni.getStorageSync('info').customerId;
+  },
+  methods: {}
+}
+</script>
+
+<style>
+</style>

+ 318 - 0
app-ui/pages/customer-management/customer-management.vue

@@ -0,0 +1,318 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">客户管理</text>
+      </view>
+    </view>
+    <view class="t-btn" @click="addCustomer()" v-if="perList.indexOf('tb-costomer-add')!==-1">+添加客户</view>
+    <u-sticky offset-top="0">
+      <u-tabs :list="tabs" @change="change" :current="current" :is-scroll="false"></u-tabs>
+    </u-sticky>
+    <view class="card-box">
+      <view class="card" v-for="(customerItem,index) in customerItemList" :key="index">
+        <view class="t">
+          <image class="icon" src="../../static/home-icon-01.png"></image>
+          <text class="title">{{ customerItem.name }}</text>
+        </view>
+        <view class="c">
+          <view class="item">
+            <text class="p1">
+              <text style="color: red;">*</text>
+              联系人:
+            </text>
+            <text class="p2">{{ customerItem.dutyPeople }}</text>
+          </view>
+          <view class="item">
+            <text class="p1">
+              <text style="color: red;">*</text>
+              联系电话:
+            </text>
+            <text class="p2">{{ customerItem.phone }}</text>
+          </view>
+          <view class="item">
+            <text class="p1">营业执照:</text>
+            <text class="p2">
+              <image class="licence" :src="customerItem.businessLicence"></image>
+            </text>
+          </view>
+          <view class="item">
+            <text class="p1">状态:</text>
+            <text class="p2">
+              <text v-if="customerItem.judgeStatus==1">未审核</text>
+              <text v-if="customerItem.judgeStatus==2">审核通过</text>
+              <text v-if="customerItem.judgeStatus==3">审核不通过</text>
+            </text>
+          </view>
+        </view>
+        <view class="b">
+          <view class="btn b1" v-if="customerItem.btnShow==1 " @click="sh(customerItem)">审核</view>
+        </view>
+      </view>
+    </view>
+    <!-- 没有数据时显示noData -->
+    <noData v-if="customerItemList.length==0"></noData>
+    <u-loadmore style="margin: 30rpx;" :status="status"/>
+    <uni-popup ref="shpopup" type="center">
+      <uni-popup-dialog mode="input" type="success" title="确定审核吗?" placeholder="请输审核意见" :duration="2000"
+                        @confirm="shconfirm"></uni-popup-dialog>
+    </uni-popup>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      current: 0,
+      pageNo: 1,
+      pageSize: 3,
+      dataCount: 0,
+      status: 'loadmore',
+      page: 0,
+      tabs: [{
+        name: '全部',
+      },
+        {
+          name: '未审核',
+        },
+        {
+          name: '审核通过',
+        },
+        {
+          name: '禁用',
+        }
+      ],
+      customerItemList: [],
+      confirmCustomerId: '',
+      judgeContent: '',
+      perList: []
+    }
+  },
+
+  methods: {
+    loadMore() {
+      this.status = 'loading';
+      if (this.dataCount > this.pageSize * this.pageNo) {
+        this.pageSize = parseInt(this.pageSize) + 3;
+        this.getCustomerList();
+      } else {
+        this.status = 'nomore';
+      }
+    },
+    getCustomerList() {
+      this.$api.getCustomerList({
+        current: this.current,
+        pageNo: this.pageNo,
+        pageSize: this.pageSize,
+        dataCount: this.dataCount,
+      }).then(resp => {
+        let customerList = resp.data;
+        for (let i in customerList) {
+          if (customerList[i].judgeStatus == 1) {
+            customerList[i].btnShow = 1;
+          }
+        }
+        this.dataCount = resp.dataCount;
+        this.pageNo = resp.pageNo;
+        this.customerItemList = customerList;
+        if (this.dataCount < this.pageSize * this.pageNo) this.status = 'nomore';
+      })
+    },
+    confirmCustomer() {
+      this.$api.confirmCustomer({
+        customerId: this.confirmCustomerId,
+        judgeContent: this.judgeContent,
+      }).then(resp => {
+        if (resp.code == 200) {
+          this.getCustomerList();
+        }
+      })
+    },
+    //点击上方切换栏,根据点击项重新加载数据
+    change(obj) {
+      console.log(obj);
+      this.current = obj.index;
+      this.getCustomerList();
+    },
+    //点击按钮
+    //------------------------------------------
+    sh(data) {
+      this.$common.to('/pages/customer-management/customer-judge?id=' + data.id + '&name=' + data.name)
+    },
+    shconfirm(val) {
+      this.judgeContent = val;
+      this.confirmCustomer();
+      this.$refs.shpopup.close()
+    },
+
+    addCustomer() {
+      this.$common.to("/pages/enterprise-reg/enterprise-reg");
+    },
+
+    //------------------------------------------
+    //上拉加载更多,分页模拟数据
+
+  },
+  onLoad() {
+    console.log(222)
+  },
+  created() {
+    this.perList = uni.getStorageSync('perList');
+    this.getCustomerList();
+  },
+  onShow() {
+
+  },
+}
+</script>
+
+<style lang="scss">
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 30rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 30rpx 0;
+      display: flex;
+      flex-wrap: wrap;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .item {
+        width: 50%;
+        padding: 20rpx 0;
+        display: flex;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 44rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+          letter-spacing: 20rpx;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+          flex: 5;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+          flex: 7;
+
+          .licence {
+            width: 80%;
+            height: 100rpx;
+          }
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+
+      .btn {
+        height: 70rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        //width: calc(50% - 15rpx);
+        width: 100%;
+        margin: 30rpx 0 0 0;
+        border-radius: 10rpx;
+        border-width: 1rpx;
+        box-sizing: border-box;
+      }
+
+      .b1 {
+        background-color: #0080ff;
+        color: #fff;
+      }
+
+      .b2 {
+        background-color: #f7f7f7;
+        color: #191919;
+      }
+
+      .b3 {
+        background-color: #fff;
+        color: #0080ff;
+        border: 1rpx solid #0080ff;
+      }
+    }
+  }
+}
+
+.t-btn {
+  width: 400rpx;
+  margin: 50rpx auto;
+  height: 88rpx;
+  font-weight: bold;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 10rpx;
+  color: #191919;
+  font-size: 28rpx;
+  background-color: #fff;
+  border: 1px solid #eee;
+}
+
+.popup-box {
+  text-align: center;
+  background-color: #fff;
+  height: 280rpx;
+  width: 560rpx;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 617 - 0
app-ui/pages/declare/add.vue

@@ -0,0 +1,617 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">申报单录入</text>
+      </view>
+      <view class="item" v-show="customerId=='1'">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报单位:
+        </view>
+        <view class="r">
+          <picker v-if="customer.customerList.length>0" class="p-picker" id="qy"
+                  @change="bindPickerChange($event)" :value="customer.index" :range="customer.customerList"
+                  range-key="name">
+            <text class="p-text">{{ customer.customerList[customer.index].name }}</text>
+            <u-icon class="p-icon" name="arrow-down-fill" size="20"></u-icon>
+          </picker>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报人:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报人" @input="handler()" v-model="form.declarePeople">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报电话:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报电话" type="number" @input="handler()" v-model="form.declarePhone">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          产品学名:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入产品学名" @input="handler()" v-model="form.goodsName">
+          </u-input>
+        </view>
+      </view>
+
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          毛重:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入毛重" @input="handler()" v-model="form.grossWeight">
+            <text slot="suffix">kg</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          件数:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入件数" @input="handler()" v-model="form.num">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          生产日期:
+        </view>
+        <view class="r">
+          <view class="r">
+            <uni-datetime-picker placeholder="请选择" :end="startDate" @input="handler()" :clear-icon="false"
+                                 type="date" v-model="form.productionDate"/>
+          </view>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          保质期(天):
+        </view>
+        <view class="r">
+          <view class="r">
+            <u-input placeholder="输入保质期" type="number" @input="handler()" v-model="form.expirationDate"/>
+          </view>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          储藏条件:
+        </view>
+        <view class="r">
+          <u-input placeholder="储存条件" @input="handler()" v-model="form.storageMode"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          生产方式:
+        </view>
+        <view class="r">
+          <u-input placeholder="生产方式" @input="handler()" v-model="form.productionMode"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          原产国:
+        </view>
+        <view class="r">
+          <u-input placeholder="原产国" @input="handler()" v-model="form.origin"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          货主单位:
+        </view>
+        <view class="r">
+          <u-input placeholder="货主单位" @input="handler()" v-model="form.sendUnit"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          生产商注册号:
+        </view>
+        <view class="r">
+          <u-input placeholder="生产商注册号" @input="handler()" v-model="form.producerCode"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          收货单位:
+        </view>
+        <view class="r">
+          <u-input placeholder="收货单位" @input="handler()" v-model="form.receiveUnit"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          货物流向:
+        </view>
+        <view class="r">
+          <u-input placeholder="货物流向" @input="handler()" v-model="form.route"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          运输车辆(车头牌):
+        </view>
+        <view class="r">
+          <u--textarea @input="handler()" v-model="form.chinaCarNo" placeholder="运输车车头牌,多个请用逗号隔开">
+          </u--textarea>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          运输车辆(车尾牌):
+        </view>
+        <view class="r">
+          <u--textarea @input="handler()" v-model="form.chinaCarSuff" placeholder="运输车车尾牌,多个请用逗号隔开">
+          </u--textarea>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          司机姓名:
+        </view>
+        <view class="r">
+          <u--textarea @input="handler()" v-model="form.driverName" placeholder="司机姓名,多个请用逗号隔开"></u--textarea>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          司机电话:
+        </view>
+        <view class="r">
+          <u--textarea @input="handler()" v-model="form.driverPhone" placeholder="司机电话,多个请用逗号隔开">
+          </u--textarea>
+        </view>
+      </view>
+
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          代理商电话:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="代理商电话" @input="handler()" v-model="form.agentPhone"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          海关报关单据:
+        </view>
+        <view class="r">
+          <u-input placeholder="海关报关单据" @input="handler()" v-model="form.customProof"/>
+        </view>
+      </view>
+
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          检验检疫证:
+        </view>
+        <view class="r">
+          <u-input placeholder="检验检疫证" @input="handler()" v-model="form.quarantineProof"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">商铺:</view>
+        <view class="r">
+          <u-input placeholder="商铺" @input="handler()" v-model="form.shop"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          生产批号:
+        </view>
+        <view class="r">
+          <u-input placeholder="生产批号" @input="handler()" v-model="form.productionCode"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          柜号:
+        </view>
+        <view class="r">
+          <u-input placeholder="柜号" @input="handler()" v-model="form.containerCode"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          越南车牌:
+        </view>
+        <view class="r">
+          <u-input placeholder="越南车牌" @input="handler()" v-model="form.carNo"/>
+        </view>
+      </view>
+
+    </view>
+    <u-button type="primary" text="确定" @click="saveFn"></u-button>
+    <u-button type="info" text="重置" @click="cleanFn" style="margin-top: 20rpx;"></u-button>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      customerId: '1',
+      customer: {
+        index: 0,
+        customerList: [],
+      },
+      startDate: new Date().getTime() - 24 * 60 * 60 * 1000,
+      form: {
+        declarePeople: '',
+        declarePhone: '',
+        goodsName: '',
+        grossWeight: '',
+        num: '',
+        productionDate: '',
+        expirationDate: '',
+        productionMode: '',
+        origin: '',
+        sendUnit: '',
+        producerCode: '',
+        receiveUnit: '',
+        route: '',
+        storageMode: '',
+        driverName: '',
+        driverPhone: '',
+        agent: '',
+        chinaCarNo: '',
+        chinaCarSuff: '',
+        carNo: '',
+        customProof: '',
+        quarantineProof: '',
+        shop: '',
+        productionCode: '',
+        containerCode: '',
+      },
+      perList: []
+    }
+  },
+  onShow() {
+    this.customerId = uni.getStorageSync('customerId');
+    this.perList = uni.getStorageSync('perList');
+  },
+
+  mounted() {
+    this.checkStore();
+    this.getCustomerList();
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index');
+    return true;
+  },
+  methods: {
+    getCustomerList() {
+      this.$api.getCustomerList({type: 0}).then(resp => {
+        this.customer.customerList = resp.data;
+      })
+    },
+    createModal() {
+      return {
+        declarePeople: '',
+        declarePhone: '',
+        goodsName: '',
+        grossWeight: '',
+        num: '',
+        productionDate: this.$common.forDate(new Date().getTime() - 24 * 60 * 60 * 1000, 1),
+        expirationDate: '',
+        productionMode: '',
+        origin: '',
+        sendUnit: '',
+        producerCode: '',
+        receiveUnit: '',
+        route: '',
+        storageMode: '',
+        driverName: '',
+        driverPhone: '',
+        agent: '',
+        chinaCarNo: '',
+        chinaCarSuff: '',
+        carNo: '',
+        customProof: '',
+        quarantineProof: '',
+        shop: '',
+        productionCode: '',
+        containerCode: ''
+      }
+    },
+    bindPickerChange(e) {
+      var value = e.detail.value; //当前picker选中的值
+      this.customer.index = value;
+      this.handler();
+    },
+    cleanFn() {
+      this.form = this.createModal();
+      this.cleanStore();
+      this.setInfo();
+    },
+    cleanStore() {
+      uni.removeStorageSync('declare')
+      uni.removeStorageSync('disinfect')
+    },
+    handler() {
+      let cacheObj = {
+        count: 0,
+        cache: this.form
+      }
+      uni.setStorageSync('info', {
+        declarePeople: this.form.declarePeople,
+        declarePhone: this.form.declarePhone
+      })
+      uni.setStorageSync('declare', cacheObj);
+    },
+    addStoreCount() {
+      let cacheObj = {
+        count: 1,
+        cache: this.form
+      }
+      uni.setStorageSync('declare', cacheObj);
+    },
+    setInfo() {
+      let info = uni.getStorageSync('info');
+      if (info) {
+        this.form.declarePeople = info.declarePeople;
+        this.form.declarePhone = info.declarePhone
+      }
+    },
+    checkStore() {
+      let store = uni.getStorageSync('declare');
+      this.setInfo();
+      if (store && store.count == 0) {
+        let that = this;
+        let cache = store.cache;
+        uni.showModal({
+          title: '提示',
+          content: '检测到您有未完成表单,是否继续?',
+          success(resp) {
+            if (resp.confirm) {
+              that.form = cache
+              if (!that.form.productionDate) {
+                that.form.productionDate = that.$common.forDate(new Date().getTime() - 24 *
+                    60 * 60 * 1000, 1)
+              }
+            } else {
+              that.cleanFn();
+            }
+          }
+        })
+      }
+      let disinfectStore = uni.getStorageSync('disinfect');
+      if (disinfectStore) {
+        let that = this;
+        let cache = disinfectStore.cache;
+        that.form.declarePeople = cache.declarePeople
+        that.form.declarePhone = cache.declarePhone
+        uni.showModal({
+          title: '提示',
+          content: '检测到最近有相似消杀申报信息,是否导入?',
+          success(resp) {
+            if (resp.confirm) {
+              that.form = cache
+            } else {
+              that.cleanFn();
+            }
+          }
+        })
+      }
+    },
+    saveFn() {
+      if (!this.form.declarePeople) {
+        this.$common.toast('请填写申报人');
+        return;
+      }
+      if (!this.$common.isPhone(this.form.declarePhone)) {
+        this.$common.toast('请填写正确的申报电话');
+        return;
+      }
+      if (!this.form.goodsName) {
+        this.$common.toast('请填写产品');
+        return;
+      }
+      if (!this.form.grossWeight || !this.$common.isNum(this.form.grossWeight)) {
+        this.$common.toast('毛重只能填写数字');
+        return;
+      }
+      if (!this.form.num || !this.$common.isNum(this.form.num)) {
+        this.$common.toast('件数只能填整数');
+        return;
+      }
+
+      if (!this.form.productionDate) {
+        this.$common.toast('请选择生产日期');
+        return;
+      }
+      if (!this.form.expirationDate || !this.$common.isNum(this.form.expirationDate)) {
+        this.$common.toast('保质期为正数');
+        return;
+      }
+      if (!this.form.storageMode) {
+        this.$common.toast('请填写储藏条件');
+        return;
+      }
+      if (!this.form.productionMode) {
+        this.$common.toast('请填写生产方式');
+        return;
+      }
+      if (!this.form.origin) {
+        this.$common.toast('请输入原产国');
+        return;
+      }
+      if (!this.form.sendUnit) {
+        this.$common.toast('请填写货主单位');
+        return;
+      }
+      if (!this.form.producerCode) {
+        this.$common.toast('请填写生产商注册号');
+        return;
+      }
+      if (!this.form.receiveUnit) {
+        this.$common.toast('请填写收货单位');
+        return;
+      }
+      if (!this.form.route) {
+        this.$common.toast('请填写货物流向');
+        return;
+      }
+      let chinaCarNo = this.form.chinaCarNo;
+      if (!chinaCarNo) {
+        this.$common.toast('请填写运输车辆车头牌');
+        return;
+      }
+      let noArray = chinaCarNo.replace(",", ",").split(",");
+      for (let i in noArray) {
+        noArray[i] = noArray[i].toUpperCase();
+        if (!this.$common.isCarNo(noArray[i])) {
+          this.$common.toast('运输车头牌不正确');
+          return;
+        }
+      }
+      let chinaCarSuff = this.form.chinaCarSuff;
+      if (!chinaCarSuff) {
+        this.$common.toast('请填写运输车辆车尾牌');
+        return;
+      }
+      let suffArray = chinaCarSuff.replace(",", ",").split(",");
+      for (let i in suffArray) {
+        suffArray[i] = suffArray[i].toUpperCase();
+        if (!this.$common.isCarNo(suffArray[i])) {
+          this.$common.toast('运输车尾牌不正确');
+          return;
+        }
+      }
+      if (!this.form.driverName) {
+        this.$common.toast('请填写司机姓名');
+        return;
+      }
+      let driverPhone = this.form.driverPhone;
+      if (!driverPhone) {
+        this.$common.toast('请填写司机号码');
+        return;
+      }
+      let phoneArray = driverPhone.replace(",", ",").split(",");
+      for (let i in phoneArray) {
+        let phone = phoneArray[i];
+        if (!this.$common.isPhone(phone)) {
+          this.$common.toast('司机联系号码不正确');
+          return;
+        }
+      }
+      if (!this.$common.isPhone(this.form.agentPhone)) {
+        this.$common.toast('代理商联系号码不正确');
+        return;
+      }
+      if (!this.form.customProof) {
+        this.$common.toast('海关报关单据');
+        return;
+      }
+      if (!this.form.quarantineProof) {
+        this.$common.toast('请填写检验检疫证');
+        return;
+      }
+      if (!this.form.productionCode) {
+        this.$common.toast('请填写生产批号');
+        return;
+      }
+      if (!this.form.containerCode) {
+        this.$common.toast('请填写柜号');
+        return;
+      }
+
+      if (!this.form.carNo) {
+        this.$common.toast('请填写越南车牌号');
+        return;
+      }
+      if (this.customerId == '1') {
+        this.form.customerId = this.customer.customerList[this.customer.index].id;
+      } else {
+        this.form.customerId = this.customerId;
+      }
+      this.$api.addDeclare(this.$common.removeNull(this.form)).then(resp => {
+        if (resp.code == 200) {
+          this.addStoreCount();
+          this.$common.to('/pages/declare/addDeclareSuccess')
+        }
+      })
+    },
+  },
+
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 63 - 0
app-ui/pages/declare/addDeclareSuccess.vue

@@ -0,0 +1,63 @@
+<template>
+  <view class="box">
+    <u-icon name="checkmark-circle-fill" color="#07c160" size="200"></u-icon>
+    <text class="text">申报信息提交成功!</text>
+    <view class="count-down-box">
+      <view @click="goDisifect" style="color: #007AFF;">消杀申报</view>
+    </view>
+    <view class="count-down-box">
+      <view @click="goback">返回</view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      timestamp: 3,
+    }
+  },
+  onBackPress() {
+    this.goback();
+    return true;
+  },
+  methods: {
+    goDisifect() {
+      this.$common.to('/pages/disinfect/addDisinfect');
+    },
+    goback() {
+      this.$common.to('/pages/declare/add');
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+  }
+}
+</style>

+ 499 - 0
app-ui/pages/disinfect/addDisinfect.vue

@@ -0,0 +1,499 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">消毒申报单录入</text>
+      </view>
+      <view class="item" v-show="customerId=='1'">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报单位:
+        </view>
+        <view class="r">
+          <picker v-if="customer.customerList.length>0" class="p-picker" id="qy"
+                  @change="bindPickerChange($event)" :value="customer.index" :range="customer.customerList"
+                  range-key="name">
+            <text class="p-text">{{ customer.customerList[customer.index].name }}</text>
+            <u-icon class="p-icon" name="arrow-down-fill" size="20"></u-icon>
+          </picker>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          发货人名称:
+        </view>
+        <view class="r">
+          <u-input placeholder="发货人名称" @input="handler()" v-model="form.sendPeople">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          收货人名称:
+        </view>
+        <view class="r">
+          <u-input placeholder="收货人名称" @input="handler()" v-model="form.receivePeople">
+          </u-input>
+        </view>
+      </view>
+
+
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          品名:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入品名" @input="handler()" v-model="form.goodsName">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          数量:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入数量" @input="handler()" v-model="form.num">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          重量:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="输入毛重" @input="handler()" v-model="form.grossWeight">
+            <text slot="suffix">kg</text>
+          </u-input>
+        </view>
+      </view>
+
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          产地:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入产地" @input="handler()" v-model="form.origin">
+          </u-input>
+        </view>
+      </view>
+
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          规格:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入规格" @input="handler()" v-model="form.unit">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          包装:
+        </view>
+        <view class="r">
+          <view class="r">
+            <u-input placeholder="输入包装" @input="handler()" v-model="form.pack"/>
+          </view>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          标记:
+        </view>
+        <view class="r">
+          <u-input placeholder="标记" @input="handler()" v-model="form.flag"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          号码:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="号码" @input="handler()" v-model="form.phone"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          启运地:
+        </view>
+        <view class="r">
+          <u-input placeholder="启运地" @input="handler()" v-model="form.sourceAddress"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          到货口岸:
+        </view>
+        <view class="r">
+          <u-input placeholder="到货口岸" @input="handler()" v-model="form.arrivePart"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          运输工具:
+        </view>
+        <view class="r">
+          <u-input placeholder="运输工具" @input="handler()" v-model="form.carName"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          工具号码:
+        </view>
+        <view class="r">
+          <u-input placeholder="运输工具号码" @input="handler()" v-model="form.carNo"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">
+          <text style="color: red;">*</text>
+          国内运输工具:
+        </view>
+        <view class="r">
+          <u-input placeholder="国内运输工具" @input="handler()" v-model="form.chinaCarName"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          工具号码:
+        </view>
+        <view class="r">
+          <u-input placeholder="工具号码" @input="handler()" v-model="form.chinaCarNo"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报人:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报人" @input="handler()" v-model="form.declarePeople">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          申报电话:
+        </view>
+        <view class="r">
+          <u-input type="number" placeholder="申报电话" @input="handler()" v-model="form.declarePhone">
+          </u-input>
+        </view>
+      </view>
+      <!-- <view class="item">
+        <view class="l"><text style="color: red;">*</text>申报单位:</view>
+        <view class="r">
+          <u-input placeholder="申报单位" @input="handler()" v-model="form.applyUnit">
+          </u-input>
+        </view>
+      </view> -->
+      <view class="item">
+        <view class="l" style="flex: 7;">其他要求:</view>
+        <view class="r">
+          <u--textarea @input="handler()" v-model="form.remark" placeholder="其他要求及备注">
+          </u--textarea>
+        </view>
+      </view>
+    </view>
+    <u-button type="primary" text="确定" @click="saveFn"></u-button>
+    <u-button type="info" text="重置" @click="cleanFn" style="margin-top: 20rpx;"></u-button>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      customerId: '1',
+      customer: {
+        index: 0,
+        customerList: [],
+      },
+      form: {
+        declarePeople: '',
+        declarePhone: '',
+        goodsName: '',
+        grossWeight: '',
+        num: '',
+        origin: '',
+        unit: '',
+        pack: '',
+        flag: '',
+        phone: '',
+        sourceAddress: '',
+        arrivePart: '',
+        carName: '',
+        carNo: '',
+        chinaCarName: '',
+        chinaCarNo: '',
+        remark: ''
+      },
+      perList: []
+    }
+  },
+  onShow() {
+    this.customerId = uni.getStorageSync('customerId');
+    this.perList = uni.getStorageSync('perList');
+  },
+
+  mounted() {
+    this.checkStore();
+    this.getCustomerList();
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index');
+    return true;
+  },
+  methods: {
+    createModal() {
+      return {
+        sendPeople: '',
+        receivePeople: '',
+        declarePeople: '',
+        declarePhone: '',
+        goodsName: '',
+        grossWeight: '',
+        num: '',
+        origin: '',
+        unit: '',
+        pack: '',
+        flag: '',
+        phone: '',
+        sourceAddress: '',
+        arrivePart: '',
+        carName: '',
+        carNo: '',
+        chinaCarName: '',
+        chinaCarNo: '',
+        remark: ''
+      }
+    },
+    getCustomerList() {
+      this.$api.getCustomerList({type: 0}).then(resp => {
+        this.customer.customerList = resp.data;
+      })
+    },
+    bindPickerChange(e) {
+      var value = e.detail.value; //当前picker选中的值
+      this.customer.index = value;
+      this.handler();
+    },
+    cleanFn() {
+      this.form = this.createModal();
+      this.cleanStore();
+      this.setInfo();
+    },
+    cleanStore() {
+      uni.removeStorageSync('disinfect')
+      uni.removeStorageSync('declare')
+    },
+    handler() {
+      let cacheObj = {
+        count: 0,
+        cache: this.form
+      }
+      uni.setStorageSync('info', {
+        declarePeople: this.form.declarePeople,
+        declarePhone: this.form.declarePhone
+      })
+      uni.setStorageSync('disinfect', cacheObj);
+    },
+    addStoreCount() {
+      let cacheObj = {
+        count: 1,
+        cache: this.form
+      }
+      uni.setStorageSync('disinfect', cacheObj);
+    },
+    setInfo() {
+      let info = uni.getStorageSync('info');
+      if (info) {
+        this.form.declarePeople = info.declarePeople;
+        this.form.declarePhone = info.declarePhone
+      }
+    },
+    checkStore() {
+      this.setInfo();
+      let disinfectStore = uni.getStorageSync('disinfect');
+      if (disinfectStore && disinfectStore.count == 0) {
+        let that = this;
+        let cache = disinfectStore.cache;
+        uni.showModal({
+          title: '提示',
+          content: '检测到您有未完成表单,是否继续?',
+          success(resp) {
+            if (resp.confirm) {
+              that.form = cache
+            } else {
+              that.cleanFn();
+            }
+          }
+        })
+      }
+      let declareStore = uni.getStorageSync('declare');
+      if (declareStore) {
+        let that = this;
+        let cache = declareStore.cache;
+        that.form.declarePeople = cache.declarePeople
+        that.form.declarePhone = cache.declarePhone
+        uni.showModal({
+          title: '提示',
+          content: '检测到最近有相似申报信息,是否导入?',
+          success(resp) {
+            if (resp.confirm) {
+              that.form = cache;
+            } else {
+              that.cleanFn();
+            }
+          }
+        })
+      }
+    },
+    saveFn() {
+      if (!this.check()) {
+        return;
+      }
+      if (this.customerId == '1') {
+        this.form.customerId = this.customer.customerList[this.customer.index].id;
+      } else {
+        this.form.customerId = this.customerId;
+      }
+      this.$api.addDisinfect(this.$common.removeNull(this.form)).then(resp => {
+        if (resp.code == 200) {
+          this.addStoreCount();
+          this.$common.to('/pages/disinfect/addDisinfectSuccess')
+        }
+      })
+    },
+    check() {
+      if (!this.form.sendPeople) {
+        this.$common.toast('请填写发货人信息');
+        return false;
+      }
+      if (!this.form.receivePeople) {
+        this.$common.toast('请填写接货人信息');
+        return false;
+      }
+      if (!this.form.goodsName) {
+        this.$common.toast('请填写品名');
+        return false;
+      }
+      if (!this.$common.isNum(this.form.num)) {
+        this.$common.toast('数量请填写数字');
+        return false;
+      }
+      if (!this.$common.isNum(this.form.grossWeight)) {
+        this.$common.toast('请填写重量');
+        return false;
+      }
+      if (!this.form.origin) {
+        this.$common.toast('请填写原产地');
+        return false;
+      }
+      if (!this.form.pack) {
+        this.$common.toast('请填写包装');
+        return false;
+      }
+      if (!this.form.flag) {
+        this.$common.toast('请填写标记');
+        return false;
+      }
+      if (!this.form.phone) {
+        this.$common.toast('请填写号码');
+        return false;
+      }
+      if (!this.form.sourceAddress) {
+        this.$common.toast('请填写启运地');
+        return false;
+      }
+      if (!this.form.arrivePart) {
+        this.$common.toast('请填写到货口岸');
+        return false;
+      }
+      if (!this.form.carName) {
+        this.$common.toast('请填写运输工具');
+        return false;
+      }
+      if (!this.form.carNo) {
+        this.$common.toast('请填写工具号码');
+        return false;
+      }
+      if (!this.form.chinaCarName) {
+        this.$common.toast('请填写国内运输工具');
+        return false;
+      }
+      if (!this.form.chinaCarNo) {
+        this.$common.toast('请填写国内运输工具号码');
+        return false;
+      }
+      if (!this.form.declarePeople) {
+        this.$common.toast('请填写申请人');
+        return false;
+      }
+      if (!this.$common.isPhone(this.form.declarePhone)) {
+        this.$common.toast('请填写正确申请电话');
+        return false;
+      }
+      return true;
+    }
+  },
+
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 68 - 0
app-ui/pages/disinfect/addDisinfectSuccess.vue

@@ -0,0 +1,68 @@
+<template>
+  <view class="box">
+    <u-icon name="checkmark-circle-fill" color="#07c160" size="200"></u-icon>
+    <text class="text">消毒申报信息提交成功!</text>
+    <view class="count-down-box">
+      <view @click="goDeclare" style="color: #007AFF;">申报录入</view>
+    </view>
+    <view class="count-down-box">
+      <text @click="goback">返回</text>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      timestamp: 3,
+    }
+  },
+  onBackPress() {
+    this.goback();
+    return true;
+  },
+  methods: {
+    goDeclare() {
+      this.$common.to('/pages/declare/add');
+    },
+    goback() {
+      this.$common.to('/pages/disinfect/addDisinfect');
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    flex: 1;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+
+    text {
+      margin-left: 20rpx;
+    }
+  }
+}
+</style>

+ 169 - 0
app-ui/pages/enterprise-reg/enterprise-reg.vue

@@ -0,0 +1,169 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">企业注册</text>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          企业名称:
+        </view>
+        <view class="r">
+          <u-input v-model="form.name" placeholder="输入企业名称"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          联系人:
+        </view>
+        <view class="r">
+          <u-input v-model="form.dutyPeople" placeholder="输入联系人"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          联系电话:
+        </view>
+        <view class="r">
+          <u-input maxlength="11" v-model="form.phone" placeholder="输入电话号码"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">结算方式:</view>
+        <view class="r">
+          <radio-group @change="payChange">
+            <label class="radio">
+              <radio value="1" checked/>
+              现结
+            </label>
+            <label class="radio" style="margin-left: 20rpx;">
+              <radio value="2"/>
+              月结
+            </label>
+          </radio-group>
+        </view>
+      </view>
+      <!-- 	<view class="item">
+        <view class="l">验证码:</view>
+        <view class="r">
+          <u-input placeholder="输入验证码"/>
+          <view class="btn">发送</view>
+        </view>
+      </view> -->
+      <view class="item">
+        <view class="l">营业执照:</view>
+        <view class="r">
+          <view class="img">
+            <uni-file-picker v-model="imageValue" fileMediatype="image" mode="grid" limit="1"
+                             @select="select" @progress="progress" @success="success" @fail="fail"
+                             @delete="form.businessLicence=''" :image-styles="imageStyles"/>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="common-btn" @click="confirm">确认注册</view>
+  </view>
+</template>
+
+<script>
+import request from '../../utils/request.js'
+
+export default {
+  data() {
+    return {
+      imgList: [],
+      imageValue: [],
+      imageStyles: {
+        width: 150,
+        height: 100,
+        border: {
+          color: "#eee",
+          width: 1,
+          style: 'dashed',
+          radius: '5px'
+        }
+      },
+      imgList: [],
+      uploadImageUrl: request.server + '/upload/image',
+      form: {
+        name: '',
+        dutyPeople: '',
+        phone: '',
+        payType: '1',
+        businessLicence: ''
+      }
+    }
+  },
+  methods: {
+    // 获取上传状态
+    select(e) {
+      let that = this;
+      uni.uploadFile({
+        url: that.uploadImageUrl,
+        filePath: e.tempFilePaths[0],
+        name: 'file',
+        success: (resp => {
+          that.form.businessLicence = JSON.parse(resp.data).data;
+        })
+      })
+    },
+    // 获取上传进度
+    progress(e) {
+      console.log('上传进度:', e)
+    },
+
+    // 上传成功
+    success(e) {
+      console.log('上传成功')
+    },
+
+    // 上传失败
+    fail(e) {
+      console.log('上传失败:', e)
+    },
+    payChange(e) {
+      this.form.payType = e.detail.value
+    },
+    check() {
+      if (!this.form.name) {
+        this.$common.toast('请录入名称');
+        return false;
+      }
+      if (!this.form.dutyPeople) {
+        this.$common.toast('请录入联系人');
+        return false;
+      }
+      if (!this.$common.isPhone(this.form.phone)) {
+        this.$common.toast('联系号码不正确');
+        return false;
+      }
+      if (!this.form.businessLicence) {
+        this.$common.toast('请上传营业执照');
+        return false;
+      }
+
+      return true;
+    },
+    confirm() {
+      if (this.check()) {
+        this.$api.register(this.form).then(resp => {
+          if (resp.code == 200) {
+            this.$common.to('/pages/ok/registerSuccess')
+          }
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+@import '@/common/common.scss'
+</style>

+ 68 - 0
app-ui/pages/home/home.vue

@@ -0,0 +1,68 @@
+<template>
+  <view class="box">
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: ''
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  created() {
+    this.$common.showLoading('正在加载...')
+  },
+  mounted() {
+    this.getRedirectUri();
+  },
+  beforeDestroy() {
+    this.$common.hidingLoading()
+  },
+  methods: {
+    getRedirectUri() {
+      this.$api.getRedirectUrl({path: '/pages/index/index', state: this.id}).then(resp => {
+        window.location.href = resp.data;
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    flex: 1;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+
+    text {
+      margin-left: 20rpx;
+    }
+  }
+}
+</style>

+ 495 - 0
app-ui/pages/index/index.vue

@@ -0,0 +1,495 @@
+<template>
+  <view>
+    <view class="top-nav">
+      <view class="l">
+        <block v-if="isLogin">
+          <image class="user-img" src="../../static/user.png" @click="toAccount"></image>
+          <view class="l-r">
+            <text class="u-name">{{ userName }}</text>
+            <text class="c-name" v-if="customerId!=='1'">{{ companyName }}</text>
+          </view>
+        </block>
+        <block v-else>
+          <view class="login-btn" @click="toLogin">登录</view>
+        </block>
+      </view>
+      <view class="r" v-if="isLogin">
+        <view class="l-out" @click="exitFn">
+          退出登录
+        </view>
+      </view>
+    </view>
+    <view class="top-bg"></view>
+    <view class="top">
+      <text class="title">场站管理系统</text>
+    </view>
+    <view class="item-box">
+      <view class="item" hover-class="hover-class" v-for="(indexItem,index) in indexItemList" :key="index"
+            @click="navTo(indexItem)" v-if="checkPer(indexItem.id)||indexItem.customer">
+        <image class="icon" :src="indexItem.icon"></image>
+        <view class="text">
+          <text v-if="indexItem.text=='企业管理'&&customerId!='1'">信息管理</text>
+          <text v-else>{{ indexItem.text }}</text>
+        </view>
+      </view>
+    </view>
+    <view class="qrcode">
+      <image class="qrcode" :src="qrcoderlc"></image>
+      <text class="text">长按二维码保存分享</text>
+    </view>
+    <view style="text-align: center;font-size: 23rpx;">
+      <a href="https://beian.miit.gov.cn/" target="_blank">桂ICP备12007573号-1</a>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      isLogin: false, //是否登录状态
+      userName: '',
+      companyName: '',
+      customerId: '',
+      qrcoderlc: '../../static/qrcode.png',
+      indexItemList: [{
+        auth: false,
+        icon: '../../static/home-icon-01.png',
+        text: '企业注册',
+        url: '/pages/enterprise-reg/enterprise-reg',
+        customer: true
+      }
+      ],
+      code: '',
+      state: '',
+      userType: 1,
+      partnerList: [
+        {
+          id: 'tb-business-item',
+          auth: true,
+          icon: '../../static/home-icon-03.png',
+          text: '作业订单',
+          url: '/pages/business-order/partner-business-item',
+        },
+        {
+          auth: false,
+          icon: '../../static/home-icon-06.jpg',
+          text: '业务管理',
+          url: '/pages/onely-disinfect/Index',
+          customer: true
+        },
+        {
+          id: 'admin-list',
+          auth: true,
+          icon: '../../static/home-icon-04.png',
+          text: '用户管理',
+          url: '/pages/user/user-index',
+        }
+      ],
+      customerList: [{
+        id: 'tb-costomer-account',
+        auth: true,
+        icon: '../../static/home-icon-charge.png',
+        text: '充值',
+        url: '/pages/account/account-redirect',
+      },
+        {
+          id: 'tb-declare',
+          auth: false,
+          icon: '../../static/home-icon-07.jpg',
+          text: '申报录入',
+          url: '/pages/declare/add',
+        },
+        {
+          id: 'tb-disinfect',
+          auth: false,
+          icon: '../../static/home-icon-06.jpg',
+          text: '消杀申报',
+          url: '/pages/disinfect/addDisinfect',
+        },
+        // {
+        // 	id: 'tb-business',
+        // 	auth: true,
+        // 	icon: '../../static/home-icon-02.png',
+        // 	text: '录入整车',
+        // 	url: '/pages/business-entering/business-entering',
+        // },
+        // {
+        // 	id: 'tb-business',
+        // 	auth: true,
+        // 	icon: '../../static/home-icon-03.png',
+        // 	text: '整车业务',
+        // 	url: '/pages/business-order/business-order',
+        // },
+        {
+          auth: false,
+          icon: '../../static/home-icon-03.png',
+          text: '业务管理',
+          url: '/pages/onely-disinfect/Index',
+          customer: true
+        },
+        {
+          id: 'tb-business-car',
+          auth: true,
+          icon: '../../static/home-icon-05.png',
+          text: '放行记录',
+          url: '/pages/inout-record/inout-record',
+        },
+        {
+          id: 'admin-list',
+          auth: true,
+          icon: '../../static/home-icon-04.png',
+          text: '用户管理',
+          url: '/pages/user/user-index',
+        }
+      ],
+      adminList: [
+        // {
+        // 	id: 'tb-business-add',
+        // 	auth: true,
+        // 	icon: '../../static/home-icon-02.png',
+        // 	text: '录入整车',
+        // 	url: '/pages/business-entering/business-entering',
+
+        // },
+        {
+          id: 'tb-declare',
+          auth: false,
+          icon: '../../static/home-icon-07.jpg',
+          text: '申报录入',
+          url: '/pages/declare/add',
+        },
+        {
+          id: 'tb-disinfect',
+          auth: false,
+          icon: '../../static/home-icon-06.jpg',
+          text: '消杀申报',
+          url: '/pages/disinfect/addDisinfect',
+        },
+        {
+          auth: false,
+          icon: '../../static/home-icon-03.png',
+          text: '业务管理',
+          url: '/pages/onely-disinfect/Index',
+          customer: true
+        },
+        // {
+        // 	id: 'tb-business-list',
+        // 	auth: true,
+        // 	icon: '../../static/home-icon-03.png',
+        // 	text: '整车业务',
+        // 	url: '/pages/business-order/business-order',
+        // },
+        {
+          id: 'tb-business-car',
+          auth: true,
+          icon: '../../static/home-icon-05.png',
+          text: '放行记录',
+          url: '/pages/inout-record/inout-record',
+        },
+        {
+          id: 'admin-list',
+          auth: true,
+          icon: '../../static/home-icon-04.png',
+          text: '用户管理',
+          url: '/pages/user/user-index',
+        },
+      ]
+    }
+  },
+  onLoad(options) {
+    this.code = options.code;
+    this.state = options.state;
+    this.getOpenidByCode();
+
+  },
+  onShow() {
+    this.loginByOpenid();
+    this.checkUserType();
+  },
+  onBackPress() {
+    return true;
+  },
+  methods: {
+    checkPer(code) {
+      return this.$common.isAuth(code);
+    },
+    getOpenidByCode() {
+      if (!this.code) {
+        this.$common.to('/pages/home/home')
+        return;
+      }
+      let storeOpenid = uni.getStorageSync('openid');
+      this.$api.getOpenidByCode({
+        code: this.code,
+        openid: storeOpenid
+      }).then(resp => {
+        this.success = resp.code == 200 && resp.data ? 1 : 0
+        if (resp.code == 200 && resp.data) {
+          this.success = 1;
+        } else {
+          this.success = 0
+        }
+        let openid = resp.data;
+        this.openid = openid;
+        if (openid) {
+          uni.setStorageSync('openid', openid)
+        }
+        this.loginByOpenid(openid)
+
+      })
+    },
+    getStoreInfo() {
+      let info = uni.getStorageSync('userInfo');
+      if (info) {
+        this.isLogin = true;
+        this.userName = info.name;
+        this.customerId = info.customerId;
+      }
+    },
+    loginByOpenid() {
+      let storeOpenid = uni.getStorageSync('openid');
+      if (!storeOpenid) {
+        return;
+      }
+      this.$api.doLoginByOpenid({
+        openid: storeOpenid
+      }).then(resp => {
+        if (resp.code == 404) {
+          return;
+        }
+        this.isLogin = true;
+        let data = resp.data;
+        this.userName = data.admin.name;
+        this.customerId = data.admin.customerId;
+        if (data.tokenInfo) {
+          uni.setStorageSync('token', data.tokenInfo.tokenValue);
+          uni.setStorageSync('customerId', data.admin.customerId)
+          uni.setStorageSync('userInfo', data.admin)
+          uni.setStorageSync('perList', data.per_list)
+          this.checkUserType()
+        } else {
+          this.$common.toast(resp.msg);
+        }
+      })
+    },
+    checkUserType() {
+      let token = uni.getStorageSync('token');
+      if (token) {
+        this.$nextTick(function () {
+          this.$api.checkUserType().then(resp => {
+            let userType = resp.data;
+            if (userType == 3) {
+              this.indexItemList = this.partnerList;
+            } else if (userType == 2) { //客户
+              this.indexItemList = this.customerList
+            } else if (userType == 1) {
+              this.indexItemList = this.adminList
+            }
+          })
+        })
+      }
+    },
+    toAccount() {
+      if (this.customerId !== '1') {
+        this.$common.to('/pages/customer-management/customer-list')
+      }
+    },
+    getStoreInfo() {
+      let info = uni.getStorageSync('userInfo');
+      if (info) {
+        this.isLogin = true;
+        this.userName = info.name;
+        this.customerId = info.customerId;
+      }
+    },
+    toLogin() {
+      this.$common.to('/pages/login/login')
+    },
+    exitFn() {
+      uni.removeStorageSync('token')
+      uni.removeStorageSync('userInfo')
+      uni.removeStorageSync('customerId')
+      uni.removeStorageSync('perList')
+      let storeOpenid = uni.getStorageSync('openid');
+      uni.setStorageSync('login_openid', storeOpenid);
+      uni.removeStorageSync('openid')
+      this.isLogin = false;
+      this.userName = '';
+      this.companyName = ''
+      this.indexItemList = [
+        {
+          auth: false,
+          icon: '../../static/home-icon-01.png',
+          text: '企业注册',
+          url: '/pages/enterprise-reg/enterprise-reg',
+          customer: true
+        }
+      ]
+    },
+    navTo(item) {
+      let auth = item.auth;
+      let token = uni.getStorageSync('token');
+      if (!auth || token) {
+        this.$common.to(item.url)
+      } else {
+        this.$common.to('/pages/login/login')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.top-nav {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  z-index: 999;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 20rpx 0;
+  background-color: #0080ff;
+
+  .l {
+    display: flex;
+    align-items: center;
+
+    .login-btn {
+      border: 1rpx solid #359aff;
+      border-radius: 8rpx;
+      color: #fff;
+      padding: 10rpx 20rpx;
+      font-size: 28rpx;
+      margin-left: 30rpx;
+    }
+
+    .user-img {
+      width: 80rpx;
+      height: 80rpx;
+      border-radius: 50%;
+      margin-left: 30rpx;
+      margin: 20rpx;
+    }
+
+    .l-r {
+      display: flex;
+      flex-direction: column;
+
+      .u-name {
+        font-size: 30rpx;
+        color: #fff;
+        font-weight: bold;
+      }
+
+      .c-name {
+        font-size: 24rpx;
+        color: #fff;
+      }
+    }
+  }
+
+  .r {
+    display: flex;
+    align-items: center;
+
+    .l-out {
+      border: 1rpx solid #359aff;
+      border-radius: 8rpx;
+      color: #c8e4ff;
+      padding: 10rpx 20rpx;
+      font-size: 28rpx;
+      margin-right: 30rpx;
+    }
+  }
+}
+
+.top-bg {
+  position: relative;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 400rpx;
+  background-color: #0080ff;
+  border-radius: 0 0 20rpx 20rpx;
+}
+
+.top {
+  display: flex;
+  width: 100%;
+  align-items: center;
+  justify-content: center;
+  margin: 60rpx 0;
+  margin-top: -400rpx;
+  position: relative;
+  z-index: 2;
+
+  .title {
+    font-size: 50rpx;
+    font-weight: bold;
+    color: #fff;
+  }
+}
+
+.item-box {
+  display: flex;
+  flex-wrap: wrap;
+  align-content: flex-start;
+  padding: 40rpx;
+  box-sizing: border-box;
+  background-color: #fff;
+  margin: 0 30rpx;
+  border-radius: 20rpx;
+  position: relative;
+  z-index: 2;
+  //height: calc(100vh - 170rpx - 500rpx);
+  box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.03);
+
+  .item {
+    width: 25%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 40rpx 0;
+
+    .icon {
+      width: 90rpx;
+      height: 90rpx;
+    }
+
+    .text {
+      font-size: 28rpx;
+      color: #191919;
+      margin-top: 20rpx;
+    }
+  }
+}
+
+.qrcode {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  margin: 30rpx 0;
+
+  .qrcode {
+    width: 350rpx;
+    height: 350rpx;
+    border: 1px solid #191919;
+  }
+
+  .text {
+    color: #191919;
+    font-size: 28rpx;
+    margin-top: 5rpx;
+  }
+}
+</style>

+ 303 - 0
app-ui/pages/inout-record/inout-record.vue

@@ -0,0 +1,303 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">出入记录</text>
+      </view>
+      <u-search placeholder="输入车牌号查询" shape="square" v-model="carNo" @search="searchFn"
+                :height="80" style="margin: 30rpx;">
+      </u-search>
+    </view>
+    <!-- <u-sticky offset-top="0">
+      <u-tabs :list="tabs" @change="change" :current="current" :is-scroll="false"></u-tabs>
+    </u-sticky> -->
+    <view class="card-box">
+      <view class="card" v-for="(recordItem,index) in recordItemList" :key="index">
+        <!-- <view class="t">
+          <image class="icon" src="../../static/home-icon-01.png"></image>
+          <text class="title">{{recordItem.customerName}}</text>
+        </view> -->
+        <view class="c">
+          <view class="item car-num-item">
+            <text class="car-num">{{ recordItem.carNo }}</text>
+          </view>
+          <!-- <view class="item">
+            <text class="p1">联系人:</text>
+            <text class="p2">{{recordItem.driverName}}</text>
+          </view> -->
+          <!-- <view class="item">
+            <text class="p1">联系电话:</text>
+            <text class="p2">{{recordItem.driverPhone}}</text>
+          </view> -->
+          <view class="item">
+            <text class="p1">入场时间:</text>
+            <text class="p2">{{ recordItem.realInTime }}</text>
+          </view>
+          <view class="item">
+            <text class="p1">出场时间:</text>
+            <text class="p2">{{ recordItem.realOutTime }}</text>
+          </view>
+          <view class="item">
+            <text class="p1">状态:</text>
+            <text class="p2">
+              <text v-if="recordItem.realInTime==null && recordItem.realOutTime==null">未进场</text>
+              <text v-if="recordItem.realInTime!=null && recordItem.realOutTime==null">已进场</text>
+              <text v-if="recordItem.realInTime!=null && recordItem.realOutTime!=null">已出场</text>
+            </text>
+          </view>
+        </view>
+      </view>
+    </view>
+    <!-- 没有数据时显示noData -->
+    <noData v-if="recordItemList.length==0"></noData>
+    <u-loadmore style="margin: 30rpx;" :status="status"/>
+    <!-- <uni-popup ref="shpopup" type="dialog">
+        <uni-popup-dialog type="success" title="确定审核吗?" :duration="2000" @confirm="shconfirm"></uni-popup-dialog>
+    </uni-popup> -->
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      carNo: '',
+      current: 0,
+      pageNo: 1,
+      pageSize: 4,
+      dataCount: 0,
+      status: 'loadmore',
+      page: 0,
+      tabs: [
+        {
+          name: '全部',
+        },
+        {
+          name: '未入场',
+        },
+        {
+          name: '已入场',
+        },
+        {
+          name: '已出场',
+        }
+      ],
+      recordItemList: [
+        {
+          carNo: '',
+          driverName: '',
+          driverPhone: '',
+          realInTime: '',
+          realOutTime: '',
+        },
+      ],
+      //recordList: [],
+    }
+  },
+  methods: {
+    getRecordList() {
+      this.$api.getInOutRecord({
+        current: this.current,
+        pageNo: this.pageNo,
+        pageSize: this.pageSize,
+        dataCount: this.dataCount,
+      }).then(resp => {
+        this.status = 'loadmore';
+        let recordList = resp.data;
+        this.dataCount = resp.dataCount;
+        this.pageNo = resp.pageNo;
+        this.recordItemList = recordList;
+        if (this.dataCount < this.pageSize * this.pageNo) this.status = 'nomore';
+      })
+    },
+    //点击上方切换栏,根据点击项重新加载数据
+    change(obj) {
+      let index = obj.index;
+      this.current = index;
+      if (index == 0) {
+        //加载全部
+        this.getRecordList();
+      }
+      if (index == 1) {
+        //加载未入场
+        this.getRecordList();
+      }
+      if (index == 2) {
+        //只加载已入场
+        this.getRecordList();
+      }
+      if (index == 3) {
+        //只加载已出场
+        this.getRecordList();
+      }
+    },
+    //------------------------------------------
+    //上拉加载更多,分页模拟数据
+    onReachBottom() {
+      this.status = 'loading';
+      if (this.dataCount > this.pageSize * this.pageNo) {
+        this.pageSize = parseInt(this.pageSize) + 3;
+        this.getRecordList();
+      } else {
+        this.status = 'nomore';
+      }
+    },
+    searchFn() {
+      console.log(123);
+      this.$api.getInOutRecord({
+        carNo: this.carNo,
+        current: this.current,
+        pageNo: this.pageNo,
+        pageSize: this.pageSize,
+        dataCount: this.dataCount,
+      }).then(resp => {
+        this.status = 'loadmore';
+        let recordList = resp.data;
+        this.dataCount = resp.dataCount;
+        this.pageNo = resp.pageNo;
+        this.recordItemList = recordList;
+        if (this.dataCount < this.pageSize * this.pageNo) this.status = 'nomore';
+      })
+    }
+  },
+  onShow() {
+    this.getRecordList();
+
+  },
+}
+</script>
+
+<style lang="scss">
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 30rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 0 0;
+      display: flex;
+      flex-wrap: wrap;
+      //border-bottom: 1rpx solid #f5f5f5;
+      .item {
+        width: 50%;
+        padding: 20rpx 0;
+        display: flex;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 44rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+          letter-spacing: 20rpx;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+          flex: 5;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+          flex: 7;
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+
+      .btn {
+        height: 70rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        //width: calc(50% - 15rpx);
+        width: 100%;
+        margin: 30rpx 0 0 0;
+        border-radius: 10rpx;
+        border-width: 1rpx;
+        box-sizing: border-box;
+      }
+
+      .b1 {
+        background-color: #0080ff;
+        color: #fff;
+      }
+
+      .b2 {
+        background-color: #f7f7f7;
+        color: #191919;
+      }
+
+      .b3 {
+        background-color: #fff;
+        color: #0080ff;
+        border: 1rpx solid #0080ff;
+      }
+    }
+  }
+}
+
+.t-btn {
+  width: 400rpx;
+  margin: 0 auto 80rpx auto;
+  height: 88rpx;
+  font-weight: bold;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 10rpx;
+  color: #191919;
+  font-size: 28rpx;
+  background-color: #fff;
+  border: 1px solid #eee;
+}
+
+@import '@/common/common.scss'
+</style>

+ 124 - 0
app-ui/pages/login/login.vue

@@ -0,0 +1,124 @@
+<template>
+  <view>
+    <view class="l-topbox">
+      <text>欢迎登录场站管理系统</text>
+    </view>
+    <view class="box">
+
+      <view class="item">
+        <view class="l">登录名:</view>
+        <view class="r">
+          <u-input v-model="form.key" placeholder="登录名"/>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">密码:</view>
+        <view class="r">
+          <u-input v-model="form.password" placeholder="输入密码" type="password"/>
+        </view>
+      </view>
+    </view>
+    <view class="common-btn" @click="sliderVerifyFLag = true">确认登录</view>
+    <slider-verify :isShow="sliderVerifyFLag" @touchSliderResult="verifyResult" ref="verifyElement"></slider-verify>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      sliderVerifyFLag: false, //滑块验证
+      form: {
+        key: '',
+        password: ''
+      }
+    }
+  },
+  methods: {
+    loginFn() {
+      if (!this.form.key) {
+        this.$common.toast('请输入登录名');
+        return;
+      }
+      if (!this.form.password) {
+        this.$common.toast('请输入密码');
+        return;
+      }
+      let openid = uni.getStorageSync('openid');
+      if (!openid) {
+        openid = uni.getStorageSync('login_openid');
+      }
+      this.form.openid = openid
+      this.$api.doLogin(this.form).then(resp => {
+        let data = resp.data;
+        if (data.tokenInfo) {
+          uni.setStorageSync('token', data.tokenInfo.tokenValue);
+          uni.setStorageSync('customerId', data.admin.customerId)
+          uni.setStorageSync('userInfo', data.admin)
+          uni.setStorageSync('perList', data.per_list)
+          uni.setStorageSync('openid', openid)
+          setTimeout(() => {
+            this.$common.to('/pages/index/index')
+          }, 500)
+
+        } else {
+          this.$common.toast('登录失败');
+        }
+      })
+    },
+    verifyResult(res) {
+      this.sliderVerifyFLag = false;
+      if (res) {  //校验通过
+        this.loginFn()
+      } else {
+        // 校验失败,点击关闭按钮
+        console.log("验证失败,并点了关闭")
+      }
+    }
+
+
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.l-topbox {
+  //background-color: #0080ff;
+  height: 400rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  //border-radius: 0 0 30rpx 30rpx;
+  margin-bottom: 50rpx;
+  background-image: url(../../static/login-bg.png);
+  background-size: 100% 100%;
+
+  text {
+    font-size: 50rpx;
+    font-weight: bold;
+    color: #fff;
+  }
+}
+
+@import '@/common/common.scss';
+.box {
+  box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.05);
+  background-color: #fff;
+  box-sizing: border-box;
+  margin: 60rpx;
+  margin-top: -150rpx;
+  width: auto;
+  border-radius: 10rpx;
+}
+
+.common-btn {
+  margin: 100rpx 60rpx;
+  width: auto;
+  height: 98rpx;
+  box-shadow: 0 30rpx 30rpx -15rpx rgba(0, 128, 255, 0.2);
+}
+</style>

+ 62 - 0
app-ui/pages/ok/registerSuccess.vue

@@ -0,0 +1,62 @@
+<template>
+  <view class="box">
+    <u-icon name="checkmark-circle-fill" color="#07c160" size="200"></u-icon>
+    <text class="text">您的信息已提交,请等待审核!</text>
+    <view class="count-down-box">
+      <text @click="goback">返回</text>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      timestamp: 3,
+    }
+  },
+  onBackPress() {
+    this.goback();
+    return true;
+  },
+  methods: {
+    goback() {
+      this.$common.to('/pages/index/index');
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    flex: 1;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+
+    text {
+      margin-left: 20rpx;
+    }
+  }
+}
+</style>

+ 347 - 0
app-ui/pages/onely-disinfect/Index.vue

@@ -0,0 +1,347 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top" style="margin-top: -1rpx;">
+        <text class="title">业务管理</text>
+      </view>
+      <view class="add" @click="addFn">+添加</view>
+    </view>
+    <view class="card-box">
+      <view class="card" v-for="(businessItem,index) in businessItemList" :key="index">
+        <view class="t">
+          <image class="icon" src="../../static/home-icon-01.png"></image>
+          <text class="title">{{ businessItem.customerName }}</text>
+        </view>
+        <view style="line-height: 60rpx;">
+          <view class="title">录入时间:{{ businessItem.createTime }}</view>
+          <view class="title">订单号:{{ businessItem.no }}</view>
+        </view>
+
+        <view class="c">
+          <view class="item car-num-item">
+            <text class="car-num">{{ businessItem.carNoStr }}</text>
+          </view>
+
+          <view class="item">
+            <text class="p1">业务项:</text>
+            <text class="p2">{{ businessItem.goodsName }}</text>
+          </view>
+          <view class="item">
+            <text class="p1">业务费(元):</text>
+            <text class="p2">
+              <text>{{ businessItem.itemPrice }}</text>
+            </text>
+          </view>
+          <view class="item">
+            <text class="p1">账单确认:</text>
+            <text class="p2">
+              <text v-if="businessItem.confirmInput==0">未确认</text>
+              <text v-else>已确认</text>
+            </text>
+          </view>
+          <view class="item">
+            <text class="p1">支付状态:</text>
+            <text class="p2">
+              <text v-if="businessItem.payStatus==1">未支付</text>
+              <!-- <text v-if="businessItem.payStatus==2">已支付(未确认)</text> -->
+              <text v-if="businessItem.payStatus==3">已支付</text>
+            </text>
+          </view>
+        </view>
+        <view class="b">
+          <view class="btn b3" v-if="businessItem.adminConfirmInput==0
+								&&perList.indexOf('tb-flex-business-confirm')!=-1" @click="sureZdFn(businessItem)">
+            账单确认
+          </view>
+          <view class="btn b3" @click="toDetail(businessItem)">详情</view>
+          <view class="btn b1"
+                v-if="businessItem.adminConfirmInput==0&&perList.indexOf('tb-flex-business-edit')!==-1"
+                @click="editFn(businessItem)">修改
+          </view>
+          <view class="btn b4" v-if="businessItem.adminConfirmInput==0
+								&&perList.indexOf('tb-flex-business-del')!==-1" @click="deleteFn(businessItem)">删除
+          </view>
+        </view>
+      </view>
+    </view>
+    <noData v-if="businessItemList.length==0"></noData>
+    <u-loadmore style="margin: 30rpx;" :status="status"/>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      p: {
+        adminConfirmInput: -1,
+        pageNo: 1,
+        pageSize: 3,
+        dataCount: 0
+      },
+      customemrId: '1',
+      fk: {
+        ids: '',
+      },
+      rc: {
+        id: '',
+        inChannel: '',
+        showTime: false,
+        visible: false,
+        realInTime: ''
+      },
+      current: 0,
+      status: 'loadmore',
+      page: 0,
+      tabs: [{
+        name: '进场',
+      }, {
+        name: '出场',
+      }],
+      businessItemList: [],
+      perList: []
+    }
+  },
+  onShow() {
+    this.customemrId = uni.getStorageSync('customerId')
+    this.getBusinessList();
+    this.perList = uni.getStorageSync('perList')
+  },
+  mounted() {
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index')
+    return true;
+  },
+  methods: {
+    addFn() {
+      this.$common.to('/pages/onely-disinfect/disinfect-Index')
+    },
+    toDetail(data) {
+      this.$common.to('/pages/onely-disinfect/type-business-info?id=' + data.id)
+    },
+    editFn(data) {
+      this.$api.getGoodsById({
+        id: data.goodsId
+      }).then(resp => {
+        let goods = resp.data;
+        this.$common.to('/pages/onely-disinfect/type-business-edit?id=' + data.id + '&goodsJson=' + JSON.stringify(goods))
+      })
+    },
+    deleteFn(data) {
+      let that = this;
+      uni.showModal({
+        title: "警告",
+        content: "是否删除该业务?",
+        success(res) {
+          if (res.confirm) {
+            that.$api.deleteOtherBusiness({
+              id: data.id
+            }).then(resp => {
+              that.$common.toast('已删除');
+              that.getBusinessList();
+            })
+          }
+        }
+      })
+    },
+    sureZdFn(data) {
+      this.$common.to('/pages/wx/payOrderTemp?id=' + data.id)
+    },
+    getBusinessList() {
+      this.$api.getOtherBusiness(this.p).then(resp => {
+        this.status = 'loadmore';
+        this.p.pageNo = resp.pageNo;
+        this.p.pageSize = resp.pageSize;
+        this.p.dataCount = resp.dataCount;
+        this.businessItemList = resp.data;
+      })
+    },
+    //点击上方切换栏,根据点击项重新加载数据
+    change(index) {
+      this.current = index;
+      if (index == 0) {
+        //只加载进场订单
+      }
+      if (index == 1) {
+        //只加载出场订单
+      }
+    },
+    //点击按钮
+    //------------------------------------------
+
+    fkconfirm() {
+      this.$api.adminConfirmPay(this.fk).then(resp => {
+        this.$refs.fkpopup.close();
+        this.getBusinessList();
+      })
+    },
+
+    rcconfirm() {
+      if (!this.rc.inChannel) {
+        this.$common.toast('请填写入场通道');
+        return false;
+      }
+      this.$api.adminConfirmIn(this.rc).then(resp => {
+        this.$refs.rcpopup.close();
+        this.getBusinessList();
+      })
+    },
+
+    ccconfirm(index) {
+      this.$refs.ccpopup.close()
+    },
+    zd() {
+      this.$refs.zdpopup.open('center')
+    },
+    zdconfirm(index) {
+      this.$refs.zdpopup.close()
+    },
+    //------------------------------------------
+    //上拉加载更多,分页模拟数据
+    onReachBottom() {
+      if (parseInt(this.p.dataCount) > parseInt(this.p.pageSize) * parseInt(this.p.pageNo)) {
+        this.status = 'loading';
+        this.p.pageSize += 5;
+        this.getBusinessList();
+      } else {
+        this.status = 'nomore';
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.add {
+  position: absolute;
+  right: 40rpx;
+  top: -60rpx;
+  z-index: 999;
+  border: 1rpx solid #359aff;
+  border-radius: 8rpx;
+  color: #c8e4ff;
+  padding: 10rpx 20rpx;
+  font-size: 28rpx;
+}
+
+.card-box {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+
+  .card {
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 20rpx 20rpx 0 20rpx;
+    padding: 30rpx;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+
+    .t {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding-bottom: 30rpx;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .icon {
+        width: 40rpx;
+        height: 40rpx;
+      }
+
+      .title {
+        font-size: 30rpx;
+        font-weight: bold;
+        margin-left: 20rpx;
+      }
+    }
+
+    .c {
+      padding: 15rpx 0 30rpx 0;
+      display: flex;
+      flex-wrap: wrap;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .item {
+        width: 50%;
+        padding: 20rpx 0;
+
+        .car-num {
+          background-color: #edf6ff;
+          color: #0080ff;
+          font-size: 44rpx;
+          padding: 15rpx 0;
+          text-align: center;
+          width: 100%;
+          border-radius: 10rpx;
+          font-weight: bold;
+        }
+
+        .p1 {
+          font-size: 28rpx;
+          color: #999;
+        }
+
+        .p2 {
+          font-size: 28rpx;
+          color: #191919;
+          font-weight: bold;
+          margin-left: 20rpx;
+        }
+      }
+
+      .car-num-item {
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      align-items: center;
+      justify-content: space-between;
+
+      .btn {
+        height: 70rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: calc(50% - 15rpx);
+        margin: 30rpx 0 0 0;
+        border-radius: 10rpx;
+        border-width: 1rpx;
+        box-sizing: border-box;
+      }
+
+      .b1 {
+        background-color: #0080ff;
+        color: #fff;
+      }
+
+      .b2 {
+        background-color: #f7f7f7;
+        color: #191919;
+      }
+
+      .b3 {
+        background-color: #fff;
+        color: #0080ff;
+        border: 1rpx solid #0080ff;
+      }
+
+      .b4 {
+        background-color: #ff0000;
+        color: #fff;
+      }
+    }
+  }
+}
+
+@import '@/common/common.scss'
+</style>

+ 89 - 0
app-ui/pages/onely-disinfect/add-remark.vue

@@ -0,0 +1,89 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">备注</text>
+      </view>
+    </view>
+    <view class="box" style="margin-top: 50px;">
+      <view class="item">
+        <view class="l">
+          <text style="color: red;" v-if="form.needRemark==1">*</text>
+          备注:
+        </view>
+        <view class="r">
+          <u-textarea placeholder="备注" v-model="form.remark" clearable>
+          </u-textarea>
+        </view>
+      </view>
+    </view>
+    <view style="margin-top: 50px;">
+      <u-button type="primary" text="确定" @click="saveFn"></u-button>
+      <u-button type="info" text="重置" @click="form.remark=''" style="margin-top: 20rpx;"></u-button>
+    </view>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      form: {
+        id: '',
+        title: '',
+        remark: '',
+        needRemark: 1
+      }
+    }
+  },
+  onLoad(options) {
+    this.form = options;
+  },
+  methods: {
+    saveFn() {
+      let data = this.form;
+      if (data.mustRemark == 1 && !data.remark) {
+        this.$common.toast('请填写备注')
+        return false;
+      }
+      console.log(data)
+      uni.navigateBack({
+        delta: 1,
+        success: function (resp) {
+          uni.$emit('getRemark', data) //触发事件
+        }
+      })
+    }
+  },
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 61 - 0
app-ui/pages/onely-disinfect/addSuccess.vue

@@ -0,0 +1,61 @@
+<template>
+  <view class="box">
+    <u-icon name="checkmark-circle-fill" color="#07c160" size="200"></u-icon>
+    <text class="text">业务添加提交成功!</text>
+    <view class="count-down-box">
+      <view @click="goback">返回</view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      timestamp: 3,
+      id: ''
+    }
+  },
+  onBackPress() {
+    this.goback();
+    return true;
+  },
+  onLoad(options) {
+    this.id = options.typeId
+  },
+  methods: {
+    goback() {
+      this.$common.to('/pages/onely-disinfect/type-business?typeId=' + this.id);
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+  }
+}
+</style>

+ 151 - 0
app-ui/pages/onely-disinfect/car-manager.vue

@@ -0,0 +1,151 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务车辆</text>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          车牌号:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入车牌号" v-model="form.carNo">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;" v-if="needCarSize==1">*</text>
+          规格(米):
+        </view>
+        <view class="r">
+          <u-input placeholder="输入规格" type="number" v-model="form.carSize">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">车辆类型:</view>
+        <view class="r" style="flex: 12;">
+          <picker v-if="carType.list.length>0" class="p-picker" @change="carTypeChange($event)"
+                  :value="carType.index" :range="carType.list" range-key="name">
+            <text class="p-text">{{ carType.list[carType.index].name }}</text>
+          </picker>
+        </view>
+      </view>
+      <view class="item" v-if="carType.index==1">
+        <view class="l">
+          <text style="color: red;">*</text>
+          载重(kg):
+        </view>
+        <view class="r">
+          <u-input placeholder="车辆载重" v-model="form.netWeight">
+          </u-input>
+        </view>
+      </view>
+    </view>
+    <view style="margin-top: 50px;">
+      <u-button type="primary" text="确定" @click="saveFn"></u-button>
+      <u-button type="info" text="返回" @click="backFn" style="margin-top: 20rpx;"></u-button>
+    </view>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      carType: {
+        index: 0,
+        list: []
+      },
+      needCarSize: 0,
+      needWeight: 0,
+      form: {
+        carNo: '',
+        carType: '',
+        netWeight: '',
+        carSize: ''
+      }
+    }
+  },
+  onLoad(options) {
+    this.form = JSON.parse(options.carJson);
+
+    this.needCarSize = options.needCarSize;
+    this.needWeight = options.needWeight;
+    this.getCarType();
+  },
+  methods: {
+    getCarType() {
+      this.$api.getCarType().then(resp => {
+        let list = resp.data;
+        this.carType.list = list;
+        let form = this.form;
+        let carType = this.form.carType;
+        if (carType) {
+          this.carType.index = this.carType.list.map(obj => obj.name).indexOf(carType);
+        }
+      })
+    },
+    carTypeChange(e) {
+      var value = e.detail.value; //当前picker选中的值
+      this.carType.index = value;
+    },
+    backFn() {
+      this.$common.back();
+    },
+    saveFn() {
+      let data = this.form;
+      if (!data.carNo) {
+        this.$common.toast('请填写车牌号')
+        return false;
+      }
+      let needCarSize = this.needCarSize;
+      if (!data.carSize && needCarSize == 1) {
+        this.$common.toast('请填写车辆规格')
+        return false;
+      }
+      let needWeight = this.needWeight;
+      if (this.carType.index == 1 && (!data.netWeight || data.netWeight <= 0)) {
+        this.$common.toast('请填写车辆载重')
+        return false;
+      }
+      if (this.carType.index == 0) {
+        data.netWeight = 0;
+      }
+      data.carType = this.carType.list[this.carType.index].name;
+      data.carNo = data.carNo.toUpperCase();
+      uni.navigateBack({
+        delta: 1,
+        success: function (resp) {
+          uni.$emit('getCar', data) //触发事件
+        }
+      })
+    }
+  },
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 84 - 0
app-ui/pages/onely-disinfect/disinfect-Index.vue

@@ -0,0 +1,84 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务项</text>
+      </view>
+    </view>
+    <view class="card-box">
+      <uni-list>
+        <uni-list-item v-for="(item,index) in typeList" link="reLaunch" @click="onClick(item)">
+          <template v-slot:body>{{ item.name }}</template>
+        </uni-list-item>
+      </uni-list>
+    </view>
+    <noData v-if="typeList.length==0"></noData>
+    <u-loadmore style="margin: 30rpx;" :status="status"/>
+  </view>
+
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      status: 'loadmore',
+      customemrId: '1',
+      typeList: [],
+      p: {
+        pageNo: 1,
+        pageSize: 3,
+        dataCount: 0
+      },
+    }
+  },
+  onShow() {
+    this.getGoodsList();
+  },
+  onBackPress() {
+    this.$common.to('/pages/onely-disinfect/Index')
+    return true;
+  },
+  methods: {
+    onClick(item) {
+      this.$common.to('/pages/onely-disinfect/type-business?goodsJson=' + JSON.stringify(item))
+    },
+    getGoodsList() {
+      this.$api.getGoodsList(this.p).then(resp => {
+        this.typeList = resp.data;
+      })
+    }
+  },
+  //上拉加载更多,分页模拟数据
+  onReachBottom() {
+    if (parseInt(this.p.dataCount) > parseInt(this.p.pageSize) * parseInt(this.p.pageNo)) {
+      this.status = 'loading';
+      this.p.pageSize += 5;
+      this.getCarDisinFect();
+    } else {
+      this.status = 'nomore';
+    }
+  }
+
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.add {
+  position: absolute;
+  right: 40rpx;
+  top: -60rpx;
+  z-index: 999;
+  border: 1rpx solid #359aff;
+  border-radius: 8rpx;
+  color: #c8e4ff;
+  padding: 10rpx 20rpx;
+  font-size: 28rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 626 - 0
app-ui/pages/onely-disinfect/type-business-edit.vue

@@ -0,0 +1,626 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">{{ goods.name }}</text>
+      </view>
+      <view class="item" v-if="goods.needDeclare==1">
+        <view class="l">
+          <text style="color: red;" v-if="goods.needDeclare==1">*</text>
+          申报单号:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报订单号" v-model="form.declareNo" clearable readonly>
+            <text slot="suffix" style="font-size: 50rpx;" @click="selectDeclare">+</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item" v-if="goods.needCustomer==1">
+        <view class="l">客户:</view>
+        <view class="r" style="flex: 12;">
+          <picker :disabled="goods.needDeclare==1" v-if="customer.customerList.length>0" class="p-picker"
+                  @change="customerChange($event)" :value="customer.index" :range="customer.customerList"
+                  range-key="name">
+            <text class="p-text">{{ customer.customerList[customer.index].name }}</text>
+          </picker>
+        </view>
+      </view>
+      <view class="item" v-if="goods.needOwner==1">
+        <view class="l">
+          <text style="color: red;">*</text>
+          货主:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入货主" v-model="form.owner">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">作业人员:</view>
+        <view class="r">
+          <u-input placeholder="输入作业人员" v-model="form.operator">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;" v-if="goods.needOperateTime">*</text>
+          作业时间:
+        </view>
+        <view class="r">
+          <uni-datetime-picker type="datetime" v-model="form.operateTime"/>
+        </view>
+      </view>
+      <view class="item-line">
+        <u-row style="height: 40px;">
+          <u-col span=4>车辆</u-col>
+          <u-col span=8>
+            <u-button type="primary" text="添加" @click="addCar" icon="plus"
+                      style="width: 60px;height: 26px;" v-if="goods.mulCar==1||car.list.length==0"/>
+          </u-col>
+        </u-row>
+      </view>
+      <view class="item" v-for="(car,index) in car.list" :key="index">
+        <view class="l">车牌:</view>
+        <view class="r">
+          <u-input placeholder="车辆" v-model="car.carNo" readonly>
+            <view slot="suffix" style="display: flex;">
+              <u-icon @click="editCar(car)" size="20" name="edit-pen-fill" color="blue"></u-icon>
+              <u-icon style="margin-left:20rpx;" size="20" @click="delCar(car)" name="close-circle-fill"
+                      color="red"></u-icon>
+            </view>
+          </u-input>
+        </view>
+      </view>
+      <view class="item-line" style="margin-top: 30rpx;">
+        业务项
+      </view>
+      <view class="business-list" v-for="(item,index) in typeList">
+        <u-row>
+          <u-col span="4">
+            <text>
+              <text style="color: red;display: inline;" v-if="item.need==1">*</text>
+              {{ item.name }}:
+            </text>
+          </u-col>
+          <u-col span="8" style="display: flex;">
+            <u-row>
+              <u-col span="10" @click="showSelect(item)">
+                {{ item.itemName ? item.itemName : '请选择' }}
+              </u-col>
+              <u-col span="2" @click="item.itemName='',item.itemId=''" v-if="item.itemId">
+                <u-icon style="margin-left:15rpx;display: inline;" size="20" name="close-circle-fill"
+                        color="red"></u-icon>
+              </u-col>
+            </u-row>
+          </u-col>
+        </u-row>
+        <view style="display: flex;position: relative;left: 30%;">
+          <u-number-box style="margin-left: 15rpx;" v-if="item.itemName" :disabled="item.inc==0"
+                        v-model="item.num"></u-number-box>
+          <text style="margin-left: 20rpx;color: red;" v-if="item.itemName">
+            ¥{{ item.num * item.price }}
+          </text>
+          <view style="margin-left: 60rpx;" @click="remarkFn(item)">
+            备注
+          </view>
+        </view>
+        <u-line></u-line>
+      </view>
+      <view class="hj" v-show="totalPrice>0">
+        合计:{{ totalPrice }}元
+      </view>
+    </view>
+    <u-button type="primary" text="确定" @click="saveFn" v-show="perList.indexOf('tb-flex-business-edit')!==-1">
+    </u-button>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+    <u-picker :show="show" :columns="columns" @confirm="confirmFn" keyName="itemName" @cancel="show=false">
+    </u-picker>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      show: false,
+      columns: [],
+      customerId: '1',
+      customer: {
+        index: 0,
+        customerList: [],
+      },
+      goods: {
+        id: '',
+        name: '',
+        mulCar: 0
+      },
+      typeList: [],
+      allTypeList: [],
+      form: {
+        customerId: '',
+        declareNo: '',
+        carNo: '',
+        owner: '',
+        carSize: '',
+        goodsName: '',
+        netWeight: '',
+      },
+      show: false,
+      item: {
+        items: []
+      },
+      car: {
+        list: [{
+          id: '',
+          carNo: '',
+          index: 0
+        }]
+      },
+      perList: []
+    }
+  },
+  computed: {
+    totalPrice() {
+      let typeList = this.typeList.filter(obj => obj.itemName);
+      let price = 0;
+      for (let i in typeList) {
+        let type = typeList[i];
+        price = price + type.price * type.num;
+      }
+      return price;
+    },
+  },
+  onLoad(options) {
+    let id = options.id;
+    this.form.id = id;
+    this.customerId = uni.getStorageSync('customerId');
+    this.goods = JSON.parse(options.goodsJson);
+    this.getOtherBusinessById();
+    let that = this;
+    uni.$on('getSelectDeclare', declare => {
+      that.$nextTick(() => {
+        that.handlerSelectDeclare(declare)
+      })
+    })
+    uni.$on('getCar', car => {
+      that.$nextTick(() => {
+        that.handlerCar(car)
+      })
+    })
+    uni.$on('getRemark', type => {
+      that.$nextTick(() => {
+        that.handlerRemark(type)
+      })
+    })
+
+  },
+  onShow() {
+
+    this.perList = uni.getStorageSync('perList')
+  },
+  methods: {
+    remarkFn(type) {
+      console.log(type)
+      let remark = type.remark ? type.remark : '';
+      this.$common.to('/pages/onely-disinfect/add-remark?needRemark=' + type.needRemark + '&typeId=' + type.id + '&remark=' + remark)
+    },
+    handlerRemark(type) {
+      let typeList = this.typeList;
+      typeList.filter(obj => type.typeId == obj.id).forEach(obj => obj.remark = type.remark)
+    },
+    addCar() {
+      this.car.list.push({
+        index: Math.random(),
+        id: '',
+        carNo: '',
+        index: 0
+      })
+    },
+    filterItems(car) {
+      let carList = this.car.list;
+      let filterTypeList = JSON.parse(JSON.stringify(this.allTypeList));
+      if (carList.length == 0) {
+        this.typeList = filterTypeList;
+        return;
+      }
+      if (!car) {
+        let checkList = carList.filter(obj => obj.carType.indexOf('空') === -1);
+        if (checkList.length > 0) {
+          car = checkList[0];
+        }
+      }
+      let carSize = car.carSize;
+      let carType = car.carType;
+      if (carType.indexOf('空') !== -1 && carList.length > 1) {
+        return;
+      }
+      let netWeight = car.netWeight;
+      let tempList = [];
+      for (let i in filterTypeList) {
+        let type = filterTypeList[i];
+        let items = type.items;
+        if (carType) {
+          items = items.filter(item => item.itemType && item.itemType.indexOf(carType) !== -1);
+        }
+        if (carSize && carSize > 1) {
+          items = items.filter(item => item.minLength <= carSize && item.carLength >= carSize);
+        }
+        if (netWeight && netWeight > 1 && carType.indexOf('空') == -1) {
+          items = items.filter(item => item.minWeight <= netWeight && item.maxWeight >= netWeight);
+        }
+        let itemIds = items.map(item => item.id);
+        if (itemIds.indexOf(type.itemId) == -1) {
+          this.cleanItem(type);
+        }
+        type.items = items;
+        tempList.push(type);
+      }
+      this.typeList = tempList;
+    },
+    cleanItem(type) {
+      type.itemId = '';
+      type.itemName = '';
+      type.price = '';
+    },
+    getOtherBusinessById() {
+      this.$api.getOtherBusinessById({
+        id: this.form.id
+      }).then(resp => {
+        let data = resp.data;
+        this.car.list = data.cars;
+        let items = data.items;
+        this.form = data;
+        this.getTypeByGoodsId(items);
+        this.getCustomerList(data.customerId);
+      })
+    },
+    showSelect(item) {
+      if (this.validBefore()) {
+        this.columns = [];
+        this.columns.push(item.items);
+        this.show = true;
+      }
+    },
+
+    confirmFn(e) {
+      let selects = e.value;
+      if (selects.length > 0) {
+        let item = selects[0];
+        let typeId = item.typeId;
+        let typeList = this.typeList;
+        typeList.filter(obj => obj.id == typeId).forEach(obj => {
+          obj.itemId = item.id;
+          obj.itemName = item.itemName;
+          obj.inc = item.inc;
+          obj.price = item.price;
+          obj.needRemark = item.needRemark;
+        })
+      }
+      this.show = false;
+    },
+    getTypeByGoodsId(items) {
+      this.$api.getTypeByGoodsId({
+        goodsId: this.goods.id
+      }).then(resp => {
+        let list = resp.data;
+        for (let i in items) {
+          let item = items[i];
+          for (let j in list) {
+            let type = list[j];
+            if (type.id == item.itemTypeId) {
+              type.items.filter(obj => obj.id == item.itemId)
+                  .forEach(obj => {
+                    console.log(obj)
+                    type.num = item.num;
+                    type.price = item.itemPrice;
+                    type.itemName = item.itemName;
+                    type.itemId = item.itemId;
+                    type.inc = obj.inc;
+                    type.remark = item.remark;
+                  })
+
+
+            }
+          }
+        }
+        this.allTypeList = JSON.parse(JSON.stringify(list));
+        this.typeList = list;
+      })
+    },
+    getCustomerList(customerId) {
+      this.$api.getCustomerList({
+        pageNo: 1,
+        pageSize: 100
+      }).then(resp => {
+        let list = resp.data;
+        console.log(list.map(obj => obj.id).indexOf(customerId))
+        this.customer.index = list.map(obj => obj.id).indexOf(customerId);
+        this.customer.customerList = list;
+        console.log(this.customer)
+      })
+    },
+    customerChange(e) {
+      var value = e.detail.value; //当前picker选中的值
+      this.customer.index = value;
+    },
+    handlerCar(car) {
+      let list = this.car.list;
+      let check = list.filter(obj => obj.carNo == car.carNo).pop();
+      if (check) {
+        check.carSize = car.carSize;
+        check.netWeight = car.netWeight;
+        check.carType = car.carType;
+      } else {
+        this.car.list.push(car);
+      }
+      this.clearEmptyCar(car);
+    },
+    clearEmptyCar(car) {
+      let list = this.car.list;
+      let obj = list.filter(obj => !obj.carNo).pop();
+      if (obj) {
+        this.car.list.splice(list.indexOf(obj), 1);
+      }
+      this.filterItems(car);
+    },
+    handlerSelectDeclare(declare) {
+      let oldDeclareNo = this.form.declareNo;
+      if (oldDeclareNo && oldDeclareNo !== declare.declareNo) {
+        this.car.list = [];
+      }
+      this.form.declareNo = declare.declareNo;
+      this.form.cardNo = declare.carNo;
+      this.form.chinaCarNo = declare.chinaCarNo;
+      this.form.netWeight = declare.grossWeight;
+      this.form.owner = declare.sendUnit;
+      let customerList = this.customer.customerList;
+      this.customer.index = customerList.map(customer => customer.id).indexOf(declare.customerId);
+      let carNo = declare.carNo;
+      let grossWeight = declare.grossWeight;
+      let carList = this.car.list;
+      let exit = carList.filter(obj => obj.carNo == carNo).pop();
+      if (!exit) {
+        let car = {
+          carNo: carNo,
+          netWeight: grossWeight,
+          carType: '载重'
+        }
+        this.car.list.push(car)
+      }
+      this.form.cardNo = declare.carNo;
+      this.form.chinaCarNo = declare.chinaCarNo;
+      this.form.netWeight = declare.grossWeight;
+      let chinaCarNo = declare.chinaCarNo;
+      if (chinaCarNo) {
+        let list = [];
+        chinaCarNo.replace(",", ",").split(",").forEach(carNo => {
+          let exit = carList.filter(obj => obj.carNo == carNo).pop();
+          if (!exit) {
+            let car = {
+              carNo: carNo,
+              carType: '空车'
+            }
+            this.car.list.push(car)
+          }
+        })
+      }
+      this.clearEmptyCar();
+    },
+
+    selectDeclare() {
+      this.$common.to('/pages/business-entering/declare-select?declareNo=' + this.form.declareNo)
+    },
+    editCar(car) {
+      let goods = this.goods;
+      this.$common.to('/pages/onely-disinfect/car-manager?carJson=' + JSON.stringify(car) + "&needCarSize=" +
+          goods.needCarSize + '&needWeight=' + goods.needWeight)
+    },
+    delCar(car) {
+      let list = this.car.list;
+      if (list.length == 1) {
+        this.$common.toast('至少有一辆车');
+        return;
+      }
+      this.car.list.splice(list.indexOf(car), 1);
+      this.filterItems();
+    },
+    validBefore() {
+      let form = this.form;
+      let goods = this.goods;
+      let needDeclare = goods.needDeclare;
+      let needCustomer = goods.needCustomer;
+      let index = this.customer.index;
+      if (needDeclare == 1 && !form.declareNo) {
+        this.$common.toast('请选择申报单');
+        return false;
+      }
+      if (!form.owner && goods.needOwner == 1) {
+        this.$common.toast('请填写货主');
+        return false;
+      }
+      let needOperateTime = goods.needOperateTime;
+      let operateTime = form.operateTime;
+      if (!operateTime && needOperateTime == '1') {
+        this.$common.toast('请录入作业时间');
+        return false;
+      }
+      if (operateTime && operateTime.length < 12) {
+        this.$common.toast('请录入准确的作业时间');
+        return false;
+      }
+      let carList = this.car.list;
+      if (carList.length == 0) {
+        this.$common.toast('请录入车辆');
+        return false;
+      }
+      let needCarSize = goods.needCarSize;
+      let needWeight = goods.needWeight;
+      for (let i in carList) {
+        let car = carList[i];
+        if (needCarSize == 1 && !car.carSize) {
+          this.$common.toast('请补充' + car.carNo + '的规格');
+          return false;
+        }
+        if (needWeight == 1 && car.carType.indexOf('重') !== -1 && !car.netWeight) {
+          this.$common.toast('请补充' + car.carNo + '载重');
+          return false;
+        }
+      }
+      return true;
+    },
+    check() {
+      let form = this.form;
+      let goods = this.goods;
+      let needDeclare = goods.needDeclare;
+      let needCustomer = goods.needCustomer;
+      let index = this.customer.index;
+      if (needDeclare == 1 && !form.declareNo) {
+        this.$common.toast('请选择申报单');
+        return false;
+      }
+      if (!form.owner && goods.needOwner == 1) {
+        this.$common.toast('请填写货主');
+        return false;
+      }
+      let needOperateTime = goods.needOperateTime;
+      let operateTime = form.operateTime;
+      if (!operateTime && needOperateTime == '1') {
+        this.$common.toast('请录入作业时间');
+        return false;
+      }
+      if (operateTime && operateTime.length < 12) {
+        this.$common.toast('请录入准确的作业时间');
+        return false;
+      }
+      let carList = this.car.list;
+      if (carList.length == 0) {
+        this.$common.toast('请录入车辆');
+        return false;
+      }
+      let needCarSize = goods.needCarSize;
+      let needWeight = goods.needWeight;
+      for (let i in carList) {
+        let car = carList[i];
+        if (needCarSize == 1 && !car.carSize) {
+          this.$common.toast('请补充' + car.carNo + '的规格');
+          return false;
+        }
+        if (needWeight == 1 && car.carType && car.carType.indexOf('重') !== -1 && !car.netWeight) {
+          this.$common.toast('请补充' + car.carNo + '载重');
+          return false;
+        }
+      }
+      let typeList = this.typeList;
+      let selectList = [];
+      for (let i in typeList) {
+        let type = typeList[i];
+        if (type.need == 1 && !type.itemId) {
+          this.$common.toast('【' + type.name + '】必选');
+          return false;
+        }
+        if (type.needRemark == 1 && !type.remark) {
+          this.$common.toast('请录入【' + type.name + '】备注');
+          return false;
+        }
+        if (type.itemId) {
+          let obj = {
+            typeId: type.id,
+            typeName: type.name,
+            id: type.itemId,
+            num: type.num,
+            price: type.price,
+            remark: type.remark
+          }
+          selectList.push(obj);
+        }
+      }
+      this.form.itemJson = JSON.stringify(selectList);
+      this.form.carJson = JSON.stringify(this.car.list);
+      this.form.items = null;
+      this.form.cars = null;
+      if (needCustomer == 1) {
+        let customerList = this.customer.customerList;
+        let index = this.customer.index;
+        let customer = customerList[index];
+        this.form.customerId = customer.id;
+        this.form.customerName = customer.name;
+      } else {
+        this.form.customerId = '';
+        this.form.customerName = '';
+      }
+      this.form.goodsId = this.goods.id;
+      this.form.goodsName = this.goods.name;
+      let chinaCarNo = carList
+          .filter(car => this.$common.isCarNo(car.carNo.toUpperCase()))
+          .map(car => car.carNo.toUpperCase())
+          .join("、");
+      let yueCarNo = carList
+          .filter(car => !this.$common.isCarNo(car.carNo.toUpperCase()))
+          .map(car => car.carNo.toUpperCase())
+          .join("、");
+      this.form.cardNo = yueCarNo;
+      this.form.chinaCarNo = chinaCarNo;
+      return true;
+    },
+    saveFn() {
+      if (this.check()) {
+        let obj = this.$common.removeNull(this.form);
+        this.$api.editOtherBusiness(obj).then(resp => {
+          if (resp.code == 200) {
+            this.$common.toast('修改成功');
+            setTimeout(() => {
+              this.$common.to('/pages/onely-disinfect/Index')
+            }, 1000)
+          }
+        })
+      }
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.business-list {
+  line-height: 75rpx;
+  margin: 4rpx 0 0 48rpx;
+
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 171 - 0
app-ui/pages/onely-disinfect/type-business-info.vue

@@ -0,0 +1,171 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">业务详情</text>
+      </view>
+      <view class="item">
+        <view class="l">企业名称:</view>
+        <view class="r">
+          {{ form.customerName }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">业务类型:</view>
+        <view class="r">
+          {{ form.goodsName }}
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">货重:</view>
+        <view class="r">
+          {{ form.netWeight }}(kg)
+        </view>
+      </view>
+      <view v-for="item in form.cars" :key="item.id" style="border-bottom: 1px solid #E5E5E5;">
+        <view class="item">
+          <view class="l">车牌号:</view>
+          <view class="r">
+            {{ item.carNo }}
+          </view>
+        </view>
+        <view class="item">
+          <view class="l">规格:</view>
+          <view class="r">
+            <label v-if="item.carSize">{{ item.carSize }} (米)</label>
+            <label v-else>-</label>
+          </view>
+        </view>
+        <view class="item" v-if="item.realInTime">
+          <view class="l">入场时间:</view>
+          <view class="r">
+            {{ item.realInTime }}
+          </view>
+        </view>
+        <view class="item" v-if="item.realOutTime">
+          <view class="l">离场时间:</view>
+          <view class="r">
+            {{ item.realOutTime }}
+          </view>
+        </view>
+        <view class="item" v-if="item.operator">
+          <view class="l">作业人员:</view>
+          <view class="r">
+            {{ item.operator }}
+          </view>
+        </view>
+        <view class="item" v-if="item.operateTime">
+          <view class="l">作业时间:</view>
+          <view class="r">
+            {{ item.operateTime }}
+          </view>
+        </view>
+      </view>
+
+      <view class="item-line">
+        业务项
+      </view>
+      <view class="item" v-for="item in form.items" :key="item.id">
+        <view class="l" style="flex: 7;">{{ item.itemTypeName }}:</view>
+        <view class="r">
+          {{ item.itemName }}({{ item.itemPrice }}x{{ item.num }}={{ item.total }}元)
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">业务费:</view>
+        <view class="r">
+          {{ form.itemPrice }}
+          <text>(元)</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">订单状态:</view>
+        <view class="r">
+          <text v-if="form.confirmInput==0">未确认</text>
+          <text v-else>已确认</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">支付状态:</view>
+        <view class="r">
+          <text v-if="form.payStatus==1">未支付</text>
+          <text v-if="form.payStatus==3">已支付</text>
+        </view>
+      </view>
+      <view class="hj">
+        总费用:{{ form.itemPrice }}元
+      </view>
+      <u-button type="primary" text="返回" @click="backFn"></u-button>
+      <view style="height: 80rpx;"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      form: {}
+    }
+  },
+  onShow() {
+  },
+
+  onLoad(options) {
+    this.id = options.id;
+  },
+  onShow() {
+    this.getBusinessById();
+  },
+  methods: {
+    backFn() {
+      this.$common.back();
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.id
+      }).then(resp => {
+        this.form = resp.data;
+      })
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 30rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 590 - 0
app-ui/pages/onely-disinfect/type-business.vue

@@ -0,0 +1,590 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">{{ goods.name }}</text>
+      </view>
+      <view class="item" v-if="goods.needDeclare==1">
+        <view class="l">
+          <text style="color: red;" v-if="goods.needDeclare==1">*</text>
+          申报单号:
+        </view>
+        <view class="r">
+          <u-input placeholder="申报订单号" v-model="form.declareNo" clearable readonly>
+            <text slot="suffix" style="font-size: 50rpx;" @click="selectDeclare">+</text>
+          </u-input>
+        </view>
+      </view>
+      <view class="item" v-if="goods.needCustomer==1">
+        <view class="l">客户:</view>
+        <view class="r" style="flex: 12;">
+          <picker :disabled="goods.needDeclare==1" v-if="customer.customerList.length>0" class="p-picker"
+                  @change="customerChange($event)" :value="customer.index" :range="customer.customerList"
+                  range-key="name">
+            <text class="p-text">{{ customer.customerList[customer.index].name }}</text>
+          </picker>
+        </view>
+      </view>
+      <view class="item" v-if="goods.needOwner==1">
+        <view class="l">
+          <text style="color: red;">*</text>
+          货主:
+        </view>
+        <view class="r">
+          <u-input placeholder="输入货主" v-model="form.owner">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">作业人员:</view>
+        <view class="r">
+          <u-input placeholder="输入作业人员" v-model="form.operator">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;" v-if="goods.needOperateTime">*</text>
+          作业时间:
+        </view>
+        <view class="r">
+          <uni-datetime-picker type="datetime" v-model="form.operateTime"/>
+        </view>
+      </view>
+      <view class="item-line">
+        <u-row style="height: 40px;">
+          <u-col span=4>车辆</u-col>
+          <u-col span=8>
+            <u-button type="primary" text="添加" @click="addCar" icon="plus"
+                      style="width: 60px;height: 26px;" v-if="goods.mulCar==1||car.list.length==0"/>
+          </u-col>
+        </u-row>
+      </view>
+      <view class="item" v-for="(car,index) in car.list" :key="index">
+        <view class="l">车牌:</view>
+        <view class="r">
+          <u-input placeholder="车辆" v-model="car.carNo" readonly>
+            <view slot="suffix" style="display: flex;">
+              <u-icon @click="editCar(car)" size="20" name="edit-pen-fill" color="blue"></u-icon>
+              <u-icon style="margin-left:20rpx;" size="20" @click="delCar(car)" name="close-circle-fill"
+                      color="red"></u-icon>
+            </view>
+          </u-input>
+        </view>
+      </view>
+      <view class="item-line" style="margin-top: 30rpx;">
+        业务项
+      </view>
+      <view class="business-list" v-for="(item,index) in typeList">
+        <u-row>
+          <u-col span="4.5">
+            <text>
+              <text style="color: red;display: inline;" v-if="item.need==1">*</text>
+              {{ item.name }}:
+            </text>
+          </u-col>
+          <u-col span="7.5">
+            <u-row>
+              <u-col span="10" @click="showSelect(item)">
+                {{ item.itemName ? item.itemName : '请选择' }}
+              </u-col>
+              <u-col span="2" @click="item.itemName='',item.itemId=''" v-if="item.itemId">
+                <u-icon style="margin-left:15rpx;display: inline;" size="20" name="close-circle-fill"
+                        color="red"></u-icon>
+              </u-col>
+            </u-row>
+          </u-col>
+        </u-row>
+        <view style="display: flex;position: relative;left: 30%;" v-if="item.itemName">
+          <u-number-box style="margin-left: 15rpx;" :disabled="item.inc==0" v-model="item.num"></u-number-box>
+          <text style="margin-left: 20rpx;color: red;">
+            ¥{{ item.num * item.price }}
+          </text>
+          <view style="margin-left: 60rpx;" @click="remarkFn(item)">
+            备注
+          </view>
+        </view>
+        <u-line></u-line>
+      </view>
+      <view class="hj" v-show="totalPrice>0">
+        合计:{{ totalPrice }}元
+      </view>
+    </view>
+    <u-button type="primary" text="确定" @click="saveFn" v-show="perList.indexOf('tb-flex-business-add')!==-1">
+    </u-button>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+    <u-picker :show="show" :columns="columns" @confirm="confirmFn" keyName="itemName" @cancel="show=false">
+    </u-picker>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      show: false,
+      columns: [],
+      customerId: '1',
+      customer: {
+        index: 0,
+        customerList: [],
+      },
+      goods: {
+        id: '',
+        name: '',
+        mulCar: 0
+      },
+      typeList: [],
+      allTypeList: [],
+      form: {
+        customerId: '',
+        declareNo: '',
+        carNo: '',
+        owner: '',
+        carSize: '',
+        goodsName: '',
+        netWeight: '',
+      },
+      show: false,
+      item: {
+        items: []
+      },
+      car: {
+        list: [{
+          id: '',
+          carNo: '',
+          index: 0
+        }]
+      },
+      perList: []
+    }
+  },
+  onShow() {
+    this.perList = uni.getStorageSync('perList')
+  },
+  computed: {
+    totalPrice() {
+      let typeList = this.typeList.filter(obj => obj.itemName);
+      let price = 0;
+      for (let i in typeList) {
+        let type = typeList[i];
+        price = price + type.price * type.num;
+      }
+      return price;
+    },
+  },
+  onLoad(options) {
+    this.customerId = uni.getStorageSync('customerId');
+    this.goods = JSON.parse(options.goodsJson);
+    this.getCustomerList();
+    this.getTypeByGoodsId();
+    let that = this;
+    uni.$on('getSelectDeclare', declare => {
+      that.$nextTick(() => {
+        that.handlerSelectDeclare(declare)
+      })
+    })
+    uni.$on('getCar', car => {
+      that.$nextTick(() => {
+        that.handlerCar(car)
+      })
+    })
+    uni.$on('getRemark', type => {
+      that.$nextTick(() => {
+        that.handlerRemark(type)
+      })
+    })
+  },
+  methods: {
+    remarkFn(type) {
+      let remark = type.remark ? type.remark : '';
+      this.$common.to('/pages/onely-disinfect/add-remark?needRemark=' + type.needRemark + '&typeId=' + type.id +
+          '&remark=' + remark)
+    },
+    handlerRemark(type) {
+      let typeList = this.typeList;
+      typeList.filter(obj => type.typeId == obj.id).forEach(obj => obj.remark = type.remark)
+    },
+    addCar() {
+      this.car.list.push({
+        index: Math.random(),
+        id: '',
+        carNo: '',
+        index: 0
+      })
+    },
+    filterItems(car) {
+      let carList = this.car.list;
+      let filterTypeList = JSON.parse(JSON.stringify(this.allTypeList));
+      if (carList.length == 0) {
+        this.typeList = filterTypeList;
+        return;
+      }
+      if (!car) {
+        let checkList = carList.filter(obj => obj.carType.indexOf('空') === -1);
+        if (checkList.length > 0) {
+          car = checkList[0];
+        }
+      }
+      let carSize = car.carSize;
+      let carType = car.carType;
+      if (carType.indexOf('空') !== -1 && carList.length > 1) {
+        return;
+      }
+      let netWeight = car.netWeight;
+      let tempList = [];
+      for (let i in filterTypeList) {
+        let type = filterTypeList[i];
+        let items = type.items;
+        if (carType) {
+          items = items.filter(item => item.itemType && item.itemType.indexOf(carType) !== -1);
+        }
+        if (carSize && carSize > 1) {
+          items = items.filter(item => item.minLength <= carSize && item.carLength >= carSize);
+        }
+        if (netWeight && netWeight > 1 && carType.indexOf('空') == -1) {
+          items = items.filter(item => item.minWeight <= netWeight && item.maxWeight >= netWeight);
+        }
+        let itemIds = items.map(item => item.id);
+        if (itemIds.indexOf(type.itemId) == -1) {
+          this.cleanItem(type);
+        }
+        type.items = items;
+        tempList.push(type);
+      }
+      this.typeList = tempList;
+    },
+    cleanItem(type) {
+      type.itemId = '';
+      type.itemName = '';
+      type.price = '';
+    },
+    showSelect(item) {
+      if (this.validBefore()) {
+        this.columns = [];
+        this.columns.push(item.items);
+        this.show = true;
+      }
+    },
+    confirmFn(e) {
+      let selects = e.value;
+      if (selects.length > 0) {
+        let item = selects[0];
+        let typeId = item.typeId;
+        let typeList = this.typeList;
+        typeList.filter(obj => obj.id == typeId).forEach(obj => {
+          obj.itemId = item.id;
+          obj.itemName = item.itemName;
+          obj.inc = item.inc;
+          obj.price = item.price;
+          obj.needRemark = item.needRemark;
+        })
+      }
+      this.show = false;
+    },
+    getTypeByGoodsId() {
+      this.$api.getTypeByGoodsId({
+        goodsId: this.goods.id
+      }).then(resp => {
+        let list = resp.data;
+        this.allTypeList = JSON.parse(JSON.stringify(list));
+        this.typeList = list;
+      })
+    },
+    getCustomerList() {
+      this.$api.getCustomerList({
+        pageNo: 1,
+        pageSize: 100
+      }).then(resp => {
+        let list = resp.data;
+        let customerId = this.customerId;
+        if (customerId !== '1') {
+          this.customer.index = list.map(obj => obj.id).indexOf(customerId);
+        }
+        this.customer.customerList = list;
+      })
+    },
+    customerChange(e) {
+      var value = e.detail.value; //当前picker选中的值
+      this.customer.index = value;
+    },
+    handlerCar(car) {
+      let list = this.car.list;
+      let check = list.filter(obj => obj.carNo == car.carNo).pop();
+      if (check) {
+        check.carSize = car.carSize;
+        check.netWeight = car.netWeight;
+        check.carType = car.carType;
+      } else {
+        this.car.list.push(car);
+      }
+      this.clearEmptyCar(car);
+    },
+    clearEmptyCar(car) {
+      let list = this.car.list;
+      let obj = list.filter(obj => !obj.carNo).pop();
+      if (obj) {
+        this.car.list.splice(list.indexOf(obj), 1);
+      }
+      this.filterItems(car);
+    },
+    handlerSelectDeclare(declare) {
+      let oldDeclareNo = this.form.declareNo;
+      if (oldDeclareNo && oldDeclareNo !== declare.declareNo) {
+        this.car.list = [];
+      }
+      this.form.declareNo = declare.declareNo;
+      this.form.cardNo = declare.carNo;
+      this.form.chinaCarNo = declare.chinaCarNo;
+      this.form.netWeight = declare.grossWeight;
+      this.form.owner = declare.sendUnit;
+      let customerList = this.customer.customerList;
+      this.customer.index = customerList.map(customer => customer.id).indexOf(declare.customerId);
+      let carNo = declare.carNo;
+      let grossWeight = declare.grossWeight;
+      let carList = this.car.list;
+      let exit = carList.filter(obj => obj.carNo == carNo).pop();
+      if (!exit) {
+        let car = {
+          carNo: carNo,
+          netWeight: grossWeight,
+          carType: '载重'
+        }
+        this.car.list.push(car)
+      }
+      this.form.cardNo = declare.carNo;
+      this.form.chinaCarNo = declare.chinaCarNo;
+      this.form.netWeight = declare.grossWeight;
+      let chinaCarNo = declare.chinaCarNo;
+      if (chinaCarNo) {
+        let list = [];
+        chinaCarNo.replace(",", ",").split(",").forEach(carNo => {
+          let exit = carList.filter(obj => obj.carNo == carNo).pop();
+          if (!exit) {
+            let car = {
+              carNo: carNo,
+              carType: '空车',
+            }
+            this.car.list.push(car)
+          }
+        })
+      }
+      this.clearEmptyCar();
+    },
+
+    selectDeclare() {
+      this.$common.to('/pages/business-entering/declare-select?declareNo=' + this.form.declareNo)
+    },
+    editCar(car) {
+      let goods = this.goods;
+      this.$common.to('/pages/onely-disinfect/car-manager?carJson=' + JSON.stringify(car) + "&needCarSize=" +
+          goods.needCarSize + '&needWeight=' + goods.needWeight)
+    },
+
+    delCar(car) {
+      let list = this.car.list;
+      if (list.length == 1) {
+        this.$common.toast('至少有一辆车');
+        return;
+      }
+      this.car.list.splice(list.indexOf(car), 1);
+      this.filterItems();
+    },
+    validBefore() {
+      let form = this.form;
+      let goods = this.goods;
+      let needDeclare = goods.needDeclare;
+      let needCustomer = goods.needCustomer;
+      let index = this.customer.index;
+      if (needDeclare == 1 && !form.declareNo) {
+        this.$common.toast('请选择申报单');
+        return false;
+      }
+      if (!form.owner && goods.needOwner == 1) {
+        this.$common.toast('请填写货主');
+        return false;
+      }
+      let needOperateTime = goods.needOperateTime;
+      let operateTime = form.operateTime;
+      if (!operateTime && needOperateTime == '1') {
+        this.$common.toast('请录入作业时间');
+        return false;
+      }
+      if (operateTime && operateTime.length < 12) {
+        this.$common.toast('请录入准确的作业时间');
+        return false;
+      }
+      let carList = this.car.list;
+      if (carList.length == 0) {
+        this.$common.toast('请录入车辆');
+        return false;
+      }
+      let needCarSize = goods.needCarSize;
+      let needWeight = goods.needWeight;
+      for (let i in carList) {
+        let car = carList[i];
+        if (needCarSize == 1 && !car.carSize) {
+          this.$common.toast('请补充' + car.carNo + '的规格');
+          return false;
+        }
+        if (needWeight == 1 && car.carType.indexOf('重') !== -1 && !car.netWeight) {
+          this.$common.toast('请补充' + car.carNo + '载重');
+          return false;
+        }
+      }
+      return true;
+    },
+    check() {
+      let form = this.form;
+      let goods = this.goods;
+      let needDeclare = goods.needDeclare;
+      let needCustomer = goods.needCustomer;
+      let index = this.customer.index;
+      if (needDeclare == 1 && !form.declareNo) {
+        this.$common.toast('请选择申报单');
+        return false;
+      }
+      if (!form.owner && goods.needOwner == 1) {
+        this.$common.toast('请填写货主');
+        return false;
+      }
+      let needOperateTime = goods.needOperateTime;
+      let operateTime = form.operateTime;
+      if (!operateTime && needOperateTime == '1') {
+        this.$common.toast('请录入作业时间');
+        return false;
+      }
+      if (operateTime && operateTime.length < 12) {
+        this.$common.toast('请录入准确的作业时间');
+        return false;
+      }
+      let carList = this.car.list;
+      if (carList.length == 0) {
+        this.$common.toast('请录入车辆');
+        return false;
+      }
+      let needCarSize = goods.needCarSize;
+      let needWeight = goods.needWeight;
+      for (let i in carList) {
+        let car = carList[i];
+        if (needCarSize == 1 && !car.carSize) {
+          this.$common.toast('请补充' + car.carNo + '的规格');
+          return false;
+        }
+        if (needWeight == 1 && car.carType.indexOf('重') !== -1 && !car.netWeight) {
+          this.$common.toast('请补充' + car.carNo + '载重');
+          return false;
+        }
+      }
+      let typeList = this.typeList;
+      let selectList = [];
+      for (let i in typeList) {
+        let type = typeList[i];
+        if (type.need == 1 && !type.itemId) {
+          this.$common.toast('【' + type.name + '】必选');
+          return false;
+        }
+        if (type.needRemark == 1 && !type.remark) {
+          this.$common.toast('请录入【' + type.name + '】备注');
+          return false;
+        }
+        if (type.itemId) {
+          let obj = {
+            typeId: type.id,
+            typeName: type.name,
+            id: type.itemId,
+            num: type.num,
+            price: type.price,
+            remark: type.remark
+          }
+          selectList.push(obj);
+        }
+      }
+      this.form.itemJson = JSON.stringify(selectList);
+      this.form.carJson = JSON.stringify(this.car.list);
+      this.form.items = null;
+      if (needCustomer == 1) {
+        let customerList = this.customer.customerList;
+        let index = this.customer.index;
+        let customer = customerList[index];
+        this.form.customerId = customer.id;
+        this.form.customerName = customer.name;
+      } else {
+        this.form.customerId = '';
+        this.form.customerName = '';
+      }
+      this.form.goodsId = this.goods.id;
+      this.form.goodsName = this.goods.name;
+      let chinaCarNo = carList
+          .filter(car => this.$common.isCarNo(car.carNo.toUpperCase()))
+          .map(car => car.carNo.toUpperCase())
+          .join("、");
+      let yueCarNo = carList
+          .filter(car => !this.$common.isCarNo(car.carNo.toUpperCase()))
+          .map(car => car.carNo.toUpperCase())
+          .join("、");
+      this.form.cardNo = yueCarNo;
+      this.form.chinaCarNo = chinaCarNo;
+      return true;
+    },
+    saveFn() {
+      if (this.check()) {
+        let obj = this.$common.removeNull(this.form);
+        this.$api.addOtherBusiness(obj).then(resp => {
+          if (resp.code == 200) {
+            this.$common.toast('录入成功');
+            setTimeout(() => {
+              this.$common.to('/pages/onely-disinfect/Index')
+            }, 1000)
+          }
+        })
+      }
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.business-list {
+  line-height: 75rpx;
+  margin: 4rpx 0 0 48rpx;
+
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 314 - 0
app-ui/pages/partner/index.vue

@@ -0,0 +1,314 @@
+<template>
+  <view>
+    <view class="top-nav">
+      <view class="l">
+        <block v-if="isLogin">
+          <image class="user-img" src="../../static/user.png" @click="toAccount"></image>
+          <view class="l-r">
+            <text class="u-name">{{ userName }}</text>
+            <text class="c-name" v-if="customerId!=='1'">{{ companyName }}</text>
+          </view>
+        </block>
+        <block v-else>
+          <view class="login-btn" @click="toLogin">登录</view>
+        </block>
+      </view>
+      <view class="r" v-if="isLogin">
+        <view class="l-out" @click="exitFn">
+          退出登录
+        </view>
+      </view>
+    </view>
+    <view class="top-bg"></view>
+    <view class="top">
+      <text class="title">场站管理系统</text>
+    </view>
+    <view class="item-box">
+      <view class="item" hover-class="hover-class" v-for="(indexItem,index) in indexItemList" :key="index"
+            @click="navTo(indexItem)" v-show="indexItem.show">
+        <image class="icon" :src="indexItem.icon"></image>
+        <view class="text">
+          <text v-if="indexItem.text=='企业管理'&&customerId!='1'">信息管理</text>
+          <text v-else>{{ indexItem.text }}</text>
+        </view>
+      </view>
+    </view>
+    <view class="qrcode">
+      <image class="qrcode" :src="qrcoderlc"></image>
+      <text class="text">长按二维码保存分享</text>
+    </view>
+    <view style="text-align: center;font-size: 23rpx;">
+      <a href="https://beian.miit.gov.cn/" target="_blank">桂ICP备12007573号-1</a>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      isLogin: false, //是否登录状态
+      userName: '',
+      companyName: '',
+      customerId: '',
+      qrcoderlc: '../../static/qrcode.png',
+      indexItemList: []
+    }
+  },
+  onShow() {
+    this.getStoreInfo();
+    this.setList();
+  },
+  onBackPress() {
+    return true;
+  },
+  methods: {
+    setList() {
+      this.indexItemList = [{
+        auth: false,
+        icon: '../../static/home-icon-01.png',
+        text: '企业注册',
+        url: '/pages/enterprise-reg/enterprise-reg',
+        show: uni.getStorageSync('info') ? false : true
+      },
+        {
+          auth: false,
+          icon: '../../static/home-icon-07.jpg',
+          text: '申报录入',
+          url: '/pages/declare/add',
+          show: true
+        },
+        {
+          auth: false,
+          icon: '../../static/home-icon-06.jpg',
+          text: '消杀申报',
+          url: '/pages/disinfect/addDisinfect',
+          show: true
+        },
+        {
+          auth: true,
+          icon: '../../static/home-icon-02.png',
+          text: '业务录入',
+          url: '/pages/business-entering/business-entering',
+          show: uni.getStorageSync('perList').indexOf('tb-business-add') !== -1
+        },
+        {
+          auth: true,
+          icon: '../../static/home-icon-03.png',
+          text: '业务订单',
+          url: '/pages/business-order/business-order',
+          show: true
+        },
+        {
+          auth: true,
+          icon: '../../static/home-icon-04.png',
+          text: '企业管理',
+          url: '/pages/customer-management/customer-list',
+          show: true
+        },
+        {
+          auth: true,
+          icon: '../../static/home-icon-05.png',
+          text: '出入记录',
+          url: '/pages/inout-record/inout-record',
+          show: true
+        },
+
+        // {
+        // 	auth: true,
+        // 	icon: '../../static/home-icon-06.jpg',
+        // 	text: '账户充值',
+        // 	url: '/pages/account/index',
+        // 	show:true
+        // },
+
+      ]
+    },
+    toAccount() {
+      if (this.customerId !== '1') {
+        this.$common.to('/pages/account/account-redirect')
+      }
+    },
+    getStoreInfo() {
+      let info = uni.getStorageSync('info');
+      if (info) {
+        this.isLogin = true;
+        this.userName = info.name;
+        this.customerId = info.customerId;
+      }
+    },
+    toLogin() {
+      this.$common.to('/pages/login/login')
+    },
+    exitFn() {
+      uni.removeStorageSync('token')
+      uni.removeStorageSync('info')
+      this.isLogin = false;
+      this.setList();
+    },
+    navTo(item) {
+      let auth = item.auth;
+      let token = uni.getStorageSync('token');
+      if (!auth || token) {
+        this.$common.to(item.url)
+      } else {
+        this.$common.to('/pages/login/login')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.top-nav {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  z-index: 999;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 20rpx 0;
+  background-color: #0080ff;
+
+  .l {
+    display: flex;
+    align-items: center;
+
+    .login-btn {
+      border: 1rpx solid #359aff;
+      border-radius: 8rpx;
+      color: #fff;
+      padding: 10rpx 20rpx;
+      font-size: 28rpx;
+      margin-left: 30rpx;
+    }
+
+    .user-img {
+      width: 80rpx;
+      height: 80rpx;
+      border-radius: 50%;
+      margin-left: 30rpx;
+      margin: 20rpx;
+    }
+
+    .l-r {
+      display: flex;
+      flex-direction: column;
+
+      .u-name {
+        font-size: 30rpx;
+        color: #fff;
+        font-weight: bold;
+      }
+
+      .c-name {
+        font-size: 24rpx;
+        color: #fff;
+      }
+    }
+  }
+
+  .r {
+    display: flex;
+    align-items: center;
+
+    .l-out {
+      border: 1rpx solid #359aff;
+      border-radius: 8rpx;
+      color: #c8e4ff;
+      padding: 10rpx 20rpx;
+      font-size: 28rpx;
+      margin-right: 30rpx;
+    }
+  }
+}
+
+.top-bg {
+  position: relative;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 400rpx;
+  background-color: #0080ff;
+  border-radius: 0 0 20rpx 20rpx;
+}
+
+.top {
+  display: flex;
+  width: 100%;
+  align-items: center;
+  justify-content: center;
+  margin: 60rpx 0;
+  margin-top: -400rpx;
+  position: relative;
+  z-index: 2;
+
+  .title {
+    font-size: 50rpx;
+    font-weight: bold;
+    color: #fff;
+  }
+}
+
+.item-box {
+  display: flex;
+  flex-wrap: wrap;
+  align-content: flex-start;
+  padding: 40rpx;
+  box-sizing: border-box;
+  background-color: #fff;
+  margin: 0 30rpx;
+  border-radius: 20rpx;
+  position: relative;
+  z-index: 2;
+  //height: calc(100vh - 170rpx - 500rpx);
+  box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.03);
+
+  .item {
+    width: 33.333%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 40rpx 0;
+
+    .icon {
+      width: 90rpx;
+      height: 90rpx;
+    }
+
+    .text {
+      font-size: 28rpx;
+      color: #191919;
+      margin-top: 20rpx;
+    }
+  }
+}
+
+.qrcode {
+  display: flex;
+  width: 100%;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  margin: 30rpx 0;
+
+  .qrcode {
+    width: 350rpx;
+    height: 350rpx;
+    border: 1px solid #191919;
+  }
+
+  .text {
+    color: #191919;
+    font-size: 28rpx;
+    margin-top: 5rpx;
+  }
+}
+</style>

+ 198 - 0
app-ui/pages/user/addUser.vue

@@ -0,0 +1,198 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title" v-if="!form.id">添加用户</text>
+        <text class="title" v-else>编辑用户</text>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          用户名:
+        </view>
+        <view class="r">
+          <u-input placeholder="用户名" v-model="form.name">
+          </u-input>
+        </view>
+      </view>
+      <view class="item" v-if="!form.id">
+        <view class="l">
+          <text style="color: red;">*</text>
+          密码:
+        </view>
+        <view class="r">
+          <u-input placeholder="密码" type="password" v-model="form.password">
+          </u-input>
+        </view>
+      </view>
+      <view class="item" v-if="!form.id">
+        <view class="l">
+          <text style="color: red;">*</text>
+          再输一次:
+        </view>
+        <view class="r">
+          <u-input placeholder="再输一次" type="password" v-model="form.againPassword">
+          </u-input>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <text style="color: red;">*</text>
+          角色:
+        </view>
+      </view>
+      <view class="item">
+        <view class="l">
+          <u-checkbox-group v-model="roleList">
+            <u-checkbox :customStyle="{marginBottom: '10px',marginLeft:'10px'}"
+                        v-for="(item, index) in checkboxList" :key="index" :label="item.name" :name="item.id">
+            </u-checkbox>
+          </u-checkbox-group>
+        </view>
+      </view>
+      <view class="item" v-show="form.id">
+        <view class="l">
+          状态:
+        </view>
+        <view class="r">
+          <radio-group @change="statusChange">
+            <label class="radio">
+              <radio value="1" :checked="form.status==1"/>
+              可用
+            </label>
+            <label class="radio" style="margin-left: 20rpx;">
+              <radio value="2" :checked="form.status==2"/>
+              禁用
+            </label>
+          </radio-group>
+        </view>
+      </view>
+
+    </view>
+    <u-button type="primary" text="确定" @click="saveFn"></u-button>
+    <!-- ---------------------------------------------------------- -->
+    <view class="bottom-safety"></view>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      roleList: [],
+      checkboxList: [],
+      form: {
+        id: '',
+        status: 1,
+        customerId: '',
+        name: '',
+        password: '',
+        againPassword: '',
+      },
+      perList: []
+    }
+  },
+  onLoad(options) {
+    this.form.id = options.id;
+    this.form.name = options.name;
+    this.form.status = options.status;
+    this.roleList = options.roleId ? options.roleId.split(',').map(id => parseInt(id)) : [];
+    console.log(this.roleList)
+    let info = uni.getStorageSync('userInfo');
+    let customerId = info.customerId;
+    this.form.customerId = customerId;
+    this.getRoleList();
+  },
+  onShow() {
+    this.perList = uni.getStorageSync('perList');
+  },
+  onBackPress() {
+    this.$common.to('/pages/user/user-index');
+    return true;
+  },
+  methods: {
+    statusChange(e) {
+      this.form.status = e.detail.value
+    },
+    getRoleList() {
+      this.$api.getRoleList({
+        customerId: this.form.customerId
+      }).then(resp => {
+        this.checkboxList = resp.data;
+      })
+    },
+    saveFn() {
+      if (!this.form.name) {
+        this.$common.toast('请填写用户名');
+        return;
+      }
+      if (!this.form.password && !this.form.id) {
+        this.$common.toast('请填写密码');
+        return;
+      }
+      if (this.form.password != this.form.againPassword) {
+        this.$common.toast('两次密码不一致');
+        return;
+      }
+      if (this.roleList.length == 0) {
+        this.$common.toast('请选择用户角色');
+        return;
+      }
+      this.form.roleId = this.roleList.join(',');
+      if (this.form.id) {
+        this.$api.editCustomerAdmin(this.$common.removeNull(this.form)).then(resp => {
+          if (resp.code == 200) {
+            this.$common.to('/pages/user/addUserSuccess')
+          }
+        })
+      } else {
+        this.$api.addCustomerAdmin(this.$common.removeNull(this.form)).then(resp => {
+          if (resp.code == 200) {
+            this.$common.to('/pages/user/addUserSuccess')
+          }
+        })
+      }
+    },
+  },
+
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.hs-item {
+  text-align: center;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+.hj {
+  padding: 50rpx;
+  font-size: 40rpx;
+  color: red;
+  font-weight: bold;
+}
+
+.save-btn {
+  background-color: #ff4200;
+  height: 88rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 60rpx;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: bold;
+  border-radius: 10rpx;
+}
+
+@import '@/common/common.scss'
+</style>

+ 57 - 0
app-ui/pages/user/addUserSuccess.vue

@@ -0,0 +1,57 @@
+<template>
+  <view class="box">
+    <u-icon name="checkmark-circle-fill" color="#07c160" size="200"></u-icon>
+    <text class="text">提交成功!</text>
+    <view class="count-down-box">
+      <view @click="goback">返回</view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      timestamp: 3,
+    }
+  },
+  onBackPress() {
+    this.goback();
+    return true;
+  },
+  methods: {
+    goback() {
+      this.$common.to('/pages/user/user-index');
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+  }
+}
+</style>

+ 66 - 0
app-ui/pages/user/user-index.vue

@@ -0,0 +1,66 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top">
+        <text class="title">用户管理</text>
+        <text class="add" @click="addUser">+添加
+        </text>
+      </view>
+    </view>
+    <view>
+      <u-cell-group>
+        <u-cell :isLink="true" arrow-direction="right" @click="toUserFn(item)"
+                :value="item.roleName"
+                v-for="(item,index) in userList">
+          <u-icon name="account" slot="icon" size="30"></u-icon>
+          <text slot="title" style="font-size: 40rpx;">{{ item.name }}</text>
+        </u-cell>
+      </u-cell-group>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      customerId: '',
+      userList: []
+    }
+  },
+  onShow() {
+    let info = uni.getStorageSync('userInfo');
+    this.customerId = info.customerId;
+    this.getUserList();
+  },
+  onBackPress() {
+    this.$common.to('/');
+    return true;
+  },
+  methods: {
+    getUserList() {
+      this.$api.getUserList({customerId: this.customerId}).then(resp => {
+        this.userList = resp.data;
+      })
+    },
+    toUserFn(data) {
+      this.$common.to('/pages/user/addUser?id=' + data.id + '&name=' + data.name + '&roleId=' + data.roleId + '&status=' + data.status)
+    },
+    addUser() {
+      this.$common.to('/pages/user/addUser')
+    }
+  }
+}
+</script>
+<style lang="scss">
+.add {
+  position: absolute;
+  right: 40rpx;
+  top: -60rpx;
+  z-index: 999;
+  font-size: 40rpx;
+  color: white;
+}
+
+@import '@/common/common.scss'
+</style>

+ 317 - 0
app-ui/pages/wx/account-pay.vue

@@ -0,0 +1,317 @@
+<template>
+  <view>
+    <view class="top-bg"></view>
+    <view class="top-box">
+      <view class="top">
+        <text class="num">{{ account.totalMoney }}</text>
+        <text class="p">账户余额</text>
+      </view>
+      <view class="bottom">
+        <view class="t">
+          <view class="p">账户:</view>
+          <view class="num">{{ account.accountNo }}</view>
+        </view>
+      </view>
+    </view>
+    <view class="item">
+      <view class="l" style="margin-top: 15rpx;">
+        充值金额:
+      </view>
+      <view class="r">
+        <u-input type="number" style="border: 1rpx solid;margin-left: 8rpx;" placeholder="充值金额"
+                 v-model="form.money">
+        </u-input>
+      </view>
+    </view>
+    <view v-if="money&&money>0" class="pay-money">
+      支付金额:
+      <text>{{ money }} 元</text>
+    </view>
+    <view class="btn-box">
+      <view class="btn t" @click="chargeFn">立即充值</view>
+    </view>
+    <view class="discount" v-if="discountList.length>0">
+      活动:
+      <view v-for="(item,index) in discountList">
+        {{ index + 1 }}、充值满{{ item.money }}元
+        <text v-if="item.discount<10">打{{ item.discount }}折</text>
+        <text v-if="item.subtract">减{{ item.subtract }}元</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+var jweixin = require('@/components/jweixin-module/index.js');
+export default {
+  data() {
+    return {
+      account: {
+        totalMoney: 0,
+        lockMoney: 0,
+        activeMoney: 0,
+        deposit: 0
+      },
+      form: {
+        money: ''
+      },
+      code: '',
+      openid: '',
+      discountList: []
+    }
+  },
+  onLoad(options) {
+    this.code = options.code;
+    this.getOpenidByCode();
+  },
+  onBackPress() {
+    this.$common.to('/pages/index/index');
+    return true;
+  },
+  mounted() {
+    this.getAccountInfo();
+    this.getDiscountInfo();
+    this.getWxConfig();
+  },
+  computed: {
+    money() {
+      let chargeMoney = this.form.money;
+      if (chargeMoney) {
+        let discountList = this.discountList;
+        let sub = 999999;
+        let obj = null;
+        for (let i in discountList) {
+          let discount = discountList[i];
+          let m = discount.money;
+          let diff = chargeMoney - m;
+          if (diff < sub && diff >= 0) {
+            sub = diff;
+            obj = discount;
+          }
+        }
+        if (obj != null) {
+          if (obj.type == 1) {
+            return (chargeMoney * (obj.discount / 10)).toFixed(2)
+          }
+          return chargeMoney - obj.subtract
+        }
+      }
+    }
+  },
+  methods: {
+    getWxConfig() {
+      let url = window.location.href;
+      this.$api.getWxConfig({
+        url: url
+      }).then(resp => {
+        jweixin.config({
+          //debug: true,
+          appId: resp.data.appId,
+          timestamp: resp.data.timestamp, // 必填,生成签名的时间戳
+          nonceStr: resp.data.noncestr, // 必填,生成签名的随机串
+          signature: resp.data.sign, // 必填,签名
+          jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表
+        });
+        jweixin.ready(function () {
+
+        });
+        jweixin.error(function (res) {
+          console.log(res)
+        });
+      })
+    },
+    getOpenidByCode() {
+      let storeOpenid = uni.getStorageSync('openid');
+      this.$api.getOpenidByCode({
+        code: this.code,
+        openid: storeOpenid
+      }).then(resp => {
+        let openid = resp.data;
+        this.openid = openid;
+        if (openid) {
+          uni.setStorageSync('openid', openid)
+        }
+
+      })
+    },
+    getAccountInfo() {
+      this.$api.getAccountInfo().then(resp => {
+        this.account = resp.data;
+      })
+    },
+    getDiscountInfo() {
+      this.$api.getDiscountInfo().then(resp => {
+        this.discountList = resp.data;
+      })
+    },
+    chargeFn() {
+      let money = this.form.money;
+      if (!money) {
+        this.$common.toast('请输入充值金额');
+      }
+      let a = {
+        id: this.account.id,
+        c: money
+      }
+      let p = {
+        a: JSON.stringify(a),
+        money: this.money > 0 ? this.money : money,
+        tradeType: "JSAPI",
+        openid: this.openid
+      }
+      p.desc = "A1-账户充值";
+      this.$api.getPrePay(this.$common.removeNull(p)).then(resp => {
+        let data = resp.data;
+        let that = this;
+        jweixin.chooseWXPay({
+          timestamp: data
+              .timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+          nonceStr: data.nonceStr, // 支付签名随机串,不长于 32 位
+          package: data.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+          signType: data.signType, // 微信支付V3的传入RSA,微信支付V2的传入格式与V2统一下单的签名格式保持一致
+          paySign: data.paySign, // 支付签名
+          success: function (res) {
+            if (res.errMsg === "chooseWXPay:ok") {
+              that.$common.toast('支付成功')
+              that.cars = [];
+              that.item.list = [];
+              that.total = 0
+              // wx.closeWindow();
+            }
+          }
+        });
+      })
+
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.top-bg {
+  width: 100%;
+  height: 400rpx;
+  position: absolute;
+  z-index: 0;
+  background-image: linear-gradient(0deg, #fff 0%, #0080ff 40%);
+}
+
+.top-box {
+  position: relative;
+  z-index: 1;
+
+  .top {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+
+    .num {
+      color: #fff;
+      font-size: 60rpx;
+      margin-top: 50rpx;
+    }
+
+    .p {
+      color: rgba(255, 255, 255, .7);
+      margin-top: 10rpx;
+    }
+  }
+
+  .bottom {
+    display: flex;
+    background-color: #fff;
+    border-radius: 20rpx;
+    margin: 40rpx;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+
+    .t {
+      display: flex;
+      width: 100%;
+      padding: 40rpx 30rpx;
+      box-sizing: border-box;
+      border-bottom: 1px solid #eee;
+
+      .p,
+      .num {
+        font-size: 30rpx;
+        color: #191919;
+      }
+
+      .num {
+        margin-left: 30rpx;
+      }
+    }
+
+    .b {
+      display: flex;
+      width: 100%;
+      padding-bottom: 60rpx;
+
+    }
+  }
+}
+
+
+.item {
+  display: flex;
+  margin-top: 100rpx;
+  margin-left: 60rpx;
+}
+
+.btn-box {
+  position: relative;
+  z-index: 1;
+  display: flex;
+  border-radius: 20rpx;
+  display: flex;
+  margin: 30rpx;
+  padding: 30rpx;
+  flex-direction: column;
+
+  .btn {
+    height: 88rpx;
+    width: 70%;
+    color: #fff;
+    margin: 20rpx auto;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 10rpx;
+  }
+
+  .t {
+    background-color: #0080ff;
+  }
+
+  .b {
+    background-color: #ffb400;
+  }
+}
+
+.pay-money {
+  margin: 20rpx 0 0 120rpx;
+  font-size: 30rpx;
+
+  text {
+    color: red;
+    font-weight: bold;
+  }
+}
+
+.discount {
+  margin: 0 0 0 60rpx;
+  font-size: 27rpx;
+
+  view {
+    margin-left: 20rpx;
+    padding-top: 10rpx;
+  }
+}
+</style>

+ 70 - 0
app-ui/pages/wx/index.vue

@@ -0,0 +1,70 @@
+<template>
+  <view class="box">
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      timestamp: 3,
+      param: ''
+    }
+  },
+  onLoad(options) {
+    this.param = options.p;
+  },
+  created() {
+    this.$common.showLoading('正在加载...')
+  },
+  mounted() {
+    this.getRedirectUri();
+  },
+  beforeDestroy() {
+    this.$common.hidingLoading()
+  },
+  methods: {
+    getRedirectUri() {
+      this.$api.getRedirectUrl({path: '/pages/wx/pay', state: this.param}).then(resp => {
+        console.log(resp);
+        window.location.href = resp.data;
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    flex: 1;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+
+    text {
+      margin-left: 20rpx;
+    }
+  }
+}
+</style>

+ 449 - 0
app-ui/pages/wx/pay.vue

@@ -0,0 +1,449 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="top" style="padding-top: 50rpx;">
+        <text class="title">缴纳费用</text>
+      </view>
+      <u-search placeholder="输入车牌号查询" shape="square" v-model="p.carNo" @search="searchFn()" @change="searchFn"
+                :height="80" style="margin: 30rpx;">
+      </u-search>
+    </view>
+    <view class="list" v-show="list.length>0">
+      <u-radio-group placement="column" @change="groupChange">
+        <u-radio :customStyle="{marginBottom: '6px',borderBottom: '1px solid #e5e5e5',paddingBottom:'5px'}"
+                 v-for="(item, index) in list" :key="index" :label="item.carNo" :name="item.id">
+        </u-radio>
+      </u-radio-group>
+    </view>
+    <view class="car-list" v-show="cars.length>0">
+      <view class="card">
+        <view class="title">
+          停车费:
+        </view>
+        <u-checkbox-group v-model="carsSelect" placement="column">
+          <view v-for="(item,index) in cars" :key="index">
+            <label class="c-item">
+              <view class="l">
+                <u-checkbox :customStyle="{marginBottom: '8px'}" :name="item.id"
+                            :disabled="item.price==0">
+                </u-checkbox>
+              </view>
+              <view class="c">{{ item.carNo }}</view>
+              <view class="r" v-if="item.price>0">{{ item.price }}元</view>
+              <view class="r" v-else>无需缴费</view>
+            </label>
+          </view>
+        </u-checkbox-group>
+      </view>
+
+      <view class="card" v-if="item.itemsPrice">
+        <view class="title">
+          <u-checkbox-group placement="column" v-model="businessSelect" @change="businessChange">
+            <u-checkbox :disabled="businessAble" :customStyle="{color: 'black'}"
+                        :label="'业务费:'+item.itemsPrice+'元'" :name='1'>
+            </u-checkbox>
+          </u-checkbox-group>
+        </view>
+        <view style="height: 600rpx;overflow-y: auto;">
+          <u-checkbox-group placement="column" v-model="itemSelect">
+            <view v-for="(item,index) in item.list" :key="index">
+              <label class="c-item">
+                <view class="l">
+                  <u-checkbox :customStyle="{marginBottom: '8px'}" disabled :name="item.id">
+                  </u-checkbox>
+                </view>
+                <view class="c">{{ item.name }}</view>
+                <view class="r">¥{{ item.price }}</view>
+              </label>
+            </view>
+          </u-checkbox-group>
+        </view>
+
+      </view>
+      <view style="height: 60rpx;">
+
+      </view>
+    </view>
+    <view v-if="showTips">
+      <view class="tips">
+        <view>
+          未查询到相关费用,可能原因:
+        </view>
+        <view>
+          1、车辆无需缴费。
+        </view>
+        <view>
+          2、业务订单需管理员确认后方可缴费。
+        </view>
+      </view>
+    </view>
+    <view class="bottom bgc-f bottom-safety" v-if="total>0">
+      <view class="box">
+        <view class="l">
+          <text class="t1">金额:</text>
+          <text class="t2">¥{{ total }}元</text>
+        </view>
+        <view class="r" v-if="showPay">
+          <view class="btn" @click="confirmPayFn()">立即支付</view>
+        </view>
+        <view class="r" v-else>
+          <view class="btn" @click="showMsg">存在待录入业务</view>
+        </view>
+      </view>
+    </view>
+  </view>
+
+</template>
+
+<script>
+var jweixin = require('@/components/jweixin-module/index.js');
+export default {
+  data() {
+    return {
+      p: {
+        carNo: ''
+      },
+      code: '',
+      selectNo: '',
+      openid: '',
+      carsSelect: [],
+      itemSelect: [],
+      businessSelect: [],
+      goodsName: '',
+      businessNos: '',
+      state: '',
+      list: [],
+      cars: [],
+      type: 0,
+      businessAble: true,
+      showPay: false,
+      item: {
+        itemsPrice: 0,
+        businessId: '',
+        list: []
+      },
+      payTypeList: [{
+        name: '微信支付',
+        value: 3
+      }],
+      form: {
+        partMoney: 0,
+        payType: 3
+      },
+      showTips: false,
+
+    }
+  },
+  onLoad(options) {
+    this.code = options.code;
+    this.state = options.state;
+    this.getOpenidByCode();
+  },
+  onShow() {
+    this.$common.hidingLoading();
+  },
+  created() {
+  },
+  mounted() {
+    this.getChannelCar();
+    this.getWxConfig();
+  },
+  beforeDestroy() {
+    this.$common.hidingLoading()
+  },
+  computed: {
+    total() {
+      let carIds = this.carsSelect;
+      let carMoney = this.cars.filter(obj => carIds.indexOf(obj.id) !== -1)
+          .map(obj => obj.price).reduce(function (pre, cur) {
+            return pre + cur;
+          }, 0);
+      let itemIds = this.itemSelect;
+      let itemMoney = this.item.list ? this.item.list.filter(obj => itemIds.indexOf(obj.id) !== -1)
+          .map(obj => obj.price).reduce(function (pre, cur) {
+            return pre + cur;
+          }, 0) : 0;
+      return (carMoney + itemMoney).toFixed(2);
+    }
+  },
+  methods: {
+    showMsg() {
+      this.$common.toast('请先完善相关业务录入');
+    },
+    businessChange(value) {
+      this.itemSelect = value.length == 0 ? this.itemSelect = [] : this.item.list.map(obj => obj.id)
+    },
+    getChannelCar() {
+      if (this.state !== 'STATE') {
+        this.$api.getPartCarByChannel({
+          channel: this.state
+        }).then(resp => {
+          let data = resp.data;
+          if (data.cars && data.cars.length > 0) {
+            this.cars = data.cars;
+            let carId = [data.cars[0].id];
+            this.carsSelect = carId;
+            this.groupChange(carId)
+          }
+        })
+      }
+    },
+    getWxConfig() {
+      let url = window.location.href;
+      this.$api.getWxConfig({
+        url: url
+      }).then(resp => {
+        jweixin.config({
+          // debug: true,
+          appId: resp.data.appId,
+          timestamp: resp.data.timestamp, // 必填,生成签名的时间戳
+          nonceStr: resp.data.noncestr, // 必填,生成签名的随机串
+          signature: resp.data.sign, // 必填,签名
+          jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表
+        });
+        jweixin.ready(function () {
+
+        });
+        jweixin.error(function (res) {
+          console.log(res)
+        });
+      })
+    },
+    confirmPayFn() {
+      let carIds = this.carsSelect
+      let cars = this.cars.filter(obj => carIds.indexOf(obj.id) !== -1);
+      let carNos = this.cars.map(obj => obj.carNo).join('、');
+      let carBusinessNo = this.cars.map(obj => obj.no).join('、');
+      let businessSelect = this.businessSelect;
+      let p = {
+        b: businessSelect.length > 0 ? this.item.businessId : '',
+        c: JSON.stringify(cars.map(obj => {
+          return {
+            id: obj.id,
+            p: obj.price
+          }
+        })),
+        money: this.total,
+        tradeType: "JSAPI",
+        openid: this.openid
+      }
+      let con = 'A1-停车费-' + carBusinessNo;
+      let tradeType = 'PORT_PARKING_FEE';
+      if (carIds.length == 0 || businessSelect.length > 0) {//交业务费
+        con = 'A1-' + this.goodsName + '-' + this.businessNos;
+        tradeType = 'PORT_OPERATION_FEE';
+      }
+      p.desc = con + '-' + carNos;
+      p.businessType = tradeType;
+      this.$common.showLoading('正在请求...');
+      let that = this;
+      that.$api.getPrePay(that.$common.removeNull(p)).then(resp => {
+        let data = resp.data;
+        if (resp.code !== 200) {
+          that.$common.toast(resp.msg);
+          return;
+        }
+        jweixin.chooseWXPay({
+          timestamp: data
+              .timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+          nonceStr: data.nonceStr, // 支付签名随机串,不长于 32 位
+          package: data.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+          signType: data.signType, // 微信支付V3的传入RSA,微信支付V2的传入格式与V2统一下单的签名格式保持一致
+          paySign: data.paySign, // 支付签名
+          success: function (res) {
+            if (res.errMsg === "chooseWXPay:ok") {
+              that.$common.toast('支付成功')
+              //that.checkPayResult(data.outTradeNo);
+              that.cars = [];
+              that.item.list = [];
+              that.total = 0
+            }
+          },
+          complete: function (res) {
+            //that.checkPayResult(data.outTradeNo);
+          }
+        });
+      })
+    },
+    checkPayResult(outTradeNo) {
+      this.$common.showLoading('正在查询结果...')
+      this.$api.checkPayResult({
+        outTradeNo: outTradeNo
+      }).then(resp => {
+        let data = resp.data;
+        if (data.orderStatus == 'SUCCESS' || data.orderStatus == 'FINISH') {
+          this.$common.toast('支付成功')
+        } else {
+          this.$common.toast('支付失败')
+        }
+      })
+    },
+    payTypeChange(value) {
+
+    },
+    getOpenidByCode() {
+      let storeOpenid = uni.getStorageSync('openid');
+      this.$api.getOpenidByCode({
+        code: this.code,
+        openid: storeOpenid
+      }).then(resp => {
+        let openid = resp.data;
+        this.openid = openid;
+        if (openid) {
+          uni.setStorageSync('openid', openid)
+        }
+
+      })
+    },
+    groupChange(carId) {
+      this.$api.getBusinessMoney({
+        carId: carId,
+        state: this.state
+      }).then(resp => {
+        let data = resp.data;
+        this.cars = data.carList;
+        this.goodsName = data.goodsName;
+        this.showPay = data.showPay;
+        this.businessNos = data.businessNo;
+        this.type = data.type;
+        let list = data.itemList;
+        this.carsSelect = this.cars.filter(obj => obj.id == carId && obj.price > 0).map(obj => obj.id)
+        Object.assign(this.item, {
+          itemsPrice: data.itemsPrice,
+          businessId: data.businessId,
+          list: list
+        })
+        this.businessAble = list.filter(obj => obj.pay == 1).length == list.length;
+        let selectCar = this.list.filter(obj => obj.id == carId).pop();
+        let carNo = selectCar.carNo;
+        this.itemSelect = data.itemList.filter(obj => obj.pay == 0).map(obj => obj.id)
+        this.businessSelect = this.itemSelect.length == 0 ? [] : [1]
+        this.list = [];
+        this.showTips = this.cars.length == 0 && data.itemsPrice == 0;
+      })
+    },
+    searchFn() {
+      this.showTips = false;
+      this.list = [];
+      this.cars = [];
+      this.carsSelect = [];
+      this.itemSelect = [];
+      this.businessSelect = []
+      this.item = {
+        itemsPrice: '',
+        businessId: '',
+        list: []
+      }
+      this.$api.searchPartCar(this.p).then(resp => {
+        this.list = resp.data;
+      })
+    }
+
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.list {
+  margin: 40rpx;
+}
+
+.card {
+  .title {
+    padding: 30rpx;
+    box-sizing: border-box;
+    font-size: 34rpx;
+    font-weight: bold;
+  }
+}
+
+.tips {
+  margin: 140rpx 0 0 80rpx;
+  line-height: 60rpx;
+}
+
+.content {
+  display: flex;
+  flex-direction: column;
+  padding: 30rpx;
+  box-sizing: border-box;
+  color: #999;
+}
+
+.c-item {
+  display: flex;
+  align-items: center;
+  margin: 5rpx 30rpx;
+  padding: 10rpx 30rpx;
+  border-radius: 10rpx;
+  background-color: #fff;
+  border: 1rpx solid #f5f5f5;
+
+  .l {
+  }
+
+  .c {
+    font-size: 30rpx;
+    color: #191919;
+    font-weight: bold;
+    margin-left: 20rpx;
+  }
+
+  .r {
+    font-size: 30rpx;
+    color: #ff4200;
+    font-weight: bold;
+    margin-left: auto;
+  }
+}
+
+.bottom {
+  min-height: 100rpx;
+  position: fixed;
+  left: 0;
+  right: 0;
+  bottom: 0;
+
+  .box {
+    display: flex;
+    width: 100%;
+    min-height: 100rpx;
+    align-items: center;
+
+    .l {
+      padding-left: 30rpx;
+      flex: 2;
+
+      .t1 {
+        color: #333;
+      }
+
+      .t2 {
+        color: #ff4200;
+        font-size: 38rpx;
+        font-weight: bold;
+      }
+    }
+
+    .r {
+      flex: 1;
+
+      .btn {
+        background-color: #ff4200;
+        min-height: 100rpx;
+        display: flex;
+        color: #fff;
+        font-size: 30rpx;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+  }
+}
+
+@import '@/common/common.scss'
+</style>

+ 215 - 0
app-ui/pages/wx/payOrder.vue

@@ -0,0 +1,215 @@
+<template>
+  <view>
+    <view class="box">
+      <view class="item">
+        <view class="l">订单号:</view>
+        <view class="r">
+          {{ form.no }}
+        </view>
+      </view>
+      <view class="item-line">
+        收费明细
+      </view>
+      <view class="item" v-for="item in form.items" :key="item.id">
+        <view class="l" style="flex: 7;">{{ item.itemTypeName }}:</view>
+        <view class="r">
+          {{ item.itemName }}({{ item.itemPrice }}x{{ item.num }}={{ item.total }}元)
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">业务费:</view>
+        <view class="r">
+          {{ form.itemPrice }}
+          <text>(元)</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">业务项:</view>
+        <view class="r">
+          {{ form.goodsName }}
+          <text>(元)</text>
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">合计费用:</view>
+        <view class="r">
+          {{ form.totalMoney }}元
+        </view>
+      </view>
+      <view class="item">
+        <view class="l" style="flex: 7;">状态:</view>
+        <view class="r">
+          <text v-if="form.adminConfirmInput==0">未确认</text>
+          <text v-else>已确认</text>
+        </view>
+      </view>
+    </view>
+    <view v-if="form.adminConfirmInput==0">
+      <u-button type="info" v-if="customerId!=='1'">待确认</u-button>
+      <u-button type="primary" @click="adminConfirmFn">确认账单</u-button>
+    </view>
+    <view v-else>
+      <u-button type="primary" v-if="form.payStatus==1&&customerId!=='1'&&form.adminConfirmInput==1"
+                @click="confirmFn">支付账单
+      </u-button>
+      <u-button type="info" v-if="form.payStatus==3">已支付</u-button>
+    </view>
+  </view>
+</template>
+
+<script>
+var jweixin = require('@/components/jweixin-module/index.js');
+export default {
+  data() {
+    return {
+      customerId: '',
+      perList: [],
+      wx: {
+        id: '',
+        code: '',
+        openid: ''
+      },
+      form: {
+        partMoney: 0
+      },
+    }
+  },
+  onBackPress() {
+    this.$common.to('/pages/business-order/business-order')
+    return false;
+  },
+  onLoad(options) {
+    this.wx.id = options.state;
+    this.wx.code = options.code;
+    this.getOpenidByCode();
+    this.getWxConfig();
+  },
+  onShow() {
+    this.perList = uni.getStorageSync('perList')
+    let info = uni.getStorageSync('userInfo');
+    this.customerId = info.customerId;
+
+    this.getBusinessById();
+  },
+  methods: {
+    adminConfirmFn() {
+      let that = this;
+      uni.showModal({
+        title: '提示',
+        content: '是否确认该业务账单?',
+        success(res) {
+          if (res.confirm) {
+            that.$api.adminConfirm({
+              ids: that.form.id
+            }).then(resp => {
+              if (resp.code == 200) {
+                that.$common.toast('已确认');
+                setTimeout(() => {
+                  that.$common.to('/pages/index/index');
+                }, 1500)
+              }
+            })
+          }
+        }
+      })
+    },
+    getWxConfig() {
+      let url = window.location.href;
+      this.$api.getWxConfig({
+        url: url
+      }).then(resp => {
+        jweixin.config({
+          //debug: true,
+          appId: resp.data.appId,
+          timestamp: resp.data.timestamp, // 必填,生成签名的时间戳
+          nonceStr: resp.data.noncestr, // 必填,生成签名的随机串
+          signature: resp.data.sign, // 必填,签名
+          jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表
+        });
+        jweixin.ready(function () {
+          console.log('111')
+
+        });
+        jweixin.error(function (res) {
+          console.log(res)
+        });
+      })
+    },
+    getOpenidByCode() {
+      let storeOpenid = uni.getStorageSync('openid');
+      this.$api.getOpenidByCode({
+        code: this.wx.code,
+        openid: storeOpenid
+      }).then(resp => {
+        let openid = resp.data;
+        this.wx.openid = openid;
+        if (openid) {
+          uni.setStorageSync('openid', openid)
+        }
+
+      })
+    },
+    getBusinessById() {
+      this.$api.getBusinessById({
+        id: this.wx.id
+      }).then(resp => {
+        this.form = resp.data;
+      })
+    },
+    confirmFn() {
+      let p = {
+        b: this.wx.id,
+        money: this.form.totalMoney,
+        tradeType: "JSAPI",
+        openid: this.wx.openid
+      }
+      p.desc = "A1-" + this.form.goodsName + this.form.no;
+      p.businessType = 'PORT_OPERATION_FEE';
+      this.$api.getPrePay(this.$common.removeNull(p)).then(resp => {
+        let data = resp.data;
+        let that = this;
+        jweixin.chooseWXPay({
+          timestamp: data
+              .timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+          nonceStr: data.nonceStr, // 支付签名随机串,不长于 32 位
+          package: data.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+          signType: data.signType, // 微信支付V3的传入RSA,微信支付V2的传入格式与V2统一下单的签名格式保持一致
+          paySign: data.paySign, // 支付签名
+          success: function (res) {
+            if (res.errMsg === "chooseWXPay:ok") {
+              that.checkPayResult(data.outTradeNo);
+            }
+          }
+        });
+      })
+    },
+    checkPayResult(outTradeNo) {
+      this.$common.showLoading('正在确认结果...')
+      this.$api.checkPayResult({
+        outTradeNo: outTradeNo
+      }).then(resp => {
+        let data = resp.data;
+        if (data.orderStatus == 'SUCCESS' || data.orderStatus == 'FINISH') {
+          this.$common.toast('支付成功')
+        } else {
+          this.$common.toast('支付失败')
+        }
+      })
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.item-line {
+  color: #a2a2a2;
+  padding: 5px 0 10px 29px;
+  border-bottom: 1px solid #E5E5E5;
+}
+
+@import '@/common/common.scss'
+</style>

+ 68 - 0
app-ui/pages/wx/payOrderTemp.vue

@@ -0,0 +1,68 @@
+<template>
+  <view class="box">
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: ''
+    }
+  },
+  onLoad(options) {
+    this.id = options.id;
+  },
+  created() {
+    this.$common.showLoading('正在加载...')
+  },
+  mounted() {
+    this.getRedirectUri();
+  },
+  beforeDestroy() {
+    this.$common.hidingLoading()
+  },
+  methods: {
+    getRedirectUri() {
+      this.$api.getRedirectUrl({path: '/pages/wx/payOrder', state: this.id}).then(resp => {
+        window.location.href = resp.data;
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+page {
+  background-color: #fff;
+}
+
+.box {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  padding: 100rpx 0;
+
+  .text {
+    color: #191919;
+    font-size: 36rpx;
+    font-weight: bold;
+    margin-top: 40rpx;
+  }
+
+  .count-down-box {
+    display: flex;
+    flex: 1;
+    align-items: center;
+    justify-content: center;
+    margin-top: 30rpx;
+
+    text {
+      margin-left: 20rpx;
+    }
+  }
+}
+</style>

+ 32 - 0
app-ui/pages/wx/remote-js.vue

@@ -0,0 +1,32 @@
+<template>
+  <view>
+
+  </view>
+</template>
+
+<script>
+export default {
+  components: {
+    'remote-js': {
+      render(createElement) {
+        return createElement('script', {
+          attrs: {
+            type: 'text/javascript',
+            src: this.src
+          }
+        });
+      },
+      props: {
+        src: {
+          type: String,
+          required: true
+        },
+      },
+    },
+  },
+}
+</script>
+
+<style>
+
+</style>

BIN
app-ui/static/home-icon-01.png


BIN
app-ui/static/home-icon-02.png


BIN
app-ui/static/home-icon-03.png


BIN
app-ui/static/home-icon-04.png


BIN
app-ui/static/home-icon-05.png


BIN
app-ui/static/home-icon-06.jpg


BIN
app-ui/static/home-icon-07.jpg


BIN
app-ui/static/home-icon-charge.png


BIN
app-ui/static/login-bg.png


BIN
app-ui/static/logo.png


BIN
app-ui/static/noData.png


BIN
app-ui/static/qrcode.png


BIN
app-ui/static/slider-verify/1.jpg


BIN
app-ui/static/slider-verify/2.jpg


BIN
app-ui/static/slider-verify/3.jpg


BIN
app-ui/static/slider-verify/4.jpg


BIN
app-ui/static/slider-verify/5.jpg


BIN
app-ui/static/slider-verify/icon-button-normal.png


BIN
app-ui/static/user.png


+ 79 - 0
app-ui/uni.scss

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

+ 29 - 0
app-ui/uni_modules/uni-badge/changelog.md

@@ -0,0 +1,29 @@
+## 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
app-ui/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="[badgeWidth, 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']
+			},
+			badgeWidth() {
+				return {
+					width: `${this.width}px`
+				}
+			},
+			dotStyle() {
+				if (!this.isDot) return {}
+				return {
+					width: '10px',
+					height: '10px',
+					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;
+		/* #endif */
+		justify-content: center;
+		flex-direction: row;
+		height: 20px;
+		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>

+ 88 - 0
app-ui/uni_modules/uni-badge/package.json

@@ -0,0 +1,88 @@
+{
+  "id": "uni-badge",
+  "displayName": "uni-badge 数字角标",
+  "version": "1.2.0",
+  "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
+  "keywords": [
+    "",
+    "badge",
+    "uni-ui",
+    "uniui",
+    "数字角标",
+    "徽章"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "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
app-ui/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 
+
+

+ 10 - 0
app-ui/uni_modules/uni-calendar/changelog.md

@@ -0,0 +1,10 @@
+## 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
app-ui/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
app-ui/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
app-ui/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
app-ui/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
app-ui/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": "六"
+}

+ 188 - 0
app-ui/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue

@@ -0,0 +1,188 @@
+<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 messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	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" >
+	$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-color-primary: #2979ff;
+	.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-color-primary;
+	}
+
+	.uni-calendar-item--isDay {
+		background-color: $uni-color-primary;
+		opacity: 0.8;
+		color: #fff;
+	}
+
+	.uni-calendar-item--extra {
+		color: $uni-color-error;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--checked {
+		background-color: $uni-color-primary;
+		color: #fff;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--multiple {
+		background-color: $uni-color-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>

+ 555 - 0
app-ui/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue

@@ -0,0 +1,555 @@
+<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 messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	/**
+	 * 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)
+			},
+			endDate(val){
+				this.cale.resetEndDate(val)
+			},
+			selected(newVal) {
+				this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
+				this.weeks = this.cale.weeks
+			}
+		},
+		created() {
+			// 获取日历方法实例
+			this.cale = new Calendar({
+				// date: new Date(),
+				selected: this.selected,
+				startDate: this.startDate,
+				endDate: this.endDate,
+				range: this.range,
+			})
+			// 选中某一天
+			// this.cale.setDate(this.date)
+			this.init(this.date)
+			// this.setDay
+		},
+		methods: {
+			// 取消穿透
+			clean() {},
+			bindDateChange(e) {
+				const value = e.detail.value + '-1'
+				console.log(this.cale.getDate(value));
+				this.init(value)
+			},
+			/**
+			 * 初始化日期显示
+			 * @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() {
+				console.log(this.cale.getDate(new Date()).fullDate);
+				let date = this.cale.getDate(new Date()).fullDate
+				// this.cale.setDate(date)
+				this.init(date)
+				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" >
+	$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;
+		bottom: calc(var(--window-bottom));
+		left: 0;
+		right: 0;
+		transition-property: transform;
+		transition-duration: 0.3s;
+		transform: translateY(460px);
+		/* #ifndef APP-NVUE */
+		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;
+		// padding: 0 15px;
+	}
+
+	.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>

+ 354 - 0
app-ui/uni_modules/uni-calendar/components/uni-calendar/util.js

@@ -0,0 +1,354 @@
+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) {
+					dd.setDate(dd.getDate() + AddDayCount)
+				} else {
+					dd.setMonth(dd.getMonth() + AddDayCount) // 获取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 isinfo = false
+			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 {
+			fullDate,
+			year,
+			month,
+			date,
+			day
+		} = 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

+ 88 - 0
app-ui/uni_modules/uni-calendar/package.json

@@ -0,0 +1,88 @@
+{
+  "id": "uni-calendar",
+  "displayName": "uni-calendar 日历",
+  "version": "1.4.2",
+  "description": "日历组件",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "日历",
+    "",
+    "打卡",
+    "日历选择"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "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"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "u"
+        }
+      }
+    }
+  }
+}

Some files were not shown because too many files changed in this diff