fix(api):update store

This commit is contained in:
wang_yp 2024-09-26 00:21:57 +08:00
parent cc638d92ee
commit ba59eadd34
19 changed files with 622 additions and 189 deletions

View File

@ -56,7 +56,6 @@ To learn React, check out the [React documentation](https://reactjs.org/).
2、武装力量 根据队伍统计 2、武装力量 根据队伍统计
3、年度训练 按照年度统计类别,次数 (任务发布时,可选择多个类别) 3、年度训练 按照年度统计类别,次数 (任务发布时,可选择多个类别)
4、物资管理 4、物资管理
5、档案管理 5、档案管理

View File

@ -1,5 +1,21 @@
import { Outlet } from "react-router"; import { Outlet } from "react-router";
import MyComponent from "./components/errorComp"; import MyComponent from "./components/errorComp";
import MapUtl from "./components/map/mapUtil";
const { socket } = require("./util/socket");
socket.init();
socket.onmessage((e) => {
const data = JSON.parse(e.data);
// if (data.type === "heartbeat") {
// MapUtl.makerList[0].setPosition([103.55, 30.342]);
// var m = MapUtl.amap;
// var newIcon = new m.Icon({
// image: "//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png", //Icon 的图像
// size: new m.Size(25, 34), // 图标大小
// anchor: new m.Pixel(12, 32), // 图标锚点
// });
// MapUtl.makerList[0].setIcon(newIcon);
// }
});
const App = () => { const App = () => {
return ( return (
<> <>

View File

@ -11,54 +11,80 @@ const LayOut = (props: Store) => {
const { usrStore } = props; const { usrStore } = props;
const nav = useNavigate(); const nav = useNavigate();
const location = useLocation(); const location = useLocation();
useEffect(() => { useEffect(() => {
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 = [ const items = [
{ {
key: "/admin/user", key: "/admin/user",
label: `用户管理`, label: `用户管理`,
}, children: [
{ {
key: "/admin/dep", key: "/admin/dep",
label: `部门管理`, label: `部门管理`,
},
{
key: "/admin/user",
label: `用户管理`,
},
{
key: "/admin/teamMgmt",
label: `队伍属性管理`,
},
{
key: "/admin/persMgmt",
label: `个人身份管理`,
},
],
}, },
{ {
key: "/admin/archives", key: "/admin/archives",
label: `档案管理`, label: `档案管理`,
}, },
{ {
key: "/admin/whse/whseMgmt", key: "/admin/material",
label: `仓库管理`,
},
{
key: "/admin/materialMgmt",
label: `物资管理`, label: `物资管理`,
children: [
{
key: "/admin/whse/whseMgmt",
label: `仓库管理`,
},
{
key: "/admin/materialMgmt",
label: `物资管理`,
},
],
}, },
{ {
key: "/admin/leaveApproval", key: "/admin/leaveApproval",
label: `请假审批`, label: `请假审批`,
}, },
{ {
key: "/admin/politicalStudy", key: "/admin/political",
label: `政治学习`, label: `政治法规`,
children: [
{
key: "/admin/politicalStudy",
label: `政治学习`,
},
{
key: `/admin/polRegulations`,
label: `政治法规管理`,
},
],
}, },
{ {
key: `/admin/polRegulations`, key: "/admin/task",
label: `政治法规管理`, label: `任务管理`,
}, children: [
{ label: "处突任务", key: "/admin/emergency" },
{ { label: "巡逻任务", key: "/admin/patrol" },
key: "/admin/teamMgmt", { label: "训练任务", key: "/admin/training" },
label: `队伍属性管理`, ],
},
{
key: "/admin/persMgmt",
label: `个人身份管理`,
}, },
]; ];
return ( return (
@ -72,7 +98,7 @@ const LayOut = (props: Store) => {
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
padding: "0 10px", padding: "0 10px",
boxSizing: "border-box" boxSizing: "border-box",
}} }}
> >
<HomeTwoTone <HomeTwoTone

View File

@ -1,142 +1,3 @@
// // 档案管理
// import { Button, Space, Modal, FormInstance, Flex } from "antd";
// import { inject, observer } from "mobx-react";
// import { useEffect, useState } from "react";
// import { Store } from "antd/lib/form/interface";
// import SimpleForm from "@/components/form/simple_form";
// import React from "react";
// import { folderConfig } from "./archives_conf";
// import { Form, Select } from "antd";
// import BTable from "@/components/b_table";
// const { Option } = Select;
// const Archive = (props: Store) => {
// const { folderStore,archivesStore } = props;
// const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
// const [isModalOpenArchives, setIsModalOpenArchives] =
// useState<boolean>(false);
// const [projectConfig, setProjectConfig] = useState<any>([]);
// const formRef = React.useRef<FormInstance>(null);
// const [tagId, setId] = useState<Number | null>(null);
// const [folderList, setfolderList] = useState<any>(null); // 仓库列表
// const onFinish = (values: any) => {
// let data = values;
// if (!tagId) {
// folderStore.add(data);
// } else {
// folderStore.putItem(tagId, data);
// }
// setIsModalOpen(false);
// };
// useEffect(() => {
// folderStore.getlist().then(()=>{
// setfolderList(folderStore.list);
// });
// }, [folderStore]);
// // 添加事件
// const addHandler = () => {
// setProjectConfig(folderConfig);
// setIsModalOpen(true);
// };
// // 取消
// const cancelHandler = () => {
// setId(null);
// setIsModalOpen(false);
// };
// const cancelHandlerArch = () => {
// setIsModalOpenArchives(false);
// };
// // 文件夹点击
// const folderHandle = () => {
// setIsModalOpenArchives(true);
// };
// const onFinishFailed = () => {};
// return (
// <div className="contentBox">
// <Space direction="vertical" size="middle" style={{ display: "flex" }}>
// <Space direction="horizontal" size={"middle"}>
// <Button type="default" onClick={addHandler}>
// 添加档案
// </Button>
// </Space>
// <BTable
// store={archivesStore}
// columns={[
// ...columns,
// {
// title: "操作",
// dataIndex: "id",
// ellipsis: {
// showTitle: false,
// },
// render: (any, record) => column_widget(any, record),
// },
// ]}
// dataSource={archivesStore.list}
// />
// <Modal
// title={"档案查看"}
// width={"80%"}
// open={isModalOpenArchives}
// onOk={() => cancelHandlerArch}
// onCancel={cancelHandlerArch}
// >
// </Modal>
// <Modal
// title={!tagId ? "添加文件夹" : "编辑文件夹"}
// width={600}
// open={isModalOpen}
// afterClose={() => formRef.current?.resetFields()}
// onOk={() => formRef.current?.submit()}
// onCancel={cancelHandler}
// >
// <SimpleForm
// formRef={formRef}
// createCallback={() => {}}
// formName="card_basic"
// colProps={12}
// span={6}
// subBtnName="提交"
// formDatas={projectConfig}
// onFinish={onFinish}
// initialValues={true}
// onFinishFailed={onFinishFailed}
// >
// <Form.Item
// key="ac_identity"
// label="所属档案类别"
// name="ac_identity"
// rules={[{ required: true, message: "请选择所属档案类别!" }]}
// >
// <Select placeholder="">
// {folderList?.map((v: any) => {
// return (
// <Option key={v.identity} value={v.identity}>
// {v.category_name}
// </Option>
// );
// })}
// </Select>
// </Form.Item>
// </SimpleForm>
// </Modal>
// </Space>
// </div>
// );
// };
// export default inject(...["archivesStore", "folderStore"])(
// observer(Archive)
// );
import { Button, Space, Modal, FormInstance, Select } from "antd"; import { Button, Space, Modal, FormInstance, Select } from "antd";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table"; import BTable from "@/components/b_table";

View File

@ -24,14 +24,14 @@ export const defaultConfig = [
{ {
type: FormType.input, type: FormType.input,
label: "档案名称", label: "档案名称",
name: "archives_name", name: "category_name",
value: "", value: "",
rules: [{ required: true, message: "请输入分类名称!" }], rules: [{ required: true, message: "请输入分类名称!" }],
}, },
{ {
type: FormType.input, type: FormType.input,
label: "档案描述", label: "档案描述",
name: "archives_desc", name: "category_desc",
value: "", value: "",
}, },
{ {

View File

@ -41,10 +41,9 @@
position: absolute; position: absolute;
left: 0px; left: 0px;
top: 80px; top: 80px;
bottom: 10px; width: 20%;
width: 15%; bottom: 0px;
bottom: 80px; z-index: 2;
z-index: 1;
opacity: 1; opacity: 1;
background: rgba(37, 52, 70, 0.4); background: rgba(37, 52, 70, 0.4);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
@ -53,21 +52,19 @@
position: absolute; position: absolute;
right: 0px; right: 0px;
top: 80px; top: 80px;
bottom: 80px; bottom: 0px;
width: 15%; width: 20%;
z-index: 1; z-index: 2;
opacity: 1; opacity: 1;
background: rgba(37, 52, 70, 0.4); background: rgba(37, 52, 70, 0.4);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
} }
.map_container_b{ .map_container_b{
position: absolute; position: absolute;
right: 0px;
bottom: 0px; bottom: 0px;
background: rgba(37, 52, 70, 0.4); background: rgba(37, 52, 70, 0.4);
height: 80px; height: 80px;
width: 100%; width: 100%;
left: 0;
z-index: 1; z-index: 1;
text-align: center; text-align: center;
.bottom_content{ .bottom_content{

View File

@ -1,21 +1,109 @@
import { useState } from "react"; import { useEffect, useState } from "react";
import { Modal } from "antd"; import { Modal } from "antd";
import "./left.less"; import "./left.less";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import MapUtl from "@/components/map/mapUtil"; import MapUtl from "@/components/map/mapUtil";
import * as echarts from "echarts";
import Orgin from "./orgin";
const HomeLeft = () => { const HomeLeft = () => {
const [isModalOpen, setIsModalOpen] = useState<boolean>(false); const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const navigate = useNavigate(); const navigate = useNavigate();
const initChart = () => {
var myChart = echarts.init(document.getElementById("xunlian"));
var option = {
xAxis: {
type: "category",
data: ["应急抢险", "消防灭火", "水上救援", "民兵训练", "维稳处突"],
axisLabel: {
show: true,
interval: 0,
rotate: 30,
},
},
grid: {
top: "10%",
bottom: "45%",
right: "5%",
},
yAxis: {
type: "value",
splitLine: {
show: false, // 去除网格线
},
},
series: [
{
data: [10, 15, 27, 10, 18],
type: "line",
smooth: true,
areaStyle: {
opacity: 0.1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgb(128, 255, 165)",
},
{
offset: 1,
color: "rgb(1, 191, 236)",
},
]),
},
},
],
};
option && myChart.setOption(option);
};
const initChart2 = () => {
var myChart = echarts.init(document.getElementById("orgin1"));
var option = {
xAxis: {
type: 'category',
data: ['基干民兵', '普通民兵', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisLabel: {
show: true,
interval: 0,
rotate: 30,
},
},
grid: {
top: "10%",
bottom: "45%",
right: "5%",
},
yAxis: {
type: 'value',
splitLine: {
show: false, // 去除网格线
},
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar'
}
]
};
option && myChart.setOption(option);
};
useEffect(() => {
initChart();
}, []);
useEffect(() => {
initChart2();
}, []);
const openDispatch = () => { const openDispatch = () => {
// 位置移动 // 位置移动
MapUtl.makerList[0].setPosition([103.55, 30.342]); // MapUtl.makerList[0].setPosition([103.55, 30.342]);
var m = MapUtl.amap; // var m = MapUtl.amap;
var newIcon = new m.Icon({ // var newIcon = new m.Icon({
image: "//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png", //Icon 的图像 // image: "//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png", //Icon 的图像
size: new m.Size(25, 34), // 图标大小 // size: new m.Size(25, 34), // 图标大小
anchor: new m.Pixel(12, 32), // 图标锚点 // anchor: new m.Pixel(12, 32), // 图标锚点
}); // });
MapUtl.makerList[0].setIcon(newIcon); // MapUtl.makerList[0].setIcon(newIcon);
}; };
const jumpToUser = () => { const jumpToUser = () => {
navigate("admin/user"); navigate("admin/user");
@ -27,16 +115,19 @@ const HomeLeft = () => {
<div className="org_head"> <div className="org_head">
<p></p> <p></p>
</div> </div>
<Orgin />
</div> </div>
<div onClick={jumpToUser} className="org"> <div onClick={jumpToUser} className="org">
<div className="org_head"> <div className="org_head">
<p></p> <p></p>
</div> </div>
<div style={{ width: "100%", height: "100%" }} id="orgin1"></div>
</div> </div>
<div onClick={openDispatch} className="org"> <div onClick={openDispatch} className="org">
<div className="org_head"> <div className="org_head">
<p></p> <p></p>
</div> </div>
<div style={{ width: "100%", height: "100%" }} id="xunlian"></div>
</div> </div>
<Modal <Modal
title="组织架构" title="组织架构"

View File

@ -1,10 +1,13 @@
.left_container{ .left_container{
width: 100%; width: 100%;
color: #fff; color: #fff;
height: auto; height: 100%;
display: flex;
flex-direction: column;
.org{ .org{
flex:1;
width: 100%; width: 100%;
min-height: 200px; overflow-y: hidden;
text-align: center; text-align: center;
.org_head{ .org_head{
width: 100%; width: 100%;
@ -16,5 +19,24 @@
text-align: left; text-align: left;
padding-left: 20px; padding-left: 20px;
} }
.orgin-content{
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
height: 80%;
.po{
position: relative;
width: 40%;
>span{
position: absolute;
left: 0;
right: 0;
}
>img{
width: 100%;
}
}
}
} }
} }

View File

@ -0,0 +1,18 @@
import origin from "@/static/orgin.png";
import origin2 from "@/static/orgin2.png";
const Orgin = () => {
return (
<div className="orgin-content">
<div className="po">
<span>234</span>
<img src={origin} alt="" />
</div>
<div className="po">
<span>238</span>
<img src={origin2} alt="" />
</div>
</div>
);
};
export default Orgin;

View File

@ -1,7 +1,23 @@
import { Tabs, TabsProps } from "antd";
import Leave from "./level";
import LeaveCat from "./levelCat";
const LeaveApproval = () => { const LeaveApproval = () => {
const items: TabsProps["items"] = [
{
key: "1",
label: "请假分类管理",
children: <LeaveCat />,
},
{
key: "2",
label: "请假管理",
children: <Leave />,
},
];
return ( return (
<> <>
<p>leaveApproval</p> <Tabs defaultActiveKey="1" items={items} />
</> </>
); );
}; };

View File

@ -0,0 +1,64 @@
import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table";
export const columns: ColumnsType<UserDataType> = [
{
title: "分类名称",
dataIndex: "name",
},
];
export const leaveColumns: ColumnsType<UserDataType> = [
{
title: "请假人",
dataIndex: "user_name",
},
{
title: "请假开始时间",
dataIndex: "leave_start_time",
},
{
title: "请假结束时间",
dataIndex: "leave_end_time",
},
{
title: "请假备注",
dataIndex: "leave_remark",
},
{
title: "驳回原因",
dataIndex: "reject",
},
{
title: "审批人",
dataIndex: "audit_name",
},
{
title: "假期类别",
dataIndex: "name",
},
{
title: "审核状态",
dataIndex: "status",
render(value, record, index) {
return record.status === 1
? "已通过"
: record.status === 2
? "已驳回"
: "待审批";
},
},
];
export const defaultConfig = [
{
type: FormType.input,
label: "驳回原因",
name: "reject",
value: "",
rules: [{ required: true, message: "请输入驳回原因!" }],
},
];

View File

@ -0,0 +1,106 @@
import BTable from "@/components/b_table";
import { inject, observer } from "mobx-react";
import { Store } from "antd/lib/form/interface";
import { Button, FormInstance, Modal, Space } from "antd";
import { defaultConfig, leaveColumns } from "./levcat_column";
import { useEffect, useState } from "react";
import SimpleForm from "@/components/form/simple_form";
import React from "react";
const Leave = (props: Store) => {
const { leaveStore } = props;
const formRef = React.useRef<FormInstance>(null);
const [record, setRecord] = useState<any>(null);
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const [projectConfig, setProjectConfig] = useState<any>([]);
useEffect(() => {
leaveStore.getlist();
setProjectConfig(defaultConfig);
}, [leaveStore]);
const onFinish = (values: any) => {
let data = {
...values,
status: 2,
};
leaveStore.access(record.id, data);
setIsModalOpen(false);
};
const onFinishFailed = () => {};
const edit = (record) => {
setIsModalOpen(true);
setRecord(record);
};
const access = (record) => {
leaveStore.access(record.id, { status: 1 });
};
const column_widget = (any, record) => {
if (record.status===0){
return (
<Space wrap>
<Button
type="dashed"
size="small"
onClick={() => {
edit(record);
}}
>
</Button>
<Button
type="dashed"
size="small"
onClick={() => {
access(record);
}}
>
</Button>
</Space>
);
}
return <div></div>;
};
return (
<>
<BTable
store={leaveStore}
columns={[
...leaveColumns,
{
title: "操作",
dataIndex: "id",
ellipsis: {
showTitle: false
},
render: (any, record) => column_widget(any, record)
},
]}
dataSource={leaveStore.list}
/>
<Modal
title={"审批"}
width={500}
open={isModalOpen}
afterClose={() => formRef.current?.resetFields()}
onOk={() => formRef.current?.submit()}
onCancel={() => {
setIsModalOpen(false);
}}
>
<SimpleForm
formRef={formRef}
formName="card_basic"
colProps={25}
subBtnName="提交"
formDatas={projectConfig}
onFinish={onFinish}
initialValues={true}
onFinishFailed={onFinishFailed}
/>
</Modal>
</>
);
};
// export default Leave;
export default inject("leaveStore")(observer(Leave));

View File

@ -0,0 +1,127 @@
import { Button, Space, Modal, FormInstance } from "antd";
import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect, useState } from "react";
import { Store } from "antd/lib/form/interface";
import SimpleForm from "@/components/form/simple_form";
import React from "react";
import { columns, defaultConfig } from "./levcat_column";
const LeaveCat = (props: Store) => {
const { leaveCategoryStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const [projectConfig, setProjectConfig] = useState<any>([]);
const formRef = React.useRef<FormInstance>(null);
const [record, setRecord] = useState<any>(null);
useEffect(() => {
leaveCategoryStore.getlist();
setProjectConfig(defaultConfig);
}, [leaveCategoryStore]);
const column_widget = (any, record) => {
return (
<Space wrap>
<Button
type="dashed"
size="small"
onClick={() => {
edit(record);
}}
>
</Button>
<Button
type="dashed"
danger
size="small"
onClick={() => {
leaveCategoryStore.deleteItem(record.id);
}}
>
</Button>
</Space>
);
};
const edit = (record) => {
setIsModalOpen(true);
setRecord(record);
};
const onFinish = (values: any) => {
let data = {
...values,
pid:values.pid??0
};
if (!record?.id) {
leaveCategoryStore.add(data);
} else {
leaveCategoryStore.putItem(record.id, data);
}
setIsModalOpen(false);
};
const onFinishFailed = () => {};
return (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Space direction="horizontal" size={"middle"}>
<Button
type="default"
onClick={() => {
setRecord(null);
setProjectConfig(defaultConfig);
setIsModalOpen(true);
}}
>
</Button>
</Space>
<BTable
store={leaveCategoryStore}
columns={[
...columns,
{
title: "操作",
dataIndex: "id",
ellipsis: {
showTitle: false,
},
render: (any, record) => column_widget(any, record),
},
]}
dataSource={leaveCategoryStore.list}
/>
<Modal
title={!record?.id ? "添加分类" : "编辑分类"}
width={500}
open={isModalOpen}
afterClose={() => formRef.current?.resetFields()}
onOk={() => formRef.current?.submit()}
onCancel={() => {
setIsModalOpen(false);
}}
>
<SimpleForm
formRef={formRef}
createCallback={() => {
if (record?.id) {
formRef.current?.setFieldsValue(record);
} else {
formRef.current?.setFieldsValue(null);
}
}}
formName="card_basic"
colProps={25}
subBtnName="提交"
formDatas={projectConfig}
onFinish={onFinish}
initialValues={true}
onFinishFailed={onFinishFailed}
/>
</Modal>
</Space>
</div>
);
};
export default inject("leaveCategoryStore")(observer(LeaveCat));

BIN
src/static/orgin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
src/static/orgin2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -13,6 +13,8 @@ import { materialCatStore } from './materialCat';
import { materialStore } from './materialStore'; import { materialStore } from './materialStore';
import { regulationsCatStore } from './regulationsCat'; import { regulationsCatStore } from './regulationsCat';
import { regulationsStore } from './regulations'; import { regulationsStore } from './regulations';
import { leaveCategoryStore } from './leave_cat';
import { leaveStore } from './leave';
const store = { const store = {
usrStore, usrStore,
@ -29,7 +31,9 @@ const store = {
materialCatStore, materialCatStore,
materialStore, materialStore,
regulationsCatStore, regulationsCatStore,
regulationsStore regulationsStore,
leaveCategoryStore,
leaveStore
}; };
export default store; export default store;

28
src/store/leave.ts Normal file
View File

@ -0,0 +1,28 @@
import { action, makeObservable } from "mobx";
// 档案分类
import BaseStore from "./baseStore";
import { TagDataType } from "@/model/userModel";
import baseHttp from "@/service/base";
class LeaveConfig {
static LIST: string = "leave/list"
static ADD: string = "leave"
static DELETE: string = "leave"
static EDIT: string = "leave"
static ACCESS: string = "leave/access"
}
class LeaveStore extends BaseStore<TagDataType> {
constructor() {
super(LeaveConfig)
makeObservable(this, {
access: action
})
}
async access(id: number, param: any) {
await baseHttp.put(LeaveConfig.ACCESS + "/" + id, param)
this.getlist()
}
}
export const leaveStore = new LeaveStore()

20
src/store/leave_cat.ts Normal file
View File

@ -0,0 +1,20 @@
import { makeObservable } from "mobx";
// 档案分类
import BaseStore from "./baseStore";
import { TagDataType } from "@/model/userModel";
class LeaveCategoryConfig {
static LIST: string = "leave/category/list"
static ADD: string = "leave/category"
static DELETE: string = "leave/category"
static EDIT: string = "leave/category"
}
class LeaveCategoryStore extends BaseStore<TagDataType> {
constructor() {
super(LeaveCategoryConfig)
makeObservable(this, {})
}
}
export const leaveCategoryStore = new LeaveCategoryStore()

38
src/util/socket.ts Normal file
View File

@ -0,0 +1,38 @@
class Socket {
static socketUrl = "ws://localhost:12214/ws";
static ws: WebSocket;
init() {
try {
Socket.ws = new WebSocket(Socket.socketUrl);
this.heartbeat();
} catch (error) {
console.log(error);
}
}
send(data: any) {
Socket.ws.send(data);
}
onmessage(callback: any) {
Socket.ws.onmessage = callback;
}
onclose(callback: any) {
Socket.ws.onclose = callback;
}
onopen(callback: any) {
Socket.ws.onopen = callback;
}
onerror(callback: any) {
Socket.ws.onerror = callback;
}
close() {
Socket.ws.close();
}
// 心跳
heartbeat() {
setInterval(() => {
Socket.ws.send(`{"type":"heartbeat"}`);
}, 1000*60);
}
}
export const socket = new Socket();