add animation

This commit is contained in:
wang_yp 2025-03-13 22:48:04 +08:00
parent 66dba51bf9
commit 41d4a359af
30 changed files with 18743 additions and 248 deletions

34
git.sh
View File

@ -14,19 +14,21 @@ git push
# rm -rf card/
# task
# pc
# 1、首页统计
# 1、组织架构组织架构图
# 2、武装力量 报表
# 3、年度训练 查看档案
# 4、物资管理 处突
# 5、档案管理 报表
# 6、评优
# 7
# 2、物资借用以及归还
# 3、任务关联档案
# app
# 1、退伍军人 列表 详情 申请领取光荣牌
# 2、接收任务
# 3、任务列表
# ps
# 编辑用户 是否党员 没回显
# app 政治面貌没有展示
# 优待证 性别 没展示
# 服务年限 展示实际年限
# 签到 个人中心 展示今日签到信息
# 通讯录,实时搜索
# pc
# 力量汇总,加一个新兴领域 网格员
# 任务管理
# 添加 通知

39
package-lock.json generated
View File

@ -48,7 +48,6 @@
"eslint-webpack-plugin": "^3.1.1",
"expose-loader": "^5.0.0",
"file-loader": "^6.2.0",
"flv.js": "^1.6.2",
"fs-extra": "^10.0.0",
"html-webpack-plugin": "^5.5.0",
"identity-obj-proxy": "^3.0.0",
@ -9935,11 +9934,6 @@
"es6-symbol": "^3.1.1"
}
},
"node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"node_modules/es6-symbol": {
"version": "3.1.4",
"resolved": "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.4.tgz",
@ -11313,15 +11307,6 @@
"readable-stream": "^2.3.6"
}
},
"node_modules/flv.js": {
"version": "1.6.2",
"resolved": "https://registry.npmmirror.com/flv.js/-/flv.js-1.6.2.tgz",
"integrity": "sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==",
"dependencies": {
"es6-promise": "^4.2.8",
"webworkify-webpack": "^2.1.5"
}
},
"node_modules/follow-redirects": {
"version": "1.15.9",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
@ -33188,11 +33173,6 @@
"node": ">=0.8.0"
}
},
"node_modules/webworkify-webpack": {
"version": "2.1.5",
"resolved": "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz",
"integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw=="
},
"node_modules/whatwg-encoding": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
@ -41161,11 +41141,6 @@
"es6-symbol": "^3.1.1"
}
},
"es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"es6-symbol": {
"version": "3.1.4",
"resolved": "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.4.tgz",
@ -42194,15 +42169,6 @@
"readable-stream": "^2.3.6"
}
},
"flv.js": {
"version": "1.6.2",
"resolved": "https://registry.npmmirror.com/flv.js/-/flv.js-1.6.2.tgz",
"integrity": "sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==",
"requires": {
"es6-promise": "^4.2.8",
"webworkify-webpack": "^2.1.5"
}
},
"follow-redirects": {
"version": "1.15.9",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
@ -58569,11 +58535,6 @@
"resolved": "https://registry.npmmirror.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
},
"webworkify-webpack": {
"version": "2.1.5",
"resolved": "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz",
"integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw=="
},
"whatwg-encoding": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",

View File

@ -43,7 +43,6 @@
"eslint-webpack-plugin": "^3.1.1",
"expose-loader": "^5.0.0",
"file-loader": "^6.2.0",
"flv.js": "^1.6.2",
"fs-extra": "^10.0.0",
"html-webpack-plugin": "^5.5.0",
"identity-obj-proxy": "^3.0.0",

View File

@ -69,7 +69,6 @@ function MyEditor(props: EditorProps) {
value={html}
onCreated={setEditor}
onChange={(editor) => {
console.log("onChange", editor.getHtml());
setHtml(editor.getHtml());
props.onChange(editor.getHtml());
}}

View File

@ -114,7 +114,7 @@ const SimpleForm = (props: SimpleFormData) => {
<Form.Item
key={v.label}
label={v.label}
valuePropName="fileList"
valuePropName="file_list"
name={v.name}
rules={v.rules}
initialValue={v.value}

View File

@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import AMapLoader from "@amap/amap-jsapi-loader";
import { mapArrs } from "@/store/map";
import MapUtlTow from "./mapUtilTow";
export default function MapContainerTow() {
let [amap, setmaps] = useState<any>(null);
@ -37,9 +38,13 @@ export default function MapContainerTow() {
});
amap.add(polygon);
amap.setFitView();
MapUtlTow.loadMap = Amap;
MapUtlTow.amap = amap;
setmaps(amap);
};
return (
<div id="containerTow" style={{ height: "100vh", width: "100%" }}></div>
);

View File

@ -0,0 +1,137 @@
import makers from "../../static/map-maker.png";
import makers1 from "../../static/map-maker1.png";
interface makersInf {
userIdentity: string,
marker: any,
}
class MapUtlTow {
static makerList: makersInf[] = [];
static amap: any = null;
static loadMap: any = null;
static wecherInfo: any = null;
static addMaker(data: any) {
const { lng, lat, title, users,clicks } = data;
let mk, dep = "";
if (users?.militia_type === 1) {
mk = makers
dep = "民兵"
}
if (users?.grid_user === 1) {
mk = makers1
dep = "网格员"
}
if (users?.patrol_user === 1) {
dep = "巡防大队"
}
// if (MapUtl.loadMap === null) return;
const marker = new MapUtlTow.loadMap.Marker({
position: new MapUtlTow.loadMap.LngLat(lng, lat),
title: title,
icon: new MapUtlTow.loadMap.Icon({
imageSize: [20, 20],
image: mk,
style: {
backgroundImage: "red"
}// 默认的样式名
}),
});
var content = [
"<div><b>姓名 :" + users?.user_name + "</b>",
"职位 : " + users.pos_held,
"电话 : " + users.tel,
"部门 : " + dep,
"</div>",
];
var infoWindow = new MapUtlTow.loadMap.InfoWindow({
offset: new MapUtlTow.loadMap.Pixel(0, -30),
autoMove: true,
content: content.join("<br/>"),
});
marker.on("click", (e) => {
infoWindow.open(MapUtlTow.amap, e.target.getPosition());
clicks(users.id)
});
MapUtlTow.amap?.add(marker);
// 将maker添加到数组
MapUtlTow.makerList.push({
userIdentity: users.identity,
marker: marker
})
}
static addMakerDis(data: any) {
const { lng, lat, title } = data;
const marker = new MapUtlTow.loadMap.Marker({
position: new MapUtlTow.loadMap.LngLat(lng, lat),
icon: new MapUtlTow.loadMap.Icon({
image:
"https://img20.360buyimg.com/n1/jfs/t1/98676/8/28819/96905/62e1e96eE69561497/0e201e39d6d1c1e3.png",
imageSize: [30, 30],
}),
title: title,
});
var content = [
"<div><b>站点名称 :" + title + "</b>",
// "职位 : " + users.pos_held,
// "电话 : " + users.tel,
"</div>",
];
var infoWindow = new MapUtlTow.loadMap.InfoWindow({
offset: new MapUtlTow.loadMap.Pixel(0, -30),
autoMove: true,
content: content.join("<br/>"),
});
marker.on("click", (e) => {
infoWindow.open(MapUtlTow.amap, e.target.getPosition());
});
MapUtlTow.amap?.add(marker);
}
static setMakericon = (maker) => {
maker.setPosition([103.55, 30.342]);
var m = MapUtlTow.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), // 图标锚点
});
maker.setIcon(newIcon);
}
static polyline = (lineArr) => {
let markerp = new MapUtlTow.loadMap.Marker({
map: MapUtlTow.amap,
position: [116.478935, 39.997761],
icon: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png",
offset: new MapUtlTow.loadMap.Pixel(-13, -26),
});
new MapUtlTow.loadMap.Polyline({
map: MapUtlTow.amap,
path: lineArr,
showDir: true,
strokeColor: "#28F", //线颜色
strokeWeight: 6, //线宽
});
let passedPolyline = new MapUtlTow.loadMap.Polyline({
map: MapUtlTow.amap,
strokeColor: "#AF5", //线颜色
strokeWeight: 6, //线宽
});
markerp.on('moving', function (e) {
passedPolyline.setPath(e.passedPath);
MapUtlTow.amap.setCenter(e.target.getPosition(), true)
});
MapUtlTow.amap.setFitView();
markerp.moveAlong(lineArr, {
duration: 500,//可根据实际采集时间间隔设置
autoRotation: true,
});
}
static getWecher() {
}
}
export default MapUtlTow;

View File

@ -90,7 +90,6 @@
bottom: 0px;
z-index: 2;
opacity: 1;
background: rgba(37, 52, 70, 0.4);
backdrop-filter: blur(10px);
}
.map_container_r {
@ -101,13 +100,13 @@
width: 20%;
z-index: 2;
opacity: 1;
background: rgba(37, 52, 70, 0.4);
backdrop-filter: blur(10px);
height: 100%;
}
.map_container_b_check {
position: absolute;
bottom: 40px;
bottom: 60px;
height: 60px;
width: 100%;
z-index: 1;
@ -115,11 +114,10 @@
}
.map_container_b {
position: absolute;
bottom: 0px;
backdrop-filter: blur(10px);
bottom: 12px;
height: 60px;
width: 100%;
z-index: 1;
z-index: 2;
text-align: center;
.bottom_content {
display: inline-block;
@ -140,3 +138,7 @@
top: 70px;
right: calc(20%);
}
:where(.css-dev-only-do-not-override-nqoqt9).ant-radio-button-wrapper:not(:first-child)::before {
background-color: #0f5693 !important;
}

View File

@ -39,7 +39,7 @@ const Home = observer(() => {
<HomeRight />
</div>
<div className="map_container_b_check">
{/* <HomeCheck /> */}
<HomeCheck />
</div>
<div className="map_container_b">
<HomeBottom />

View File

@ -2,7 +2,7 @@ import { Modal } from "antd";
import { inject, observer } from "mobx-react";
import { useState } from "react";
import Config from "@/util/config";
import VideoPlayer from "@/pages/home/video";
import EasyPlayer from "../videoTow";
const WhichVideo = (props) => {
const { homeStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
@ -11,21 +11,39 @@ const WhichVideo = (props) => {
const [deviceId, setDeviceId] = useState<number>(0);
const [channelId, setChannelId] = useState<number>(0);
const [videoUrl, setVideoUrl] = useState<string | null>("");
let timer: any = null;
const openDispatch = async () => {
setIsModalOpen(true);
let req = await homeStore.getVideoUrlList();
setDeviceList(req.EasyDarwin.Body.Devices);
};
};
const getChannerList = async (id) => {
let reqs = await homeStore.getChannerUrlList(id);
setChannelList(reqs.EasyDarwin.Body.Channels);
};
const getUrl = async (id) => {
let reqs = await homeStore.getChannerStrem(deviceId, id);
if (!reqs.EasyDarwin) return;
let url = Config.videoApis + reqs.EasyDarwin.Body.URL
setVideoUrl(url);
if (timer) {
clearInterval(timer);
}
const fetchUrl = async () => {
try {
const reqs = await homeStore.getChannerStrem(deviceId, id);
if (!reqs.EasyDarwin) return;
const url = Config.videoApis + reqs.EasyDarwin.Body.URL;
setVideoUrl(url);
} catch (error) {
console.error("Error fetching video URL:", error);
}
};
fetchUrl()
timer = setInterval( () => {
fetchUrl();
},15000);
};
return (
<>
@ -51,7 +69,7 @@ const WhichVideo = (props) => {
>
<div>
<div style={{ display: "flex" }}>
<div style={{overflowY: "scroll",height: "550px"}}>
<div style={{ overflowY: "scroll", height: "550px" }}>
{deviceList.map((item, index) => {
return (
<div
@ -74,7 +92,7 @@ const WhichVideo = (props) => {
})}
</div>
<div style={{ width: "20px" }}></div>
<div style={{height:"550px",overflow:"scroll"}}>
<div style={{ height: "550px", overflow: "scroll" }}>
{channelList.map((item, index) => {
return (
<div
@ -98,9 +116,7 @@ const WhichVideo = (props) => {
</div>
<div style={{ width: "20px" }}></div>
<div className="video" style={{ width: "100%", height: "550px" }}>
{
<VideoPlayer url={videoUrl} />
}
{<EasyPlayer url={videoUrl} />}
</div>
</div>
</div>

View File

@ -23,18 +23,21 @@ const HomeLeft = () => {
</div>
<Orgin />
</div>
<div style={{height:"10px"}}></div>
<div className="org">
<div className="org_head">
<p></p>
</div>
<Pover />
</div>
<div style={{height:"10px"}}></div>
<div className="org">
<div className="org_head">
<p></p>
</div>
<Turn />
</div>
<div style={{height:"20px"}}></div>
</div>
);
};

View File

@ -8,16 +8,18 @@
.org{
flex:1;
width: 100%;
background: rgba(37, 52, 70, 0.4);
overflow-y: hidden;
text-align: center;
.org_head{
background-image: url("../../../static/sub_title.png");
background-size: 100% 100%;
background-repeat: no-repeat;
line-height: 36px;
height: 36px;
line-height: 32px;
height: 32px;
text-align: left;
padding-left: 30px;
font-size: 15px;
}
.orgin-content{
display: flex;

View File

@ -11,7 +11,7 @@ export const trunEchatConfig = (data) => {
rotate: 30,
},
},
grid: { top: "10%", bottom: "35%", right: "5%" },
grid: { top: "10%", bottom: "40%", right: "5%" },
yAxis: {
type: "value",
splitLine: {

View File

@ -72,11 +72,11 @@ const Turn = (props: Store) => {
let fileType = getFileTypeFromUrl(imageUrl);
switch (fileType) {
case "jpeg":
return <img style={{ width: "100%" }} src={imageUrl} alt="" />;
return <img style={{ width: "100%",objectFit:"fill" }} src={imageUrl} alt="" />;
case "jpg":
return <img style={{ width: "100%" }} src={imageUrl} alt="" />;
return <img style={{ width: "100%" ,objectFit:"fill"}} src={imageUrl} alt="" />;
case "png":
return <img style={{ width: "100%" }} src={imageUrl} alt="" />;
return <img style={{ width: "100%",objectFit:"fill" }} src={imageUrl} alt="" />;
case "pdf":
return (
<div style={{ width: "100%", height: "500px" }}>
@ -106,7 +106,7 @@ const Turn = (props: Store) => {
src={imageUrl}
fileName="docx"
onError={(e) => {
console.log("error doc",e);
console.log("error doc", e);
}}
/>
</div>
@ -137,34 +137,50 @@ const Turn = (props: Store) => {
setisModalOpen(false);
}}
>
<div >
<div>
<Row>
<Col span={2}>
<div style={{ color: "#fff" }}>
<p></p>
<div style={{ height: "600px",overflowY:"hidden" }}>
{trainingStore.list?.map((item) => {
return (
<p
key={item.identity}
style={{
color: item.identity === taskId ? "blue" : "#fff",
cursor: "pointer",
}}
onClick={() => {
setTaskId(item.identity);
getFolderhandler(item.identity);
}}
>
{item.title}
</p>
);
})}
</div>
<div
style={{
height: "500px",
overflowY: "hidden",
border: "1px solid #fff",
padding: "10px",
margin: "5px",
}}
>
<p></p>
{trainingStore.list?.map((item) => {
return (
<p
key={item.identity}
style={{
margin: "5px",
color: item.identity === taskId ? "blue" : "#fff",
cursor: "pointer",
}}
onClick={() => {
setTaskId(item.identity);
getFolderhandler(item.identity);
}}
>
{item.title}
</p>
);
})}
</div>
</div>
</Col>
<Col span={2}>
<div style={{ color: "#fff" }}>
<div
style={{
color: "#fff",
border: "1px solid #fff",
padding: "10px",
margin: "5px",
}}
>
<p></p>
{folderList?.map((item) => {
return (
@ -185,70 +201,73 @@ const Turn = (props: Store) => {
})}
</div>
</Col>
<Col span={2} style={{height:"600px",overflowY:"hidden"}}>
<div style={{ color: "#fff" }}>
<Col span={2}>
<div style={{ color: "#fff", border: "1px solid #fff",
padding: "10px",
margin: "5px", }}>
<div style={{ height: "500px", overflowY: "scroll" }}>
<p></p>
<div style={{height:"600px",overflowY:"scroll"}}>
{imageList?.map((item) => {
let fileType = getFileTypeFromUrl(item.file_url);
switch (fileType) {
case "png":
return imageWidget(item);
case "jpeg":
return imageWidget(item);
case "jpg":
return imageWidget(item);
case "pdf":
return (
<p
key={item.identity}
style={{ cursor: "pointer" }}
onClick={() => {
setImageUrl(item.file_url);
}}
>
{item.file_name}
</p>
);
case "mp4":
return (
<p
key={item.identity}
style={{ cursor: "pointer" }}
onClick={() => {
setImageUrl(item.file_url);
}}
>
{item.file_name}
</p>
);
case "docx":
return (
<p
key={item.identity}
style={{ cursor: "pointer" }}
onClick={() => {
setImageUrl(item.file_url);
}}
>
{item.file_name}
</p>
);
default:
return (
<img
onClick={() => {
setImageUrl(item.file_url);
}}
key={item.identity}
style={{ width: "80px" }}
src={item.file_url}
alt=""
/>
);
}
})}
</div>
{imageList?.map((item) => {
let fileType = getFileTypeFromUrl(item.file_url);
switch (fileType) {
case "png":
return imageWidget(item);
case "jpeg":
return imageWidget(item);
case "jpg":
return imageWidget(item);
case "pdf":
return (
<p
key={item.identity}
style={{ cursor: "pointer" }}
onClick={() => {
setImageUrl(item.file_url);
}}
>
{item.file_name}
</p>
);
case "mp4":
return (
<p
key={item.identity}
style={{ cursor: "pointer" }}
onClick={() => {
setImageUrl(item.file_url);
}}
>
{item.file_name}
</p>
);
case "docx":
return (
<p
key={item.identity}
style={{ cursor: "pointer" }}
onClick={() => {
setImageUrl(item.file_url);
}}
>
{item.file_name}
</p>
);
default:
return (
<img
onClick={() => {
setImageUrl(item.file_url);
}}
key={item.identity}
style={{ width: "80px" }}
src={item.file_url}
alt=""
/>
);
}
})}
</div>
</div>
</Col>
<Col span={18}>
@ -259,6 +278,7 @@ const Turn = (props: Store) => {
display: "flex",
alignItems: "center",
justifyContent: "center",
padding:"10px"
}}
>
{preView()}

View File

@ -1,9 +1,18 @@
import FileViewer from "@codesmith-99/react-file-preview";
import { Modal, Space } from "antd";
import { Store } from "antd/es/form/interface";
import * as echarts from "echarts";
import { inject, observer } from "mobx-react";
import { useEffect } from "react";
import { useEffect, useState } from "react";
const Ac = (props: Store) => {
const { homeStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const [year, setYear] = useState<Array<any>>([]);
const [folder, setFolder] = useState<Array<any>>([]);
const [files, setFiles] = useState<Array<any>>([]);
const [imageUrl, setImageUrl] = useState<any>([]);
const [folderId, setFolderId] = useState<any>([]);
const [fileId, setFileId] = useState<any>([]);
const initChart = (data) => {
var myChart = echarts.init(document.getElementById("ac"));
@ -62,8 +71,177 @@ const Ac = (props: Store) => {
homeStore.getRm().then((res) => {
initChart(res.data?.record);
});
}, [homeStore]);
return <div style={{ width: "100%", height: "100%" }} id="ac"></div>;
const getFileTypeFromUrl = (url) => {
if (url === "" || url.length === 0) return;
// 解析URL以提取文件名
const filename = url.split("/").pop();
// 获取文件扩展名
const fileExtension = filename.split(".").pop();
// 返回文件扩展名
return fileExtension;
};
const preView = () => {
let fileType = getFileTypeFromUrl(imageUrl);
switch (fileType) {
case "jpeg":
return <img style={{ width: "100%",height:"100%" }} src={imageUrl} alt="" />;
case "jpg":
return <img style={{ width: "100%" ,height:"100%"}} src={imageUrl} alt="" />;
case "png":
return <img style={{ width: "100%",height:"100%" }} src={imageUrl} alt="" />;
case "pdf":
return (
<div style={{ width: "100%", height: "100%" }}>
<iframe
style={{ width: "100%", height: "100%" }}
src={imageUrl}
title="描述"
></iframe>
</div>
);
case "mp4":
return (
<div key={imageUrl} style={{ width: "100%", height: "100%" }}>
<video
controls
style={{ width: "100%", height: "100%" }}
src={imageUrl}
></video>
</div>
);
case "docx":
return (
<div key={imageUrl} style={{ width: "100%", height: "400px" }}>
<FileViewer
loader={undefined}
src={imageUrl}
fileName="docx"
onError={(e) => {
console.log("error doc", e);
}}
/>
</div>
);
case "":
return <div style={{ width: "100%", height: "400px" }}></div>;
default:
return <div style={{ width: "100%", height: "400px" }}></div>;
}
};
return (
<>
<div
style={{ width: "100%", height: "100%" }}
id="ac"
onClick={() => {
homeStore.getTimes().then((res) => {
setYear(res.data?.record);
});
homeStore.getFolders("2025").then((res) => {
setFolder(res.data?.record);
});
setIsModalOpen(true);
}}
></div>
<Modal
title="档案查看"
className="owner_model"
width={"80%"}
open={isModalOpen}
afterClose={() => {}}
onOk={() => {}}
footer={null}
onCancel={() => {
setIsModalOpen(false);
}}
>
<>
<Space style={{ color: "#fff" }}>
{year.map((item) => {
return (
<h2
style={{ cursor: "pointer" }}
onClick={() => {
homeStore.getFolders(item.unique_years).then((res) => {
setFolder(res.data?.record);
});
}}
>
{item.unique_years}
</h2>
);
})}
</Space>
<h2 style={{ color: "#fff" }}></h2>
<div style={{ height: "500px", overflow: "hidden" }}>
<div style={{ display: "flex", alignItems: "flex-start" }}>
<div
style={{
border: "1px solid #fff",
width: "200px",
overflow: "auto",
height: "480px",
flex:1
}}
>
{folder?.map((item) => {
return (
<p
style={{
color: folderId === item.identity ? "blue" : "#fff",
cursor: "pointer",
margin: "5px",
}}
onClick={() => {
homeStore.getFolderss(item.identity).then((res) => {
setFolderId(item.identity);
setFiles(res.data?.record);
});
}}
>
{item.folder_desc}
</p>
);
})}
</div>
<div
style={{
border: "1px solid #fff",
width: "200px",
height: "480px",
overflow: "auto",
flex:1
}}
>
{files?.map((item) => {
return (
<p
style={{
color: fileId === item.identity ? "blue" : "#fff",
cursor: "pointer",
margin: "5px",
}}
onClick={() => {
setFileId(item.identity)
setImageUrl(item.file_url);
}}
>
{item.file_name}
</p>
);
})}
</div>
<div style={{height:"400px",flex:4}}>
{preView()}
</div>
</div>
</div>
</>
</Modal>
</>
);
};
export default inject("homeStore")(observer(Ac));

View File

@ -1,10 +1,8 @@
import { useNavigate } from "react-router";
import Ac from "./ac";
import Pyzx from "./pyzx";
import "./right.less";
import Wz from "./wz";
const HomeRight = () => {
const nv = useNavigate();
return (
<div className="right_container">
<div className="org">
@ -13,18 +11,21 @@ const HomeRight = () => {
</div>
<Wz />
</div>
<div className="org" onClick={()=>nv('/admin/archives/box')}>
<div style={{ height: "10px" }}></div>
<div className="org">
<div className="org_head">
<p></p>
</div>
<Ac />
</div>
<div style={{ height: "10px" }}></div>
<div className="org">
<div className="org_head">
<p></p>
</div>
<Pyzx />
<Pyzx />
</div>
<div style={{ height: "20px" }}></div>
</div>
);
};

View File

@ -18,7 +18,7 @@ const Pyzx = (props: Store) => {
}, [homeStore]);
return (
<div className="pyzx">
<div className="pyzx" style={{height:"150px"}}>
{user?.map((item) => {
return (
<div

View File

@ -8,13 +8,15 @@
flex: 1;
width: 100%;
overflow-y: hidden;
background: rgba(37, 52, 70, 0.4);
text-align: center;
.org_head {
background-image: url("../../../static/sub_title.png");
background-size: 100% 100%;
background-repeat: no-repeat;
line-height: 36px;
height: 36px;
line-height: 32px;
height: 32px;
font-size: 15px;
text-align: left;
padding-left: 30px;
}
@ -23,7 +25,6 @@
.pyzx {
height: 100%;
min-height: 200px;
padding: 10px;
margin-bottom: 10px;
overflow-y: scroll;

View File

@ -4,6 +4,7 @@ import { inject, observer } from "mobx-react";
import { Store } from "antd/es/form/interface";
import MapUtl from "@/components/map/mapUtil";
import MapContainerTow from "@/components/map/MapComponentTow";
import MapUtlTow from "@/components/map/mapUtilTow";
const HomeCheck = (props: Store) => {
const { homeStore ,usrStore} = props;
@ -45,7 +46,7 @@ const HomeCheck = (props: Store) => {
return;
}
if (data.length > 0) {
MapUtl.polyline(data);
MapUtlTow.polyline(data);
}
}
});
@ -64,7 +65,7 @@ const HomeCheck = (props: Store) => {
query = { patrol_brigade: 1 };
break;
}
let marks = MapUtl.makerList;
let marks = MapUtlTow.makerList;
if (marks.length) {
marks.forEach((item) => {
item?.marker.remove();
@ -89,10 +90,10 @@ const HomeCheck = (props: Store) => {
};
return (
<>
<Radio.Group value={size} onChange={handleSizeChange}>
<Radio.Button value="1"></Radio.Button>
<Radio.Button value="2"></Radio.Button>
<Radio.Button value="3"></Radio.Button>
<Radio.Group value={size} onChange={handleSizeChange} >
<Radio.Button style={{backgroundColor:"rgba(15,86,147, 0.4)",border:"0px",color:"#fff"}} value="1"></Radio.Button>
<Radio.Button style={{backgroundColor:"rgba(15,86,187, 0.4)",border:"0px",color:"#fff"}} value="2"></Radio.Button>
<Radio.Button style={{backgroundColor:"rgba(15,86,147, 0.4)",border:"0px",color:"#fff"}} value="3"></Radio.Button>
</Radio.Group>
<Modal
title={"轨迹回放"}

View File

@ -1,9 +1,9 @@
import { Store } from "antd/es/form/interface";
import { inject, observer } from "mobx-react";
import { useEffect, useState } from "react";
import Video from "./video";
import "./video.less";
import { ZoomInOutlined } from "@ant-design/icons";
import VideoTow from "./videoTow";
const HomeVideo = (props: Store) => {
const { homeStore } = props;
const [videoUrls, setVideoUrl] = useState<Array<string> | null>([]);
@ -43,8 +43,8 @@ const HomeVideo = (props: Store) => {
<div className="homeVideoBox" style={obj}>
{videoUrls?.map((videoUrl, index) => {
return (
<div key={videoUrl} style={{ flex: "1", margin: "5px" }}>
<Video url={videoUrl} className="homeVideo" />;
<div key={videoUrl} style={{ flex: "1", margin: "5px",height:"200px"}}>
<VideoTow url={videoUrl} className="homeVideo" />;
</div>
);
})}

View File

@ -1,46 +0,0 @@
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useRef } from "react";
import flvjs from "flv.js";
import { Store } from "antd/es/form/interface";
const VideoPlayer = (props: Store) => {
const videoRef = useRef<HTMLVideoElement | null>(null);
let player: flvjs.Player | null = null;
useEffect(() => {
if (!props.url) return;
if (flvjs.isSupported()) {
const videoElement = videoRef.current;
if (videoElement) {
player = flvjs.createPlayer({
type: "mp4",
url: props.url,
});
player.attachMediaElement(videoElement);
player.load();
player.play();
}
}
return () => {
if (player) {
player.pause();
player.unload();
player.detachMediaElement();
player.destroy();
player = null;
}
};
}, [props.url]);
return (
<video
ref={videoRef}
style={{ width: "100%", height: "100%"}}
controls
autoPlay
/>
);
};
export default VideoPlayer;

View File

@ -0,0 +1,79 @@
import { Store } from "antd/es/form/interface";
import React, { useEffect } from "react";
// 声明 EasyPlayerPro 的类型
declare global {
interface Window {
EasyPlayerPro?: any; // 或者定义更精确的类型
}
}
// 创建 Player 组件
const EasyPlayer = (props: Store) => {
const myRef = React.useRef(null); // 用于引用 DOM 元素
const easyPro = React.useRef<any>(null); // 存储播放器实例
// 配置项
const config = {
isLive: true,
bufferTime: 0.2,
stretch: false,
MSE: true,
WCS: true,
hasAudio: false,
};
// 在组件挂载后创建播放器实例
useEffect(() => {
if (easyPro.current) {
easyPro.current?.destroy().then(() => {
if (props.url){
create();
}
});
} else {
if (props.url){
create();
}
}
return () => {
if (easyPro.current) {
easyPro.current.destroy()
}
};
}, [props.url],);
// 创建播放器实例
const create = () => {
easyPro.current = new window.EasyPlayerPro(myRef.current, {
isLive: config.isLive,
bufferTime: config.bufferTime,
stretch: config.stretch,
MSE: config.MSE,
WCS: config.WCS,
hasAudio: config.hasAudio,
watermark: { text: { content: "easyplayer-pro" }, right: 10, top: 10 },
});
play();
};
// 播放视频
const play = () => {
if (!easyPro.current) return create();
easyPro.current
?.play(props.url)
.then(() => {
console.log("player started");
})
.catch((e) => {
console.error("error", e);
});
};
return (
<div
style={{ width: "100%", height: "100%", backgroundColor: "#000000" }}
ref={myRef}
></div>
);
};
export default EasyPlayer;

View File

@ -240,7 +240,7 @@ const Patrol = (props: Store) => {
onFinish={onFinish}
initialValues={true}
onFinishFailed={onFinishFailed}
childrenPosi={true}
childrenPosi={false}
>
<>
<Form.Item

View File

@ -1,4 +1,4 @@
import { Button, Space, Modal, FormInstance } from "antd";
import { Button, Space, Modal, FormInstance, Form } from "antd";
import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect, useState } from "react";
@ -44,17 +44,28 @@ const PoliticalStudy = (props: Store) => {
);
};
const edit = (record) => {
let data = {
...record,
file_url: [record.file_url],
};
let config = defaultConfig;
config.forEach((e: any) => {
if (e.name === "file_url") {
e.value = [{ url: record.file_url }];
}
});
setProjectConfig(config);
setRecord(data);
setIsModalOpen(true);
setRecord(record);
};
const onFinish = (values: any) => {
let data = {
...values,
score: Number(values.score),
};
if (values.file_url.length>0) {
if (values.file_url.length > 0) {
data.file_url = values.file_url[0].url;
}else{
} else {
data.file_url = "";
}
if (!record?.id) {
@ -88,7 +99,7 @@ const PoliticalStudy = (props: Store) => {
{
title: "操作",
dataIndex: "id",
render: (any, record) => column_widget(any, record),
},
]}

View File

@ -172,7 +172,7 @@ export const defaultConfig =(team,per)=>
},
{
type: FormType.radio,
label: "是否党员",
label: "政治面貌",
name: "p_member",
value: 1,
radioData: [

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -21,7 +21,9 @@ class HomeConfig {
static channerList: string = "/api/v1/channelsconfig" //设备列表
static channelstream: string = "/api/v1/devices/channelstream" //设备包活
static scores: string = "/v1/user/scores"
static times: string = "/v1/archives/times"
static folderall: string = "/v1/archives/folder/all"
static folderalls: string = "/v1/archives/list"
}
class HomeStore extends BaseStore<TagDataType> {
scoreData = {}
@ -29,7 +31,7 @@ class HomeStore extends BaseStore<TagDataType> {
super(HomeConfig)
makeObservable(this, {
getOgCount: action,
scoreData:observable,
scoreData: observable,
ogMap: observable,
alist: observable,
showVideo: observable,
@ -42,7 +44,7 @@ class HomeStore extends BaseStore<TagDataType> {
async getScores(id) {
let data = await baseHttp.get(HomeConfig.scores + "/" + id, null)
this.scoreData = data.data.record
}
async getOgCount() {
let res = await baseHttp.get(HomeConfig.os, {});
@ -72,6 +74,22 @@ class HomeStore extends BaseStore<TagDataType> {
return await baseHttp.get(HomeConfig.todo, params);
}
// 获取档案时间
async getTimes() {
return await baseHttp.get(HomeConfig.times, {});
}
// 获取档案列表
async getFolders(year: string) {
return await baseHttp.get(HomeConfig.folderall, { "year": year });
}
async getFolderss(identity: string) {
return await baseHttp.get(HomeConfig.folderalls+"/"+identity, { });
}
// folderDetail
// 获取视频推流连接
async getVideoUrlList() {
try {
@ -103,7 +121,7 @@ class HomeStore extends BaseStore<TagDataType> {
let data = await baseHttp.gets(HomeConfig.channelstream, {
device: deviceId,
channel: channel,
protocol: "fmp4"
protocol: "flv"
})
return data;
} catch (error) {

View File

@ -1,8 +1,7 @@
class Config {
// static baseUrl = "https://www.hswzct.cn:12016/";
static baseUrl = "http://127.0.0.1:12214/";
static baseUrl = "https://www.hswzct.cn:12016/";
// static baseUrl = "http://127.0.0.1:12214/";
static ws = "wss://www.hswzct.cn:12016/wsadmin?id=admin";
// static ws = "wss://rw.quwanya.cn/wsadmin?id=admin";
static userStatic = "https://www.hswzct.cn:12016/api/uploads/user/";
static videoApi = "https://sprh.hswzct.cn:4443"; //
static videoApis = "https://sprh.hswzct.cn:4443"; //

18107
yarn.lock Normal file

File diff suppressed because it is too large Load Diff