fix(amap):集成webrtc 到自有代码
This commit is contained in:
parent
08c8a91182
commit
210df9fa06
|
@ -1,17 +1,25 @@
|
||||||
import React, { useMemo, useRef, useState } from 'react';
|
import React, { useMemo, useRef, useState } from "react";
|
||||||
import { Select, Spin } from 'antd';
|
import { Select, Spin } from "antd";
|
||||||
import type { SelectProps } from 'antd';
|
import type { SelectProps } from "antd";
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from "lodash/debounce";
|
||||||
|
|
||||||
export interface DebounceSelectProps<ValueType = any>
|
export interface DebounceSelectProps<ValueType = any>
|
||||||
extends Omit<SelectProps<ValueType | ValueType[]>, 'options' | 'children'> {
|
extends Omit<SelectProps<ValueType | ValueType[]>, "options" | "children"> {
|
||||||
fetchOptions: (search: string) => Promise<ValueType[]>;
|
fetchOptions: (search: string) => Promise<ValueType[]>;
|
||||||
debounceTimeout?: number;
|
debounceTimeout?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DebounceSelect = <
|
const DebounceSelect = <
|
||||||
ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any,
|
ValueType extends {
|
||||||
>({ fetchOptions, debounceTimeout = 800, ...props }: DebounceSelectProps<ValueType>) =>{
|
key?: string;
|
||||||
|
label: React.ReactNode;
|
||||||
|
value: string | number;
|
||||||
|
} = any
|
||||||
|
>({
|
||||||
|
fetchOptions,
|
||||||
|
debounceTimeout = 800,
|
||||||
|
...props
|
||||||
|
}: DebounceSelectProps<ValueType>) => {
|
||||||
const [fetching, setFetching] = useState(false);
|
const [fetching, setFetching] = useState(false);
|
||||||
const [options, setOptions] = useState<ValueType[]>([]);
|
const [options, setOptions] = useState<ValueType[]>([]);
|
||||||
const fetchRef = useRef(0);
|
const fetchRef = useRef(0);
|
||||||
|
@ -43,9 +51,10 @@ const DebounceSelect = <
|
||||||
onSearch={debounceFetcher}
|
onSearch={debounceFetcher}
|
||||||
notFoundContent={fetching ? <Spin size="small" /> : null}
|
notFoundContent={fetching ? <Spin size="small" /> : null}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
||||||
options={options}
|
options={options}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default DebounceSelect
|
export default DebounceSelect;
|
||||||
|
|
|
@ -7,107 +7,19 @@ import { HomeTwoTone } from "@ant-design/icons";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import { Store } from "antd/es/form/interface";
|
import { Store } from "antd/es/form/interface";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { items } from "./layout_config";
|
||||||
const LayOut = (props: Store) => {
|
const LayOut = (props: Store) => {
|
||||||
const { usrStore } = props;
|
const { usrStore } = props;
|
||||||
const nav = useNavigate();
|
const nav = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("layout ",usrStore.isNeedLogin);
|
|
||||||
if (usrStore.isNeedLogin) {
|
if (usrStore.isNeedLogin) {
|
||||||
nav("/login");
|
nav("/login");
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [usrStore.isNeedLogin]);
|
}, [usrStore.isNeedLogin]);
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
key: "/admin/user",
|
|
||||||
label: `用户管理`,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
key: "/admin/dep",
|
|
||||||
label: `部门管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/user",
|
|
||||||
label: `用户管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/teamMgmt",
|
|
||||||
label: `队伍属性管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/persMgmt",
|
|
||||||
label: `个人身份管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/community",
|
|
||||||
label: `社区管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/grid",
|
|
||||||
label: `网格管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/patrolBrigade",
|
|
||||||
label: `巡防大队`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/archives/box",
|
|
||||||
label: `档案管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/material",
|
|
||||||
label: `物资管理`,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
key: "/admin/whse/whseMgmt",
|
|
||||||
label: `仓库管理`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/materialMgmt",
|
|
||||||
label: `物资管理`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/leaveApproval",
|
|
||||||
label: `请假审批`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/political",
|
|
||||||
label: `政治法规`,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
key: "/admin/politicalStudy",
|
|
||||||
label: `政治学习`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: `/admin/polRegulations`,
|
|
||||||
label: `政治法规管理`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/task",
|
|
||||||
label: `任务管理`,
|
|
||||||
children: [
|
|
||||||
{ label: "处突任务", key: "/admin/emergency" },
|
|
||||||
{ label: "巡逻任务", key: "/admin/patrol" },
|
|
||||||
{ label: "训练任务", key: "/admin/training" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/admin/sys",
|
|
||||||
label: `系统管理`,
|
|
||||||
children: [
|
|
||||||
{ label: "系统设置", key: "/admin/sys/setting" },
|
|
||||||
{ label: "光荣牌审核", key: "/admin/sys/gp" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return (
|
return (
|
||||||
<div className="layout">
|
<div className="layout">
|
||||||
<Header
|
<Header
|
||||||
|
@ -136,12 +48,14 @@ const LayOut = (props: Store) => {
|
||||||
}}
|
}}
|
||||||
style={{ flex: 1, minWidth: 0 }}
|
style={{ flex: 1, minWidth: 0 }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<span style={{ color: "#fff" }}>退出登录</span>
|
||||||
</Header>
|
</Header>
|
||||||
<Content style={{ padding: "0 20px" }}>
|
<Content style={{ padding: "0 20px" }}>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</Content>
|
</Content>
|
||||||
<Footer style={{ textAlign: "center" }}>
|
<Footer style={{ textAlign: "center" }}>
|
||||||
双流区黄水镇人民政府 ©{new Date().getFullYear()} Created
|
双流区黄水镇人民政府 ©{new Date().getFullYear()} Created
|
||||||
</Footer>
|
</Footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
export const items = [
|
||||||
|
{
|
||||||
|
key: "/admin/user",
|
||||||
|
label: `用户管理`,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: "/admin/user",
|
||||||
|
label: `用户管理`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/teamMgmt",
|
||||||
|
label: `队伍属性管理`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/persMgmt",
|
||||||
|
label: `个人身份管理`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/community",
|
||||||
|
label: `社区管理`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/grid",
|
||||||
|
label: `网格管理`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/patrolBrigade",
|
||||||
|
label: `巡防大队`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/archives/box",
|
||||||
|
label: `档案管理`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/material",
|
||||||
|
label: `物资管理`,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: "/admin/whse/whseMgmt",
|
||||||
|
label: `仓库管理`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/materialMgmt",
|
||||||
|
label: `物资管理`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/leaveApproval",
|
||||||
|
label: `请假审批`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/political",
|
||||||
|
label: `政治法规`,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: "/admin/politicalStudy",
|
||||||
|
label: `政治学习`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: `/admin/polRegulations`,
|
||||||
|
label: `政治法规管理`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/task",
|
||||||
|
label: `任务管理`,
|
||||||
|
children: [
|
||||||
|
{ label: "处突任务", key: "/admin/emergency" },
|
||||||
|
{ label: "巡逻任务", key: "/admin/patrol" },
|
||||||
|
{ label: "训练任务", key: "/admin/training" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/admin/sys",
|
||||||
|
label: `系统管理`,
|
||||||
|
children: [
|
||||||
|
{ label: `部门管理`, key: "/admin/dep" },
|
||||||
|
{ label: "系统设置", key: "/admin/sys/setting" },
|
||||||
|
{ label: "光荣牌审核", key: "/admin/sys/gp" },
|
||||||
|
{ label: "评优审核", key: "/admin/sys/gp" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
|
@ -35,7 +35,7 @@ const Dep = (props: Store) => {
|
||||||
setIsModalOpen(true);
|
setIsModalOpen(true);
|
||||||
formRef.current?.setFieldsValue(data);
|
formRef.current?.setFieldsValue(data);
|
||||||
setRecord(data);
|
setRecord(data);
|
||||||
setId(record.id);
|
setId(record.key);
|
||||||
};
|
};
|
||||||
const onFinish = (values: any) => {
|
const onFinish = (values: any) => {
|
||||||
if (!tagId) {
|
if (!tagId) {
|
||||||
|
@ -95,11 +95,11 @@ const Dep = (props: Store) => {
|
||||||
type DirectoryTreeProps = GetProps<typeof Tree.DirectoryTree>;
|
type DirectoryTreeProps = GetProps<typeof Tree.DirectoryTree>;
|
||||||
|
|
||||||
const onSelect: DirectoryTreeProps["onSelect"] = (keys, info) => {
|
const onSelect: DirectoryTreeProps["onSelect"] = (keys, info) => {
|
||||||
console.log("Trigger Select", keys, info);
|
// console.log("Trigger Select", keys, info);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onExpand: DirectoryTreeProps["onExpand"] = (keys, info) => {
|
const onExpand: DirectoryTreeProps["onExpand"] = (keys, info) => {
|
||||||
console.log("Trigger Expand", keys, info);
|
// console.log("Trigger Expand", keys, info);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -126,11 +126,32 @@ const Dep = (props: Store) => {
|
||||||
onExpand={onExpand}
|
onExpand={onExpand}
|
||||||
treeData={org}
|
treeData={org}
|
||||||
titleRender={(nodeData: DataNode) => {
|
titleRender={(nodeData: DataNode) => {
|
||||||
return <>{nodeData.title}<span style={{marginLeft:"10px",color:"blue"}} onClick={edit}>编辑</span></>
|
return (
|
||||||
|
<>
|
||||||
|
{nodeData.title}
|
||||||
|
<span
|
||||||
|
style={{ marginLeft: "10px", color: "blue" }}
|
||||||
|
onClick={() => {
|
||||||
|
edit(nodeData);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{ marginLeft: "10px", color: "blue" }}
|
||||||
|
onClick={() => {
|
||||||
|
depStore.deleteItem(nodeData.key);
|
||||||
|
getOrg()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Modal
|
<Modal
|
||||||
title={!tagId ? "添加部门" : "编辑部门"}
|
title={!record ? "添加部门" : "编辑部门"}
|
||||||
width={800}
|
width={800}
|
||||||
open={isModalOpen}
|
open={isModalOpen}
|
||||||
afterClose={() => formRef.current?.resetFields()}
|
afterClose={() => formRef.current?.resetFields()}
|
||||||
|
@ -139,6 +160,7 @@ const Dep = (props: Store) => {
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setId(null);
|
setId(null);
|
||||||
|
setRecord(null);
|
||||||
setIsModalOpen(false);
|
setIsModalOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -149,7 +149,7 @@ const Emergency = (props: Store) => {
|
||||||
baseHttp.get("/user/list", null).then((res) => {
|
baseHttp.get("/user/list", null).then((res) => {
|
||||||
let data = res.data?.record ?? [];
|
let data = res.data?.record ?? [];
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
item.label = item.account;
|
item.label = item.user_name;
|
||||||
item.value = item.identity;
|
item.value = item.identity;
|
||||||
});
|
});
|
||||||
setUserList(data ?? []);
|
setUserList(data ?? []);
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex: 2;
|
flex: 5;
|
||||||
.title_img {
|
.title_img {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 30px;
|
font-size:25px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
letter-spacing: 0.1em;
|
letter-spacing: 0.1em;
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 20px;
|
font-size: 14px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
letter-spacing: 0.1em;
|
letter-spacing: 0.1em;
|
||||||
|
|
|
@ -21,7 +21,7 @@ const Home = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
<div className="map_container_t_c">
|
<div className="map_container_t_c">
|
||||||
<img className="twp on_to" src={image2} alt="" />
|
<img className="twp on_to" src={image2} alt="" />
|
||||||
<span>黄水镇武装平台</span>
|
<span>黄水镇微网实格应急处突综合指挥服务平台</span>
|
||||||
<img className="twp" src={image2} alt="" />
|
<img className="twp" src={image2} alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div className="map_container_t_r">
|
<div className="map_container_t_r">
|
||||||
|
|
|
@ -5,25 +5,33 @@ import { useState } from "react";
|
||||||
import "./bot.less";
|
import "./bot.less";
|
||||||
import { PhoneTwoTone } from "@ant-design/icons";
|
import { PhoneTwoTone } from "@ant-design/icons";
|
||||||
import { webRTC } from "@/util/webRtc";
|
import { webRTC } from "@/util/webRtc";
|
||||||
|
import DebounceSelect from "@/components/form/featch_select";
|
||||||
|
interface UserValue {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
const Ec = (props: Store) => {
|
const Ec = (props: Store) => {
|
||||||
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
||||||
const { usrStore } = props;
|
const { usrStore } = props;
|
||||||
const [userList, setUserList] = useState<any>([]);
|
|
||||||
const openDispatch = () => {
|
const openDispatch = () => {
|
||||||
try {
|
try {
|
||||||
usrStore.getlist().then(() => {
|
setIsModalOpen(true);
|
||||||
setUserList(usrStore.list);
|
|
||||||
webRTC.init();
|
|
||||||
setIsModalOpen(true);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const callphone = (record: any) => {
|
const callphone = (record: any) => {
|
||||||
webRTC.calls(record.identity);
|
webRTC.calls(record.value);
|
||||||
};
|
};
|
||||||
|
const [value, setValue] = useState<UserValue[]>([]);
|
||||||
|
async function fetchUserList(username: string): Promise<UserValue[]> {
|
||||||
|
return usrStore.serchUser(username).then((res) => {
|
||||||
|
return res.data.record.map((item) => ({
|
||||||
|
label: item.user_name,
|
||||||
|
value: item.identity,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span onClick={openDispatch}> 应急连线</span>
|
<span onClick={openDispatch}> 应急连线</span>
|
||||||
|
@ -45,16 +53,27 @@ const Ec = (props: Store) => {
|
||||||
<h3>应急连线</h3>
|
<h3>应急连线</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="u-item">
|
<div className="u-item">
|
||||||
{userList.map((item: any) => {
|
<DebounceSelect
|
||||||
|
mode="multiple"
|
||||||
|
value={value}
|
||||||
|
placeholder="输入搜索"
|
||||||
|
fetchOptions={fetchUserList}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
setValue(newValue as UserValue[]);
|
||||||
|
}}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
<p></p>
|
||||||
|
{value.map((item: any) => {
|
||||||
return (
|
return (
|
||||||
<div key={item.account}>
|
<div key={item.key}>
|
||||||
<div>姓名:{item.user_name} : 未在线</div>
|
<div>姓名:{item.label} : 未在线</div>
|
||||||
<p></p>
|
|
||||||
<div>
|
<div>
|
||||||
点击呼叫:
|
点击呼叫:
|
||||||
<PhoneTwoTone
|
<PhoneTwoTone
|
||||||
style={{ fontSize: "20px" }}
|
style={{ fontSize: "20px" }}
|
||||||
onClick={(items) => {
|
onClick={(items) => {
|
||||||
|
webRTC.init();
|
||||||
callphone(item);
|
callphone(item);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -75,7 +94,6 @@ const Ec = (props: Store) => {
|
||||||
style={{ width: "300px", height: "300px" }}
|
style={{ width: "300px", height: "300px" }}
|
||||||
></video>
|
></video>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
className="ec_right_end"
|
className="ec_right_end"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -14,16 +14,33 @@ const Weather = () => {
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
flex: "1",
|
flex: "1",
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-around",
|
|
||||||
color: "#fff",
|
color: "#fff",
|
||||||
|
fontSize: "13px",
|
||||||
|
padding:"10px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>天气:{wechaer?.weather}</p>
|
<div
|
||||||
<p>风向:{wechaer?.windDirection}</p>
|
style={{
|
||||||
<p>风级:{wechaer?.windPower}</p>
|
fontSize: "13px",
|
||||||
<p>湿度:{wechaer?.humidity}</p>
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>天气:{wechaer?.weather}</span>
|
||||||
|
<span>风向:{wechaer?.windDirection}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "13px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>风级:{wechaer?.windPower}</span>
|
||||||
|
<span>湿度:{wechaer?.humidity}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ const videoJsOptions = {
|
||||||
fluid: true,
|
fluid: true,
|
||||||
sources: [
|
sources: [
|
||||||
{
|
{
|
||||||
src: "http://112.19.145.68:18000/hls/stream_1_0/playlist.m3u8",
|
src: "http://183.221.86.205:18000/hls/stream_1_0/playlist.m3u8",
|
||||||
type: "application/x-mpegURL",
|
type: "application/x-mpegURL",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -19,7 +19,6 @@ const Video = (props: Store) => {
|
||||||
const { homeStore, onReady } = props;
|
const { homeStore, onReady } = props;
|
||||||
const videoRef = useRef<HTMLDivElement>(null);
|
const videoRef = useRef<HTMLDivElement>(null);
|
||||||
const playerRef = useRef<any>(null); // 使用 any 类型
|
const playerRef = useRef<any>(null); // 使用 any 类型
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
homeStore.getNewTask();
|
homeStore.getNewTask();
|
||||||
}, [homeStore]);
|
}, [homeStore]);
|
||||||
|
@ -44,7 +43,6 @@ const Video = (props: Store) => {
|
||||||
}, [videoRef, onReady]);
|
}, [videoRef, onReady]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (player && !player.isDisposed()) {
|
if (player && !player.isDisposed()) {
|
||||||
player.dispose();
|
player.dispose();
|
||||||
|
|
|
@ -64,7 +64,7 @@ const Regulations = (props: Store) => {
|
||||||
const onFinish = (values: any) => {
|
const onFinish = (values: any) => {
|
||||||
let data = {
|
let data = {
|
||||||
...values,
|
...values,
|
||||||
file_url: values.file_url[0].name,
|
file_url: (values.file_url.length>0)? values.file_url[0].name:'',
|
||||||
};
|
};
|
||||||
if (!record?.id) {
|
if (!record?.id) {
|
||||||
regulationsStore.add(data);
|
regulationsStore.add(data);
|
||||||
|
|
|
@ -37,7 +37,12 @@ export const defaultConfig = [
|
||||||
label: "法规副标题",
|
label: "法规副标题",
|
||||||
name: "sub_title",
|
name: "sub_title",
|
||||||
value: "",
|
value: "",
|
||||||
rules: [{ required: true, message: "请输入法规副标题!" }],
|
},
|
||||||
|
{
|
||||||
|
type: FormType.inputNumber,
|
||||||
|
label: "排序",
|
||||||
|
name: "level",
|
||||||
|
value: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "editor",
|
type: "editor",
|
||||||
|
|
|
@ -24,7 +24,6 @@ axios.interceptors.response.use((res: AxiosResponse) => {
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
|
|
||||||
if (err.status === 401) {
|
if (err.status === 401) {
|
||||||
store.usrStore.openLoginDilog()
|
store.usrStore.openLoginDilog()
|
||||||
store.usrStore.logOut()
|
store.usrStore.logOut()
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 362 KiB After Width: | Height: | Size: 101 KiB |
|
@ -2,7 +2,7 @@ class Config {
|
||||||
static baseUrl = "https://rw.quwanya.cn/";
|
static baseUrl = "https://rw.quwanya.cn/";
|
||||||
static uploadUrl = "https://rw.quwanya.cn/";
|
static uploadUrl = "https://rw.quwanya.cn/";
|
||||||
static ws = "wss://rw.quwanya.cn/wsadmin?id=admin";
|
static ws = "wss://rw.quwanya.cn/wsadmin?id=admin";
|
||||||
static rtc = "wss://rw.quwanya.cn/ws";
|
// static rtc = "wss://rw.quwanya.cn/ws";
|
||||||
static userStatic = "https://rw.quwanya.cn/uploads/user/";
|
static userStatic = "https://rw.quwanya.cn/uploads/user/";
|
||||||
// https://rw.quwanya.cn/uploads/user/%E5%B4%94%E6%96%87%E8%8C%9C.jpg
|
// https://rw.quwanya.cn/uploads/user/%E5%B4%94%E6%96%87%E8%8C%9C.jpg
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
import Config from "./config";
|
import SocketService from "./socket";
|
||||||
|
|
||||||
class WebRtc {
|
class WebRtc {
|
||||||
private mediaStream: MediaStream | Blob | null = null;
|
private mediaStream: MediaStream | Blob | null = null;
|
||||||
private pee: RTCPeerConnection | null = null;
|
private pee: RTCPeerConnection | null = null;
|
||||||
private ws: WebSocket | null = null;
|
private ws: SocketService | null = null;
|
||||||
private video: HTMLVideoElement | null = null;
|
private video: HTMLVideoElement | null = null;
|
||||||
private userToId: string = "";
|
private userToId: string = "";
|
||||||
open = () => {
|
open = () => {
|
||||||
|
@ -17,57 +17,55 @@ class WebRtc {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
async init() {
|
async init() {
|
||||||
this.ws = new WebSocket(Config.rtc)
|
this.ws = SocketService.getInstance();
|
||||||
this.ws.addEventListener('open', this.open);
|
this.ws.on("message", this.onMessage);
|
||||||
let that = this;
|
|
||||||
this.createOffer()
|
this.createOffer()
|
||||||
this.ws.onmessage = function (evt) {
|
}
|
||||||
let msg = JSON.parse(evt.data)
|
onMessage = (e: any) => {
|
||||||
if (!msg) {
|
let that = this;
|
||||||
return console.log('failed to parse msg')
|
let msg = JSON.parse(e.data)
|
||||||
}
|
if (!msg) {
|
||||||
switch (msg.type) {
|
return console.log('failed to parse msg')
|
||||||
case 'offer':
|
}
|
||||||
let offer = msg.data.description
|
switch (msg.type) {
|
||||||
that.pee?.setRemoteDescription(offer)
|
case 'offer':
|
||||||
that.pee?.createAnswer().then(answer => {
|
let offer = msg.data.description
|
||||||
that.pee?.setLocalDescription(answer)
|
that.pee?.setRemoteDescription(offer)
|
||||||
that.ws?.send(JSON.stringify({
|
that.pee?.createAnswer().then(answer => {
|
||||||
type: 'answer', data: {
|
that.pee?.setLocalDescription(answer)
|
||||||
'to': msg.data.from,
|
that.ws?.send(JSON.stringify({
|
||||||
'from': "31283192",
|
type: 'answer', data: {
|
||||||
'description': { 'sdp': answer.sdp, 'type': answer.type },
|
'to': msg.data.from,
|
||||||
'session_id': msg.data.from + "-31283192",
|
'from': "31283192",
|
||||||
}
|
'description': { 'sdp': answer.sdp, 'type': answer.type },
|
||||||
}))
|
'session_id': msg.data.from + "-31283192",
|
||||||
})
|
}
|
||||||
return
|
}))
|
||||||
|
})
|
||||||
|
return
|
||||||
|
|
||||||
case 'candidate':
|
case 'candidate':
|
||||||
let candidate = msg.data.candidate
|
let candidate = msg.data.candidate
|
||||||
if (!candidate) {
|
if (!candidate) {
|
||||||
return console.log('failed to parse candidate')
|
return console.log('failed to parse candidate')
|
||||||
}
|
}
|
||||||
that.pee?.addIceCandidate(candidate)
|
that.pee?.addIceCandidate(candidate)
|
||||||
break;
|
break;
|
||||||
case "answer":
|
case "answer":
|
||||||
that.pee?.setRemoteDescription(msg.data.description)
|
that.pee?.setRemoteDescription(msg.data.description)
|
||||||
break;
|
break;
|
||||||
case "bye":
|
case "bye":
|
||||||
that.pee?.close()
|
that.pee?.close()
|
||||||
that.close()
|
that.close()
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async createOffer() {
|
async createOffer() {
|
||||||
|
|
||||||
var url =
|
var url =
|
||||||
'http://rw.quwanya.cn:12217/api/turn?service=turn&username=flutter-webrtc';
|
'http://rw.quwanya.cn:12217/api/turn?service=turn&username=flutter-webrtc';
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
|
||||||
const configuration = {
|
const configuration = {
|
||||||
iceServers: [
|
iceServers: [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue