This commit is contained in:
zy 2025-11-10 09:46:35 +08:00
commit 706ff18d36
745 changed files with 213152 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/unpackage/
/.idea/

20
.hbuilderx/launch.json Normal file
View File

@ -0,0 +1,20 @@
{
// launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version" : "0.0",
"configurations" : [
{
"default" : {
"launchtype" : "local"
},
"mp-weixin" : {
"launchtype" : "local"
},
"type" : "uniCloud"
},
{
"openVueDevtools" : false,
"type" : "uni-app:miniProgram"
}
]
}

344
App.vue Normal file
View File

@ -0,0 +1,344 @@
<script>
import Vue from 'vue'
import appUpdate from 'common/util/appUpdate.js'
import api from "@/api/api"
export default {
globalData:{
navTop:0,
},
onLaunch: function() {
var that = this;
//
if (uni.canIUse('getUpdateManager')) {
const updateManager = uni.getUpdateManager()
//
updateManager.onCheckForUpdate(function(res) {
//
if (res.hasUpdate) {
//2.
updateManager.onUpdateReady(function() {
uni.showModal({
title: '更新提示',
content: '新版本已上线,是否更新?',
success: function(res) {
if (res.confirm) {
//3. applyUpdate
updateManager.applyUpdate()
} else if (res.cancel) {
//
}
}
})
})
updateManager.onUpdateFailed(function() {
//
uni.showModal({
title: '已经有新版本了哟~',
content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~',
})
})
}
})
} else {
uni.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
uni.getSystemInfo({
success: function(e) {
// #ifdef APP-PLUS
//
appUpdate()
// #endif
// #ifndef MP
Vue.prototype.StatusBar = e.statusBarHeight;
if (e.platform == 'android') {
Vue.prototype.CustomBar = e.statusBarHeight + 50;
} else {
Vue.prototype.CustomBar = e.statusBarHeight + 45;
};
// #endif
// #ifdef MP-WEIXIN
Vue.prototype.StatusBar = e.statusBarHeight;
let menuButtonObject = uni.getMenuButtonBoundingClientRect();//
let custom = {
top: menuButtonObject.top,
bottom: menuButtonObject.bottom,
right: menuButtonObject.right,
height: menuButtonObject.height,
width: menuButtonObject.width
}
Vue.prototype.Custom = custom;
Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
// #endif
// #ifdef MP-ALIPAY
Vue.prototype.StatusBar = e.statusBarHeight;
Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
// #endif
// #ifdef APP-PLUS
//Vue.prototype.$api.listenTranMsg()
// var info = plus.push.getClientInfo();
// /* 5+ push ps:使:H5+*/
// plus.push.addEventListener("click", function(msg) {
// console.log("click:" + JSON.stringify(msg));
// console.log(msg.payload);
// console.log(JSON.stringify(msg));
// //
// }, false);
// // 线
// plus.push.addEventListener("receive", function(msg) {
// // plus.ui.alert(2);
// //
// console.log("recevice:" + JSON.stringify(msg))
// }, false);
// #endif
//Vue.prototype.$api.initLogin()
}
})
Vue.prototype.NavBarColor='bg-gradual-blue'
Vue.prototype.Radio_Check_Size='scale(0.7)'
Vue.prototype.bannerList=[
{id:1,type: 'image',url: 'https://static.jeecg.com/upload/test/banner0_1595850438042.jpeg', link: ''},
{id:2,type: 'image',url: 'https://static.jeecg.com/upload/test/banner2_1595818081327.jpg', link: ''},
{id:3,type: 'image',url: 'https://static.jeecg.com/upload/test/oabanner-2_1595648520760.png', link: ''},
{id:4,type: 'image',url: 'https://static.jeecg.com/upload/test/banner5_1595818089013.jpeg', link: ''},
]
Vue.prototype.ColorList = [{
title: '嫣红',
name: 'red',
color: '#e54d42'
},
{
title: '桔橙',
name: 'orange',
color: '#f37b1d'
},
{
title: '明黄',
name: 'yellow',
color: '#fbbd08'
},
{
title: '橄榄',
name: 'olive',
color: '#8dc63f'
},
{
title: '森绿',
name: 'green',
color: '#39b54a'
},
{
title: '天青',
name: 'cyan',
color: '#1cbbb4'
},
{
title: '海蓝',
name: 'blue',
color: '#0081ff'
},
{
title: '姹紫',
name: 'purple',
color: '#6739b6'
},
{
title: '木槿',
name: 'mauve',
color: '#9c26b0'
},
{
title: '桃粉',
name: 'pink',
color: '#e03997'
},
{
title: '棕褐',
name: 'brown',
color: '#a5673f'
},
{
title: '玄灰',
name: 'grey',
color: '#8799a3'
},
{
title: '草灰',
name: 'gray',
color: '#aaaaaa'
},
{
title: '墨黑',
name: 'black',
color: '#333333'
},
{
title: '雅白',
name: 'white',
color: '#ffffff'
},
]
},
onLoad() {
if(!uni.getStorageSync('third_session')){
uni.reLaunch({
url:'/pages/loginindex'
})
}else{
uni.reLaunch({
url:'/pages/index/index'
})
}
},
onShow: function() {
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
@import "plugin/colorui/main.css";
@import "plugin/colorui/icon.css";
@import "plugin/colorui/animation.css";
.nav-list {
display: flex;
flex-wrap: wrap;
padding: 0px 40upx 0px;
justify-content: space-between;
}
.nav-li {
padding: 30upx;
border-radius: 12upx;
width: 45%;
margin: 0 2.5% 40upx;
background-image: url(https://cdn.nlark.com/yuque/0/2019/png/280374/1552996358352-assets/web-upload/cc3b1807-c684-4b83-8f80-80e5b8a6b975.png);
background-size: cover;
background-position: center;
position: relative;
z-index: 1;
}
.nav-li::after {
content: "";
position: absolute;
z-index: -1;
background-color: inherit;
width: 100%;
height: 100%;
left: 0;
bottom: -10%;
border-radius: 10upx;
opacity: 0.2;
transform: scale(0.9, 0.9);
}
.nav-li.cur {
color: #fff;
background: rgb(94, 185, 94);
box-shadow: 4upx 4upx 6upx rgba(94, 185, 94, 0.4);
}
.nav-title {
font-size: 32upx;
font-weight: 300;
}
.nav-title::first-letter {
font-size: 40upx;
margin-right: 4upx;
}
.nav-name {
font-size: 28upx;
text-transform: Capitalize;
margin-top: 20upx;
position: relative;
}
.nav-name::before {
content: "";
position: absolute;
display: block;
width: 40upx;
height: 6upx;
background: #fff;
bottom: 0;
right: 0;
opacity: 0.5;
}
.nav-name::after {
content: "";
position: absolute;
display: block;
width: 100upx;
height: 1px;
background: #fff;
bottom: 0;
right: 40upx;
opacity: 0.3;
}
.nav-name::first-letter {
font-weight: bold;
font-size: 36upx;
margin-right: 1px;
}
.nav-li text {
position: absolute;
right: 30upx;
top: 30upx;
font-size: 52upx;
width: 60upx;
height: 60upx;
text-align: center;
line-height: 60upx;
}
.text-light {
font-weight: 300;
}
@keyframes show {
0% {
transform: translateY(-50px);
}
60% {
transform: translateY(40upx);
}
100% {
transform: translateY(0px);
}
}
@-webkit-keyframes show {
0% {
transform: translateY(-50px);
}
60% {
transform: translateY(40upx);
}
100% {
transform: translateY(0px);
}
}
</style>

201
LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (c) 2019 <a href="http://www.jeecg.com">Jeecg Boot</a> All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

79
README.md Normal file
View File

@ -0,0 +1,79 @@
# JeecgUniapp项目介绍
JeecgBoot - APP移动解决方案采用uniapp框架一份代码多终端适配同时支持APP、小程序、H5实现了与[JeecgBoot低代码平台](https://github.com/jeecgboot/jeecg-boot)完美对接!目前已经实现登录、用户信息、通讯录、公告、移动首页、九宫格等基础功能,更多功能请自己扩展。
当前最新版本: 2.0发布日期2020-07-05
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京敲敲云科技-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://my.oschina.net/jeecg)
[![](https://img.shields.io/badge/version-3.4.1-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
> 本项目关闭issue遇到BUG可以在github上 [发Issue](https://github.com/jeecgboot/jeecg-uniapp/issues/new)
### 源码下载
- https://github.com/jeecgboot/jeecg-uniapp
- https://gitee.com/jeecg/jeecg-uniapp
### 后台代码
- https://github.com/jeecgboot/jeecg-boot
### 技术文档
- APP体验 http://jeecg.com/appIndex
- 技术官网: [http://www.jeecg.com](http://www.jeecg.com)
- 技术文档: [http://doc.jeecg.com/2044258](http://doc.jeecg.com/2044258)
- 视频教程: [零基础入门视频](https://www.bilibili.com/video/BV1sQ4y1R7Rz)
- 官方支持: http://jeecg.com/doc/help
效果预览
----
![](https://oscimg.oschina.net/oscnet/up-9fb74025440e6066651599d78b4bc78f2cd.png)
![](https://oscimg.oschina.net/oscnet/up-7605e213638a559bba64279b6db93af3ed0.png)
![](https://oscimg.oschina.net/oscnet/up-43ddd52486509ab06a920c3f99f42b8b432.png)
![](https://oscimg.oschina.net/oscnet/up-02d83a8fe3fab4c0153862a9084f8a94cbb.png)
![](https://oscimg.oschina.net/oscnet/up-937a63d5e13869c40e6f1437452171d8235.png)
![输入图片说明](https://oscimg.oschina.net/oscnet/up-49e27699eb278c7c6b6748bfeaeb6c13b72.gif "在这里输入图片标题")
### 功能模块
```
├─框架实现
│ ├─APP开发框架搭建
│ ├─登录对接
│ ├─TOKEN接口机制
│ ├─热更新\覆盖更新
├─基础功能
│ ├─菜单栏目
│ ├─登录页面
│ ├─移动首页
│ ├─个人信息设置
├─消息中心
│ ├─通讯录
│ ├─系统公告
│ ├─消息推送
├─示例代码
│ ├─调用摄像头扫码(扫码)
│ ├─获取地理位置(定位)
├─新增组件
│ ├─页面滚动
│ ├─日历
│ ├─时间选择
│ ├─下拉选择
│ ├─图片上传
├─。。。
```

43
api/api.js Normal file
View File

@ -0,0 +1,43 @@
import { http } from '@/common/service/service.js'
import configService from '@/common/service/config.service.js';
const apiService = {
/**
* 登录
*/
login(params) {
return http.post('/sys/mLogin',params)
},
/**
* 手机号码登录
*/
phoneNoLogin(params) {
return http.post('/sys/phoneLogin',params);
},
// 授权登录
wxlogin(params){
return http.post('/applet/userInfo/loginmas',params)
},
/**
* 退出
*/
logout(params) {
return http.post('/sys/logout',params);
},
/**
* 获取文件访问路径
* @param avatar
* @param subStr
* @returns {*}
*/
getFileAccessHttpUrl(avatar,subStr){
if(!subStr) subStr = 'http'
if(avatar && avatar.startsWith(subStr)){
return avatar;
}else{
return configService.staticDomainURL + "/" + avatar;
}
}
};
export default apiService;

31
common/amap-wx.130.js Normal file
View File

@ -0,0 +1,31 @@
function AMapWX(a){this.key=a.key;this.requestConfig={key:a.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};this.MeRequestConfig={key:a.key,serviceName:"https://restapi.amap.com/rest/me"}}
AMapWX.prototype.getWxLocation=function(a,b){wx.getLocation({type:"gcj02",success:function(c){c=c.longitude+","+c.latitude;wx.setStorage({key:"userLocation",data:c});b(c)},fail:function(c){wx.getStorage({key:"userLocation",success:function(d){d.data&&b(d.data)}});a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getMEKeywordsSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.city&&(d.city=b.city);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);b.sig&&(d.sig=
b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/local",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getMEIdSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.id&&(d.id=b.id);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/id",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&
0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getMEPolygonSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.polygon&&(d.polygon=b.polygon);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);
b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/polygon",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getMEaroundSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.center&&(d.center=b.center);b.radius&&(d.radius=b.radius);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&
(d.pageSize=b.pageSize);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/around",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getGeo=function(a){var b=this.requestConfig,c=a.options;b={key:this.key,extensions:"all",s:b.s,platform:b.platform,appname:this.key,sdkversion:b.sdkversion,logversion:b.logversion};c.address&&(b.address=c.address);c.city&&(b.city=c.city);c.batch&&(b.batch=c.batch);c.sig&&(b.sig=c.sig);wx.request({url:"https://restapi.amap.com/v3/geocode/geo",data:b,method:"GET",header:{"content-type":"application/json"},success:function(d){(d=d.data)&&d.status&&"1"===d.status?a.success(d):a.fail({errCode:"0",
errMsg:d})},fail:function(d){a.fail({errCode:"0",errMsg:d.errMsg||""})}})};
AMapWX.prototype.getRegeo=function(a){function b(d){var e=c.requestConfig;wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:c.key,location:d,extensions:"all",s:e.s,platform:e.platform,appname:c.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){g=g.data.regeocode;var h=g.addressComponent,f=[],k=g.roads[0].name+"\u9644\u8fd1",m=d.split(",")[0],n=d.split(",")[1];if(g.pois&&
g.pois[0]){k=g.pois[0].name+"\u9644\u8fd1";var l=g.pois[0].location;l&&(m=parseFloat(l.split(",")[0]),n=parseFloat(l.split(",")[1]))}h.provice&&f.push(h.provice);h.city&&f.push(h.city);h.district&&f.push(h.district);h.streetNumber&&h.streetNumber.street&&h.streetNumber.number?(f.push(h.streetNumber.street),f.push(h.streetNumber.number)):f.push(g.roads[0].name);f=f.join("");a.success([{iconPath:a.iconPath,width:a.iconWidth,height:a.iconHeight,name:f,desc:k,longitude:m,latitude:n,id:0,regeocodeData:g}])}else a.fail({errCode:g.data.infocode,
errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this;a.location?b(a.location):c.getWxLocation(a,function(d){b(d)})};
AMapWX.prototype.getWeather=function(a){function b(g){var h="base";a.type&&"forecast"==a.type&&(h="all");wx.request({url:"https://restapi.amap.com/v3/weather/weatherInfo",data:{key:d.key,city:g,extensions:h,s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(f){if(f.data.status&&"1"==f.data.status)if(f.data.lives){if((f=f.data.lives)&&0<f.length){f=f[0];var k={city:{text:"\u57ce\u5e02",data:f.city},
weather:{text:"\u5929\u6c14",data:f.weather},temperature:{text:"\u6e29\u5ea6",data:f.temperature},winddirection:{text:"\u98ce\u5411",data:f.winddirection+"\u98ce"},windpower:{text:"\u98ce\u529b",data:f.windpower+"\u7ea7"},humidity:{text:"\u6e7f\u5ea6",data:f.humidity+"%"}};k.liveData=f;a.success(k)}}else f.data.forecasts&&f.data.forecasts[0]&&a.success({forecast:f.data.forecasts[0]});else a.fail({errCode:f.data.infocode,errMsg:f.data.info})},fail:function(f){a.fail({errCode:"0",errMsg:f.errMsg||""})}})}
function c(g){wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:d.key,location:g,extensions:"all",s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(h){if(h.data.status&&"1"==h.data.status){h=h.data.regeocode;if(h.addressComponent)var f=h.addressComponent.adcode;else h.aois&&0<h.aois.length&&(f=h.aois[0].adcode);b(f)}else a.fail({errCode:h.data.infocode,errMsg:h.data.info})},
fail:function(h){a.fail({errCode:"0",errMsg:h.errMsg||""})}})}var d=this,e=d.requestConfig;a.city?b(a.city):d.getWxLocation(a,function(g){c(g)})};
AMapWX.prototype.getPoiAround=function(a){function b(e){e={key:c.key,location:e,s:d.s,platform:d.platform,appname:c.key,sdkversion:d.sdkversion,logversion:d.logversion};a.querytypes&&(e.types=a.querytypes);a.querykeywords&&(e.keywords=a.querykeywords);wx.request({url:"https://restapi.amap.com/v3/place/around",data:e,method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){if((g=g.data)&&g.pois){for(var h=[],f=0;f<g.pois.length;f++){var k=0==
f?a.iconPathSelected:a.iconPath;h.push({latitude:parseFloat(g.pois[f].location.split(",")[1]),longitude:parseFloat(g.pois[f].location.split(",")[0]),iconPath:k,width:22,height:32,id:f,name:g.pois[f].name,address:g.pois[f].address})}a.success({markers:h,poisData:g.pois})}}else a.fail({errCode:g.data.infocode,errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this,d=c.requestConfig;a.location?b(a.location):c.getWxLocation(a,function(e){b(e)})};
AMapWX.prototype.getStaticmap=function(a){function b(e){c.push("location="+e);a.zoom&&c.push("zoom="+a.zoom);a.size&&c.push("size="+a.size);a.scale&&c.push("scale="+a.scale);a.markers&&c.push("markers="+a.markers);a.labels&&c.push("labels="+a.labels);a.paths&&c.push("paths="+a.paths);a.traffic&&c.push("traffic="+a.traffic);e="https://restapi.amap.com/v3/staticmap?"+c.join("&");a.success({url:e})}var c=[];c.push("key="+this.key);var d=this.requestConfig;c.push("s="+d.s);c.push("platform="+d.platform);
c.push("appname="+d.appname);c.push("sdkversion="+d.sdkversion);c.push("logversion="+d.logversion);a.location?b(a.location):this.getWxLocation(a,function(e){b(e)})};
AMapWX.prototype.getInputtips=function(a){var b=Object.assign({},this.requestConfig);a.location&&(b.location=a.location);a.keywords&&(b.keywords=a.keywords);a.type&&(b.type=a.type);a.city&&(b.city=a.city);a.citylimit&&(b.citylimit=a.citylimit);wx.request({url:"https://restapi.amap.com/v3/assistant/inputtips",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.tips&&a.success({tips:c.data.tips})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||
""})}})};
AMapWX.prototype.getDrivingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.waypoints&&(b.waypoints=a.waypoints);a.avoidpolygons&&(b.avoidpolygons=a.avoidpolygons);a.avoidroad&&(b.avoidroad=a.avoidroad);wx.request({url:"https://restapi.amap.com/v3/direction/driving",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths,
taxi_cost:c.data.route.taxi_cost||""})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getWalkingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/walking",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getTransitRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.city&&(b.city=a.city);a.cityd&&(b.cityd=a.cityd);wx.request({url:"https://restapi.amap.com/v3/direction/transit/integrated",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&(c=c.data.route,a.success({distance:c.distance||"",taxi_cost:c.taxi_cost||
"",transits:c.transits}))},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getRidingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/riding",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};module.exports.AMapWX=AMapWX;

View File

@ -0,0 +1,438 @@
/**
* Request 2.0.1
* @Class Request
* @description luch-request 2.0.1 http请求插件
* @Author lu-ch
* @Date 2020-05-01
* @Email webwork.s@qq.com
* http://ext.dcloud.net.cn/plugin?id=392
* hbuilderx:2.6.15
*/
import buildURL from '../helpers/buildURL'
import buildFullPath from './buildFullPath'
import { isBoolean } from '../utils'
export default class Request {
config = {
baseUrl: '',
header: {},
method: 'GET',
dataType: 'json',
// #ifndef MP-ALIPAY || APP-PLUS
responseType: 'text',
// #endif
custom: {},
// #ifdef MP-ALIPAY || MP-WEIXIN
timeout: 30000,
// #endif
// #ifdef APP-PLUS
sslVerify: true,
// #endif
// #ifdef H5
withCredentials: false
// #endif
}
/**
* @property {Function} request 请求拦截器
* @property {Function} response 响应拦截器
* @type {{request: Request.interceptor.request, response: Request.interceptor.response}}
*/
interceptor = {
/**
* @param {Request~requestCallback} cb - 请求之前拦截,接收一个函数config, cancel=> {return config}第一个参数为全局config,第二个参数为函数调用则取消本次请求
*/
request: (cb) => {
if (cb) {
this.requestBeforeFun = cb
}
},
/**
* @param {Request~responseCallback} cb 响应拦截器对响应数据做点什么
* @param {Request~responseErrCallback} ecb 响应拦截器对响应错误做点什么
*/
response: (cb, ecb) => {
if (cb) {
this.requestComFun = cb
}
if (ecb) {
this.requestComFail = ecb
}
}
}
requestBeforeFun = (config) => {
return config
}
requestComFun = (response) => {
return response
}
requestComFail = (response) => {
return response
}
/**
* 自定义验证器如果返回true 则进入响应拦截器的响应成功函数(resolve)否则进入响应拦截器的响应错误函数(reject)
* @param { Number } statusCode - 请求响应体statusCode只读
* @return { Boolean } 如果为true, resolve, 否则 reject
*/
validateStatus(statusCode) {
return statusCode === 200
}
/**
* @Function
* @param {Request~setConfigCallback} f - 设置全局默认配置
*/
setConfig(f) {
this.config = f(this.config)
}
/**
* @Function
* @param {Object} options - 请求配置项
* @prop {String} options.url - 请求路径
* @prop {Object} options.data - 请求参数
* @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
* @prop {Object} [options.dataType = config.dataType] - 如果设为 json会尝试对返回的数据做一次 JSON.parse
* @prop {Object} [options.header = config.header] - 请求header
* @prop {Object} [options.method = config.method] - 请求方法
* @returns {Promise<unknown>}
*/
async request(options = {}) {
return new Promise((resolve, reject) => {
options.baseUrl = this.config.baseUrl
options.dataType = options.dataType || this.config.dataType
// #ifndef MP-ALIPAY || APP-PLUS
options.responseType = options.responseType || this.config.responseType
// #endif
// #ifdef MP-ALIPAY || MP-WEIXIN
options.timeout = options.timeout || this.config.timeout
// #endif
// #ifdef H5
options.withCredentials = isBoolean(options.withCredentials) ? options.withCredentials : this.config.withCredentials
// #endif
options.url = options.url || ''
options.data = options.data || {}
options.params = options.params || {}
options.header = {...this.config.header, ...(options.header || {})}
options.method = options.method || this.config.method
options.custom = {...this.config.custom,...(options.custom || {})}
// #ifdef APP-PLUS
options.sslVerify = options.sslVerify === undefined ? this.config.sslVerify : options.sslVerify
// #endif
options.getTask = options.getTask || this.config.getTask
let next = true
const cancel = (t = 'handle cancel', config = options) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
const handleRe = {...this.requestBeforeFun(options, cancel)}
const _config = {...handleRe}
if (!next) return
const requestTask = uni.request({
url: buildURL(buildFullPath(_config.baseUrl, _config.url), _config.params),
data: _config.data,
header: _config.header,
method: _config.method,
// #ifdef MP-ALIPAY || MP-WEIXIN
timeout: _config.timeout,
// #endif
dataType: _config.dataType,
// #ifndef MP-ALIPAY || APP-PLUS
responseType: _config.responseType,
// #endif
// #ifdef APP-PLUS
sslVerify: _config.sslVerify,
// #endif
// #ifdef H5
withCredentials: _config.withCredentials,
// #endif
complete: (response) => {
response.config = handleRe
if (this.validateStatus(response.statusCode)) { // 成功
response = this.requestComFun(response)
resolve(response)
} else {
response = this.requestComFail(response)
reject(response)
}
}
})
if (handleRe.getTask) {
handleRe.getTask(requestTask, handleRe)
}
})
}
get(url, options = {}) {
return this.request({
url,
method: 'GET',
...options
})
}
post(url, data, options = {}) {
return this.request({
url,
data,
method: 'POST',
...options
})
}
// #ifndef MP-ALIPAY
put(url, data, options = {}) {
return this.request({
url,
data,
method: 'PUT',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
delete(url, data, options = {}) {
return this.request({
url,
data,
method: 'DELETE',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN
connect(url, data, options = {}) {
return this.request({
url,
data,
method: 'CONNECT',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
head(url, data, options = {}) {
return this.request({
url,
data,
method: 'HEAD',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
options(url, data, options = {}) {
return this.request({
url,
data,
method: 'OPTIONS',
...options
})
}
// #endif
// #ifdef APP-PLUS || H5 || MP-WEIXIN
trace(url, data, options = {}) {
return this.request({
url,
data,
method: 'TRACE',
...options
})
}
// #endif
upload(url, {
// #ifdef APP-PLUS || H5
files,
// #endif
// #ifdef MP-ALIPAY
fileType,
// #endif
filePath,
name,
// #ifdef H5
file,
// #endif
header = {},
formData = {},
custom = {},
params = {},
getTask
}) {
return new Promise((resolve, reject) => {
let next = true
const globalHeader = {...this.config.header}
delete globalHeader['content-type']
delete globalHeader['Content-Type']
const pubConfig = {
baseUrl: this.config.baseUrl,
url,
// #ifdef MP-ALIPAY
fileType,
// #endif
filePath,
method: 'UPLOAD',
name,
header: {...globalHeader, ...header},
formData,
params,
custom: {...this.config.custom, ...custom},
getTask: getTask || this.config.getTask
}
// #ifdef APP-PLUS || H5
if (files) {
pubConfig.files = files
}
// #endif
// #ifdef H5
if (file) {
pubConfig.file = file
}
// #endif
const cancel = (t = 'handle cancel', config = pubConfig) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
const handleRe = {...this.requestBeforeFun(pubConfig, cancel)}
const _config = {
url: buildURL(buildFullPath(handleRe.baseUrl, handleRe.url), handleRe.params),
// #ifdef MP-ALIPAY
fileType: handleRe.fileType,
// #endif
filePath: handleRe.filePath,
name: handleRe.name,
header: handleRe.header,
formData: handleRe.formData,
complete: (response) => {
response.config = handleRe
try {
// 对可能字符串不是json 的情况容错
if (typeof response.data === 'string') {
response.data = JSON.parse(response.data)
}
// eslint-disable-next-line no-empty
} catch (e) {
}
if (this.validateStatus(response.statusCode)) { // 成功
response = this.requestComFun(response)
resolve(response)
} else {
response = this.requestComFail(response)
reject(response)
}
}
}
// #ifdef APP-PLUS || H5
if (handleRe.files) {
_config.files = handleRe.files
}
// #endif
// #ifdef H5
if (handleRe.file) {
_config.file = handleRe.file
}
// #endif
if (!next) return
const requestTask = uni.uploadFile(_config)
if (handleRe.getTask) {
handleRe.getTask(requestTask, handleRe)
}
})
}
download(url, options = {}) {
return new Promise((resolve, reject) => {
let next = true
const pubConfig = {
baseUrl: this.config.baseUrl,
url,
method: 'DOWNLOAD',
header: {...this.config.header, ...(options.header || {})},
params: options.params || {},
custom: {...this.config.custom, ...(options.custom || {})},
getTask: options.getTask || this.config.getTask
}
const cancel = (t = 'handle cancel', config = pubConfig) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
const handleRe = {...this.requestBeforeFun(pubConfig, cancel)}
if (!next) return
const requestTask = uni.downloadFile({
url: buildURL(buildFullPath(handleRe.baseUrl, handleRe.url), handleRe.params),
header: handleRe.header,
complete: (response) => {
response.config = handleRe
if (this.validateStatus(response.statusCode)) { // 成功
response = this.requestComFun(response)
resolve(response)
} else {
response = this.requestComFail(response)
reject(response)
}
}
})
if (handleRe.getTask) {
handleRe.getTask(requestTask, handleRe)
}
})
}
}
/**
* setConfig回调
* @return {Object} - 返回操作后的config
* @callback Request~setConfigCallback
* @param {Object} config - 全局默认config
*/
/**
* 请求拦截器回调
* @return {Object} - 返回操作后的config
* @callback Request~requestCallback
* @param {Object} config - 全局config
* @param {Function} [cancel] - 取消请求钩子调用会取消本次请求
*/
/**
* 响应拦截器回调
* @return {Object} - 返回操作后的response
* @callback Request~responseCallback
* @param {Object} response - 请求结果 response
*/
/**
* 响应错误拦截器回调
* @return {Object} - 返回操作后的response
* @callback Request~responseErrCallback
* @param {Object} response - 请求结果 response
*/

View File

@ -0,0 +1,20 @@
'use strict'
import isAbsoluteURL from '../helpers/isAbsoluteURL'
import combineURLs from '../helpers/combineURLs'
/**
* Creates a new URL by combining the baseURL with the requestedURL,
* only when the requestedURL is not already an absolute URL.
* If the requestURL is absolute, this function returns the requestedURL untouched.
*
* @param {string} baseURL The base URL
* @param {string} requestedURL Absolute or relative URL to combine
* @returns {string} The combined full path
*/
export default function buildFullPath(baseURL, requestedURL) {
if (baseURL && !isAbsoluteURL(requestedURL)) {
return combineURLs(baseURL, requestedURL)
}
return requestedURL
}

View File

@ -0,0 +1,69 @@
'use strict'
import * as utils from './../utils'
function encode(val) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%20/g, '+').
replace(/%5B/gi, '[').
replace(/%5D/gi, ']')
}
/**
* Build a URL by appending params to the end
*
* @param {string} url The base of the url (e.g., http://www.google.com)
* @param {object} [params] The params to be appended
* @returns {string} The formatted url
*/
export default function buildURL(url, params) {
/*eslint no-param-reassign:0*/
if (!params) {
return url
}
var serializedParams
if (utils.isURLSearchParams(params)) {
serializedParams = params.toString()
} else {
var parts = []
utils.forEach(params, function serialize(val, key) {
if (val === null || typeof val === 'undefined') {
return
}
if (utils.isArray(val)) {
key = key + '[]'
} else {
val = [val]
}
utils.forEach(val, function parseValue(v) {
if (utils.isDate(v)) {
v = v.toISOString()
} else if (utils.isObject(v)) {
v = JSON.stringify(v)
}
parts.push(encode(key) + '=' + encode(v))
})
})
serializedParams = parts.join('&')
}
if (serializedParams) {
var hashmarkIndex = url.indexOf('#')
if (hashmarkIndex !== -1) {
url = url.slice(0, hashmarkIndex)
}
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
}
return url
}

View File

@ -0,0 +1,14 @@
'use strict'
/**
* Creates a new URL by combining the specified URLs
*
* @param {string} baseURL The base URL
* @param {string} relativeURL The relative URL
* @returns {string} The combined URL
*/
export default function combineURLs(baseURL, relativeURL) {
return relativeURL
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
: baseURL
}

View File

@ -0,0 +1,14 @@
'use strict'
/**
* Determines whether the specified URL is absolute
*
* @param {string} url The URL to test
* @returns {boolean} True if the specified URL is absolute, otherwise false
*/
export default function isAbsoluteURL(url) {
// A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
// RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
// by any combination of letters, digits, plus, period, or hyphen.
return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
}

View File

@ -0,0 +1,2 @@
import Request from './core/Request'
export default Request

View File

@ -0,0 +1,95 @@
'use strict'
// utils is a library of generic helper functions non-specific to axios
var toString = Object.prototype.toString
/**
* Determine if a value is an Array
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an Array, otherwise false
*/
export function isArray (val) {
return toString.call(val) === '[object Array]'
}
/**
* Determine if a value is an Object
*
* @param {Object} val The value to test
* @returns {boolean} True if value is an Object, otherwise false
*/
export function isObject (val) {
return val !== null && typeof val === 'object'
}
/**
* Determine if a value is a Date
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a Date, otherwise false
*/
export function isDate (val) {
return toString.call(val) === '[object Date]'
}
/**
* Determine if a value is a URLSearchParams object
*
* @param {Object} val The value to test
* @returns {boolean} True if value is a URLSearchParams object, otherwise false
*/
export function isURLSearchParams (val) {
return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
}
/**
* Iterate over an Array or an Object invoking a function for each item.
*
* If `obj` is an Array callback will be called passing
* the value, index, and complete array for each item.
*
* If 'obj' is an Object callback will be called passing
* the value, key, and complete object for each property.
*
* @param {Object|Array} obj The object to iterate
* @param {Function} fn The callback to invoke for each item
*/
export function forEach (obj, fn) {
// Don't bother if no value provided
if (obj === null || typeof obj === 'undefined') {
return
}
// Force an array if not already something iterable
if (typeof obj !== 'object') {
/*eslint no-param-reassign:0*/
obj = [obj]
}
if (isArray(obj)) {
// Iterate over array values
for (var i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj)
}
} else {
// Iterate over object keys
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj)
}
}
}
}
/**
* 是否为boolean
* @param val
* @returns {boolean}
*/
export function isBoolean(val) {
return typeof val === 'boolean'
}

99
common/mixin/Mixin.js Normal file
View File

@ -0,0 +1,99 @@
/**
* 下了列表混入
* @type {{data(): *, methods: {upCallback(*): void, downCallback(): void, loadList(*): void}}}
*/
const ListMixin = {
data() {
return {
downOption:{
auto:false,//是否在初始化完毕之后自动执行下拉回调callback; 默认true
},
upOption:{
page:{
num : 0 ,
size : 8 ,
time : null
}
},
queryParam:{
pageNo:1,
pageSize:8
},
list:[],
pageNo:1,
pageSize:8,
}
},
methods: {
/*下拉刷新的回调 */
downCallback(){
//加载列表数据
this.loadList('down');
},
/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
upCallback(page) {
let param = this.queryParam
param.pageNo= page.num,
param.pageSize= page.size
if(page.num == 1){
this.list = [];
}
console.log("upCallback==param::",param)
this.$http.get(this.url,{params:param}).then(res=>{
console.log("upCallback请求返回res",res)
if(res.data.success){
let rec=res.data.result.records;
let hasNext=true;
if(!rec || rec.length<this.pageSize){
console.log("加载完成!没有更多了")
hasNext=false;
}
console.log("hasNext",hasNext)
//方法四 (不推荐),会存在一个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据当前页的数据个数判断,则需翻到第三页才会知道无更多数据.
this.mescroll.endSuccess(rec.length);
//设置列表数据
this.list=this.list.concat(rec);
this.$forceUpdate();
}else{
this.mescroll.endErr();
}
}).catch(()=>{
//加载失败, 结束
this.mescroll.endErr();
})
},
loadList(flag){
let param = this.queryParam
param.pageNo=this.pageNo,
param.pageSize=this.pageSize
console.log("请求参数",param)
this.$http.get(this.url,{params:param}).then(res=>{
if(res.data.success){
console.log("请求返回res.data",res.data)
let rec=res.data.result.records
if(flag=='down'){
//下拉刷新成功的回调,隐藏下拉刷新的状态
this.mescroll.endSuccess();
}
//添加新数据
this.list=rec;
/* if(!rec || rec.length<this.pageSize){
console.log("加载完成!")
} */
}else{
console.log("请求返回else",res)
this.mescroll.endErr();
}
}).catch((err)=>{
console.log("请求返回err",err)
//加载失败, 结束
this.mescroll.endErr();
})
},
}
}
export default ListMixin;

33
common/router/index.js Normal file
View File

@ -0,0 +1,33 @@
import modules from './modules'
import Vue from 'vue'
import Router from '@/plugin/uni-simple-router/index.js'
import {ACCESS_TOKEN} from '@/common/util/constants.js'
Vue.use(Router)
//初始化
const router = new Router({
encodeURI:true,
routes: [...modules]//路由表
});
const whiteList = ['/packDetail/pages/login/login','/pages/index/index']
//全局路由前置守卫
router.beforeEach((to, from, next) => {
const Access_Token = uni.getStorageSync('Access-Token')
let third_session=uni.getStorageSync('third_session');
if(third_session){
next()
}else{
if (whiteList.indexOf(to.path) !== -1) {
next()
}else{
next({ path: '/pages/index/index'})
// next({ path: '/packDetail/pages/login/login'})
}
}
})
// 全局路由后置守卫
router.afterEach((to, from) => {
console.log("afterEach")
})
export default router;

View File

@ -0,0 +1,10 @@
const files = require.context('.', false, /\.js$/)
const modules = []
files.keys().forEach(key => {
if (key === './index.js') return
const item = files(key).default
modules.push(...item)
})
export default modules

View File

@ -0,0 +1,131 @@
const routes = [
{
path: "/pages/login/login",
name: 'login',
meta: {
title: '登录',
},
},
{
//注意path必须跟pages.json中的地址对应最前面别忘了加'/'哦
path: '/pages/index/index',
name: 'index',
meta: {
title: '主页',
},
},
{
//注意path必须跟pages.json中的地址对应最前面别忘了加'/'哦
path: '/pages/home/home',
//aliasPath:'/', //对于h5端你必须在首页加上aliasPath并设置为/
name: 'home',
meta: {
title: '首页',
},
},
{
path: '/pages/user/people',
name: 'people',
meta: {
title: '个人中心',
},
},
{
path: '/pages/approve/approve',
name: 'approve',
meta: {
title: '审批',
},
},
{
path: '/pages/user/userdetail',
name: 'userdetail',
meta: {
title: '个人详情',
},
},
{
path: '/pages/user/useredit',
name: 'useredit',
meta: {
title: '个人编辑',
},
},
{
path: '/pages/user/userexit',
name: 'userexit',
meta: {
title: '退出',
},
},
{
path: '/pages/user/location',
name: 'location',
meta: {
title: '定位',
},
},
{
path: '/pages/common/exit',
name: 'exit',
meta: {
title: '退出',
},
},
{
path: '/pages/common/success',
name: 'success',
meta: {
title: 'success',
},
},{
path: '/pages/addressbook/address-book',
name: 'addressBook',
meta: {
title: 'addressBook',
},
},
{
path: '/pages/addressbook/level-address-book',
name: 'levelAddressBook',
meta: {
title: 'levelAddressBook',
},
},
{
path: '/pages/addressbook/member',
name: 'member',
meta: {
title: 'member',
},
},
{
path: '/pages/addressbook/address-detail',
name: 'addressDetail',
meta: {
title: 'addressDetail',
},
},
{
path: '/pages/annotation/annotationList',
name: 'annotationList',
meta: {
title: '通知公告',
},
},
{
path: '/pages/annotation/annotationDetail',
name: 'annotationDetail',
meta: {
title: '通知详情',
},
},
{
path: '/pages/common/helloWorld',
name: 'helloWorld',
meta: {
title: 'helloWorld',
},
},
]
export default routes

View File

@ -0,0 +1,18 @@
let BASE_URL = ''
if (process.env.NODE_ENV == 'development') {
BASE_URL = 'https://nsp.sxcooh.com/zh-api' // 生产环境
// BASE_URL = 'https://zy.sxzooh.com/zh-api' // 开发环境
} else {
BASE_URL = 'https://nsp.sxcooh.com/zh-api' // 生产环境
// BASE_URL = 'https://zy.sxzooh.com/zh-api' // 开发环境
}
let staticDomainURL = BASE_URL+ '/sys/common/static';
const configService = {
apiUrl: BASE_URL,
staticDomainURL: staticDomainURL
};
export default configService

176
common/service/service.js Normal file
View File

@ -0,0 +1,176 @@
import Request from '@/common/luch-request/index.js'
import {ACCESS_TOKEN} from '@/common/util/constants.js'
import configService from './config.service.js'
import tip from '@/common/util/tip.js';
import store from '@/store/index.js';
import api from "@/api/api"
let apiUrl = configService.apiUrl;
// const getTokenStorage = () => {
// let token = ''
// try{
// token = uni.getStorageSync(ACCESS_TOKEN)
// }catch(e){
// //TODO handle the exception
// console.log("getTokenStorage",token)
// }
// return token
// }
const http = new Request()
http.setConfig((config) => { /* 设置全局配置 */
config.baseUrl = apiUrl /* 根域名不同 */
config.header = {
...config.header
}
return config
})
/**
* 自定义验证器如果返回true 则进入响应拦截器的响应成功函数(resolve)否则进入响应拦截器的响应错误函数(reject)
* @param { Number } statusCode - 请求响应体statusCode只读
* @return { Boolean } 如果为true, resolve, 否则 reject
*/
// 有默认,非必写
http.validateStatus = (statusCode) => {
return statusCode === 200
}
http.interceptor.request((config, cancel) => { /* 请求之前拦截器 */
config.header = {
...config.header,
// 'X-Access-Token':getTokenStorage()
'app-id':uni.getAccountInfoSync().miniProgram.appId,
"client-type":"MA",
'third-session':uni.getStorageSync('third_session')
}
/*
if (!token) { // 如果token不存在调用cancel 会取消本次请求但是该函数的catch() 仍会执行
cancel('token 不存在') // 接收一个参数会传给catch((err) => {}) err.errMsg === 'token 不存在'
}
*/
return config
})
// 必须使用异步函数,注意
http.interceptor.response(async (response) => { /* 请求之后拦截器 */
// if (response.data.code !== 200) { // 服务端返回的状态码不等于200则reject()
// return Promise.reject(response)
// }
console.log(response.data.code,'状态码')
if(response.data.code == 60001){
uni.showToast({
title: response.data.msg,
icon: 'none',
duration: 2000
})
setTimeout(function(){
uni.removeStorageSync('third_session')
uni.switchTab({
url:'/pages/index/index'
})
// uni.reLaunch({
// url:'/packDetail/pages/login/login'
// })
},200)
}
return response
}, (response) => {
// 请求错误做点什么
console.log("请求错误做点什么",response);
if (response) {
let data = response.data
console.log(data,'状态码')
const token = uni.getStorageSync(ACCESS_TOKEN)
console.log("------异常响应------",token)
console.log("------异常响应------",data.status)
switch (data.status) {
case 403:
uni.showToast({
title: response.data.message,
icon: 'none',
duration: 2000
})
setTimeout(function(){
uni.removeStorageSync('third_session')
uni.removeStorageSync('constant')
uni.reLaunch({
url:'/pages/loginindex'
})
},2000)
tip.error('拒绝访问');
break
case 500:
uni.showToast({
title: response.data.message,
icon: 'none',
duration: 2000
})
setTimeout(function(){
uni.removeStorageSync('third_session')
uni.removeStorageSync('constant')
uni.reLaunch({
url:'/pages/loginindex'
})
},2000)
break
case 404:
uni.showToast({
title: response.data.message,
icon: 'none',
duration: 2000
})
setTimeout(function(){
uni.removeStorageSync('third_session')
uni.removeStorageSync('constant')
uni.reLaunch({
url:'/pages/loginindex'
})
},2000)
break
case 504:
uni.showToast({
title: response.data.message,
icon: 'none',
duration: 2000
})
setTimeout(function(){
uni.removeStorageSync('third_session')
uni.removeStorageSync('constant')
uni.reLaunch({
url:'/pages/loginindex'
})
},2000)
break
case 401:
uni.showToast({
title: response.data.message,
icon: 'none',
duration: 2000
})
setTimeout(function(){
uni.removeStorageSync('third_session')
uni.removeStorageSync('constant')
uni.reLaunch({
url:'/pages/loginindex'
})
},2000)
break
default:
tip.error({
duration: 0,
forbidClick: true,
message: data.message
});
break
}
}
return response
})
export {
http
}

101
common/util/MinCache.js Normal file
View File

@ -0,0 +1,101 @@
let cacheMap = new Map()
let timeoutDefault = 1200
function isTimeout (name) {
const data = cacheMap.get(name)
if (!data) return true
if (data.timeout === 0) return false
const currentTime = Date.now()
const overTime = (currentTime - data.createTime) / 1000
if (overTime > data.timeout) {
cacheMap.delete(name)
if (name.startsWith('_')) {
try {
uni.removeStorageSync(name)
} catch (e) {
console.log(e)
}
}
return true
}
return false
}
class CacheCell {
constructor (data, timeout) {
this.data = data
this.timeout = timeout
this.createTime = Date.now()
}
}
class MinCache {
constructor (timeout) {
try {
const res = uni.getStorageInfoSync()
res.keys.forEach(name => {
try {
const value = uni.getStorageSync(name)
cacheMap.set(name, value)
} catch (e) {
console.log(e)
}
})
} catch (e) {
console.log(e)
}
timeoutDefault = timeout
}
set (name, data, timeout = timeoutDefault) {
const cachecell = new CacheCell(data, timeout)
let cache = null
if (name.startsWith('_')) {
try {
uni.setStorageSync(name, cachecell)
cache = cacheMap.set(name, cachecell)
} catch (e) {
console.log(e)
}
} else {
cache = cacheMap.set(name, cachecell)
}
return cache
}
get (name) {
return isTimeout(name) ? null : cacheMap.get(name).data
}
delete (name) {
let value = false
if (name.startsWith('_')) {
try {
uni.removeStorageSync(name)
value = cacheMap.delete(name)
} catch (e) {
console.log(e)
}
} else {
value = cacheMap.delete(name)
}
return value
}
has (name) {
return !isTimeout(name)
}
clear () {
let value = false
try {
uni.clearStorageSync()
cacheMap.clear()
value = true
} catch (e) {
console.log(e)
}
return value
}
}
MinCache.install = function (Vue, {timeout = 1200} = {}) {
Vue.prototype.$cache = new MinCache(timeout)
}
export default MinCache

73
common/util/appUpdate.js Normal file
View File

@ -0,0 +1,73 @@
//APP更新
export default function appUpdate() {
uni.request({
url: 'http://app.jeecg.com/update.json', //检查更新的服务器地址
data: {
appid: plus.runtime.appid,
version: plus.runtime.version,
imei: plus.device.imei
},
success: (res) => {
plus.runtime.getProperty(plus.runtime.appid, function(wgtinfo) {
let client_version = wgtinfo.version
var flag_update = client_version.split(".").splice(0, 2).join(".") != res.data.version.split(".").splice(0, 2)
.join(".")
var flag_hot = (Number(client_version.split(".")[2]) < Number(res.data.version.split(".")[2])) & !flag_update
console.log(client_version)
console.log(flag_update)
console.log(flag_hot)
if (flag_update) {
// 提醒用户更新
uni.showModal({
title: '更新提示',
content: res.data.note,
success: (showResult) => {
if (showResult.confirm) {
plus.nativeUI.toast("正在准备环境,请稍后!");
console.log(res.data.url, )
var dtask = plus.downloader.createDownload(res.data.url, {
method: 'GET',
filename: '_doc/update/'
}, function(d, status) {
if (status == 200) {
var path = d.filename; //下载apk
plus.runtime.install(path); // 自动安装apk文件
} else {
plus.nativeUI.alert('版本更新失败:' + status);
}
});
dtask.start();
}
}
})
} else if (flag_hot) {
uni.downloadFile({
url: res.data.wgtUrl,
success: (downloadResult) => {
console.log(downloadResult.tempFilePath)
if (downloadResult.statusCode === 200) {
plus.nativeUI.toast(`正在热更新!${res.data.versionCode}`);
plus.runtime.install(downloadResult.tempFilePath, {
force: false
}, function() {
plus.nativeUI.toast("热更新成功");
plus.runtime.restart();
}, function(e) {
console.log(e)
plus.nativeUI.toast(`热更新失败:${e.message}`);
});
}
}
});
}
});
}
})
}

14
common/util/constants.js Normal file
View File

@ -0,0 +1,14 @@
export const ACCESS_TOKEN = 'Access-Token'
export const USER_NAME = 'login_username'
export const USER_INFO = 'login_user_info'
const STORAGE_OPTIONS = {
namespace: 'pro__', // key prefix
name: 'ls', // name variable Vue.[ls] or this.[$ls],
storage: 'local', // storage name session, local, memory
}
export default STORAGE_OPTIONS;

130
common/util/tip.js Normal file
View File

@ -0,0 +1,130 @@
/**
* 提示与加载工具类
*/
export default class Tips {
constructor() {
this.isLoading = false;
}
/**
* 弹出提示框
*/
static success(title, duration = 1000) {
setTimeout(() => {
uni.showToast({
title: title,
icon: "success",
mask: true,
duration: duration
});
}, 300);
if (duration > 0) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, duration);
});
}
}
/**
* 弹出确认窗口
*/
static confirm(text,showCancel, payload = {}, title = "提示") {
return new Promise((resolve, reject) => {
uni.showModal({
title: title,
content: text,
showCancel: showCancel,
success: res => {
if (res.confirm) {
resolve(payload);
} else if (res.cancel) {
reject(payload);
}
},
fail: res => {
reject(payload);
}
});
});
}
static toast(title, onHide, icon = "none") {
setTimeout(() => {
uni.showToast({
title: title,
icon: icon,
mask: true,
duration:1000
});
}, 300);
// 隐藏结束回调
if (onHide) {
setTimeout(() => {
onHide();
}, 500);
}
}
/**
* 警告框
*/
static alert(title) {
uni.showToast({
title: title,
image: "../../static/alert.png",
mask: true,
duration: 1500
});
}
/**
* 错误框
*/
static error(title, onHide) {
uni.showToast({
title: title,
image: "../../static/error.png",
mask: true,
duration: 1500
});
// 隐藏结束回调
if (onHide) {
setTimeout(() => {
onHide();
}, 500);
}
}
/**
* 弹出加载提示
*/
static loading(title = "加载中") {
if (Tips.isLoading) {
return;
}
Tips.isLoading = true;
uni.showLoading({
title: title,
mask: true
});
}
/**
* 加载完毕
*/
static loaded() {
if (Tips.isLoading) {
Tips.isLoading = false;
uni.hideLoading();
}
}
}
/**
* 静态变量是否加载中
*/
Tips.isLoading = false;

37
common/util/vue-py.js Normal file
View File

@ -0,0 +1,37 @@
import { pinyin } from './constants.js';
export default {
chineseToPinYin: function (l1) {
var l2 = l1.length;
var I1 = '';
var reg = new RegExp('[a-zA-Z0-9]');
for (var i = 0; i < l2; i++) {
var val = l1.substr(i, 1);
var name = this.arraySearch(val, pinyin);
if (reg.test(val)) {
I1 += val;
} else if (name !== false) {
I1 += name;
}
}
I1 = I1.replace(/ /g, '-');
while (I1.indexOf('--') > 0) {
I1 = I1.replace('--', '-');
}
return I1;
},
arraySearch: function (l1, l2) {
for (var name in pinyin) {
if (pinyin[name].indexOf(l1) !== -1) {
return this.ucfirst(name);
}
}
return false;
},
ucfirst: function (l1) {
if (l1.length > 0) {
var first = l1.substr(0, 1).toUpperCase();
var spare = l1.substr(1, l1.length);
return first + spare;
}
}
};

124
common/util/work.js Normal file
View File

@ -0,0 +1,124 @@
/**
* 常用服务
* useful server
*/
const icon_prefix="/static/home/128/"
export const us = {
data:[
{
title:"日报",
icon:icon_prefix+"richang.png",
description:"记录每天的工作经验和心得",
useCount:1000,
page:'helloWorld'
},{
title:"周报",
icon:icon_prefix+"zhoubao.png",
description:"总结每周的工作情况和下周计划",
useCount:10000,
page:'helloWorld'
},{
title:"考勤",
icon:icon_prefix+"kaoqin.png",
description:"工作考勤",
useCount:10000,
page:'helloWorld'
},{
title:"日程",
icon:icon_prefix+"richeng.png",
description:"建立和查看个人工作安排",
useCount:10000,
page:'helloWorld'
},{
title:"请假申请",
icon:icon_prefix+"qingjia1.png",
description:"请假申请",
useCount:10000,
page:'helloWorld'
},{
title:"出差申请",
icon:icon_prefix+"chuchai.png",
description:"出差申请",
useCount:10000,
page:'helloWorld'
},{
title:"公文发文",
icon:icon_prefix+"gongwen.png",
description:"公文发文",
useCount:10000,
page:'helloWorld'
},{
title:"通知公告",
icon:icon_prefix+"tongzhi.png",
description:"查看企业对员工下发的通知公告",
useCount:10000,
page:'annotationList'
},{
title:"内部邮件",
icon:icon_prefix+"youjian.png",
description:"查看内部消息",
useCount:10000,
dot:false,
page:'helloWorld'
},{
title:"通讯录",
icon:icon_prefix+"tongxun.png",
description:"查看部门,组员",
useCount:10000,
page:'levelAddressBook'
}
]
}
/**
* other server 其他服务
*/
export const os = {
data:[
{
title:"新闻中心",
icon:icon_prefix+"xinwen.png",
description:"新闻中心",
useCount:10000,
page:'helloWorld'
},{
title:"投票中心",
icon:icon_prefix+"toupiao.png",
description:"投票中心",
useCount:10000,
page:'helloWorld'
},{
title:"任务中心",
icon:icon_prefix+"renwu.png",
description:"任务中心",
useCount:10000,
page:'helloWorld'
},{
title:"文档中心",
icon:icon_prefix+"wendang.png",
description:"文档中心",
useCount:10000,
page:'helloWorld'
},{
title:"合同",
icon:icon_prefix+"hetong.png",
description:"合同",
useCount:10000,
page:'helloWorld'
},{
title:"会议",
icon:icon_prefix+"huiyi.png",
description:"会议",
useCount:10000,
page:'helloWorld'
},{
title:"客户关系",
icon:icon_prefix+"tongzhi.png",
description:"客户关系",
useCount:10000,
page:'helloWorld'
}
]
}

View File

@ -0,0 +1,83 @@
<template>
<view v-if="tabs && tabs.length" class="app-tabs" :class="{'tabs-fixed': fixed}">
<view class="tabs-item">
<view class="tab-item" v-for="(tab, i) in tabs" :class="{'active': value===i}" :key="i" @click="tabClick(i)">
{{getTabName(tab)}}
</view>
</view>
<view class="tabs-line" :style="{left:lineLift}"></view>
</view>
</template>
<script>
export default {
props:{
tabs: Array,
value: { // (使v-model: 1.propsvalue; 2.input)
type: [String, Number],
default(){
return 0
}
},
fixed: Boolean // ,false
},
computed: {
lineLift() {
return 100/this.tabs.length*(this.value + 1) - 100/(this.tabs.length*2) + '%'
}
},
methods: {
getTabName(tab){
return typeof tab === "object" ? tab.name : tab
},
tabClick(i){
if(this.value!=i){
this.$emit("input",i);
this.$emit("change",i);
}
}
}
}
</script>
<style>
.app-tabs{
position: relative;
height: 80rpx;
line-height: 80rpx;
font-size: 24rpx;
background-color: #fff;
border-bottom: 1rpx solid #eee;
}
.app-tabs .tabs-item{
display: flex;
text-align: center;
font-size: 28rpx;
}
.app-tabs .tabs-item .tab-item{
flex: 1;
}
.app-tabs .tabs-item .active{
color: red;
}
.app-tabs .tabs-line{
position: absolute;
bottom: 0;
width: 150rpx;
height: 4rpx;
transform: translateX(-50%);
border-radius: 4rpx;
transition: left .3s;
background: red;
}
/*悬浮*/
.app-tabs.tabs-fixed{
z-index: 9999;
position: fixed;
top: var(--window-top);
left: 0;
width: 100%;
}
</style>

View File

@ -0,0 +1,55 @@
/* 下拉刷新区域 */
.mescroll-downwarp {
position: absolute;
top: -100%;
left: 0;
width: 100%;
height: 100%;
text-align: center;
}
/* 下拉刷新--内容区,定位于区域底部 */
.mescroll-downwarp .downwarp-content {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
min-height: 60rpx;
padding: 20rpx 0;
text-align: center;
}
/* 下拉刷新--提示文本 */
.mescroll-downwarp .downwarp-tip {
display: inline-block;
font-size: 28rpx;
vertical-align: middle;
margin-left: 16rpx;
/* color: gray; 已在style设置color,此处删去*/
}
/* 下拉刷新--旋转进度条 */
.mescroll-downwarp .downwarp-progress {
display: inline-block;
width: 32rpx;
height: 32rpx;
border-radius: 50%;
border: 2rpx solid gray;
border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
vertical-align: middle;
}
/* 旋转动画 */
.mescroll-downwarp .mescroll-rotate {
animation: mescrollDownRotate 0.6s linear infinite;
}
@keyframes mescrollDownRotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -0,0 +1,47 @@
<!-- 下拉刷新区域 -->
<template>
<view v-if="mOption.use" class="mescroll-downwarp" :style="{'background-color':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
<view class="downwarp-content">
<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform':downRotate}"></view>
<view class="downwarp-tip">{{downText}}</view>
</view>
</view>
</template>
<script>
export default {
props: {
option: Object , // down
type: Number, // inOffset1 outOffset2 showLoading3 endDownScroll4
rate: Number // (inOffset: rate<1; outOffset: rate>=1)
},
computed: {
// ,propdefault
mOption(){
return this.option || {}
},
//
isDownLoading(){
return this.type === 3
},
//
downRotate(){
return 'rotate(' + 360 * this.rate + 'deg)'
},
//
downText(){
switch (this.type){
case 1: return this.mOption.textInOffset;
case 2: return this.mOption.textOutOffset;
case 3: return this.mOption.textLoading;
case 4: return this.mOption.textLoading;
default: return this.mOption.textInOffset;
}
}
}
};
</script>
<style>
@import "./mescroll-down.css";
</style>

View File

@ -0,0 +1,91 @@
<!--空布局
可作为独立的组件, 不使用mescroll的页面也能单独引入, 以便APP全局统一管理:
import MescrollEmpty from '@/components/mescroll-uni/components/mescroll-empty.vue';
<mescroll-empty v-if="isShowEmpty" :option="optEmpty" @emptyclick="emptyClick"></mescroll-empty>
-->
<template>
<view class="mescroll-empty" :class="{ 'empty-fixed': option.fixed }" :style="{ 'z-index': option.zIndex, top: option.top }">
<image v-if="icon" class="empty-icon" src="/static/nocontent-1.png" mode="widthFix" />
<view v-if="tip" class="empty-tip">{{ tip }}</view>
<view v-if="option.btnText" class="empty-btn" @click="emptyClick">{{ option.btnText }}</view>
</view>
</template>
<script>
//
import GlobalOption from './../mescroll-uni-option.js';
export default {
props: {
// empty: GlobalOption.up.empty
option: {
type: Object,
default() {
return {
};
}
}
},
// 使computed,option
computed: {
//
icon() {
return this.option.icon == null ? GlobalOption.up.empty.icon : this.option.icon; // 使,
},
//
tip() {
return this.option.tip == null ? GlobalOption.up.empty.tip : this.option.tip; // 使,
}
},
methods: {
//
emptyClick() {
this.$emit('emptyclick');
}
}
};
</script>
<style>
/* 无任何数据的空布局 */
.mescroll-empty {
box-sizing: border-box;
width: 100%;
padding: 60% 50rpx;
text-align: center;
}
.mescroll-empty.empty-fixed {
z-index: 99;
position: absolute; /*transform会使fixed失效,最终会降级为absolute */
top: 100rpx;
left: 0;
}
.mescroll-empty .empty-icon {
width: 280rpx;
height: 280rpx;
}
.mescroll-empty .empty-tip {
font-size: 24rpx;
margin-top: -80rpx;
color: gray;
}
.mescroll-empty .empty-btn {
display: inline-block;
margin-top: 40rpx;
min-width: 200rpx;
padding: 18rpx;
font-size: 28rpx;
border: 1rpx solid #e04b28;
border-radius: 60rpx;
color: #e04b28;
}
.mescroll-empty .empty-btn:active {
opacity: 0.75;
}
</style>

View File

@ -0,0 +1,81 @@
<!-- 回到顶部的按钮 -->
<template>
<image
v-if="mOption.src"
class="mescroll-totop"
:class="[value ? 'mescroll-totop-in' : 'mescroll-totop-out', {'mescroll-safe-bottom': mOption.safearea}]"
:style="{'z-index':mOption.zIndex, 'left': left, 'right': right, 'bottom':addUnit(mOption.bottom), 'width':addUnit(mOption.width), 'border-radius':addUnit(mOption.radius)}"
:src="mOption.src"
mode="widthFix"
@click="toTopClick"
/>
</template>
<script>
export default {
props: {
// up.toTop
option: Object,
//
value: false
},
computed: {
// ,propdefault
mOption(){
return this.option || {}
},
//
left(){
return this.mOption.left ? this.addUnit(this.mOption.left) : 'auto';
},
// ()
right() {
return this.mOption.left ? 'auto' : this.addUnit(this.mOption.right);
}
},
methods: {
addUnit(num){
if(!num) return 0;
if(typeof num === 'number') return num + 'rpx';
return num
},
toTopClick() {
this.$emit('input', false); // 使v-model
this.$emit('click'); //
}
}
};
</script>
<style>
/* 回到顶部的按钮 */
.mescroll-totop {
z-index: 9990;
position: fixed !important; /* 加上important避免编译到H5,在多mescroll中定位失效 */
right: 20rpx;
bottom: 120rpx;
width: 72rpx;
height: auto;
border-radius: 50%;
opacity: 0;
transition: opacity 0.5s; /* 过渡 */
margin-bottom: var(--window-bottom); /* css变量 */
}
/* 适配 iPhoneX */
.mescroll-safe-bottom{
margin-bottom: calc(var(--window-bottom) + constant(safe-area-inset-bottom)); /* window-bottom + 适配 iPhoneX */
margin-bottom: calc(var(--window-bottom) + env(safe-area-inset-bottom));
}
/* 显示 -- 淡入 */
.mescroll-totop-in {
opacity: 1;
}
/* 隐藏 -- 淡出且不接收事件*/
.mescroll-totop-out {
opacity: 0;
pointer-events: none;
}
</style>

View File

@ -0,0 +1,46 @@
/* 上拉加载区域 */
.mescroll-upwarp {
min-height: 60rpx;
padding: 30rpx 0;
text-align: center;
clear: both;
}
/*提示文本 */
.mescroll-upwarp .upwarp-tip,
.mescroll-upwarp .upwarp-nodata {
display: inline-block;
font-size: 28rpx;
vertical-align: middle;
/* color: gray; 已在style设置color,此处删去*/
}
.mescroll-upwarp .upwarp-tip {
margin-left: 16rpx;
}
/*旋转进度条 */
.mescroll-upwarp .upwarp-progress {
display: inline-block;
width: 32rpx;
height: 32rpx;
border-radius: 50%;
border: 2rpx solid gray;
border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
vertical-align: middle;
}
/* 旋转动画 */
.mescroll-upwarp .mescroll-rotate {
animation: mescrollUpRotate 0.6s linear infinite;
}
@keyframes mescrollUpRotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -0,0 +1,39 @@
<!-- 上拉加载区域 -->
<template>
<view class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
<view v-show="isUpLoading">
<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
<view class="upwarp-tip">{{ mOption.textLoading }}</view>
</view>
<!-- 无数据 -->
<view v-if="isUpNoMore" class="upwarp-nodata">{{ mOption.textNoMore }}</view>
</view>
</template>
<script>
export default {
props: {
option: Object, // up
type: Number // 0loading1loading2
},
computed: {
// ,propdefault
mOption() {
return this.option || {};
},
//
isUpLoading() {
return this.type === 1;
},
//
isUpNoMore() {
return this.type === 2;
}
}
};
</script>
<style>
@import './mescroll-up.css';
</style>

View File

@ -0,0 +1,10 @@
page {
-webkit-overflow-scrolling: touch; /* 使iOS滚动流畅 */
}
.mescroll-body {
position: relative; /* 下拉刷新区域相对自身定位 */
height: auto; /* 不可固定高度,否则overflow: hidden, 可通过设置最小高度使列表不满屏仍可下拉*/
overflow: hidden; /* 遮住顶部下拉刷新区域 */
box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
}

View File

@ -0,0 +1,292 @@
<template>
<view class="mescroll-body" :style="{'minHeight':minHeight, 'padding-top': padTop, 'padding-bottom': padBottom, 'padding-bottom': padBottomConstant, 'padding-bottom': padBottomEnv }" @touchstart="touchstartEvent" @touchmove="touchmoveEvent" @touchend="touchendEvent" @touchcancel="touchendEvent" >
<view class="mescroll-body-content" :style="{ transform: translateY, transition: transition }">
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background-color':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
<view class="downwarp-content">
<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform': downRotate}"></view>
<view class="downwarp-tip">{{downText}}</view>
</view>
</view>
<!-- 列表内容 -->
<slot></slot>
<!-- 空布局 -->
<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
<view v-if="mescroll.optUp.use && !isDownLoading" class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
<view v-show="upLoadType===1">
<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
</view>
<!-- 无数据 -->
<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
</view>
</view>
<!-- 回到顶部按钮 (fixed元素需写在transform外面,防止降级为absolute)-->
<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
</view>
</template>
<script>
// mescroll-uni.js,
import MeScroll from './mescroll-uni.js';
//
import GlobalOption from './mescroll-uni-option.js';
//
import MescrollEmpty from './components/mescroll-empty.vue';
//
import MescrollTop from './components/mescroll-top.vue';
export default {
components: {
MescrollEmpty,
MescrollTop
},
data() {
return {
mescroll: {optDown:{},optUp:{}}, // mescroll
downHight: 0, //:
downRate: 0, // (inOffset: rate<1; outOffset: rate>=1)
downLoadType: 4, // inOffset1 outOffset2 showLoading3 endDownScroll4
upLoadType: 0, // 0loading1loading2
isShowEmpty: false, //
isShowToTop: false, //
windowHeight: 0, // 使
statusBarHeight: 0, //
isSafearea: false //
};
},
props: {
down: Object, //
up: Object, //
top: [String, Number], // (20, "20rpx", "20px", "20%", rpx, windowHeight)
topbar: Boolean, // top, false (使:,)
bottom: [String, Number], // (20, "20rpx", "20px", "20%", rpx, windowHeight)
safearea: Boolean, // bottom, false (iPhoneX使)
height: [String, Number] // mescroll,windowHeight,使
},
computed: {
// mescroll,windowHeight,使
minHeight(){
return this.toPx(this.height || '100%') + 'px'
},
// (px)
numTop() {
return this.toPx(this.top) + (this.topbar ? this.statusBarHeight : 0);
},
padTop() {
return this.numTop + 'px';
},
// (px)
numBottom() {
return this.toPx(this.bottom);
},
padBottom() {
return this.numBottom + 'px';
},
padBottomConstant() {
return this.isSafearea ? 'calc(' + this.padBottom + ' + constant(safe-area-inset-bottom))' : this.padBottom;
},
padBottomEnv() {
return this.isSafearea ? 'calc(' + this.padBottom + ' + env(safe-area-inset-bottom))' : this.padBottom;
},
//
isDownReset() {
return this.downLoadType === 3 || this.downLoadType === 4;
},
//
transition() {
return this.isDownReset ? 'transform 300ms' : this.downTransition;
},
translateY() {
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform使fixed,fixedmescroll
},
//
isDownLoading(){
return this.downLoadType === 3
},
//
downRotate(){
return 'rotate(' + 360 * this.downRate + 'deg)'
},
//
downText(){
switch (this.downLoadType){
case 1: return this.mescroll.optDown.textInOffset;
case 2: return this.mescroll.optDown.textOutOffset;
case 3: return this.mescroll.optDown.textLoading;
case 4: return this.mescroll.optDown.textLoading;
default: return this.mescroll.optDown.textInOffset;
}
}
},
methods: {
//number,rpx,upx,px,% --> px
toPx(num) {
if (typeof num === 'string') {
if (num.indexOf('px') !== -1) {
if (num.indexOf('rpx') !== -1) {
// "10rpx"
num = num.replace('rpx', '');
} else if (num.indexOf('upx') !== -1) {
// "10upx"
num = num.replace('upx', '');
} else {
// "10px"
return Number(num.replace('px', ''));
}
} else if (num.indexOf('%') !== -1) {
// ,windowHeight,"10%"windowHeight10%
let rate = Number(num.replace('%', '')) / 100;
return this.windowHeight * rate;
}
}
return num ? uni.upx2px(Number(num)) : 0;
},
//touchstart,
touchstartEvent(e) {
this.mescroll.touchstartEvent(e);
},
//touchmove,
touchmoveEvent(e) {
this.mescroll.touchmoveEvent(e);
},
//touchend,
touchendEvent(e) {
this.mescroll.touchendEvent(e);
},
//
emptyClick() {
this.$emit('emptyclick', this.mescroll);
},
//
toTopClick() {
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); //
this.$emit('topclick', this.mescroll); //
}
},
// 使createdmescroll; mountedcssH5
created() {
let vm = this;
let diyOption = {
//
down: {
inOffset(mescroll) {
vm.downLoadType = 1; // offset (mescroll,)
},
outOffset(mescroll) {
vm.downLoadType = 2; // offset (mescroll,)
},
onMoving(mescroll, rate, downHight) {
// ,;
vm.downHight = downHight; // (mescroll,)
vm.downRate = rate; // (inOffset: rate<1; outOffset: rate>=1)
},
showLoading(mescroll, downHight) {
vm.downLoadType = 3; // (mescroll,)
vm.downHight = downHight; // (mescroll,)
},
endDownScroll(mescroll) {
vm.downLoadType = 4; // (mescroll,)
vm.downHight = 0; // (mescroll,)
},
//
callback: function(mescroll) {
vm.$emit('down', mescroll);
}
},
//
up: {
//
showLoading() {
vm.upLoadType = 1;
},
//
showNoMore() {
vm.upLoadType = 2;
},
//
hideUpScroll() {
vm.upLoadType = 0;
},
//
empty: {
onShow(isShow) {
//
vm.isShowEmpty = isShow;
}
},
//
toTop: {
onShow(isShow) {
//
vm.isShowToTop = isShow;
}
},
//
callback: function(mescroll) {
vm.$emit('up', mescroll);
}
}
};
MeScroll.extend(diyOption, GlobalOption); //
let myOption = JSON.parse(
JSON.stringify({
down: vm.down,
up: vm.up
})
); // ,props
MeScroll.extend(myOption, diyOption); //
// MeScroll
vm.mescroll = new MeScroll(myOption, true); // true,body
// initmescroll
vm.$emit('init', vm.mescroll);
//
const sys = uni.getSystemInfoSync();
if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
// 使downbottomOffset
vm.mescroll.setBodyHeight(sys.windowHeight);
// mescroll-bodyAndroid,mescroll-uni"disableScroll":true,
// #ifdef MP
if(sys.platform == "android") vm.downTransition = 'transform 200ms'
// #endif
// 使pagescroll,scrollTo
vm.mescroll.resetScrollTo((y, t) => {
uni.pageScrollTo({
scrollTop: y,
duration: t
})
});
// up.toTop.safearea,vuesafearea
if(sys.platform == "ios"){
vm.isSafearea = vm.safearea;
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
vm.mescroll.optUp.toTop.safearea = vm.safearea;
}
}else{
vm.isSafearea = false
vm.mescroll.optUp.toTop.safearea = false
}
}
};
</script>
<style>
@import "./mescroll-body.css";
@import "./components/mescroll-down.css";
@import './components/mescroll-up.css';
</style>

View File

@ -0,0 +1,60 @@
// mescroll-body 和 mescroll-uni 通用
// import MescrollUni from "./mescroll-uni.vue";
// import MescrollBody from "./mescroll-body.vue";
const MescrollMixin = {
// components: { // 非H5端无法通过mixin注册组件, 只能在main.js中注册全局组件或具体界面中注册
// MescrollUni,
// MescrollBody
// },
data() {
return {
mescroll: null //mescroll实例对象
}
},
// 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
onPullDownRefresh(){
this.mescroll && this.mescroll.onPullDownRefresh();
},
// 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
onPageScroll(e) {
this.mescroll && this.mescroll.onPageScroll(e);
},
// 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
onReachBottom() {
this.mescroll && this.mescroll.onReachBottom();
},
methods: {
// mescroll组件初始化的回调,可获取到mescroll对象
mescrollInit(mescroll) {
this.mescroll = mescroll;
this.mescrollInitByRef(); // 兼容字节跳动小程序
},
// 以ref的方式初始化mescroll对象 (兼容字节跳动小程序: http://www.mescroll.com/qa.html?v=20200107#q26)
mescrollInitByRef() {
if(!this.mescroll || !this.mescroll.resetUpScroll){
let mescrollRef = this.$refs.mescrollRef;
if(mescrollRef) this.mescroll = mescrollRef.mescroll
}
},
// 下拉刷新的回调
downCallback() {
// mixin默认resetUpScroll
this.mescroll.resetUpScroll()
},
// 上拉加载的回调
upCallback() {
// mixin默认延时500自动结束加载
setTimeout(()=>{
this.mescroll.endErr();
}, 500)
}
},
mounted() {
this.mescrollInitByRef(); // 兼容字节跳动小程序, 避免未设置@init或@init此时未能取到ref的情况
}
}
export default MescrollMixin;

View File

@ -0,0 +1,34 @@
// 全局配置
// mescroll-body 和 mescroll-uni 通用
const GlobalOption = {
down: {
// 其他down的配置参数也可以写,这里只展示了常用的配置:
textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
textLoading: '加载中 ...', // 加载中的提示文本
offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
},
up: {
// 其他up的配置参数也可以写,这里只展示了常用的配置:
textLoading: '加载中 ...', // 加载中的提示文本
textNoMore: '-- END --', // 没有更多数据的提示文本
offset: 80, // 距底部多远时,触发upCallback
isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
toTop: {
// 回到顶部按钮,需配置src才显示
src: "http://www.mescroll.com/img/mescroll-totop.png?v=1", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
},
empty: {
use: true, // 是否显示空布局
icon: "http://www.mescroll.com/img/mescroll-empty.png?v=1", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
tip: '~ 暂无相关数据 ~' // 提示
}
}
}
export default GlobalOption

View File

@ -0,0 +1,29 @@
page {
height: 100%;
box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
}
.mescroll-uni-warp{
height: 100%;
}
.mescroll-uni {
position: relative;
width: 100%;
height: 100%;
min-height: 200rpx;
overflow-y: auto;
box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
}
/* 定位的方式固定高度 */
.mescroll-uni-fixed{
z-index: 1;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: auto; /* 使right生效 */
height: auto; /* 使bottom生效 */
}

View File

@ -0,0 +1,862 @@
/* mescroll
* version 1.2.5
* 2020-03-15 wenju
* http://www.mescroll.com
*/
export default function MeScroll(options, isScrollBody) {
let me = this;
me.version = '1.2.5'; // mescroll版本号
me.options = options || {}; // 配置
me.isScrollBody = isScrollBody || false; // 滚动区域是否为原生页面滚动; 默认为scroll-view
me.isDownScrolling = false; // 是否在执行下拉刷新的回调
me.isUpScrolling = false; // 是否在执行上拉加载的回调
let hasDownCallback = me.options.down && me.options.down.callback; // 是否配置了down的callback
// 初始化下拉刷新
me.initDownScroll();
// 初始化上拉加载,则初始化
me.initUpScroll();
// 自动加载
setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
// 自动触发下拉刷新 (只有配置了down的callback才自动触发下拉刷新)
if (me.optDown.use && me.optDown.auto && hasDownCallback) {
if (me.optDown.autoShowLoading) {
me.triggerDownScroll(); // 显示下拉进度,执行下拉回调
} else {
me.optDown.callback && me.optDown.callback(me); // 不显示下拉进度,直接执行下拉回调
}
}
// 自动触发上拉加载
setTimeout(function(){ // 延时确保先执行down的callback,再执行up的callback,因为部分小程序emit是异步,会导致isUpAutoLoad判断有误
me.optUp.use && me.optUp.auto && !me.isUpAutoLoad && me.triggerUpScroll();
},100)
}, 30); // 需让me.optDown.inited和me.optUp.inited先执行
}
/* 配置参数:下拉刷新 */
MeScroll.prototype.extendDownScroll = function(optDown) {
// 下拉刷新的配置
MeScroll.extend(optDown, {
use: true, // 是否启用下拉刷新; 默认true
auto: true, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
native: false, // 是否使用系统自带的下拉刷新; 默认false; 仅mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
autoShowLoading: false, // 如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
isLock: false, // 是否锁定下拉刷新,默认false;
offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
startTop: 100, // scroll-view滚动到顶部时,此时的scroll-top不一定为0, 此值用于控制最大的误差
fps: 80, // 下拉节流 (值越大每秒刷新频率越高)
inOffsetRate: 1, // 在列表顶部,下拉的距离小于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
outOffsetRate: 0.2, // 在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
bottomOffset: 20, // 当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
minAngle: 45, // 向下滑动最少偏移的角度,取值区间 [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
textLoading: '加载中 ...', // 加载中的提示文本
bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorTop)
textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
inited: null, // 下拉刷新初始化完毕的回调
inOffset: null, // 下拉的距离进入offset范围内那一刻的回调
outOffset: null, // 下拉的距离大于offset那一刻的回调
onMoving: null, // 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
showLoading: null, // 显示下拉刷新进度的回调
afterLoading: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】
endDownScroll: null, // 结束下拉刷新的回调
callback: function(mescroll) {
// 下拉刷新的回调;默认重置上拉加载列表为第一页
mescroll.resetUpScroll();
}
})
}
/* 配置参数:上拉加载 */
MeScroll.prototype.extendUpScroll = function(optUp) {
// 上拉加载的配置
MeScroll.extend(optUp, {
use: true, // 是否启用上拉加载; 默认true
auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
isLock: false, // 是否锁定上拉加载,默认false;
isBoth: true, // 上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认true,两者可同时触发;
isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
callback: null, // 上拉加载的回调;function(page,mescroll){ }
page: {
num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
size: 10, // 每页数据的数量
time: null // 加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
},
noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
offset: 80, // 距底部多远时,触发upCallback
textLoading: '加载中 ...', // 加载中的提示文本
textNoMore: '-- END --', // 没有更多数据的提示文本
bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorBottom)
textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
inited: null, // 初始化完毕的回调
showLoading: null, // 显示加载中的回调
showNoMore: null, // 显示无更多数据的回调
hideUpScroll: null, // 隐藏上拉加载的回调
errDistance: 60, // endErr的时候需往上滑动一段距离,使其往下滑动时再次触发onReachBottom,仅mescroll-body生效
toTop: {
// 回到顶部按钮,需配置src才显示
src: null, // 图片路径,默认null (绝对路径或网络图)
offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
duration: 300, // 回到顶部的动画时长,默认300ms (当值为0或300则使用系统自带回到顶部,更流畅; 其他值则通过step模拟,部分机型可能不够流畅,所以非特殊情况不建议修改此项)
btnClick: null, // 点击按钮的回调
onShow: null, // 是否显示的回调
zIndex: 9990, // fixed定位z-index值
left: null, // 到左边的距离, 默认null. 此项有值时,right不生效. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
right: 20, // 到右边的距离, 默认20 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
bottom: 120, // 到底部的距离, 默认120 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
safearea: false, // bottom的偏移量是否加上底部安全区的距离, 默认false, 需要适配iPhoneX时使用 (具体的界面如果不配置此项,则取本vue的safearea值)
width: 72, // 回到顶部图标的宽度, 默认72 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
radius: "50%" // 圆角, 默认"50%" (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
},
empty: {
use: true, // 是否显示空布局
icon: null, // 图标路径
tip: '~ 暂无相关数据 ~', // 提示
btnText: '', // 按钮
btnClick: null, // 点击按钮的回调
onShow: null, // 是否显示的回调
fixed: false, // 是否使用fixed定位,默认false; 配置fixed为true,以下的top和zIndex才生效 (transform会使fixed失效,最终会降级为absolute)
top: "100rpx", // fixed定位的top值 (完整的单位值,如 "10%"; "100rpx")
zIndex: 99 // fixed定位z-index值
},
onScroll: false // 是否监听滚动事件
})
}
/* 配置参数 */
MeScroll.extend = function(userOption, defaultOption) {
if (!userOption) return defaultOption;
for (let key in defaultOption) {
if (userOption[key] == null) {
let def = defaultOption[key];
if (def != null && typeof def === 'object') {
userOption[key] = MeScroll.extend({}, def); // 深度匹配
} else {
userOption[key] = def;
}
} else if (typeof userOption[key] === 'object') {
MeScroll.extend(userOption[key], defaultOption[key]); // 深度匹配
}
}
return userOption;
}
/* 简单判断是否配置了颜色 (非透明,非白色) */
MeScroll.prototype.hasColor = function(color) {
if(!color) return false;
let c = color.toLowerCase();
return c != "#fff" && c != "#ffffff" && c != "transparent" && c != "white"
}
/* -------初始化下拉刷新------- */
MeScroll.prototype.initDownScroll = function() {
let me = this;
// 配置参数
me.optDown = me.options.down || {};
if(!me.optDown.textColor && me.hasColor(me.optDown.bgColor)) me.optDown.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
me.extendDownScroll(me.optDown);
// 如果是mescroll-body且配置了native,则禁止自定义的下拉刷新
if(me.isScrollBody && me.optDown.native){
me.optDown.use = false
}else{
me.optDown.native = false // 仅mescroll-body支持,mescroll-uni不支持
}
me.downHight = 0; // 下拉区域的高度
// 在页面中加入下拉布局
if (me.optDown.use && me.optDown.inited) {
// 初始化完毕的回调
setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
me.optDown.inited(me);
}, 0)
}
}
/* 列表touchstart事件 */
MeScroll.prototype.touchstartEvent = function(e) {
if (!this.optDown.use) return;
this.startPoint = this.getPoint(e); // 记录起点
this.startTop = this.getScrollTop(); // 记录此时的滚动条位置
this.lastPoint = this.startPoint; // 重置上次move的点
this.maxTouchmoveY = this.getBodyHeight() - this.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
this.inTouchend = false; // 标记不是touchend
}
/* 列表touchmove事件 */
MeScroll.prototype.touchmoveEvent = function(e) {
// #ifdef H5
window.isPreventDefault = false // 标记不需要阻止window事件
// #endif
if (!this.optDown.use) return;
if (!this.startPoint) return;
let me = this;
// 节流
let t = new Date().getTime();
if (me.moveTime && t - me.moveTime < me.moveTimeDiff) { // 小于节流时间,则不处理
return;
} else {
me.moveTime = t
if(!me.moveTimeDiff) me.moveTimeDiff = 1000 / me.optDown.fps
}
let scrollTop = me.getScrollTop(); // 当前滚动条的距离
let curPoint = me.getPoint(e); // 当前点
let moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
// 向下拉 && 在顶部
// mescroll-body,直接判定在顶部即可
// scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
// scroll-view滚动到顶部时,scrollTop不一定为0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
if (moveY > 0 && (
(me.isScrollBody && scrollTop <= 0)
||
(!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
)) {
// 可下拉的条件
if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
me.optUp.isBoth))) {
// 下拉的角度是否在配置的范围内
let angle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
if (angle < me.optDown.minAngle) return; // 如果小于配置的角度,则不往下执行下拉刷新
// 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
me.inTouchend = true; // 标记执行touchend
me.touchendEvent(); // 提前触发touchend
return;
}
// #ifdef H5
window.isPreventDefault = true // 标记阻止window事件
// #endif
me.preventDefault(e); // 阻止默认事件
let diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
// 下拉距离 < 指定距离
if (me.downHight < me.optDown.offset) {
if (me.movetype !== 1) {
me.movetype = 1; // 加入标记,保证只执行一次
me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
}
me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
// 指定距离 <= 下拉距离
} else {
if (me.movetype !== 2) {
me.movetype = 2; // 加入标记,保证只执行一次
me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
}
if (diff > 0) { // 向下拉
me.downHight += Math.round(diff * me.optDown.outOffsetRate); // 越往下,高度变化越小
} else { // 向上收
me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
}
}
let rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
}
}
me.lastPoint = curPoint; // 记录本次移动的点
}
/* 列表touchend事件 */
MeScroll.prototype.touchendEvent = function(e) {
if (!this.optDown.use) return;
// 如果下拉区域高度已改变,则需重置回来
if (this.isMoveDown) {
if (this.downHight >= this.optDown.offset) {
// 符合触发刷新的条件
this.triggerDownScroll();
} else {
// 不符合的话 则重置
this.downHight = 0;
this.optDown.endDownScroll && this.optDown.endDownScroll(this);
}
this.movetype = 0;
this.isMoveDown = false;
} else if (!this.isScrollBody && this.getScrollTop() === this.startTop) { // scroll-view到顶/左/右/底的滑动事件
let isScrollUp = this.getPoint(e).y - this.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
// 上滑
if (isScrollUp) {
// 需检查滑动的角度
let angle = this.getAngle(this.getPoint(e), this.startPoint); // 两点之间的角度,区间 [0,90]
if (angle > 80) {
// 检查并触发上拉
this.triggerUpScroll(true);
}
}
}
}
/* 根据点击滑动事件获取第一个手指的坐标 */
MeScroll.prototype.getPoint = function(e) {
if (!e) {
return {
x: 0,
y: 0
}
}
if (e.touches && e.touches[0]) {
return {
x: e.touches[0].pageX,
y: e.touches[0].pageY
}
} else if (e.changedTouches && e.changedTouches[0]) {
return {
x: e.changedTouches[0].pageX,
y: e.changedTouches[0].pageY
}
} else {
return {
x: e.clientX,
y: e.clientY
}
}
}
/* 计算两点之间的角度: 区间 [0,90]*/
MeScroll.prototype.getAngle = function(p1, p2) {
let x = Math.abs(p1.x - p2.x);
let y = Math.abs(p1.y - p2.y);
let z = Math.sqrt(x * x + y * y);
let angle = 0;
if (z !== 0) {
angle = Math.asin(y / z) / Math.PI * 180;
}
return angle
}
/* 触发下拉刷新 */
MeScroll.prototype.triggerDownScroll = function() {
if (this.optDown.beforeLoading && this.optDown.beforeLoading(this)) {
//return true则处于完全自定义状态
} else {
this.showDownScroll(); // 下拉刷新中...
this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
}
}
/* 显示下拉进度布局 */
MeScroll.prototype.showDownScroll = function() {
this.isDownScrolling = true; // 标记下拉中
if (this.optDown.native) {
uni.startPullDownRefresh(); // 系统自带的下拉刷新
this.optDown.showLoading && this.optDown.showLoading(this, 0); // 仍触发showLoading,因为上拉加载用到
} else{
this.downHight = this.optDown.offset; // 更新下拉区域高度
this.optDown.showLoading && this.optDown.showLoading(this, this.downHight); // 下拉刷新中...
}
}
/* 显示系统自带的下拉刷新时需要处理的业务 */
MeScroll.prototype.onPullDownRefresh = function() {
this.isDownScrolling = true; // 标记下拉中
this.optDown.showLoading && this.optDown.showLoading(this, 0); // 仍触发showLoading,因为上拉加载用到
this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
}
/* 结束下拉刷新 */
MeScroll.prototype.endDownScroll = function() {
if (this.optDown.native) { // 结束原生下拉刷新
this.isDownScrolling = false;
this.optDown.endDownScroll && this.optDown.endDownScroll(this);
uni.stopPullDownRefresh();
return
}
let me = this;
// 结束下拉刷新的方法
let endScroll = function() {
me.downHight = 0;
me.isDownScrolling = false;
me.optDown.endDownScroll && me.optDown.endDownScroll(me);
!me.isScrollBody && me.setScrollHeight(0) // scroll-view重置滚动区域,使数据不满屏时仍可检查触发翻页
}
// 结束下拉刷新时的回调
let delay = 0;
if (me.optDown.afterLoading) delay = me.optDown.afterLoading(me); // 结束下拉刷新的延时,单位ms
if (typeof delay === 'number' && delay > 0) {
setTimeout(endScroll, delay);
} else {
endScroll();
}
}
/* 锁定下拉刷新:isLock=ture,null锁定;isLock=false解锁 */
MeScroll.prototype.lockDownScroll = function(isLock) {
if (isLock == null) isLock = true;
this.optDown.isLock = isLock;
}
/* 锁定上拉加载:isLock=ture,null锁定;isLock=false解锁 */
MeScroll.prototype.lockUpScroll = function(isLock) {
if (isLock == null) isLock = true;
this.optUp.isLock = isLock;
}
/* -------初始化上拉加载------- */
MeScroll.prototype.initUpScroll = function() {
let me = this;
// 配置参数
me.optUp = me.options.up || {use: false}
if(!me.optUp.textColor && me.hasColor(me.optUp.bgColor)) me.optUp.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
me.extendUpScroll(me.optUp);
if (!me.optUp.isBounce) me.setBounce(false); // 不允许bounce时,需禁止window的touchmove事件
if (me.optUp.use === false) return; // 配置不使用上拉加载时,则不初始化上拉布局
me.optUp.hasNext = true; // 如果使用上拉,则默认有下一页
me.startNum = me.optUp.page.num + 1; // 记录page开始的页码
// 初始化完毕的回调
if (me.optUp.inited) {
setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
me.optUp.inited(me);
}, 0)
}
}
/*滚动到底部的事件 (仅mescroll-body生效)*/
MeScroll.prototype.onReachBottom = function() {
if (this.isScrollBody && !this.isUpScrolling) { // 只能支持下拉刷新的时候同时可以触发上拉加载,否则滚动到底部就需要上滑一点才能触发onReachBottom
if (!this.optUp.isLock && this.optUp.hasNext) {
this.triggerUpScroll();
}
}
}
/*列表滚动事件 (仅mescroll-body生效)*/
MeScroll.prototype.onPageScroll = function(e) {
if (!this.isScrollBody) return;
// 更新滚动条的位置 (主要用于判断下拉刷新时,滚动条是否在顶部)
this.setScrollTop(e.scrollTop);
// 顶部按钮的显示隐藏
if (e.scrollTop >= this.optUp.toTop.offset) {
this.showTopBtn();
} else {
this.hideTopBtn();
}
}
/*列表滚动事件*/
MeScroll.prototype.scroll = function(e, onScroll) {
// 更新滚动条的位置
this.setScrollTop(e.scrollTop);
// 更新滚动内容高度
this.setScrollHeight(e.scrollHeight);
// 向上滑还是向下滑动
if (this.preScrollY == null) this.preScrollY = 0;
this.isScrollUp = e.scrollTop - this.preScrollY > 0;
this.preScrollY = e.scrollTop;
// 上滑 && 检查并触发上拉
this.isScrollUp && this.triggerUpScroll(true);
// 顶部按钮的显示隐藏
if (e.scrollTop >= this.optUp.toTop.offset) {
this.showTopBtn();
} else {
this.hideTopBtn();
}
// 滑动监听
this.optUp.onScroll && onScroll && onScroll()
}
/* 触发上拉加载 */
MeScroll.prototype.triggerUpScroll = function(isCheck) {
if (!this.isUpScrolling && this.optUp.use && this.optUp.callback) {
// 是否校验在底部; 默认不校验
if (isCheck === true) {
let canUp = false;
// 还有下一页 && 没有锁定 && 不在下拉中
if (this.optUp.hasNext && !this.optUp.isLock && !this.isDownScrolling) {
if (this.getScrollBottom() <= this.optUp.offset) { // 到底部
canUp = true; // 标记可上拉
}
}
if (canUp === false) return;
}
this.showUpScroll(); // 上拉加载中...
this.optUp.page.num++; // 预先加一页,如果失败则减回
this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
this.num = this.optUp.page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
this.size = this.optUp.page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
this.time = this.optUp.page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
this.optUp.callback(this); // 执行回调,联网加载数据
}
}
/* 显示上拉加载中 */
MeScroll.prototype.showUpScroll = function() {
this.isUpScrolling = true; // 标记上拉加载中
this.optUp.showLoading && this.optUp.showLoading(this); // 回调
}
/* 显示上拉无更多数据 */
MeScroll.prototype.showNoMore = function() {
this.optUp.hasNext = false; // 标记无更多数据
this.optUp.showNoMore && this.optUp.showNoMore(this); // 回调
}
/* 隐藏上拉区域**/
MeScroll.prototype.hideUpScroll = function() {
this.optUp.hideUpScroll && this.optUp.hideUpScroll(this); // 回调
}
/* 结束上拉加载 */
MeScroll.prototype.endUpScroll = function(isShowNoMore) {
if (isShowNoMore != null) { // isShowNoMore=null,不处理下拉状态,下拉刷新的时候调用
if (isShowNoMore) {
this.showNoMore(); // isShowNoMore=true,显示无更多数据
} else {
this.hideUpScroll(); // isShowNoMore=false,隐藏上拉加载
}
}
this.isUpScrolling = false; // 标记结束上拉加载
}
/*
*isShowLoading 是否显示进度布局;
* 1.默认null,不传参,则显示上拉加载的进度布局
* 2.传参true, 则显示下拉刷新的进度布局
* 3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)
*/
MeScroll.prototype.resetUpScroll = function(isShowLoading) {
if (this.optUp && this.optUp.use) {
let page = this.optUp.page;
this.prePageNum = page.num; // 缓存重置前的页码,加载失败可退回
this.prePageTime = page.time; // 缓存重置前的时间,加载失败可退回
page.num = this.startNum; // 重置为第一页
page.time = null; // 重置时间为空
if (!this.isDownScrolling && isShowLoading !== false) { // 如果不是下拉刷新触发的resetUpScroll并且不配置列表静默更新,则显示进度;
if (isShowLoading == null) {
this.removeEmpty(); // 移除空布局
this.showUpScroll(); // 不传参,默认显示上拉加载的进度布局
} else {
this.showDownScroll(); // 传true,显示下拉刷新的进度布局,不清空列表
}
}
this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
this.num = page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
this.size = page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
this.time = page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
this.optUp.callback && this.optUp.callback(this); // 执行上拉回调
}
}
/* 设置page.num的值 */
MeScroll.prototype.setPageNum = function(num) {
this.optUp.page.num = num - 1;
}
/* 设置page.size的值 */
MeScroll.prototype.setPageSize = function(size) {
this.optUp.page.size = size;
}
/* ,
* dataSize: 当前页的数据量(必传)
* totalPage: 总页数(必传)
* systime: 服务器时间 (可空)
*/
MeScroll.prototype.endByPage = function(dataSize, totalPage, systime) {
let hasNext;
if (this.optUp.use && totalPage != null) hasNext = this.optUp.page.num < totalPage; // 是否还有下一页
this.endSuccess(dataSize, hasNext, systime);
}
/* ,
* dataSize: 当前页的数据量(必传)
* totalSize: 列表所有数据总数量(必传)
* systime: 服务器时间 (可空)
*/
MeScroll.prototype.endBySize = function(dataSize, totalSize, systime) {
let hasNext;
if (this.optUp.use && totalSize != null) {
let loadSize = (this.optUp.page.num - 1) * this.optUp.page.size + dataSize; // 已加载的数据总数
hasNext = loadSize < totalSize; // 是否还有下一页
}
this.endSuccess(dataSize, hasNext, systime);
}
/* ,
* dataSize: 当前页的数据个数(不是所有页的数据总和),用于上拉加载判断是否还有下一页.如果不传,则会判断还有下一页
* hasNext: 是否还有下一页,布尔类型;用来解决这个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据dataSize判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
* systime: 服务器时间(可空);用来解决这个小问题:当准备翻下一页时,数据库新增了几条记录,此时翻下一页,前面的几条数据会和上一页的重复;这里传入了systime,那么upCallback的page.time就会有值,把page.time传给服务器,让后台过滤新加入的那几条记录
*/
MeScroll.prototype.endSuccess = function(dataSize, hasNext, systime) {
let me = this;
// 结束下拉刷新
if (me.isDownScrolling) me.endDownScroll();
// 结束上拉加载
if (me.optUp.use) {
let isShowNoMore; // 是否已无更多数据
if (dataSize != null) {
let pageNum = me.optUp.page.num; // 当前页码
let pageSize = me.optUp.page.size; // 每页长度
// 如果是第一页
if (pageNum === 1) {
if (systime) me.optUp.page.time = systime; // 设置加载列表数据第一页的时间
}
if (dataSize < pageSize || hasNext === false) {
// 返回的数据不满一页时,则说明已无更多数据
me.optUp.hasNext = false;
if (dataSize === 0 && pageNum === 1) {
// 如果第一页无任何数据且配置了空布局
isShowNoMore = false;
me.showEmpty();
} else {
// 总列表数少于配置的数量,则不显示无更多数据
let allDataSize = (pageNum - 1) * pageSize + dataSize;
if (allDataSize < me.optUp.noMoreSize) {
isShowNoMore = false;
} else {
isShowNoMore = true;
}
me.removeEmpty(); // 移除空布局
}
} else {
// 还有下一页
isShowNoMore = false;
me.optUp.hasNext = true;
me.removeEmpty(); // 移除空布局
}
}
// 隐藏上拉
me.endUpScroll(isShowNoMore);
}
}
/* 回调失败,结束下拉刷新和上拉加载 */
MeScroll.prototype.endErr = function(errDistance) {
// 结束下拉,回调失败重置回原来的页码和时间
if (this.isDownScrolling) {
let page = this.optUp.page;
if (page && this.prePageNum) {
page.num = this.prePageNum;
page.time = this.prePageTime;
}
this.endDownScroll();
}
// 结束上拉,回调失败重置回原来的页码
if (this.isUpScrolling) {
this.optUp.page.num--;
this.endUpScroll(false);
// 如果是mescroll-body,则需往回滚一定距离
if(this.isScrollBody && errDistance !== 0){ // 不处理0
if(!errDistance) errDistance = this.optUp.errDistance; // 不传,则取默认
this.scrollTo(this.getScrollTop() - errDistance, 0) // 往上回滚的距离
}
}
}
/* 显示空布局 */
MeScroll.prototype.showEmpty = function() {
this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(true)
}
/* 移除空布局 */
MeScroll.prototype.removeEmpty = function() {
this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(false)
}
/* 显示回到顶部的按钮 */
MeScroll.prototype.showTopBtn = function() {
if (!this.topBtnShow) {
this.topBtnShow = true;
this.optUp.toTop.onShow && this.optUp.toTop.onShow(true);
}
}
/* 隐藏回到顶部的按钮 */
MeScroll.prototype.hideTopBtn = function() {
if (this.topBtnShow) {
this.topBtnShow = false;
this.optUp.toTop.onShow && this.optUp.toTop.onShow(false);
}
}
/* 获取滚动条的位置 */
MeScroll.prototype.getScrollTop = function() {
return this.scrollTop || 0
}
/* 记录滚动条的位置 */
MeScroll.prototype.setScrollTop = function(y) {
this.scrollTop = y;
}
/* 滚动到指定位置 */
MeScroll.prototype.scrollTo = function(y, t) {
this.myScrollTo && this.myScrollTo(y, t) // scrollview需自定义回到顶部方法
}
/* 自定义scrollTo */
MeScroll.prototype.resetScrollTo = function(myScrollTo) {
this.myScrollTo = myScrollTo
}
/* 滚动条到底部的距离 */
MeScroll.prototype.getScrollBottom = function() {
return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
}
/*
star: 开始值
end: 结束值
callback(step,timer): 回调step值,计步器timer,可自行通过window.clearInterval(timer)结束计步器;
t: 计步时长,传0则直接回调end值;不传则默认300ms
rate: 周期;不传则默认30ms计步一次
* */
MeScroll.prototype.getStep = function(star, end, callback, t, rate) {
let diff = end - star; // 差值
if (t === 0 || diff === 0) {
callback && callback(end);
return;
}
t = t || 300; // 时长 300ms
rate = rate || 30; // 周期 30ms
let count = t / rate; // 次数
let step = diff / count; // 步长
let i = 0; // 计数
let timer = setInterval(function() {
if (i < count - 1) {
star += step;
callback && callback(star, timer);
i++;
} else {
callback && callback(end, timer); // 最后一次直接设置end,避免计算误差
clearInterval(timer);
}
}, rate);
}
/* 滚动容器的高度 */
MeScroll.prototype.getClientHeight = function(isReal) {
let h = this.clientHeight || 0
if (h === 0 && isReal !== true) { // 未获取到容器的高度,可临时取body的高度 (可能会有误差)
h = this.getBodyHeight()
}
return h
}
MeScroll.prototype.setClientHeight = function(h) {
this.clientHeight = h;
}
/* 滚动内容的高度 */
MeScroll.prototype.getScrollHeight = function() {
return this.scrollHeight || 0;
}
MeScroll.prototype.setScrollHeight = function(h) {
this.scrollHeight = h;
}
/* body的高度 */
MeScroll.prototype.getBodyHeight = function() {
return this.bodyHeight || 0;
}
MeScroll.prototype.setBodyHeight = function(h) {
this.bodyHeight = h;
}
/* 阻止浏览器默认滚动事件 */
MeScroll.prototype.preventDefault = function(e) {
// 小程序不支持e.preventDefault
// app的bounce只能通过配置pages.json的style.app-plus.bounce为"none"来禁止
// cancelable:是否可以被禁用; defaultPrevented:是否已经被禁用
if (e && e.cancelable && !e.defaultPrevented) e.preventDefault()
}
/* 是否允许下拉回弹(橡皮筋效果); true或null为允许; false禁止bounce */
MeScroll.prototype.setBounce = function(isBounce) {
// #ifdef H5
if (isBounce === false) {
this.optUp.isBounce = false; // 禁止
// 标记当前页使用了mescroll (需延时,确保page已切换)
setTimeout(function() {
let uniPageDom = document.getElementsByTagName('uni-page')[0];
uniPageDom && uniPageDom.setAttribute('use_mescroll', true)
}, 30);
// 避免重复添加事件
if (window.isSetBounce) return;
window.isSetBounce = true;
// 需禁止window的touchmove事件才能有效的阻止bounce
window.bounceTouchmove = function(e) {
if(!window.isPreventDefault) return; // 根据标记判断是否阻止
let el = e.target;
// 当前touch的元素及父元素是否要拦截touchmove事件
let isPrevent = true;
while (el !== document.body && el !== document) {
if (el.tagName === 'UNI-PAGE') { // 只扫描当前页
if (!el.getAttribute('use_mescroll')) {
isPrevent = false; // 如果当前页没有使用mescroll,则不阻止
}
break;
}
let cls = el.classList;
if (cls) {
if (cls.contains('mescroll-touch')) { // 采用scroll-view 此处不能过滤mescroll-uni,否则下拉仍然有回弹
isPrevent = false; // mescroll-touch无需拦截touchmove事件
break;
} else if (cls.contains('mescroll-touch-x') || cls.contains('mescroll-touch-y')) {
// 如果配置了水平或者垂直滑动
let curX = e.touches ? e.touches[0].pageX : e.clientX; // 当前第一个手指距离列表顶部的距离x
let curY = e.touches ? e.touches[0].pageY : e.clientY; // 当前第一个手指距离列表顶部的距离y
if (!this.preWinX) this.preWinX = curX; // 设置上次移动的距离x
if (!this.preWinY) this.preWinY = curY; // 设置上次移动的距离y
// 计算两点之间的角度
let x = Math.abs(this.preWinX - curX);
let y = Math.abs(this.preWinY - curY);
let z = Math.sqrt(x * x + y * y);
this.preWinX = curX; // 记录本次curX的值
this.preWinY = curY; // 记录本次curY的值
if (z !== 0) {
let angle = Math.asin(y / z) / Math.PI * 180; // 角度区间 [0,90]
if ((angle <= 45 && cls.contains('mescroll-touch-x')) || (angle > 45 && cls.contains('mescroll-touch-y'))) {
isPrevent = false; // 水平滑动或者垂直滑动,不拦截touchmove事件
break;
}
}
}
}
el = el.parentNode; // 继续检查其父元素
}
// 拦截touchmove事件:是否可以被禁用&&是否已经被禁用 (这里不使用me.preventDefault(e)的方法,因为某些情况下会报找不到方法的异常)
if (isPrevent && e.cancelable && !e.defaultPrevented && typeof e.preventDefault === "function") e.preventDefault();
}
window.addEventListener('touchmove', window.bounceTouchmove, {
passive: false
});
} else {
this.optUp.isBounce = true; // 允许
if (window.bounceTouchmove) {
window.removeEventListener('touchmove', window.bounceTouchmove);
window.bounceTouchmove = null;
window.isSetBounce = false;
}
}
// #endif
}

View File

@ -0,0 +1,364 @@
<template>
<view class="mescroll-uni-warp">
<scroll-view :id="viewId" class="mescroll-uni" :class="{'mescroll-uni-fixed':isFixed}" :style="{'height':scrollHeight,'padding-top':padTop,'padding-bottom':padBottom,'padding-bottom':padBottomConstant,'padding-bottom':padBottomEnv,'top':fixedTop,'bottom':fixedBottom,'bottom':fixedBottomConstant,'bottom':fixedBottomEnv}" :scroll-top="scrollTop" :scroll-into-view="scrollToViewId" :scroll-with-animation="scrollAnim" @scroll="scroll" @touchstart="touchstartEvent" @touchmove="touchmoveEvent" @touchend="touchendEvent" @touchcancel="touchendEvent" :scroll-y='isDownReset' :enable-back-to-top="true">
<view class="mescroll-uni-content" :style="{'transform': translateY, 'transition': transition}">
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background-color':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
<view class="downwarp-content">
<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform': downRotate}"></view>
<view class="downwarp-tip">{{downText}}</view>
</view>
</view>
<!-- 列表内容 -->
<slot></slot>
<!-- 空布局 -->
<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
<view v-if="mescroll.optUp.use && !isDownLoading" class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
<view v-show="upLoadType===1">
<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
</view>
<!-- 无数据 -->
<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
</view>
</view>
</scroll-view>
<!-- 回到顶部按钮 (fixed元素,需写在scroll-view外面,防止滚动的时候抖动)-->
<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
</view>
</template>
<script>
// mescroll-uni.js,
import MeScroll from './mescroll-uni.js';
//
import GlobalOption from './mescroll-uni-option.js';
//
import MescrollEmpty from './components/mescroll-empty.vue';
//
import MescrollTop from './components/mescroll-top.vue';
export default {
components: {
MescrollEmpty,
MescrollTop
},
data() {
return {
mescroll: {optDown:{},optUp:{}}, // mescroll
viewId: 'id_' + Math.random().toString(36).substr(2), // mescrollid(,)
downHight: 0, //:
downRate: 0, // (inOffset: rate<1; outOffset: rate>=1)
downLoadType: 4, // inOffset1 outOffset2 showLoading3 endDownScroll4
upLoadType: 0, // 0loading1loading2
isShowEmpty: false, //
isShowToTop: false, //
scrollTop: 0, //
scrollAnim: false, //
windowTop: 0, // 使
windowBottom: 0, // 使
windowHeight: 0, // 使
statusBarHeight: 0, //
isSafearea: false, //
scrollToViewId: '' // viewid
}
},
props: {
down: Object, //
up: Object, //
top: [String, Number], // (20, "20rpx", "20px", "20%", rpx, windowHeight)
topbar: Boolean, // top, false (使:,)
bottom: [String, Number], // (20, "20rpx", "20px", "20%", rpx, windowHeight)
safearea: Boolean, // bottom, false (iPhoneX使)
fixed: { // fixedmescroll, true
type: Boolean,
default () {
return true
}
},
height: [String, Number] // mescroll, ,使fixed. (20, "20rpx", "20px", "20%", rpx, windowHeight)
},
computed: {
// 使fixed (height,使)
isFixed(){
return !this.height && this.fixed
},
// mescroll
scrollHeight(){
if (this.isFixed) {
return "auto"
} else if(this.height){
return this.toPx(this.height) + 'px'
}else{
return "100%"
}
},
// (px)
numTop() {
return this.toPx(this.top) + (this.topbar ? this.statusBarHeight : 0)
},
fixedTop() {
return this.isFixed ? (this.numTop + this.windowTop) + 'px' : 0
},
padTop() {
return !this.isFixed ? this.numTop + 'px' : 0
},
// (px)
numBottom() {
return this.toPx(this.bottom)
},
fixedBottom() {
return this.isFixed ? (this.numBottom + this.windowBottom) + 'px' : 0
},
fixedBottomConstant(){
return this.isSafearea ? "calc("+this.fixedBottom+" + constant(safe-area-inset-bottom))" : this.fixedBottom
},
fixedBottomEnv(){
return this.isSafearea ? "calc("+this.fixedBottom+" + env(safe-area-inset-bottom))" : this.fixedBottom
},
padBottom() {
return !this.isFixed ? this.numBottom + 'px' : 0
},
padBottomConstant(){
return this.isSafearea ? "calc("+this.padBottom+" + constant(safe-area-inset-bottom))" : this.padBottom
},
padBottomEnv(){
return this.isSafearea ? "calc("+this.padBottom+" + env(safe-area-inset-bottom))" : this.padBottom
},
//
isDownReset(){
return this.downLoadType===3 || this.downLoadType===4
},
//
transition() {
return this.isDownReset ? 'transform 300ms' : '';
},
translateY() {
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform使fixed,fixedmescroll
},
//
isDownLoading(){
return this.downLoadType === 3
},
//
downRotate(){
return 'rotate(' + 360 * this.downRate + 'deg)'
},
//
downText(){
switch (this.downLoadType){
case 1: return this.mescroll.optDown.textInOffset;
case 2: return this.mescroll.optDown.textOutOffset;
case 3: return this.mescroll.optDown.textLoading;
case 4: return this.mescroll.optDown.textLoading;
default: return this.mescroll.optDown.textInOffset;
}
}
},
methods: {
//number,rpx,upx,px,% --> px
toPx(num){
if(typeof num === "string"){
if (num.indexOf('px') !== -1) {
if(num.indexOf('rpx') !== -1) { // "10rpx"
num = num.replace('rpx', '');
} else if(num.indexOf('upx') !== -1) { // "10upx"
num = num.replace('upx', '');
} else { // "10px"
return Number(num.replace('px', ''))
}
}else if (num.indexOf('%') !== -1){
// ,windowHeight,"10%"windowHeight10%
let rate = Number(num.replace("%","")) / 100
return this.windowHeight * rate
}
}
return num ? uni.upx2px(Number(num)) : 0
},
//,
scroll(e) {
this.mescroll.scroll(e.detail, () => {
this.$emit('scroll', this.mescroll) // this.mescroll.scrollTop; this.mescroll.isScrollUp
})
},
//touchstart,
touchstartEvent(e) {
this.mescroll.touchstartEvent(e);
},
//touchmove,
touchmoveEvent(e) {
this.mescroll.touchmoveEvent(e);
},
//touchend,
touchendEvent(e) {
this.mescroll.touchendEvent(e);
},
//
emptyClick() {
this.$emit('emptyclick', this.mescroll)
},
//
toTopClick() {
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); //
this.$emit('topclick', this.mescroll); //
},
// (使,)
setClientHeight() {
if (this.mescroll.getClientHeight(true) === 0 && !this.isExec) {
this.isExec = true; //
this.$nextTick(() => { // dom
let view = uni.createSelectorQuery().in(this).select('#' + this.viewId);
view.boundingClientRect(data => {
this.isExec = false;
if (data) {
this.mescroll.setClientHeight(data.height);
} else if (this.clientNum != 3) { // ,dom,,3
this.clientNum = this.clientNum == null ? 1 : this.clientNum + 1;
setTimeout(() => {
this.setClientHeight()
}, this.clientNum * 100)
}
}).exec();
})
}
}
},
// 使createdmescroll; mountedcssH5
created() {
let vm = this;
let diyOption = {
//
down: {
inOffset(mescroll) {
vm.downLoadType = 1; // offset (mescroll,)
},
outOffset(mescroll) {
vm.downLoadType = 2; // offset (mescroll,)
},
onMoving(mescroll, rate, downHight) {
// ,;
vm.downHight = downHight; // (mescroll,)
vm.downRate = rate; // (inOffset: rate<1; outOffset: rate>=1)
},
showLoading(mescroll, downHight) {
vm.downLoadType = 3; // (mescroll,)
vm.downHight = downHight; // (mescroll,)
},
endDownScroll(mescroll) {
vm.downLoadType = 4; // (mescroll,)
vm.downHight = 0; // (mescroll,)
},
//
callback: function(mescroll) {
vm.$emit('down', mescroll)
}
},
//
up: {
//
showLoading() {
vm.upLoadType = 1;
},
//
showNoMore() {
vm.upLoadType = 2;
},
//
hideUpScroll() {
vm.upLoadType = 0;
},
//
empty: {
onShow(isShow) { //
vm.isShowEmpty = isShow;
}
},
//
toTop: {
onShow(isShow) { //
vm.isShowToTop = isShow;
}
},
//
callback: function(mescroll) {
vm.$emit('up', mescroll);
// (mescroll)
vm.setClientHeight()
}
}
}
MeScroll.extend(diyOption, GlobalOption); //
let myOption = JSON.parse(JSON.stringify({
'down': vm.down,
'up': vm.up
})) // ,props
MeScroll.extend(myOption, diyOption); //
// MeScroll
vm.mescroll = new MeScroll(myOption);
vm.mescroll.viewId = vm.viewId; // id
// initmescroll
vm.$emit('init', vm.mescroll);
//
const sys = uni.getSystemInfoSync();
if(sys.windowTop) vm.windowTop = sys.windowTop;
if(sys.windowBottom) vm.windowBottom = sys.windowBottom;
if(sys.windowHeight) vm.windowHeight = sys.windowHeight;
if(sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
// 使downbottomOffset
vm.mescroll.setBodyHeight(sys.windowHeight);
// 使scrollview,scrollTo
vm.mescroll.resetScrollTo((y, t) => {
vm.scrollAnim = (t !== 0); // t0,使
if(typeof y === 'string'){ // ,使scroll-into-view
vm.scrollToViewId = y;
return;
}
let curY = vm.mescroll.getScrollTop()
if (t === 0 || t === 300) { // t使300,使
vm.scrollTop = curY;
vm.$nextTick(function() {
vm.scrollTop = y
})
} else {
vm.mescroll.getStep(curY, y, step => { // t
vm.scrollTop = step
}, t)
}
})
// up.toTop.safearea,vuesafearea
if(sys.platform == "ios"){
vm.isSafearea = vm.safearea;
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
vm.mescroll.optUp.toTop.safearea = vm.safearea;
}
}else{
vm.isSafearea = false
vm.mescroll.optUp.toTop.safearea = false
}
},
mounted() {
//
this.setClientHeight()
}
}
</script>
<style>
@import "./mescroll-uni.css";
@import "./components/mescroll-down.css";
@import './components/mescroll-up.css';
</style>

View File

@ -0,0 +1,23 @@
/**
* mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
* 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
* 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
*/
const MescrollCompMixin = {
// 因为子组件无onPageScroll和onReachBottom的页面生命周期需在页面传递进到子组件
onPageScroll(e) {
let item = this.$refs["mescrollItem"];
if(item && item.mescroll) item.mescroll.onPageScroll(e);
},
onReachBottom() {
let item = this.$refs["mescrollItem"];
if(item && item.mescroll) item.mescroll.onReachBottom();
},
// 当down的native: true时, 还需传递此方法进到子组件
onPullDownRefresh(){
let item = this.$refs["mescrollItem"];
if(item && item.mescroll) item.mescroll.onPullDownRefresh();
}
}
export default MescrollCompMixin;

View File

@ -0,0 +1,48 @@
/**
* mescroll-more-item的mixins, 仅在多个 mescroll-body 写在子组件时使用 (参考 mescroll-more 案例)
*/
const MescrollMoreItemMixin = {
props:{
i: Number, // 每个tab页的专属下标
index: { // 当前tab的下标
type: Number,
default(){
return 0
}
}
},
data() {
return {
downOption:{
auto:false // 不自动加载
},
upOption:{
auto:false // 不自动加载
},
isInit: false // 当前tab是否已初始化
}
},
watch:{
// 监听下标的变化
index(val){
if (this.i === val && !this.isInit) {
this.isInit = true; // 标记为true
this.mescroll && this.mescroll.triggerDownScroll();
}
}
},
methods: {
// mescroll组件初始化的回调,可获取到mescroll对象
mescrollInit(mescroll) {
this.mescroll = mescroll;
this.mescrollInitByRef && this.mescrollInitByRef(); // 兼容字节跳动小程序 (mescroll-mixins.js)
// 自动加载当前tab的数据
if(this.i === this.index){
this.isInit = true; // 标记为true
this.mescroll.triggerDownScroll();
}
},
}
}
export default MescrollMoreItemMixin;

View File

@ -0,0 +1,56 @@
/**
* mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
* 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
* 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
*/
const MescrollMoreMixin = {
data() {
return {
tabIndex: 0 // 当前tab下标
}
},
// 因为子组件无onPageScroll和onReachBottom的页面生命周期需在页面传递进到子组件
onPageScroll(e) {
let mescroll = this.getMescroll(this.tabIndex);
mescroll && mescroll.onPageScroll(e);
},
onReachBottom() {
let mescroll = this.getMescroll(this.tabIndex);
mescroll && mescroll.onReachBottom();
},
// 当down的native: true时, 还需传递此方法进到子组件
onPullDownRefresh(){
let mescroll = this.getMescroll(this.tabIndex);
mescroll && mescroll.onPullDownRefresh();
},
methods:{
// 根据下标获取对应子组件的mescroll
getMescroll(i){
if(!this.mescrollItems) this.mescrollItems = [];
if(!this.mescrollItems[i]) {
// v-for中的refs
let vForItem = this.$refs["mescrollItem"];
if(vForItem){
this.mescrollItems[i] = vForItem[i]
}else{
// 普通的refs,不可重复
this.mescrollItems[i] = this.$refs["mescrollItem"+i];
}
}
let item = this.mescrollItems[i]
return item ? item.mescroll : null
},
// 切换tab,恢复滚动条位置
tabChange(i){
let mescroll = this.getMescroll(i);
if(mescroll){
// 延时(比$nextTick靠谱一些),确保元素已渲染
setTimeout(()=>{
mescroll.scrollTo(mescroll.getScrollTop(),0)
},30)
}
}
}
}
export default MescrollMoreMixin;

View File

@ -0,0 +1,158 @@
<template>
<view class="cu-form-group" style="z-index:10">
<view class="flex align-center">
<view class="title">
<text class="text-red" v-if="required">*</text>
<text space="ensp">{{label}}</text>
</view>
<picker
@change="pickerChange"
:range="selections"
:value="valueIndex"
:disabled="disabled">
<input
:placeholder="placeholder"
name="input"
v-model="selected"
:disabled="true"
></input>
</picker>
</view>
</view>
</template>
<script>
export default {
name: "AppSecelt",
behaviors: ['uni://form-field'],
props:{
display:{
type:String,
default:'inline-block',
required:false
},
placeholder:{
type:String,
default:'请选择',
required:false
},
label:{
type:String,
default:'',
required:false
},
value:{
type:String,
required:false
},
border:{
type:Boolean,
default:false,
required:false
},
dict:{
type:Array,
default:()=>[],
required:true
},
name:{
type:String,
default:'',
required:false
},
required:{
type:Boolean,
default:false,
required:false
},
disabled:{
type:Boolean,
default:false,
required:false
},
space:{
type:Boolean,
default:false,
required:false
}
},
data(){
return {
show:false,
selected:'',
valueIndex:0,
selections:[]
}
},
watch:{
value:{
immediate:true,
handler(val){
if(!val){
this.selected = ''
this.valueIndex = 0
}else{
this.dict.map((item,index)=>{
if(item.value == val){
this.selected = item.text;
this.valueIndex = index
}
})
}
}
},
dict(){
this.initSelections();
}
},
created(){
this.initSelections();
},
methods:{
initSelections(){
let arr = [];
this.dict.map(item=>{
arr.push(item.text)
});
this.selections = arr
},
pickerChange(e){
console.log("appselect::pickerChange",e.detail.value)
let backString = '';
let obj=this.dict[e.detail.value];
this.selected=obj.text;
backString=obj.value;
console.log("backString",backString)
console.log("this.selected",this.selected)
this.$emit('input',backString);
// #ifndef MP-WEIXIN
this.$emit('change',backString);
// #endif
}
},
model: {
prop: 'value',
event:'change'
}
}
</script>
<style scoped>
.cu-form-group uni-picker::after {
font-family: cuIcon;
display: block;
content: "\e6a3";
position: absolute;
font-size: 14px;
color: #FFFFFF;
line-height: 42px;
width: 25px;
text-align: center;
top: 0;
bottom: 0;
right: -8px;
margin: auto;
}
</style>

View File

@ -0,0 +1,93 @@
<template>
<view class="cu-form-group" @click="timechange">
<view class="title"><text class="text-red" v-if="required">*</text>{{label}}</view>
<input
:placeholder="placeholder"
name="input"
v-model="selected"
disabled="true"
></input>
<w-picker
:visible.sync="visible"
ref="picker"
mode="date"
startYear="2020"
endYear="2100"
:value="value"
:fields="fields"
@confirm="onConfirm($event,'date')"
></w-picker>
</view>
</template>
<script>
export default {
name: "AppSecelt",
props:{
placeholder:{
type:String,
default:'请选择',
required:false
},
label:{
type:String,
default:'',
required:false
},
fields:{
type:String,
default:'second',
required:false
},
value:{
type:String,
required:false
} ,
required:{
type:Boolean,
default:false,
required:false
}
},
data(){
return {
visible:false,
selected:''
}
},
watch:{
value:{
immediate:true,
handler(val){
if(!val){
this.selected = ''
}else{
this.selected = val;
}
}
}
},
created(){
},
methods:{
timechange(){
this.$refs.picker.show()
},
onConfirm(e){
console.log("confirm",e)
let backString = e.value;
this.selected=e.value;
this.$emit('input',backString);
}
},
model: {
prop: 'value',
event: 'input'
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,106 @@
<template>
<view class="margin-top">
<view class="cu-bar bg-white ">
<view class="action">
{{label}}
</view>
<view class="action">
{{imgList.length}}/{{maxImg}}
</view>
</view>
<view class="cu-form-group">
<view class="grid col-4 grid-square flex-sub">
<view class="bg-img" v-for="(item,index) in imgList" :key="index" @tap="ViewImage" :data-url="imgList[index]">
<image :src="imgList[index]" mode="aspectFill"></image>
<view class="cu-tag bg-red" @tap.stop="DelImg" :data-index="index">
<text class='cuIcon-close'></text>
</view>
</view>
<view class="solids" @tap="ChooseImage" v-if="imgList.length<maxImg">
<text class='cuIcon-cameraadd'></text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'MyImageUpoad',
props: {
value: {type:String,default:''},
label:{type:String,default:'图片上传'},
maxImg: {
type: Number,
default: 3
},
},
mounted:function(){
if (this.value.split(',')!=''){
this.value.split(',').forEach(res=>{
this.imgList.push(baseurl+res)
})
}
},
data() {
return {
imgList: [],
pathlist:[],
}
},
methods: {
ChooseImage() {
uni.chooseImage({
count: this.maxImg, //9
sizeType: ['original', 'compressed'], //
sourceType: ['album','camera'], //
success: (res) => {
uni.uploadFile({
url: `${baseurl}systemController/filedeal.do?isup=1`,
filePath: res.tempFilePaths[0],
name: 'file',
success: (uploadFileRes) => {
let path = JSON.parse(uploadFileRes.data).obj
this.pathlist.push(path);
this.$emit('input',this.pathlist.join(','))
if (this.imgList.length != 0) {
this.imgList = this.imgList.concat(res.tempFilePaths)
} else {
this.imgList = res.tempFilePaths
}
}
})
}
});
},
ViewImage(e) {
uni.previewImage({
urls: this.imgList,
current: e.currentTarget.dataset.url
});
},
DelImg(e) {
uni.showModal({
title: '提示',
content: '确认要删除吗',
cancelText: '取消',
confirmText: '确认',
success: res => {
if (res.confirm) {
this.pathlist.splice(e.currentTarget.dataset.index,1)
this.imgList.splice(e.currentTarget.dataset.index, 1)
this.$emit('input',this.pathlist.join(','))
}
}
})
},
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,326 @@
<template>
<view>
<map
style="width: 100%; height:250px;"
:latitude="latitude"
:longitude="longitude"
:markers="marker"
:scale="scale"
:circles="circles"
>
<!-- :circles="circles" -->
</map>
</view>
</template>
<script>
import { geoDistance } from '@/common/util/util.js'
import amap from "@/common/js-sdk/js-amap/amap-wx.js";
// #ifdef H5
import AMap from "@/common/js-sdk/js-amap/amap-h5.js";
// #endif
export default {
props:{
compLatitude:{
type:Number,
default:40.009390,
required:false
},
compLongitude:{
type:Number,
default:116.374322,
required:false
}
},
data() {
return {
amapPlugin:null,
wxMapKey:"53324ee357405c4a65f35a1aa05ffaf2",
id:0,
title: 'map',
distance:0,
address:"",
  latitude: this.compLatitude, //
longitude: this.compLongitude, //
scale:16,//
tipText:'打卡范围',
bgColor:'#00c16f',
marker: [],
  circles:[{//
  latitude: this.compLatitude,
  longitude: this.compLongitude,
  radius:80,//
fillColor:"#ffffffAA",//
  color:"#55aaffAA",//
   strokeWidth:1//
}],
resAmap:null
}
},
created() {
// #ifdef MP-WEIXIN || APP-PLUS
this.amapPlugin = new amap.AMapWX({
key: this.wxMapKey
});
// #endif
// #ifdef H5
this.initAMap()
// #endif
},
mounted() {
// #ifdef MP-WEIXIN
this.getAuthorizeInfo();
// #endif
// #ifdef APP-PLUS
this.getLocationInfoWx();
// #endif
// #ifdef H5
//this.getLocationInfo()
// #endif
},
computed:{
inCircle(){
return this.address && this.distance <= 80
}
},
methods: {
allowed(){
return this.inCircle
},
getMyAddress(){
return this.address
},
refreshLocation(){
// #ifdef MP-WEIXIN
this.getAuthorizeInfo();
// #endif
// #ifdef APP-PLUS
this.getLocationInfoWx();
// #endif
// #ifdef H5
this.initAMap()
// #endif
},
getAuthorizeInfo(){
//1. uniapp
var _this=this;
uni.authorize({
scope: "scope.userLocation",
success() { //1.1
_this.getLocationInfoWx();
},
fail(){ //1.2
console.log("你拒绝了授权,无法获得周边信息")
_this.openConfirm();
}
})
},
getLocationInfoWx(){
var that=this;
this.amapPlugin.getRegeo({
type: 'gcj02', //map 使 type gcj02
success: function(res) {
console.log("success",res);
that.latitude = res[0].latitude;
that.longitude = res[0].longitude;
that.address = res[0].name + res[0].desc;
that.distance=geoDistance(that.longitude, that.latitude,that.compLongitude,that.compLatitude)
console.log("that.distance",that.distance);
let tipText=(that.distance>80?"未在":"已在")+"打卡范围内";
let bgColor=that.distance>80?"#ff0000":"#00c16f";
let marker={
id:0,
  latitude:that.latitude,//
  longitude:that.longitude,//
iconPath: '/static/location.png',
width:35,
height:35,
// #ifdef MP-WEIXIN
label:{//
   content:tipText,//
    color:'#ffffff',//
  fontSize:14,//
borderWidth:2,//
borderColor:bgColor,//
bgColor:bgColor,//
  borderRadius:2,//
  padding:5,//
textAlign:'center',//
x:0,//label marker
y:0,//label marker
},
// #endif
// #ifdef APP-PLUS
callout:{//
  content:tipText,//
  color:'#ffffff',//
  fontSize:14,//
  //borderRadius:2,//
   bgColor:bgColor,//
  display:'ALWAYS',//
textAlign:'center'
},
// #endif
}
that.marker=[marker];
},
fail: (res) => {
console.log(JSON.stringify(res));
}
});
},
getLocationInfo() {
// var _this=this;
// uni.showLoading({
// title: '',
// mask:true
// });
// uni.getLocation({
// //type: 'wgs84',
// type:'gcj02',
// success: function (res) {
// console.log('' + res.longitude);
// console.log('' + res.latitude);
// _this.distance=geoDistance(res.longitude, res.latitude,_this.compLongitude,_this.compLatitude)
// let tipText=(_this.distance>80?"":"")+"";
// let bgColor=_this.distance>80?"#ff0000":"#00c16f";
// _this.longitude=res.longitude
// _this.latitude=res.latitude
// let marker={
//   latitude: res.latitude,//
//   longitude:res.longitude,//
//   callout:{//
//   content:tipText,//
//   color:'#ffffff',//
//   fontSize:14,//
//   borderRadius:2,//
//    bgColor:bgColor,//
//   display:'ALWAYS'//
// }
// }
// _this.marker=[marker];
// },
// fail: function (res){
// console.log('getLocation==> fail' + res);
// console.log(res);
// }
// });
// uni.hideLoading();
},
//
openConfirm(){
uni.showModal({
title: '请求授权当前位置',
content: '需要获取您的地理位置,请确认授权',
success: (res)=> {
if (res.confirm) {
uni.openSetting();//
} else if (res.cancel) {
uni.showToast({
title: '你拒绝了授权,无法获得位置信息',
icon: 'none',
duration: 1000
})
}
}
});
},
// ()
/* async getAddress (points) {
try {
this.resAmap = await AMap();
this.$nextTick(function() {
this.resAmap.plugin('AMap.Geocoder', () => {
var geocoder = new this.resAmap.Geocoder({
radius: 1000,
});
geocoder.getAddress(points, (status, result) => {
if (status === 'complete' && result.regeocode) {
this.address = result.regeocode.formattedAddress
}
})
});
})
} catch (e) {
console.log(e)
}
}, */
// #ifdef H5
async initAMap() {
try {
uni.showLoading({
title: '定位中...',
mask:true
});
this.resAmap = await AMap();
this.$nextTick(function() {
this.resAmap.plugin('AMap.Geolocation', () => {
var geolocation = new this.resAmap.Geolocation({
enableHighAccuracy: true, //使:true
timeout: 10000, //105s
buttonPosition: 'RB', //
// buttonOffset: new AMap.Pixel(10, 20),//Pixel(10, 20)
zoomToAccuracy: true, //
});
geolocation.getCurrentPosition(function(status, result) {
if (status == 'complete') {
onComplete(result)
} else {
onError(result)
}
});
});
//
var _this = this;
function onComplete(data) {
console.log("H5高德定位",data)
console.log('当前位置的经度:' + data.position.lat);
console.log('当前位置的纬度:' + data.position.lng);
_this.distance=geoDistance(data.position.lng, data.position.lat,_this.compLongitude,_this.compLatitude)
let tipText=(_this.distance>80?"未在":"已在")+"打卡范围内";
let bgColor=_this.distance>80?"#ff0000":"#00c16f";
_this.longitude=data.position.lng
_this.latitude=data.position.lat
_this.address=data.formattedAddress
let marker={
  latitude: _this.latitude,//
  longitude:_this.longitude,//
  callout:{//
  content:tipText,//
  color:'#ffffff',//
  fontSize:14,//
  borderRadius:2,//
   bgColor:bgColor,//
  display:'ALWAYS'//
}
}
_this.marker=[marker];
uni.hideLoading();
_this.$tip.success("定位成功")
}
function onError(data) {
console.log(data) //
}
})
} catch (e) {
console.log(e)
_this.$tip.alert("定位失败")
}
},
// #endif
}
}
</script>
<style>
</style>

View File

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

View File

@ -0,0 +1,46 @@
<template>
<view>
<scroll-view :scroll-y="modalName==null" class="page" :class="modalName!=null?'show':''">
<cu-custom bgColor="bg-gradual-pink" :isBack="true">
<block slot="backText">{{back}}</block>
<block slot="content">{{title}}</block>
</cu-custom>
<slot></slot>
</scroll-view>
</view>
</template>
<script>
export default {
name: 'MyPage',
props: {
title: {
type: String,
default: '标题'
},
back: {
type: String,
default: '返回'
},
modalName: {
type: String,
default: null
},
},
watch: {
},
computed: {
},
data() {
return {
}
},
methods: {}
}
</script>
<style>
</style>

View File

@ -0,0 +1,85 @@
<template>
<view class="cu-form-group">
<view class="title">{{label}}</view>
<picker @change="PickerChange" :value="index" :range-key="rangeKey" :range="dictOptions">
<view class="picker">
{{index>-1?dictOptions[index][rangeKey]:'请选择'}}
</view>
</picker>
</view>
</template>
<script>
export default {
name: 'MySelect',
props: {
dictCode: String,
value: String,
label:String,
rangeKey:{type:String,default:'label'},
valueKey:{type:String,default:'value'},
searchUrl:String,
},
watch: {
dictCode: {
immediate: true,
handler() {
this.initDictData()
},
},
},
computed: {
},
data() {
return {
dictOptions: [],
index: -1,
}
},
methods: {
initDictData() {
//Code,
if (this.searchUrl){
this.$http.get(this.searchUrl,{"code":this.dictCode}).then(res=>{
if(res.data.success){
this.dictOptions = res;
this.getIndex()
}
})
}else{
let code = this.dictCode;
this.$http.get(`/sys/dict/getDictItems/${code}`).then(res=>{
if(res.data.success){
this.dictOptions = res.data.result;
this.getIndex()
}
})
}
},
PickerChange(e) {
this.index=e.detail.value
if(this.index==-1){
this.index=0
this.$emit('input',this.dictOptions[0][this.valueKey])
}else{
this.$emit('input', this.dictOptions[this.index][this.valueKey]);
}
},
getIndex() {
for (var i = 0; i < this.dictOptions.length; i++) {
if (this.dictOptions[i].value == this.value) {
this.index = i
return
}
}
this.index=-1
},
}
}
</script>
<style>
</style>

View File

@ -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 2033hexAttribution 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 (02930)
* @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 (-12930)
* @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 (-128293031)
* @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

View File

@ -0,0 +1,179 @@
<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,
}">今天</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?'今天': (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>
export default {
props: {
weeks: {
type: Object,
default () {
return {}
}
},
calendar: {
type: Object,
default: () => {
return {}
}
},
selected: {
type: Array,
default: () => {
return []
}
},
lunar: {
type: Boolean,
default: false
}
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks)
}
}
}
</script>
<style lang="scss" scoped>
.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__weeks-box-circle{
position: absolute;
top: 37px;
right: 23px;
width: 3px;
height: 3px;
border-radius: 3px;
//background-color: $uni-color-primary;
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>

View File

@ -0,0 +1,512 @@
<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">取消</text>
</view>
<view class="uni-calendar__header-btn-box" @click="confirm">
<text class="uni-calendar__header-text uni-calendar--fixed-width">确定</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">回到今天</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"></text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text"></text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text"></text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text"></text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text"></text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text"></text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text"></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 :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'
/**
* 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
},
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
}
},
watch: {
date(newVal) {
this.cale.setDate(newVal)
this.init(this.cale.selectDate.fullDate)
},
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.cale.selectDate.fullDate)
// this.setDay
},
methods: {
// 穿
clean() {},
bindDateChange(e) {
const value = e.detail.value + '-1'
console.log(this.cale.getDate(value));
this.cale.setDate(value)
this.init(value)
},
/**
* 初始化日期显示
* @param {Object} date
*/
init(date) {
this.weeks = this.cale.weeks
this.nowDate = this.calendar = this.cale.getInfo(date)
console.log("this.weeks",this.weeks)
},
/**
* 打开日历弹窗
*/
open() {
//
if (this.clearDate && !this.insert) {
this.cale.cleanMultipleStatus()
this.cale.setDate(this.date)
this.init(this.cale.selectDate.fullDate)
}
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) {
console.log(weeks)
if (weeks.disable){
//this.next()
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()
this.$emit("monthChange",preDate)
},
/**
* 下个月
*/
next() {
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
this.setDate(nextDate)
this.monthSwitch()
this.$emit("monthChange",nextDate)
},
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.cale.getInfo(date)
}
}
}
</script>
<style lang="scss" scoped>
.uni-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: 0;
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-gray;
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-xl;
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>

View File

@ -0,0 +1,352 @@
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)
}
if (this.endDate) {
let dateCompAfter = this.dateCompare(fullDate, this.endDate)
disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
}
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

View File

@ -0,0 +1,54 @@
<template>
<view class="uni-collapse">
<slot />
</view>
</template>
<script>
export default {
name: 'UniCollapse',
props: {
accordion: {
//
type: [Boolean, String],
default: false
}
},
data() {
return {}
},
provide() {
return {
collapse: this
}
},
created() {
this.childrens = []
},
methods: {
onChange() {
let activeItem = []
this.childrens.forEach((vm, index) => {
if (vm.isOpen) {
activeItem.push(vm.nameSync)
}
})
this.$emit('change', activeItem)
}
}
}
</script>
<style lang="scss" scoped>
@import '@/uni.scss';
.uni-collapse {
/* #ifndef APP-NVUE */
width: 100%;
display: flex;
/* #endif */
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
flex-direction: column;
background-color: $uni-bg-color;
}
</style>

View File

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

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,742 @@
<template>
<view class="w-picker-view">
<picker-view v-if="fields=='year'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='month'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='day'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='hour'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='minute'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='second'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.seconds" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{
years:[],
months:[],
days:[],
hours:[],
minutes:[],
seconds:[]
},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
startYear:{
type:[String,Number],
default:""
},
endYear:{
type:[String,Number],
default:""
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
disabledAfter:{//
type:Boolean,
default:false
},
fields:{
type:String,
default:"day"
}
},
watch:{
fields(val){
this.initData();
},
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg,example
switch(this.fields){
case "year":
strReg=/^\d{4}$/;
example="2019";
break;
case "month":
strReg=/^\d{4}-\d{2}$/;
example="2019-02";
break;
case "day":
strReg=/^\d{4}-\d{2}-\d{2}$/;
example="2019-02-01";
break;
case "hour":
strReg=/^\d{4}-\d{2}-\d{2} \d{2}(:\d{2}){1,2}?$/;
example="2019-02-01 18:00:00或2019-02-01 18";
break;
case "minute":
strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2}){0,1}?$/;
example="2019-02-01 18:06:00或2019-02-01 18:06";
break;
case "second":
strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
example="2019-02-01 18:06:01";
break;
}
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day,hour,minute){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
let months=[],days=[],hours=[],minutes=[],seconds=[];
let disabledAfter=this.disabledAfter;
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
let totalDays=new Date(year,month,0).getDate();//;
let daysLen=disabledAfter?((year*1<curYear||month*1<curMonth)?totalDays:curDay):totalDays;
let hoursLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)?24:curHour+1):24;
let minutesLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay||hour*1<curHour)?60:curMinute+1):60;
let secondsLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay||hour*1<curHour||minute*1<curMinute)?60:curSecond+1):60;
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
};
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
for(let hour=0;hour<hoursLen;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<minutesLen;minute++){
minutes.push(this.formatNum(minute));
}
for(let second=0;second<secondsLen;second++){
seconds.push(this.formatNum(second));
}
return{
months,
days,
hours,
minutes,
seconds
}
},
isLeapYear (Year) {
if (((Year % 4)==0) && ((Year % 100)!=0) || ((Year % 400)==0)) {
return true;
} else {
return false;
}
},
getData(dVal){
//
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let fields=this.fields;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonthdays=curDate.curMonthdays;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
let defaultDate=this.getDefaultDate();
let startYear=this.getStartDate().getFullYear();
let endYear=this.getEndDate().getFullYear();
//year,month,day,hour;,
let years=[],months=[],days=[],hours=[],minutes=[],seconds=[];
let year=dVal[0]*1;
let month=dVal[1]*1;
let day=dVal[2]*1;
let hour=dVal[3]*1;
let minute=dVal[4]*1;
let monthsLen=disabledAfter?(year<curYear?12:curDate.curMonth):12;
let daysLen=disabledAfter?((year<curYear||month<curMonth)?defaultDate.defaultDays:curDay):(curFlag?curMonthdays:defaultDate.defaultDays);
let hoursLen=disabledAfter?((year<curYear||month<curMonth||day<curDay)?24:curHour+1):24;
let minutesLen=disabledAfter?((year<curYear||month<curMonth||day<curDay||hour<curHour)?60:curMinute+1):60;
let secondsLen=disabledAfter?((year<curYear||month<curMonth||day<curDay||hour<curHour||minute<curMinute)?60:curSecond+1):60;
for(let year=startYear;year<=(disabledAfter?curYear:endYear);year++){
years.push(year.toString())
}
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
}
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
for(let hour=0;hour<hoursLen;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<minutesLen;minute++){
minutes.push(this.formatNum(minute));
}
// for(let second=0;second<(disabledAfter?curDate.curSecond+1:60);second++){
// seconds.push(this.formatNum(second));
// }
for(let second=0;second<60;second++){
seconds.push(this.formatNum(second));
}
return {
years,
months,
days,
hours,
minutes,
seconds
}
},
getCurrenDate(){
let curDate=new Date();
let curYear=curDate.getFullYear();
let curMonth=curDate.getMonth()+1;
let curMonthdays=new Date(curYear,curMonth,0).getDate();
let curDay=curDate.getDate();
let curHour=curDate.getHours();
let curMinute=curDate.getMinutes();
let curSecond=curDate.getSeconds();
return{
curDate,
curYear,
curMonth,
curMonthdays,
curDay,
curHour,
curMinute,
curSecond
}
},
getDefaultDate(){
let value=this.value;
let reg=/-/g;
let defaultDate=value?new Date(value.replace(reg,"/")):new Date();
let defaultYear=defaultDate.getFullYear();
let defaultMonth=defaultDate.getMonth()+1;
let defaultDay=defaultDate.getDate();
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
return{
defaultDate,
defaultYear,
defaultMonth,
defaultDay,
defaultDays
}
},
getStartDate(){
let start=this.startYear;
let startDate="";
let reg=/-/g;
if(start){
startDate=new Date(start+"/01/01");
}else{
startDate=new Date("1970/01/01");
}
return startDate;
},
getEndDate(){
let end=this.endYear;
let reg=/-/g;
let endDate="";
if(end){
endDate=new Date(end+"/12/01");
}else{
endDate=new Date();
}
return endDate;
},
getDval(){
let value=this.value;
let fields=this.fields;
let dVal=null;
let aDate=new Date();
let year=this.formatNum(aDate.getFullYear());
let month=this.formatNum(aDate.getMonth()+1);
let day=this.formatNum(aDate.getDate());
let hour=this.formatNum(aDate.getHours());
let minute=this.formatNum(aDate.getMinutes());
let second=this.formatNum(aDate.getSeconds());
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[year,month,day,hour,minute,second]
}else{
switch(this.fields){
case "year":
dVal=value?[value]:[];
break;
case "month":
dVal=value?value.split("-"):[];
break;
case "day":
dVal=value?value.split("-"):[];
break;
case "hour":
dVal=[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")];
break;
case "minute":
dVal=value?[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")]:[];
break;
case "second":
dVal=[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")];
break;
}
}
}else{
dVal=[year,month,day,hour,minute,second]
}
return dVal;
},
initData(){
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
let years=[],months=[],days=[],hours=[],minutes=[],seconds=[];
let dVal=[],pickVal=[];
let value=this.value;
let reg=/-/g;
let range={};
let result="",full="",year,month,day,hour,minute,second,obj={};
let defaultDate=this.getDefaultDate();
let defaultYear=defaultDate.defaultYear;
let defaultMonth=defaultDate.defaultMonth;
let defaultDay=defaultDate.defaultDay;
let defaultDays=defaultDate.defaultDays;
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curMonthdays=curDate.curMonthdays;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
let dateData=[];
dVal=this.getDval();
startDate=this.getStartDate();
endDate=this.getEndDate();
startYear=startDate.getFullYear();
startMonth=startDate.getMonth();
startDay=startDate.getDate();
endYear=endDate.getFullYear();
endMonth=endDate.getMonth();
endDay=endDate.getDate();
dateData=this.getData(dVal);
years=dateData.years;
months=dateData.months;
days=dateData.days;
hours=dateData.hours;
minutes=dateData.minutes;
seconds=dateData.seconds;
switch(this.fields){
case "year":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0
]:(curFlag?[
years.indexOf(curYear+'')
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0
]);
range={years};
year=dVal[0]?dVal[0]:years[0];
result=full=`${year}`;
obj={
year
}
break;
case "month":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth))
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0
]);
range={years,months};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
result=full=`${year+'-'+month}`;
obj={
year,
month
}
break;
case "day":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0
]);
range={years,months,days};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
result=full=`${year+'-'+month+'-'+day}`;
obj={
year,
month,
day
}
break;
case "hour":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
hours.indexOf(this.formatNum(curHour)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0
]);
range={years,months,days,hours};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
hour=dVal[3]?dVal[3]:hours[0];
result=`${year+'-'+month+'-'+day+' '+hour}`;
full=`${year+'-'+month+'-'+day+' '+hour+':00:00'}`;
obj={
year,
month,
day,
hour
}
break;
case "minute":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
hours.indexOf(this.formatNum(curHour)),
minutes.indexOf(this.formatNum(curMinute)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0
]);
range={years,months,days,hours,minutes};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
hour=dVal[3]?dVal[3]:hours[0];
minute=dVal[4]?dVal[4]:minutes[0];
full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':00'}`;
result=`${year+'-'+month+'-'+day+' '+hour+':'+minute}`;
obj={
year,
month,
day,
hour,
minute
}
break;
case "second":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0,
dVal[5]&&seconds.indexOf(dVal[5])!=-1?seconds.indexOf(dVal[5]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
hours.indexOf(this.formatNum(curHour)),
minutes.indexOf(this.formatNum(curMinute)),
seconds.indexOf(this.formatNum(curSecond)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0,
dVal[5]&&seconds.indexOf(dVal[5])!=-1?seconds.indexOf(dVal[5]):0
]);
range={years,months,days,hours,minutes,seconds};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
hour=dVal[3]?dVal[3]:hours[0];
minute=dVal[4]?dVal[4]:minutes[0];
second=dVal[5]?dVal[5]:seconds[0];
result=full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second}`;
obj={
year,
month,
day,
hour,
minute,
second
}
break;
default:
range={years,months,days};
break;
}
this.range=range;
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
});
this.$nextTick(()=>{
this.pickVal=pickVal;
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let year="",month="",day="",hour="",minute="",second="";
let result="",full="",obj={};
let months=null,days=null,hours=null,minutes=null,seconds=null;
let disabledAfter=this.disabledAfter;
let leapYear=false,resetData={};
year=(arr[0]||arr[0]==0)?data.years[arr[0]]||data.years[data.years.length-1]:"";
month=(arr[1]||arr[1]==0)?data.months[arr[1]]||data.months[data.months.length-1]:"";
day=(arr[2]||arr[2]==0)?data.days[arr[2]]||data.days[data.days.length-1]:"";
hour=(arr[3]||arr[3]==0)?data.hours[arr[3]]||data.hours[data.hours.length-1]:"";
minute=(arr[4]||arr[4]==0)?data.minutes[arr[4]]||data.minutes[data.minutes.length-1]:"";
second=(arr[5]||arr[5]==0)?data.seconds[arr[5]]||data.seconds[data.seconds.length-1]:"";
resetData=this.resetData(year,month,day,hour,minute);//;
leapYear=this.isLeapYear(year);//;
switch(this.fields){
case "year":
result=full=`${year}`;
obj={
year
};
break;
case "month":
result=full=`${year+'-'+month}`;
if(this.disabledAfter)months=resetData.months;
if(months)this.range.months=months;
obj={
year,
month
}
break;
case "day":
result=full=`${year+'-'+month+'-'+day}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
obj={
year,
month,
day
}
break;
case "hour":
result=`${year+'-'+month+'-'+day+' '+hour}`;
full=`${year+'-'+month+'-'+day+' '+hour+':00:00'}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
hours=resetData.hours;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(hours)this.range.hours=hours;
obj={
year,
month,
day,
hour
}
break;
case "minute":
full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':00'}`;
result=`${year+'-'+month+'-'+day+' '+hour+':'+minute}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
hours=resetData.hours;
minutes=resetData.minutes;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(hours)this.range.hours=hours;
if(minutes)this.range.minutes=minutes;
obj={
year,
month,
day,
hour,
minute
};
break;
case "second":
result=full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
hours=resetData.hours;
minutes=resetData.minutes;
//seconds=resetData.seconds;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(hours)this.range.hours=hours;
if(minutes)this.range.minutes=minutes;
//if(seconds)this.range.seconds=seconds;
obj={
year,
month,
day,
hour,
minute,
second
}
break;
}
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,346 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.sections" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
startYear:{
type:String,
default:""
},
endYear:{
type:String,
default:""
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
disabledAfter:{//
type:Boolean,
default:false
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{4}-\d{2}-\d{2} [\u4e00-\u9fa5]{2}$/,example;
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let months=[],days=[],sections=[];
let disabledAfter=this.disabledAfter;
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
let totalDays=new Date(year,month,0).getDate();//;
let daysLen=disabledAfter?((year*1<curYear||month*1<curMonth)?totalDays:curDay):totalDays;
let sectionFlag=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)==true?false:true):(curHour>12==true?true:false);
sections=["上午","下午"];
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
};
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
if(sectionFlag){
sections=["上午"];
}
return{
months,
days,
sections
}
},
getData(dVal){
//
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonthdays=curDate.curMonthdays;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let defaultDate=this.getDefaultDate();
let startYear=this.getStartDate().getFullYear();
let endYear=this.getEndDate().getFullYear();
let years=[],months=[],days=[],sections=[];
let year=dVal[0]*1;
let month=dVal[1]*1;
let day=dVal[2]*1;
let monthsLen=disabledAfter?(year<curYear?12:curDate.curMonth):12;
let daysLen=disabledAfter?((year<curYear||month<curMonth)?defaultDate.defaultDays:curDay):(curFlag?curMonthdays:defaultDate.defaultDays);
let sectionFlag=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)==true?false:true):(curHour>12==true?true:false);
for(let year=startYear;year<=(disabledAfter?curYear:endYear);year++){
years.push(year.toString())
}
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
}
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
if(sectionFlag){
sections=["下午"];
}else{
sections=["上午","下午"];
}
sections=["上午","下午"];
return {
years,
months,
days,
sections
}
},
getCurrenDate(){
let curDate=new Date();
let curYear=curDate.getFullYear();
let curMonth=curDate.getMonth()+1;
let curMonthdays=new Date(curYear,curMonth,0).getDate();
let curDay=curDate.getDate();
let curHour=curDate.getHours();
let curSection="上午";
if(curHour>=12){
curSection="下午";
}
return{
curDate,
curYear,
curMonth,
curMonthdays,
curDay,
curHour,
curSection
}
},
getDefaultDate(){
let value=this.value;
let reg=/-/g;
let defaultDate=value?new Date(value.split(" ")[0].replace(reg,"/")):new Date();
let defaultYear=defaultDate.getFullYear();
let defaultMonth=defaultDate.getMonth()+1;
let defaultDay=defaultDate.getDate();
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
return{
defaultDate,
defaultYear,
defaultMonth,
defaultDay,
defaultDays
}
},
getStartDate(){
let start=this.startYear;
let startDate="";
let reg=/-/g;
if(start){
startDate=new Date(start+"/01/01");
}else{
startDate=new Date("1970/01/01");
}
return startDate;
},
getEndDate(){
let end=this.endYear;
let reg=/-/g;
let endDate="";
if(end){
endDate=new Date(end+"/12/31");
}else{
endDate=new Date();
}
return endDate;
},
getDval(){
let value=this.value;
let dVal=null;
let aDate=new Date();
let year=this.formatNum(aDate.getFullYear());
let month=this.formatNum(aDate.getMonth()+1);
let day=this.formatNum(aDate.getDate());
let hour=aDate.getHours();
let section="上午";
if(hour>=12)section="下午";
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[year,month,day,section]
}else{
let v=value.split(" ");
dVal=[...v[0].split("-"),v[1]];
}
}else{
dVal=[year,month,day,section]
}
return dVal;
},
initData(){
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
let years=[],months=[],days=[],sections=[];
let dVal=[],pickVal=[];
let value=this.value;
let reg=/-/g;
let range={};
let result="",full="",year,month,day,section,obj={};
let defaultDate=this.getDefaultDate();
let defaultYear=defaultDate.defaultYear;
let defaultMonth=defaultDate.defaultMonth;
let defaultDay=defaultDate.defaultDay;
let defaultDays=defaultDate.defaultDays;
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curMonthdays=curDate.curMonthdays;
let curDay=curDate.curDay;
let curSection=curDate.curSection;
let dateData=[];
dVal=this.getDval();
startDate=this.getStartDate();
endDate=this.getEndDate();
startYear=startDate.getFullYear();
startMonth=startDate.getMonth();
startDay=startDate.getDate();
endYear=endDate.getFullYear();
endMonth=endDate.getMonth();
endDay=endDate.getDate();
dateData=this.getData(dVal);
years=dateData.years;
months=dateData.months;
days=dateData.days;
sections=dateData.sections;
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&sections.indexOf(dVal[3])!=-1?sections.indexOf(dVal[3]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
sections.indexOf(curSection),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&sections.indexOf(dVal[3])!=-1?sections.indexOf(dVal[3]):0
]);
range={years,months,days,sections};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
section=dVal[3]?dVal[3]:sections[0];
result=full=`${year+'-'+month+'-'+day+' '+section}`;
obj={
year,
month,
day,
section
}
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:full,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let year="",month="",day="",section="";
let result="",full="",obj={};
let months=null,days=null,sections=null;
let disabledAfter=this.disabledAfter;
year=(arr[0]||arr[0]==0)?data.years[arr[0]]||data.years[data.years.length-1]:"";
month=(arr[1]||arr[1]==0)?data.months[arr[1]]||data.months[data.months.length-1]:"";
day=(arr[2]||arr[2]==0)?data.days[arr[2]]||data.days[data.days.length-1]:"";
section=(arr[3]||arr[3]==0)?data.sections[arr[3]]||data.sections[data.sections.length-1]:"";
result=full=`${year+'-'+month+'-'+day+' '+section}`;
let resetData=this.resetData(year,month,day);
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
sections=resetData.sections;
}else{
if(year%4==0||(month!=this.checkObj.month)){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(sections)this.range.sections=sections;
obj={
year,
month,
day,
section
}
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,274 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column v-for="(group,gIndex) in range" :key="gIndex">
<view class="w-picker-item" v-for="(item,index) in group" :key="index">{{item[nodeKey]}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:[],
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[Array,String],
default:""
},
defaultType:{
type:String,
default:"label"
},
options:{
type:Array,
default(){
return []
}
},
defaultProps:{
type:Object,
default(){
return{
lable:"label",
value:"value",
children:"children"
}
}
},
level:{
//
type:[Number,String],
default:2
}
},
computed:{
nodeKey(){
return this.defaultProps.label;
},
nodeVal(){
return this.defaultProps.value;
},
nodeChild(){
return this.defaultProps.children;
}
},
watch:{
value(val){
if(this.options.length!=0){
this.initData();
}
},
options(val){
this.initData();
}
},
created() {
if(this.options.length!=0){
this.initData();
}
},
methods:{
getData(){
//
let options=this.options;
let col1={},col2={},col3={},col4={};
let arr1=options,arr2=[],arr3=[],arr4=[];
let col1Index=0,col2Index=0,col3Index=0,col4Index=0;
let a1="",a2="",a3="",a4="";
let dVal=[],obj={};
let value=this.value;
let data=[];
a1=value[0];
a2=value[1];
if(this.level>2){
a3=value[2];
}
if(this.level>3){
a4=value[3];
};
/*第1列*/
col1Index=arr1.findIndex((v)=>{
return v[this.defaultType]==a1
});
col1Index=value?(col1Index!=-1?col1Index:0):0;
col1=arr1[col1Index];
/*第2列*/
arr2=arr1[col1Index][this.nodeChild];
col2Index=arr2.findIndex((v)=>{
return v[this.defaultType]==a2
});
col2Index=value?(col2Index!=-1?col2Index:0):0;
col2=arr2[col2Index];
/*第3列*/
if(this.level>2){
arr3=arr2[col2Index][this.nodeChild];
col3Index=arr3.findIndex((v)=>{
return v[this.defaultType]==a3;
});
col3Index=value?(col3Index!=-1?col3Index:0):0;
col3=arr3[col3Index];
};
/*第4列*/
if(this.level>3){
arr4=arr3[col4Index][this.nodeChild];
col4Index=arr4.findIndex((v)=>{
return v[this.defaultType]==a4;
});
col4Index=value?(col4Index!=-1?col4Index:0):0;
col4=arr4[col4Index];
};
switch(this.level*1){
case 2:
dVal=[col1Index,col2Index];
obj={
col1,
col2
}
data=[arr1,arr2];
break;
case 3:
dVal=[col1Index,col2Index,col3Index];
obj={
col1,
col2,
col3
}
data=[arr1,arr2,arr3];
break;
case 4:
dVal=[col1Index,col2Index,col3Index,col4Index];
obj={
col1,
col2,
col3,
col4
}
data=[arr1,arr2,arr3,arr4];
break
}
return {
data,
dVal,
obj
}
},
initData(){
let dataData=this.getData();
let data=dataData.data;
let arr1=data[0];
let arr2=data[1];
let arr3=data[2]||[];
let arr4=data[3]||[];
let obj=dataData.obj;
let col1=obj.col1,col2=obj.col2,col3=obj.col3||{},col4=obj.col4||{};
let result="",value=[];
let range=[];
switch(this.level){
case 2:
value=[col1[this.nodeVal],col2[this.nodeVal]];
result=`${col1[this.nodeKey]+col2[this.nodeKey]}`;
range=[arr1,arr2];
break;
case 3:
value=[col1[this.nodeVal],col2[this.nodeVal],col3[this.nodeVal]];
result=`${col1[this.nodeKey]+col2[this.nodeKey]+col3[this.nodeKey]}`;
range=[arr1,arr2,arr3];
break;
case 4:
value=[col1[this.nodeVal],col2[this.nodeVal],col3[this.nodeVal],col4[this.nodeVal]];
result=`${col1[this.nodeKey]+col2[this.nodeKey]+col3[this.nodeKey]+col4[this.nodeKey]}`;
range=[arr1,arr2,arr3,arr4];
break;
}
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=dataData.dVal;
});
this.$emit("change",{
result:result,
value:value,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let col1Index=arr[0],col2Index=arr[1],col3Index=arr[2]||0,col4Index=arr[3]||0;
let arr1=[],arr2=[],arr3=[],arr4=[];
let col1,col2,col3,col4,obj={};
let result="",value=[];
arr1=this.options;
arr2=(arr1[col1Index]&&arr1[col1Index][this.nodeChild])||arr1[arr1.length-1][this.nodeChild]||[];
col1=arr1[col1Index]||arr1[arr1.length-1]||{};
col2=arr2[col2Index]||arr2[arr2.length-1]||{};
if(this.level>2){
arr3=(arr2[col2Index]&&arr2[col2Index][this.nodeChild])||arr2[arr2.length-1][this.nodeChild];
col3=arr3[col3Index]||arr3[arr3.length-1]||{};
}
if(this.level>3){
arr4=(arr3[col3Index]&&arr3[col3Index][this.nodeChild])||arr3[arr3.length-1][this.nodeChild]||[];
col4=arr4[col4Index]||arr4[arr4.length-1]||{};
}
switch(this.level){
case 2:
obj={
col1,
col2
}
this.range=[arr1,arr2];
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')}`;
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||''];
break;
case 3:
obj={
col1,
col2,
col3
}
this.range=[arr1,arr2,arr3];
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')+(col3[this.nodeKey]||'')}`;
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||'',col3[this.nodeVal]||''];
break;
case 4:
obj={
col1,
col2,
col3,
col4
}
this.range=[arr1,arr2,arr3,arr4];
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')+(col3[this.nodeKey]||'')+(col4[this.nodeKey]||'')}`;
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||'',col3[this.nodeVal]||'',col4[this.nodeVal]||''];
break;
}
this.checkObj=obj;
this.pickVal=arr;
this.$emit("change",{
result:result,
value:value,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,344 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.fyears" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.fmonths" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.fdays" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex1">
<view class="w-picker-item">-</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.tyears" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.tmonths" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.tdays" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[String,Array],
default(){
return []
}
},
current:{//
type:Boolean,
default:false
},
startYear:{
type:[String,Number],
default:1970
},
endYear:{
type:[String,Number],
default:new Date().getFullYear()
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{4}-\d{2}-\d{2}$/,example="2020-04-03";
if(!strReg.test(value[0])||!strReg.test(value[1])){
console.log(new Error("请传入与mode匹配的value值例["+example+","+example+"]"))
}
return strReg.test(value[0])&&strReg.test(value[1]);
},
resetToData(fmonth,fday,tyear,tmonth){
let range=this.range;
let tmonths=[],tdays=[];
let yearFlag=tyear!=range.tyears[0];
let monthFlag=tyear!=range.tyears[0]||tmonth!=range.tmonths[0];
let ttotal=new Date(tyear,tmonth,0).getDate();
for(let i=yearFlag?1:fmonth*1;i<=12;i++){
tmonths.push(this.formatNum(i))
}
for(let i=monthFlag?1:fday*1;i<=ttotal;i++){
tdays.push(this.formatNum(i))
}
return{
tmonths,
tdays
}
},
resetData(fyear,fmonth,fday,tyear,tmonth){
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[];
let startYear=this.startYear;
let endYear=this.endYear;
let ftotal=new Date(fyear,fmonth,0).getDate();
let ttotal=new Date(tyear,tmonth,0).getDate();
for(let i=startYear*1;i<=endYear;i++){
fyears.push(this.formatNum(i))
}
for(let i=1;i<=12;i++){
fmonths.push(this.formatNum(i))
}
for(let i=1;i<=ftotal;i++){
fdays.push(this.formatNum(i))
}
for(let i=fyear*1;i<=endYear;i++){
tyears.push(this.formatNum(i))
}
for(let i=fmonth*1;i<=12;i++){
tmonths.push(this.formatNum(i))
}
for(let i=fday*1;i<=ttotal;i++){
tdays.push(this.formatNum(i))
}
return {
fyears,
fmonths,
fdays,
tyears,
tmonths,
tdays
}
},
getData(dVal){
let start=this.startYear*1;
let end=this.endYear*1;
let value=dVal;
let flag=this.current;
let aToday=new Date();
let tYear,tMonth,tDay,tHours,tMinutes,tSeconds,pickVal=[];
let initstartDate=new Date(start.toString());
let endDate=new Date(end.toString());
if(start>end){
initstartDate=new Date(end.toString());
endDate=new Date(start.toString());
};
let startYear=initstartDate.getFullYear();
let startMonth=initstartDate.getMonth()+1;
let endYear=endDate.getFullYear();
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[],returnArr=[],startDVal=[],endDVal=[];
let curMonth=flag?value[1]*1:(startDVal[1]*1+1);
let curMonth1=flag?value[5][1]*1:(value[5]*1+1);
let totalDays=new Date(value[0],value[1],0).getDate();
let totalDays1=new Date(value[4],value[5],0).getDate();
for(let s=startYear;s<=endYear;s++){
fyears.push(this.formatNum(s));
};
for(let m=1;m<=12;m++){
fmonths.push(this.formatNum(m));
};
for(let d=1;d<=totalDays;d++){
fdays.push(this.formatNum(d));
};
for(let s=value[0]*1;s<=endYear;s++){
tyears.push(this.formatNum(s));
};
if(value[4]*1>value[0]*1){
for(let m=1;m<=12;m++){
tmonths.push(this.formatNum(m));
};
for(let d=1;d<=totalDays1;d++){
tdays.push(this.formatNum(d));
};
}else{
for(let m=value[1]*1;m<=12;m++){
tmonths.push(this.formatNum(m));
};
for(let d=value[2]*1;d<=totalDays1;d++){
tdays.push(this.formatNum(d));
};
};
pickVal=[
fyears.indexOf(value[0])==-1?0:fyears.indexOf(value[0]),
fmonths.indexOf(value[1])==-1?0:fmonths.indexOf(value[1]),
fdays.indexOf(value[2])==-1?0:fdays.indexOf(value[2]),
0,
tyears.indexOf(value[4])==-1?0:tyears.indexOf(value[4]),
tmonths.indexOf(value[5])==-1?0:tmonths.indexOf(value[5]),
tdays.indexOf(value[6])==-1?0:tdays.indexOf(value[6])
];
return {
fyears,
fmonths,
fdays,
tyears,
tmonths,
tdays,
pickVal
}
},
getDval(){
let value=this.value;
let fields=this.fields;
let dVal=null;
let aDate=new Date();
let fyear=this.formatNum(aDate.getFullYear());
let fmonth=this.formatNum(aDate.getMonth()+1);
let fday=this.formatNum(aDate.getDate());
let tyear=this.formatNum(aDate.getFullYear());
let tmonth=this.formatNum(aDate.getMonth()+1);
let tday=this.formatNum(aDate.getDate());
if(value&&value.length>0){
let flag=this.checkValue(value);
if(!flag){
dVal=[fyear,fmonth,fday,"-",tyear,tmonth,tday]
}else{
dVal=[...value[0].split("-"),"-",...value[1].split("-")];
}
}else{
dVal=[fyear,fmonth,fday,"-",tyear,tmonth,tday]
}
return dVal;
},
initData(){
let range=[],pickVal=[];
let result="",full="",obj={};
let dVal=this.getDval();
let dateData=this.getData(dVal);
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[];
let fyear,fmonth,fday,tyear,tmonth,tday;
pickVal=dateData.pickVal;
fyears=dateData.fyears;
fmonths=dateData.fmonths;
fdays=dateData.fdays;
tyears=dateData.tyears;
tmonths=dateData.tmonths;
tdays=dateData.tdays;
range={
fyears,
fmonths,
fdays,
tyears,
tmonths,
tdays,
}
fyear=range.fyears[pickVal[0]];
fmonth=range.fmonths[pickVal[1]];
fday=range.fdays[pickVal[2]];
tyear=range.tyears[pickVal[4]];
tmonth=range.tmonths[pickVal[5]];
tday=range.tdays[pickVal[6]];
obj={
fyear,
fmonth,
fday,
tyear,
tmonth,
tday
}
result=`${fyear+'-'+fmonth+'-'+fday+'至'+tyear+'-'+tmonth+'-'+tday}`;
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:result.split("至"),
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let result="",full="",obj={};
let year="",month="",day="",hour="",minute="",second="",note=[],province,city,area;
let checkObj=this.checkObj;
let days=[],months=[],endYears=[],endMonths=[],endDays=[],startDays=[];
let mode=this.mode;
let col1,col2,col3,d,a,h,m;
let xDate=new Date().getTime();
let range=this.range;
let fyear=range.fyears[arr[0]]||range.fyears[range.fyears.length-1];
let fmonth=range.fmonths[arr[1]]||range.fmonths[range.fmonths.length-1];
let fday=range.fdays[arr[2]]||range.fdays[range.fdays.length-1];
let tyear=range.tyears[arr[4]]||range.tyears[range.tyears.length-1];
let tmonth=range.tmonths[arr[5]]||range.tmonths[range.tmonths.length-1];
let tday=range.tdays[arr[6]]||range.tdays[range.tdays.length-1];
let resetData=this.resetData(fyear,fmonth,fday,tyear,tmonth);
if(fyear!=checkObj.fyear||fmonth!=checkObj.fmonth||fday!=checkObj.fday){
arr[4]=0;
arr[5]=0;
arr[6]=0;
range.tyears=resetData.tyears;
range.tmonths=resetData.tmonths;
range.tdays=resetData.tdays;
tyear=range.tyears[0];
checkObj.tyears=range.tyears[0];
tmonth=range.tmonths[0];
checkObj.tmonths=range.tmonths[0];
tday=range.tdays[0];
checkObj.tdays=range.tdays[0];
}
if(fyear!=checkObj.fyear||fmonth!=checkObj.fmonth){
range.fdays=resetData.fdays;
};
if(tyear!=checkObj.tyear){
arr[5]=0;
arr[6]=0;
let toData=this.resetToData(fmonth,fday,tyear,tmonth);
range.tmonths=toData.tmonths;
range.tdays=toData.tdays;
tmonth=range.tmonths[0];
checkObj.tmonths=range.tmonths[0];
tday=range.tdays[0];
checkObj.tdays=range.tdays[0];
};
if(tmonth!=checkObj.tmonth){
arr[6]=0;
let toData=this.resetToData(fmonth,fday,tyear,tmonth);
range.tdays=toData.tdays;
tday=range.tdays[0];
checkObj.tdays=range.tdays[0];
};
result=`${fyear+'-'+fmonth+'-'+fday+'至'+tyear+'-'+tmonth+'-'+tday}`;
obj={
fyear,fmonth,fday,tyear,tmonth,tday
}
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=arr;
})
this.$emit("change",{
result:result,
value:result.split("至"),
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,183 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.provinces" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.citys" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column v-if="!hideArea">
<view class="w-picker-item" v-for="(item,index) in range.areas" :key="index">{{item.label}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
import areaData from "./areadata/areadata.js"
export default {
data() {
return {
pickVal:[],
range:{
provinces:[],
citys:[],
areas:[]
},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[Array,String],
default:""
},
defaultType:{
type:String,
default:"label"
},
hideArea:{
type:Boolean,
default:false
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
getData(){
//
let provinces=areaData;
let dVal=[];
let value=this.value;
let a1=value[0];//
let a2=value[1];//
let a3=value[2];//
let province,city,area;
let provinceIndex=provinces.findIndex((v)=>{
return v[this.defaultType]==a1
});
provinceIndex=value?(provinceIndex!=-1?provinceIndex:0):0;
let citys=provinces[provinceIndex].children;
let cityIndex=citys.findIndex((v)=>{
return v[this.defaultType]==a2
});
cityIndex=value?(cityIndex!=-1?cityIndex:0):0;
let areas=citys[cityIndex].children;
let areaIndex=areas.findIndex((v)=>{
return v[this.defaultType]==a3;
});
areaIndex=value?(areaIndex!=-1?areaIndex:0):0;
dVal=this.hideArea?[provinceIndex,cityIndex]:[provinceIndex,cityIndex,areaIndex];
province=provinces[provinceIndex];
city=citys[cityIndex];
area=areas[areaIndex];
let obj=this.hideArea?{
province,
city
}:{
province,
city,
area
}
return this.hideArea?{
provinces,
citys,
dVal,
obj
}:{
provinces,
citys,
areas,
dVal,
obj
}
},
initData(){
let dataData=this.getData();
let provinces=dataData.provinces;
let citys=dataData.citys;
let areas=this.hideArea?[]:dataData.areas;
let obj=dataData.obj;
let province=obj.province,city=obj.city,area=this.hideArea?{}:obj.area;
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
this.range=this.hideArea?{
provinces,
citys,
}:{
provinces,
citys,
areas
};
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=dataData.dVal;
});
this.$emit("change",{
result:result,
value:value,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let provinceIndex=arr[0],cityIndex=arr[1],areaIndex=this.hideArea?0:arr[2];
let provinces=areaData;
let citys=(provinces[provinceIndex]&&provinces[provinceIndex].children)||provinces[provinces.length-1].children||[];
let areas=this.hideArea?[]:((citys[cityIndex]&&citys[cityIndex].children)||citys[citys.length-1].children||[]);
let province=provinces[provinceIndex]||provinces[provinces.length-1],
city=citys[cityIndex]||[citys.length-1],
area=this.hideArea?{}:(areas[areaIndex]||[areas.length-1]);
let obj=this.hideArea?{
province,
city
}:{
province,
city,
area
}
if(this.checkObj.province.label!=province.label){
//;
this.range.citys=citys;
if(!this.hideArea){
this.range.areas=areas;
}
}
if(this.checkObj.city.label!=city.label){
//;
if(!this.hideArea){
this.range.areas=areas;
}
}
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=arr;
})
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
this.$emit("change",{
result:result,
value:value,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,129 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range" :key="index">{{item[nodeKey]}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
props:{
itemHeight:{
type:String,
default:"44px"
},
options:{
type:[Array,Object],
default(){
return []
}
},
value:{
type:String,
default:""
},
defaultType:{
type:String,
default:"label"
},
defaultProps:{
type:Object,
default(){
return{
label:"label",
value:"value"
}
}
}
},
data() {
return {
pickVal:[]
};
},
computed:{
nodeKey(){
return this.defaultProps.label;
},
nodeValue(){
return this.defaultProps.value;
},
range(){
return this.options
}
},
watch:{
value(val){
if(this.options.length!=0){
this.initData();
}
},
options(val){
this.initData();
}
},
created() {
if(this.options.length!=0){
this.initData();
}
},
methods:{
initData(){
let dVal=this.value||"";
let data=this.range;
let pickVal=[0];
let cur=null;
let label="";
let value,idx;
if(this.defaultType==this.nodeValue){
value=data.find((v)=>v[this.nodeValue]==dVal);
idx=data.findIndex((v)=>v[this.nodeValue]==dVal);
}else{
value=data.find((v)=>v[this.nodeKey]==dVal);
idx=data.findIndex((v)=>v[this.nodeKey]==dVal);
}
pickVal=[idx!=-1?idx:0];
this.$nextTick(()=>{
this.pickVal=pickVal;
});
if(this.defaultType==this.nodeValue){
this.$emit("change",{
result:value?value[this.nodeKey]:data[0][this.nodeKey],
value:dVal||data[0][this.nodeKey],
obj:value?value:data[0]
})
}else{
this.$emit("change",{
result:dVal||data[0][this.nodeKey],
value:value?value[this.nodeValue]:data[0][this.nodeValue],
obj:value?value:data[0]
})
}
},
handlerChange(e){
let arr=[...e.detail.value];
let pickVal=[arr[0]||0];
let data=this.range;
let cur=data[arr[0]];
let label="";
let value="";
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:cur[this.nodeKey],
value:cur[this.nodeValue],
obj:cur
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,250 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.dates" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item.label}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
expand:{
type:[Number,String],
default:30
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/,example="2019-12-12 18:05:00或者2019-12-12 18:05";
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let months=[],days=[],sections=[];
let disabledAfter=this.disabledAfter;
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
let totalDays=new Date(year,month,0).getDate();//;
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
};
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
return{
months,
days,
sections
}
},
getData(dVal){
//
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let dates=[],hours=[],minutes=[];
let curDate=new Date();
let curYear=curDate.getFullYear();
let curMonth=curDate.getMonth();
let curDay=curDate.getDate();
let aDate=new Date(curYear,curMonth,curDay);
for(let i=0;i<this.expand*1;i++){
aDate=new Date(curYear,curMonth,curDay+i);
let year=aDate.getFullYear();
let month=aDate.getMonth()+1;
let day=aDate.getDate();
let label=year+"-"+this.formatNum(month)+"-"+this.formatNum(day);
switch(i){
case 0:
label="今天";
break;
case 1:
label="明天";
break;
case 2:
label="后天";
break
}
dates.push({
label:label,
value:year+"-"+this.formatNum(month)+"-"+this.formatNum(day)
})
};
for(let i=0;i<24;i++){
hours.push({
label:this.formatNum(i),
value:this.formatNum(i)
})
}
for(let i=0;i<60;i++){
minutes.push({
label:this.formatNum(i),
value:this.formatNum(i)
})
}
return {
dates,
hours,
minutes
}
},
getDefaultDate(){
let value=this.value;
let reg=/-/g;
let defaultDate=value?new Date(value.replace(reg,"/")):new Date();
let defaultYear=defaultDate.getFullYear();
let defaultMonth=defaultDate.getMonth()+1;
let defaultDay=defaultDate.getDate();
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
return{
defaultDate,
defaultYear,
defaultMonth,
defaultDay,
defaultDays
}
},
getDval(){
let value=this.value;
let dVal=null;
let aDate=new Date();
let year=this.formatNum(aDate.getFullYear());
let month=this.formatNum(aDate.getMonth()+1);
let day=this.formatNum(aDate.getDate());
let date=this.formatNum(year)+"-"+this.formatNum(month)+"-"+this.formatNum(day);
let hour=aDate.getHours();
let minute=aDate.getMinutes();
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[date,hour,minute]
}else{
let v=value.split(" ");
dVal=[v[0],...v[1].split(":")];
}
}else{
dVal=[date,hour,minute]
}
return dVal;
},
initData(){
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
let dates=[],hours=[],minutes=[];
let dVal=[],pickVal=[];
let value=this.value;
let reg=/-/g;
let range={};
let result="",full="",date,hour,minute,obj={};
let defaultDate=this.getDefaultDate();
let defaultYear=defaultDate.defaultYear;
let defaultMonth=defaultDate.defaultMonth;
let defaultDay=defaultDate.defaultDay;
let defaultDays=defaultDate.defaultDays;
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let dateData=[];
dVal=this.getDval();
dateData=this.getData(dVal);
dates=dateData.dates;
hours=dateData.hours;
minutes=dateData.minutes;
pickVal=[
dates.findIndex(n => n.value == dVal[0])!=-1?dates.findIndex(n => n.value == dVal[0]):0,
hours.findIndex(n => n.value == dVal[1])!=-1?hours.findIndex(n => n.value == dVal[1]):0,
minutes.findIndex(n => n.value == dVal[2])!=-1?minutes.findIndex(n => n.value == dVal[2]):0,
];
range={dates,hours,minutes};
date=dVal[0]?dVal[0]:dates[0].label;
hour=dVal[1]?dVal[1]:hours[0].label;
minute=dVal[2]?dVal[2]:minutes[0].label;
result=full=`${date+' '+hour+':'+minute}`;
obj={
date,
hour,
minute
}
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:full,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let date="",hour="",minute="";
let result="",full="",obj={};
let disabledAfter=this.disabledAfter;
date=(arr[0]||arr[0]==0)?data.dates[arr[0]]||data.dates[data.dates.length-1]:"";
hour=(arr[1]||arr[1]==0)?data.hours[arr[1]]||data.hours[data.hours.length-1]:"";
minute=(arr[2]||arr[2]==0)?data.minutes[arr[2]]||data.minutes[data.minutes.length-1]:"";
result=full=`${date.label+' '+hour.label+':'+minute.label+':00'}`;
obj={
date,
hour,
minute
}
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,218 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column v-if="second">
<view class="w-picker-item" v-for="(item,index) in range.seconds" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
second:{
type:Boolean,
default:true
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{2}:\d{2}:\d{2}$/,example="18:00:05";
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day,hour,minute){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
for(let hour=0;hour<24;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<60;minute++){
minutes.push(this.formatNum(minute));
}
for(let second=0;second<60;second++){
seconds.push(this.formatNum(second));
}
return{
hours,
minutes,
seconds
}
},
getData(curDate){
//
let hours=[],minutes=[],seconds=[];
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let fields=this.fields;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
for(let hour=0;hour<24;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<60;minute++){
minutes.push(this.formatNum(minute));
}
for(let second=0;second<60;second++){
seconds.push(this.formatNum(second));
}
return this.second?{
hours,
minutes,
seconds
}:{
hours,
minutes
}
},
getCurrenDate(){
let curDate=new Date();
let curHour=curDate.getHours();
let curMinute=curDate.getMinutes();
let curSecond=curDate.getSeconds();
return this.second?{
curHour,
curMinute,
curSecond
}:{
curHour,
curMinute,
}
},
getDval(){
let value=this.value;
let fields=this.fields;
let dVal=null;
let aDate=new Date();
let hour=this.formatNum(aDate.getHours());
let minute=this.formatNum(aDate.getMinutes());
let second=this.formatNum(aDate.getSeconds());
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[hour,minute,second]
}else{
dVal=value?value.split(":"):[];
}
}else{
dVal=this.second?[hour,minute,second]:[hour,minute]
}
return dVal;
},
initData(){
let curDate=this.getCurrenDate();
let dateData=this.getData(curDate);
let pickVal=[],obj={},full="",result="",hour="",minute="",second="";
let dVal=this.getDval();
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let hours=dateData.hours;
let minutes=dateData.minutes;
let seconds=dateData.seconds;
let defaultArr=this.second?[
dVal[0]&&hours.indexOf(dVal[0])!=-1?hours.indexOf(dVal[0]):0,
dVal[1]&&minutes.indexOf(dVal[1])!=-1?minutes.indexOf(dVal[1]):0,
dVal[2]&&seconds.indexOf(dVal[2])!=-1?seconds.indexOf(dVal[2]):0
]:[
dVal[0]&&hours.indexOf(dVal[0])!=-1?hours.indexOf(dVal[0]):0,
dVal[1]&&minutes.indexOf(dVal[1])!=-1?minutes.indexOf(dVal[1]):0
];
pickVal=disabledAfter?defaultArr:(curFlag?(this.second?[
hours.indexOf(this.formatNum(curDate.curHour)),
minutes.indexOf(this.formatNum(curDate.curMinute)),
seconds.indexOf(this.formatNum(curDate.curSecond)),
]:[
hours.indexOf(this.formatNum(curDate.curHour)),
minutes.indexOf(this.formatNum(curDate.curMinute))
]):defaultArr);
this.range=dateData;
this.checkObj=obj;
hour=dVal[0]?dVal[0]:hours[0];
minute=dVal[1]?dVal[1]:minutes[0];
if(this.second)second=dVal[2]?dVal[0]:seconds[0];
result=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute}`;
full=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute+':00'}`;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:full,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let hour="",minute="",second="",result="",full="",obj={};
hour=(arr[0]||arr[0]==0)?data.hours[arr[0]]||data.hours[data.hours.length-1]:"";
minute=(arr[1]||arr[1]==0)?data.minutes[arr[1]]||data.minutes[data.minutes.length-1]:"";
if(this.second)second=(arr[2]||arr[2]==0)?data.seconds[arr[2]]||data.seconds[data.seconds.length-1]:"";
obj=this.second?{
hour,
minute,
second
}:{
hour,
minute
};
this.checkObj=obj;
result=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute}`;
full=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute+':00'}`;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,26 @@
.w-picker-flex2{
flex:2;
}
.w-picker-flex1{
flex:1;
}
.w-picker-view {
width: 100%;
height: 476upx;
overflow: hidden;
background-color: rgba(255, 255, 255, 1);
z-index: 666;
}
.d-picker-view{
height: 100%;
}
.w-picker-item {
text-align: center;
width: 100%;
height: 88upx;
line-height: 88upx;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 30upx;
}

View File

@ -0,0 +1,340 @@
<template name="w-picker">
<view class="w-picker" :key="createKey" :data-key="createKey">
<view class="mask" :class="{'visible':visible}" @tap="onCancel" @touchmove.stop.prevent catchtouchmove="true"></view>
<view class="w-picker-cnt" :class="{'visible':visible}">
<view class="w-picker-header" @touchmove.stop.prevent catchtouchmove="true">
<text @tap.stop.prevent="onCancel">取消</text>
<slot></slot>
<text :style="{'color':themeColor}" @tap.stop.prevent="pickerConfirm">确定</text>
</view>
<date-picker
v-if="mode=='date'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:fields="fields"
:item-height="itemHeight"
:current="current"
:disabled-after="disabledAfter"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</date-picker>
<range-picker
v-if="mode=='range'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:item-height="itemHeight"
:current="current"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</range-picker>
<half-picker
v-if="mode=='half'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:item-height="itemHeight"
:current="current"
:disabled-after="disabledAfter"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</half-picker>
<shortterm-picker
v-if="mode=='shortTerm'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:item-height="itemHeight"
:current="current"
expand="60"
:disabled-after="disabledAfter"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</shortterm-picker>
<time-picker
v-if="mode=='time'"
class="w-picker-wrapper"
:value="value"
:item-height="itemHeight"
:current="current"
:disabled-after="disabledAfter"
:second="second"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</time-picker>
<selector-picker
v-if="mode=='selector'"
class="w-picker-wrapper"
:value="value"
:item-height="itemHeight"
:options="options"
:default-type="defaultType"
:default-props="defaultProps"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</selector-picker>
<region-picker
v-if="mode=='region'"
class="w-picker-wrapper"
:value="value"
:hide-area="hideArea"
:default-type="defaultType"
:item-height="itemHeight"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</region-picker>
<linkage-picker
v-if="mode=='linkage'"
class="w-picker-wrapper"
:value="value"
:options="options"
:level="level"
:default-type="defaultType"
:default-props="defaultProps"
:item-height="itemHeight"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</linkage-picker>
</view>
</view>
</template>
<script>
import datePicker from "./date-picker.vue"
import rangePicker from "./range-picker.vue"
import halfPicker from "./half-picker.vue"
import shorttermPicker from "./shortterm-picker.vue"
import timePicker from "./time-picker.vue"
import selectorPicker from "./selector-picker.vue"
import regionPicker from "./region-picker.vue"
import linkagePicker from "./linkage-picker.vue"
export default {
name:"w-picker",
components:{
datePicker,
rangePicker,
halfPicker,
timePicker,
selectorPicker,
shorttermPicker,
regionPicker,
linkagePicker
},
props:{
mode:{
type:String,
default:"date"
},
value:{//
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
themeColor:{//
type:String,
default:"#f5a200"
},
fields:{//:yearmonthdayhourminutesecond
type:String,
default:"date"
},
disabledAfter:{//
type:Boolean,
default:false
},
second:{//time-picker
type:Boolean,
default:true
},
options:{//selector,region
type:[Array,Object],
default(){
return []
}
},
defaultProps:{//selector,linkagle
type:Object,
default(){
return{
label:"label",
value:"value",
children:"children"
}
}
},
defaultType:{
type:String,
default:"label"
},
hideArea:{//mode=region
type:Boolean,
default:false
},
level:{
//,2-4;
type:[Number,String],
default:2
},
timeout:{//,
type:Boolean,
default:false
},
expand:{//mode=shortterm
type:[Number,String],
default:30
},
startYear:{
type:[String,Number],
default:1970
},
endYear:{
type:[String,Number],
default:new Date().getFullYear()
},
visible:{
type:Boolean,
default:false
}
},
created() {
this.createKey=Math.random()*1000;
},
data() {
return {
itemHeight:`height: ${uni.upx2px(88)}px;`,
result:{},
confirmFlag:true
};
},
methods:{
touchStart(){
if(this.timeout){
this.confirmFlag=false;
}
},
touchEnd(){
if(this.timeout){
setTimeout(()=>{
this.confirmFlag=true;
},500)
}
},
handlerChange(res){
let _this=this;
this.result={...res};
},
show(){
this.$emit("update:visible",true);
},
hide(){
this.$emit("update:visible",false);
},
onCancel(res){
this.$emit("update:visible",false);
this.$emit("cancel");
},
pickerConfirm(){
if(!this.confirmFlag){
return;
};
this.$emit("confirm",this.result);
this.$emit("update:visible",false);
}
}
}
</script>
<style lang="scss">
.w-picker-item {
text-align: center;
width: 100%;
height: 88upx;
line-height: 88upx;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 30upx;
}
.w-picker{
z-index: 888;
.mask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
visibility: hidden;
opacity: 0;
transition: all 0.3s ease;
}
.mask.visible{
visibility: visible;
opacity: 1;
}
.w-picker-cnt {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 3000;
background-color: #fff;
}
.w-picker-cnt.visible {
transform: translateY(0);
}
.w-picker-header{
display: flex;
align-items: center;
padding: 0 30upx;
height: 88upx;
background-color: #fff;
position: relative;
text-align: center;
font-size: 32upx;
justify-content: space-between;
border-bottom: solid 1px #eee;
.w-picker-btn{
font-size: 30upx;
}
}
.w-picker-hd:after {
content: ' ';
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<view class="switch-container" :style="[{ background: bj_color}]">
<view class="switch_view">
<view
class="switch-item"
:class="{'checked_switch':isSwitch}"
:style="isSwitch?`color:${checked_color}`:''"
@click.prevent.stop="changeSwitch(true)"
:animation="animationData2"
>
{{switchList[0]}}
</view>
<view
class="switch-item"
:class="{'checked_switch':!isSwitch}"
:style="!isSwitch?`color:${checked_color}`:''"
@click.prevent.stop="changeSwitch(false)"
:animation="animationData3"
>
{{switchList[1]}}
</view>
</view>
<view class="disabled" v-if="disabled"></view>
<view
class="position_view" :animation="animationData1"
:style="[{ background: checked_bj_color}]"
></view>
</view>
</template>
<script>
export default {
props: {
switchList: {
type: Array,
default: ()=>{
return ['隐藏','显示'];
}
},
defaultSwitch:{ //
type:Boolean,
default:true
},
isShowModal:{//
type:Boolean,
default:false
},
disabled:{
type:Boolean,
default:false
},
bj_color:{
type:String,
default:'#fff'
},
checked_bj_color:{
type:String,
default:'#1989fa'
},
checked_color:{
type:String,
default:'#fff'
},
id:{
type:null,
default:null
}
},
watch:{
//
defaultSwitch(){
if(this.isSwitch != this.defaultSwitch){
this.isSwitch = this.defaultSwitch;
this.changeAnimation();
}
}
},
data () {
return {
isSwitch:true,
initAnimation:{},
animationData1: {},
animationData2: {},
animationData3: {}
};
},
created () {
this.initAnimation = uni.createAnimation({
duration: 500,
timingFunction: 'ease'
});
this.isSwitch = this.defaultSwitch;
this.changeAnimation();
},
methods: {
changeSwitch(isSwitch) {
if(isSwitch == this.isSwitch || this.disabled){
return;
}
if(this.isShowModal){
let index = isSwitch?0:1;
let text = this.switchList[index];
// uni.showModal({
// title: '',
// content: `${text}`,
// success: (res) => {
// if(res.confirm){
// this.isSwitch = isSwitch;
// this.changeAnimation();
// this.callParentEvent(isSwitch);
// }
// }
// });
}else{
this.isSwitch = isSwitch;
this.changeAnimation();
this.callParentEvent(isSwitch);
}
},
//
changeAnimation(){
if(this.isSwitch){
this.animationData1 = this.initAnimation.left(0).width('50%').step().export();
this.animationData2 = this.initAnimation.width('50%').step().export();
this.animationData3 = this.initAnimation.width('50%').step().export();
}else{
this.animationData1 = this.initAnimation.left('50%').width('50%').step().export();
this.animationData2 = this.initAnimation.width('50%').step().export();
this.animationData3 = this.initAnimation.width('50%').step().export();
}
},
// change
callParentEvent(){
this.$emit('change',this.isSwitch,this.id);
}
}
};
</script>
<style lang="scss" scoped>
.switch-container {
display: flex;
flex-direction: row;
width: 180upx;
height: 60upx;
border-radius: 100upx;
border: 1upx solid #ccc;
position: relative;
.switch_view{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
display: flex;
border-radius: 100upx;
.switch-item {
color: #666;
font-size: 24upx;
height: 100%;
width: 40%;
border-radius: 100upx;
display: flex;
justify-content: center;
align-items: center;
}
}
.position_view{
position: absolute;
top: 0;
left: 0;
width: 60%;
height: 100%;
border-radius: 100upx;
background: $uni-color-primary;
}
.disabled{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99;
background: #fff;
opacity: 0.6;
border-radius: 100upx;
}
}
</style>

117
main.js Normal file
View File

@ -0,0 +1,117 @@
import Vue from 'vue'
import App from './App'
import store from './store'
import MinCache from'./common/util/MinCache.js'
import tip from'./common/util/tip.js'
import configService from'./common/service/config.service.js'
import router from './common/router'
import {RouterMount} from './plugin/uni-simple-router/index.js'
//引入mescroll插件
// import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue"
// import MescrollUni from "@/components/mescroll-uni/mescroll-uni.vue"
// Vue.component('mescroll-body', MescrollBody);
// Vue.component('mescroll-uni', MescrollUni);
// 注册缓存器
Vue.use(MinCache,{timeout: 6})
// store
Vue.prototype.$store=store;
// tip
Vue.prototype.$tip=tip;
// config
Vue.prototype.$config=configService;
// request请求
import { http } from '@/common/service/service.js'
Vue.prototype.$http = http
Vue.prototype.cutMoneyFiter = (amount) => {
if(!amount) {
return "0"
}
//强制保留两位小数
let f = parseFloat(amount);
if (isNaN(f)) return false;
f = Math.round(amount * 100) / 100;
let s = f.toString();
// let rs = s.indexOf('.');
// if (rs < 0) {
// rs = s.length;
// s += '.';
// }
// while (s.length < (rs + 1) + 2) {
// s += '0';
// }
//每三位用一个逗号隔开
let leftNum=s.split(".")[0];
let rightNum="."+s.split(".")[1];
let result;
//定义数组记录截取后的价格
let resultArray=new Array();
if(leftNum.length>3){
let i=true;
while (i){
resultArray.push(leftNum.slice(-3));
leftNum=leftNum.slice(0,leftNum.length-3);
if(leftNum.length<4){
i=false;
}
}
//由于从后向前截取,所以从最后一个开始遍历并存到一个新的数组,顺序调换
let sortArray=new Array();
for(let i=resultArray.length-1;i>=0;i--){
sortArray.push(resultArray[i]);
}
// result=leftNum+","+sortArray.join(",")+rightNum;
result=leftNum+","+sortArray.join(",");
}else {
result=s;
}
return result;
}
// 自定义组件
// import mySelect from './components/my-componets/my-select.vue'
// Vue.component('mySelect',mySelect)
// import myImageUpload from './components/my-componets/my-image-upload.vue'
// Vue.component('myImageUpload',myImageUpload)
// import myPage from './components/my-componets/my-page.vue'
// Vue.component('myPage',myPage)
// import cuCustom from './plugin/colorui/components/cu-custom.vue'
// Vue.component('cu-custom',cuCustom)
// import VConsole from './js_sdk/vconsole.min'
// var vConsole = new VConsole();
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
store,
MinCache,
...App
})
//v1.3.5起 H5端 你应该去除原有的app.$mount();使用路由自带的渲染方式
// #ifdef H5
RouterMount(app,'#app');
// #endif
// #ifndef H5
app.$mount(); //为了兼容小程序及app端必须这样写才有效果
// #endif

122
manifest.json Normal file
View File

@ -0,0 +1,122 @@
{
"name" : "农业面源污染监测系统",
"appid" : "__UNI__44A8AB0",
"description" : "",
"versionName" : "2.2.22",
"versionCode" : 233,
"transformPx" : false,
"app-plus" : {
/* 5+App */
"modules" : {
"Maps" : {},
"Push" : {},
"VideoPlayer" : {},
"LivePusher" : {},
"Geolocation" : {},
"Record" : {}
},
/* */
"distribute" : {
/* */
"android" : {
/* android */
"permissions" : [
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_MOCK_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"ios" : {},
/* ios */
"sdkConfigs" : {
"ad" : {},
"maps" : {
"amap" : {
"appkey_ios" : "df5dfa6a0882f3564bca78cd7abcee9a",
"appkey_android" : "df5dfa6a0882f3564bca78cd7abcee9a"
}
},
"push" : {
"unipush" : {}
},
"geolocation" : {
"system" : {
"__platform__" : [ "ios", "android" ]
},
"amap" : {
"__platform__" : [ "ios", "android" ],
"appkey_ios" : "df5dfa6a0882f3564bca78cd7abcee9a",
"appkey_android" : "df5dfa6a0882f3564bca78cd7abcee9a"
}
}
}
},
"splashscreen" : {}
},
// "waiting" : false,
// "alwaysShowBeforeRender" : true,
// "autoclose" : false,
// "delay" : 0
/* SDK */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wx2fb61322f3042141",
"setting" : {
"urlCheck" : false,
"es6" : true,
"minified" : true
},
"permission" : {
"scope.userLocation" : {
"desc" : "获取当前地理位置"
}
},
"requiredPrivateInfos" : [ "getLocation", "chooseLocation", "onLocationChange" ],
"optimization" : {
"subPackages" : true
}
},
// "plugins": {
// "live-player-plugin": {
// "version": "1.1.0",
// "provider": "wxa77e7ba6131ada78"
// }
// }
"h5" : {
"title" : "Do it today",
"domain" : "myhjdc.cn",
"sdkConfigs" : {
"maps" : {
"amap" : {
"key" : "df5dfa6a0882f3564bca78cd7abcee9a",
"securityJsCode" : "",
"serviceHost" : ""
}
}
}
}
}

BIN
myhjdc.keystore Normal file

Binary file not shown.

View File

@ -0,0 +1,106 @@
export class UniCanvas {
constructor(ctx, canvasNode) {
this.ctx = ctx
this.chart = {}
this.canvasNode = canvasNode
if (!canvasNode) {
this._initStyle(ctx)
}
this._initEvent()
}
getContext(contextType) {
if (contextType === '2d') {
return this.ctx
}
}
setChart(chart) {
this.chart = chart
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
addEventListener() {
// noop
}
removeEventListener() {
// noop
}
_initCanvas(zrender, ctx) {
zrender.util.getContext = () => {
return ctx
}
zrender.util.$override('measureText', (text, font) => {
ctx.font = font || '12px sans-serif'
return ctx.measureText(text)
})
}
_initStyle(ctx) {
ctx.createCircularGradient = (x, y, r) => {
return ctx.createCircularGradient(x, y, r)
}
}
_initEvent() {
this.event = {}
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown',
},
{
wxName: 'touchMove',
ecName: 'mousemove',
},
{
wxName: 'touchEnd',
ecName: 'mouseup',
},
{
wxName: 'touchEnd',
ecName: 'click',
},
]
eventNames.forEach((name) => {
this.event[name.wxName] = (e) => {
const touch = e.touches[0]
this.chart.getZr().handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {},
})
}
})
}
get width() {
if (this.canvasNode) return this.canvasNode.width
return 0
}
set width(w) {
if (this.canvasNode) this.canvasNode.width = w
}
get height() {
if (this.canvasNode) return this.canvasNode.height
return 0
}
set height(h) {
if (this.canvasNode) this.canvasNode.height = h
}
}

View File

@ -0,0 +1,351 @@
<template>
<!-- #ifdef APP-VUE || H5 -->
<view v-if="systemInfo.deviceType === 'pc'" :id="canvasId" class="uni-canvas" @click="emits('click', $event)" />
<view
v-else
:id="canvasId"
class="uni-canvas"
@click="click"
@touchstart="touchStart"
@touchmove.stop="touchMove"
@touchend="touchEnd"
/>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN || MP-QQ -->
<canvas
v-if="useNewCanvas"
type="2d"
:id="canvasId"
class="uni-canvas"
:canvas-id="canvasId"
@click="click"
@touchstart="touchStart"
@touchmove.stop="touchMove"
@touchend="touchEnd"
/>
<canvas
v-else
:id="canvasId"
class="uni-canvas"
:canvas-id="canvasId"
@click="click"
@touchstart="touchStart"
@touchmove.stop="touchMove"
@touchend="touchEnd"
/>
<!-- #endif -->
</template>
<script>
// #ifdef VUE3
import '../../static/echarts.min.js'
// #endif
// #ifdef VUE2 || MP-WEIXIN
const echarts = require('../../static/echarts.min.js')
// #endif
import { UniCanvas } from './uni-canvas.js'
let chart = null
export default {
name: 'uni-chart',
emits: ['inited', 'click', 'touchStart', 'touchMove', 'touchEnd'],
props: {
// 使 canvas
forceUseOldCanvas: {
type: Boolean,
default: false
},
//
theme: {
type: [String, Object],
},
//
option: {
type: Object,
require: true,
default() {
return {}
}
},
//
map: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
canvasId: `uni-canvas-${Date.now()}`,
systemInfo: uni.getSystemInfoSync(),
useNewCanvas: true
}
},
mounted() {
this.registerPreprocessor()
this.registerMap()
this.$nextTick(() => {
// #ifdef APP-VUE || H5
this.initH5()
// #endif
// #ifdef MP-WEIXIN || MP-QQ
this.initMiniProgram()
// #endif
})
},
beforeDestroy() {
this.dispose()
},
methods: {
// register echarts preprocessor
registerPreprocessor() {
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0
})
} else if (typeof option.series === 'object') {
option.series.progressive = 0
}
}
})
},
// register geo json
registerMap() {
if (JSON.stringify(this.$props.map) === '{}') return
echarts.registerMap(this.$props.map.name, this.$props.map.opt)
},
// register theme color
registerTheme(name, opt) {
console.log('registerTheme', name, opt)
echarts.registerTheme(name, opt)
},
// init H5 app-vue
initH5() {
const canvasNode = document.getElementById(this.canvasId)
chart = echarts.init(canvasNode, this.$props.theme)
this.$emit('inited', chart)
chart.setOption(this.$props.option)
},
// init mini program
initMiniProgram() {
const version = this.systemInfo.SDKVersion
console.log(`当前基础库版本为: ${version}`)
const oldVersion = '1.9.91'
const baseVersion = '2.9.0'
let canUseNewCanvas = this.compareVersion(version, baseVersion) >= 0
if (this.$props.forceUseOldCanvas) {
if (canUseNewCanvas) console.warn('开发者强制使用旧canvas,建议关闭')
canUseNewCanvas = false
}
this.useNewCanvas = canUseNewCanvas && !this.forceUseOldCanvas
if (this.useNewCanvas) {
// 2.9.0 使 <canvas type="2d"></canvas>
this.initNewCanvas()
} else {
const isValid = this.compareVersion(version, oldVersion) >= 0
if (!isValid) {
console.error(`基础库版本过低,需大于等于 ${oldVersion}`)
return
} else {
console.warn(`建议将基础库调整大于等于${baseVersion}版本。升级后绘图将有更好性能`)
this.initOldCanvas()
}
}
},
// initNewCanvas
initNewCanvas() {
const query = uni.createSelectorQuery().in(this)
query
.select(`#${this.canvasId}`)
.node(res => {
const canvasNode = res.node
const ctx = canvasNode?.getContext('2d')
canvasNode.width = canvasNode.width * this.systemInfo.pixelRatio
canvasNode.height = canvasNode.height * this.systemInfo.pixelRatio
ctx.scale(this.pixelRatio, this.pixelRatio)
const canvas = new UniCanvas(ctx, canvasNode)
this.initECharts(canvas, canvasNode.width, canvasNode.width, this.pixelRatio)
})
.exec()
},
// initOldCanvas
initOldCanvas() {
// 1.9.91 <= sdkVersion < 2.9.0
const ctx = uni.createCanvasContext(`#${this.canvasId}`, this)
const canvas = new UniCanvas(ctx)
const query = uni.createSelectorQuery().in(this)
query
.select(`#${this.canvasId}`)
.boundingClientRect(res => {
// canvasdpr
this.initECharts(res.width, res.height, 1)
})
.exec()
},
// init
initECharts(canvas, width, height, dpr) {
echarts.setPlatformAPI({ createCanvas: () => canvas })
const theme = this.$props.theme
let themeName = ''
console.log('typeof theme', typeof theme)
if (typeof theme === 'object') {
this.registerTheme(theme.name, theme.opt)
themeName = theme.name
}
if (typeof theme === 'string') {
themeName = theme
}
chart = echarts.init(canvas, themeName, {
width: width,
height: height,
devicePixelRatio: dpr
})
this.$emit('inited', chart)
this.setOption(this.$props.option)
},
canvasToTempFilePath(opt) {
if (this.useNewCanvas) {
const query = uni.createSelectorQuery().in(this)
query
.select(`#${this.canvasId}`)
.node(res => {
const canvasNode = res.node
opt.canvas = canvasNode
uni.canvasToTempFilePath(opt)
})
.exec()
} else {
if (!opt.canvasId) {
opt.canvasId = this.canvasId
}
// TODO
chart.ctx.draw(true, () => {
uni.canvasToTempFilePath(opt, this)
})
}
},
setOption(opt) {
chart.setOption(opt)
},
dispose() {
chart && chart.dispose()
},
// event
wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i]
touch.offsetX = touch.x
touch.offsetY = touch.y
}
return event
},
click(e) {
this.$emit('click', e)
},
touchStart(e) {
if (chart && e.touches.length > 0) {
const touch = e.touches[0]
const handler = chart.getZr().handler
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopPropagation: () => {}
})
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopPropagation: () => {}
})
handler.processGesture(this.wrapTouch(e), 'start')
this.$emit('touchStart', e)
}
},
touchMove(e) {
if (chart && e.touches.length > 0) {
let touch = e.touches[0]
const {
target: { offsetLeft, offsetTop }
} = e
touch.x = touch.pageX - offsetLeft
touch.y = touch.pageY - offsetTop
const handler = chart.getZr().handler
if (handler) {
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
})
handler.processGesture(this.wrapTouch(e), 'change')
}
this.$emit('touchMove', e)
}
},
touchEnd(e) {
if (chart) {
const touch = e.changedTouches ? e.changedTouches[0] : {}
const {
target: { offsetLeft, offsetTop }
} = e
touch.x = touch.pageX - offsetLeft
touch.y = touch.pageY - offsetTop
var handler = chart.getZr().handler
if (handler) {
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y
})
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y
})
handler.processGesture(this.wrapTouch(e), 'end')
}
this.$emit('touchEnd', e)
}
},
// utils
compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
}
}
</script>
<style>
.uni-canvas {
width: 100%;
height: 100%;
display: block;
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,331 @@
<template>
<canvas type="2d" v-if="isUseNewCanvas" class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart"
@touchmove="touchMove" @touchend="touchEnd">
</canvas>
<canvas v-else class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart" @touchmove="touchMove"
@touchend="touchEnd">
</canvas>
</template>
<script>
import WxCanvas from "./wx-canvas";
import * as echarts from "./echarts";
let ctx;
function wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i];
touch.offsetX = touch.x;
touch.offsetY = touch.y;
}
return event;
}
export default {
props: {
canvasId: {
type: String,
default: () => {
return "ec-canvas";
}
},
ec: {
type: Object
},
forceUseOldCanvas: {
type: Boolean,
value: false
}
},
data() {
return {
$curChart: {},
toHandleList: [],
isUseNewCanvas: true
};
},
watch: {
"ec.option": {
deep: true,
handler(val, oldVal) {
this.setOption(val);
}
}
},
onReady: function() {
if (!this.ec) {
console.warn(
'组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" ' +
'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>'
);
return;
}
if (!this.ec.lazyLoad) {
this.init();
}
},
methods: {
compareVersion(v1, v2) {
v1 = v1.split(".");
v2 = v2.split(".");
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push("0");
}
while (v2.length < len) {
v2.push("0");
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i]);
const num2 = parseInt(v2[i]);
if (num1 > num2) {
return 1;
} else if (num1 < num2) {
return -1;
}
}
return 0;
},
init(callback) {
const version = wx.getSystemInfoSync().SDKVersion;
let canUseNewCanvas = this.compareVersion(version, "2.9.0") >= 0;
if (this.forceUseOldCanvas) {
if (canUseNewCanvas) console.warn("开发者强制使用旧canvas,建议关闭");
canUseNewCanvas = false;
}
this.isUseNewCanvas = canUseNewCanvas && !this.forceUseOldCanvas;
if (this.isUseNewCanvas) {
console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
// 2.9.0 使 <canvas type="2d"></canvas>
this.initByNewWay(callback);
} else {
const isValid = this.compareVersion(version, "1.9.91") >= 0;
if (!isValid) {
console.error(
"微信基础库版本过低,需大于等于 1.9.91。" +
"参见https://github.com/ecomfe/echarts-for-weixin" +
"#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82"
);
return;
} else {
console.warn(
"建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能"
);
this.initByOldWay(callback);
}
}
},
initByOldWay(callback) {
// 1.9.91 <= version < 2.9.0
ctx = wx.createCanvasContext(this.canvasId, this);
const canvas = new WxCanvas(ctx, this.canvasId, false);
const that = this
echarts.setCanvasCreator(() => {
return canvas;
});
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // canvasdpr
const canvasDpr = 1;
var query = wx.createSelectorQuery().in(this);
query
.select(".ec-canvas")
.boundingClientRect(res => {
if (typeof callback === "function") {
that.$curChart = callback(canvas, res.width, res.height, canvasDpr);
} else if (that.ec) {
that.initChart(canvas, res.width, res.height, canvasDpr)
} else {
that.triggerEvent("init", {
canvas: canvas,
width: res.width,
height: res.height,
devicePixelRatio: canvasDpr // dpr便echarts.init
});
}
})
.exec();
},
initByNewWay(callback) {
const that = this
// version >= 2.9.0使
const query = wx.createSelectorQuery().in(this);
query
.select(".ec-canvas")
.fields({
node: true,
size: true
})
.exec(res => {
const canvasNode = res[0].node;
const canvasDpr = wx.getSystemInfoSync().pixelRatio;
const canvasWidth = res[0].width;
const canvasHeight = res[0].height;
const ctx = canvasNode.getContext("2d");
const canvas = new WxCanvas(ctx, that.canvasId, true, canvasNode);
echarts.setCanvasCreator(() => {
return canvas;
});
if (typeof callback === "function") {
that.$curChart = callback(
canvas,
canvasWidth,
canvasHeight,
canvasDpr
);
} else if (that.ec) {
that.initChart(canvas, canvasWidth, canvasHeight, canvasDpr)
} else {
that.triggerEvent("init", {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
devicePixelRatio: canvasDpr
});
}
});
},
setOption(val) {
if (!this.$curChart || !this.$curChart.setOption) {
this.toHandleList.push(val);
} else {
this.$curChart.clear();
this.$curChart.setOption(val);
}
},
canvasToTempFilePath(opt) {
if (this.isUseNewCanvas) {
//
const query = wx.createSelectorQuery().in(this);
query
.select(".ec-canvas")
.fields({
node: true,
size: true
})
.exec(res => {
const canvasNode = res[0].node;
opt.canvas = canvasNode;
wx.canvasToTempFilePath(opt);
});
} else {
//
if (!opt.canvasId) {
opt.canvasId = this.canvasId;
}
ctx.draw(true, () => {
wx.canvasToTempFilePath(opt, this);
});
}
},
touchStart(e) {
if (this.ec.stopTouchEvent) {
e.preventDefault();
e.stopPropagation();
return;
}
this.$emit("touchstart", e);
if (this.$curChart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.$curChart.getZr().handler;
if (handler) {
handler.dispatch("mousedown", {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch("mousemove", {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), "start");
}
}
},
touchMove(e) {
if (this.ec.stopTouchEvent) {
e.preventDefault();
e.stopPropagation();
return;
}
this.$emit("touchmove", e);
if (this.$curChart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.$curChart.getZr().handler;
if (handler) {
handler.dispatch("mousemove", {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), "change");
}
}
},
touchEnd(e) {
if (this.ec.stopTouchEvent) {
e.preventDefault();
e.stopPropagation();
return;
}
this.$emit("touchend", e);
if (this.$curChart) {
const touch = e.changedTouches ? e.changedTouches[0] : {};
var handler = this.$curChart.getZr().handler;
if (handler) {
handler.dispatch("mouseup", {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch("click", {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), "end");
}
}
},
initChart(canvas, width, height, canvasDpr) {
this.$curChart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: canvasDpr
});
canvas.setChart(this.$curChart);
this.$curChart.setOption(this.ec.option,true);
}
}
};
</script>
<style lang="scss">
.ec-canvas {
width: 100%;
height: 100%;
display: block;
}
</style>

View File

@ -0,0 +1,126 @@
export default class WxCanvas {
constructor(ctx, canvasId, isNew, canvasNode) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
this.isNew = isNew
if (isNew) {
this.canvasNode = canvasNode;
} else {
this._initStyle(ctx);
}
// this._initCanvas(zrender, ctx);
this._initEvent();
}
getContext(contextType) {
if (contextType === '2d') {
return this.ctx;
}
}
// canvasToTempFilePath(opt) {
// if (!opt.canvasId) {
// opt.canvasId = this.canvasId;
// }
// return wx.canvasToTempFilePath(opt, this);
// }
setChart(chart) {
this.chart = chart;
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
addEventListener() {
// noop
}
preventDefault(){
// noop
}
_initCanvas(zrender, ctx) {
zrender.util.getContext = function () {
return ctx;
};
zrender.util.$override('measureText', function (text, font) {
ctx.font = font || '12px sans-serif';
return ctx.measureText(text);
});
}
_initStyle(ctx) {
var styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'
];
styles.forEach(style => {
Object.defineProperty(ctx, style, {
set: value => {
if (style !== 'fillStyle' && style !== 'strokeStyle' ||
value !== 'none' && value !== null
) {
ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
}
}
});
});
ctx.createRadialGradient = () => {
return ctx.createCircularGradient(arguments);
};
}
_initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown'
}, {
wxName: 'touchMove',
ecName: 'mousemove'
}, {
wxName: 'touchEnd',
ecName: 'mouseup'
}, {
wxName: 'touchEnd',
ecName: 'click'
}];
eventNames.forEach(name => {
this.event[name.wxName] = e => {
const touch = e.touches[0];
this.chart.getZr().handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y
});
};
});
}
set width(w) {
if (this.canvasNode) this.canvasNode.width = w
}
set height(h) {
if (this.canvasNode) this.canvasNode.height = h
}
get width() {
if (this.canvasNode)
return this.canvasNode.width
return 0
}
get height() {
if (this.canvasNode)
return this.canvasNode.height
return 0
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
<template>
<view class="container">
<view class="liebiaos" v-if="List.length != 0">
<scroll-view :style="{height:scorllheight + 'rpx'}" scroll-y="true" class="scroll-Y" @scrolltolower="lower" @refresherrefresh="refresherrefreshFun" @refresherpulling="refresherpullingFun" :refresher-triggered="isRefresher" refresher-enabled="true">
<view class="topnum">
监测站数量 <span class="number">{{cutMoneyFiter(List.length) || 0}}</span>
</view>
<view class="list_item" v-for="(item,index) in List" :key="index" @click="todetail(item,index)">
<view class="list_item_top">
<view class="list_item_left">
<image v-if="item.stationType == 'livestock'" src="../../static/zhandian_icon_xuqin.png" mode=""></image>
<image v-else src="../../static/zd.png" mode=""></image>
<view class="item_right" v-if="item.stationName">
<view class="right_top">
{{item.stationName}}
</view>
<view class="right_bot" v-if="item.stationLocation">
<image src="../../static/wz.png" mode=""></image>
<view class="">{{item.stationLocation}}</view>
</view>
</view>
</view>
<image src="../../../static/me_icon_in.png" mode="" class="jt"></image>
</view>
<view class="list_item_bot">
<view class="bot_box">
<view class="sbnum">
{{item.deviceCount || 0}}
</view>
<view class="sbtext">
设备数量
</view>
</view>
<view class="bot_box">
<view class="sbnum">
{{item.survObj.length || 0}}
</view>
<view class="sbtext">
监测指标
</view>
</view>
<view class="bot_box">
<view class="sbnum">
{{item.survDataCount || 0}}
</view>
<view class="sbtext">
上报数据
</view>
</view>
</view>
</view>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default{
data(){
return{
baseUrl:configService.apiUrl,
height:0,
scorllheight:0,
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
show:false,
show1:false,
top:0,
List:[],
pageNo:1,
pageSize:4,
isRefresher: false, //
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height
}
});
this.getList()
},
methods:{
//
refresherrefreshFun() {
this.pageNo = 1
this.getList()
},
//
refresherpullingFun() {
this.isRefresher= true
},
getList(){
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
uni.showLoading({
title: '加载中'
});
this.List = []
this.$http.get('/applet/survStationInfo/page',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
for(var i=0;i<this.List.length;i++){
if(this.List[i].deviceCount >= 10000 && this.List[i].deviceCount < 100000000){
this.List[i].deviceCount = (this.List[i].deviceCount /10000).toFixed(1) + '万'
}
if(this.List[i].deviceCount >= 100000000){
this.List[i].deviceCount = (this.List[i].deviceCount /100000000).toFixed(1) + '亿'
}
if(this.List[i].survObj.length >= 10000 && this.List[i].survObj.length < 100000000){
this.List[i].survObj.length = (this.List[i].survObj.length /10000).toFixed(1) + '万'
}
if(this.List[i].survObj.length >= 100000000){
this.List[i].survObj.length = (this.List[i].survObj.length /100000000).toFixed(1) + '亿'
}
if(this.List[i].survDataCount >= 10000 && this.List[i].survDataCount < 100000000){
this.List[i].survDataCount = (this.List[i].survDataCount /10000).toFixed(1) + '万'
}
if(this.List[i].survDataCount >= 100000000){
this.List[i].survDataCount = (this.List[i].survDataCount /100000000).toFixed(1) + '亿'
}
}
console.log(this.List,'35415')
if(res.data.data.total != 0){
this.allNum = Number(res.data.data.total)/Number(this.pageSize)+'';
console.log(this.allNum,'总页数')
if(this.allNum.indexOf('.') == -1) {
this.allNum = this.allNum;
console.log(this.allNum,'if')
} else {
this.allNum = parseInt(Number(this.allNum)+1);
console.log(this.allNum,'else')
}
console.log(this.pageNo,this.allNum,'156156')
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true','nomore')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
uni.hideLoading();
this.isRefresher= false
})
},
lower() {
console.log("最后一页了,取消下拉功能");
//
if (this.isLastpage) {
return
}
clearInterval(this.intervalId);
var num = 1;
this.intervalId = setInterval(() => {
num = num+1;
},1000)
console.log(this.intervalId,num)
this.pageNo = this.pageNo + 1;
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
this.$http.get('/applet/survStationInfo/page',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
if(res.data.data.total != 0){
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
})
},
todetail(item,index){
uni.navigateTo({
url:'/packDetail/pages/Site/detail?item=' + encodeURIComponent(JSON.stringify(item))
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
}
.container{
height: 100%;
// overflow-y: scroll;
// overflow-x: hidden;
}
.bgimg{
width: 100%;
height: 1365rpx;
}
.liebiaos{
padding: 0rpx 32rpx 0;
}
.topnum{
margin-bottom: 25rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #B3C1D1;
margin-top: 14rpx;
}
.number{
font-size: 34rpx;
font-family: DIN Next LT Pro;
font-weight: 500;
color: #2AC166;
margin-left: 15rpx;
margin-right: 15rpx;
}
.list_item{
width: 100%;
padding: 37rpx 34rpx 28rpx;
background: #FFFFFF;
border-radius: 34rpx;
margin-bottom: 25rpx;
}
.list_item:last-child{
margin-bottom: 0;
}
.list_item_top{
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 25rpx;
}
.list_item_left{
display: flex;
align-items: center;
}
.list_item_left image{
width: 73rpx;
height: 73rpx;
margin-right: 18rpx;
}
.item_right{
height: 76rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.right_top{
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
}
.right_bot{
display: flex;
align-items: center;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #9CA9BE;
}
.right_bot image{
height: 26rpx;
width: 24rpx;
margin-right: 11rpx;
}
.jt{
width: 40rpx;
height: 48rpx;
}
.list_item_bot{
width: 100%;
background: #F6F6F6;
border-radius: 16rpx;
padding: 28rpx 0;
display: flex;
justify-content: space-between;
}
.bot_box{
width: 30%;
padding: 0 20rpx;
box-sizing: border-box;
border-right: 2rpx solid #e6e9ef;
display: flex;
flex-direction: column;
align-items: center;
}
.bot_box:last-child{
border: none;
flex: 1;
}
.sbnum{
width: 100%;
font-size: 42rpx;
font-family: DIN Next LT Pro;
font-weight: 500;
color: #142E55;
margin-bottom: 15rpx;
text-align: center;
}
.sbtext{
width:100%;
text-align: center;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #9CA9BE;
}
.load{
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
.zwsj{
width: 100%;
height: 100%;
display: flex;
padding: 60% 170rpx 0;
}
.inzwsj{
width: 100%;
}
.zwsjimg{
width: 100%;
height: 224rpx;
margin-bottom: 37rpx;
}
.zwsjtext{
width: 100%;
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #999999;
line-height: 31rpx;
text-align: center;
}
</style>

View File

@ -0,0 +1,551 @@
<template>
<view class="container">
<uni-nav-bar :fixed="true" left-icon="left" background-color="#0F6EFF" @clickLeft="back()" status-bar
:title="details.name" />
<view class="contant">
<view class="list_item">
<view class="list_item_top">
<view class="list_item_left">
<image :src="details.icon" mode=""></image>
<view class="item_right">
<view class="right_top" v-if="details.name">
监测指标-{{details.name}}
</view>
<view class="right_bot" v-if="stationName">
<image src="../../static/wz.png" mode=""></image>
<view class="">{{stationName}}</view>
</view>
</view>
</view>
</view>
<view class="qsttitle">
总磷趋势图
</view>
<view class="qstcontent">
<uni-ec-canvas :ec="ec" canvas-id="multi-charts-pie"></uni-ec-canvas>
</view>
</view>
<view class="qst">
<view class="list_item_bot">
<view class="scrolltop" v-if="list.length != 0">
<view class="tabitem" v-for="(item,index) in tabList" :key="index">
{{item}}
</view>
</view>
<scroll-view style="height: 550rpx;" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<block v-if="list.length != 0">
<view class="lists_item" v-for="(item,index) in list" :key="index">
<view class="jczbs" v-if="item.codelist[0].name">
{{item.codelist[0].name}}
</view>
<view class="zbz" v-if="item.codelist[0].value">
{{item.codelist[0].value}}{{item.codelist[0].unit}}
</view>
<!--<view class="szqs">
<image v-if="item.type == 1" src="../../../static/home_shuju_shang.png" mode=""></image>
<image v-if="item.type == 0" src="../../../static/home_shuju_xia.png" mode=""></image>
<view class="szqss" v-if="item.type == 2"></view>
</view> -->
<view class="sbsj" v-if="item.codelist[0].dataDateTime">
{{item.codelist[0].dataDateTime}}
</view>
</view>
</block>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
</view>
</view>
</view>
</template>
<script>
import uniEcCanvas from '../../components/uni-ec-canvas/uni-ec-canvas.vue'
import * as echarts from '../../components/uni-ec-canvas/echarts.js'
export default {
components: {
uniEcCanvas,
},
data() {
return {
items: {},
details: {},
list: [],
stationCode: '',
stationName: '',
tabList: ['监测指标', '指标值', '上报时间'],
wrwlist: uni.getStorageSync('wrwlist'),
// nullecharts
myChart: null,
ec: {
option: {}
},
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
show:false,
show1:false,
top:0,
List:[],
pageNo:1,
pageSize:10,
isRefresher: false, //
}
},
onLoad(options) {
this.details = JSON.parse(decodeURIComponent(options.item));
console.log(this.details)
this.stationCode = options.stationCode
this.stationName = options.stationName
},
onShow() {
this.getsssj()
this.gettjt()
},
methods: {
getsssj() {
let params = {}
params.pollutionCode = this.details.code
params.stationCode = this.stationCode
params.pageNo = this.pageNo
params.pageSize = this.pageSize
// params.dataCounts = 100
this.$http.get('/applet/wxclient/getRealTimeSignle', {
params: params
}).then(res => {
var data = res.data.data.records
for (var i = 0; i < data.length; i++) {
data[i].codelist = []
for (var j = 0; j < this.wrwlist.length; j++) {
for (var k = 0; k < Object.keys(data[i]).length; k++) {
if (this.wrwlist[j].code == Object.keys(data[i])[k]) {
if (this.details.code == Object.keys(data[i])[k]) {
data[i].codelist.push({
name: this.wrwlist[j].description,
unit: this.wrwlist[j].unit,
value: (Math.floor(Object.values(data[i])[k] * 100) / 100).toFixed(2),
dataDateTime:data[i].dataDateTime
})
console.log(data[i].codelist, '数据')
console.log(data, '数据全部')
}
}
}
}
}
// this.list = data
this.list = this.list.concat(data)
// console.log(this.list, 'all')
if(res.data.data.total != 0){
this.allNum = Number(res.data.data.total)/Number(this.pageSize)+'';
console.log(this.allNum,'总页数')
if(this.allNum.indexOf('.') == -1) {
this.allNum = this.allNum;
console.log(this.allNum,'if')
} else {
this.allNum = parseInt(Number(this.allNum)+1);
console.log(this.allNum,'else')
}
console.log(this.pageNo,this.allNum,'156156')
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true','nomore')
} else {
this.isLastpage = false;
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
})
},
lower() {
console.log("最后一页了,取消下拉功能");
//
if (this.isLastpage) {
return
}
clearInterval(this.intervalId);
var num = 1;
this.intervalId = setInterval(() => {
num = num+1;
},1000)
console.log(this.intervalId,num)
this.pageNo = this.pageNo + 1;
let params = {}
params.pollutionCode = this.details.code
params.stationCode = this.stationCode
params.pageNo = this.pageNo
params.pageSize = this.pageSize
this.$http.get('/applet/wxclient/getRealTimeSignle',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
for (var i = 0; i < data.length; i++) {
data[i].codelist = []
for (var j = 0; j < this.wrwlist.length; j++) {
for (var k = 0; k < Object.keys(data[i]).length; k++) {
if (this.wrwlist[j].code == Object.keys(data[i])[k]) {
if (this.details.code == Object.keys(data[i])[k]) {
data[i].codelist.push({
name: this.wrwlist[j].description,
unit: this.wrwlist[j].unit,
value: (Math.floor(Object.values(data[i])[k] * 100) / 100).toFixed(2),
dataDateTime:data[i].dataDateTime
})
console.log(data[i].codelist, '数据')
console.log(data, '数据全部')
}
}
}
}
}
// this.list = data
this.list = this.list.concat(data)
if(res.data.data.total != 0){
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
})
},
gettjt() {
this.$http.post('/applet/wxclient/getSinglePollutionSummry?pollutionCode=' + this.details.code +
'&stationCode=' + this.stationCode).then(res => {
var datas = res.data.data
this.ec.option = {
title: {
subtext: '(单位mg/l)'
},
grid: {
top: "46",
left: "5",
bottom: "5",
right: "20",
containLabel: true,
},
tooltip: {
trigger: 'axis',
position: [60, 60],
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
color: '#19D58A',
xAxis: {
type: 'category',
boundaryGap: false,
axisLabel: {
//x
show: true,
interval: 0, //使x
color: '#999999',
},
data: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
},
dataZoom: [{
type: "inside", //
// start: 0,
// end: 10,
endValue: 6,
zoomOnMouseWheel: false, //
moveOnMouseWheel: true, //
moveOnMouseMove: true //
}],
yAxis: {
type: 'value'
},
series: [{
data: datas,
type: 'line',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(25, 213, 138, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
}
}]
}
})
},
back() {
uni.navigateBack({
delta: 1
})
},
},
}
</script>
<style lang="scss">
.uni-nav-bar {
height: 44px;
}
.uni-nav-bar-text {
font-size: 32rpx !important;
font-family: Source Han Sans SC;
color: #FFFFFF !important;
}
.uni-nav-bar__left,
.uni-nav-bar__right {
color: #FFFFFF !important;
}
.uni-navbar__content {
border: 0 none !important;
}
.uni-navbar__header-container-inner {
padding: 0 40rpx;
box-sizing: border-box;
/* 文本不折行 */
white-space: nowrap;
/* 溢出隐藏 */
overflow: hidden;
}
.uni-icons {
color: #FFFFFF !important;
}
page {
height: 100%;
}
.container {
height: 100%;
padding: 0rpx 32rpx;
box-sizing: border-box;
}
.bgimg {
width: 100%;
height: 3550rpx;
}
.content {
padding: 28rpx 0 58rpx;
box-sizing: border-box;
}
.list_item {
width: 100%;
padding: 37rpx 0rpx 28rpx;
background: #FFFFFF;
border-radius: 34rpx;
margin-bottom: 25rpx;
margin-top: 28rpx;
}
.list_item:last-child {
margin-bottom: 0;
}
.list_item_top {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 25rpx;
padding: 0 34rpx 36rpx;
box-sizing: border-box;
border-bottom: 2rpx solid #F6F8FB;
}
.list_item_left {
display: flex;
align-items: center;
}
.list_item_left image {
width: 73rpx;
height: 73rpx;
margin-right: 18rpx;
}
.item_right {
height: 76rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.right_top {
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
}
.right_bot {
display: flex;
align-items: center;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #9CA9BE;
}
.right_bot image {
height: 26rpx;
width: 24rpx;
margin-right: 11rpx;
}
.scroll-Y {
padding: 0 32rpx 0 32rpx;
box-sizing: border-box;
}
.lists_item {
padding-top: 35rpx;
box-sizing: border-box;
display: flex;
}
.jczbs {
width: 30%;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
// text-align: center
}
.zbz {
width: 30%;
font-size: 24rpx;
font-family: DIN Next LT Pro;
font-weight: 400;
color: #2FCD81;
// text-align: center
}
.zbzs {
color: #2FCD81;
}
.szqs {
width: 53rpx;
display: flex;
align-items: center;
justify-content: center;
}
.szqs image {
width: 24rpx;
height: 31rpx;
}
.sbsj {
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
flex: 1;
// text-align: center
// text-align: right;
}
.szqss {
width: 24rpx;
}
.scrolltop {
padding: 0rpx 32rpx 16rpx 32rpx;
display: flex;
justify-content: space-between;
border-bottom: 2rpx solid #F6F8FB;
width: 100%;
}
.tabitem {
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
display: inline-block;
padding-bottom: 26rpx;
}
.tabitem:first-child{
width: 30%;
// text-align: center
}
.tabitem:nth-child(2){
width: 30%;
// text-align: center
}
.tabitem:nth-child(3){
flex: 1;
// text-align: center
}
.qst {
background: #FFFFFF;
border-radius: 34rpx;
padding-top: 43rpx;
padding-bottom: 34rpx;
}
.qsttitle {
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: bold;
color: #2F3841;
padding-left: 33rpx;
}
.qstcontent {
height: 400rpx;
width: 100%;
padding-left: 20rpx;
overflow-x: scroll;
overflow-y: hidden;
}
.uni-ec-canvas {
width: 100%;
height: 400rpx;
}
.load{
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
</style>

View File

@ -0,0 +1,968 @@
<template>
<view class="container">
<!-- <image src="../../static/sjfx.png" mode="" class="bgimg"></image> -->
<view class="pj">
<view class="pjtitle">
面源污染治理效果评价
</view>
<view class="ybecharts">
<image src="../../static/data_bg_img.png" mode=""></image>
<view class="ybechartstext">
{{pjnr}}
</view>
</view>
<view class="bot3">
<view class="bot3_left" v-for="(item,index) in pjlist.slice(0,3)" :key="index">
<view class="bfb">
{{item.detailValue}}
</view>
<view class="bfbname">
{{item.detailCode}}
</view>
</view>
</view>
</view>
<view class="qst">
<view class="qsttitle">
重要污染物趋势图
</view>
<view class="search">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="uni-input">{{array[index]}}
<image src="../../static/data_btn_sanjiao_xia.png"></image>
</view>
</picker>
</view>
<view class="qstcontent">
<uni-ec-canvas :ec="ec" canvas-id="multi-charts-pie"></uni-ec-canvas>
</view>
</view>
<view class="znyj">
<view class="znyj_top">
<view class="znyjtop_left">
智能预警
</view>
<view class="znyjtop_right">
预警次数 <span class="numbers">{{cutMoneyFiter(total) || 0}}</span>
</view>
</view>
<view class="sxbox">
<view class="leftsxbox">
<picker @change="bindPickerChange1" :value="index1" :range="array1">
<view class="uni-input1">{{array1[index1]}}
<image src="../../static/data_btn_sanjiao_xia.png"></image>
</view>
</picker>
</view>
<view class="rightsxbox">
<picker mode="date" fields="year" :value="date" :start="startDate" :end="endDate"
@change="bindDateChange">
<view class="uni-input2">{{date}}
<image src="../../static/data_btn_sanjiao_xia.png"></image>
</view>
</picker>
</view>
</view>
<view class="list_item_bot">
<view class="scrolltop">
<view class="tabitem" v-for="(item,index) in tabList" :key="index">
{{item}}
</view>
</view>
<scroll-view style="height: 530rpx;" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<view class="lists_item" v-for="(item,index) in list" :key="index">
<block>
<view class="jczbs" v-if="item.stationName">
{{item.stationName}}
</view>
<view class="jczbs" v-else></view>
</block>
<block>
<view class="zbz" v-if="item.alertContent">
{{item.alertContent[0].name}}
</view>
<view class="zbz" v-else></view>
</block>
<block>
<view class="zbzs" v-if="item.alertContent">
{{item.alertContent[0].val}}{{item.alertContent[0].unit}}
</view>
<view class="zbzs" v-else></view>
</block>
<block>
<view class="sbsj" v-if="item.datetime">
{{item.datetime}}
</view>
<view class="sbsj" v-else></view>
</block>
</view>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
</view>
<view class="pagebot">
</view>
</view>
</template>
<script>
import uniEcCanvas from '../../components/uni-ec-canvas/uni-ec-canvas.vue'
import * as echarts from '../../components/uni-ec-canvas/echarts.js'
export default {
components: {
uniEcCanvas,
},
data() {
return {
height: 0,
scorllheight: 0,
zt: '',
date: new Date().getFullYear(),
array: [],
index: '',
index1: '',
array1: [],
arrays: [],
list: [],
tabList: ['站点名称', '告警指标', '指标值','告警时间'],
pjlist: [],
ec: {
option: {
title: {
subtext: '(单位mg/l)'
},
grid: {
top: "45",
left: "5",
bottom: "5",
right: "25",
containLabel: true,
},
tooltip: {
trigger: 'axis',
position: [20, 20],
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
icon: 'roundRect',
itemHeight: 10,
itemWidth: 10,
right: '10%',
top: '10%',
textStyle: {
//
fontSize: 10,
},
data: []
},
color: [],
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: [{
type: 'category',
boundaryGap: false,
axisLabel: {
//x
show: true,
interval: 0, //使x
color: '#999999',
},
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月',
'12月'
],
}],
yAxis: [{
type: 'value'
}],
series: []
}
},
pjnr: '',
pageNo: 1,
pageSize: 9,
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus: 'more', //more-loading-nomore-
isLoadMore: false, //
show: false,
show1: false,
top: 0,
total: 0,
yearStr: null,
stationName1: '',
stationCode1: null,
stationCode: '',
arrays1:[],
zxtdata:[]
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale //px rpx
console.log(this.height, ktxStatusHeight, navigationHeight)
this.scorllheight = this.height
}
});
this.index = 0
this.index1 = 0
this.getpj()
this.getazsurvMulchRecord()
this.getyjList()
this.gettj()
},
methods: {
//
getazsurvMulchRecord() {
this.array = []
this.arrays = []
this.array1 = ['全部监测站点', ]
this.arrays1 = [
{
label:'全部监测站点',
value:''
}
]
this.$http.get('/applet/survStationInfo/list').then(res => {
for (var i = 0; i < res.data.data.length; i++) {
this.arrays.push({
label: res.data.data[i].stationName,
value: res.data.data[i].stationCode
})
this.arrays1.push({
label: res.data.data[i].stationName,
value: res.data.data[i].stationCode
})
this.array.push(res.data.data[i].stationName)
this.array1.push(res.data.data[i].stationName)
// console.log(this.array,this.array1)
}
})
},
//
getyjList() {
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.stationCode = this.stationCode1
params.yearStr = this.yearStr
uni.showLoading({
title: '加载中'
});
this.list = []
this.$http.get('/applet/wxclient/alertRecord', {
params: params
}).then(res => {
if (res.data.code == 0) {
var data = res.data.data.records
for (var i = 0; i < data.length; i++) {
data[i].times = data[i].alertTime.replace(" ", ":").replace(/\:/g, "-").split("-");
data[i].nian = data[i].times[0];
data[i].yue = data[i].times[1] - 1;
data[i].ri = data[i].times[2];
data[i].shi = data[i].times[3];
data[i].fen = data[i].times[4];
data[i].miao = data[i].times[5];
data[i].datetime = data[i].yue + '-' + data[i].ri + ' ' + data[i].shi + ':' + data[i]
.fen
if(data[i].alertContent.indexOf('监测数据名称:') != -1){
data[i].alertContent = data[i].alertContent.replace('监测数据名称:','')
}
}
this.list = this.list.concat(data)
this.total = res.data.data.total
if (res.data.data.total != 0) {
this.allNum = Number(res.data.data.total) / Number(this.pageSize) + '';
console.log(this.allNum, '总页数')
if (this.allNum.indexOf('.') == -1) {
this.allNum = this.allNum;
console.log(this.allNum, 'if')
} else {
this.allNum = parseInt(Number(this.allNum) + 1);
console.log(this.allNum, 'else')
}
console.log(this.pageNo, this.allNum, '156156')
if (this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus = 'nomore'
console.log(this.isLastpage, 'true', 'nomore')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage, 'false')
}
} else {
this.isLastpage = true;
this.loadStatus = 'nomore'
}
}
uni.hideLoading();
this.isRefresher = false
})
},
//
lower() {
console.log("最后一页了,取消下拉功能");
//
if (this.isLastpage) {
return
}
clearInterval(this.intervalId);
var num = 1;
this.intervalId = setInterval(() => {
num = num + 1;
}, 1000)
console.log(this.intervalId, num)
this.pageNo = this.pageNo + 1;
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.stationCode = this.stationCode1
params.yearStr = this.yearStr
this.$http.get('/applet/wxclient/alertRecord', {
params: params
}).then(res => {
if (res.data.code == 0) {
var data = res.data.data.records
for (var i = 0; i < data.length; i++) {
data[i].times = data[i].alertTime.replace(" ", ":").replace(/\:/g, "-").split("-");
data[i].nian = data[i].times[0];
data[i].yue = data[i].times[1] - 1;
data[i].ri = data[i].times[2];
data[i].shi = data[i].times[3];
data[i].fen = data[i].times[4];
data[i].miao = data[i].times[5];
data[i].datetime = data[i].yue + '-' + data[i].ri + ' ' + data[i].shi + ':' + data[i]
.fen
if(data[i].alertContent.indexOf('监测数据名称:') != -1){
data[i].alertContent = data[i].alertContent.replace('监测数据名称:','')
}
}
this.list = this.list.concat(data)
if (res.data.data.total != 0) {
if (this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus = 'nomore'
console.log(this.isLastpage, 'true')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage, 'false')
}
} else {
this.isLastpage = true;
this.loadStatus = 'nomore'
}
}
})
},
//
getpj() {
this.$http.post('/applet/wxclient/displayInfo?infoType=' + 'effect_assess').then(res => {
let data = res.data.data.effect_assess.detailList
this.pjlist = data
for (var i = 0; i < data.length; i++) {
if (data[i].detailCode == '综合评价') {
this.pjnr = data[i].detailValue
}
}
})
},
// 线
gettj() {
if (!this.stationCode) {
this.stationCode = 'S_1'
}
this.$http.post('/applet/wxclient/getPplutionSummry?stationCode=' + this.stationCode).then(res => {
this.zxtdata = res.data.data[0]
console.log(this.array[this.index],'弄哦文')
this.ec.option.legend.data = ['总磷', '总氮','硝态氮']
this.ec.option.color = ['#19D58A', '#FFC53B', '#3BA0FF']
this.ec.option.series = [
{
name: '总磷',
type: 'line',
stack: 'Total1',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(25, 213, 138, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
},
emphasis: {
focus: 'series'
},
data: this.zxtdata.TPSummry
},
{
name: '总氮',
type: 'line',
stack: 'Total2',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(255, 197, 59, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
},
emphasis: {
focus: 'series'
},
data: this.zxtdata.TNSummry
},
{
name: '硝态氮',
type: 'line',
stack: 'Total3',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(59, 160, 255, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
},
emphasis: {
focus: 'series'
},
data: this.zxtdata.NOSummry
},
]
if(this.array[this.index].indexOf('畜禽') != -1){
this.ec.option.legend.data = ['总磷', '总氮','COD','氨氮']
this.ec.option.color = ['#19D58A', '#FFC53B', '#3BA0FF','#FF3B3B']
this.ec.option.series = [
{
name: '总磷',
type: 'line',
stack: 'Total1',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(25, 213, 138, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
},
emphasis: {
focus: 'series'
},
data: this.zxtdata.TPSummry
},
{
name: '总氮',
type: 'line',
stack: 'Total2',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(255, 197, 59, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
},
emphasis: {
focus: 'series'
},
data: this.zxtdata.TNSummry
},
{
name: 'COD',
type: 'line',
stack: 'Total3',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(59, 160, 255, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
},
emphasis: {
focus: 'series'
},
data: this.zxtdata.CODSummry
},
{
name: '氨氮',
type: 'line',
stack: 'Total4',
areaStyle: { //
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(255, 59, 59, 1)' // 0%
}, {
offset: 1,
color: 'rgba(255, 255, 255, 1)' // 100%
}],
global: false // false
}
},
emphasis: {
focus: 'series'
},
data: this.zxtdata.NHSummry
},
]
}
})
},
// 线
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
this.stationName = this.array[this.index]
for (var i = 0; i < this.arrays.length; i++) {
if (this.stationName == this.arrays[i].label) {
this.stationCode = this.arrays[i].value
}
}
this.gettj()
},
//
bindPickerChange1: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index1 = e.detail.value
this.stationName1 = this.array1[this.index1]
for (var i = 0; i < this.arrays.length; i++) {
if (this.stationName1 == this.arrays1[i].label) {
this.stationCode1 = this.arrays1[i].value
}
}
if (this.stationName1 == '全部监测站点') {
this.stationCode1 = null
}
this.pageNo = 1
this.getyjList()
},
//
bindDateChange: function(e) {
this.yearStr = e.detail.value
this.date = e.detail.value
this.pageNo = 1
this.getyjList()
},
}
}
</script>
<style lang="scss">
page {
// height: 100%;
background-color: #0f6efe;
}
.container {
// height: 100%;
padding: 0 32rpx;
box-sizing: border-box;
overflow-y: scroll;
overflow-x: hidden;
}
.bgimg {
width: 100%;
height: 2022rpx;
}
.pj {
background: #FFFFFF;
border-radius: 34rpx;
padding: 41rpx 31rpx 33rpx;
}
.pjtitle {
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: bold;
color: #2F3841;
margin-bottom: 31rpx;
}
.ybecharts {
width: 100%;
height: 279rpx;
margin-bottom: 38rpx;
display: flex;
justify-content: center;
position: relative;
}
.ybecharts image {
// position: absolute;
width: 90%;
height: 100%;
}
.ybechartstext {
color: #2DC37B;
font-size: 60rpx;
position: absolute;
bottom: 13rpx;
left: 50%;
transform: translateX(-50%);
}
.bot3 {
width: 100%;
display: flex;
justify-content: space-between;
}
.bot3_left {
border-right: 2rpx solid #E6E9EF;
display: flex;
flex-direction: column;
align-items: center;
width: 33%;
}
.bot3_left:last-child {
border: none;
}
.bfb {
font-size: 42rpx;
font-family: DIN Next LT Pro;
font-weight: 500;
color: #184C9A;
}
.bfbname {
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #9CA9BE
}
.qst {
background: #FFFFFF;
border-radius: 34rpx;
padding-top: 43rpx;
padding-bottom: 34rpx;
margin-top: 26rpx;
}
.qsttitle {
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: bold;
color: #2F3841;
padding-left: 33rpx;
}
.qstcontent {
height: 400rpx;
width: 98%;
padding-left: 20rpx;
}
.uni-ec-canvas {
width: 100%;
height: 500rpx;
}
.search {
height: 72rpx;
padding: 0 32rpx 0;
margin-top: 32rpx;
}
.uni-input {
width: 100%;
height: 72rpx;
font-size: 28rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #667482;
background: #F6F6F6;
border-radius: 16rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 22rpx 25rpx;
}
.uni-input image {
width: 44rpx;
height: 44rpx;
}
.znyj {
padding: 43rpx 31rpx 43rpx 32rpx;
background: #FFFFFF;
border-radius: 34rpx;
margin-top: 26rpx;
}
.znyj_top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 32rpx;
}
.znyjtop_left {
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: bold;
color: #2F3841;
}
.znyjtop_right {
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #B3C1D1;
}
.numbers {
font-size: 34rpx;
font-family: DIN Next LT Pro;
font-weight: 500;
color: #FF4343;
margin-left: 9rpx;
margin-right: 11rpx;
}
.sxbox {
width: 100%;
display: flex;
justify-content: space-between;
}
.leftsxbox {
width: 60%;
}
.rightsxbox {
width: 35%;
}
.uni-input1 {
width: 100%;
height: 72rpx;
background: #F6F6F6;
border-radius: 16rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #667482;
padding: 22rpx 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.uni-input1 image {
width: 44rpx;
height: 44rpx;
}
.uni-input2 {
width: 100%;
height: 72rpx;
background: #F6F6F6;
border-radius: 16rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #667482;
padding: 22rpx 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.uni-input2 image {
width: 44rpx;
height: 44rpx;
}
.scrolltop {
padding: 34rpx 0rpx 16rpx 0rpx;
display: flex;
justify-content: space-between;
border-bottom: 2rpx solid #F6F8FB;
}
.tabitem {
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
display: inline-block;
padding-bottom: 26rpx;
}
.tabitem:first-child{
width: 31%;
// text-align: center
}
.tabitem:nth-child(2){
width: 27%;
// text-align: center
}
.tabitem:nth-child(3){
width: 19%;
// text-align: center
}
.tabitem:nth-child(4){
flex:1
// text-align: center
}
.scroll-Y {
box-sizing: border-box;
}
.lists_item {
padding-top: 35rpx;
box-sizing: border-box;
display: flex;
}
// .lists_item:first-child {
// padding-top: 0;
// }
.jczbs {
width: 32%;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// text-align: center
}
.zbz {
width: 27%;
font-size: 24rpx;
font-family: DIN Next LT Pro;
font-weight: 400;
padding-right: 10rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// text-align: center
}
.sbsj {
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
flex: 1;
// text-align: center
// text-align: right;
}
.szqss {
width: 24rpx;
}
.zbzs {
width: 19%;
font-size: 24rpx;
font-family: DIN Next LT Pro;
font-weight: 400;
padding-right: 10rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// text-align: center
}
.load {
// height: 50rpx;
// line-height: 50rpx;
text-align: center;
color: #c6c6c6;
}
.pagebot {
height: 100rpx;
}
</style>

View File

@ -0,0 +1,444 @@
<template>
<view class="container">
<view class="form">
<view class="form_item">
<view class="form_top">
养殖场名称:
</view>
<view class="form_bot">
<input type="text" placeholder="请输入养殖场名称" v-model="details.farmName">
</view>
</view>
<view class="form_item">
<view class="form_top">
养殖品种:
</view>
<view class="form_bot">
<uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change1" selectedColor="#47c693" mode="tag" v-model="details.breedVariety" :localdata="hobby"></uni-data-checkbox>
</view>
</uni-section>
</view>
</view>
<view class="form_item">
<view class="form_top">
现有存栏:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入现有存栏" v-model="details.breedScale" style="width: 85%;">
<span class="dw"> / </span>
</view>
</view>
<view class="form_item">
<view class="form_top">
年份:
</view>
<view class="form_bot">
<picker mode="date" fields="year" :value="date" :start="startDate" :end="endDate" @change="bindDateChangeyear">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!details.countYear">请选择年份</view>
<view class="uni-input" v-else>{{details.countYear}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
固体粪便产生量:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入固体粪便产生量" v-model="details.fecesQuantity" style="width: 85%;">
<span class="dw"> / </span>
</view>
</view>
<view class="form_item">
<view class="form_top">
液体产生量:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入液体产生量" v-model="details.urineQuantity" style="width: 85%;">
<span class="dw">立方米</span>
</view>
</view>
<view class="form_item">
<view class="form_top">
混合产生量:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入混合产生量" v-model="details.mixQuantity" style="width: 85%;">
<span class="dw">立方米</span>
</view>
</view>
<view class="form_item">
<view class="form_top">
治污模式:
</view>
<view class="form_bot">
<uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change2" selectedColor="#47c693" mode="tag" v-model="details.controlMode" :localdata="hobby2"></uni-data-checkbox>
</view>
</uni-section>
</view>
</view>
<view class="form_item">
<view class="form_top">
利用模式:
</view>
<view class="form_bot">
<uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change3" selectedColor="#47c693" mode="tag" v-model="details.useMode" :localdata="hobby3"></uni-data-checkbox>
</view>
</uni-section>
</view>
</view>
<view class="form_item">
<view class="form_top">
收入金额:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入收入金额" v-model="details.chargeAmount" style="width: 85%;">
<span class="dw"></span>
</view>
</view>
<view class="bz_item">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea v-model="details.sNote" style="width: 100%;"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="tosubmit()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
export default{
data(){
return{
array:['生猪1号养殖场','生猪2号养殖场','生猪3号养殖场','生猪4号养殖场'],
details:{
breedScale: "",
breedVariety: "",
chargeAmount: "",
controlMode: "",
countYear: "",
createTime: "",
createdBy: "",
entId: "",
entName: "",
farmName: "",
fecesQuantity: "",
id: "",
isDel: 0,
mixQuantity: "",
reVision: 0,
sNote: "",
tenantId: "",
updatedBy: "",
updatedTime: "",
urineQuantity: "",
useMode: "",
},
index:'',
date:'',
year:'',
number:'',
tag:'',
hobby: [],
hobby2: [],
hobby3: [],
reload:'true'
}
},
onLoad() {
},
onShow() {
this.getazsurvMulchRecord()
this.getazsurvMulchRecord1()
this.getazsurvMulchRecord2()
},
methods:{
//
getazsurvMulchRecord(){
this.hobby = []
let params = {}
params.dictCode = 'dict_breed_type'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
console.log(this.hobby)
}
})
},
//
getazsurvMulchRecord1(){
this.hobby2 = []
let params = {}
params.dictCode = 'surv_control_mode'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby2.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
}
})
},
//
getazsurvMulchRecord2(){
this.hobby3 = []
let params = {}
params.dictCode = 'surv_use_mode'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby3.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
console.log(this.hobby3)
}
})
},
//
bindDateChangeyear(e){
this.details.countYear = e.detail.value
},
//
change1(e){
console.log(e)
this.details.breedVariety = e.detail.value
},
//
change2(e){
console.log(e)
this.details.controlMode = e.detail.value
},
//
change3(e){
console.log(e)
this.details.useMode = e.detail.value
},
//
tosubmit(){
if(!this.details.farmName){
uni.showToast({
title: "请输入养殖场名称",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.breedVariety){
uni.showToast({
title: "请选择养殖品种",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.breedScale){
uni.showToast({
title: "请输入现有存栏",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.countYear){
uni.showToast({
title: "请选择年份",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.fecesQuantity){
uni.showToast({
title: "请输入固体粪便产生量",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.urineQuantity){
uni.showToast({
title: "请输入液体产生量",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.mixQuantity){
uni.showToast({
title: "请输入混合产生量",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.controlMode){
uni.showToast({
title: "请选择治污模式",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.useMode){
uni.showToast({
title: "请选择利用模式",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.chargeAmount){
uni.showToast({
title: "请输入收入金额",
icon: 'none',
duration: 2000
})
return
}
this.$http.post('/applet/survFecesLedger/add',this.details).then(res=>{
uni.showLoading({
title: '正在提交...'
});
if(res.data.code == 0){
uni.hideLoading();
uni.navigateBack()
let pages = getCurrentPages();
let prevPage = pages[ pages.length - 2 ];
prevPage.$vm.reload = this.reload;
}
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: white;
}
.form{
padding: 0 30rpx;
}
.form_item{
padding-top: 33rpx;
padding-bottom: 25rpx;
border-bottom: 1rpx solid #e6e6e6;
}
.form_top{
margin-bottom: 26rpx;
font-weight: bold;
}
.form_bot{
position: relative;
}
.dates{
display: flex;
align-items: center;
justify-content: space-between;
}
.dateimg{
height: 32rpx;
width: 32rpx;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.dw{
color: #2ac066;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgList image{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgList image:nth-child(4n){
margin-right: 0rpx;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz{
margin-left: 30rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
border: 1rpx solid #ececec;
border-radius: 10rpx;
padding: 16rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.pagebot{
height: 200rpx;
}
.text {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.uni-px-5 {
padding-left: 10px;
padding-right: 10px;
}
.uni-pb-5 {
padding-bottom: 10px;
}
.checkpeople{
width: 187rpx;
height: 57rpx;
border: 1rpx dashed #0472e3;
line-height: 57rpx;
text-align: center;
color: #0472e3;
}
.dw{
color: #2ac066;
flex: 1;
text-align: right;
}
</style>

View File

@ -0,0 +1,255 @@
<template>
<view class="container">
<view class="form">
<view class="form_item" v-if="details.farmName">
<view class="left">养殖场名称:</view>
<view class="nr">{{details.farmName}}</view>
</view>
<view class="form_item" v-if="details.breedVariety">
<view class="left">养殖品种:</view>
<view class="nr"><block v-for="(dict,i) in yzlist" :key="i"><span v-if="details.breedVariety == dict.itemValue">{{dict.itemText}}</span></block></view>
</view>
<view class="form_item" v-if="details.breedScale">
<view class="left">现有存栏:</view>
<view class="nr">{{details.breedScale}}</view>
</view>
<view class="form_item" v-if="details.countYear">
<view class="left">年份:</view>
<view class="nr">{{details.countYear}}</view>
</view>
<view class="form_item" v-if="details.fecesQuantity">
<view class="left">固体粪便产生量:</view>
<view class="nr">{{details.fecesQuantity}}/</view>
</view>
<view class="form_item" v-if="details.urineQuantity">
<view class="left">液体产生量:</view>
<view class="nr">{{details.urineQuantity}}立方米</view>
</view>
<view class="form_item" v-if="details.farmName">
<view class="left">混合产生量:</view>
<view class="nr">{{details.mixQuantity}}立方米</view>
</view>
<view class="form_item" v-if="details.controlMode1">
<view class="left">治污模式:</view>
<view class="nr">{{details.controlMode1}}</view>
</view>
<view class="form_item" v-if="details.useMode1">
<view class="left">利用模式:</view>
<view class="nr">{{details.useMode1}}</view>
</view>
<view class="form_item" v-if="details.chargeAmount">
<view class="left">收入金额:</view>
<view class="nr">{{details.chargeAmount}}</view>
</view>
<view class="bz_item" v-if="details.sNote">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea style="width: 100%;" v-model="details.sNote" placeholder="请输入备注" disabled="true"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="toback()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
export default{
data(){
return{
details:{
breedScale: "",
breedVariety: "",
chargeAmount: "",
controlMode: "",
countYear: "",
createTime: "",
createdBy: "",
entId: "",
entName: "",
farmName: "",
fecesQuantity: "",
id: "",
isDel: 0,
mixQuantity: "",
reVision: 0,
sNote: "",
tenantId: "",
updatedBy: "",
updatedTime: "",
urineQuantity: "",
useMode: "",
breedVariety1:'',
controlMode1:'',
useMode1:''
},
index:'',
date:'',
year:'',
number:'',
tag:'',
hobby: [],
hobby2: [],
hobby3: [],
yzlist:[]
}
},
onLoad(options) {
this.details = JSON.parse(decodeURIComponent(options.item));
},
onShow() {
this.getazsurvMulchRecord()
this.getazsurvMulchRecord1()
this.getazsurvMulchRecord2()
},
methods:{
//
getazsurvMulchRecord(){
this.hobby = []
let params = {}
params.dictCode = 'dict_breed_type'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
this.yzlist = res.data.data
for(var i=0;i<res.data.data.length;i++){
this.hobby.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
console.log(this.hobby)
}
})
},
//
getazsurvMulchRecord1(){
this.hobby2 = []
let params = {}
params.dictCode = 'surv_control_mode'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby2.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
}
for(var i=0;i<this.hobby2.length;i++){
if(this.details.controlMode){
if(this.details.controlMode == this.hobby2[i].value){
this.details.controlMode1 = this.hobby2[i].itemText
}
}
}
})
},
//
getazsurvMulchRecord2(){
this.hobby3 = []
let params = {}
params.dictCode = 'surv_use_mode'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby3.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
console.log(this.hobby3)
}
for(var i=0;i<this.hobby3.length;i++){
if(this.details.useMode){
if(this.details.useMode == this.hobby3[i].value){
this.details.useMode1 = this.hobby3[i].itemText
}
}
}
})
},
toback(){
uni.navigateBack({
delta:1
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: #fff;
}
.form{
padding: 0 30rpx;
}
.form_item{
display: flex;
justify-content: space-between;
padding: 30rpx 0rpx;
border-bottom:1rpx solid #e4e4e4;
}
.left{
font-weight: bold;
}
.nr{
flex: 1;
color: #767676;
padding-left: 16rpx;
text-align: right;
}
.dw{
color: greenyellow;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgList image{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgList image:nth-child(4n){
margin-right: 0rpx;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 20rpx;
}
.bz{
margin-left: 30rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.dw{
margin-left: 5rpx;
}
.pagebot{
height: 200rpx;
}
</style>

View File

@ -0,0 +1,445 @@
<template>
<view class="container">
<view class="form">
<view class="form_item">
<view class="form_top">
养殖场名称:
</view>
<view class="form_bot">
<input type="text" placeholder="请输入养殖场名称" v-model="details.farmName">
</view>
</view>
<view class="form_item">
<view class="form_top">
养殖品种:
</view>
<view class="form_bot">
<uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change1" selectedColor="#47c693" mode="tag" v-model="details.breedVariety" :localdata="hobby"></uni-data-checkbox>
</view>
</uni-section>
</view>
</view>
<view class="form_item">
<view class="form_top">
现有存栏:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入现有存栏" v-model="details.breedScale" style="width: 85%;">
<span class="dw"> / </span>
</view>
</view>
<view class="form_item">
<view class="form_top">
年份:
</view>
<view class="form_bot">
<picker mode="date" fields="year" :value="date" :start="startDate" :end="endDate" @change="bindDateChangeyear">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!details.countYear">请选择年份</view>
<view class="uni-input" v-else>{{details.countYear}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
固体粪便产生量:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入固体粪便产生量" v-model="details.fecesQuantity" style="width: 85%;">
<span class="dw"> / </span>
</view>
</view>
<view class="form_item">
<view class="form_top">
液体产生量:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入液体产生量" v-model="details.urineQuantity" style="width: 85%;">
<span class="dw">立方米</span>
</view>
</view>
<view class="form_item">
<view class="form_top">
混合产生量:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入混合产生量" v-model="details.mixQuantity" style="width: 85%;">
<span class="dw">立方米</span>
</view>
</view>
<view class="form_item">
<view class="form_top">
治污模式:
</view>
<view class="form_bot">
<uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change2" selectedColor="#47c693" mode="tag" v-model="details.controlMode" :localdata="hobby2"></uni-data-checkbox>
</view>
</uni-section>
</view>
</view>
<view class="form_item">
<view class="form_top">
利用模式:
</view>
<view class="form_bot">
<uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change3" selectedColor="#47c693" mode="tag" v-model="details.useMode" :localdata="hobby3"></uni-data-checkbox>
</view>
</uni-section>
</view>
</view>
<view class="form_item">
<view class="form_top">
收入金额:
</view>
<view class="form_bot" style="display: flex;">
<input type="number" placeholder="请输入收入金额" v-model="details.chargeAmount" style="width: 85%;">
<span class="dw"></span>
</view>
</view>
<view class="bz_item">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea v-model="details.sNote" style="width: 100%;"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="tosubmit()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
export default{
data(){
return{
array:['生猪1号养殖场','生猪2号养殖场','生猪3号养殖场','生猪4号养殖场'],
details:{
breedScale: "",
breedVariety: "",
chargeAmount: "",
controlMode: "",
countYear: "",
createTime: "",
createdBy: "",
entId: "",
entName: "",
farmName: "",
fecesQuantity: "",
id: "",
isDel: 0,
mixQuantity: "",
reVision: 0,
sNote: "",
tenantId: "",
updatedBy: "",
updatedTime: "",
urineQuantity: "",
useMode: "",
},
index:'',
date:'',
year:'',
number:'',
tag:'',
hobby: [],
hobby2: [],
hobby3: [],
reload:'true'
}
},
onLoad(options) {
this.details = JSON.parse(decodeURIComponent(options.item));
},
onShow() {
this.getazsurvMulchRecord()
this.getazsurvMulchRecord1()
this.getazsurvMulchRecord2()
},
methods:{
//
getazsurvMulchRecord(){
this.hobby = []
let params = {}
params.dictCode = 'dict_breed_type'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
console.log(this.hobby)
}
})
},
//
getazsurvMulchRecord1(){
this.hobby2 = []
let params = {}
params.dictCode = 'surv_control_mode'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby2.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
}
})
},
//
getazsurvMulchRecord2(){
this.hobby3 = []
let params = {}
params.dictCode = 'surv_use_mode'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby3.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
console.log(this.hobby3)
}
})
},
//
bindDateChangeyear(e){
this.details.countYear = e.detail.value
},
//
change1(e){
console.log(e)
this.details.breedVariety = e.detail.value
},
//
change2(e){
console.log(e)
this.details.controlMode = e.detail.value
},
//
change3(e){
console.log(e)
this.details.useMode = e.detail.value
},
//
tosubmit(){
if(!this.details.farmName){
uni.showToast({
title: "请输入养殖场名称",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.breedVariety){
uni.showToast({
title: "请选择养殖品种",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.breedScale){
uni.showToast({
title: "请输入现有存栏",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.countYear){
uni.showToast({
title: "请选择年份",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.fecesQuantity){
uni.showToast({
title: "请输入固体粪便产生量",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.urineQuantity){
uni.showToast({
title: "请输入液体产生量",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.mixQuantity){
uni.showToast({
title: "请输入混合产生量",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.controlMode){
uni.showToast({
title: "请选择治污模式",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.useMode){
uni.showToast({
title: "请选择利用模式",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.chargeAmount){
uni.showToast({
title: "请输入收入金额",
icon: 'none',
duration: 2000
})
return
}
this.$http.post('/applet/survFecesLedger/edit',this.details).then(res=>{
uni.showLoading({
title: '正在提交...'
});
if(res.data.code == 0){
uni.hideLoading();
uni.navigateBack()
let pages = getCurrentPages();
let prevPage = pages[ pages.length - 2 ];
prevPage.$vm.reload = this.reload;
}
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: white;
}
.form{
padding: 0 30rpx;
}
.form_item{
padding-top: 33rpx;
padding-bottom: 25rpx;
border-bottom: 1rpx solid #e6e6e6;
}
.form_top{
margin-bottom: 26rpx;
font-weight: bold;
}
.form_bot{
position: relative;
}
.dates{
display: flex;
align-items: center;
justify-content: space-between;
}
.dateimg{
height: 32rpx;
width: 32rpx;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.dw{
color: #2ac066;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgList image{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgList image:nth-child(4n){
margin-right: 0rpx;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz{
margin-left: 30rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
border: 1rpx solid #ececec;
border-radius: 10rpx;
padding: 16rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.pagebot{
height: 200rpx;
}
.text {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.uni-px-5 {
padding-left: 10px;
padding-right: 10px;
}
.uni-pb-5 {
padding-bottom: 10px;
}
.checkpeople{
width: 187rpx;
height: 57rpx;
border: 1rpx dashed #0472e3;
line-height: 57rpx;
text-align: center;
color: #0472e3;
}
.dw{
color: #2ac066;
flex: 1;
text-align: right;
}
</style>

View File

@ -0,0 +1,524 @@
<template>
<view class="container">
<scroll-view scroll-y="true" :style="{height:height + 'rpx'}" @refresherrefresh="refresherrefreshFun" @refresherpulling="refresherpullingFun" :refresher-triggered="isRefresher" refresher-enabled="true">
<view class="topcheck">
<view class="left">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="uni-input" v-if="!breedVariety1">养殖品种 <image src="../../static/xia.png"></image></view>
<view class="uni-input" v-else>{{breedVariety1}} <image src="../../static/xia.png"></image></view>
</picker>
</view>
<view class="right">
<picker mode="date" fields="year" :value="date" :start="startDate" :end="endDate" @change="bindDateChange">
<view class="uni-input" v-if="!countYear">选择年份 <image src="../../static/xia.png"></image></view>
<view class="uni-input" v-else>{{countYear}} <image src="../../static/xia.png"></image></view>
</picker>
</view>
</view>
<view class="searchbox">
<image src="../../static/meishi_icon_sousuo.png" mode=""></image>
<input class="search_input" v-model="farmName" placeholder="请输入要搜索的养殖场名称">
<view class="searchbutton" @click="changenr()">
搜索
</view>
</view>
<view class="liebiaos" v-if="List.length != 0">
<scroll-view :style="{height:scorllheight + 'rpx'}" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<view class="itembox" v-for="(item,index) in List" :key="index">
<view class="itembox_top">
<view class="itembox_lef" @click="todetails(item,index)">
<image src="../../static/fwtz.png" mode=""></image>
<view class="title">
{{item.farmName}}
</view>
</view>
<view class="caozuo" @click="caozuo(item)">
<image src="../../static/dian.png" mode=""></image>
</view>
</view>
<view class="itembox_bot" @click="todetails(item,index)">
<view class="bot_item">
<span class="nrbt">养殖品种:</span>
<block v-for="(dict,i) in yzlist" :key="i"><span v-if="item.breedVariety == dict.itemValue">{{dict.itemText}}</span></block>
</view>
<view class="bot_item">
<span class="nrbt">现有存栏:</span>
<span class="number">{{item.breedScale}}</span>
</view>
<view class="bot_item">
<span class="nrbt">收入金额:</span>
{{item.chargeAmount}}
</view>
</view>
</view>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
<image @click="toadd()" class="add" src="../../static/add.png" mode=""></image>
</scroll-view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default {
data() {
return {
List:[],
baseUrl:configService.apiUrl,
array:[],
index:'',
date:'',
searchValue:'',
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
height:0,
scorllheight:0,
show:false,
show1:false,
top:0,
breedScale: "",
breedVariety: "",
chargeAmount: "",
controlMode: "",
countYear: "",
createTime: "",
createdBy: "",
entId: "",
entName: "",
farmName: "",
fecesQuantity: "",
id: "",
isDel: 0,
mixQuantity: "",
reVision: 0,
sNote: "",
tenantId: "",
updatedBy: "",
updatedTime: "",
urineQuantity: "",
breedVariety1:'',
useMode: "",
deleteUrl:'/applet/survFecesLedger/delete',
arrays:[],
isRefresher: false, //
pageNo:1,
pageSize:4,
reload:'',
yzlist:[]
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 182
}
});
this.getList()
},
onShow() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 182
}
});
let pages = getCurrentPages();
let currPage = pages[pages.length - 1]; //
this.reload = currPage.data.reload
console.log(this.reload,'Ge')
if(this.reload){
this.farmName = ''
this.breedVariety = ''
this.breedVariety1 = ''
this.countYear = ''
this.pageNo = 1
this.getList()
this.reload = ''
}
this.getazsurvMulchRecord()
},
methods:{
//
getazsurvMulchRecord(){
this.array = []
let params = {}
params.dictCode = 'dict_breed_type'
this.$http.get('/applet/Dict/getDictByType',{params:params}).then(res=>{
this.yzlist = res.data.data
for(var i=0;i<res.data.data.length;i++){
this.arrays.push({
text:res.data.data[i].itemText,
value:res.data.data[i].itemValue
})
this.array.push(res.data.data[i].itemText)
console.log(this.array)
}
})
},
//
refresherrefreshFun() {
this.farmName = ''
this.breedVariety = ''
this.breedVariety1 = ''
this.countYear = ''
this.pageNo = 1
this.getList()
},
//
refresherpullingFun() {
this.isRefresher= true
},
//
getList(){
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.farmName = this.farmName
params.countYear = this.countYear
params.breedVariety = this.breedVariety
uni.showLoading({
title: '加载中'
});
this.List = []
this.$http.get('/applet/survFecesLedger/list',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
if(res.data.data.total != 0){
this.allNum = Number(res.data.data.total)/Number(this.pageSize)+'';
console.log(this.allNum,'总页数')
if(this.allNum.indexOf('.') == -1) {
this.allNum = this.allNum;
console.log(this.allNum,'if')
} else {
this.allNum = parseInt(Number(this.allNum)+1);
console.log(this.allNum,'else')
}
console.log(this.pageNo,this.allNum,'156156')
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true','nomore')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
uni.hideLoading();
this.isRefresher= false
})
},
//
lower() {
console.log("最后一页了,取消下拉功能");
//
if (this.isLastpage) {
return
}
clearInterval(this.intervalId);
var num = 1;
this.intervalId = setInterval(() => {
num = num+1;
},1000)
console.log(this.intervalId,num)
this.pageNo = this.pageNo + 1;
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.farmName = this.farmName
params.countYear = this.countYear
params.breedVariety = this.breedVariety
this.$http.get('/applet/survFecesLedger/list',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
if(res.data.data.total != 0){
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
})
},
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
this.breedVariety = this.arrays[this.index].value
this.breedVariety1 = this.arrays[this.index].text
this.pageNo = 1
this.getList()
},
bindDateChange: function(e) {
this.countYear = e.detail.value
this.pageNo = 1
this.getList()
},
//
changenr(){
this.pageNo = 1
this.getList()
},
//
todetails(item,index){
uni.navigateTo({
url:'/packDetail/pages/fwtz/detail?item=' + encodeURIComponent(JSON.stringify(item))
})
},
//
toadd(){
uni.navigateTo({
url:'/packDetail/pages/fwtz/add'
})
},
//
caozuo(item){
console.log(item)
var that = this
uni.showActionSheet({
itemList: ['编辑', '删除'],
success: function (res) {
console.log('选中了第' + (res.tapIndex + 1) + '个按钮');
if((res.tapIndex + 1) == 1){
uni.navigateTo({
url:'/packDetail/pages/fwtz/edit?item='+ encodeURIComponent(JSON.stringify(item))
})
}else{
uni.showModal({
title: '提示',
content: '是否删除数据?',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
console.log(item.id,1)
that.$http.delete(that.deleteUrl+'?id='+item.id).then(res =>{
if(res.data.code == 0){
uni.showToast({
title: '删除成功',
icon:'success',
duration: 2000
});
that.pageNo = 1
that.farmName = ''
that.breedVariety = ''
that.breedVariety1 = ''
that.countYear = ''
that.getList()
}
})
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
},
fail: function (res) {
console.log(res.errMsg);
}
});
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
}
.container{
height: 100%;
}
.topcheck{
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1rpx solid #ededed;
background-color: white;
}
.left{
width: 50%;
display: flex;
justify-content: center;
}
.right{
width: 50%;
border-left: 4rpx solid #ededed;
display: flex;
justify-content: center;
}
.searchbox{
padding: 20rpx 30rpx;
background-color: white;
position: relative;
display: flex;
justify-content: space-between;
}
.search_input{
border: none;
height: 60rpx;
width: 86%;
font-size: 24rpx;
border-radius: 30rpx;
background-color: #F6F6F6;
padding-left: 50rpx;
}
.searchbox image{
width: 32rpx;
height: 32rpx;
position: absolute;
left: 40rpx;
top: 35%;
z-index: 99;
}
.searchbutton{
width: 10%;
height: 60rpx;
font-size: 26rpx;
text-align: center;
line-height: 60rpx;
}
.itembox{
background-color: white;
padding: 30rpx;
margin-top: 20rpx;
}
.itembox:first-child{
margin-top: 0;
}
.uni-input{
display: flex;
align-items: center;
}
.uni-input image{
height: 12rpx;
width: 24rpx;
margin-left: 5rpx;
}
.itembox_top{
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 30rpx;
border-bottom: 2rpx solid #e4e4e4;
}
.itembox_lef image{
width: 40rpx;
height: 40rpx;
margin-right: 14rpx;
}
.itembox_lef{
display: flex;
align-items: center;
font-weight: 500;
width: 70%;
}
.caozuo{
height: 100%;
display: flex;
align-items: center;
flex:1;
justify-content: flex-end;
}
.caozuo image{
width: 7rpx;
height: 29rpx;
z-index: 99;
}
.bot_item{
margin-top: 30rpx;
}
.nrbt{
color: #898989;
margin-right: 10rpx;
}
.number{
// color: #ff6563;
}
.numbers{
color:#26bf64;
}
.load{
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
.add{
height: 150rpx;
width: 150rpx;
position: fixed;
bottom: 100rpx;
right: 60rpx;
}
.popup{
background-color: white;
height: 100%;
width: 100%;
}
.title{
font-weight: bold;
}
.zwsj{
width: 100%;
// height: 100%;
display: flex;
padding: 60% 170rpx 0;
}
.inzwsj{
width: 100%;
}
.zwsjimg{
width: 100%;
height: 224rpx;
margin-bottom: 37rpx;
}
.zwsjtext{
width: 100%;
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #999999;
line-height: 31rpx;
text-align: center;
}
</style>

View File

@ -0,0 +1,344 @@
<template>
<view class="zai-box" v-show="login == true">
<view class="header_banner">
<view class="backs" :style="{top:CustomTop+'px'}" @click="backs">
<uni-icons type="home" color="#999" size="22"></uni-icons>
</view>
<image class="bigimg" src="../../static/dls.jpg" mode=""></image>
</view>
<view class="loginpage">
<view class="hydl">
欢迎登录
</view>
<view class="wel">
Welcome to login
</view>
<view class="pages">
<view class="cu-form-group margin-top" :class="[shape=='round'?'round':'']">
<text class="cuIcon-people margin-right-xs" style="color: #3e8eff;"></text>
<input @input="TypeInput($event)" placeholder="请输入账号名称" name="input"
v-model="userInfoLoginDTO.userName"></input>
</view>
<view class="cu-form-group margin-top" :class="[shape=='round'?'round':'']">
<text class="cuIcon-lock margin-right-xs" style="color: #3e8eff;"></text>
<input class="uni-input" placeholder="请输入登陆密码" :password="!showPassword"
v-model="userInfoLoginDTO.password"/>
</view>
<view class="padding text-center margin-top">
<button class="cu-btn bg-blue" :loading="loading" :class="[shape=='round'?'round':'']"
@click="tologins()">
<text space="emsp">{{ loading ? "登录中..." : " 登录 " }}</text>
</button>
<view class="botbq">
</view>
</view>
</view>
</view>
<!-- <view class="loginpage">
<image class="bigimg" src="../../static/dls.jpg" mode=""></image>
<view class="padding text-center margin-top">
<button class="login-btn block bg-blue lg round" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号登录</button>
<view class="botbq">
版权所有@河津市农业农村局
</view>
</view>
</view> -->
<!-- 登录加载弹窗 -->
<view class="cu-load load-modal" v-if="loading">
<!-- <view class="cuIcon-emojifill text-orange"></view> -->
<image src="https://static.jeecg.com/upload/test/login4_1595818039175.png" mode="aspectFit" class="round"></image>
<view class="gray-text">登录中...</view>
</view>
</view>
</template>
<script>
import {ACCESS_TOKEN, USER_NAME, USER_INFO} from "@/common/util/constants"
import {mapActions} from "vuex"
import configService from '@/common/service/config.service.js';
import api from "@/api/api"
export default {
data() {
return {
shape: '',//round
loading: false,
phoneNo: '',
smsCode: '',
showPassword: false, //
loginWay: 3, //1: 2
pages: 2,
smsCountDown: 0,
smsCountInterval: null,
toggleDelay: false,
version: '',
//
thirdType: "",
thirdLoginInfo: "",
thirdLoginState: false,
bindingPhoneModal: false,
login: false,
thirdUserUuid: '',
url: {
bindingThirdPhone: '/sys/thirdLogin/bindingThirdPhone'
},
code: '',
userInfoLoginDTO: {
userName: '',
password: '',
},
CustomTop: 0,
};
},
onLoad() {
this.CustomTop = this.Custom.top
},
onShow() {
var that = this
uni.login({
success: function (res) {
console.log(res.code)
that.code = res.code
let params = {}
params.jsCode = that.code
console.log(params, 152)
api.wxlogin(params).then(res => {
console.log(res, 165)
if (res.data.code == 0) {
let userInfo = res.data.data;
uni.setStorageSync('third_session', userInfo.thirdSession);
console.log(that.login, '状态')
if (userInfo.id) {
that.login = false
uni.reLaunch({
url: '/pages/index/index'
})
} else if (!userInfo.id) {
that.login = true
}
}
})
}
});
},
methods: {
backs() {
uni.switchTab({
url: '/pages/index/index'
})
},
getPhoneNumber(e) {
this.code = e.detail.code
var json = {
"code": this.code
}
this.$http.post('/applet/userInfo/ma/phone/login', json).then(res => {
//
if (res.data.code == 0) {
// uni.setStorageSync('App-Token',res.token)
uni.setStorageSync('constant', res.data.data)
uni.reLaunch({
url: '/pages/index/index'
})
} else {
uni.removeStorageSync('third_session')
uni.removeStorageSync('constant')
}
})
},
TypeInput(e) {
console.log(e, 415)
// ;
const inputType = /[\W]/g //
this.$nextTick(function () {
this.userInfoLoginDTO.userName = e.detail.value.replace(inputType, '');
})
},
tologins() {
console.log(this.userInfoLoginDTO.password, this.userInfoLoginDTO.userName, '密码用户')
if (!this.userInfoLoginDTO.userName) {
uni.showToast({
title: '请输入账号',
icon: 'error',
duration: 2000
})
return
}
if (!this.userInfoLoginDTO.password) {
uni.showToast({
title: '请输入密码',
icon: 'error',
duration: 2000
})
return
}
this.$http.post('/applet/userInfo/logins', this.userInfoLoginDTO).then(res => {
if (res.data.code == 0) {
uni.setStorageSync('constant', res.data.data)
uni.setStorageSync('password', this.userInfoLoginDTO.password)
uni.setStorageSync('userName', this.userInfoLoginDTO.userName)
uni.reLaunch({
url: '/pages/index/index'
})
} else {
uni.removeStorageSync('constant')
uni.showToast({
title: res.data.msg,
icon: 'none',
duration: 2000
})
// this.userInfoLoginDTO.password = ''
// this.userInfoLoginDTO.userName = ''
}
})
}
}
}
</script>
<style>
.login-paddingtop {
padding-top: 100upx;
}
.zai-box {
width: 100%;
height: 100%;
}
.backs {
width: 60rpx;
height: 60rpx;
position: absolute;
background: rgba(255, 255, 255, 0.6);
text-align: center;
line-height: 60rpx;
border-radius: 50%;
left: 30rpx;
}
.header_banner {
width: 100%;
height: 800rpx;
position: absolute;
}
.bigimg {
z-index: -99;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 800rpx;
}
/* .zai-box {
padding: 0 20upx;
padding-top: 100upx;
position: relative;
} */
.zai-logo {
width: 200upx;
height: 150px;
}
.zai-title {
font-size: 58upx;
color: #000000;
text-align: center;
}
.input-placeholder, .zai-input {
color: #94afce;
}
.zai-label {
padding: 60upx 0;
text-align: center;
font-size: 30upx;
color: #a7b6d0;
}
.zai-btn {
background: #ff65a3;
color: #fff;
border: 0;
border-radius: 100upx;
font-size: 36upx;
}
.zai-btn:after {
border: 0;
}
/*按钮点击效果*/
.zai-btn.button-hover {
transform: translate(1upx, 1upx);
}
.login-btn {
width: 90%;
line-height: 98rpx;
height: 98rpx;
border-radius: 49rpx;
}
page {
background-color: white;
height: 100%;
}
.loginpage {
border-top-left-radius: 64rpx;
border-top-right-radius: 64rpx;
box-sizing: border-box;
background-color: #fff;
position: relative;
top: 500rpx;
padding: 63rpx 56rpx 0;
}
.hydl {
font-size: 40rpx;
margin-bottom: 30rpx;
font-weight: bold;
}
.wel {
color: #7e7e80;
margin-bottom: 50rpx;
}
input {
width: 100%;
height: 110rpx;
border-radius: 20rpx;
}
.cu-form-group {
background-color: #f6f7fb;
height: 110rpx;
border-radius: 20rpx;
}
.cu-btn {
width: 100%;
height: 107rpx;
font-size: 36rpx;
border-radius: 20rpx;
}
.botbq {
font-size: 28rpx;
position: fixed;
bottom: 48rpx;
left: 50%;
transform: translateX(-50%);
color: #2a2a2a;
}
.pages {
/* border-top-left-radius: 64rpx;
border-top-right-radius: 64rpx; */
width: 100%;
}
</style>

View File

@ -0,0 +1,318 @@
<template>
<view class="container">
<view class="form">
<view class="form_item">
<view class="form_top">
选择站点:
</view>
<view class="form_bot">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="dates">
<view class="uni-input" v-if="!details.stationName" style="color: #808080;">请选择监测站点</view>
<view class="uni-input" v-else>{{details.stationName}}</view>
</view>
<image class="dateimg" src="../../../static/xiala.png" mode="" style="width: 32rpx;height: 16rpx;"></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
维护内容:
</view>
<view class="form_bot">
<!-- <uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change1" selectedColor="#47c693" mode="tag" v-model="details.itemId" :localdata="hobby"></uni-data-checkbox>
</view>
</uni-section> -->
<view class="uni-textarea">
<textarea placeholder-style="color:#808080" auto-height placeholder="请输入内容" @blur="bindTextAreaBlur"/>
</view>
</view>
</view>
<view class="form_item">
<view class="form_top">
维护人:
</view>
<!-- <view class="form_bot" @click="tolist()">
<view class="checkpeople">
+ 选择维护人
</view>
</view> -->
<input type="text" placeholder="请输入运维人姓名" v-model="details.maintainPerson">
</view>
<view class="form_item">
<view class="form_top">
维护时间:
</view>
<view class="form_bot">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="bindDateChange">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!details.maintainTime">请选择维护时间</view>
<view class="uni-input" v-else>{{details.maintainTime}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="bz_item">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea v-model="details.maintainNote" style="width: 100%;"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="tosubmit()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
export default{
data(){
return{
array:[],
arrays:[],
details:{
createTime: "",
createdBy: "",
id: "",
isDel: 0,
itemId: "",
maintainData1: "",
maintainData2: "",
maintainNote: "",
maintainPerson: "",
maintainTime: "",
reVision: 0,
stationCode: "",
stationName: "",
tenantId: "",
updatedBy: "",
updatedTime: ""
},
index:'',
date:'',
year:'',
number:'',
tag:'',
hobby: [],
checkbox1: [],
reload:'true'
}
},
onLoad() {
},
onShow() {
this.getazsurvMulchRecord()
this.getazsurvMulchRecord1()
},
methods:{
//
getazsurvMulchRecord(){
this.array = []
this.arrays = []
this.$http.get('/applet/survStationInfo/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.arrays.push({
label:res.data.data[i].stationName,
value:res.data.data[i].stationCode
})
this.array.push(res.data.data[i].stationName)
console.log(this.array)
}
})
},
bindTextAreaBlur(e) {
console.log("00",e.detail.value)
this.details.maintainData1 = e.detail.value
},
//
getazsurvMulchRecord1(){
this.hobby = []
this.$http.get('/applet/survMaintainItem/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby.push({
text:res.data.data[i].maintainData1,
value:res.data.data[i].id
})
console.log(this.hobby)
}
})
},
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
this.details.stationName = this.array[this.index]
for(var i=0;i<this.arrays.length;i++){
if(this.details.stationName == this.arrays[i].label){
this.details.stationCode = this.arrays[i].value
}
}
},
bindDateChange: function(e) {
this.details.maintainTime = e.detail.value
},
//
tosubmit(){
if(!this.details.stationName){
uni.showToast({
title: "请选择站点",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.maintainData1){
uni.showToast({
title: "请填写维护内容",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.maintainPerson){
uni.showToast({
title: "请输入运维人姓名",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.maintainTime){
uni.showToast({
title: "请选择维护时间",
icon: 'none',
duration: 2000
})
return
}
this.$http.post('/applet/survMaintainRecord/add',this.details).then(res=>{
uni.showLoading({
title: '正在提交...'
});
if(res.data.code == 0){
uni.hideLoading();
uni.navigateBack()
let pages = getCurrentPages();
let prevPage = pages[ pages.length - 2 ];
prevPage.$vm.reload = this.reload;
}
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: white;
}
.form{
padding: 0 30rpx;
}
.form_item{
padding-top: 33rpx;
padding-bottom: 25rpx;
border-bottom: 1rpx solid #e6e6e6;
}
.form_top{
margin-bottom: 26rpx;
font-weight: bold;
}
.form_bot{
position: relative;
}
.dates{
display: flex;
align-items: center;
justify-content: space-between;
}
.dateimg{
height: 32rpx;
width: 32rpx;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.dw{
color: #2ac066;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgList image{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgList image:nth-child(4n){
margin-right: 0rpx;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz{
margin-left: 30rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
border: 1rpx solid #ececec;
border-radius: 10rpx;
padding: 16rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.pagebot{
height: 200rpx;
}
.text {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.uni-px-5 {
padding-left: 10px;
padding-right: 10px;
}
.uni-pb-5 {
padding-bottom: 10px;
}
.checkpeople{
width: 187rpx;
height: 57rpx;
border: 1rpx dashed #0472e3;
line-height: 57rpx;
text-align: center;
color: #0472e3;
}
</style>

View File

@ -0,0 +1,144 @@
<template>
<view class="container">
<view class="form">
<view class="form_item" v-if="details.stationName">
<view class="left">选择站点:</view>
<view class="nr">{{details.stationName}}</view>
</view>
<view class="form_item" v-if="details.omName">
<view class="left">维护内容:</view>
<view class="nr">{{details.omName}}</view>
</view>
<view class="form_item" v-if="details.maintainPerson">
<view class="left">维护人:</view>
<view class="nr">{{details.maintainPerson}}</view>
</view>
<view class="form_item" v-if="details.maintainTime">
<view class="left">维护时间:</view>
<view class="nr">{{details.maintainTime}}</view>
</view>
<view class="bz_item" v-if="details.maintainNote">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea style="width: 100%;" v-model="details.maintainNote" placeholder="请输入备注" disabled="true"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="toback()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
export default{
data(){
return{
details:{
stationName:'',
stationCode:'',
maintainPerson:'',
maintainTime:'',
maintainNote:'',
omName:''
}
}
},
onLoad(options) {
this.details = JSON.parse(decodeURIComponent(options.item));
},
onShow() {
},
methods:{
toback(){
uni.navigateBack({
delta:1
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: #fff;
}
.form{
padding: 0 30rpx;
}
.form_item{
display: flex;
justify-content: space-between;
padding: 30rpx 0rpx;
border-bottom:1rpx solid #e4e4e4;
// font-weight: 500;
}
.left{
font-weight: bold;
}
.nr{
flex: 1;
color: #767676;
padding-left: 16rpx;
text-align: right;
}
.dw{
color: greenyellow;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgList image{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgList image:nth-child(4n){
margin-right: 0rpx;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 20rpx;
}
.bz{
margin-left: 30rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.dw{
margin-left: 5rpx;
}
.pagebot{
height: 200rpx;
}
</style>

View File

@ -0,0 +1,317 @@
<template>
<view class="container">
<view class="form">
<view class="form_item">
<view class="form_top">
选择站点:
</view>
<view class="form_bot">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="dates">
<view class="uni-input" v-if="!details.stationName" style="color: #808080;">请选择监测站点</view>
<view class="uni-input" v-else>{{details.stationName}}</view>
</view>
<image class="dateimg" src="../../../static/xiala.png" mode="" style="width: 32rpx;height: 16rpx;"></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
维护内容:
</view>
<view class="form_bot">
<uni-section type="line">
<view class="uni-px-5 uni-pb-5">
<uni-data-checkbox @change="change1" selectedColor="#47c693" mode="tag" v-model="details.itemId" :localdata="hobby"></uni-data-checkbox>
</view>
</uni-section>
</view>
</view>
<view class="form_item">
<view class="form_top">
维护人:
</view>
<!-- <view class="form_bot" @click="tolist()">
<view class="checkpeople">
+ 选择维护人
</view>
</view> -->
<input type="text" placeholder="请输入运维人姓名" v-model="details.maintainPerson">
</view>
<view class="form_item">
<view class="form_top">
维护时间:
</view>
<view class="form_bot">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="bindDateChange">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!details.maintainTime">请选择维护时间</view>
<view class="uni-input" v-else>{{details.maintainTime}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="bz_item">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea v-model="details.maintainNote" style="width: 100%;"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="tosubmit()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
export default{
data(){
return{
array:[],
arrays:[],
details:{
createTime: "",
createdBy: "",
id: "",
isDel: 0,
itemId: "",
maintainData1: "",
maintainData2: "",
maintainNote: "",
maintainPerson: "",
maintainTime: "",
omName: "",
reVision: 0,
stationCode: "",
stationName: "",
tenantId: "",
updatedBy: "",
updatedTime: ""
},
index:'',
date:'',
year:'',
number:'',
tag:'',
hobby: [],
checkbox1: [],
reload:'true'
}
},
onLoad(options) {
this.details = JSON.parse(decodeURIComponent(options.item));
},
onShow() {
this.getazsurvMulchRecord()
this.getazsurvMulchRecord1()
},
methods:{
//
getazsurvMulchRecord(){
this.array = []
this.arrays = []
this.$http.get('/applet/survStationInfo/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.arrays.push({
label:res.data.data[i].stationName,
value:res.data.data[i].stationCode
})
this.array.push(res.data.data[i].stationName)
console.log(this.array)
}
})
},
//
getazsurvMulchRecord1(){
this.hobby = []
this.$http.get('/applet/survMaintainItem/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.hobby.push({
text:res.data.data[i].omName,
value:res.data.data[i].id
})
console.log(this.hobby)
}
})
},
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
this.details.stationName = this.array[this.index]
for(var i=0;i<this.arrays.length;i++){
if(this.details.stationName == this.arrays[i].label){
this.details.stationCode = this.arrays[i].value
}
}
},
bindDateChange: function(e) {
this.details.maintainTime = e.detail.value
},
change1(e){
console.log(e)
this.details.itemId = e.detail.value
},
//
tosubmit(){
if(!this.details.stationName){
uni.showToast({
title: "请选择站点",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.itemId){
uni.showToast({
title: "请选择维护内容",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.maintainPerson){
uni.showToast({
title: "请输入运维人姓名",
icon: 'none',
duration: 2000
})
return
}
if(!this.details.maintainTime){
uni.showToast({
title: "请选择维护时间",
icon: 'none',
duration: 2000
})
return
}
this.$http.post('/applet/survMaintainRecord/edit',this.details).then(res=>{
uni.showLoading({
title: '正在提交...'
});
if(res.data.code == 0){
uni.hideLoading();
uni.navigateBack()
let pages = getCurrentPages();
let prevPage = pages[ pages.length - 2 ];
prevPage.$vm.reload = this.reload;
}
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: white;
}
.form{
padding: 0 30rpx;
}
.form_item{
padding-top: 33rpx;
padding-bottom: 25rpx;
border-bottom: 1rpx solid #e6e6e6;
}
.form_top{
margin-bottom: 26rpx;
font-weight: bold;
}
.form_bot{
position: relative;
}
.dates{
display: flex;
align-items: center;
justify-content: space-between;
}
.dateimg{
height: 32rpx;
width: 32rpx;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.dw{
color: #2ac066;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgList image{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgList image:nth-child(4n){
margin-right: 0rpx;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz{
margin-left: 30rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
border: 1rpx solid #ececec;
border-radius: 10rpx;
padding: 16rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.pagebot{
height: 200rpx;
}
.text {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.uni-px-5 {
padding-left: 10px;
padding-right: 10px;
}
.uni-pb-5 {
padding-bottom: 10px;
}
.checkpeople{
width: 187rpx;
height: 57rpx;
border: 1rpx dashed #0472e3;
line-height: 57rpx;
text-align: center;
color: #0472e3;
}
</style>

View File

@ -0,0 +1,505 @@
<template>
<view class="container">
<scroll-view scroll-y="true" :style="{height:height + 'rpx'}" @refresherrefresh="refresherrefreshFun" @refresherpulling="refresherpullingFun" :refresher-triggered="isRefresher" refresher-enabled="true">
<view class="topcheck">
<view class="left">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="uni-input" v-if="!stationName">选择站点 <image src="../../static/xia.png"></image></view>
<view class="uni-input" v-else>{{stationName}} <image src="../../static/xia.png"></image></view>
</picker>
</view>
<view class="right">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="bindDateChange">
<view class="uni-input" v-if="!maintainTime">选择日期 <image src="../../static/xia.png"></image></view>
<view class="uni-input" v-else>{{maintainTime}} <image src="../../static/xia.png"></image></view>
</picker>
</view>
</view>
<view class="searchbox">
<image src="../../static/meishi_icon_sousuo.png" mode=""></image>
<input class="search_input" v-model="maintainPerson" placeholder="请输入要搜索的运维人员">
<view class="searchbutton" @click="changenr()">
搜索
</view>
</view>
<view class="liebiaos" v-if="List.length != 0">
<scroll-view :style="{height:scorllheight + 'rpx'}" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<view class="itembox" v-for="(item,index) in List" :key="index">
<view class="itembox_top">
<view class="itembox_lef" @click="todetails(item,index)">
<image src="../../static/fz.png" mode=""></image>
<view class="title">
{{item.stationName}}
</view>
</view>
<view class="caozuo" @click="caozuo(item)">
<image src="../../static/dian.png" mode=""></image>
</view>
</view>
<view class="itembox_bot" @click="todetails(item,index)">
<view class="bot_item">
<span class="nrbt">维护内容:</span>
{{item.maintainData1}}
</view>
<view class="bot_item">
<span class="nrbt">维护人员:</span>
<span class="number">{{item.maintainPerson}}</span>
</view>
<view class="bot_item">
<span class="nrbt">维护时间:</span>
{{item.maintainTime}}
</view>
</view>
</view>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
<image @click="toadd()" class="add" src="../../static/add.png" mode=""></image>
</scroll-view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default {
data() {
return {
List:[],
baseUrl:configService.apiUrl,
array:[],
arrays:[],
index:'',
date:'',
searchValue:'',
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
height:0,
scorllheight:0,
show:false,
show1:false,
top:0,
maintainPerson:'',
maintainTime:'',
omName:'',
pageNo:1,
pageSize:4,
deleteUrl:'/applet/survMaintainRecord/delete',
stationName:'',
stationCode:'',
isRefresher: false, //
reload:''
}
},
onLoad(options) {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 182
}
});
this.getList()
},
onShow() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 182
}
});
let pages = getCurrentPages();
let currPage = pages[pages.length - 1]; //
this.reload = currPage.data.reload
if(this.reload){
this.maintainTime = ''
this.stationCode = ''
this.stationName = ''
this.maintainPerson = ''
this.pageNo = 1
this.getList()
this.reload = ''
}
this.getazsurvMulchRecord()
},
methods:{
//
getazsurvMulchRecord(){
this.array = []
this.arrays = []
this.$http.get('/applet/survStationInfo/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.arrays.push({
label:res.data.data[i].stationName,
value:res.data.data[i].stationCode
})
this.array.push(res.data.data[i].stationName)
console.log(this.array)
}
})
},
//
refresherrefreshFun() {
this.maintainTime = ''
this.stationCode = ''
this.stationName = ''
this.maintainPerson = ''
this.pageNo = 1
this.getList()
},
//
refresherpullingFun() {
this.isRefresher= true
},
//
getList(){
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.maintainPerson = this.maintainPerson
params.maintainTime = this.maintainTime
params.stationCode = this.stationCode
params.stationName = this.stationName
uni.showLoading({
title: '加载中'
});
this.List = []
this.$http.get('/applet/survMaintainRecord/list',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
if(res.data.data.total != 0){
this.allNum = Number(res.data.data.total)/Number(this.pageSize)+'';
console.log(this.allNum,'总页数')
if(this.allNum.indexOf('.') == -1) {
this.allNum = this.allNum;
console.log(this.allNum,'if')
} else {
this.allNum = parseInt(Number(this.allNum)+1);
console.log(this.allNum,'else')
}
console.log(this.pageNo,this.allNum,'156156')
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true','nomore')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
uni.hideLoading();
this.isRefresher= false
})
},
//
lower() {
console.log("最后一页了,取消下拉功能");
//
if (this.isLastpage) {
return
}
clearInterval(this.intervalId);
var num = 1;
this.intervalId = setInterval(() => {
num = num+1;
},1000)
console.log(this.intervalId,num)
this.pageNo = this.pageNo + 1;
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.maintainPerson = this.maintainPerson
params.maintainTime = this.maintainTime
params.stationCode = this.stationCode
params.stationName = this.stationName
this.$http.get('/applet/survMaintainRecord/list',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
if(res.data.data.total != 0){
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
})
},
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
this.stationName = this.array[this.index]
for(var i=0;i<this.arrays.length;i++){
if(this.stationName == this.arrays[i].label){
this.stationCode = this.arrays[i].value
}
}
this.pageNo = 1
this.getList()
},
bindDateChange: function(e) {
this.maintainTime = e.detail.value
this.pageNo = 1
this.getList()
},
changenr(){
console.log(this.maintainPerson)
this.pageNo = 1
this.getList()
},
todetails(item,index){
uni.navigateTo({
url:'/packDetail/pages/operations/detail?item=' + encodeURIComponent(JSON.stringify(item))
})
},
toadd(){
uni.navigateTo({
url:'/packDetail/pages/operations/add'
})
},
caozuo(item){
console.log(item)
var that = this
uni.showActionSheet({
itemList: ['编辑', '删除'],
success: function (res) {
console.log('选中了第' + (res.tapIndex + 1) + '个按钮');
if((res.tapIndex + 1) == 1){
uni.navigateTo({
url:'/packDetail/pages/operations/edit?item='+ encodeURIComponent(JSON.stringify(item))
})
}else{
uni.showModal({
title: '提示',
content: '是否删除数据?',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
that.$http.delete(that.deleteUrl+'?id='+item.id).then(res =>{
if(res.data.code == 0){
uni.showToast({
title: '删除成功',
icon:'success',
duration: 2000
});
that.pageNo = 1
that.maintainTime = ''
that.stationCode = ''
that.stationName = ''
that.maintainPerson = ''
that.getList()
}
})
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
},
fail: function (res) {
console.log(res.errMsg);
}
});
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
}
.container{
height: 100%;
}
.topcheck{
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1rpx solid #ededed;
background-color: white;
}
.left{
width: 50%;
display: flex;
justify-content: center;
}
.right{
width: 50%;
border-left: 4rpx solid #ededed;
display: flex;
justify-content: center;
}
.searchbox{
padding: 20rpx 30rpx;
background-color: white;
position: relative;
display: flex;
justify-content: space-between;
}
.search_input{
border: none;
height: 60rpx;
width: 86%;
font-size: 24rpx;
border-radius: 30rpx;
background-color: #F6F6F6;
padding-left: 50rpx;
}
.searchbox image{
width: 32rpx;
height: 32rpx;
position: absolute;
left: 40rpx;
top: 35%;
z-index: 99;
}
.searchbutton{
width: 10%;
height: 60rpx;
font-size: 26rpx;
text-align: center;
line-height: 60rpx;
}
.itembox{
background-color: white;
padding: 30rpx;
margin-top: 20rpx;
}
.itembox:first-child{
margin-top: 0;
}
.uni-input{
display: flex;
align-items: center;
}
.uni-input image{
height: 12rpx;
width: 24rpx;
margin-left: 5rpx;
}
.itembox_top{
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 30rpx;
border-bottom: 2rpx solid #e4e4e4;
}
.itembox_lef image{
width: 40rpx;
height: 40rpx;
margin-right: 14rpx;
}
.itembox_lef{
display: flex;
align-items: center;
font-weight: 500;
width: 70%;
}
.caozuo{
height: 100%;
display: flex;
align-items: center;
flex:1;
justify-content: flex-end;
}
.caozuo image{
width: 7rpx;
height: 29rpx;
z-index: 99;
}
.bot_item{
margin-top: 30rpx;
}
.nrbt{
color: #898989;
margin-right: 10rpx;
}
.number{
// color: #ff6563;
}
.numbers{
color:#26bf64;
}
.load{
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
.add{
height: 150rpx;
width: 150rpx;
position: fixed;
bottom: 100rpx;
right: 60rpx;
}
.popup{
background-color: white;
height: 100%;
width: 100%;
}
.title{
font-weight: bold;
}
.zwsj{
width: 100%;
// height: 100%;
display: flex;
padding: 60% 170rpx 0;
}
.inzwsj{
width: 100%;
}
.zwsjimg{
width: 100%;
height: 224rpx;
margin-bottom: 37rpx;
}
.zwsjtext{
width: 100%;
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #999999;
line-height: 31rpx;
text-align: center;
}
</style>

View File

@ -0,0 +1,403 @@
<template>
<view class="container">
<!-- <image src="../../static/list.png" mode="" class="bigimg" @click="submit()"></image> -->
<view class="searchbox">
<image src="../../static/meishi_icon_sousuo.png" mode=""></image>
<input class="search_input" v-model="searchValue" @input="changenr($event)" placeholder="请输入要搜索的姓名">
</view>
<scroll-view :style="{height:scorllheight + 'rpx'}" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<view class="lists_items" v-for="(it,i) in dataList" :key="i">
<view class="bm">
{{it.department}}
</view>
<view class="rylist" v-for="(item,index) in it.list" :key="index">
<checkbox-group @change="checkSelectItem($event,item)" class="rylist1">
<view class="rylists">
<view class="rylist_left">
<image src="../../static/tx.jpg" mode=""></image>
</view>
<view class="rylist_right">
<view class="toptitle">
{{item.name}}
</view>
<view class="zw">
{{item.position}}
</view>
</view>
</view>
<view class="checked">
<checkbox :value="item.value" :checked="item.checked" />
</view>
</checkbox-group>
</view>
</view>
<view class="load">
暂无更多~
</view>
</scroll-view>
<view class="pagebot">
</view>
<view class="botadd">
<view class="qxan">
<checkbox-group @change="checkSelect" >
<view class="allcheck">
<view class="checkalls">
<checkbox :checked="checkTrue"></checkbox>
</view>
<view class="qx">
全选
</view>
</view>
</checkbox-group>
</view>
<view class="btnsubmit">
确定({{checkList.length}}/{{alllist.length}})
</view>
</view>
</view>
</template>
<script>
export default{
data(){
return{
searchValue:'',
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
height:0,
scorllheight:0,
show:false,
show1:false,
top:0,
checkTrue:false,
checkList:[],
alllist:[],
dataList:[
{
department:'后勤部',
list:[
{
value:0,
name:'陈丽云',
position:'部长',
checked:false
},
{
value:1,
name:'陈丽云',
position:'组员',
checked:false
}
]
},
{
department:'市场部',
list:[
{
value:2,
name:'陈丽云',
position:'部长',
checked:false
},
{
value:3,
name:'陈丽云',
position:'组员',
checked:false
},
{
value:4,
name:'陈丽云',
position:'市场专员',
checked:false
}
]
},
{
department:'办公室',
list:[
{
value:5,
name:'陈丽云',
position:'总经理',
checked:false
},
{
value:6,
name:'陈丽云',
position:'副经理',
checked:false
}
]
},
{
department:'技术部',
list:[
{
value:7,
name:'陈丽云',
position:'部长',
checked:false
},
{
value:8,
name:'陈丽云',
position:'项目经理',
checked:false
},
{
value:9,
name:'陈丽云',
position:'员工',
checked:false
},
]
},
]
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 120
}
});
this.allnumber()
},
methods:{
allnumber(){
this.alllist = []
for(var i=0;i<this.dataList.length;i++){
for(var j=0;j<this.dataList[i].list.length;j++){
this.dataList[i].list[j].checked = false
this.alllist.push(this.dataList[i].list[j])
}
}
},
//
checkSelect() {
if (this.checkTrue == true) {
this.checkTrue = false;
// RecordList
this.alllist.forEach(item => {
this.$set(item, 'checked', false)
})
this.checkList = []
} else {
this.checkTrue = true;
// alllist
this.alllist.forEach(item => {
this.$set(item, 'checked', true)
})
this.checkList = this.alllist
console.log(this.checkList,156)
}
},
checkSelectItem(e, item) {
console.log(item,156)
// checkedfalse,checked=true
if (item.checked == true) {
this.$set(item, 'checked', false)
this.checkList = this.checkList.filter(items => (items.value !== item.value))
console.log(this.checkList,'true')
} else {
this.$set(item, 'checked', true)
this.checkList.push(item)
console.log(this.checkList,'false')
}
// checkedtruealllist
let newArr = this.alllist.filter(item => (item.checked == true))
if (newArr.length === this.alllist.length) {
this.checkTrue = true;
} else {
this.checkTrue = false;
}
console.log(this.checkList,41561456)
},
submit(){
uni.navigateBack({
delta:1
})
}
}
}
</script>
<style lang="scss">
.bigimg{
width: 100%;
height: 100%;
position: fixed;
z-index: -99;
top: 0;
left: 0;
}
.searchbox{
background-color: #fff;
padding: 30rpx 20rpx;
box-sizing: border-box;
position: relative;
}
.search_input{
border: none;
height: 60rpx;
width: 100%;
font-size: 24rpx;
border-radius: 30rpx;
background-color: #F6F6F6;
padding-left: 50rpx;
}
.searchbox image{
width: 32rpx;
height: 32rpx;
position: absolute;
left: 40rpx;
top: 40%;
z-index: 99;
}
.bm{
height: 60rpx;
line-height: 60rpx;
padding-left: 20rpx;
}
.rylist{
background-color: #fff;
padding: 26rpx 54rpx 26rpx 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2rpx solid #ececec;
}
.rylists{
display: flex;
align-items: center;
}
.rylist_left{
width: 96rpx;
height: 96rpx;
border-radius: 50%;
margin-right: 28rpx;
}
.rylist_left image{
width: 96rpx;
height: 96rpx;
border-radius: 50%;
}
.rylist_right{
height: 96rpx;
}
.zw{
font-size: 24rpx;
color:#696969;
margin-top: 16rpx;
}
.load{
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
.botadd{
position: fixed;
left: 0;
bottom: 0;
z-index: 99;
display: flex;
align-items: center;
background-color: #fff;
width: 100%;
padding: 20rpx 0 40rpx 34rpx;
}
.allcheck{
display: flex;
align-items: center;
margin-right: 74rpx;
}
.checked{
width: 38rpx;
height: 38rpx;
}
.checked image{
width: 38rpx;
height: 38rpx;
}
.btnsubmit{
width:50%;
height: 80rpx;
border-radius: 40rpx;
background-color: #0f6efe;
color:#fff;
display: flex;
align-items: center;
justify-content: center;
}
.checked {
width: 38rpx;
height: 38rpx;
/* #ifdef APP-PLUS ||MP-WEIXIN */
checkbox .wx-checkbox-input {
border-radius: 50% !important;
border: none !important;
/* color: #ffffff !important; */
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked {
color: #fff;
border: none !important;
background-image: linear-gradient(to right, #0f6efe, #0f6efe);
background-size: 100%;
background-repeat: no-repeat;
}
/* .wx-checkbox-input.wx-checkbox-input-checked {
border: none !important;
} */
/* #endif */
}
.checkalls {
width: 38rpx;
height: 38rpx;
/* #ifdef APP-PLUS ||MP-WEIXIN */
checkbox .wx-checkbox-input {
border-radius: 50% !important;
width: 38rpx;
height: 38rpx;
/* color: #ffffff !important; */
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked {
color: #fff;
width: 38rpx;
height: 38rpx;
border: none !important;
background-image: linear-gradient(to right, #0f6efe, #0f6efe);
background-size: 100%;
background-repeat: no-repeat;
}
/* .wx-checkbox-input.wx-checkbox-input-checked {
border: none !important;
} */
/* #endif */
}
.qx{
margin-left: 16rpx;
}
.rylist1{
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.pagebot{
height: 120rpx;
}
</style>

View File

@ -0,0 +1,697 @@
<template>
<view class="container">
<scroll-view scroll-y="true" :style="{height:height + 'rpx'}" @refresherrefresh="refresherrefreshFun" @refresherpulling="refresherpullingFun" :refresher-triggered="isRefresher" refresher-enabled="true">
<view class="topScroll">
<scroll-view scroll-x="true" class="scroll">
<view class="scroll-item" v-for="(item,index) in topItems" :key="index" @click="chooseClick(item,index)" :class="{'scroll-item2':isActive == index}">
{{item.dictLabel}}
<view class="zliebs" v-show="isActive === index">
</view>
</view>
</scroll-view>
</view>
<block v-if="isActive == 1">
<view class="searchbox">
<image src="../../static/meishi_icon_sousuo.png" mode=""></image>
<input class="search_input" v-model="deviceNo" placeholder="请输入要搜索的设备编号">
<view class="searchbutton" @click="changenr()">
搜索
</view>
</view>
<view class="liebiaos" v-if="List.length != 0">
<scroll-view :style="{height:scorllheight + 'rpx'}" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<view class="itembox" v-for="(item,index) in List" :key="index">
<view class="itembox_top">
<view class="itembox_lef" v-if="item.deviceNo">
<!-- <image src="../../static/fz.png" mode=""></image> -->
<view class="title">
编号{{item.deviceNo}}
</view>
</view>
</view>
<view class="itembox_bot">
<view class="bot_item" v-if="item.flg">
<span class="nrbt">报警原因:</span>
<view class="bj" v-if="item.deviceStatus == 1">
{{item.flg}}
</view>
<view class="jcbj" v-if="item.deviceStatus == 0">
{{item.flg}}
</view>
</view>
<view class="bot_item" v-if="item.userDeviceNo">
<span class="nrbt">用户设备编号:</span>
<span class="number">{{item.userDeviceNo}}</span>
</view>
<view class="bot_item" v-if="item.alertTime">
<span class="nrbt" v-if="item.deviceStatus == 1">报警时间:</span>
<span class="nrbt" v-if="item.deviceStatus == 0">解除时间:</span>
{{item.alertTime}}
</view>
<view class="bot_item" v-if="item.reveiveTime">
<span class="nrbt">上报时间:</span>
{{item.reveiveTime}}
</view>
</view>
</view>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
</block>
<block v-else-if="isActive == 0">
<view class="liebiaos" v-if="List.length != 0">
<scroll-view :style="{height:scorllheights + 'rpx'}" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<view class="itembox" v-for="(item,index) in List" :key="index">
<view class="itembox_top" v-if="item.stationName">
<view class="itembox_lef">
<image src="../../static/fz.png" mode=""></image>
<view class="title">
{{item.stationName}}
</view>
</view>
<view class="itembox_right">
{{item.alertTime}}
</view>
</view>
<view class="itembox_bot">
<block v-if="item.alertContent.length != 0">
<view class="scrolltop">
<view class="tabitem" v-for="(it,i) in tabList" :key="i">
{{it}}
</view>
</view>
<view class="lists_item" v-for="(Item,Index) in item.alertContent" :key="Index">
<view class="jczbs" v-if="Item.name">
{{Item.name}}
</view>
<view class="zbz" v-if="Item.val">
{{Item.val}}
</view>
<view class="sbsj" v-if="Item.valHeight" style="color: #FF4242;">
{{Item.valHeight}}
<image class="zximg" src="../../../static/home_shuju_shang.png" mode=""></image>
</view>
<view class="sbsj" v-if="Item.valLow" style="color: #19D58A;">
{{Item.valLow}}
<image class="zximg" src="../../../static/home_shuju_xia.png" mode=""></image>
</view>
<view class="szqss" v-if="Item.unit">
{{Item.unit}}
</view>
</view>
</block>
</view>
</view>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
</block>
</scroll-view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default {
data() {
return {
List:[],
baseUrl:configService.apiUrl,
tabList: ['监测指标名称', '监测指标值', '高/低阈值','计量单位'],
array:[],
index:'',
sampTime:'',
deviceNo:'',
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
height:0,
scorllheight:0,
scorllheights:0,
show:false,
show1:false,
top:0,
pageNo:1,
pageSize:4,
deleteUrl:'/applet/survMulchRecord/delete',
stationName:'',
stationCode:'',
sampTime:'',
arrays:[],
isRefresher: false, //
reload:'',
topItems:[
{
dictLabel:'监测站告警'
},
{
dictLabel:'杀虫灯告警'
}
],
isActive:0,
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 174
this.scorllheights = this.height - 90
}
});
this.getList()
},
onShow() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 174
this.scorllheights = this.height - 90
}
});
},
methods:{
//
refresherrefreshFun() {
this.pageNo = 1
this.deviceNo = ''
this.getList()
},
//
refresherpullingFun() {
this.isRefresher= true
},
//
chooseClick(item,index){
this.isActive = index;
this.pageNo = 1
this.deviceNo = ''
this.getList()
},
getList(){
var params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
uni.showLoading({
title: '加载中'
});
this.List = []
if(this.isActive == 0){
var url = '/applet/wxclient/alertRecord'
}else if(this.isActive == 1){
var url= '/applet/survPestlightAlert/list'
if(this.deviceNo){
params.deviceNo = this.deviceNo
}
}
this.$http.get(url,{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
// for(var i=0;i<data.length;i++){
// if(data[i].alertContent){
// for(var j=0;j<data[i].alertContent.length;j++){
// data[i].alertContent[j] = JSON.parse(data[i].alertContent[j])
// console.log(data[i].alertContent[j])
// }
// console.log(data[i].alertContent)
// }
// }
this.List = this.List.concat(data)
if(res.data.data.total != 0){
this.allNum = Number(res.data.data.total)/Number(this.pageSize)+'';
console.log(this.allNum,'总页数')
if(this.allNum.indexOf('.') == -1) {
this.allNum = this.allNum;
console.log(this.allNum,'if')
} else {
this.allNum = parseInt(Number(this.allNum)+1);
console.log(this.allNum,'else')
}
console.log(this.pageNo,this.allNum,'156156')
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true','nomore')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
uni.hideLoading();
this.isRefresher= false
})
},
lower() {
console.log("最后一页了,取消下拉功能");
//
if (this.isLastpage) {
return
}
clearInterval(this.intervalId);
var num = 1;
this.intervalId = setInterval(() => {
num = num+1;
},1000)
console.log(this.intervalId,num)
this.pageNo = this.pageNo + 1;
var params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
if(this.isActive == 0){
var url= '/applet/survPestlightAlert/list'
if(this.deviceNo){
params.deviceNo = this.deviceNo
}
}else if(this.isActive == 1){
var url = '/applet/wxclient/alertRecord'
}
this.$http.get(url,{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
// for(var i=0;i<data.length;i++){
// if(data[i].alertContent){
// for(var j=0;j<data[i].alertContent.length;j++){
// data[i].alertContent[j] = JSON.parse(data[i].alertContent[j])
// console.log(data[i].alertContent[j])
// }
// console.log(data[i].alertContent)
// }
// }
this.List = this.List.concat(data)
if(res.data.data.total != 0){
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
})
},
changenr(){
console.log(this.deviceNo)
this.pageNo = 1
this.getList()
},
}
}
</script>
<style lang="scss">
page{
height: 100%;
// background-color: #fff;
}
.container{
height: 100%;
}
.topcheck{
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1rpx solid #ededed;
background-color: white;
}
.left{
width: 50%;
display: flex;
justify-content: center;
}
.right{
width: 50%;
border-left: 4rpx solid #ededed;
display: flex;
justify-content: center;
}
.searchbox{
height: 88rpx;
padding: 15rpx 30rpx;
// padding: 30rpx;
background-color: white;
position: relative;
display: flex;
justify-content: space-between;
}
.search_input{
border: none;
height: 60rpx;
width: 86%;
font-size: 24rpx;
border-radius: 30rpx;
background-color: #F6F6F6;
padding-left: 50rpx;
}
.searchbox image{
width: 32rpx;
height: 32rpx;
position: absolute;
left: 40rpx;
// top: 24%;
top:35%;
z-index: 99;
}
.searchbutton{
width: 10%;
height: 60rpx;
font-size: 26rpx;
text-align: center;
line-height: 60rpx;
}
.itembox{
background-color: white;
padding: 10rpx 30rpx;
margin-top: 20rpx;
}
.itembox:first-child{
margin-top: 0;
}
.uni-input{
display: flex;
align-items: center;
}
.uni-input image{
height: 12rpx;
width: 24rpx;
margin-left: 5rpx;
}
.itembox_top{
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 2rpx solid #e4e4e4;
}
.itembox_lef image{
width: 40rpx;
height: 40rpx;
margin-right: 14rpx;
}
.itembox_lef{
display: flex;
align-items: center;
font-weight: 500;
width: 63%;
}
.caozuo{
height: 100%;
display: flex;
align-items: center;
flex:1;
justify-content: flex-end;
}
.caozuo image{
width: 7rpx;
height: 29rpx;
z-index: 99;
}
.bot_item{
margin-top: 30rpx;
display: flex;
}
.nrbt{
color: #898989;
margin-right: 10rpx;
min-width: 120rpx;
}
.number{
// color: #ff6563;
}
.numbers{
color:#26bf64;
}
.load{
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
.add{
height: 150rpx;
width: 150rpx;
position: fixed;
bottom: 100rpx;
right: 60rpx;
}
.popup{
background-color: white;
height: 100%;
width: 100%;
}
.title{
font-weight: bold;
}
.zwsj{
width: 100%;
display: flex;
padding: 60% 170rpx 0;
}
.inzwsj{
width: 100%;
}
.zwsjimg{
width: 100%;
height: 224rpx;
margin-bottom: 37rpx;
}
.zwsjtext{
width: 100%;
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #999999;
line-height: 31rpx;
text-align: center;
}
.bj{
padding: 6rpx 12rpx;
border-radius: 6rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #FFFFFF;
background-color: #FF4242;
}
.jcbj{
padding: 6rpx 12rpx;
border-radius: 6rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #FFFFFF;
background-color: #26bf64;
}
.topScroll{
width: 100%;
height: 85rpx;
background-color: #fff;
border-bottom: 1rpx solid #ededed;
// line-height: 80rpx;
// padding:0 32rpx;
}
.scroll{
height: 85rpx;
// line-height: 80rpx;
display: flex;
white-space: nowrap;
justify-content: space-between;
padding-top: 12rpx;
}
.scroll-item{
width: 50%;
text-align: center;
display: inline-block;
font-size: 28rpx;
font-family: Source Han Sans SC;
// border-bottom: 2rpx solid #ededed;
// font-weight: 500;
// color: #545C6C;
}
.scroll-item:first-child{
border-right: 4rpx solid #ededed;
// border-bottom: 2rpx solid #ededed;
// border-right: 2rpx solid #ededed;
}
.scroll-item2{
font-size: 30rpx;
font-family: Source Han Sans SC;
// font-weight: bold;
color: #0F6EFF;
}
.initem{
display: flex;
flex-direction: column;
// border-bottom: 2rpx solid #ededed;
}
.zliebs{
width: 100rpx;
height: 4rpx;
background-color: #0F6EFF;
margin: 12rpx auto 0;
border-radius: 20rpx;
}
.lists_item {
// padding-top: 35rpx;
padding: 0rpx 0rpx 16rpx 0rpx;
box-sizing: border-box;
display: flex;
}
.lists_item{
padding-top: 16rpx;
}
.jczbs {
width: 32%;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
// text-align: center
}
.zbz {
width: 27%;
font-size: 24rpx;
font-family: DIN Next LT Pro;
font-weight: 400;
// color: #2FCD81;
// text-align: center
}
.zbzs {
color: #2FCD81;
}
.szqs {
width: 53rpx;
display: flex;
align-items: center;
justify-content: center;
}
.szqs image {
width: 24rpx;
height: 31rpx;
}
.sbsj {
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
width: 23%;
display: flex;
align-items: center;
// text-align: center
// text-align: right;
}
.zximg{
width: 30rpx;
height: 30rpx;
margin-left: 6rpx;
}
.szqss {
flex:1;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
}
.scrolltop {
padding: 20rpx 0rpx 16rpx 0rpx;
display: flex;
justify-content: space-between;
border-bottom: 2rpx solid #F6F8FB;
width: 100%;
}
.tabitem {
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
display: inline-block;
padding-bottom: 8rpx;
}
.tabitem:first-child{
width: 31%;
// text-align: center
}
.tabitem:nth-child(2){
width: 27%;
// text-align: center
}
.tabitem:nth-child(3){
width: 23%;
// text-align: center
}
.tabitem:nth-child(4){
flex:1
// text-align: center
}
.topcheck{
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1rpx solid #ededed;
background-color: white;
}
.left{
width: 50%;
display: flex;
justify-content: center;
}
.right{
width: 50%;
border-left: 4rpx solid #ededed;
display: flex;
justify-content: center;
}
.itembox_right{
font-size: 26rpx;
}
</style>

View File

@ -0,0 +1,289 @@
<template>
<view>
<view class="headerImg">
<image :src="baseUrl + '/applet/common/static/' + constant.headimgUrl" class="images"></image>
<view class="ghtx" @click="uploadimg()">
<image src="../../static/xj.png" mode=""></image>
</view>
</view>
<view class="xinxi">
<view class="name">
<view class="xms">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</view>
<input class="iptnr" placeholder="请输入姓名" v-model="constant.nickName" />
</view>
<view class="name1">
<view class="xms">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</view>
<view class="sexs">
<view class="sex">
<radio-group @change="radioChange" class="group">
<label class="uni-list-cell uni-list-cell-pd" v-for="(item, index) in items" :key="item.value">
<view>
<radio style="transform:scale(0.7)" :value="item.value" :checked="item.value === constant.sex" />
</view>
<view class="sexname">{{item.name}}</view>
</label>
</radio-group>
</view>
</view>
</view>
<button class="btn" :disabled="istrue" @click="submit()">保存</button>
</view>
</view>
</template>
<script>
import api from '@/api/api'
import configService from '@/common/service/config.service.js';
export default {
data() {
return {
contentheight:0,
baseUrl:configService.apiUrl,
uploadUrl:'/applet/common/upload',
constant:{
headimgUrl:'',
nickName:'',
sex:'',
id:''
},
current:0,
items:[{
value:"1",
name:'男'
},
{
value:"2",
name:'女'
}],
istrue:false
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
this.contentheight = this.height - ktxStatusHeight - navigationHeight - 150
console.log(this.contentheight,123132)
}
});
},
onShow() {
this.getuserInfo()
},
methods: {
getuserInfo(){
this.$http.get('/applet/userInfo').then(res=>{
this.constant = res.data.data
})
},
uploadimg(){
var that = this
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'], //
sourceType: ['album', 'camera'], //
success: (res) => {
var tempFilePaths = res.tempFilePaths
for(var i=0;i<tempFilePaths.length;i++){
that.$http.upload(that.baseUrl+that.uploadUrl,{
filePath: res.tempFilePaths[i],
name: 'file',
formData:{
file:res.tempFilePaths[i],
biz:'busi'
}
}).then(res =>{
if(res.data.code == 0){
this.constant.headimgUrl = res.data.data.savePath
}
})
}
}
});
},
radioChange(value){
console.log(value)
this.constant.sex = value.detail.value
},
submit() {
const data = {
nickName:this.constant.nickName,
sex:this.constant.sex,
headimgUrl:this.constant.headimgUrl,
id:this.constant.id
}
this.istrue = true
this.$http.put('/applet/userInfo',data).then(response => {
if(response.data.code == 0){
uni.showToast({ title: "修改成功", icon: 'success' })
uni.navigateBack({
delta:1
})
}
})
},
}
}
</script>
<style lang="scss">
page{
background-color: white;
height: 100%;
}
.uni-nav-bar {
background-color: transparent;
border-color: transparent;
height: 44px;
}
.uni-nav-bar-text {
font-size: 31rpx;
font-family: Source Han Sans SC;
font-weight: bold;
color: #193772;
}
.uni-nav-bar__left,
.uni-nav-bar__right {
color: #000;
}
.uni-navbar__content {
border: 0 none !important;
}
.bg-img{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
.contents{
margin-top: 150rpx;
background: #FFFFFF;
border-radius: 36rpx 36rpx 0rpx 0rpx;
width: 100%;
position: relative;
}
.ghtx{
width: 60rpx;
height: 60rpx;
position: absolute;
top: 104rpx;
left: 113rpx;
z-index: 99;
}
.ghtx image{
width: 60rpx;
height: 60rpx;
border-radius: 50%;
}
.headerImg{
width: 160rpx;
height: 160rpx;
display: flex;
justify-content: center;
position: relative;
margin: 0 auto;
margin-top: 86rpx;
}
.images{
width: 160rpx;
height: 160rpx;
border-radius: 50%;
margin-bottom: 48rpx;
}
.xinxi{
padding: 0 32rpx;
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #303B4F;
}
.iptnr{
height: 80rpx;
margin-top: 26rpx;
box-sizing: border-box;
font-size: 28rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #303B4F;
border-bottom: 2rpx solid #ececec;
}
.name1{
margin-top: 39rpx;
border-bottom: 2rpx solid #ececec;
padding-bottom: 36rpx;
}
.radio{
margin-top: 18rpx;
display: flex;
}
.uni-list-cell{
display: flex;
}
.sexs{
display: flex;
margin-top: 18rpx;
}
.sex{
height: 44rpx;
display: flex;
align-items: center;
font-size: 28rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #303B4F;
}
.sex:first-child{
margin-right: 41rpx;
}
.nanv{
width: 33rpx;
height: 33rpx;
margin-right: 14rpx;
}
.labels{
margin-right: 12rpx;
}
.checked{
width: 41rpx;
height: 41rpx;
background: #EEF3F5;
border-radius: 50%;
}
.checked image{
width: 41rpx;
height: 41rpx;
background: #EEF3F5;
border-radius: 50%;
}
.btn{
margin-top: 120rpx;
height: 88rpx;
background: #0f6efe;
border-radius: 44rpx;
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #FFFFFF;
}
.group{
display: flex;
margin-top: 26rpx;
}
.sexname{
margin-left: 14rpx;
}
.uni-list-cell{
margin-left: 144rpx;
}
.uni-list-cell:first-child{
margin-left: 0;
}
.xms{
font-weight: bold;
}
</style>

View File

@ -0,0 +1,435 @@
<template>
<view class="container">
<uni-nav-bar :fixed="true" left-icon="left" background-color="#0F6EFF" @clickLeft="back()" status-bar :title="item.stationName"/>
<view class="liebiaos">
<view class="list_item">
<view class="list_item_top">
<view class="list_item_left">
<image v-if="item.deviceInfo.deviceIcon" :src="baseUrl + '/applet/common/static/' + item.deviceInfo.deviceIcon" mode=""></image>
<view class="item_right">
<view class="right_top" v-if="item.deviceInfo.deviceName">
{{item.deviceInfo.deviceName}}
</view>
<view class="right_bot">
<image src="../../static/shebei_icon_zhibiao.png" mode=""></image>
<view class="">监测指标{{survItem.length || 0}} </view>
</view>
</view>
</view>
<view class="state">
<view class="" v-if="item.runStatus == 0">
在线
</view>
<view class="" v-else>
下线
</view>
<image v-if="item.runStatus == 0" src="../../static/zhandian_icon_zaixian .png" mode="" class="zt"></image>
<image v-else src="../../static/zhandian_icon_lixian.png" mode="" class="zt"></image>
</view>
</view>
<view class="list_item_bot">
<view class="bots_item" v-if="item.deviceInfo.deviceManufacturer">
<image src="../../static/shebei_icon_pinpai.png" mode=""></image>
<view class="pp">
设备品牌:
</view>
<view class="mz">
{{item.deviceInfo.deviceManufacturer}}
</view>
</view>
<view class="bots_item" style="margin-top: 34rpx;" v-if="item.deviceInfo.deviceModel">
<image src="../../static/shebei_icon_xinghao.png" mode=""></image>
<view class="pp">
设备型号:
</view>
<view class="mz">
{{item.deviceInfo.deviceModel}}
</view>
</view>
<view class="bots_item" style="margin-top: 34rpx;" v-if="survItem.length != 0">
<!-- <view style="display: flex;align-items: center;height: 34rpx;">
<image src="../../static/shebei_icon_jiancezhibiao.png" mode=""></image>
<view class="pp">
监测指标:
</view>
</view> -->
<view class="jstimerig_bot">
<view style="display: flex;align-items: center;height: 34rpx;">
<image src="../../static/shebei_icon_jiancezhibiao.png" mode=""></image>
<view class="pp">
监测指标:
</view>
</view>
<view class="tag-view" v-for="(item,index) in survItem" :key="index">
<view :style="{background:item.color}" class="tag">{{item.name}}</view>
</view>
</view>
</view>
</view>
</view>
<view class="sssjjc">
<view class="sssjjc_left">
实时数据监测
</view>
<view class="topnum">
累计 <span class="number">{{list.length}}</span>
</view>
</view>
<view class="scrolllist">
<view class="scrolltop" v-if="list.length != 0">
<view class="tabitem" v-for="(item,index) in tabList" :key="index">
{{item}}
</view>
</view>
<scroll-view style="height: 550rpx;" scroll-y="true" class="scroll-Y">
<block v-if="list.length != 0">
<view class="lists_item" v-for="(item,index) in list" :key="index">
<view class="jczbs">
{{item.name}}
</view>
<view class="zbz">
{{item.value || 0}}{{item.unit}}
</view>
<!-- <view class="szqs">
<image v-if="item.type == 1" src="../../../static/home_shuju_shang.png" mode=""></image>
<image v-if="item.type == 0" src="../../../static/home_shuju_xia.png" mode=""></image>
<view class="szqss" v-if="item.type == 2"></view>
</view> -->
<view class="sbsj">
{{item.dataDateTime}}
</view>
</view>
<view class="zwgd" style="width: 100%;height: 100rpx; line-height: 100rpx;text-align: center;color: #c6c6c6;">
暂无更多数据
</view>
</block>
<view class="load" v-else>
暂无数据
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default{
data(){
return{
item:{},
baseUrl:configService.apiUrl,
tabList:['监测指标','指标值','上报时间'],
colorList:['#22BB8A','#EE701C','#52AC2A','#2BADB9','#D75A28','#AD8F49','#26A3CC','#6C48C7','#22BB8A','#415FBE','#52AC2A','#EE701C'],
list:[],
deployCode:'',
survItem:[]
}
},
onLoad(options) {
console.log(JSON.parse(decodeURIComponent(options.item)))
this.item = JSON.parse(decodeURIComponent(options.item));
},
onShow() {
this.getsssj()
},
methods:{
getsssj(){
let params = {}
params.deployCode = this.item.deployCode
this.$http.get('/applet/wxclient/getSurvDataByDevice',{params:params}).then(res=>{
this.list = res.data.data.dataList
this.survItem = res.data.data.zhibiao
for(var i=0;i<this.list.length;i++){
this.list[i].value = (Math.floor(this.list[i].value * 100) / 100).toFixed(2)
}
})
},
back(){
uni.navigateBack({
delta:1
})
},
}
}
</script>
<style lang="scss">
.uni-nav-bar {
height: 44px;
}
.uni-nav-bar-text {
font-size: 32rpx !important;
font-family: Source Han Sans SC;
color: #FFFFFF !important;
}
.uni-nav-bar__left,
.uni-nav-bar__right {
color: #FFFFFF !important;
}
.uni-navbar__content {
border: 0 none !important;
}
.uni-navbar__header-container-inner{
padding: 0 40rpx;
box-sizing: border-box;
/* 文本不折行 */
white-space: nowrap;
/* 溢出隐藏 */
overflow: hidden;
}
.uni-icons{
color: #FFFFFF !important;
}
page{
height: 100%;
}
.container{
height: 100%;
}
.liebiaos{
padding: 28rpx 32rpx;
}
.list_item{
width: 100%;
padding: 37rpx 34rpx 28rpx;
background: #FFFFFF;
border-radius: 34rpx;
margin-bottom: 42rpx;
position: relative;
}
.list_item:last-child{
margin-bottom: 0;
}
.list_item_top{
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 64rpx;
}
.list_item_left{
display: flex;
align-items: center;
}
.list_item_left image{
width: 73rpx;
height: 73rpx;
margin-right: 18rpx;
}
.item_right{
height: 76rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.right_top{
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
}
.right_bot{
display: flex;
align-items: center;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #9CA9BE;
}
.right_bot image{
height: 26rpx;
width: 24rpx;
margin-right: 11rpx;
}
.jt{
width: 40rpx;
height: 48rpx;
}
.state{
background: #F6F6F6;
border-top-left-radius: 26rpx;
border-bottom-left-radius: 26rpx;
width: 171rpx;
height: 52rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #5F7088;
display: flex;
align-items: center;
padding-left: 24rpx;
box-sizing: border-box;
position: absolute;
top: 31rpx;
right: -32rpx;
}
.zt{
width: 24rpx;
height: 24rpx;
margin-left: 18rpx;
}
.bots_item{
display: flex;
align-items: center;
}
.bots_item image{
width: 24rpx;
height: 24rpx;
margin-right: 12rpx;
}
.pp{
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #142E55;
margin-right: 38rpx;
min-width: 112rpx;
}
.mz{
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #566070;
}
.jstimerig_bot{
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #566070;
display: flex;
flex-wrap: wrap;
}
.tag{
padding: 6rpx 12rpx 6rpx 12rpx;
border-radius: 6rpx;
margin-right: 12rpx;
margin-bottom: 15rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #FFFFFF;
}
.tag:nth-child(4n){
margin-right: 0;
}
.sssjjc{
padding: 0 31rpx 26rpx 34rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
}
.topnum{
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #B3C1D1;
}
.number{
font-size: 34rpx;
font-family: DIN Next LT Pro;
font-weight: 500;
color: #2AC166;
margin-left: 15rpx;
margin-right: 15rpx;
}
.sssjjc_left{
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: bold;
color: #2F3841;
}
.scrolllist{
width: 100%;
// height: 1095rpx;
background: #FFFFFF;
border-radius: 34rpx;
padding: 35rpx 0rpx 37rpx 0rpx;
}
.scrolltop{
padding: 0rpx 32rpx 16rpx 32rpx;
display: flex;
justify-content: space-between;
border-bottom: 2rpx solid #F6F8FB;;
width: 100%;
}
.tabitem{
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
display: inline-block;
padding-bottom: 26rpx;
}
.tabitem:first-child{
width: 30%;
// text-align: center
}
.tabitem:nth-child(2){
width: 30%;
// text-align: center
}
.tabitem:nth-child(3){
flex: 1;
// text-align: center
}
.scroll-Y{
padding: 0 32rpx 0 32rpx;
box-sizing: border-box;
}
.lists_item{
padding-top: 35rpx;
box-sizing: border-box;
display: flex;
}
.jczbs{
width: 30%;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
// text-align: center
}
.zbz{
width: 30%;
font-size: 24rpx;
font-family: DIN Next LT Pro;
font-weight: 400;
color: #2FCD81;
// text-align: center
}
.zbzs{
color: #2FCD81;
}
.szqs{
width: 53rpx;
display: flex;
align-items: center;
justify-content: center;
}
.szqs image{
width: 24rpx;
height: 31rpx;
}
.sbsj{
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
flex: 1;
// text-align: center
// text-align: right;
}
.szqss{
width: 24rpx;
}
.load {
height: 100%;
line-height: 550rpx;
text-align: center;
color: #c6c6c6;
font-size: 32rpx;
}
</style>

View File

@ -0,0 +1,280 @@
<template>
<view class="container">
<view class="liebiaos" v-if="list.length">
<scroll-view :style="{height:scorllheight + 'rpx'}" scroll-y="true" class="scroll-Y">
<view class="list_item" v-for="(it,i) in list" :key="i">
<view class="list_item_top">
<view class="list_item_left">
<image v-if="it[0].stationType == 'orient'" src="../../static/zd.png" mode=""></image>
<image v-if="it[0].stationType == 'livestock'" src="../../static/zhandian_icon_xuqin.png" mode=""></image>
<view class="item_right">
<view class="right_top">
{{it[0].stationName}}
</view>
<view class="right_bot">
<image src="../../static/shebei_icon_shebei.png" mode=""></image>
<view class="">设备数量{{it.length}} </view>
</view>
</view>
</view>
<view class="state">
<view class="">
在线
</view>
<image src="../../static/zhandian_icon_zaixian .png" mode="" class="zt"></image>
</view>
</view>
<view class="botcontent">
<block v-for="(item,index) in it" :key="index">
<view class="botcontent_left" @click="todetail(item,index)">
<view class="botleft_left">
<view class="botleftleft_top">
<image :src="baseUrl + '/applet/common/static/' + item.deviceInfo.deviceIcon" mode=""></image>
</view>
<view class="botleftleft_bot">
<view class="botleft_bottop">
{{item.deviceInfo.deviceName}}
</view>
<!-- <view class="botleft_botbot">
型号{{item.deviceInfo.deviceModel}}
</view> -->
</view>
</view>
</view>
</block>
</view>
</view>
</scroll-view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default{
data(){
return{
height:0,
scorllheight:0,
baseUrl:configService.apiUrl,
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
show:false,
show1:false,
top:0,
list:[]
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height
}
});
this.getList()
},
methods:{
getList(){
uni.showLoading({
title: '加载中'
});
this.$http.get('/applet/survStationInfo/deviceList').then(res =>{
this.list = res.data.data
uni.hideLoading();
})
},
todetail(item,index){
console.log(item,12)
uni.navigateTo({
url:'/packDetail/pages/vidio/detail?item=' + encodeURIComponent(JSON.stringify(item))
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
}
.container{
height: 100%;
// overflow-y: scroll;
// overflow-x: hidden;
}
.bgimg{
width: 100%;
height: 3631rpx;
}
.liebiaos{
padding: 28rpx 32rpx;
}
.list_item{
width: 100%;
padding: 37rpx 34rpx 28rpx;
background: #FFFFFF;
border-radius: 34rpx;
margin-bottom: 25rpx;
position: relative;
}
.list_item:last-child{
margin-bottom: 0;
}
.list_item_top{
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 25rpx;
}
.list_item_left{
display: flex;
align-items: center;
}
.list_item_left image{
width: 73rpx;
height: 73rpx;
margin-right: 18rpx;
}
.item_right{
height: 76rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.right_top{
font-size: 32rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
}
.right_bot{
display: flex;
align-items: center;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #9CA9BE;
}
.right_bot image{
height: 26rpx;
width: 24rpx;
margin-right: 11rpx;
}
.jt{
width: 40rpx;
height: 48rpx;
}
.state{
background: #F6F6F6;
border-top-left-radius: 26rpx;
border-bottom-left-radius: 26rpx;
width: 171rpx;
height: 52rpx;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #5F7088;
display: flex;
align-items: center;
padding-left: 24rpx;
box-sizing: border-box;
position: absolute;
top: 31rpx;
right: -32rpx;
}
.zt{
width: 24rpx;
height: 24rpx;
margin-left: 18rpx;
}
.botcontent{
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.botcontent_left{
width: 48%;
background: #F8F8F8;
border-radius: 24rpx;
padding: 44rpx 5rpx 44rpx 5rpx;
margin-top: 20rpx;
}
.botcontent_left image{
width: 61rpx;
height: 61rpx;
}
.botleftleft_top{
display: flex;
justify-content: center;
margin-bottom: 24rpx;
}
.botleftleft_top image{
width: 65rpx;
height: 65rpx;
}
.botleftleft_bot{
display: flex;
flex-direction: column;
align-items: center;
}
.botleft_bottop{
width: 70%;
font-size: 28rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #333333;
text-align: center;
}
.botleft_botbot{
width: 60%;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #9CA9BE;
margin-top: 17rpx;
word-break: break-all;
// text-align: center;
}
.zwsj{
width: 100%;
height: 100%;
display: flex;
padding: 60% 170rpx 0;
}
.inzwsj{
width: 100%;
}
.zwsjimg{
width: 100%;
height: 224rpx;
margin-bottom: 37rpx;
}
.zwsjtext{
width: 100%;
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #999999;
line-height: 31rpx;
text-align: center;
}
</style>

View File

@ -0,0 +1,401 @@
<template>
<view class="container">
<view class="form">
<view class="form_item">
<view class="form_top">
选择站点:
</view>
<view class="form_bot">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="dates">
<view class="uni-input" v-if="!survMulchRecord.stationName" style="color: #808080;">请选择监测站点</view>
<view class="uni-input" v-else>{{survMulchRecord.stationName}}</view>
</view>
<image class="dateimg" src="../../../static/xiala.png" mode="" style="width: 32rpx;height: 16rpx;"></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
采样时间:
</view>
<view class="form_bot">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="bindDateChange">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!survMulchRecord.sampTime">请选择采样时间</view>
<view class="uni-input" v-else>{{survMulchRecord.sampTime}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
覆膜作物:
</view>
<view class="form_bot">
<input type="text" placeholder="请输入覆膜作物" v-model="survMulchRecord.cropName" @blur="crop">
</view>
</view>
<view class="form_item">
<view class="form_top">
覆膜年份:
</view>
<view class="form_bot">
<picker mode="date" fields="year" :value="year" :start="startDate" :end="endDate" @change="bindDateChangeyear">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!survMulchRecord.mulchYear">请选择覆膜年份</view>
<view class="uni-input" v-else>{{survMulchRecord.mulchYear}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
覆膜残留量:
</view>
<view class="form_bot" style="display: flex;">
<input type="text" placeholder="请输入覆膜残留量" v-model="survMulchRecord.mulchRemain" style="width: 90%;">
<span class="dw">kg/hm²</span>
</view>
</view>
<view class="item_pic">
<view class="pic_top">
相关图片:
</view>
<view class="pic_bot">
<view class="imgList">
<image class="imgs2" src="../../static/upload.png" mode="" @click="uploadimg()"></image>
<view class="imgs1" v-for="(item,index) in imglist" :key="index">
<image class="imgs" @click="seepic(item)" :src="baseUrl + '/applet/common/static/' + item.path" mode=""></image>
<image class="delet" src="../../static/del_people.png" mode="" @click="todelet(index)"></image>
</view>
</view>
</view>
</view>
<view class="bz_item">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea v-model="survMulchRecord.mNote" style="width: 100%;" @blur="mNote"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="tosubmit()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default{
data(){
return{
array:[],
arrays:[],
survMulchRecord:{
sampTime:'',
mulchYear:'',
mulchRemain:'',
cropName:'',
stationName:'',
stationCode:'',
mNote:'',
mPics:[]
},
index:'',
imglist:[],
mpics:[],
baseUrl:configService.apiUrl,
uploadUrl:'/applet/common/upload',
reload:'true'
}
},
onLoad() {
},
onShow() {
this.getazsurvMulchRecord()
},
methods:{
getazsurvMulchRecord(){
this.array = []
this.arrays = []
this.$http.get('/applet/survStationInfo/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.arrays.push({
label:res.data.data[i].stationName,
value:res.data.data[i].stationCode
})
this.array.push(res.data.data[i].stationName)
console.log(this.array)
}
})
},
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
console.log(this.index)
this.survMulchRecord.stationName = this.array[this.index]
for(var i=0;i<this.arrays.length;i++){
if(this.survMulchRecord.stationName == this.arrays[i].label){
this.survMulchRecord.stationCode = this.arrays[i].value
}
}
console.log(this.survMulchRecord)
},
bindDateChange: function(e) {
this.survMulchRecord.sampTime = e.detail.value
},
bindDateChangeyear: function(e){
this.survMulchRecord.mulchYear = e.detail.value
},
mNote(e){
this.survMulchRecord.mNote = e.detail.value
},
crop(e){
this.survMulchRecord.cropName = e.detail.value
},
uploadimg(){
var that = this
uni.chooseImage({
count: 9,
sizeType: ['original', 'compressed'], //
sourceType: ['album', 'camera'], //
success: function (res) {
var tempFilesSize = res.tempFiles[0].size; //B
if (tempFilesSize <= 2000000) { //2M
let params = {}
params.file = res.tempFilePaths[0]
params.biz = 'busi'
var tempFilePaths = res.tempFilePaths
for(var i=0;i<tempFilePaths.length;i++){
that.$http.upload(that.baseUrl+that.uploadUrl,{
filePath: res.tempFilePaths[i],
name: 'file',
formData:{
file:res.tempFilePaths[i],
biz:'busi'
}
}).then(res =>{
console.log(res.data)
var imglist = that.imglist
imglist.push({
path:res.data.data.savePath,
fileid:res.data.data.savePath
})
var mpics = that.mpics
mpics.push(res.data.data.savePath)
console.log(imglist,1456145)
})
}
}else {
uni.showToast({
title: '上传图片不能大于2M!', //
icon: 'none' // none使
})
}
}
});
},
//
seepic(item) {
console.log(item.path,'图片路径')
let photoList = this.imglist.map(item => {
return this.baseUrl + '/applet/common/static/' + item.path;
});
uni.previewImage({
current: 0, // /
urls: photoList, // photoList
loop:true //
});
},
todelet(index){
this.imglist.splice(index,1)
this.mpics.splice(index,1)
},
tosubmit(){
this.survMulchRecord.mPics = this.mpics
if(!this.survMulchRecord.stationCode){
uni.showToast({
title: "请选择站点",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.sampTime){
uni.showToast({
title: "请选择采样时间",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.cropName){
uni.showToast({
title: "请输入覆膜作物",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.mulchYear){
uni.showToast({
title: "请选择覆膜年份",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.mulchRemain){
uni.showToast({
title: "请输入覆膜残留量",
icon: 'none',
duration: 2000
})
return
}
if(this.survMulchRecord.mPics.length == 0){
uni.showToast({
title: "请至少上传一张图片",
icon: 'none',
duration: 2000
})
return
}
this.$http.post('/applet/survMulchRecord/add',this.survMulchRecord).then(res=>{
uni.showLoading({
title: '正在提交...'
});
if(res.data.code == 0){
uni.hideLoading();
uni.navigateBack()
let pages = getCurrentPages();
let prevPage = pages[ pages.length - 2 ];
prevPage.$vm.reload = this.reload;
}
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: white;
}
.form{
padding: 0 30rpx;
}
.form_item{
padding-top: 33rpx;
padding-bottom: 25rpx;
border-bottom: 1rpx solid #e6e6e6;
}
.form_top{
margin-bottom: 26rpx;
font-weight: bold;
}
.form_bot{
position: relative;
}
.dates{
display: flex;
align-items: center;
justify-content: space-between;
}
.dateimg{
height: 32rpx;
width: 32rpx;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.dw{
color: #2ac066;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgs2{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgs1{
width: 130rpx;
height: 130rpx;
position: relative;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgs{
width: 130rpx;
height: 130rpx;
}
.imgs1:nth-child(4n){
margin-right: 0rpx;
}
.imgs image{
width: 100%;
height: 100%;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz{
margin-left: 30rpx;
}
.pic_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
border: 1rpx solid #ececec;
border-radius: 10rpx;
padding: 16rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.pagebot{
height: 200rpx;
}
.delet{
width: 40rpx;
height: 40rpx;
position: absolute;
top: -10rpx;
right: -10rpx;
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<view class="container">
<view class="form">
<view class="form_item" v-if="survMulchRecord.stationName">
<view class="left">选择站点:</view>
<view class="nr">{{survMulchRecord.stationName}}</view>
</view>
<view class="form_item" v-if="survMulchRecord.sampTime">
<view class="left">采样时间:</view>
<view class="nr">{{survMulchRecord.sampTime}}</view>
</view>
<view class="form_item" v-if="survMulchRecord.cropName">
<view class="left">覆膜作物:</view>
<view class="nr">{{survMulchRecord.cropName}}</view>
</view>
<view class="form_item" v-if="survMulchRecord.mulchYear">
<view class="left">覆膜年份:</view>
<view class="nr">{{survMulchRecord.mulchYear}}</view>
</view>
<view class="form_item" v-if="survMulchRecord.mulchRemain">
<view class="left">覆膜残留量:</view>
<view class="nr">{{survMulchRecord.mulchRemain}}kg/hm²</view>
</view>
<view class="item_pic" v-if="imglist.length!=0">
<view class="pic_top">
相关图片:
</view>
<view class="pic_bot">
<view class="imgList">
<image @click="seepic(item)" v-for="(item,index) in imglist" :key="index" :src="item.path" mode=""></image>
</view>
</view>
</view>
<view class="bz_item" v-if="survMulchRecord.mNote">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea v-model="survMulchRecord.mNote" disabled="true" placeholder="请输入备注" style="width: 100%;"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="toback()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default{
data(){
return{
array:[],
arrays:[],
survMulchRecord:{
sampTime:'',
mulchYear:'',
mulchRemain:'',
cropName:'',
stationName:'',
stationCode:'',
mNote:'',
mPics:[],
id:''
},
index:'',
imglist:[],
mpics:[],
baseUrl:configService.apiUrl,
uploadUrl:'/applet/common/upload',
}
},
onLoad(options) {
this.survMulchRecord = JSON.parse(decodeURIComponent(options.item));
console.log(this.survMulchRecord)
this.mpics = this.survMulchRecord.mPics
console.log(this.mpics)
this.imglist = []
var imglist = this.imglist
for(var i=0;i<this.mpics.length;i++){
imglist.push({
path:this.baseUrl + '/applet/common/static/' + this.mpics[i],
fileid:this.mpics[i]
})
}
console.log(this.imglist,'图片')
},
onShow() {
},
methods:{
toback(){
uni.navigateBack({
delta:1
})
},
//
seepic(item) {
console.log(item.path,'图片路径')
let photoList = this.imglist.map(item => {
return item.path;
});
uni.previewImage({
current: 0, // /
urls: photoList, // photoList
loop:true //
});
},
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: #fff;
}
.form{
padding: 0 30rpx;
}
.form_item{
display: flex;
justify-content: space-between;
padding: 30rpx 0rpx;
border-bottom:1rpx solid #e4e4e4;
// font-weight: 500
}
.left{
font-weight: bold;
}
.nr{
flex: 1;
color: #767676;
padding-left: 16rpx;
text-align: right;
}
.dw{
color: greenyellow;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgList image{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgList image:nth-child(4n){
margin-right: 0rpx;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
// font-weight: 500;
margin-bottom: 20rpx;
font-weight: bold;
}
.pic_top{
font-weight: bold;
}
.bz{
margin-left: 30rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.dw{
margin-left: 5rpx;
}
.pagebot{
height: 200rpx;
}
</style>

View File

@ -0,0 +1,415 @@
<template>
<view class="container">
<view class="form">
<view class="form_item">
<view class="form_top">
选择站点:
</view>
<view class="form_bot">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="dates">
<view class="uni-input" v-if="!survMulchRecord.stationName" style="color: #808080;">请选择监测站点</view>
<view class="uni-input" v-else>{{survMulchRecord.stationName}}</view>
</view>
<image class="dateimg" src="../../../static/xiala.png" mode="" style="width: 32rpx;height: 16rpx;"></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
采样时间:
</view>
<view class="form_bot">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="bindDateChange">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!survMulchRecord.sampTime">请选择采样时间</view>
<view class="uni-input" v-else>{{survMulchRecord.sampTime}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
覆膜作物:
</view>
<view class="form_bot">
<input type="text" placeholder="请输入覆膜作物" v-model="survMulchRecord.cropName" @blur="crop">
</view>
</view>
<view class="form_item">
<view class="form_top">
覆膜年份:
</view>
<view class="form_bot">
<picker mode="date" fields="year" :value="year" :start="startDate" :end="endDate" @change="bindDateChangeyear">
<view class="dates">
<view class="uni-input" style="color: #808080;" v-if="!survMulchRecord.mulchYear">请选择覆膜年份</view>
<view class="uni-input" v-else>{{survMulchRecord.mulchYear}}</view>
</view>
<image class="dateimg" src="../../static/data.png" mode=""></image>
</picker>
</view>
</view>
<view class="form_item">
<view class="form_top">
覆膜残留量:
</view>
<view class="form_bot" style="display: flex;">
<input type="text" placeholder="请输入覆膜残留量" v-model="survMulchRecord.mulchRemain" style="width: 90%;">
<span class="dw">kg/hm²</span>
</view>
</view>
<view class="item_pic">
<view class="pic_top">
相关图片:
</view>
<view class="pic_bot">
<view class="imgList">
<image class="imgs2" src="../../static/upload.png" mode="" @click="uploadimg()"></image>
<view class="imgs1" v-for="(item,index) in imglist" :key="index">
<image @click="seepic(item)" class="imgs" :src="baseUrl + '/applet/common/static/' + item.path" mode=""></image>
<image class="delet" src="../../static/del_people.png" mode="" @click="todelet(index)"></image>
</view>
</view>
</view>
</view>
<view class="bz_item">
<view class="bz_top">
<span class="bz">:</span>
</view>
<view class="bz_bot">
<textarea v-model="survMulchRecord.mNote" style="width: 100%;" @blur="mNote"/>
</view>
</view>
</view>
<view class="bot_btn">
<button class="primary" @click="tosubmit()"> </button>
</view>
<view class="pagebot"></view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default{
data(){
return{
array:[],
arrays:[],
survMulchRecord:{
sampTime:'',
mulchYear:'',
mulchRemain:'',
cropName:'',
stationName:'',
stationCode:'',
mNote:'',
mPics:[],
id:''
},
index:'',
imglist:[],
mpics:[],
baseUrl:configService.apiUrl,
uploadUrl:'/applet/common/upload',
reload:'true'
}
},
onLoad(options) {
this.survMulchRecord = JSON.parse(decodeURIComponent(options.item));
console.log(this.survMulchRecord)
this.mpics = this.survMulchRecord.mPics
console.log(this.mpics)
this.imglist = []
var imglist = this.imglist
for(var i=0;i<this.mpics.length;i++){
imglist.push({
path:this.mpics[i],
fileid:this.mpics[i]
})
}
},
onShow() {
this.getazsurvMulchRecord()
},
methods:{
getazsurvMulchRecord(){
this.array = []
this.arrays = []
this.$http.get('/applet/survStationInfo/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.arrays.push({
label:res.data.data[i].stationName,
value:res.data.data[i].stationCode
})
this.array.push(res.data.data[i].stationName)
console.log(this.array)
}
})
},
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
console.log(this.index)
this.survMulchRecord.stationName = this.array[this.index]
for(var i=0;i<this.arrays.length;i++){
if(this.survMulchRecord.stationName == this.arrays[i].label){
this.survMulchRecord.stationCode = this.arrays[i].value
}
}
console.log(this.survMulchRecord)
},
bindDateChange: function(e) {
this.survMulchRecord.sampTime = e.detail.value
},
bindDateChangeyear: function(e){
this.survMulchRecord.mulchYear = e.detail.value
},
mNote(e){
this.survMulchRecord.mNote = e.detail.value
},
crop(e){
this.survMulchRecord.cropName = e.detail.value
},
uploadimg(){
var that = this
uni.chooseImage({
count: 9,
sizeType: ['original', 'compressed'], //
sourceType: ['album', 'camera'], //
success: function (res) {
var tempFilesSize = res.tempFiles[0].size; //B
if (tempFilesSize <= 2000000) { //2M
let params = {}
params.file = res.tempFilePaths[0]
params.biz = 'busi'
var tempFilePaths = res.tempFilePaths
for(var i=0;i<tempFilePaths.length;i++){
that.$http.upload(that.baseUrl+that.uploadUrl,{
filePath: res.tempFilePaths[i],
name: 'file',
formData:{
file:res.tempFilePaths[i],
biz:'busi'
}
}).then(res =>{
console.log(res.data)
var imglist = that.imglist
imglist.push({
path:res.data.data.savePath,
fileid:res.data.data.savePath
})
var mpics = that.mpics
mpics.push(res.data.data.savePath)
console.log(imglist,1456145)
})
}
}else {
uni.showToast({
title: '上传图片不能大于2M!', //
icon: 'none' // none使
})
}
}
});
},
todelet(index){
this.imglist.splice(index,1)
this.mpics.splice(index,1)
},
//
seepic(item) {
console.log(item.path,'图片路径')
let photoList = this.imglist.map(item => {
return this.baseUrl + '/applet/common/static/' + item.path;
});
uni.previewImage({
current: 0, // /
urls: photoList, // photoList
loop:true //
});
},
tosubmit(){
this.survMulchRecord.mPics = this.mpics
if(!this.survMulchRecord.stationCode){
uni.showToast({
title: "请选择站点",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.sampTime){
uni.showToast({
title: "请选择采样时间",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.cropName){
uni.showToast({
title: "请输入覆膜作物",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.mulchYear){
uni.showToast({
title: "请选择覆膜年份",
icon: 'none',
duration: 2000
})
return
}
if(!this.survMulchRecord.mulchRemain){
uni.showToast({
title: "请输入覆膜残留量",
icon: 'none',
duration: 2000
})
return
}
if(this.survMulchRecord.mPics.length == 0){
uni.showToast({
title: "请至少上传一张图片",
icon: 'none',
duration: 2000
})
return
}
console.log(this.survMulchRecord)
this.$http.post('/applet/survMulchRecord/edit',this.survMulchRecord).then(res=>{
uni.showLoading({
title: '正在提交...'
});
if(res.data.code == 0){
uni.hideLoading();
uni.navigateBack()
let pages = getCurrentPages();
let prevPage = pages[ pages.length - 2 ];
prevPage.$vm.reload = this.reload;
}
})
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
background-color: white;
}
.form{
padding: 0 30rpx;
}
.form_item{
padding-top: 33rpx;
padding-bottom: 25rpx;
border-bottom: 1rpx solid #e6e6e6;
}
.form_top{
margin-bottom: 26rpx;
font-weight: bold;
}
.form_bot{
position: relative;
}
.dates{
display: flex;
align-items: center;
justify-content: space-between;
}
.dateimg{
height: 32rpx;
width: 32rpx;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.dw{
color: #2ac066;
}
.item_pic{
border-bottom:1rpx solid #e4e4e4;
padding: 30rpx 0rpx;
font-weight: 500;
}
.imgList{
display: flex;
flex-wrap: wrap;
}
.imgs2{
width: 130rpx;
height: 130rpx;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgs1{
width: 130rpx;
height: 130rpx;
position: relative;
margin-right: 24rpx;
margin-top: 20rpx;
}
.imgs{
width: 130rpx;
height: 130rpx;
}
.imgs1:nth-child(4n){
margin-right: 0rpx;
}
.imgs image{
width: 100%;
height: 100%;
}
.bz_item{
padding: 40rpx 0rpx;
}
.bz_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz{
margin-left: 30rpx;
}
.pic_top{
font-weight: bold;
margin-bottom: 26rpx;
}
.bz_bot{
color: #767676;
line-height: 50rpx;
border: 1rpx solid #ececec;
border-radius: 10rpx;
padding: 16rpx;
}
.bot_btn{
padding: 0 30rpx;
margin-top: 30rpx;
}
.primary{
width: 100%;
height: 90rpx;
background-color: #0F6EFF;
border: none;
border-radius: 50rpx;
color:#fff;
font-weight: bold;
}
.pagebot{
height: 200rpx;
}
.delet{
width: 40rpx;
height: 40rpx;
position: absolute;
top: -10rpx;
right: -10rpx;
}
</style>

View File

@ -0,0 +1,501 @@
<template>
<view class="container">
<scroll-view scroll-y="true" :style="{height:height + 'rpx'}" @refresherrefresh="refresherrefreshFun" @refresherpulling="refresherpullingFun" :refresher-triggered="isRefresher" refresher-enabled="true">
<view class="topcheck">
<view class="left">
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="uni-input" v-if="!stationName">选择站点 <image src="../../static/xia.png"></image></view>
<view class="uni-input" v-else>{{stationName}} <image src="../../static/xia.png"></image></view>
</picker>
</view>
<view class="right">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="bindDateChange">
<view class="uni-input" v-if="!sampTime">选择日期 <image src="../../static/xia.png"></image></view>
<view class="uni-input" v-else>{{sampTime}} <image src="../../static/xia.png"></image></view>
</picker>
</view>
</view>
<view class="searchbox">
<image src="../../static/meishi_icon_sousuo.png" mode=""></image>
<input class="search_input" v-model="cropName" placeholder="请输入要搜索的覆膜作物">
<view class="searchbutton" @click="changenr()">
搜索
</view>
</view>
<view class="liebiaos" v-if="List.length != 0">
<scroll-view :style="{height:scorllheight + 'rpx'}" scroll-y="true" class="scroll-Y" @scrolltolower="lower">
<view class="itembox" v-for="(item,index) in List" :key="index">
<view class="itembox_top">
<view class="itembox_lef" @click="todetails(item,index)">
<image src="../../static/fz.png" mode=""></image>
<view class="title">
{{item.stationName}}
</view>
</view>
<view class="caozuo" @click="caozuo(item)">
<image src="../../static/dian.png" mode=""></image>
</view>
</view>
<view class="itembox_bot" @click="todetails(item,index)">
<view class="bot_item">
<span class="nrbt">覆膜作物:</span>
{{item.cropName}}
</view>
<view class="bot_item">
<span class="nrbt">地膜残留量:</span>
<span class="number">{{item.mulchRemain}}kg/hm²</span>
</view>
<view class="bot_item">
<span class="nrbt">采样时间:</span>
{{item.sampTime}}
</view>
</view>
</view>
<view class="load">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
<image @click="toadd()" class="add" src="../../static/add.png" mode=""></image>
</scroll-view>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default {
data() {
return {
List:[],
baseUrl:configService.apiUrl,
array:[],
index:'',
sampTime:'',
cropName:'',
allNum: '',
isLastpage: '',
intervalId: null,
loadStatus:'more', //more-loading-nomore-
isLoadMore:false, //
height:0,
scorllheight:0,
show:false,
show1:false,
top:0,
pageNo:1,
pageSize:4,
deleteUrl:'/applet/survMulchRecord/delete',
stationName:'',
stationCode:'',
sampTime:'',
arrays:[],
isRefresher: false, //
reload:''
}
},
onLoad() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 182
}
});
this.getList()
},
onShow() {
uni.getSystemInfo({
success: res => {
var pxToRpxScale = 750 / res.windowWidth
var ktxStatusHeight = res.statusBarHeight * pxToRpxScale
var navigationHeight = 44 * pxToRpxScale
this.height = res.windowHeight * pxToRpxScale//px rpx
console.log(this.height,ktxStatusHeight,navigationHeight)
this.scorllheight = this.height - 182
}
});
let pages = getCurrentPages();
let currPage = pages[pages.length - 1]; //
this.reload = currPage.data.reload
console.log('this.reload',this.reload)
if(this.reload){
this.cropName = ''
this.sampTime = ''
this.stationCode = ''
this.stationName = ''
this.pageNo = 1
this.getList()
this.reload = ''
}
this.getazsurvMulchRecord()
},
methods:{
getazsurvMulchRecord(){
this.array = []
this.arrays = []
this.$http.get('/applet/survStationInfo/list').then(res=>{
for(var i=0;i<res.data.data.length;i++){
this.arrays.push({
label:res.data.data[i].stationName,
value:res.data.data[i].stationCode
})
this.array.push(res.data.data[i].stationName)
console.log(this.array)
}
})
},
//
refresherrefreshFun() {
this.cropName = ''
this.sampTime = ''
this.stationCode = ''
this.stationName = ''
this.pageNo = 1
this.getList()
},
//
refresherpullingFun() {
this.isRefresher= true
},
getList(){
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.cropName = this.cropName
params.sampTime = this.sampTime
params.stationCode = this.stationCode
params.stationName = this.stationName
uni.showLoading({
title: '加载中'
});
this.List = []
this.$http.get('/applet/survMulchRecord/list',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
if(res.data.data.total != 0){
this.allNum = Number(res.data.data.total)/Number(this.pageSize)+'';
console.log(this.allNum,'总页数')
if(this.allNum.indexOf('.') == -1) {
this.allNum = this.allNum;
console.log(this.allNum,'if')
} else {
this.allNum = parseInt(Number(this.allNum)+1);
console.log(this.allNum,'else')
}
console.log(this.pageNo,this.allNum,'156156')
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true','nomore')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
uni.hideLoading();
this.isRefresher= false
})
},
lower() {
console.log("最后一页了,取消下拉功能");
//
if (this.isLastpage) {
return
}
clearInterval(this.intervalId);
var num = 1;
this.intervalId = setInterval(() => {
num = num+1;
},1000)
console.log(this.intervalId,num)
this.pageNo = this.pageNo + 1;
let params = {}
params.pageNo = this.pageNo
params.pageSize = this.pageSize
params.cropName = this.cropName
params.sampTime = this.sampTime
params.stationCode = this.stationCode
params.stationName = this.stationName
this.$http.get('/applet/survMulchRecord/list',{params:params}).then(res =>{
if(res.data.code == 0){
var data = res.data.data.records
this.List = this.List.concat(data)
if(res.data.data.total != 0){
if(this.pageNo == this.allNum) {
this.isLastpage = true;
this.loadStatus='nomore'
console.log(this.isLastpage,'true')
} else {
this.isLastpage = false;
// this.isLoadMore=true
this.loadStatus = 'more'
console.log(this.isLastpage,'false')
}
}else{
this.isLastpage = true;
this.loadStatus='nomore'
}
}
})
},
bindPickerChange: function(e) {
console.log('picker发送选择改变携带值为', e.detail.value)
this.index = e.detail.value
this.stationName = this.array[this.index]
for(var i=0;i<this.arrays.length;i++){
if(this.stationName == this.arrays[i].label){
this.stationCode = this.arrays[i].value
}
}
this.pageNo = 1
this.getList()
},
bindDateChange: function(e) {
this.sampTime = e.detail.value
this.pageNo = 1
this.getList()
},
changenr(){
console.log(this.cropName)
this.pageNo = 1
this.getList()
},
todetails(item,index){
uni.navigateTo({
url:'/packDetail/pages/waste/detail?item=' + encodeURIComponent(JSON.stringify(item))
})
},
toadd(){
uni.navigateTo({
url:'/packDetail/pages/waste/add'
})
},
caozuo(item){
console.log(item)
var that = this
uni.showActionSheet({
itemList: ['编辑', '删除'],
success: function (res) {
console.log('选中了第' + (res.tapIndex + 1) + '个按钮');
if((res.tapIndex + 1) == 1){
uni.navigateTo({
url:'/packDetail/pages/waste/edit?item='+ encodeURIComponent(JSON.stringify(item))
})
}else{
uni.showModal({
title: '提示',
content: '是否删除数据?',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
console.log(item.id,1)
that.$http.delete(that.deleteUrl+'?id='+item.id).then(res =>{
if(res.data.code == 0){
uni.showToast({
title: '删除成功',
icon:'success',
duration: 2000
});
that.cropName = ''
that.sampTime = ''
that.stationCode = ''
that.stationName = ''
that.pageNo = 1
that.getList()
}
})
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
},
fail: function (res) {
console.log(res.errMsg);
}
});
}
}
}
</script>
<style lang="scss">
page{
height: 100%;
}
.container{
height: 100%;
}
.topcheck{
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1rpx solid #ededed;
background-color: white;
}
.left{
width: 50%;
display: flex;
justify-content: center;
}
.right{
width: 50%;
border-left: 4rpx solid #ededed;
display: flex;
justify-content: center;
}
.searchbox{
padding: 20rpx 30rpx;
background-color: white;
position: relative;
display: flex;
justify-content: space-between;
}
.search_input{
border: none;
height: 60rpx;
width: 86%;
font-size: 24rpx;
border-radius: 30rpx;
background-color: #F6F6F6;
padding-left: 50rpx;
}
.searchbox image{
width: 32rpx;
height: 32rpx;
position: absolute;
left: 40rpx;
top: 35%;
z-index: 99;
}
.searchbutton{
width: 10%;
height: 60rpx;
font-size: 26rpx;
text-align: center;
line-height: 60rpx;
}
.itembox{
background-color: white;
padding: 30rpx;
margin-top: 20rpx;
}
.itembox:first-child{
margin-top: 0;
}
.uni-input{
display: flex;
align-items: center;
}
.uni-input image{
height: 12rpx;
width: 24rpx;
margin-left: 5rpx;
}
.itembox_top{
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 30rpx;
border-bottom: 2rpx solid #e4e4e4;
}
.itembox_lef image{
width: 40rpx;
height: 40rpx;
margin-right: 14rpx;
}
.itembox_lef{
display: flex;
align-items: center;
font-weight: 500;
width: 70%;
}
.caozuo{
height: 100%;
display: flex;
align-items: center;
flex:1;
justify-content: flex-end;
}
.caozuo image{
width: 7rpx;
height: 29rpx;
z-index: 99;
}
.bot_item{
margin-top: 30rpx;
}
.nrbt{
color: #898989;
margin-right: 10rpx;
}
.number{
color: #26bf64;
}
// .numbers{
// color:#26bf64;
// }
.load{
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
.add{
height: 150rpx;
width: 150rpx;
position: fixed;
bottom: 100rpx;
right: 60rpx;
}
.popup{
background-color: white;
height: 100%;
width: 100%;
}
.title{
font-weight: bold;
}
.zwsj{
width: 100%;
display: flex;
padding: 60% 170rpx 0;
}
.inzwsj{
width: 100%;
}
.zwsjimg{
width: 100%;
height: 224rpx;
margin-bottom: 37rpx;
}
.zwsjtext{
width: 100%;
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #999999;
line-height: 31rpx;
text-align: center;
}
</style>

BIN
packDetail/static/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
packDetail/static/data.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

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