巡检
This commit is contained in:
BIN
nativeplugins/LF-Sense-Card/android/uniplugin_m1card-release.aar
Normal file
BIN
nativeplugins/LF-Sense-Card/android/uniplugin_m1card-release.aar
Normal file
Binary file not shown.
201
nativeplugins/LF-Sense-Card/license.md
Normal file
201
nativeplugins/LF-Sense-Card/license.md
Normal 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 [2020] 雷龙飞[1102228556@qq.com]
|
||||
|
||||
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.
|
||||
42
nativeplugins/LF-Sense-Card/package.json
Normal file
42
nativeplugins/LF-Sense-Card/package.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "Android-NFC读卡",
|
||||
"id": "LF-Sense-Card",
|
||||
"version": "0.0.2",
|
||||
"description": "uni-app android原生插件 用来使用nfc读取m1卡",
|
||||
"_dp_type": "nativeplugin",
|
||||
"_dp_nativeplugin": {
|
||||
"android": {
|
||||
"plugins": [
|
||||
{
|
||||
"type": "module",
|
||||
"name": "LF-Sense-Card-M1",
|
||||
"class": "com.clubank.uniplugin_m1card.M1CardModule"
|
||||
}
|
||||
],
|
||||
"hooksClass": "",
|
||||
"integrateType": "aar",
|
||||
"dependencies": [],
|
||||
"compileOptions": {
|
||||
"sourceCompatibility": "1.8",
|
||||
"targetCompatibility": "1.8"
|
||||
},
|
||||
"abis": [
|
||||
"armeabi-v7a",
|
||||
"arm64-v8a",
|
||||
"x86"
|
||||
],
|
||||
"minSdkVersion": 19,
|
||||
"useAndroidX": false,
|
||||
"permissions": [
|
||||
"<uses-permission android:name=\"android.permission.NFC\" />"
|
||||
],
|
||||
"parameters": {
|
||||
"插件需要配置的参数名称, 如appid": {
|
||||
"des": "参数描述",
|
||||
"key": "AndroidManifest.xml中添加meta-data节点!对应android:name属性值, 如GETUI_APPID",
|
||||
"placeholder": "build.gradle中添加到manifestPlaceholders中的字段名"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
93
src/components/mediaPreview.vue
Normal file
93
src/components/mediaPreview.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<!-- 放大后的遮罩层 -->
|
||||
<view v-if="isEnlarged" class="image-preview-overlay" @click="handleClose">
|
||||
<block v-if="getFileType(mediaUrl)=='image'">
|
||||
<image
|
||||
:src="mediaUrl"
|
||||
mode="widthFix"
|
||||
class="enlarged-image"
|
||||
/>
|
||||
</block>
|
||||
<view :class="videoClass" v-else-if="getFileType(mediaUrl)=='video'">
|
||||
<!-- object-fit="cover" -->
|
||||
<video :src="mediaUrl" controls @loadedmetadata="onVideoLoaded"></video>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref,watch } from 'vue';
|
||||
import {getFileType} from '@/utils/common.js';
|
||||
const props = defineProps({
|
||||
visible:{
|
||||
type:Boolean
|
||||
},
|
||||
url:{}//图片路径
|
||||
})
|
||||
|
||||
const isEnlarged = ref(props.visible);
|
||||
const mediaUrl = ref(props.url);//http://192.168.236.184:9000/718ys-test/polling/2483ee76b28b4d43b87c13386dad90bb.jpg
|
||||
// const mediaType = ref('');//类型
|
||||
// 显示隐藏
|
||||
watch(() => props.visible, (newVal, oldVal) => {
|
||||
isEnlarged.value = newVal
|
||||
},{
|
||||
deep:true, // 深度监听
|
||||
immediate:true // 立即执行
|
||||
});
|
||||
|
||||
watch(() => props.url, (newVal, oldVal) => {
|
||||
mediaUrl.value = newVal;
|
||||
},{
|
||||
deep:true,
|
||||
immediate:true
|
||||
});
|
||||
const emit = defineEmits(['close'])
|
||||
const handleClose=()=>{
|
||||
emit('close');
|
||||
}
|
||||
|
||||
// 获取视频的宽和高
|
||||
let videoClass = ref('enlarged-image');
|
||||
const onVideoLoaded = (e) => {
|
||||
// 通过事件对象获取原始宽高[citation:3]
|
||||
let w = e.detail.width;
|
||||
let h = e.detail.height;
|
||||
// 你也可以在这里进行后续操作,比如根据宽高比调整UI
|
||||
console.log(w,h)
|
||||
if(h>w){
|
||||
videoClass.value="enlarged-image"
|
||||
}else{
|
||||
videoClass.value="enlarged-image"
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.image-preview-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
:deep(uni-video){
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.enlarged-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.enlarged-image2 {
|
||||
width:auto;
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
@@ -112,6 +112,27 @@
|
||||
"pid" : "",
|
||||
"parameters" : {}
|
||||
}
|
||||
},
|
||||
"LF-Sense-Card" : {
|
||||
"插件需要配置的参数名称, 如appid" : "",
|
||||
"__plugin_info__" : {
|
||||
"name" : "Android-NFC读卡",
|
||||
"description" : "uni-app android原生插件 用来使用nfc读取m1卡",
|
||||
"platforms" : "Android",
|
||||
"url" : "",
|
||||
"android_package_name" : "",
|
||||
"ios_bundle_id" : "",
|
||||
"isCloud" : false,
|
||||
"bought" : -1,
|
||||
"pid" : "",
|
||||
"parameters" : {
|
||||
"插件需要配置的参数名称, 如appid" : {
|
||||
"des" : "参数描述",
|
||||
"key" : "AndroidManifest.xml中添加meta-data节点!对应android:name属性值, 如GETUI_APPID",
|
||||
"value" : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<view class="r-l-left">
|
||||
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
|
||||
</view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum).toFixed()+'%'}}</span></view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum*100).toFixed()+'%'}}</span></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="r-list">
|
||||
@@ -102,7 +102,7 @@
|
||||
<view class="r-l-left">
|
||||
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
|
||||
</view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum).toFixed()+'%'}}</span></view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum*100).toFixed()+'%'}}</span></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="r-list">
|
||||
@@ -305,12 +305,12 @@ const handleJump = (item)=>{
|
||||
.white-bg{
|
||||
width: 670rpx;
|
||||
padding: 30rpx 40rpx 40rpx;
|
||||
margin-bottom: 0;
|
||||
margin: 0 auto !important;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
.white-bg2{
|
||||
border-radius: 0;
|
||||
margin-top:20rpx;
|
||||
border-top:20rpx solid #F5F5F5
|
||||
}
|
||||
.report-list{
|
||||
position: relative;
|
||||
|
||||
@@ -129,8 +129,8 @@
|
||||
<view>{{ item.pointName }}</view>
|
||||
</view>
|
||||
<view class="img-flex">
|
||||
<view class="img-show" v-for="(item2,index) in imgArr2" :key="index">
|
||||
<img :src="item2" />
|
||||
<view class="img-show" v-for="(item2,index) in imgArr2" :key="index" @click="showMediaPreview(item2)">
|
||||
<img :src="item2.shortUrl" />
|
||||
</view>
|
||||
<view class="img-con" @click="chooseImage(item)">
|
||||
<img :src="'static/images/polling/icon-AddPic.png'" class="img-pic" />
|
||||
@@ -145,8 +145,8 @@
|
||||
<view>{{ item.pointName }}</view>
|
||||
</view>
|
||||
<view class="img-flex">
|
||||
<view class="img-show" v-for="(item2,index) in videoArr2" :key="index">
|
||||
<video :src="item2" controls></video>
|
||||
<view class="img-show" v-for="(item2,index) in videoArr2" :key="index" @click="showMediaPreview(item2)">
|
||||
<video :src="item2.url" controls v-show="videoShow"></video>
|
||||
</view>
|
||||
<view class="img-con" @click="chooseVideo(item)">
|
||||
<img :src="'static/images/polling/icon-AddVideo.png'" class="img-pic" />
|
||||
@@ -194,6 +194,8 @@
|
||||
ref="showModel3"
|
||||
></customShowModal>
|
||||
|
||||
<!-- 图片放大 -->
|
||||
<mediaPreview :visible="isVisible" :url="mediaUrl" @close="handlePreviewClose"></mediaPreview>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
@@ -205,28 +207,28 @@ import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
|
||||
import multipleSelect from "@/components/multipleSelect.vue";
|
||||
import pollingShowModal from "@/components/pollingShowModal.vue";
|
||||
import customShowModal from "@/components/customShowModal.vue"
|
||||
import mediaPreview from "@/components/mediaPreview.vue"
|
||||
import { parseTime } from '@/utils/datetime.js';
|
||||
import { formatTaskStatus } from '@/utils/status.js';
|
||||
import { taskGroupDetail,submitResult,minioUpload } from '@/api/polling.js'
|
||||
import {compressImageUni,getMinioThumbUrl} from '@/utils/common.js'
|
||||
import {compressImageUni} from '@/utils/common.js'
|
||||
// import {uploadFileMinio} from '@/utils/minio.js'
|
||||
// #ifdef APP-PLUS
|
||||
import nfcUtil from "@/utils/nfcUtil.js"
|
||||
let m1CardModule = uni.requireNativePlugin("LF-Sense-Card-M1")
|
||||
// #endif
|
||||
|
||||
let taskId = ref(undefined);
|
||||
let groupId = ref(undefined);
|
||||
let minioObj = ref({});
|
||||
let minioObj = {};
|
||||
onLoad(option => {
|
||||
// console.log(option)
|
||||
taskId.value = option.taskId;
|
||||
groupId.value = option.groupId;
|
||||
|
||||
minioObj.value = JSON.parse(uni.getStorageSync(MINIO_KEY) || "\{\}")
|
||||
// console.log(minioObj.value)
|
||||
minioObj = JSON.parse(uni.getStorageSync(MINIO_KEY) || "\{\}")
|
||||
// console.log(minioObj)
|
||||
})
|
||||
|
||||
|
||||
// 下拉刷新
|
||||
const mescrollRef = ref(null);
|
||||
const mescrollInit = (mescroll) => {
|
||||
@@ -269,21 +271,24 @@ const getList = async() => {
|
||||
}else if(item.pointType==7){
|
||||
imgArr.value=[];
|
||||
imgArr2.value=[];
|
||||
let imgList = item.resultContent.split(",");
|
||||
let imgList = item.resultContent?.split(",")||[];
|
||||
imgList.forEach(imgUrl=>{
|
||||
imgArr.value.push(imgUrl);
|
||||
let urlNew = minioObj.value.endpoint + "/thumb/"+minioObj.value.bucketName +"/"+imgUrl
|
||||
imgArr2.value.push(urlNew)
|
||||
imgArr2.value.push({
|
||||
shortUrl:minioObj.minioThumbUrl +"/"+imgUrl,
|
||||
url:minioObj.minioUrl +"/"+imgUrl,
|
||||
})
|
||||
})
|
||||
|
||||
}else if(item.pointType==8){
|
||||
videoArr.value=[];
|
||||
videoArr2.value=[]
|
||||
let videoList = item.resultContent.split(",");
|
||||
let videoList = item.resultContent?.split(",")||[];
|
||||
videoList.forEach(videoUrl=>{
|
||||
videoArr.value.push(videoUrl);
|
||||
let urlNew = minioObj.value.endpoint + "/"+minioObj.value.bucketName +"/"+videoUrl
|
||||
videoArr2.value.push(urlNew)
|
||||
videoArr2.value.push({
|
||||
shortUrl:minioObj.minioThumbUrl +"/"+videoUrl,
|
||||
url:minioObj.minioUrl +"/"+videoUrl,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -408,70 +413,32 @@ const chooseVideo = (item) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 放大视频或图片
|
||||
let isVisible= ref(false);//放大处理
|
||||
let mediaUrl= ref('');//放大地址
|
||||
let videoShow = ref(true);
|
||||
const showMediaPreview=(item)=>{
|
||||
console.log("showMediaPreview===")
|
||||
isVisible.value = true;
|
||||
videoShow.value = false;
|
||||
mediaUrl.value = item.url
|
||||
}
|
||||
const handlePreviewClose=()=>{
|
||||
isVisible.value = false;
|
||||
videoShow.value = true;
|
||||
}
|
||||
|
||||
// nfc 处理
|
||||
let discoveryCallback = null
|
||||
let cardUID = ref('');
|
||||
let cardValue = ref('');
|
||||
const initNFC = async(item) => {
|
||||
// console.log("initNFC=>",plus)
|
||||
|
||||
//这里用异步获取读取到的NFC数据
|
||||
const nfcId = await nfcUtil.listenNFCStatus();
|
||||
console.log("initNFC=>",nfcId)
|
||||
|
||||
// 确保在 App 环境
|
||||
// if (typeof plus === 'undefined') {
|
||||
// showModel3('此功能仅支持 App 端')
|
||||
// return
|
||||
// }
|
||||
|
||||
// // 检查设备是否支持NFC
|
||||
// if (!plus.nfc) {
|
||||
// showModel3('设备不支持 NFC')
|
||||
// return;
|
||||
// }
|
||||
// if (!plus.nfc.isSupportNFC()) {
|
||||
// showModel3('设备不支持 NFC')
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // 检查NFC是否开启
|
||||
// plus.nfc.isNFCEnabled((enabled) => {
|
||||
// if (enabled) {
|
||||
// startDiscovery()
|
||||
// } else {
|
||||
// showModel3('请先开启设备NFC功能')
|
||||
// }
|
||||
// },(error) => {
|
||||
// console.error('检查NFC状态失败:'+error.message);
|
||||
// showModel3('检查NFC状态失败')
|
||||
// })
|
||||
}
|
||||
// 执行NFC扫描
|
||||
const startDiscovery = () => {
|
||||
// 开始监听NFC标签
|
||||
plus.nfc.startDiscovery((res) => {
|
||||
console.log('NFC监听启动成功')
|
||||
// 监听NFC标签被发现的事件
|
||||
discoveryCallback = (result) => {
|
||||
try {
|
||||
console.log("NFC监听返回=>",result)
|
||||
// 尝试读取标签ID或NDEF数据
|
||||
const tag = result.tag
|
||||
if (tag && tag.id) {
|
||||
// 将标签ID字节数组转换为十六进制字符串
|
||||
const tagId = tag.id.map(b => b.toString(16).padStart(2, '0')).join(':')
|
||||
console.log(`检测到标签,ID: ${tagId}`)
|
||||
// 此处可以处理tag.ndefMessage等数据
|
||||
} else {
|
||||
console.log( `检测到标签,但无法解析数据`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.log( '处理NFC数据时出错:' + error.message)
|
||||
}
|
||||
}
|
||||
plus.nfc.addEventListener('discovered', discoveryCallback, false)
|
||||
},(err) => {
|
||||
console.log( 'NFC监听启动失败:' + err.message)
|
||||
m1CardModule.openNativeSenseCard({
|
||||
'keyA': 'TestKey',
|
||||
'sector': 0,
|
||||
'block': 0
|
||||
},ret => {
|
||||
cardUID.value = ret.uid
|
||||
cardValue.value = ret.code
|
||||
})
|
||||
}
|
||||
|
||||
@@ -576,8 +543,9 @@ const handleConfirm=()=>{
|
||||
submitResult(submitParam).then(res=>{
|
||||
subTime.value = res;
|
||||
visible.value = false;
|
||||
console.log("submitResult=>",visible.value)
|
||||
// console.log("submitResult=>",visible.value)
|
||||
showModel2('此巡检项已完成');
|
||||
uni.navigateBack();
|
||||
}).finally(() => {
|
||||
submitLoading.value = false;
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
:leftFlag="true" :rightFlag="true"
|
||||
>
|
||||
<template #right>
|
||||
<view class="head-right" @click="handleQuestion">
|
||||
<view class="head-right" @click="handleQuestion" v-if="problemObj.problemStatus==1">
|
||||
<view class="btn-yellow">
|
||||
<uni-icons type="plus" size="20" color="#4C2D11"></uni-icons> 新增跟踪信息
|
||||
</view>
|
||||
@@ -56,18 +56,18 @@
|
||||
<view class="report-list">
|
||||
<block v-for="(item,index) in problemObj.listFile" :key="index">
|
||||
<view class="img-flex">
|
||||
<view class="img-show" v-if="getFileType(item)=='image'">
|
||||
<img :src="item" />
|
||||
<view class="img-show" v-if="getFileType(item)=='image'" @click="showMediaPreview(minioObj.minioUrl+'/'+item)">
|
||||
<img :src="minioObj.minioThumbUrl+'/'+item" />
|
||||
</view>
|
||||
<view class="img-show" v-else-if="getFileType(item)=='video'">
|
||||
<video :src="item" controls></video>
|
||||
<view class="img-show" v-else-if="getFileType(item)=='video'" @click="showMediaPreview(minioObj.minioUrl+'/'+item)">
|
||||
<video :src="minioObj.minioUrl+'/'+item" controls v-show="videoShow"></video>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 当天提的 增加按钮 修改和删除 -->
|
||||
<view class="btn-con" v-if="isToday">
|
||||
<view class="btn-con" v-if="isToday && problemObj.problemStatus==1">
|
||||
<button type="primary" @click="handleUpdate" size="mini" style="margin-right:50rpx;" class="btn-primary">修改</button>
|
||||
<button type="primary" @click="handleDelete" size="mini">删除</button>
|
||||
</view>
|
||||
@@ -88,11 +88,11 @@
|
||||
<view class="report-list">
|
||||
<view class="img-flex">
|
||||
<block v-for="(item,index) in item.listFile" :key="index">
|
||||
<view class="img-show" v-if="getFileType(item)=='image'">
|
||||
<img :src="item" />
|
||||
<view class="img-show" v-if="getFileType(item)=='image'" @click="showMediaPreview(minioObj.minioUrl+'/'+item)">
|
||||
<img :src="minioObj.minioThumbUrl+'/'+item" />
|
||||
</view>
|
||||
<view class="img-show" v-else-if="getFileType(item)=='video'">
|
||||
<video :src="item" controls></video>
|
||||
<view class="img-show" v-else-if="getFileType(item)=='video'" @click="showMediaPreview(minioObj.minioUrl+'/'+item)">
|
||||
<video :src="minioObj.minioUrl+'/'+item" controls v-show="videoShow"></video>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
@@ -103,24 +103,35 @@
|
||||
</view>
|
||||
</mescroll-uni>
|
||||
</view>
|
||||
<!-- 图片放大 -->
|
||||
<mediaPreview :visible="isVisible" :url="mediaUrl" @close="handlePreviewClose"></mediaPreview>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
|
||||
import { onLoad,onHide} from '@dcloudio/uni-app';
|
||||
import { onLoad,onShow,onHide} from '@dcloudio/uni-app';
|
||||
import customHeader from '@/components/customHeader.vue';
|
||||
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
|
||||
import mediaPreview from "@/components/mediaPreview.vue"
|
||||
import { parseTime } from '@/utils/datetime.js';
|
||||
import {getFileType} from '@/utils/common.js';
|
||||
import { problemDetail } from '@/api/polling.js'
|
||||
import { problemDetail,problemDel } from '@/api/polling.js'
|
||||
import { MINIO_KEY } from '@/enums/cacheEnums';
|
||||
import {showAlert,showLoading,hideLoading} from '@/utils/message.js'
|
||||
|
||||
let problemId=ref('');
|
||||
let problemObj = ref({});
|
||||
let isToday = ref(false)
|
||||
let isToday = ref(false);
|
||||
let minioObj = {};
|
||||
onLoad(option => {
|
||||
// console.log(option)
|
||||
problemId.value = option.problemId;
|
||||
minioObj = JSON.parse(uni.getStorageSync(MINIO_KEY) || "\{\}")
|
||||
})
|
||||
|
||||
onShow(()=>{
|
||||
getList();
|
||||
})
|
||||
|
||||
// 下拉刷新
|
||||
@@ -129,7 +140,7 @@ const mescrollInit = (mescroll) => {
|
||||
mescrollRef.value = mescroll;
|
||||
};
|
||||
const downOption = ref({
|
||||
auto: true,
|
||||
auto: false,
|
||||
textInOffset: '下拉刷新',
|
||||
textOutOffset: '释放更新',
|
||||
textLoading: '刷新中...'
|
||||
@@ -150,28 +161,10 @@ const downCallback = async (mescroll) => {
|
||||
const getList = async() => {
|
||||
isToday.value = false;
|
||||
let data = await problemDetail({problemId:problemId.value});
|
||||
// let res = {
|
||||
// "code": 200,
|
||||
// "msg": "操作成功",
|
||||
// "data": {
|
||||
// groupName:'配电箱箱体和内部线路检查',
|
||||
// problemDesc:'电箱右侧箱体有锈蚀,需要及时修补;电箱前门关闭不严,缝隙过大;箱门密封条出现老化痕迹;显示屏出现若干像素坏点。',
|
||||
// planTime:new Date().getTime(),
|
||||
// realname:'张三',
|
||||
// pointName:'技术中心机房总电源,监控室消防设备阀门正常开启闭合,监控室10组灭火器压力指针处于绿色区域',
|
||||
// problemVedio:'http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4',
|
||||
// logList:[
|
||||
// {
|
||||
// logId:1,logDesc:'配电箱箱体和内部线路检查',createTime:new Date().getTime(),modifyUserName:'张三',
|
||||
// logVedio:'http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg',
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
data.list = data.pointName.split(",") || [];
|
||||
data.listFile=data.problemVedio.split(",") || [];
|
||||
data.list = data.pointName?.split(",") || [];
|
||||
data.listFile=data.problemVedio?.split(",") || [];
|
||||
data.logList.forEach(item => {
|
||||
item.listFile = item.logVedio.split(",")||[]
|
||||
item.listFile = item.logVedio?.split(",")||[]
|
||||
});
|
||||
// 判断是否当天创建的,显示按钮
|
||||
let createTime = parseTime(data.createTime,'{y}-{m}-{d}');
|
||||
@@ -182,10 +175,24 @@ const getList = async() => {
|
||||
problemObj.value = data;
|
||||
}
|
||||
|
||||
// 放大视频或图片
|
||||
let isVisible= ref(false);//放大处理
|
||||
let mediaUrl= ref('');//放大地址
|
||||
let videoShow = ref(true);
|
||||
const showMediaPreview=(url)=>{
|
||||
isVisible.value = true;
|
||||
videoShow.value = false;
|
||||
mediaUrl.value = url
|
||||
}
|
||||
const handlePreviewClose=()=>{
|
||||
isVisible.value = false;
|
||||
videoShow.value = true;
|
||||
}
|
||||
|
||||
// 跳转问题上报页面
|
||||
const handleQuestion=()=>{
|
||||
uni.navigateTo({
|
||||
url: '/pages/business/polling/problemLog'
|
||||
url: '/pages/business/polling/problemLog?problemId='+problemId.value
|
||||
});
|
||||
}
|
||||
|
||||
@@ -198,7 +205,15 @@ const handleUpdate=()=>{
|
||||
|
||||
// 删除
|
||||
const handleDelete=()=>{
|
||||
|
||||
showLoading("加载中...")
|
||||
problemDel({problemId:problemId.value}).then(res=>{
|
||||
// content, title = '提示',showCancel=false,succFun
|
||||
showAlert("删除成功!",'提示',false,()=>{
|
||||
uni.navigateBack()
|
||||
})
|
||||
}).finally(()=>{
|
||||
hideLoading();
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -231,7 +246,7 @@ const handleDelete=()=>{
|
||||
}
|
||||
.white-bg{
|
||||
width: 680rpx;
|
||||
padding: 15rpx 30rpx 10rpx 40rpx;
|
||||
padding: 15rpx 30rpx 50rpx 40rpx;
|
||||
margin-bottom: 0;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,6 @@ import customHeader from '@/components/customHeader.vue'
|
||||
import customSearch from '@/components/customSearch.vue'
|
||||
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
|
||||
import { getNavBarPaddingTop } from '@/utils/system.js'
|
||||
import { noticeList } from '@/api/notice.js'
|
||||
import { parseTime } from '@/utils/datetime.js'
|
||||
import { problemList } from '@/api/polling.js'
|
||||
|
||||
@@ -188,90 +187,10 @@ const getList = (pageIndex, pageSize) => {
|
||||
taskType:notictTypeCheck.value.id
|
||||
}
|
||||
let res = await problemList(param);
|
||||
// let res={
|
||||
// "code": 200,
|
||||
// "msg": "操作成功",
|
||||
// "data": {
|
||||
// list:[
|
||||
// {
|
||||
// problemDesc:'西区地下车库入口防汛物资摆放',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:1,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:0,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'监控室消防设备阀门确保正常开启闭合',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:2,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:20,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'西区地下车库入口防汛物资摆放',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:1,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:0,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'监控室消防设备阀门确保正常开启闭合',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:2,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:20,
|
||||
// },{
|
||||
// problemDesc:'西区地下车库入口防汛物资摆放',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:1,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:0,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'监控室消防设备阀门确保正常开启闭合',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:2,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:20,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'监控室消防设备阀门确保正常开启闭合',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:2,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:20,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'监控室消防设备阀门确保正常开启闭合',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:2,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:20,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'监控室消防设备阀门确保正常开启闭合',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:2,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:20,
|
||||
// },
|
||||
// {
|
||||
// problemDesc:'监控室消防设备阀门确保正常开启闭合',
|
||||
// problemId:202512297899,
|
||||
// problemStatus:2,
|
||||
// modifyTime:new Date().getTime(),
|
||||
// count:20,
|
||||
// }
|
||||
// ],
|
||||
// recordCount:2
|
||||
// }
|
||||
// }
|
||||
|
||||
let list = res.list || [];
|
||||
|
||||
resolve({
|
||||
list,
|
||||
total: res.recordCount || 0
|
||||
// total: res.recordCount || 0
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
<!-- 高度来避免头部遮挡 -->
|
||||
<view class="top-height"></view>
|
||||
|
||||
<!-- 下拉刷新 -->
|
||||
<mescroll-uni ref="mescrollRef" @init="mescrollInit"
|
||||
:down="downOption" @down="downCallback"
|
||||
:fixed="false" class="scroll-h"
|
||||
>
|
||||
<view class="white-bg">
|
||||
<view class="red-title">问题:{{optionObj.groupName}}</view>
|
||||
<view class="report-list">
|
||||
@@ -23,8 +28,8 @@
|
||||
</view>
|
||||
<view class="report-border"></view>
|
||||
<view class="report-list">
|
||||
<view class="report-pro">巡检人</view>
|
||||
<view class="report-right">{{realname}}</view>
|
||||
<view class="report-pro">提交人</view>
|
||||
<view class="report-right">{{optionObj.createUserName}}</view>
|
||||
</view>
|
||||
<view class="report-border"></view>
|
||||
<view class="report-list" style="display:block;">
|
||||
@@ -43,83 +48,127 @@
|
||||
<view class="img-show" v-for="(item,index) in videoArr" :key="index">
|
||||
<video :src="item" controls></video>
|
||||
</view>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="img-con" @click="chooseMedia">
|
||||
<img :src="'static/images/polling/icon-AddPorV.png'" class="img-pic" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-PLUS -->
|
||||
<view class="img-con">
|
||||
<img :src="'static/images/polling/icon-AddPorV.png'" class="img-pic" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-submit">
|
||||
<button type="primary" @click="handleSubmit">提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</mescroll-uni>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
|
||||
import { onLoad,onHide} from '@dcloudio/uni-app';
|
||||
import { onLoad,onHide, onShow} from '@dcloudio/uni-app';
|
||||
import customHeader from '@/components/customHeader.vue';
|
||||
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
|
||||
import { getUserInfo } from '@/api/auth.js'
|
||||
import { problemDetail,problemAddLog,minioUpload } from '@/api/polling.js'
|
||||
import { MINIO_KEY } from '@/enums/cacheEnums';
|
||||
import {showAlert,showLoading,hideLoading} from '@/utils/message.js'
|
||||
import {compressImageUni} from '@/utils/common.js'
|
||||
|
||||
let id = ref('');
|
||||
let problemId = ref('');
|
||||
let realname = ref('');
|
||||
let desc = ref('');//描述
|
||||
onLoad(async option => {
|
||||
// console.log(option)
|
||||
id.value = option.id;
|
||||
problemId.value = option.problemId;
|
||||
|
||||
let userinfo = await getUserInfo({});
|
||||
realname.value = userinfo.realname
|
||||
})
|
||||
|
||||
onShow(()=>{
|
||||
getList();
|
||||
})
|
||||
|
||||
// 查询列表
|
||||
let list = ref([]);
|
||||
let optionObj = ref({})
|
||||
|
||||
// 下拉刷新
|
||||
const mescrollRef = ref(null);
|
||||
const mescrollInit = (mescroll) => {
|
||||
mescrollRef.value = mescroll;
|
||||
};
|
||||
const downOption = ref({
|
||||
auto: false,
|
||||
textInOffset: '下拉刷新',
|
||||
textOutOffset: '释放更新',
|
||||
textLoading: '刷新中...'
|
||||
});
|
||||
// 下拉刷新
|
||||
const downCallback = async (mescroll) => {
|
||||
try {
|
||||
getList();
|
||||
} catch (error) {
|
||||
mescroll.endErr();
|
||||
} finally {
|
||||
mescroll.endSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据列表
|
||||
const getList = () => {
|
||||
// let res = await noticeList();
|
||||
// 1 单选 2多选 3判断 4问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位
|
||||
let res = {
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
groupName:'配电箱箱体和内部线路检查',
|
||||
planTime:new Date().getTime(),
|
||||
pointName:'技术中心机房总电源,监控室消防设备阀门正常开启闭合,监控室10组灭火器压力指针处于绿色区域',
|
||||
}
|
||||
}
|
||||
let data = res.data || {};
|
||||
const getList = async () => {
|
||||
let res = await problemDetail({problemId:problemId.value});
|
||||
let data = res || {};
|
||||
data.list = data.pointName.split(",") || [];
|
||||
optionObj.value = data;
|
||||
}
|
||||
|
||||
// 图片或视频
|
||||
let imgArr = ref([]);//视频
|
||||
let videoArr = ref([]);//视频
|
||||
const imgArr2=ref([]);
|
||||
let mediaArr = ref([]);//传给后台的地址
|
||||
let imgArr=ref([]);//图片 后台返回的
|
||||
let videoArr = ref([]);//视频 后台返回的
|
||||
const chooseMedia = () => {
|
||||
imgArr.value=[];
|
||||
videoArr.value=[];
|
||||
uni.chooseMedia({
|
||||
count: 9,
|
||||
mediaType: ['image', 'video'], // 指定可选择图片和视频
|
||||
sourceType: ['album', 'camera'],
|
||||
maxDuration: 30, // 拍摄视频最长拍摄时间
|
||||
maxDuration: 60, // 拍摄视频最长拍摄时间
|
||||
camera: 'back',
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
res.tempFiles.forEach(file => {
|
||||
console.log("问题跟踪chooseMedia=>",res)
|
||||
res.tempFiles.forEach(async file => {
|
||||
console.log(`文件类型: ${file.type}, 文件路径: ${file.tempFilePath}`);
|
||||
if (file.type === 'image') {
|
||||
// 显示本地图片
|
||||
imgArr.value.push(file)
|
||||
} else if (file.type === 'video') {
|
||||
// 处理视频
|
||||
videoArr.value.push(file)
|
||||
let compressImg = file.tempFilePath;
|
||||
// 图片进行压缩
|
||||
if (file.fileType === 'image') {
|
||||
// #ifdef APP-PLUS
|
||||
// 压缩图片
|
||||
compressImg = await compressImageUni(file.tempFilePath);
|
||||
// #endif
|
||||
}
|
||||
// 执行上传
|
||||
let param = {
|
||||
filePath: compressImg,
|
||||
name: 'file',
|
||||
formData: {
|
||||
directory:'polling'
|
||||
},
|
||||
}
|
||||
minioUpload(param).then(res=>{
|
||||
let data = res.data;
|
||||
mediaArr.value.push(data.fileName);
|
||||
if (file.fileType === 'image') {// 图片
|
||||
imgArr.value.push(data.fileUrl)
|
||||
} else if (file.type === 'video') {// 视频
|
||||
videoArr.value.push(data.fileUrl)
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -127,12 +176,33 @@ const chooseMedia = () => {
|
||||
|
||||
// 提交
|
||||
const handleSubmit=()=>{
|
||||
// showModel('有未完成的巡检项');
|
||||
// showModel2('此巡检项已完成');
|
||||
let param = {
|
||||
problemId:problemId.value,
|
||||
logVedio:mediaArr.value.join(","),
|
||||
logDesc:desc.value
|
||||
}
|
||||
console.log("problemAddLog=>",param)
|
||||
problemAddLog(param).then(res=>{
|
||||
showAlert("新建问题跟踪成功!");
|
||||
uni.navigateBack();
|
||||
}).finally(()=>{
|
||||
hideLoading();
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.scroll-h{
|
||||
/* #ifdef APP-PLUS */
|
||||
height:calc(100vh - 78px) !important;
|
||||
/* #endif */
|
||||
/* #ifndef APP-PLUS */
|
||||
height: calc(100vh - 58px) !important;
|
||||
/* #endif */
|
||||
}
|
||||
:deep(.mescroll-upwarp){
|
||||
display: none !important;
|
||||
}
|
||||
.white-bg{
|
||||
width: 680rpx;
|
||||
padding: 15rpx 30rpx 40rpx 40rpx;
|
||||
|
||||
@@ -45,11 +45,11 @@
|
||||
<view class="report-list" style="display:block;">
|
||||
<view class="r-title">问题点位照片或视频 <text>*</text></view>
|
||||
<view class="img-flex">
|
||||
<view class="img-show" v-for="(item,index) in imgArr" :key="index">
|
||||
<img :src="item" />
|
||||
<view class="img-show" v-for="(item,index) in imgArr" :key="index" @click="showMediaPreview(item)">
|
||||
<img :src="item.shortUrl" />
|
||||
</view>
|
||||
<view class="img-show" v-for="(item,index) in videoArr" :key="index">
|
||||
<video :src="item" controls></video>
|
||||
<view class="img-show" v-for="(item,index) in videoArr" :key="index" @click="showMediaPreview(item)">
|
||||
<video :src="item.url" controls></video>
|
||||
</view>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="img-con" @click="chooseMedia">
|
||||
@@ -69,33 +69,42 @@
|
||||
</view>
|
||||
</mescroll-uni>
|
||||
</view>
|
||||
|
||||
<!-- 图片放大 -->
|
||||
<mediaPreview :visible="isVisible" :url="mediaUrl" @close="handlePreviewClose"></mediaPreview>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
|
||||
import { ref,onMounted,onUnmounted,nextTick,computed,reactive, watch } from 'vue'
|
||||
import { onLoad,onHide} from '@dcloudio/uni-app';
|
||||
import customHeader from '@/components/customHeader.vue';
|
||||
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
|
||||
import mediaPreview from "@/components/mediaPreview.vue"
|
||||
import { getUserInfo } from '@/api/auth.js'
|
||||
import { problemDetail,problemAdd,problemEdit,minioUpload } from '@/api/polling.js'
|
||||
import {compressImageUni,getMinioThumbUrl} from '@/utils/common.js'
|
||||
import {compressImageUni,getFileType} from '@/utils/common.js'
|
||||
import {showAlert,showLoading,hideLoading} from '@/utils/message.js'
|
||||
import { MINIO_KEY } from '@/enums/cacheEnums';
|
||||
|
||||
let taskId = ref('');//任务id
|
||||
let groupId = ref('');//组id
|
||||
let problemId = ref('');//问题id
|
||||
let realname = ref('');
|
||||
let desc = ref('');//描述
|
||||
let minioObj = {};
|
||||
onLoad(async option => {
|
||||
// console.log(option)
|
||||
taskId.value = option.taskId;
|
||||
groupId.value = option.groupId;
|
||||
problemId.value = option.problemId;
|
||||
|
||||
minioObj = JSON.parse(uni.getStorageSync(MINIO_KEY) || "\{\}")
|
||||
|
||||
let userinfo = await getUserInfo({});
|
||||
realname.value = userinfo.realname
|
||||
})
|
||||
|
||||
// 查询列表
|
||||
let list = ref([]);
|
||||
let optionObj = ref({})
|
||||
@@ -132,7 +141,7 @@ const getList = async () => {
|
||||
let res = await problemDetail(param);
|
||||
let data = res||{};
|
||||
|
||||
let pointIds = data.pointId.split(",");
|
||||
let pointIds = data.pointId?.split(",") || [];
|
||||
data.pointList.forEach(item2=>{
|
||||
item2.active=false;
|
||||
for (let i = 0; i < pointIds.length; i++) {
|
||||
@@ -143,6 +152,25 @@ const getList = async () => {
|
||||
}
|
||||
})
|
||||
|
||||
// 视频回显
|
||||
imgArr.value = [];
|
||||
mediaArr.value=[];
|
||||
videoArr.value=[];
|
||||
let fileList =data.problemVedio?.split(",") || [];
|
||||
fileList.forEach(item=>{
|
||||
mediaArr.value.push(item)
|
||||
if(getFileType(item)=='image'){
|
||||
imgArr.value.push({
|
||||
shortUrl:minioObj.minioThumbUrl +"/"+item,
|
||||
url:minioObj.minioUrl +"/"+item,
|
||||
})
|
||||
}else if(getFileType(item)=='video'){
|
||||
videoArr.value.push({
|
||||
shortUrl:minioObj.minioThumbUrl +"/"+item,
|
||||
url:minioObj.minioUrl +"/"+item,
|
||||
})
|
||||
}
|
||||
})
|
||||
optionObj.value = data;
|
||||
}
|
||||
|
||||
@@ -158,7 +186,7 @@ const chooseMedia = () => {
|
||||
maxDuration: 60, // 拍摄视频最长拍摄时间
|
||||
camera: 'back',
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
console.log("chooseMedia=>",res)
|
||||
res.tempFiles.forEach(async file => {
|
||||
// tempFilePath
|
||||
console.log(`文件类型: ${file.fileType}, 文件路径: ${file.tempFilePath}`);
|
||||
@@ -183,9 +211,17 @@ const chooseMedia = () => {
|
||||
let data = res.data;
|
||||
mediaArr.value.push(data.fileName);
|
||||
if (file.fileType === 'image') {// 图片
|
||||
imgArr.value.push(data.fileUrl)
|
||||
// imgArr.value.push(data.fileUrl)
|
||||
imgArr.value.push({
|
||||
shortUrl:minioObj.minioThumbUrl +"/"+data.fileName,
|
||||
url:minioObj.minioUrl +"/"+data.fileName,
|
||||
})
|
||||
} else if (file.type === 'video') {// 视频
|
||||
videoArr.value.push(data.fileUrl)
|
||||
// videoArr.value.push(data.fileUrl)
|
||||
videoArr.value.push({
|
||||
shortUrl:minioObj.minioThumbUrl +"/"+data.fileName,
|
||||
url:minioObj.minioUrl +"/"+data.fileName,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -194,6 +230,21 @@ const chooseMedia = () => {
|
||||
});
|
||||
}
|
||||
|
||||
// 放大视频或图片
|
||||
let isVisible= ref(false);//放大处理
|
||||
let mediaUrl= ref('');//放大地址
|
||||
let videoShow = ref(true);
|
||||
const showMediaPreview=(item)=>{
|
||||
isVisible.value = true;
|
||||
videoShow.value = false;
|
||||
mediaUrl.value = item.url
|
||||
}
|
||||
const handlePreviewClose=()=>{
|
||||
isVisible.value = false;
|
||||
videoShow.value = true;
|
||||
}
|
||||
|
||||
|
||||
// 红点点击
|
||||
const handleRound=(item)=>{
|
||||
item.active=!item.active
|
||||
@@ -214,11 +265,11 @@ const handleSubmit=()=>{
|
||||
problemId:problemId.value,
|
||||
pointId:pointIds.join(","),
|
||||
problemVedio:mediaArr.value.join(","),
|
||||
problemDesc:optionObj.problemDesc
|
||||
problemDesc:optionObj.value.problemDesc
|
||||
}
|
||||
console.log("problemEdit=>",param)
|
||||
// console.log("problemEdit=>",param)
|
||||
problemEdit(param).then(res=>{
|
||||
showAlert("新增上报问题成功")
|
||||
showAlert("修改问题上报成功!")
|
||||
}).finally(()=>{
|
||||
hideLoading();
|
||||
})
|
||||
@@ -228,11 +279,12 @@ const handleSubmit=()=>{
|
||||
groupId:groupId.value,
|
||||
pointId:pointIds.join(","),
|
||||
problemVedio:mediaArr.value.join(","),
|
||||
problemDesc:optionObj.problemDesc
|
||||
problemDesc:optionObj.value.problemDesc
|
||||
}
|
||||
console.log("problemAdd=>",param)
|
||||
// console.log("problemAdd=>",param)
|
||||
problemAdd(param).then(res=>{
|
||||
showAlert("编辑上报问题成功")
|
||||
showAlert("新建问题上报成功!");
|
||||
problemId.value = res;
|
||||
}).finally(()=>{
|
||||
hideLoading();
|
||||
})
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
<block v-for="(row,index) in list" :key="index">
|
||||
|
||||
<!-- 日期展示 parseTime(row.date,'{y}-{m}-{d} 星期{a}')-->
|
||||
<view class="date-title">{{row.day}}</view>
|
||||
<view class="date-title" v-if="activeTab==1 && row.day">{{row.day}}</view>
|
||||
<view class="bg-border" v-else></view>
|
||||
|
||||
<!-- 日常巡检 -->
|
||||
<view class="blue-title">日常巡检</view>
|
||||
@@ -99,7 +100,7 @@
|
||||
<view class="r-l-left">
|
||||
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
|
||||
</view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum*100).toFixed()+'%'}}</span></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="r-list">
|
||||
@@ -547,6 +548,7 @@ const handleJump = (item)=>{
|
||||
margin-left:-40rpx;
|
||||
color:#919191;
|
||||
font-size:28rpx;
|
||||
margin-top:30rpx;
|
||||
}
|
||||
|
||||
.scroll-h{
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
<view class="bg-progress">
|
||||
<view class="progress-container">
|
||||
<circleTemplate :progress="progress"></circleTemplate>
|
||||
<span>{{ (taskObj.groupFinishNum / taskObj.groupNum).toFixed() }}%</span>
|
||||
<span>{{ (taskObj.groupFinishNum / taskObj.groupNum*100).toFixed() }}%</span>
|
||||
</view>
|
||||
<view class="polling">
|
||||
<view class="p-title p-border">巡检单号<text>{{taskObj.taskNo}}</text></view>
|
||||
<view class="p-title">完成进度<text class="p-blue">{{taskObj.groupFinishNum}}</text>/{{taskObj.groupNum}}</view>
|
||||
<view class="btn-primary">
|
||||
<button type="primary" size="mini" @click="handleConfirm">任务提交</button>
|
||||
<button type="primary" size="mini" @click="handleConfirm" :disabled="taskObj.taskStatus!=3">任务提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -95,13 +95,14 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref,onMounted,nextTick,computed } from 'vue'
|
||||
import { onLoad,onHide } from '@dcloudio/uni-app';
|
||||
import { onLoad,onHide, onShow } from '@dcloudio/uni-app';
|
||||
import customHeader from '@/components/customHeader.vue';
|
||||
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
|
||||
import circleTemplate from '@/components/circleTemplate.vue';
|
||||
import { parseTime } from '@/utils/datetime.js';
|
||||
import { formatTaskStatus } from '@/utils/status.js';
|
||||
import { taskDetail } from '@/api/polling.js'
|
||||
import { taskDetail,submitTask } from '@/api/polling.js';
|
||||
import {showAlert,showLoading,hideLoading} from '@/utils/message.js'
|
||||
|
||||
// '2025-12-29 星期五'
|
||||
let taskId = ref(undefined);
|
||||
@@ -112,6 +113,10 @@ onLoad(option => {
|
||||
taskId.value = option.id;
|
||||
})
|
||||
|
||||
onShow(async ()=>{
|
||||
let res = await getList(1, 10);
|
||||
taskObj.value = res;
|
||||
})
|
||||
|
||||
// 查询列表
|
||||
let taskObj = ref({
|
||||
@@ -134,7 +139,7 @@ const upOption = ref({
|
||||
});
|
||||
|
||||
const downOption = ref({
|
||||
auto: true,
|
||||
auto: false,
|
||||
textInOffset: '下拉刷新',
|
||||
textOutOffset: '释放更新',
|
||||
textLoading: '刷新中...'
|
||||
@@ -348,7 +353,15 @@ const getList = (pageIndex, pageSize) => {
|
||||
|
||||
// 执行提交
|
||||
const handleConfirm=()=>{
|
||||
|
||||
let param = {
|
||||
taskId:taskObj.value.taskId
|
||||
}
|
||||
showLoading("加载中...")
|
||||
submitTask(param).then(res=>{
|
||||
showAlert("任务提交成功!");
|
||||
}).finally(()=>{
|
||||
hideLoading();
|
||||
})
|
||||
}
|
||||
|
||||
// 查看详情 type 1-详情 2-问题详情
|
||||
|
||||
@@ -28,9 +28,7 @@
|
||||
<!-- 列表 -->
|
||||
<mescroll-uni ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
|
||||
:up="upOption" :down="downOption" :fixed="false" class="scroll-h" :class="{'loading-scroll':cssFlag}">
|
||||
<view class="white-bg">
|
||||
<block v-if="list">
|
||||
<block v-if="list.length>0">
|
||||
<view class="white-bg" v-if="list.length>0">
|
||||
<!-- <view class="r-title">{{ parseTime(obj.dateStr,'{y}-{m}-{d} 星期{a}')}}</view> -->
|
||||
<view class="report-list" v-for="(item, index) in list" :key="index" @click="handleDetail(item)">
|
||||
<view class="r-list" style="padding-bottom:0">
|
||||
@@ -63,7 +61,7 @@
|
||||
<view class="r-l-left">
|
||||
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
|
||||
</view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum).toFixed()+'%'}}</span></view>
|
||||
<view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum*100).toFixed()+'%'}}</span></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="r-list">
|
||||
@@ -79,14 +77,7 @@
|
||||
</view>
|
||||
<view class="report-border" v-if="index<list.length-1"></view>
|
||||
</view>
|
||||
</block>
|
||||
<view v-else class="no-data">
|
||||
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
|
||||
</view>
|
||||
</block>
|
||||
<view v-else class="no-data">
|
||||
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</mescroll-uni>
|
||||
</view>
|
||||
@@ -105,7 +96,6 @@ import searchDate from '@/components/searchDate.vue';
|
||||
import { parseTime,getDateRange,getDateRangeName } from '@/utils/datetime.js';
|
||||
import { taskTypeOptions,formatTaskType,formatTaskStatus } from '@/utils/status.js';
|
||||
import { taskLists } from '@/api/polling.js'
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 底部日期选择
|
||||
@@ -118,7 +108,6 @@ const dateClose=()=>{
|
||||
}
|
||||
// 选完日期提交回显
|
||||
const dateConfirm=(dateObj)=>{
|
||||
console.log(dateObj)
|
||||
isShow.value = false;
|
||||
dateStr.value = dateObj.startDate + ' 至 '+dateObj.endDate;
|
||||
dateStrName.value = getDateRangeName(dateObj.lastType)
|
||||
@@ -132,7 +121,7 @@ let taskTypeIndex = ref(0);
|
||||
let taskTypeArr = ref([]);
|
||||
let dateStr = ref('');
|
||||
let dateStrName=ref('');
|
||||
onLoad(option => {
|
||||
onLoad(async option => {
|
||||
taskTypeOptions.forEach(item => {
|
||||
taskTypeArr.value.push(item.label)
|
||||
});
|
||||
@@ -144,6 +133,10 @@ onLoad(option => {
|
||||
form.value.startDate = dateObj.startDate;
|
||||
form.value.endDate = dateObj.endDate
|
||||
|
||||
// let res = await getList(0,3);
|
||||
// cssFlag.value = false;
|
||||
// list.value = res.list;
|
||||
|
||||
})
|
||||
|
||||
|
||||
@@ -155,6 +148,7 @@ const changeTaskType = (e)=>{
|
||||
}
|
||||
|
||||
// 查询列表
|
||||
let lastId = ref('');
|
||||
let list = ref([]);
|
||||
let form = ref({
|
||||
startDate:''
|
||||
@@ -162,6 +156,7 @@ let form = ref({
|
||||
const mescrollRef = ref(null);
|
||||
const upOption = ref({
|
||||
// use: false,
|
||||
auto: true, // 禁用自动上拉
|
||||
page: { num: 0, size: 10 },
|
||||
noMoreSize: 5,
|
||||
empty: {
|
||||
@@ -183,16 +178,18 @@ let cssFlag=ref(false);//控制样式
|
||||
const mescrollInit = (mescroll) => {
|
||||
cssFlag.value = true;
|
||||
mescrollRef.value = mescroll;
|
||||
// mescrollRef.value.triggerUpScroll();
|
||||
};
|
||||
|
||||
// 下拉刷新
|
||||
const downCallback = async (mescroll) => {
|
||||
console.log("mescroll=>",mescroll)
|
||||
try {
|
||||
console.log("下拉刷新")
|
||||
const res = await getList(1, upOption.value.page.size);
|
||||
console.log("下拉刷新");
|
||||
const res = await getList(1, upOption.value.page.size,undefined);
|
||||
cssFlag.value = false;
|
||||
list.value = res.list;
|
||||
mescroll.resetUpScroll();
|
||||
mescroll.resetUpScroll()
|
||||
} catch (error) {
|
||||
mescroll.endErr();
|
||||
} finally {
|
||||
@@ -204,8 +201,8 @@ const downCallback = async (mescroll) => {
|
||||
// 上拉加载更多
|
||||
const upCallback = async (mescroll) => {
|
||||
try {
|
||||
console.log("上拉加载更多")
|
||||
let res = await getList(mescroll.num, mescroll.size);
|
||||
console.log("上拉加载更多",mescroll)
|
||||
let res = await getList(mescroll.num, mescroll.size,lastId.value);
|
||||
if (mescroll.num === 1) {
|
||||
list.value = res.list;
|
||||
} else {
|
||||
@@ -218,27 +215,32 @@ const upCallback = async (mescroll) => {
|
||||
}
|
||||
|
||||
// 获取数据列表
|
||||
const getList = (pageIndex, pageSize) => {
|
||||
const getList = (pageIndex, pageSize,last) => {
|
||||
return new Promise(async (resolve) => {
|
||||
let param = {
|
||||
pageIndex,
|
||||
// pageIndex,
|
||||
pageSize,
|
||||
timeBegin: form.value.startDate,
|
||||
timeEnd: form.value.endDate,
|
||||
lastId:last,
|
||||
taskType:taskTypeOptions[taskTypeIndex.value].value
|
||||
}
|
||||
let res = await taskLists(param);
|
||||
let data = res ||{};
|
||||
lastId.value = data.isEnd==1?undefined:data.lastId
|
||||
resolve({
|
||||
...data,
|
||||
// total: res.recordCount || 0
|
||||
total: (data.isEnd==1?0:data.lastId) || 1, //是否最后一页(1-是,0-否)
|
||||
lastId: data.isEnd==1?undefined:data.lastId
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
const handleSearch=()=>{
|
||||
getList(0,10)
|
||||
const handleSearch= async ()=>{
|
||||
let res = await getList(0,10);
|
||||
cssFlag.value = false;
|
||||
list.value = res.list;
|
||||
}
|
||||
|
||||
// 查看详情
|
||||
@@ -253,10 +255,10 @@ const handleDetail = (item,type) =>{
|
||||
<style scoped>
|
||||
.scroll-h{
|
||||
/* #ifdef APP-PLUS */
|
||||
height: calc(100vh - 108px);
|
||||
height: calc(100vh - 148px);
|
||||
/* #endif */
|
||||
/* #ifndef APP-PLUS */
|
||||
height: calc(100vh - 135px);
|
||||
height: calc(100vh - 132px);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
@@ -364,7 +366,7 @@ const handleDetail = (item,type) =>{
|
||||
width:525rpx
|
||||
}
|
||||
.r-left .r-l-left{
|
||||
width:370rpx;
|
||||
width:350rpx;
|
||||
}
|
||||
.r-left .r-l-right{
|
||||
|
||||
|
||||
@@ -284,11 +284,3 @@ export const compressImageUni = (file) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取minio缩略图地址
|
||||
export function getMinioThumbUrl(ossObj,path){
|
||||
let baseUrl = process.env.VUE_APP_MINIO?process.env.VUE_APP_MINIO:'';
|
||||
// let replaceStr="http://"+ossObj.clientObj.url+":"+ossObj.clientObj.port+"/new-gd-manager"
|
||||
// let thumbUrl = path.replace(replaceStr,baseUrl+'/thumb/new-gd-manager');
|
||||
return {baseUrl}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
// 包路径
|
||||
const package_NdefRecord = 'android.nfc.NdefRecord';
|
||||
const package_NdefMessage = 'android.nfc.NdefMessage';
|
||||
const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED';
|
||||
const package_Intent = 'android.content.Intent';
|
||||
const package_Activity = 'android.app.Activity';
|
||||
const package_PendingIntent = 'android.app.PendingIntent';
|
||||
const package_IntentFilter = 'android.content.IntentFilter';
|
||||
const package_NfcAdapter = 'android.nfc.NfcAdapter';
|
||||
const package_Ndef = 'android.nfc.tech.Ndef';
|
||||
const package_NdefFormatable = 'android.nfc.tech.NdefFormatable';
|
||||
const package_Parcelable = 'android.os.Parcelable';
|
||||
const package_String = 'java.lang.String';
|
||||
|
||||
let NfcAdapter;
|
||||
let NdefRecord;
|
||||
let NdefMessage;
|
||||
let readyRead = true; //开启读
|
||||
let noNFC = false;
|
||||
let techListsArray = [
|
||||
['android.nfc.tech.IsoDep'],
|
||||
['android.nfc.tech.NfcA'],
|
||||
['android.nfc.tech.NfcB'],
|
||||
['android.nfc.tech.NfcF'],
|
||||
['android.nfc.tech.Nfcf'],
|
||||
['android.nfc.tech.NfcV'],
|
||||
['android.nfc.tech.NdefFormatable'],
|
||||
['android.nfc.tech.MifareClassi'],
|
||||
['android.nfc.tech.MifareUltralight']
|
||||
];
|
||||
// 要写入的数据
|
||||
// let text = '{id:8888,name:nfc,stie:wangqin.com}';
|
||||
// let readResult = '';
|
||||
|
||||
export default {
|
||||
listenNFCStatus() {
|
||||
console.log("---------listenNFCStatus--------------")
|
||||
let that = this;
|
||||
try {
|
||||
let main = plus.android.runtimeMainActivity();
|
||||
let Intent = plus.android.importClass('android.content.Intent');
|
||||
let Activity = plus.android.importClass('android.app.Activity');
|
||||
let PendingIntent = plus.android.importClass('android.app.PendingIntent');
|
||||
let IntentFilter = plus.android.importClass('android.content.IntentFilter');
|
||||
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
|
||||
let nfcAdapter = NfcAdapter.getDefaultAdapter(main);
|
||||
console.log("nfcAdapter=>",nfcAdapter)
|
||||
if (nfcAdapter == null) {
|
||||
uni.showToast({
|
||||
title: '设备不支持NFC!',
|
||||
icon: 'none'
|
||||
})
|
||||
noNFC = true;
|
||||
return;
|
||||
}
|
||||
if (!nfcAdapter.isEnabled()) {
|
||||
uni.showToast({
|
||||
title: '请在系统设置中先启用NFC功能!',
|
||||
icon: 'none'
|
||||
});
|
||||
noNFC = true;
|
||||
return;
|
||||
} else {
|
||||
noNFC = false;
|
||||
}
|
||||
console.log("nfcAdapter=>noNFC=>",noNFC)
|
||||
let intent = new Intent(main, main.getClass());
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
|
||||
let ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
|
||||
ndef.addDataType("*/*");
|
||||
let intentFiltersArray = [ndef];
|
||||
|
||||
//重点部分代码
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
plus.globalEvent.addEventListener('newintent', function () {
|
||||
// 轮询调用 NFC
|
||||
// setTimeout(that.nfcRuning(resolve), 1000);
|
||||
setTimeout(() => {
|
||||
that.nfcRuning(resolve)
|
||||
}, 1000);
|
||||
});
|
||||
})
|
||||
|
||||
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
|
||||
return promise
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
nfcRuning(resolve){
|
||||
console.log("--------------nfcRuning---------------")
|
||||
NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
|
||||
NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
|
||||
let main = plus.android.runtimeMainActivity();
|
||||
let intent = main.getIntent(); console.log("intent=>",intent)
|
||||
let that = this;
|
||||
if (package_TECH_DISCOVERED == intent.getAction()) {
|
||||
if (readyRead) {
|
||||
//这里通过read方法拿到NFC数据
|
||||
const id = that.read(intent);
|
||||
console.log("nfcRuning=>",id)
|
||||
// readyRead = false;
|
||||
//将数据返回出去
|
||||
resolve(id)
|
||||
}
|
||||
}
|
||||
},
|
||||
read(intent) {
|
||||
// toast('请勿移开标签正在读取数据');
|
||||
let that = this;
|
||||
// NFC id
|
||||
let bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
|
||||
let nfc_id = that.byteArrayToHexString(bytesId);
|
||||
|
||||
return nfc_id;
|
||||
},
|
||||
byteArrayToHexString(inarray){ // converts byte arrays to string
|
||||
let i, j, inn;
|
||||
let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
|
||||
let out = "";
|
||||
|
||||
for (j = 0; j < inarray.length; ++j) {
|
||||
inn = inarray[j] & 0xff;
|
||||
i = (inn >>> 4) & 0x0f;
|
||||
out += hex[i];
|
||||
i = inn & 0x0f;
|
||||
out += hex[i];
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
function toast(content) {
|
||||
uni.showToast({
|
||||
title: content,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user