441 lines
13 KiB
Plaintext
441 lines
13 KiB
Plaintext
<template>
|
||
<div class="center-column">
|
||
<!-- 视频播放组件,监听原生事件 -->
|
||
<MonitorView ref="monitor" init="5" style="width:300px;height:200px;margin-top: 20px;" @onTel="handleTelEvent"
|
||
@onSnapShot="handleSnapShotEvent" @onRecord="handleRecordEvent" @onTalkStatus="handleTalkEvent" />
|
||
|
||
<view style="display: flex;flex-direction: row; align-items: flex-start;">
|
||
<!-- 云台控制组件 -->
|
||
<MonitorControlView ref="control" init="5" style="width:300px;height:300px;margin-top: 20px;" />
|
||
|
||
<!-- 功能按钮 -->
|
||
<div class="button-group">
|
||
<button class="button" @click="switchDisplay(0)">原图</button>
|
||
<button class="button" @click="switchDisplay(1)">四分屏</button>
|
||
<button class="button" @click="switchDisplay(2)">180°全景</button>
|
||
<button class="button" @click="switchDisplay(3)">360°全景</button>
|
||
<button class="button" @click="switchDisplay(4)">环状全景</button>
|
||
|
||
<button class="button" @click="startAlarm">开启手动报警</button>
|
||
<button class="button" @click="stopAlarm">停止手动报警</button>
|
||
|
||
<button class="button" @click="flipImage(0)">左右翻转</button>
|
||
<button class="button" @click="flipImage(1)">上下翻转</button>
|
||
<button class="button" @click="flipImage(2)">中心翻转</button>
|
||
<button class="button" @click="flipImage(3)">顺时针90°</button>
|
||
<button class="button" @click="flipImage(4)">逆时针90°</button>
|
||
<button class="button" @click="flipImage(5)">逆时针180°</button>
|
||
<button class="button" @click="flipImage(6)">不翻转</button>
|
||
|
||
<button class="button" @click="resumeOrPause">暂停/继续</button>
|
||
<button class="button" @click="changeQuality">切换清晰度</button>
|
||
|
||
<!-- === 新增的功能按钮:截图 / 录屏 / 对讲 === -->
|
||
<button class="button" @click="doSnapshot">截图</button>
|
||
|
||
<button class="button" :disabled="isRecording" @click="doStartRecord">
|
||
开始录屏
|
||
</button>
|
||
<button class="button" :disabled="!isRecording" @click="doStopRecord">
|
||
结束录屏
|
||
</button>
|
||
|
||
<button class="button" :disabled="isTalking" @click="doOpenTalk">
|
||
开始对讲
|
||
</button>
|
||
<button class="button" :disabled="!isTalking" @click="doStopTalk">
|
||
结束对讲
|
||
</button>
|
||
|
||
<!-- 测试按钮 -->
|
||
<button class="button" @click="test">test</button>
|
||
</div>
|
||
</view>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
phoneNumber: "1234567890",
|
||
isAlarming: false,
|
||
isRecording: false, // 录屏状态
|
||
isTalking: false, // 对讲状态
|
||
};
|
||
},
|
||
onLoad() {
|
||
// 全局事件监听:保留原有用法(有时原生插件会走 globalEvent 发广播)
|
||
const globalEvent = uni.requireNativePlugin && uni.requireNativePlugin("globalEvent");
|
||
if (globalEvent && globalEvent.addEventListener) {
|
||
globalEvent.addEventListener("myEvent", (e) => {
|
||
console.log("myEvent", e);
|
||
});
|
||
}
|
||
},
|
||
methods: {
|
||
/* ------------------ 原有功能 ------------------ */
|
||
handleTelEvent(event) {
|
||
console.log("Tel event detail:", event.detail);
|
||
// 如果需要解析电话事件,在这里处理
|
||
},
|
||
|
||
switchDisplay(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();
|
||
},
|
||
|
||
test() {
|
||
this.$refs.monitor && this.$refs.monitor.test && this.$refs.monitor.test();
|
||
},
|
||
|
||
/* ------------------ 新增:截图/录屏/对讲 调用方法 ------------------ */
|
||
|
||
// 1. 截图(调用)
|
||
doSnapshot() {
|
||
if (!this.$refs.monitor || !this.$refs.monitor.snapShot) {
|
||
uni.showToast({
|
||
title: "组件不支持 snapShot()",
|
||
icon: "none"
|
||
});
|
||
return;
|
||
}
|
||
// 有些原生实现既会通过 callback 返回结果,也可能通过事件推送。这里同时处理 callback
|
||
try {
|
||
this.$refs.monitor.snapShot((res) => {
|
||
// callback 返回路径或结果,优先显示
|
||
console.log("snapShot callback:", res);
|
||
this._handleSnapshotResultFromNative(res);
|
||
});
|
||
uni.showToast({
|
||
title: "正在截屏...",
|
||
icon: "none",
|
||
duration: 800
|
||
});
|
||
} catch (err) {
|
||
console.error("snapShot 调用失败", err);
|
||
uni.showToast({
|
||
title: "snapShot 调用失败",
|
||
icon: "none"
|
||
});
|
||
}
|
||
},
|
||
|
||
// 2. 开始录屏(调用)
|
||
doStartRecord() {
|
||
if (!this.$refs.monitor || !this.$refs.monitor.startRecord) {
|
||
uni.showToast({
|
||
title: "组件不支持 startRecord()",
|
||
icon: "none"
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
this.$refs.monitor.startRecord((res) => {
|
||
// 有些实现会在 start 的 callback 里返回启动结果
|
||
console.log("startRecord callback:", res);
|
||
});
|
||
this.isRecording = true;
|
||
uni.showToast({
|
||
title: "录屏已开始",
|
||
icon: "none"
|
||
});
|
||
} catch (err) {
|
||
console.error("startRecord 调用失败", err);
|
||
uni.showToast({
|
||
title: "startRecord 调用失败",
|
||
icon: "none"
|
||
});
|
||
}
|
||
},
|
||
|
||
// 3. 停止录屏(调用)
|
||
doStopRecord() {
|
||
if (!this.$refs.monitor || !this.$refs.monitor.stopRecord) {
|
||
uni.showToast({
|
||
title: "组件不支持 stopRecord()",
|
||
icon: "none"
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
this.$refs.monitor.stopRecord((res) => {
|
||
// stopRecord 通常会回传录屏结果(recordUrl / recordFailedReason)
|
||
console.log("stopRecord callback:", res);
|
||
this._handleRecordResultFromNative(res);
|
||
});
|
||
// 注意:实际是否结束以及是否成功,会通过回调或事件告诉你,这里先等待回调/事件设置状态
|
||
} catch (err) {
|
||
console.error("stopRecord 调用失败", err);
|
||
uni.showToast({
|
||
title: "stopRecord 调用失败",
|
||
icon: "none"
|
||
});
|
||
}
|
||
},
|
||
|
||
// 4. 开始对讲(调用)
|
||
doOpenTalk() {
|
||
if (!this.$refs.monitor || !this.$refs.monitor.openTalk) {
|
||
uni.showToast({
|
||
title: "组件不支持 openTalk()",
|
||
icon: "none"
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
this.$refs.monitor.openTalk((res) => {
|
||
console.log("openTalk callback:", res);
|
||
// 有的实现会在 callback 中返回立即结果
|
||
});
|
||
// 将状态标为正在建立连接(最终以事件推送为准)
|
||
this.isTalking = true;
|
||
uni.showToast({
|
||
title: "尝试建立对讲连接...",
|
||
icon: "none"
|
||
});
|
||
} catch (err) {
|
||
console.error("openTalk 调用失败", err);
|
||
uni.showToast({
|
||
title: "openTalk 调用失败",
|
||
icon: "none"
|
||
});
|
||
}
|
||
},
|
||
|
||
// 5. 停止对讲(调用)
|
||
doStopTalk() {
|
||
if (!this.$refs.monitor || !this.$refs.monitor.stopTalk) {
|
||
uni.showToast({
|
||
title: "组件不支持 stopTalk()",
|
||
icon: "none"
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
this.$refs.monitor.stopTalk((res) => {
|
||
console.log("stopTalk callback:", res);
|
||
// 回调/事件会通知最终状态
|
||
});
|
||
this.isTalking = false;
|
||
// 依赖事件或回调再把 isTalking 更新为 false(有些实现会立即回调成功)
|
||
} catch (err) {
|
||
console.error("stopTalk 调用失败", err);
|
||
uni.showToast({
|
||
title: "stopTalk 调用失败",
|
||
icon: "none"
|
||
});
|
||
}
|
||
},
|
||
|
||
/* ------------------ 事件回调处理(来自原生推送的事件) ------------------ */
|
||
|
||
// 处理来自模板 @onSnapShot 的事件(event.detail)
|
||
handleSnapShotEvent(event) {
|
||
// event.detail 里可能是你给出的结构:{snapShotUrl, snapShotResult:true/false, snapShotErrorCode:""}
|
||
console.log("onSnapShot event:", event && event.detail ? event.detail : event);
|
||
this._handleSnapshotResultFromNative(event && event.detail ? event.detail : event);
|
||
},
|
||
|
||
// 处理来自模板 @onRecord 的事件(event.detail)
|
||
handleRecordEvent(event) {
|
||
// 期待结构:{recordUrl:"", snapShotResult:true, recordFailedReason:""}
|
||
console.log("onRecord event:", event && event.detail ? event.detail : event);
|
||
this._handleRecordResultFromNative(event && event.detail ? event.detail : event);
|
||
},
|
||
|
||
// 处理来自模板 @onTalkStatus 的事件
|
||
handleTalkEvent(event) {
|
||
// 期待结构:{talkStatus:"loading"|"playing"|"stopped"|"failed", tips:""}
|
||
const payload = event && event.detail ? event.detail : event;
|
||
console.log("onTalkStatus event:", payload);
|
||
|
||
const status = payload && payload.talkStatus;
|
||
const tips = payload && payload.tips;
|
||
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) {
|
||
// res 可能是对象,也可能是字符串,做兼容
|
||
if (!res) {
|
||
uni.showToast({
|
||
title: "截图没有返回数据",
|
||
icon: "none"
|
||
});
|
||
return;
|
||
}
|
||
let payload = res;
|
||
// 当 res 是带 detail 的 event 时(在上层已经做过处理,但再次保险处理)
|
||
if (res.detail) payload = res.detail;
|
||
|
||
// 常见结构: { snapShotUrl: "...", snapShotResult: true/false, snapShotErrorCode: "" }
|
||
console.log("snapshot payload normalized:", payload);
|
||
if (payload.snapShotResult === true || payload.snapShotResult === "true") {
|
||
const url = payload.snapShotUrl || payload.snapShotPath || payload.url;
|
||
uni.showToast({
|
||
title: "截图成功",
|
||
icon: "success",
|
||
duration: 1200
|
||
});
|
||
console.log("截图地址:", url);
|
||
// 你可以在这里把 url 存入 state / 调用后端上传 / 打开预览等
|
||
// 例如打开图片预览:
|
||
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) {
|
||
if (!res) {
|
||
uni.showToast({
|
||
title: "录屏没有返回数据",
|
||
icon: "none"
|
||
});
|
||
this.isRecording = false;
|
||
return;
|
||
}
|
||
let payload = res;
|
||
if (res.detail) payload = res.detail;
|
||
|
||
// 期待: { recordUrl: "...", snapShotResult: true, recordFailedReason: "" }
|
||
console.log("record payload normalized:", payload);
|
||
|
||
// 如果有成功 URL
|
||
if (payload.recordUrl) {
|
||
uni.showToast({
|
||
title: "录屏完成",
|
||
icon: "success",
|
||
duration: 1400
|
||
});
|
||
console.log("录屏地址:", payload.recordUrl);
|
||
this.isRecording = false;
|
||
// TODO: 根据需要下载/上传/播放录屏文件
|
||
} else if (payload.recordFailedReason) {
|
||
uni.showToast({
|
||
title: "录屏失败: " + payload.recordFailedReason,
|
||
icon: "none",
|
||
duration: 2000
|
||
});
|
||
console.warn("record failed reason:", payload.recordFailedReason);
|
||
this.isRecording = false;
|
||
} else {
|
||
// 有些实现可能只返回一个标志位
|
||
if (payload.snapShotResult === true) {
|
||
uni.showToast({
|
||
title: "录屏操作已完成(返回未知)",
|
||
icon: "none"
|
||
});
|
||
}
|
||
this.isRecording = false;
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style>
|
||
.center-column {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.button-group {
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
margin-top: 40px;
|
||
width: 620px;
|
||
}
|
||
|
||
.button {
|
||
margin: 6px;
|
||
padding: 8px 12px;
|
||
min-width: 120px;
|
||
height: 44px;
|
||
border-radius: 6px;
|
||
border: 1px solid #ddd;
|
||
background: #fff;
|
||
}
|
||
|
||
.button[disabled] {
|
||
opacity: 0.5;
|
||
}
|
||
</style> |