hldy_app/pages/camera.nvue

618 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="center-column" :style="{ height: isshow ? '520px' : '0px' }">
<!-- 视频播放组件 -->
<MonitorView ref="monitor" init="5" style="width: 680px;height: 520px;" @onTel="handleTelEvent"
@onSnapShot="handleSnapShotEvent" @onRecord="handleRecordEvent" @onTalkStatus="handleTalkEvent" />
</div>
</template>
<script>
export default {
data() {
return {
phoneNumber: "1234567890",
initnumber: 5,
isAlarming: false,
isRecording: false, // 录屏状态
isTalking: false, // 对讲状态
// 内部 pending 请求队列,用于在 native 事件到达时把结果返回给特定 reqId
// 结构: { snapshot: [reqId,...], record: [reqId,...], talk: [reqId,...] }
// 注意:这仅用于在 native 事件没有直接 callback 时仍能把结果回传给请求方。
_pendingRequests: {
snapshot: [],
record: [],
talk: []
},
suo: true,
isshow: true
};
},
onLoad() {
// 保留你的 globalEvent 监听
const globalEvent = uni.requireNativePlugin && uni.requireNativePlugin("globalEvent");
if (globalEvent && globalEvent.addEventListener) {
globalEvent.addEventListener("myEvent", (e) => {
console.log(e)
if (e.recordUrl) {
uni.showToast({
title: '录屏成功',
icon: 'success', // 'success' | 'loading' | 'none'
duration: 1500
})
}
if (e.snapShotUrl) {
uni.showToast({
title: '截屏成功',
icon: 'success', // 'success' | 'loading' | 'none'
duration: 1500
})
}
if (this.suo && e.onVolumeChange) {
if (e.onVolumeChange) {
this.toggleVolume();
}
this.suo = false;
}
});
}
uni.setStorageSync('saveinit', 5);
// this.doStopRecord()
uni.$on('monitor:changeinit', (number) => {
// this.initnumber = number;
// this.$refs.monitor.killView
this.$refs.monitor.initAutoPlay(number)
uni.setStorageSync('saveinit', number);
console.log("?????",number)
}
);
uni.$on('monitor:isshow', (bool) => this.isshow = bool);
uni.$on('monitor:killView', this.killView);
// 在页面生命周期注册 uni.$on 事件,暴露给其他页面调用
uni.$on('monitor:doSnapshot', this.doSnapshot);
uni.$on('monitor:startRecord', this.doStartRecord);
uni.$on('monitor:stopRecord', this.doStopRecord);
uni.$on('monitor:openTalk', this.doOpenTalk);
uni.$on('monitor:stopTalk', this.doStopTalk);
uni.$on('monitor:switchDisplay', (payload) => this.switchDisplay(payload));
uni.$on('monitor:startAlarm', this.startAlarm);
uni.$on('monitor:stopAlarm', this.stopAlarm);
uni.$on('monitor:flipImage', (payload) => this.flipImage(payload));
uni.$on('monitor:resumeOrPause', this.resumeOrPause);
uni.$on('monitor:changeQuality', this.changeQuality);
uni.$on('monitor:toggleVolume', this.toggleVolume);
uni.$on('monitor:test', this.test);
},
onUnload() {
// 页面卸载时一定要解绑
uni.$off('monitor:killView', (bool) => this.killView);
uni.$off('monitor:changeinit', (number) => this.initnumber = number);
uni.$off('monitor:isshow', (bool) => this.isshow = bool);
uni.$off('monitor:doSnapshot', this.doSnapshot);
uni.$off('monitor:startRecord', this.doStartRecord);
uni.$off('monitor:stopRecord', this.doStopRecord);
uni.$off('monitor:openTalk', this.doOpenTalk);
uni.$off('monitor:stopTalk', this.doStopTalk);
uni.$off('monitor:switchDisplay', (payload) => this.switchDisplay(payload));
uni.$off('monitor:startAlarm', this.startAlarm);
uni.$off('monitor:stopAlarm', this.stopAlarm);
uni.$off('monitor:flipImage', (payload) => this.flipImage(payload));
uni.$off('monitor:resumeOrPause', this.resumeOrPause);
uni.$off('monitor:changeQuality', this.changeQuality);
uni.$off('monitor:toggleVolume', this.toggleVolume);
uni.$off('monitor:test', this.test);
},
methods: {
/* ------------------ 原有功能 ------------------ */
handleTelEvent(event) {
console.log("Tel event detail:", event.detail);
// 如果需要解析电话事件,在这里处理
},
killView() {
this.$refs.monitor.killView && this.$refs.monitor.killView();
},
switchDisplay(mode) {
console.log("zzzzz", mode)
this.$refs.monitor && this.$refs.monitor.switchDisplayModeFragment(mode);
},
startAlarm() {
this.isAlarming = true;
this.$refs.monitor.startOrStopManualAlarm(this.isAlarming, (res) => {
console.log("startAlarm callback:", res);
});
},
stopAlarm() {
this.isAlarming = false;
this.$refs.monitor.startOrStopManualAlarm(this.isAlarming, (res) => {
console.log("stopAlarm callback:", res);
});
},
flipImage(type) {
this.$refs.monitor.changeImageSwitch(type, (res) => {
console.log("flipImage callback:", res);
});
},
resumeOrPause() {
this.$refs.monitor.resumeOrPause && this.$refs.monitor.resumeOrPause();
},
changeQuality() {
this.$refs.monitor.changeQuality && this.$refs.monitor.changeQuality();
},
toggleVolume() {
this.$refs.monitor.toggleVolume && this.$refs.monitor.toggleVolume();
},
test() {
this.$refs.monitor && this.$refs.monitor.test && this.$refs.monitor.test();
},
/* ------------------ 新增:截图/录屏/对讲 调用方法(支持 payload.reqId ------------------ */
// 1. 截图(调用)
// payload 可选:{ reqId: number }
doSnapshot(payload = {}) {
if (!this.$refs.monitor || !this.$refs.monitor.snapShot) {
uni.showToast({
title: "组件不支持 snapShot()",
icon: "none"
});
// 直接给请求方回错
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'snapShot_not_supported'
});
}
return;
}
// 如果 caller 传了 reqId就把 reqId 放入 pending以备 native 事件回调时匹配)
if (payload.reqId) {
this._pendingRequests.snapshot.push(payload.reqId);
}
try {
this.$refs.monitor.snapShot((res) => {
// 这个 callback 优先使用,直接回传结果给请求方(如果有)
console.log("snapShot callback:", res);
this._handleSnapshotResultFromNative(res, payload.reqId);
});
uni.showToast({
title: "正在截屏...",
icon: "none",
duration: 800
});
} catch (err) {
console.error("snapShot 调用失败", err);
uni.showToast({
title: "snapShot 调用失败",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'snapShot_call_failed',
detail: String(err)
});
}
}
},
// 2. 开始录屏(调用)
// payload 可选:{ reqId: number }
doStartRecord(payload = {}) {
if (!this.$refs.monitor || !this.$refs.monitor.startRecord) {
uni.showToast({
title: "组件不支持 startRecord()",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'startRecord_not_supported'
});
}
return;
}
try {
this.$refs.monitor.startRecord((res) => {
console.log("startRecord callback:", res);
// 有些实现会在 start 的 callback 里返回启动结果;如果 caller 传了 reqId 则回传
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: true,
res
});
}
});
this.isRecording = true;
uni.showToast({
title: "录屏已开始",
icon: "none"
});
} catch (err) {
console.error("startRecord 调用失败", err);
uni.showToast({
title: "startRecord 调用失败",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'startRecord_call_failed',
detail: String(err)
});
}
}
},
// 3. 停止录屏(调用)
// payload 可选:{ reqId: number }
doStopRecord(payload = {}) {
if (!this.$refs.monitor || !this.$refs.monitor.stopRecord) {
uni.showToast({
title: "组件不支持 stopRecord()",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'stopRecord_not_supported'
});
}
return;
}
// 记录 pending以便 native 的 onRecord 事件回传可匹配)
if (payload.reqId) {
this._pendingRequests.record.push(payload.reqId);
}
try {
this.$refs.monitor.stopRecord((res) => {
console.log("stopRecord callback:", res);
this._handleRecordResultFromNative(res, payload.reqId);
});
// 状态会在回调或事件里最终设置
} catch (err) {
console.error("stopRecord 调用失败", err);
uni.showToast({
title: "stopRecord 调用失败",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'stopRecord_call_failed',
detail: String(err)
});
}
}
},
// 4. 开始对讲(调用)
// payload 可选:{ reqId: number }
doOpenTalk(payload = {}) {
if (!this.$refs.monitor || !this.$refs.monitor.openTalk) {
uni.showToast({
title: "组件不支持 openTalk()",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'openTalk_not_supported'
});
}
return;
}
// pending 用于当 native 发来 talk 状态事件时回传
if (payload.reqId) {
this._pendingRequests.talk.push(payload.reqId);
}
try {
this.$refs.monitor.openTalk((res) => {
console.log("openTalk callback:", res);
// 如果 callback 里有最终状态可以直接回传
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: true,
res
});
}
});
this.isTalking = true;
uni.showToast({
title: "尝试建立对讲连接...",
icon: "none"
});
} catch (err) {
console.error("openTalk 调用失败", err);
uni.showToast({
title: "openTalk 调用失败",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'openTalk_call_failed',
detail: String(err)
});
}
}
},
// 5. 停止对讲(调用)
// payload 可选:{ reqId: number }
doStopTalk(payload = {}) {
if (!this.$refs.monitor || !this.$refs.monitor.stopTalk) {
uni.showToast({
title: "组件不支持 stopTalk()",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'stopTalk_not_supported'
});
}
return;
}
try {
this.$refs.monitor.stopTalk((res) => {
console.log("stopTalk callback:", res);
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: true,
res
});
}
});
this.isTalking = false;
} catch (err) {
console.error("stopTalk 调用失败", err);
uni.showToast({
title: "stopTalk 调用失败",
icon: "none"
});
if (payload.reqId) {
uni.$emit(`monitor:response:${payload.reqId}`, {
ok: false,
error: 'stopTalk_call_failed',
detail: String(err)
});
}
}
},
/* ------------------ 事件回调处理(来自原生推送的事件) ------------------ */
// 处理来自模板 @onSnapShot 的事件event.detail
handleSnapShotEvent(event) {
const payload = event && event.detail ? event.detail : event;
console.log("onSnapShot event:", payload);
// 统一处理并尝试把结果回给 pending 请求者
this._handleSnapshotResultFromNative(payload);
},
// 处理来自模板 @onRecord 的事件event.detail
handleRecordEvent(event) {
const payload = event && event.detail ? event.detail : event;
console.log("onRecord event:", payload);
this._handleRecordResultFromNative(payload);
},
// 处理来自模板 @onTalkStatus 的事件
handleTalkEvent(event) {
const payload = event && event.detail ? event.detail : event;
console.log("onTalkStatus event:", payload);
const status = payload && payload.talkStatus;
const tips = payload && payload.tips;
// 通知调用方(通用事件)
uni.$emit('monitor:talk:status', payload);
// 如果有 pending talk 请求,回传结果
if (this._pendingRequests.talk && this._pendingRequests.talk.length) {
while (this._pendingRequests.talk.length) {
const reqId = this._pendingRequests.talk.shift();
uni.$emit(`monitor:response:${reqId}`, {
ok: true,
payload
});
}
}
switch ((status || "").toLowerCase()) {
case "loading":
uni.showToast({
title: tips || "对讲连接中...",
icon: "none"
});
this.isTalking = true;
break;
case "playing":
uni.showToast({
title: tips || "对讲已连接",
icon: "none"
});
this.isTalking = true;
break;
case "stopped":
uni.showToast({
title: tips || "对讲已停止",
icon: "none"
});
this.isTalking = false;
break;
case "failed":
uni.showToast({
title: tips || "对讲失败",
icon: "none"
});
this.isTalking = false;
break;
default:
uni.showToast({
title: tips || ("对讲状态: " + (status || "unknown")),
icon: "none"
});
break;
}
},
/* ------------------ 原生结果的内部处理函数(统一处理 callback / event ------------------ */
_handleSnapshotResultFromNative(res, reqIdFromCallback = null) {
if (!res) {
uni.showToast({
title: "截图没有返回数据",
icon: "none"
});
// 回传失败
if (reqIdFromCallback) {
uni.$emit(`monitor:response:${reqIdFromCallback}`, {
ok: false,
error: 'no_data'
});
}
return;
}
let payload = res;
if (res.detail) payload = res.detail;
console.log("snapshot payload normalized:", payload);
// 优先判断 callback 里直接传进来的 reqId
if (reqIdFromCallback) {
uni.$emit(`monitor:response:${reqIdFromCallback}`, {
ok: !!payload.snapShotResult,
payload
});
}
// 如果没有 callback reqId但有 pending 列表,则把结果分发给所有 pending reqId典型场景调用方只发了 reqId但 native 最终通过 onSnapShot 事件推回)
if ((!reqIdFromCallback) && this._pendingRequests.snapshot && this._pendingRequests.snapshot.length) {
while (this._pendingRequests.snapshot.length) {
const rid = this._pendingRequests.snapshot.shift();
uni.$emit(`monitor:response:${rid}`, {
ok: !!payload.snapShotResult,
payload
});
}
}
// 无论如何,都发一个通用完成事件,方便只监听通用事件的页面
uni.$emit('monitor:snapshot:done', payload);
if (payload.snapShotResult === true || payload.snapShotResult === "true") {
const url = payload.snapShotUrl || payload.snapShotPath || payload.url;
uni.showToast({
title: "截图成功",
icon: "success",
duration: 1200
});
if (url) {
uni.previewImage({
urls: [url]
});
}
} else {
const err = payload.snapShotErrorCode || payload.error || "unknown";
uni.showToast({
title: "截图失败: " + err,
icon: "none",
duration: 2000
});
console.warn("snapshot failed reason:", err, payload);
}
},
_handleRecordResultFromNative(res, reqIdFromCallback = null) {
if (!res) {
uni.showToast({
title: "录屏没有返回数据",
icon: "none"
});
this.isRecording = false;
if (reqIdFromCallback) {
uni.$emit(`monitor:response:${reqIdFromCallback}`, {
ok: false,
error: 'no_data'
});
}
return;
}
let payload = res;
if (res.detail) payload = res.detail;
console.log("record payload normalized:", payload);
// 优先用 callback 的 reqId 回传
if (reqIdFromCallback) {
uni.$emit(`monitor:response:${reqIdFromCallback}`, {
ok: !!(payload.recordUrl || payload.snapShotResult),
payload
});
}
// 如果没有 callback reqId但有 pending则回传给 pending 列表
if ((!reqIdFromCallback) && this._pendingRequests.record && this._pendingRequests.record.length) {
while (this._pendingRequests.record.length) {
const rid = this._pendingRequests.record.shift();
uni.$emit(`monitor:response:${rid}`, {
ok: !!(payload.recordUrl || payload.snapShotResult),
payload
});
}
}
// 通用事件
uni.$emit('monitor:record:done', payload);
if (payload.recordUrl) {
uni.showToast({
title: "录屏完成",
icon: "success",
duration: 1400
});
this.isRecording = false;
console.log("录屏地址:", payload.recordUrl);
} else if (payload.recordFailedReason) {
uni.showToast({
title: "录屏失败: " + payload.recordFailedReason,
icon: "none",
duration: 2000
});
this.isRecording = false;
console.warn("record failed reason:", payload.recordFailedReason);
} else {
if (payload.snapShotResult === true) {
uni.showToast({
title: "录屏操作已完成(返回未知)",
icon: "none"
});
}
this.isRecording = false;
}
},
},
};
</script>
<style>
.center-column {
width: 680px;
height: 520px;
border-radius: 30px;
overflow: hidden;
}
</style>