fix(amap):集成webrtc 到自有代码

This commit is contained in:
wang_yp 2024-11-14 22:31:30 +08:00
parent 210df9fa06
commit 32c9bd2381
12 changed files with 301 additions and 145 deletions

View File

@ -81,7 +81,7 @@ export const items = [
{ label: `部门管理`, key: "/admin/dep" },
{ label: "系统设置", key: "/admin/sys/setting" },
{ label: "光荣牌审核", key: "/admin/sys/gp" },
{ label: "评优审核", key: "/admin/sys/gp" },
{ label: "评优审核", key: "/admin/sys/exce_compet" },
],
},
];

View File

@ -10,6 +10,7 @@ class MapUtl {
static addMaker(data: any) {
const { lng, lat, title, users } = data;
if (MapUtl.loadMap === null) return;
const marker = new MapUtl.loadMap.Marker({
position: new MapUtl.loadMap.LngLat(lng, lat),
title: title,

View File

@ -0,0 +1,53 @@
import BTable from "@/components/b_table";
import { UserDataType } from "@/model/userModel";
import { Button } from "antd";
import { Store } from "antd/es/form/interface";
import { ColumnsType } from "antd/lib/table";
import { inject, observer } from "mobx-react";
import { useEffect } from "react";
const ExceCompet = (props: Store) => {
const { exceCompetStore } = props;
useEffect(() => {
exceCompetStore.getlist();
}, [exceCompetStore]);
const columns: ColumnsType<UserDataType> = [
{ title: "评优标题", dataIndex: "title" },
{ title: "内容", dataIndex: "content" },
{
title: "评优申请人",
dataIndex: "users",
render: (users) => <span>{users?.user_name}</span>
},
{ title: "申请积分", dataIndex: "reviewer_score" },
{ title: "申请时间", dataIndex: "created_at" },
{ title: "描述", dataIndex: "desc" },
{ title: "审核状态", dataIndex: "status" },
{ title: "审核人", dataIndex: "reviewer_identity" },
{
title: "操作",
dataIndex: "id",
render: (any, record) => (
<Button
type="dashed"
size="small"
onClick={() => {
// edit(record);
}}
>
</Button>
),
},
];
return (
<div>
<BTable
store={exceCompetStore}
columns={columns}
dataSource={exceCompetStore.list}
/>
</div>
);
};
export default inject("exceCompetStore")(observer(ExceCompet));

View File

@ -48,7 +48,7 @@ const Home = observer(() => {
</div>
<MapContainer />
<div className="map_video_container">
<Video />
{/* <Video /> */}
</div>
<div className="map_container_r">
<HomeRight />

View File

@ -20,9 +20,7 @@ const Ec = (props: Store) => {
console.log(error);
}
};
const callphone = (record: any) => {
webRTC.calls(record.value);
};
const [value, setValue] = useState<UserValue[]>([]);
async function fetchUserList(username: string): Promise<UserValue[]> {
return usrStore.serchUser(username).then((res) => {
@ -73,8 +71,8 @@ const Ec = (props: Store) => {
<PhoneTwoTone
style={{ fontSize: "20px" }}
onClick={(items) => {
webRTC.init();
callphone(item);
webRTC.init(item.key);
webRTC.calls();
}}
/>
</div>

View File

@ -10,7 +10,7 @@ const videoJsOptions = {
fluid: true,
sources: [
{
src: "http://183.221.86.205:18000/hls/stream_1_0/playlist.m3u8",
src: "https://sprh.hswzct.cn:4443/hls/stream_1_0/playlist.m3u8",
type: "application/x-mpegURL",
},
],

View File

@ -26,6 +26,7 @@ import GloryPlaque from "@/pages/glory_plaque";
import Grid from "@/pages/grid";
import Community from "@/pages/community";
import PatrolBrigade from "@/pages/patrolBrigade";
import ExceCompet from "@/pages/exce_compet";
export const homeRouter = [
{
path: "/",
@ -148,6 +149,7 @@ export const homeRouter = [
index: true,
element: <Training />,
},
{
path: "/admin/whse",
element: <WhseMgmtRoute />,
@ -178,6 +180,11 @@ export const homeRouter = [
index: true,
element: <GloryPlaque />,
},
{
path: "/admin/sys/exce_compet",
index: true,
element: <ExceCompet />,
},
],
},
],

26
src/store/exce_compet.ts Normal file
View File

@ -0,0 +1,26 @@
import { action, makeObservable } from "mobx";
// 档案
import BaseStore from "./baseStore";
import { TagDataType } from "@/model/userModel";
import baseHttp from "@/service/base";
class ExceCompetConfig {
static LIST: string = "exceCompet/list"
static ADD: string = "exceCompet"
static DELETE: string = "exceCompet"
static EDIT: string = "exceCompet"
}
class ExceCompetStore extends BaseStore<TagDataType> {
constructor() {
super(ExceCompetConfig)
makeObservable(this, {
save: action
})
}
async save(id: string, list: Array<any>) {
return await baseHttp.post(ExceCompetConfig.ADD +"/"+ id, {"list":list});
}
}
export const exceCompetStore = new ExceCompetStore()

View File

@ -25,6 +25,7 @@ import gpStore from './gp';
import { communityStore } from './community';
import { gridStore } from './grid';
import { patrolBrigadeStore } from './patrol_brigade';
import { exceCompetStore } from './exce_compet';
@ -55,7 +56,8 @@ const store = {
gpStore,
gridStore,
communityStore,
patrolBrigadeStore
patrolBrigadeStore,
exceCompetStore
};
export default store;

View File

@ -25,11 +25,11 @@
</body>
<script>
let ws;
let pc;
let configuration;
var url =
'http://127.0.0.1:12214/v1/public/webRtcConfig?service=turn&username=flutter-webrtc';
let ws, pc, configuration,
url =
'https://rw.quwanya.cn/v1/public/webRtcConfig?service=turn&username=flutter-webrtc',
formId = "admin",
toId = "01J9T8MP541EJ54KY4505C0S4Y";
fetch(url)
.then(response => response.json())
.then(data => {
@ -45,6 +45,123 @@
}
})
const call = () => {
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
pc = new RTCPeerConnection(configuration)
pc.ontrack = function (event) {
console.log(event)
if (event.track.kind === 'audio') {
return
}
let el = document.createElement(event.track.kind)
el.srcObject = event.streams[0]
el.autoplay = true
el.controls = true
document.getElementById('remoteVideos').appendChild(el)
event.track.onmute = function (event) {
el.play()
}
event.streams[0].onremovetrack = ({ track }) => {
if (el.parentNode) {
el.parentNode.removeChild(el)
}
}
}
document.getElementById('localVideo').srcObject = stream
stream.getTracks().forEach(track => pc.addTrack(track, stream))
pc.onicecandidate = e => {
if (!e.candidate) {
return
}
ws.send(JSON.stringify({
type: "candidate", data: {
"to": toId,
"from": formId,
"description": e.candidate,
"media": "video",
"session_id": toId + "-" + formId,
}
}))
}
this.send({
type: "call",
"data": {
"to": toId,
"from": formId,
"description": "call",
"media": "video",
"session_id": toId + "-" + formId,
}
})
})
}
send = (data) => {
ws.send(JSON.stringify(data))
}
// wss://rw.quwanya.cn/ws
initSocket = () => {
ws = new WebSocket("wss://rw.quwanya.cn/wsadmin?id=" + formId)
ws.addEventListener('open', function (event) {
ws.send(JSON.stringify({
type: "peerRoot", "data": {
"name": "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 )",
"id": formId,
"user_agent": "flutter-webrtc/js"
}
}))
});
ws.onclose = function (evt) {
console.log(evt);
}
ws.onmessage = function (evt) {
let msg = JSON.parse(evt.data)
if (!msg) {
return console.log('failed to parse msg')
}
switch (msg.type) {
case 'offer':
let offer = msg.content.body.description
pc.setRemoteDescription(offer)
pc.createAnswer().then(answer => {
pc.setLocalDescription(answer)
ws.send(JSON.stringify({
type: 'answer', data: {
'to': msg.content.body.from,
'from': formId,
'description': { 'sdp': answer.sdp, 'type': answer.type },
'session_id': msg.content.body.from + "-" + toId,
}
}))
})
return
case 'candidate':
let candidate = msg.content.body.description
console.log("candidate1111", msg.content)
if (!candidate) {
return console.log('failed to parse candidate')
}
pc.addIceCandidate(candidate)
return
case "read":
pc?.createOffer().then(function (offer) {
pc?.setLocalDescription(offer);
ws.send(JSON.stringify({
type: "offer", "data": {
"to": toId,//"31283192",
"from": formId,
"description": offer,
"media": "video",
"session_id": formId + "-" + toId,
}
}),)
}).catch(function (error) {
// 错误处理
console.error(error);
});
return
case "call": // 接收到call 初始化 然后发送消息 read
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
pc = new RTCPeerConnection(configuration)
@ -72,76 +189,31 @@
if (!e.candidate) {
return
}
ws.send(JSON.stringify({ type: 'candidate', data: e }))
}
pc?.createOffer().then(function (offer) {
pc?.setLocalDescription(offer);
ws.send(JSON.stringify({
type: "offer", "data": {
"to": "31283192",
"from": "31283191",
"description": offer,
type: 'candidate',
data: {
"to": toId,
"from": formId,
"description": e,
"media": "video",
"session_id": "31283192-31283191",
"session_id": toId + "-" + formId,
}
}))
// socketService.send({ type: 'offer', data: offer })
}).catch(function (error) {
// 错误处理
console.error(error);
});
}).catch((e) => {
console.log(e);
})
}
// wss://rw.quwanya.cn/ws
initSocket = () => {
ws = new WebSocket("ws://127.0.0.1:12214/wsadmin?id=31283192")
ws.addEventListener('open', function (event) {
ws.send(JSON.stringify({
type: "peerRoot", "data": {
"name": "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 )",
"id": "31283192",
"user_agent": "flutter-webrtc/js"
type: "read", "data": {
"to": toId,
"from": formId,
"description": "read",
"media": "video",
"session_id": toId + "-" + formId,
}
}))
});
ws.onclose = function (evt) {
console.log(evt);
}
ws.onmessage = function (evt) {
let msg = JSON.parse(evt.data)
if (!msg) {
return console.log('failed to parse msg')
}
console.log(msg);
switch (msg.type) {
case 'offer':
let offer = msg.data.description
pc.setRemoteDescription(offer)
pc.createAnswer().then(answer => {
pc.setLocalDescription(answer)
ws.send(JSON.stringify({
type: 'answer', data: {
'to': msg.data.from,
'from': "31283192",
'description': { 'sdp': answer.sdp, 'type': answer.type },
'session_id': msg.data.from + "-31283192",
}
}))
})
return
case 'candidate':
let candidate = msg.content.body
if (!candidate) {
return console.log('failed to parse candidate')
}
pc.addIceCandidate(candidate)
case "answer":
pc?.setRemoteDescription(msg.data.description)
pc?.setRemoteDescription(msg.content.body.description)
}
}
@ -150,6 +222,7 @@
}
}
initSocket()
</script>
</html>

View File

@ -61,7 +61,7 @@ export type AutoReconnectOptions = boolean | {
}
}
public hert(){
this.times = setInterval(() => this.send({"type":"heartbeat"}), 3000)
this.times = setInterval(() => this.send({"type":"heartbeat","data":{}}), 10000)
}
private shouldReconnect(): boolean {
if (typeof this.autoReconnect === 'boolean') {

View File

@ -1,5 +1,6 @@
import SocketService from "./socket";
import baseHttp from "@/service/base";
class WebRtc {
private mediaStream: MediaStream | Blob | null = null;
@ -7,167 +8,162 @@ class WebRtc {
private ws: SocketService | null = null;
private video: HTMLVideoElement | null = null;
private userToId: string = "";
open = () => {
this.ws?.send(JSON.stringify({
type: "new", "data": {
"name": "admin",
"id": "31283192",
"user_agent": "flutter-webrtc/js"
}
}))
}
async init() {
async init(userId) {
this.userToId = userId
this.ws = SocketService.getInstance();
this.ws.on("message", this.onMessage);
this.createOffer()
}
onMessage = (e: any) => {
let that = this;
let msg = JSON.parse(e.data)
let msg = JSON.parse(e)
if (!msg) {
return console.log('failed to parse msg')
}
switch (msg.type) {
case 'offer':
let offer = msg.data.description
that.pee?.setRemoteDescription(offer)
that.pee?.createAnswer().then(answer => {
that.pee?.setLocalDescription(answer)
that.ws?.send(JSON.stringify({
type: 'answer', data: {
'to': msg.data.from,
'from': "31283192",
'description': { 'sdp': answer.sdp, 'type': answer.type },
'session_id': msg.data.from + "-31283192",
let offer = msg.content.body.description;
this.pee?.setRemoteDescription(offer)
this.pee?.createAnswer().then(answer => {
this.pee?.setLocalDescription(answer)
this.ws?.send({
type: 'answer',
data: {
to: msg.content.body.from,
from: "admin",
description: { 'sdp': answer.sdp, 'type': answer.type },
session_id: msg.content.body.from + "-admin",
}
}))
})
return
})
break;
case "read":
this.sendOffer()
break;
case 'candidate':
let candidate = msg.data.candidate
let candidate = msg.content.body.description
if (!candidate) {
return console.log('failed to parse candidate')
}
that.pee?.addIceCandidate(candidate)
this.pee?.addIceCandidate(candidate)
break;
case "answer":
that.pee?.setRemoteDescription(msg.data.description)
this.pee?.setRemoteDescription(msg.content.body.description)
break;
case "bye":
that.pee?.close()
that.close()
this.close()
break;
}
}
async createOffer() {
var url =
'http://rw.quwanya.cn:12217/api/turn?service=turn&username=flutter-webrtc';
fetch(url)
.then(response => response.json())
.then(data => {
let basData =await baseHttp.get('/public/webRtcConfig', { service: "11", username: "admin" })
const configuration = {
iceServers: [
{
urls: data.uris[0],
"username": data.username,
"credential": data.password
urls: basData.data.credential.uris,
username: basData.data.credential.username,
credential: basData.data.credential.password,
ttl:basData.data.credential.ttl
},
]
}
this.gets(configuration)
})
try {
} catch (error) {
console.log(error);
}
}
async gets(configuration) {
console.log(configuration);
const peerConnection = new RTCPeerConnection(configuration);
this.pee = peerConnection
this.pee = new RTCPeerConnection(configuration);
// 获取远方流添加到页面播放
peerConnection.ontrack = event => {
const remoteVideo = document.querySelector('#remoteVideo') as HTMLVideoElement;
remoteVideo.autoplay = true
remoteVideo.controls = true
remoteVideo.srcObject = event.streams[0];
console.log(event);
event.track.onmute = function () {
remoteVideo.play()
this.pee.ontrack = event => {
const re = document.querySelector('#remoteVideo') as HTMLVideoElement;
re.autoplay = true
re.controls = true
console.log(event.streams[0])
re.srcObject = event.streams[0];
event.track.onmute = function (event) {
re.play()
}
event.streams[0].onremovetrack = ({ track }) => {
if (re.parentNode) {
re.parentNode.removeChild(re)
}
}
};
await this.getMedia(peerConnection)
peerConnection.onicecandidate = e => {
this.pee.onicecandidate = e => {
if (!e.candidate) {
return
}
this.ws?.send(JSON.stringify({ type: 'candidate', data: e }))
this.ws?.send({
type: "candidate", data: {
to: this.userToId,
from: "admin",
description: e.candidate,
media: "video",
session_id: this.userToId + "-admin",
}
})
}
sendOffer(userId) {
this.ws?.send({
type: "call",
data: {
to: this.userToId,
from: "admin",
description: "call",
media: "video",
session_id: this.userToId + "-admin",
}
})
}
sendOffer() {
let that = this;
that.userToId = userId;
that.video = document.getElementById('rtcVideo') as HTMLVideoElement;
if (that.pee?.connectionState === "closed") {
that.createOffer()
}
that.pee?.createOffer().then(function (offer) {
that.pee?.setLocalDescription(offer);
that.ws?.send(JSON.stringify({
type: "offer", "data": {
"to": userId,
"from": "31283192",
"description": offer,
"media": "video",
"session_id": userId + "-31283192",
that.ws?.send({
type: "offer",
data: {
to: that.userToId,
from: "admin",
description: offer,
media: "video",
session_id: that.userToId + "-admin",
}
}))
})
}).catch(function (error) {
// 错误处理
console.error(error);
});
}
addIceCandidate(candidate) {
this.pee?.addIceCandidate(candidate)
}
async getMedia(pee: RTCPeerConnection) {
async getMedia() {
try {
this.video = document.getElementById('rtcVideo') as HTMLVideoElement;
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
this.mediaStream = stream;
stream.getTracks().forEach(track => pee.addTrack(track, stream))
} catch (error) {
console.log(error);
}
}
calls(userId) {
this.sendOffer(userId)
stream.getTracks().forEach(track => this.pee?.addTrack(track, stream))
if (this.video) {
this.video.srcObject = this.mediaStream;
this.video.autoplay = true;
}
} catch (error) {
console.log(error);
}
}
async calls() {
await this.createOffer()
await this.getMedia()
}
close() {
this.video?.pause();
this.pee?.close();
this.ws?.send(JSON.stringify({
"type": "bye", "data": {
"session_id": this.userToId + "31283192",
"to": this.userToId
}
}
));
// this.ws?.send({
// type: "bye",
// data: {
// session_id: this.userToId + "admin",
// to: this.userToId,
// from: "admin"
// }
// });
(this.mediaStream as MediaStream)?.getTracks().forEach(track => track.stop());
this.ws?.close()
}
}