|
@@ -5,8 +5,6 @@
|
|
|
<camera class="camera" device-position="front" flash="off" style="width: 200px;height: 200px" :class="myClass" @initdone="onVideoSuccess" @error="handleError" @stop="handleStop"></camera>
|
|
<camera class="camera" device-position="front" flash="off" style="width: 200px;height: 200px" :class="myClass" @initdone="onVideoSuccess" @error="handleError" @stop="handleStop"></camera>
|
|
|
<!-- 用于抓拍切出去传递固定img-->
|
|
<!-- 用于抓拍切出去传递固定img-->
|
|
|
<img :src="imgUrl" alt="" v-show="false">
|
|
<img :src="imgUrl" alt="" v-show="false">
|
|
|
- <!-- 测试抓拍使用 -->
|
|
|
|
|
- <!-- <button @click="handleZhua">抓拍</button> -->
|
|
|
|
|
</view>
|
|
</view>
|
|
|
<view v-show="showVideo" @click="noShowVideoBtn" class="shiti-video-hidden-btn">
|
|
<view v-show="showVideo" @click="noShowVideoBtn" class="shiti-video-hidden-btn">
|
|
|
<icon :style="{ backgroundImage: 'url(' + iconsArr.videoCloseIcon + ')' }"></icon>
|
|
<icon :style="{ backgroundImage: 'url(' + iconsArr.videoCloseIcon + ')' }"></icon>
|
|
@@ -14,11 +12,16 @@
|
|
|
<view v-show="!showVideo" @click="showVideoBtn" class="shiti-video-show-btn">
|
|
<view v-show="!showVideo" @click="showVideoBtn" class="shiti-video-show-btn">
|
|
|
<icon :style="{ backgroundImage: 'url(' + iconsArr.videoPlayIcon + ')' }"></icon>
|
|
<icon :style="{ backgroundImage: 'url(' + iconsArr.videoPlayIcon + ')' }"></icon>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <canvas
|
|
|
|
|
+ canvas-id="frameCanvas"
|
|
|
|
|
+ id="frameCanvas"
|
|
|
|
|
+ style="position: absolute;top:9999px;left: 0px;width: 100vw; height: 100vh;z-index:-2"
|
|
|
|
|
+ ></canvas>
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
- import {ref,onUnmounted,nextTick,computed,onMounted,reactive} from "vue";
|
|
|
|
|
|
|
+ import {ref,onUnmounted,nextTick,computed,onMounted,reactive,getCurrentInstance} from "vue";
|
|
|
import cacheManager from '@/utils/cacheManager.js';
|
|
import cacheManager from '@/utils/cacheManager.js';
|
|
|
import * as ksApi from "@/api/kaoshi.js"
|
|
import * as ksApi from "@/api/kaoshi.js"
|
|
|
import {
|
|
import {
|
|
@@ -34,6 +37,13 @@
|
|
|
|
|
|
|
|
const cameraContext = ref(null);
|
|
const cameraContext = ref(null);
|
|
|
|
|
|
|
|
|
|
+ // 响应式数据
|
|
|
|
|
+ const frameListener = ref(null)
|
|
|
|
|
+ const isCapturing = ref(false)
|
|
|
|
|
+ const capturedImage = ref('')
|
|
|
|
|
+ const currentFrame = ref(null) // 存储当前帧数据
|
|
|
|
|
+ const myInstanceR = getCurrentInstance()
|
|
|
|
|
+
|
|
|
const DropRef = ref(null);
|
|
const DropRef = ref(null);
|
|
|
const DropContainerRef = ref(null);
|
|
const DropContainerRef = ref(null);
|
|
|
const zhuapai = ref(0); // 单位分
|
|
const zhuapai = ref(0); // 单位分
|
|
@@ -63,6 +73,8 @@
|
|
|
|
|
|
|
|
const emits = defineEmits(['init', 'success', 'error', 'cancel', 'progress'])
|
|
const emits = defineEmits(['init', 'success', 'error', 'cancel', 'progress'])
|
|
|
|
|
|
|
|
|
|
+ let timer1 = null;
|
|
|
|
|
+
|
|
|
function noShowVideoBtn() {
|
|
function noShowVideoBtn() {
|
|
|
showVideo.value = false
|
|
showVideo.value = false
|
|
|
}
|
|
}
|
|
@@ -125,7 +137,10 @@
|
|
|
nextTick(() => {
|
|
nextTick(() => {
|
|
|
startCamera()
|
|
startCamera()
|
|
|
// 设定计时器
|
|
// 设定计时器
|
|
|
- setInterval(() => handleZhua(), zhuapai.value * 60 * 1000)
|
|
|
|
|
|
|
+ console.log('抓拍设定', zhuapai.value)
|
|
|
|
|
+ setInterval(() => {
|
|
|
|
|
+ handleZhua()
|
|
|
|
|
+ }, zhuapai.value * 60 * 1000)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
}
|
|
}
|
|
@@ -135,8 +150,9 @@
|
|
|
function startCamera() {
|
|
function startCamera() {
|
|
|
// 请求摄像头权限并获取流
|
|
// 请求摄像头权限并获取流
|
|
|
cameraContext.value = uni.createCameraContext();
|
|
cameraContext.value = uni.createCameraContext();
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ startFrameListener()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function urlToBase64(url) {
|
|
function urlToBase64(url) {
|
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
// #ifdef MP-WEIXIN
|
|
// #ifdef MP-WEIXIN
|
|
@@ -156,9 +172,9 @@
|
|
|
// #endif
|
|
// #endif
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
function getSnapShotImage(data) {
|
|
function getSnapShotImage(data) {
|
|
|
|
|
+ console.log('转转图片成base64')
|
|
|
urlToBase64(data).then((d1) => {
|
|
urlToBase64(data).then((d1) => {
|
|
|
const imgData = d1.split(';base64,');
|
|
const imgData = d1.split(';base64,');
|
|
|
|
|
|
|
@@ -172,7 +188,7 @@
|
|
|
suffix: 'png',
|
|
suffix: 'png',
|
|
|
|
|
|
|
|
};
|
|
};
|
|
|
-
|
|
|
|
|
|
|
+ console.log('上传图片')
|
|
|
getFileUpload(opt).then(res => {
|
|
getFileUpload(opt).then(res => {
|
|
|
const dOption = {
|
|
const dOption = {
|
|
|
operId:operId.value,
|
|
operId:operId.value,
|
|
@@ -181,6 +197,8 @@
|
|
|
ksApi.getClientZhuaPaiUpdate(dOption)
|
|
ksApi.getClientZhuaPaiUpdate(dOption)
|
|
|
.then(res => {
|
|
.then(res => {
|
|
|
console.log('【源 : 获取抓拍数据】');
|
|
console.log('【源 : 获取抓拍数据】');
|
|
|
|
|
+ // 抓拍成功 继续监听
|
|
|
|
|
+ frameListener.value.start()
|
|
|
})
|
|
})
|
|
|
.catch(err => {
|
|
.catch(err => {
|
|
|
console.error('源 :抓拍接口异常', err);
|
|
console.error('源 :抓拍接口异常', err);
|
|
@@ -205,7 +223,6 @@
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
function doZhuaiPai(ImageFile) {
|
|
function doZhuaiPai(ImageFile) {
|
|
|
try {
|
|
try {
|
|
|
if (zhuapaiStore.status == 0) {
|
|
if (zhuapaiStore.status == 0) {
|
|
@@ -220,22 +237,15 @@
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function handleZhua() {
|
|
function handleZhua() {
|
|
|
- cameraContext.value.takePhoto({
|
|
|
|
|
- quality: 'high',
|
|
|
|
|
- success: (res) => {
|
|
|
|
|
- doZhuaiPai(res.tempImagePath)
|
|
|
|
|
- },
|
|
|
|
|
- fail: (err) => {
|
|
|
|
|
- console.error('拍照失败:', err);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ console.log('抓拍')
|
|
|
|
|
+ captureSilently();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function onVideoSuccess() {
|
|
function onVideoSuccess() {
|
|
|
- // setTimeout(() => {
|
|
|
|
|
- // // 首次运行进行抓拍一次
|
|
|
|
|
- // handleZhua();
|
|
|
|
|
- // }, 3000);
|
|
|
|
|
|
|
+/* setTimeout(() => {
|
|
|
|
|
+ // 首次运行进行抓拍一次
|
|
|
|
|
+ handleZhua();
|
|
|
|
|
+ }, 3000);*/
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function onVideoError() {
|
|
function onVideoError() {
|
|
@@ -272,17 +282,135 @@
|
|
|
isBuffer.value = true;
|
|
isBuffer.value = true;
|
|
|
console.log('onProgress')
|
|
console.log('onProgress')
|
|
|
// buffer时间增大到3秒 过滤掉后续的onTimeupdate
|
|
// buffer时间增大到3秒 过滤掉后续的onTimeupdate
|
|
|
- setTimeout(() => {isBuffer.value = false}, 3000)
|
|
|
|
|
|
|
+ timer1 = setTimeout(() => {isBuffer.value = false}, 3000)
|
|
|
// 视频中途暂停被占用
|
|
// 视频中途暂停被占用
|
|
|
stopTimer.value = setTimeout(() => {
|
|
stopTimer.value = setTimeout(() => {
|
|
|
emits('progress', false);
|
|
emits('progress', false);
|
|
|
console.log('结束')
|
|
console.log('结束')
|
|
|
}, 10 * 1000)
|
|
}, 10 * 1000)
|
|
|
}
|
|
}
|
|
|
- onMounted(() => {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /******************************************************/
|
|
|
|
|
+ // 开始监听相机帧数据
|
|
|
|
|
+ function startFrameListener(){
|
|
|
|
|
+ if (!cameraContext.value) {
|
|
|
|
|
+ uni.showToast({ title: '相机未初始化', icon: 'none' })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ frameListener.value = cameraContext.value.onCameraFrame((frame) => {
|
|
|
|
|
+ // 存储当前帧数据,用于后续抓拍
|
|
|
|
|
+ currentFrame.value = frame
|
|
|
|
|
+ // console.log('接收帧数据:', frame.width, frame.height)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ frameListener.value.start()
|
|
|
|
|
+ isCapturing.value = true
|
|
|
|
|
+ // uni.showToast({ title: '开始监控帧数据', icon: 'success' })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 停止监听帧数据
|
|
|
|
|
+ function stopFrameListener(){
|
|
|
|
|
+ if (frameListener.value) {
|
|
|
|
|
+ frameListener.value.stop()
|
|
|
|
|
+ frameListener.value = null
|
|
|
|
|
+ }
|
|
|
|
|
+ isCapturing.value = false
|
|
|
|
|
+ // uni.showToast({ title: '已停止监控', icon: 'success' })
|
|
|
|
|
+ }
|
|
|
|
|
+ // 静音抓拍核心函数
|
|
|
|
|
+ async function captureSilently (){
|
|
|
|
|
+
|
|
|
|
|
+ if (!isCapturing.value || !currentFrame.value) {
|
|
|
|
|
+ uni.showToast({ title: '请先开始监控帧数据', icon: 'none' })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ console.log('停止前')
|
|
|
|
|
+ // 临时停止监听以避免数据冲突
|
|
|
|
|
+ stopFrameListener()
|
|
|
|
|
+ console.log('开始绘制',)
|
|
|
|
|
+ // 将帧数据绘制到Canvas并导出为图片
|
|
|
|
|
+ await drawFrameToCanvas(currentFrame.value).then(url => {
|
|
|
|
|
+ console.log('获取地址')
|
|
|
|
|
+ getSnapShotImage(url)
|
|
|
|
|
+ })
|
|
|
|
|
+ // 重新开始监听
|
|
|
|
|
+ startFrameListener()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.log('errrrr',error)
|
|
|
|
|
+ handleError();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 将帧数据绘制到Canvas
|
|
|
|
|
+ function drawFrameToCanvas(frame) {
|
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 确保有有效的帧数据
|
|
|
|
|
+ if (!frame || !frame.data || !frame.width || !frame.height) {
|
|
|
|
|
+ reject(new Error('无效的帧数据'))
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ // 将ArrayBuffer转换为Uint8ClampedArray[4](@ref)
|
|
|
|
|
+ const dataArray = new Uint8Array(frame.data)
|
|
|
|
|
+ const clampedArray = new Uint8ClampedArray(dataArray)
|
|
|
|
|
+ console.log('clampedArray', clampedArray.length)
|
|
|
|
|
+ // 使用wx.canvasPutImageData将帧数据绘制到Canvas[4](@ref)
|
|
|
|
|
+ wx.canvasPutImageData({
|
|
|
|
|
+ canvasId: 'frameCanvas',
|
|
|
|
|
+ data: clampedArray,
|
|
|
|
|
+ x: 0,
|
|
|
|
|
+ y: 0,
|
|
|
|
|
+ width: frame.width,
|
|
|
|
|
+ height: frame.height,
|
|
|
|
|
+ success: () => {
|
|
|
|
|
+ // 绘制成功后,将Canvas内容转换为临时图片文件
|
|
|
|
|
+ wx.canvasToTempFilePath({
|
|
|
|
|
+ canvasId: 'frameCanvas',
|
|
|
|
|
+ destWidth: frame.width,
|
|
|
|
|
+ destHeight: frame.height,
|
|
|
|
|
+ fileType: 'png',
|
|
|
|
|
+ quality: 0.7,
|
|
|
|
|
+ success: (res) => {
|
|
|
|
|
+ capturedImage.value = res.tempFilePath
|
|
|
|
|
+ resolve(res.tempFilePath)
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ console.log('5555',err)
|
|
|
|
|
+ reject(new Error(`生成图片失败: ${err.errMsg}`))
|
|
|
|
|
+ }
|
|
|
|
|
+ }, myInstanceR.proxy)
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ console.log('6666',err)
|
|
|
|
|
+ reject(new Error(`绘制到Canvas失败: ${err.errMsg}`))
|
|
|
|
|
+ }
|
|
|
|
|
+ }, myInstanceR.proxy)
|
|
|
|
|
+
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+
|
|
|
|
|
+ console.log('ccccc',err)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /******************************************************/
|
|
|
|
|
+
|
|
|
|
|
+ onMounted(() => {
|
|
|
iconsArr.videoCloseIcon = cacheManager.get('projectImg').video_close_icon;
|
|
iconsArr.videoCloseIcon = cacheManager.get('projectImg').video_close_icon;
|
|
|
iconsArr.videoPlayIcon = cacheManager.get('projectImg').video_play_icon;
|
|
iconsArr.videoPlayIcon = cacheManager.get('projectImg').video_play_icon;
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ onUnmounted(() => {
|
|
|
|
|
+ stopFrameListener()
|
|
|
|
|
+
|
|
|
|
|
+ if (timer1) {
|
|
|
|
|
+ clearTimeout(timer1);
|
|
|
|
|
+ timer1 = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
defineExpose({
|
|
defineExpose({
|
|
|
init,
|
|
init,
|
|
|
showVideoBtn
|
|
showVideoBtn
|