feat: 完成内层layout构建

develop2
donghao 1 year ago
parent 0b8f2759bc
commit c86d2b7a9e

@ -495,7 +495,7 @@
"username": {
"type": "string"
},
"password": {
"psw": {
"type": "string"
},
"autoLogin": {

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-03-27 14:56:27
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-19 14:51:38
* @LastEditTime: 2024-04-22 16:50:40
* @FilePath: \general-ai-manage\config\routes.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -38,6 +38,7 @@ export const homeRoute = [
* @param subModelRoute
* @param level
* @param isHideMenu
* @param icon
*/
const modelRouteIndex = {
@ -88,6 +89,37 @@ export const outerMenuRoute = {
routes: [...homeRoute, ...modelRoute],
};
/**
* @
*/
export const innerMenuRoutes = [
{
name: 'business-info-index',
path: '/business/index',
component: './Project/BusinessInfo',
access: 'canReadMenu',
key: '1001',
// icon: 'TestIcon',
menuIcon: 'TestIcon',
},
{
name: 'business-node-setting',
path: '/business/nodeSetting',
component: './Business/NodeSetting',
access: 'canReadMenu',
key: '1002',
menuIcon: '',
},
{
name: 'business-model-index',
path: '/business/businessModel',
component: './Business/BusinessModel',
access: 'canReadMenu',
key: '1003',
menuIcon: '',
},
];
// 全路由模块
export default [
outerMenuRoute,
@ -102,50 +134,7 @@ export default [
},
],
},
{
path: '/testPage',
name: 'testPage',
access: 'canReadMenu',
routes: [
{
name: 'testPage-business-project',
path: '/testPage/business-project',
component: './Project/BusinessProject',
access: 'canReadMenu',
},
],
},
{
name: 'businessInfo',
path: '/businessInfo',
access: 'canReadMenu',
routes: [
{
name: 'business-info-index',
path: '/businessInfo/index',
component: './Project/BusinessInfo',
access: 'canReadMenu',
},
// {
// name: 'realTime-alarm-list',
// path: '/realTime/alarm-list',
// component: './RealTime/AlarmList',
// access: 'canReadMenu',
// },
// {
// name: 'realTime-alarm-rules',
// path: '/realTime/alarm-rules',
// component: './RealTime/AlarmRules',
// access: 'canReadMenu',
// },
// {
// name: 'realTime-device-list',
// path: '/realTime/device-list',
// component: './RealTime/DeviceList',
// access: 'canReadMenu',
// },
],
},
...innerMenuRoutes,
{
path: '/',
redirect: '/home/business-project',

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-01-24 16:05:16
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-19 10:19:59
* @LastEditTime: 2024-04-22 11:03:15
* @FilePath: \general-ai-platform-web\mock\pools\menuData.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -10,63 +10,15 @@
export const mockGetMenuData = {
data: {
routes: [
// {
// path: '/welcome',
// key: '0',
// name: 'welcome',
// icon: 'HomeOutlined',
// access: '',
// component: 'Welcome',
// label: '首页',
// title: '首页',
// },
{
path: '/realTime',
key: '1',
name: 'realTime',
icon: 'WarningOutlined',
component: '',
title: '实时分析',
component: 'RealTime/InvolvedList',
icon: '',
key: '101',
name: 'realTime-involved-list',
path: '/realTime/involved-list',
routes: [],
title: '告警汇总',
access: 'canReadMenu',
routes: [
{
component: 'RealTime/InvolvedList',
icon: '',
key: '101',
name: 'realTime-involved-list',
path: '/realTime/involved-list',
routes: [],
title: '告警汇总',
access: 'canReadMenu',
},
{
component: 'RealTime/AlarmList',
icon: '',
key: '102',
name: 'realTime-alarm-list',
path: '/realTime/alarm-list',
routes: [],
title: '告警列表',
},
{
component: 'RealTime/AlarmRules',
icon: '',
key: '103',
name: 'realTime-alarm-rules',
path: '/realTime/alarm-rules',
routes: [],
title: '告警规则',
},
{
component: 'RealTime/DeviceList',
icon: '',
key: '104',
name: 'realTime-device-list',
path: '/realTime/device-list',
routes: [],
title: '设备管理',
},
],
},
],
},

@ -31,9 +31,9 @@ const getAccess = () => {
export default {
// 登录
'POST /api/v1/login': async (req: Request, res: Response) => {
const { password, username, type } = req.body;
const { psw, username, type } = req.body;
await waitTime(1000);
if (password === 'Sju2984?' && username === 'admin') {
if (psw === 'Sju2984?' && username === 'admin') {
const adminData: successMockApiProps = {
...fetchMockSuccessFullByOther(mockBaseLoginData),
};
@ -42,7 +42,7 @@ export default {
return;
}
// TODO 以下未做任何处理
// if (password === 'ant.design' && username === 'user') {
// if (psw === 'ant.design' && username === 'user') {
// res.send({
// status: 'ok',
// type,

@ -0,0 +1,9 @@
<svg t="1713774734546" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="2346" width="200" height="200">
<path
d="M535.872 328.992v163.36l129.664 74.816a24 24 0 1 1-24 41.6l-129.632-74.848-129.44 74.816a24 24 0 1 1-24.032-41.568l129.44-74.816v-163.36a24 24 0 0 1 48 0z"
fill="#333333" p-id="2347"></path>
<path
d="M512.8 213.376c-3.2 0-6.336 0.832-9.088 2.432l-237.696 137.344a17.984 17.984 0 0 0-9.216 15.744v274.496a17.984 17.984 0 0 0 9.216 15.744l118.72 68.672 113.056 65.216 5.92 3.456a18.176 18.176 0 0 0 18.176 0l237.728-137.344a17.952 17.952 0 0 0 9.184-15.744v-274.496a17.952 17.952 0 0 0-9.184-15.744L667.616 299.84l-26.752-15.328-118.976-68.672a18.208 18.208 0 0 0-9.088-2.432z m130.88 128.032l77.12 44.736v240l-207.936 120.16-208.064-120.16v-240l208-120.16 104.064 60.064 26.816 15.36z"
fill="#333333" p-id="2348"></path>
</svg>

After

Width:  |  Height:  |  Size: 926 B

@ -1,8 +1,8 @@
.app_page_wrap {
height: calc(100vh);
padding: 16px 0 16px 14px;
padding: 0;
/* TODO 替换整体页面背景图 */
background-color: #ebeff3;
background: #F8FAFD;
}
.app_page_wrap .ant-pro-layout .ant-pro-layout-content {
position: relative;
@ -14,21 +14,25 @@
padding-inline: 0 !important;
}
.app_page_wrap .page_body {
width: calc(100vw - 160px);
width: calc(100vw - 200px);
}
.app_page_wrap .page_body .body_nav_bar {
position: absolute;
top: 28px;
right: 40px;
z-index: 999;
position: fixed;
top: 0;
right: 0;
width: calc(100vw - 200px);
min-width: 100px;
height: 50px;
padding: 0 24px 0 20px;
}
.app_page_wrap .page_body .body_nav_bar .avatar_box > img {
width: 40px;
height: 40px;
border-radius: 50%;
}
.app_page_wrap .page_body .body_content {
padding-top: 50px;
}
.ant-pro-layout .ant-pro-layout-content {
position: relative;
display: flex;

@ -1,9 +1,9 @@
// @primary-color: red; // 定义主题色
.app_page_wrap {
height: calc(100vh);
padding: 16px 0 16px 14px;
padding: 0;
/* TODO 替换整体页面背景图 */
background-color: rgb(235, 239, 243);
background: #f8fafd;
.ant-pro-layout .ant-pro-layout-content {
position: relative;
display: flex;
@ -14,15 +14,17 @@
padding-inline: 0 !important;
}
.page_body {
width: calc(100vw - 160px);
width: calc(100vw - 200px);
.body_nav_bar {
position: absolute;
top: 28px;
right: 40px;
z-index: 999;
// background-color: red;
position: fixed;
top: 0;
right: 0;
width: calc(100vw - 200px);
min-width: 100px;
height: 50px;
// z-index: 999;
padding: 0 24px 0 20px;
// background-color: red;
.avatar_box {
& > img {
width: 40px;
@ -31,6 +33,9 @@
}
}
}
.body_content {
padding-top: 50px;
}
}
}

@ -1,5 +1,4 @@
import { AvatarDropdown, AvatarName, MenuBar } from '@/components';
import { postMenuGetMenu } from '@/services/system/Menu';
import { getUserGetUserInfo } from '@/services/system/User';
import fixMenuItemIcon from '@/utils/FixMenuItemIcon';
import { getAllRouteNameTile, replaceMenuWithRoutesData } from '@/utils/common';
@ -7,9 +6,12 @@ import { addLocale } from '@@/plugin-locale';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import { SettingDrawer } from '@ant-design/pro-components';
import { MenuDataItem } from '@ant-design/pro-layout';
import { RunTimeLayoutConfig, getLocale, history } from '@umijs/max';
import { RunTimeLayoutConfig, getLocale, history, useIntl } from '@umijs/max';
import { innerMenuRoutes } from '../config/routes';
import zhCN from '@/locales/zh-CN';
// import 'https://at.alicdn.com/t/c/font_4412653_qjjikxo6f6p.css'; // 阿里字体图标
import { useState } from 'react';
import cookie from 'react-cookies';
import { RequestConfig } from 'umi';
import defaultSettings from '../config/defaultSettings';
@ -44,10 +46,10 @@ export async function getInitialState(): Promise<{
const { location } = history;
if (location.pathname !== loginPath && localStorage.getItem('access')) {
// const currentUser = await fetchUserInfo();
const menus = await postMenuGetMenu();
// console.log('app_menus', replaceMenuWithRoutesData(menus.data.routes));
const menusData = innerMenuRoutes;
// console.log('app_menus', replaceMenuWithRoutesData(menusData));
if (getLocale() === 'zh-CN') {
let localData = getAllRouteNameTile(menus.data.routes, '');
let localData = getAllRouteNameTile(menusData, '');
let localRes: any = {};
localData.forEach((v) => {
// console.log(v.title,'localData_v')
@ -65,9 +67,9 @@ export async function getInitialState(): Promise<{
currentUser: await fetchUserInfo(),
settings: {
...(defaultSettings as Partial<LayoutSettings>),
// menuData: replaceMenuWithRoutesData(menus.data.routes),
// menuData: replaceMenuWithRoutesData(menusData),
},
menuData: replaceMenuWithRoutesData(menus.data.routes),
menuData: replaceMenuWithRoutesData(menusData),
};
}
@ -79,6 +81,11 @@ export async function getInitialState(): Promise<{
// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const intl = useIntl();
// eslint-disable-next-line react-hooks/rules-of-hooks
const [currMenu, setCurrMenu] = useState({});
// useEffect(() => {
// console.log('initialState', initialState);
// }, []);
@ -138,10 +145,15 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
// if (initialState?.loading) return <PageLoading />;
return (
<div className="flex app_page_wrap">
<MenuBar menuData={initialState?.menuData}></MenuBar>
<MenuBar
menuData={initialState?.menuData}
changeMenu={(record) => setCurrMenu(record)}
></MenuBar>
<div className="page_body">
<div className="flex items-center justify-between body_nav_bar">
{/* <h5>首页1 {initialState?.currentUser?.userName}</h5> */}
<span>
{intl.formatMessage({ id: `menu-${currMenu?.name}`, defaultMessage: '首页' })}
</span>
<div>
{initialState?.currentUser?.userName ? (
<AvatarDropdown menu={true}>

@ -1,29 +1,47 @@
.menubar_wrap {
display: flex;
width: 160px;
padding: 24px 0;
background-color: #004fb2;
border-radius: 12px;
box-shadow: 4px 0px 24px 0px rgba(0, 63, 143, 0.3);
}
.menubar_wrap .ant-menu-dark,
.menubar_wrap .ant-menu-dark > .ant-menu,
.menubar_wrap .ant-menu-dark.ant-menu-inline .ant-menu-sub.ant-menu-inline,
.menubar_wrap .ant-menu-dark > .ant-menu.ant-menu-inline .ant-menu-sub.ant-menu-inline {
background-color: #004fb2;
}
.menubar_wrap .ant-menu-dark .ant-menu-item-selected,
.menubar_wrap .ant-menu-dark > .ant-menu .ant-menu-item-selected {
color: #004fb2;
background: rgba(255, 255, 255, 0.9);
border-radius: 4px;
width: 200px;
padding: 0;
background-color: #fff;
border-radius: 0px 0px 32px 0px;
}
.menubar_wrap .ant-menu,
.menubar_wrap .ant-menu > .ant-menu,
.menubar_wrap .ant-menu.ant-menu-inline .ant-menu-sub.ant-menu-inline,
.menubar_wrap .ant-menu > .ant-menu.ant-menu-inline .ant-menu-sub.ant-menu-inline {
font-size: 14px;
background-color: #fff;
}
.menubar_wrap .ant-menu .ant-menu-item-selected,
.menubar_wrap .ant-menu > .ant-menu .ant-menu-item-selected {
color: #fff;
background: #154ddd;
border-radius: 0px 8px 8px 0px;
}
.menubar_wrap .menu_top {
width: 120px;
width: 100%;
height: 72px;
color: #154ddd;
font-weight: bold;
border-radius: 0px 0px 64px 0px;
box-shadow: 0px 1px 0px 0px rgba(21, 77, 221, 0.15);
}
.menubar_wrap .ant-menu,
.menubar_wrap .ant-menu-item {
margin: 0;
padding: 0;
width: 100%;
}
.menubar_wrap .ant-menu-item-icon {
width: 20px;
height: 20px;
font-size: 14px;
}
.menubar_wrap .menu_center {
display: flex;
flex: 1;
width: 100%;
padding-top: 10px;
}
.menubar_wrap .menu_bottom {
width: 96px;

@ -1,30 +1,53 @@
@menubar_ThemeColor: #004fb2;
@menubar_ThemeColor: #fff;
@themeColor: #154ddd;
.menubar_wrap {
display: flex;
// flex: 1;
width: 160px;
padding: 24px 0;
width: 200px;
padding: 0;
background-color: @menubar_ThemeColor;
border-radius: 12px;
box-shadow: 4px 0px 24px 0px rgba(0, 63, 143, 0.3);
.ant-menu-dark,
.ant-menu-dark > .ant-menu,
.ant-menu-dark.ant-menu-inline .ant-menu-sub.ant-menu-inline,
.ant-menu-dark > .ant-menu.ant-menu-inline .ant-menu-sub.ant-menu-inline {
border-radius: 0px 0px 32px 0px;
// border-radius: 12px;
// box-shadow: 4px 0px 24px 0px rgba(0, 63, 143, 0.3);
.ant-menu,
.ant-menu > .ant-menu,
.ant-menu.ant-menu-inline .ant-menu-sub.ant-menu-inline,
.ant-menu > .ant-menu.ant-menu-inline .ant-menu-sub.ant-menu-inline {
font-size: 14px;
background-color: @menubar_ThemeColor;
}
.ant-menu-dark .ant-menu-item-selected,
.ant-menu-dark > .ant-menu .ant-menu-item-selected {
.ant-menu .ant-menu-item-selected,
.ant-menu > .ant-menu .ant-menu-item-selected {
color: @menubar_ThemeColor;
background: rgba(255, 255, 255, 0.9);
border-radius: 4px;
background: @themeColor;
border-radius: 0px 8px 8px 0px;
}
.menu_top {
width: 120px;
width: 100%;
height: 72px;
color: @themeColor;
font-weight: bold;
border-radius: 0px 0px 64px 0px;
box-shadow: 0px 1px 0px 0px rgba(21, 77, 221, 0.15);
}
.ant-menu,
.ant-menu-item {
width: 100%;
margin: 0;
padding: 0;
}
.ant-menu-item-icon {
width: 20px;
height: 20px;
font-size: 14px;
}
.menu_center {
display: flex;
flex: 1;
width: 100%;
padding-top: 10px;
}
.menu_bottom {
width: 96px;

@ -2,77 +2,130 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-03-27 16:03:20
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-07 17:46:07
* @LastEditTime: 2024-04-22 17:10:55
* @FilePath: \general-ai-manage\src\components\Header\index.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: layout
*/
import { history } from '@umijs/max';
import { useBusinessInfo } from '@/hooks/useBusinessInfo';
import { history, useIntl } from '@umijs/max';
import type { MenuProps } from 'antd';
import { Menu } from 'antd';
import React, { useEffect } from 'react';
import menuFooter from '/public/menuFooter.svg';
import menuLogo from '/public/menuLogo.svg';
import React, { useEffect, useState } from 'react';
import { ReactComponent as BusinessLogoIcon } from '/public/home/business_logo.svg';
// import menuFooter from '/public/menuFooter.svg';
import './index.less';
export type MenuBarProps = {
menuData: any[];
changeMenu: (arg1: MenuProps) => void;
};
const MenuBar: React.FC<MenuBarProps> = ({ menuData }) => {
// const tabRouter = (record) => {
// console.log('tabRouter_record', record);
// const currRouteItem =
// record.routes && Array.isArray(record.routes) && record.routes.length
// ? record.routes[0]
// : record;
// history.push(currRouteItem.path);
// };
const MenuBar: React.FC<MenuBarProps> = ({ menuData, changeMenu }) => {
const intl = useIntl();
const { getStoreBusinessInfo } = useBusinessInfo();
const [selectedMenu, setSelectedMenu] = useState([]);
const [stateOpenKeys, setStateOpenKeys] = useState(['1', '2']);
// 根据路径查找对应的菜单项
const findMenuByPath = (menuData: any, pathname: any) => {
for (const item of menuData) {
if (item.path === pathname) {
return item;
}
// 多级菜单使用递归调用
// if (item.children) {
// const matchedChild: any = findMenuByPath(item.children, pathname);
// if (matchedChild) {
// return matchedChild;
// }
// }
}
return null;
};
// const menuClick = ({ item, key, keyPath, domEvent }) => {
// console.log("menuClick", item, key, keyPath, domEvent);
// };
const menuClick: MenuProps['onClick'] = (e) => {
console.log('menuClick ', e.item.props.path);
const currRouteItem = e.item.props;
history.push(currRouteItem.path);
const menuClick: MenuProps['onClick'] = (menuItem) => {
console.log('menuClick_menuItem:', menuItem);
// Check if menuItem has route defined
if (menuItem && menuItem.path) {
history.push(menuItem.path);
}
};
const onOpenChange: MenuProps['onOpenChange'] = (openKeys) => {
console.log(openKeys, 'openKeys');
const currentOpenKey = openKeys.find((key) => stateOpenKeys.indexOf(key) === -1);
console.log(currentOpenKey, 'currentOpenKey');
// open
if (currentOpenKey !== undefined) {
const repeatIndex = openKeys
.filter((key) => key !== currentOpenKey)
.findIndex((key) => levelKeys[key] === levelKeys[currentOpenKey]);
setStateOpenKeys(
openKeys
// remove repeat key
.filter((_, index) => index !== repeatIndex)
// remove current level all child
.filter((key) => levelKeys[key] <= levelKeys[currentOpenKey]),
);
localStorage.setItem(
'openKeys',
JSON.stringify(
openKeys
// remove repeat key
.filter((_, index) => index !== repeatIndex)
// remove current level all child
.filter((key) => levelKeys[key] <= levelKeys[currentOpenKey]),
),
);
} else {
// close
setStateOpenKeys(openKeys);
localStorage.setItem('openKeys', JSON.stringify(openKeys));
}
};
// 当路由变化时更新当前选中菜单项
useEffect(() => {
console.log(history, 'menu_history', menuData);
}, []);
const pathname = history.location.pathname;
const matchedMenu = findMenuByPath(menuData, pathname);
console.log('matchedMenu', matchedMenu);
if (matchedMenu) {
setSelectedMenu([matchedMenu.key]);
changeMenu(matchedMenu);
}
}, [menuData, history.location.pathname]);
return (
<div className="flex flex-col items-center justify-between menubar_wrap">
<div className="menu_top">
<img src={menuLogo} />
<div className="flex items-center menu_top">
<BusinessLogoIcon></BusinessLogoIcon>
<span>{getStoreBusinessInfo()?.name}</span>
</div>
{/* <ul className="menus_box m-[0px]">
{menuData &&
menuData.length &&
menuData.map((item, index) => {
return (
<li key={index} className="px-[16px]" onClick={() => tabRouter(item)}>
<span>{item.title}</span>
</li>
);
})}
</ul> */}
{/* // TODO 菜单需要补充路由聚焦状态 */}
<div className="menu_center">
<Menu
mode="inline"
theme="dark"
defaultSelectedKeys={['101']}
items={menuData}
onClick={menuClick}
/>
selectedKeys={selectedMenu}
openKeys={stateOpenKeys}
onOpenChange={onOpenChange}
>
{menuData.map((menuItem) => (
<Menu.Item key={menuItem.key} icon={menuItem.icon} onClick={() => menuClick(menuItem)}>
{intl.formatMessage({ id: `menu-${menuItem.name}`, defaultMessage: '菜单' })}
</Menu.Item>
))}
</Menu>
</div>
<div className="menu_bottom">
{/* <div className="menu_bottom">
<img src={menuFooter} />
</div>
</div> */}
</div>
);
};

@ -7,8 +7,8 @@ export default {
'pages.login.success': 'সফল লগইন!',
'pages.login.username.placeholder': 'ব্যবহারকারীর নাম: admin or user',
'pages.login.username.required': 'আপনার ব্যবহারকারীর নাম ইনপুট করুন!',
'pages.login.password.placeholder': 'পাসওয়ার্ড: ant.design',
'pages.login.password.required': 'আপনার পাসওয়ার্ড ইনপুট করুন!',
'pages.login.psw.placeholder': 'পাসওয়ার্ড: ant.design',
'pages.login.psw.required': 'আপনার পাসওয়ার্ড ইনপুট করুন!',
'pages.login.phoneLogin.tab': 'ফোন লগইন',
'pages.login.phoneLogin.errorMessage': 'যাচাইকরণ কোড ত্রুটি',
'pages.login.phoneNumber.placeholder': 'ফোন নম্বর',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': 'শক্তিশালী',
'app.settings.security.medium': 'মধ্যম',
'app.settings.security.weak': 'দুর্বল',
'app.settings.security.password': 'অ্যাকাউন্টের পাসওয়ার্ড',
'app.settings.security.password-description': 'বর্তমান পাসওয়ার্ড শক্তি',
'app.settings.security.psw': 'অ্যাকাউন্টের পাসওয়ার্ড',
'app.settings.security.psw-description': 'বর্তমান পাসওয়ার্ড শক্তি',
'app.settings.security.phone': 'সুরক্ষা ফোন',
'app.settings.security.phone-description': 'আবদ্ধ ফোন',
'app.settings.security.question': 'নিরাপত্তা প্রশ্ন',
@ -46,8 +46,8 @@ export default {
'app.settings.binding.dingding': 'বাঁধাই ডিঙ্গটালক',
'app.settings.binding.dingding-description': 'বর্তমানে আনবাউন্ড ডিঙ্গটাল অ্যাকাউন্ট',
'app.settings.binding.bind': 'বাঁধাই',
'app.settings.notification.password': 'অ্যাকাউন্টের পাসওয়ার্ড',
'app.settings.notification.password-description':
'app.settings.notification.psw': 'অ্যাকাউন্টের পাসওয়ার্ড',
'app.settings.notification.psw-description':
'অন্যান্য ব্যবহারকারীর বার্তাগুলি স্টেশন চিঠি আকারে জানানো হবে',
'app.settings.notification.messages': 'সিস্টেম বার্তা',
'app.settings.notification.messages-description':

@ -2,13 +2,13 @@ export default {
'pages.layouts.userLayout.title':
'Ant Design is the most influential web design specification in Xihu district',
'pages.login.accountLogin.tab': 'Account Login',
'pages.login.accountLogin.errorMessage': 'Incorrect username/password(admin/ant.design)',
'pages.login.accountLogin.errorMessage': 'Incorrect username/psw(admin/ant.design)',
'pages.login.failure': 'Login failed, please try again!',
'pages.login.success': 'Login successful!',
'pages.login.username.placeholder': 'Username: admin or user',
'pages.login.username.required': 'Please input your username!',
'pages.login.password.placeholder': 'Password: ant.design',
'pages.login.password.required': 'Please input your password!',
'pages.login.psw.placeholder': 'Password: ant.design',
'pages.login.psw.required': 'Please input your psw!',
'pages.login.phoneLogin.tab': 'Phone Login',
'pages.login.phoneLogin.errorMessage': 'Verification Code Error',
'pages.login.phoneNumber.placeholder': 'Phone Number',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': 'Strong',
'app.settings.security.medium': 'Medium',
'app.settings.security.weak': 'Weak',
'app.settings.security.password': 'Account Password',
'app.settings.security.password-description': 'Current password strength',
'app.settings.security.psw': 'Account Password',
'app.settings.security.psw-description': 'Current psw strength',
'app.settings.security.phone': 'Security Phone',
'app.settings.security.phone-description': 'Bound phone',
'app.settings.security.question': 'Security Question',
@ -46,8 +46,8 @@ export default {
'app.settings.binding.dingding': 'Binding DingTalk',
'app.settings.binding.dingding-description': 'Currently unbound DingTalk account',
'app.settings.binding.bind': 'Bind',
'app.settings.notification.password': 'Account Password',
'app.settings.notification.password-description':
'app.settings.notification.psw': 'Account Password',
'app.settings.notification.psw-description':
'Messages from other users will be notified in the form of a station letter',
'app.settings.notification.messages': 'System Messages',
'app.settings.notification.messages-description':

@ -6,8 +6,8 @@ export default {
'pages.login.success': 'ورود موفق!',
'pages.login.username.placeholder': 'نام کاربری: مدیر یا کاربر',
'pages.login.username.required': 'لطفا نام کاربری خود را وارد کنید!',
'pages.login.password.placeholder': 'رمز عبور: ant.design',
'pages.login.password.required': 'لطفاً رمز ورود خود را وارد کنید!',
'pages.login.psw.placeholder': 'رمز عبور: ant.design',
'pages.login.psw.required': 'لطفاً رمز ورود خود را وارد کنید!',
'pages.login.phoneLogin.tab': 'ورود به سیستم تلفن',
'pages.login.phoneLogin.errorMessage': 'خطای کد تأیید',
'pages.login.phoneNumber.placeholder': 'شماره تلفن',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': 'قوی',
'app.settings.security.medium': 'متوسط',
'app.settings.security.weak': 'ضعیف',
'app.settings.security.password': 'رمز عبور حساب کاربری',
'app.settings.security.password-description': 'قدرت رمز عبور فعلی',
'app.settings.security.psw': 'رمز عبور حساب کاربری',
'app.settings.security.psw-description': 'قدرت رمز عبور فعلی',
'app.settings.security.phone': 'تلفن امنیتی',
'app.settings.security.phone-description': 'تلفن مقید',
'app.settings.security.question': 'سوال امنیتی',
@ -46,8 +46,8 @@ export default {
'app.settings.binding.dingding': 'اتصال DingTalk',
'app.settings.binding.dingding-description': 'حساب DingTalk در حال حاضر محدود نشده است',
'app.settings.binding.bind': 'بستن',
'app.settings.notification.password': 'رمز عبور حساب کاربری',
'app.settings.notification.password-description':
'app.settings.notification.psw': 'رمز عبور حساب کاربری',
'app.settings.notification.psw-description':
'پیام های سایر کاربران در قالب یک نامه ایستگاهی اعلام خواهد شد',
'app.settings.notification.messages': 'پیام های سیستم',
'app.settings.notification.messages-description':

@ -7,8 +7,8 @@ export default {
'pages.login.success': 'Login berhasil!',
'pages.login.username.placeholder': 'nama pengguna: admin atau user',
'pages.login.username.required': 'Nama pengguna harus diisi!',
'pages.login.password.placeholder': 'kata sandi: ant.design',
'pages.login.password.required': 'Kata sandi harus diisi!',
'pages.login.psw.placeholder': 'kata sandi: ant.design',
'pages.login.psw.required': 'Kata sandi harus diisi!',
'pages.login.phoneLogin.tab': 'Login dengan ponsel',
'pages.login.phoneLogin.errorMessage': 'Kesalahan kode verifikasi',
'pages.login.phoneNumber.placeholder': 'masukkan nomor telepon',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': 'Kuat',
'app.settings.security.medium': 'Sedang',
'app.settings.security.weak': 'Lemah',
'app.settings.security.password': 'Kata Sandi Akun',
'app.settings.security.password-description': 'Kekuatan Kata Sandi saat ini',
'app.settings.security.psw': 'Kata Sandi Akun',
'app.settings.security.psw-description': 'Kekuatan Kata Sandi saat ini',
'app.settings.security.phone': 'Keamanan Ponsel',
'app.settings.security.phone-description': 'Mengikat Ponsel',
'app.settings.security.question': 'Pertanyaan Keamanan',
@ -46,8 +46,8 @@ export default {
'app.settings.binding.dingding': 'Mengikat DingTalk',
'app.settings.binding.dingding-description': 'Tidak mengikat akun DingTalk',
'app.settings.binding.bind': 'Ikat',
'app.settings.notification.password': 'Kata Sandi Akun',
'app.settings.notification.password-description':
'app.settings.notification.psw': 'Kata Sandi Akun',
'app.settings.notification.psw-description':
'Pesan dari pengguna lain akan diberitahu dalam bentuk surat',
'app.settings.notification.messages': 'Pesan Sistem',
'app.settings.notification.messages-description':

@ -7,8 +7,8 @@ export default {
'pages.login.success': 'ログイン成功!',
'pages.login.username.placeholder': 'ユーザー名adminまたはuser',
'pages.login.username.required': 'ユーザー名を入力してください!',
'pages.login.password.placeholder': 'パスワードant.design',
'pages.login.password.required': 'パスワードを入力してください!',
'pages.login.psw.placeholder': 'パスワードant.design',
'pages.login.psw.required': 'パスワードを入力してください!',
'pages.login.phoneLogin.tab': '電話ログイン',
'pages.login.phoneLogin.errorMessage': '検証コードエラー',
'pages.login.phoneNumber.placeholder': '電話番号',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': '強い',
'app.settings.security.medium': 'ミディアム',
'app.settings.security.weak': '弱い',
'app.settings.security.password': 'アカウントパスワード',
'app.settings.security.password-description': '現在のパスワードの強度',
'app.settings.security.psw': 'アカウントパスワード',
'app.settings.security.psw-description': '現在のパスワードの強度',
'app.settings.security.phone': 'セキュリティ電話番号',
'app.settings.security.phone-description': 'バインドされた電話番号',
'app.settings.security.question': '秘密の質問',
@ -46,8 +46,8 @@ export default {
'app.settings.binding.dingding': 'ディントークをバインドする',
'app.settings.binding.dingding-description': '現在バインドされていないディントークアカウント',
'app.settings.binding.bind': 'バインド',
'app.settings.notification.password': 'アカウントパスワード',
'app.settings.notification.password-description':
'app.settings.notification.psw': 'アカウントパスワード',
'app.settings.notification.psw-description':
'他のユーザーからのメッセージは、ステーションレターの形式で通知されます',
'app.settings.notification.messages': 'システムメッセージ',
'app.settings.notification.messages-description':

@ -7,8 +7,8 @@ export default {
'pages.login.success': 'Login efetuado com sucesso!',
'pages.login.username.placeholder': 'Usuário: admin or user',
'pages.login.username.required': 'Por favor insira seu usuário!',
'pages.login.password.placeholder': 'Senha: ant.design',
'pages.login.password.required': 'Por favor insira sua senha!',
'pages.login.psw.placeholder': 'Senha: ant.design',
'pages.login.psw.required': 'Por favor insira sua senha!',
'pages.login.phoneLogin.tab': 'Login com Telefone',
'pages.login.phoneLogin.errorMessage': 'Erro de Código de Verificação',
'pages.login.phoneNumber.placeholder': 'Telefone',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': 'Forte',
'app.settings.security.medium': 'Média',
'app.settings.security.weak': 'Fraca',
'app.settings.security.password': 'Senha da Conta',
'app.settings.security.password-description': 'Força da senha',
'app.settings.security.psw': 'Senha da Conta',
'app.settings.security.psw-description': 'Força da senha',
'app.settings.security.phone': 'Telefone de Seguraça',
'app.settings.security.phone-description': 'Telefone vinculado',
'app.settings.security.question': 'Pergunta de Segurança',
@ -46,8 +46,8 @@ export default {
'app.settings.binding.dingding': 'Vincular DingTalk',
'app.settings.binding.dingding-description': 'Atualmente não vinculado à conta DingTalk',
'app.settings.binding.bind': 'Vincular',
'app.settings.notification.password': 'Senha da Conta',
'app.settings.notification.password-description':
'app.settings.notification.psw': 'Senha da Conta',
'app.settings.notification.psw-description':
'Mensagens de outros usuários serão notificadas na forma de uma estação de letra',
'app.settings.notification.messages': 'Mensagens de Sistema',
'app.settings.notification.messages-description':

@ -84,7 +84,7 @@ export const interface_manage: { [key: string]: string } = {
'device.interface_manage.table.list.capture': '最近拍摄',
'device.interface_manage.table.list.port': '端口',
'device.interface_manage.table.list.loginName': '登录名',
'device.interface_manage.table.list.password': '密码',
'device.interface_manage.table.list.psw': '密码',
'device.interface_manage.table.list.fileDirectory': '文件目录',
'device.interface_manage.table.list.requestAddress': '请求地址',
'device.interface_manage.table.list.requestKey': '请求Key',
@ -100,7 +100,7 @@ export const interface_manage: { [key: string]: string } = {
'device.interface_manage.table.rule.required.address': '接口地址为必填项',
'device.interface_manage.table.rule.required.ip': 'IP地址为必填项',
'device.interface_manage.table.rule.required.loginName': '登录名为必填项',
'device.interface_manage.table.rule.required.password': '密码为必填项',
'device.interface_manage.table.rule.required.psw': '密码为必填项',
'device.interface_manage.table.rule.required.fileDirectory': '文件目录为必填项',
'device.interface_manage.table.rule.required.requestAddress': '请求地址为必填项',
'device.interface_manage.table.rule.required.requestKey': '请求Key为必填项',

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-01 11:20:09
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-10 15:53:11
* @LastEditTime: 2024-04-22 15:42:18
* @FilePath: \uighur-recognition-web2\src\locales\zh-CN\menu.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -62,6 +62,10 @@ export default {
'menu.home-business-project': '企业项目',
'menu.model-index': '模型管理',
'menu.model-runtime-lib': '模型运行库',
'menu-business-info-index': '企业信息',
'menu-business-node-setting': '节点设置',
'menu-business-model-index': '业务模型',
// 待废弃
'menu.realTime': '实时分析',
'menu.realTime.realTime-involved-list': '告警汇总',

@ -132,7 +132,7 @@ export const server_status: { [key: string]: string } = {
'resource.server_status.table.list.name': '服务器名称',
'resource.server_status.table.list.userName': '用户名',
'resource.server_status.table.list.ip': 'IP',
'resource.server_status.table.list.password': '密码',
'resource.server_status.table.list.psw': '密码',
'resource.server_status.table.list.defaultPort': '默认端口',
'resource.server_status.table.list.parameter': '服务器参数',
'resource.server_status.table.list.publicKeyString': '公钥字符串',

@ -14,8 +14,8 @@ export default {
'pages.login.success': '登录成功!',
'pages.login.username.placeholder': '用户名: admin or user',
'pages.login.username.required': '用户名是必填项!',
'pages.login.password.placeholder': '密码: ant.design',
'pages.login.password.required': '密码是必填项!',
'pages.login.psw.placeholder': '密码: ant.design',
'pages.login.psw.required': '密码是必填项!',
'pages.login.phoneLogin.tab': '手机号登录',
'pages.login.phoneLogin.errorMessage': '验证码错误',
'pages.login.phoneNumber.placeholder': '请输入手机号!',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': '强',
'app.settings.security.medium': '中',
'app.settings.security.weak': '弱',
'app.settings.security.password': '账户密码',
'app.settings.security.password-description': '当前密码强度',
'app.settings.security.psw': '账户密码',
'app.settings.security.psw-description': '当前密码强度',
'app.settings.security.phone': '密保手机',
'app.settings.security.phone-description': '已绑定手机',
'app.settings.security.question': '密保问题',
@ -44,8 +44,8 @@ export default {
'app.settings.binding.dingding': '绑定钉钉',
'app.settings.binding.dingding-description': '当前未绑定钉钉账号',
'app.settings.binding.bind': '绑定',
'app.settings.notification.password': '账户密码',
'app.settings.notification.password-description': '其他用户的消息将以站内信的形式通知',
'app.settings.notification.psw': '账户密码',
'app.settings.notification.psw-description': '其他用户的消息将以站内信的形式通知',
'app.settings.notification.messages': '系统消息',
'app.settings.notification.messages-description': '系统消息将以站内信的形式通知',
'app.settings.notification.todo': '待办任务',

@ -82,7 +82,7 @@ export const user: { [key: string]: string } = {
'system.user.table.list.id': 'ID',
'system.user.table.list.userName': '用户名',
'system.user.table.list.nickName': '昵称',
'system.user.table.list.password': '密码',
'system.user.table.list.psw': '密码',
'system.user.table.list.password_re': '再一次确认密码',
'system.user.table.list.roleId': '角色',
'system.user.table.list.roleIds': '角色',
@ -100,8 +100,8 @@ export const user: { [key: string]: string } = {
'system.user.table.list.update': '更新用户',
'system.user.table.rule.required.userName': '用户名为必填项',
'system.user.table.rule.required.nickName': '昵称为必填项',
'system.user.table.rule.required.password': '密码为必填项',
'system.user.table.rule.password.not_same': '两次密码不一致',
'system.user.table.rule.required.psw': '密码为必填项',
'system.user.table.rule.psw.not_same': '两次密码不一致',
};
export const post: { [key: string]: string } = {

@ -6,8 +6,8 @@ export default {
'pages.login.success': '登錄成功!',
'pages.login.username.placeholder': '用戶名: admin or user',
'pages.login.username.required': '用戶名是必填項!',
'pages.login.password.placeholder': '密碼: ant.design',
'pages.login.password.required': '密碼是必填項!',
'pages.login.psw.placeholder': '密碼: ant.design',
'pages.login.psw.required': '密碼是必填項!',
'pages.login.phoneLogin.tab': '手機號登錄',
'pages.login.phoneLogin.errorMessage': '驗證碼錯誤',
'pages.login.phoneNumber.placeholder': '請輸入手機號!',

@ -24,8 +24,8 @@ export default {
'app.settings.security.strong': '強',
'app.settings.security.medium': '中',
'app.settings.security.weak': '弱',
'app.settings.security.password': '賬戶密碼',
'app.settings.security.password-description': '當前密碼強度',
'app.settings.security.psw': '賬戶密碼',
'app.settings.security.psw-description': '當前密碼強度',
'app.settings.security.phone': '密保手機',
'app.settings.security.phone-description': '已綁定手機',
'app.settings.security.question': '密保問題',
@ -44,8 +44,8 @@ export default {
'app.settings.binding.dingding': '綁定釘釘',
'app.settings.binding.dingding-description': '當前未綁定釘釘賬號',
'app.settings.binding.bind': '綁定',
'app.settings.notification.password': '賬戶密碼',
'app.settings.notification.password-description': '其他用戶的消息將以站內信的形式通知',
'app.settings.notification.psw': '賬戶密碼',
'app.settings.notification.psw-description': '其他用戶的消息將以站內信的形式通知',
'app.settings.notification.messages': '系統消息',
'app.settings.notification.messages-description': '系統消息將以站內信的形式通知',
'app.settings.notification.todo': '待辦任務',

@ -0,0 +1,14 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-22 15:37:39
* @FilePath: \general-ai-platform-web\src\pages\Node\BusinessModel\index.tsx
* @Description:
* @
*/
const BusinessModel: React.FC = () => {
return <div className="businessModel_page"></div>;
};
export default BusinessModel;

@ -0,0 +1,14 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-22 15:34:36
* @FilePath: \general-ai-platform-web\src\pages\Node\NodeSetting\index.tsx
* @Description:
* @
*/
const NodeSetting: React.FC = () => {
return <div className="nodeSetting_page"></div>;
};
export default NodeSetting;

@ -1,100 +0,0 @@
import { postUploadRecognition } from '@/services/realTime/involved';
import { CloseCircleOutlined, EllipsisOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Image, Popover, message } from 'antd';
import React, { useState } from 'react';
interface ImageWithPopoverProps {
src: string;
reload: any;
person_id: any;
}
const ImageWithPopover: React.FC<ImageWithPopoverProps> = ({ src, person_id, reload }) => {
const intl = useIntl();
const [open, setOpen] = useState(false);
const content = (
<div
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}
>
{/* <div>1</div>
<div>2</div> */}
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF' }}
icon={<CloseCircleOutlined style={{ color: '#E80D0D', fontSize: 12 }} />}
onClick={(event) => {
event.stopPropagation();
postUploadRecognition({
person_id: person_id,
classify: '0',
})
.then(() => {
message.success('此人已被移除重点关注');
reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
setOpen(false);
}}
>
</Button>
</div>
);
const handleOpenChange = (value: boolean) => {
setOpen(value);
};
const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation(); // 阻止事件冒泡到父组件并阻止默认事件触发
};
return (
<div style={{ position: 'relative', boxSizing: 'border-box', width: 96, height: 96 }}>
<Image style={{ borderRadius: 4 }} width={96} height={96} preview={false} src={src} />
<Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 32 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 32, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 0, right: -4 }}
type="text"
icon={
<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />
}
onClick={handleButtonClick}
/>
</Popover>
{/* {involved.state && (
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px'
}}
>
</div>
)} */}
</div>
);
};
export default ImageWithPopover;

@ -1,26 +0,0 @@
.InvolvedImgBox {
box-sizing: border-box;
// display: flex;
// justify-content: flex-start;
padding: 16px 32px;
border-top: 1px solid #e0e0e0;
.involvedImgList {
position: relative;
span {
position: absolute;
bottom: -30px;
left: 15px;
width: 2px;
height: 30px;
border-left: 2px dashed #081fa8;
}
}
}
.myButtonDisabled {
visibility: hidden;
}
.involvedModalForm {
.ant-modal .ant-modal-content {
padding: 0 !important;
}
}

@ -1,318 +0,0 @@
import { getUploadInvolvedTravelList, postUploadRecognition } from '@/services/realTime/involved';
import { CloseCircleOutlined, EllipsisOutlined } from '@ant-design/icons';
import { ModalForm } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Form, Image, List, Popover, message } from 'antd';
import moment from 'moment';
import VirtualList from 'rc-virtual-list';
import React, { useEffect, useState } from 'react';
import trajectoryBottom from '../../../../../public/images/involved/trajectoryBottom.png';
import './InvolvedDetails.less';
import styles from './InvolvedDetails.less';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.InvolvedDetailsParams>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.InvolvedDetailsParams>;
reload: any;
};
const InvolvedDetails: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.InvolvedDetailsParams>();
const [dataFlag, setDataFlag] = useState(false);
const [open, setOpen] = useState(false);
const [trajectoryData, setTrajectoryData] = useState([]);
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentPage, setCurrentPage] = useState<number>(1);
const [total, setTotal] = useState<number>(0);
const ContainerHeight = 630;
const content = (
<div
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}
>
{/* <div>1</div>
<div>2</div> */}
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF' }}
icon={<CloseCircleOutlined style={{ color: '#E80D0D', fontSize: 12 }} />}
onClick={(event) => {
event.stopPropagation();
postUploadRecognition({
person_id: props.values.person_id,
classify: '0',
})
.then(() => {
message.success('此人已被移除重点关注');
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
setOpen(false);
props.handleModal();
}}
>
</Button>
</div>
);
const handleOpenChange = (value: boolean) => {
setOpen(value);
};
const appendData = (page: any, pageSize: any) => {
const reqParams = {
page: page,
pageSize: pageSize,
// desc: false,
person_id: props.values.person_id,
// ...rest,
};
getUploadInvolvedTravelList(reqParams)
.then((res) => {
console.log(res);
if (res.data.results) {
setTrajectoryData(trajectoryData.concat(res.data.results));
setTotal(res.data.count);
if (res.data.next) {
setDataFlag(true);
} else {
setDataFlag(false);
// setTrajectoryData([]); // 重置trajectoryData数据为空数组
}
}
})
.catch(() => {
// setLoading(false);
setDataFlag(false);
// setTrajectoryData([]); // 重置trajectoryData数据为空数组
});
};
const onScroll = (e: React.UIEvent<HTMLElement, UIEvent>) => {
// Refer to: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#problems_and_solutions
console.log(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - ContainerHeight);
if (Math.abs(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - ContainerHeight) <= 1) {
if (dataFlag) {
const nextPage = currentPage + 1;
setCurrentPage(nextPage);
appendData(nextPage, 10);
}
}
};
useEffect(() => {
if (props.updateModalOpen) {
// 调用接口获取数据
setTrajectoryData([]); // 重置trajectoryData数据为空数组
setCurrentPage(1);
setCurrentPageSize(10);
appendData(currentPage, currentPageSize);
}
}, [props.updateModalOpen]);
return (
<ModalForm<any>
width={615}
title={
<div
style={{
display: 'flex',
alignItems: 'center',
padding: '24px 32px 0px',
justifyContent: 'flex-start',
}}
>
<div style={{ position: 'relative', boxSizing: 'border-box', width: 120, height: 120 }}>
<Image
style={{ borderRadius: 4 }}
width={120}
height={120}
preview={false}
src={props?.values?.picture_path}
/>
<Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 32 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 32, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 0, right: -4 }}
type="text"
icon={
<EllipsisOutlined
style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }}
/>
}
// onClick={handleButtonClick}
/>
</Popover>
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px',
fontWeight: 400,
}}
>
</div>
</div>
<div
style={{
marginLeft: 12,
height: 98,
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
color: '#666',
fontSize: 14,
fontWeight: 400,
}}
>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(props?.values?.classify_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(props?.values?.appear_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
{/* <div>
:{' '}
<span
style={{
color: '#333',
}}
>
{props?.values?.device_name}
</span>
</div> */}
</div>
</div>
}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
setTrajectoryData([]);
setCurrentPage(1);
setCurrentPageSize(10);
props.handleModal();
},
wrapClassName: 'involvedModalForm',
}}
submitter={false}
submitTimeout={2000}
onFinish={async (values) => {
values.is_ignore = true;
values.person_id = props.values.person_id;
// console.log(values);
// postIgnoringvents(values)
// .then(() => {
// message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
// props.reload();
// })
// .catch(() => {
// message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
// });
setTrajectoryData([]);
setCurrentPage(1);
setCurrentPageSize(10);
props.handleModal();
return true;
}}
>
{/* <ProForm.Group> */}
{/* <div className={styles.alarmDetails}>
: <span className={styles.alarmSpan}></span>: <span className={styles.alarmSpan}>广1#</span>: <span className={styles.alarmSpan}>2023-01-15 22:00:03</span>
</div> */}
<div className={styles.InvolvedImgBox}>
<List>
<VirtualList
data={trajectoryData}
height={ContainerHeight}
itemHeight={64}
itemKey="id"
onScroll={onScroll}
>
{(item: any, index: any) => (
<div key={item.person_id + index}>
<List.Item style={{ borderBottom: 0, height: 64, padding: 0 }}>
<List.Item.Meta
avatar={
<div className={styles.involvedImgList}>
<img style={{ width: 32, height: 32 }} src={trajectoryBottom} />
{index + 1 !== total && <span />}
</div>
}
title={
<div style={{ lineHeight: '30px', color: '#666' }}>
:{' '}
<span style={{ color: '#333', marginRight: 16 }}>
{moment(item.create_time).format('YYYY-MM-DD hh:mm:ss')}
</span>{' '}
: <span style={{ color: '#333' }}>{item.video_name}</span>
</div>
}
/>
<div>
<Image
style={{ borderRadius: 4 }}
width={48}
height={48}
preview={{
mask: '',
}}
src={item.picture_path}
/>
</div>
</List.Item>
{index === total - 1 && (
<div style={{ textAlign: 'center', color: '#999' }}>~</div>
)}
</div>
)}
</VirtualList>
</List>
</div>
{/* </ProForm.Group> */}
</ModalForm>
);
};
export default InvolvedDetails;

@ -1,355 +0,0 @@
import { PageContainer, ProCard, ProList } from '@ant-design/pro-components';
import React, { useEffect, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
// import DeviceStatusCard from './components/DeviceStatusCard';
// import CreateForm from './components/CreateForm';
import { getUploadInvolvedList } from '@/services/realTime/involved';
import moment from 'moment';
import ImageWithPopover from './components/ImageWithPopover';
import InvolvedDetails from './components/InvolvedDetails';
/**
* @
* 1
*/
// const tabOptions: Record<string, any> = {
// singlePersonHoveringAlarm: 90,
// multiplePersonGatheringAlarm: 20,
// sensitiveTimePeriodAlarm: 20,
// ignored: 2,
// // processingStatus: 10,
// // errorStatus: 20,
// };
export type DeleteBoxProps = {
modalOpen: boolean;
handleModal: () => void;
values: any;
reload: any;
};
const InvolvedUploadList: React.FC = () => {
// const [cardActionProps, setCardActionProps] = useState<'actions' | 'extra'>('extra');
/**
* @en-US Pop-up window of new window
* @zh-CN
* */
// const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
// const [modalOpen, setModalOpen] = useState(false);
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
/**
* @en-US International configuration
* @zh-CN
* */
// const access = useAccess();
// const intl = useIntl();
// const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentPage, setCurrentPage] = useState<number>(1);
const [total, setTotal] = useState<number>(0);
// const [activeTabIndex, setActiveTabIndex] = useState<number>(0);
const [dataTestList, setdataTestList] = useState<any>([]);
// const [tab, setTab] = useState<string>(alarmRulesEnums[0].key);
// const [tabs, setTabs] = useState<any>([]);
// const changeProjectTab = (key: string) => {
// setTab(key);
// console.log(key);
// // eslint-disable-next-line @typescript-eslint/no-use-before-define
// initList(key)
// };
// const handleCreateModal = () => {
// if (createModalOpen) {
// setCreateModalOpen(false);
// setCurrentRow(undefined);
// } else {
// setCreateModalOpen(true);
// }
// };
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
// const handleDestroy = async () => {
// if (modalOpen) {
// setModalOpen(false);
// setCurrentRow(undefined);
// } else {
// setModalOpen(true);
// }
// // deleteBusinessImageDeleteBusinessImage({ id: selectedRow.id })
// // .then(() => {
// // message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
// // actionRef.current?.reload();
// // })
// // .catch(() => {
// // message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
// // });
// };
// const { confirm } = Modal;
// const showConfirm = (record: any) => {
// confirm({
// title: `确定删除${record.name}吗`,
// icon: <QuestionCircleFilled />,
// content: '确定删除服务器1吗删除后将找不到此服务器请谨慎操作.',
// okText: '确认',
// cancelText: '取消',
// width: 560,
// onOk() {
// console.log('OK');
// },
// onCancel() {
// console.log('Cancel');
// },
// });
// };
// 处理初始值
function initDataTestList(dataList: Record<string, any>[]) {
console.log(dataList, 'initDataTestList');
let finalList: { content: React.JSX.Element }[] = [];
if (Array.isArray(dataList) && dataList.length) {
finalList = dataList.map((record, index) => {
return {
content: (
<ProCard
className="gn"
style={{ backgroundColor: '#F5F6FF', margin: 0, padding: 0, borderRadius: 4 }}
bodyStyle={{ margin: 0, padding: 0 }}
>
<div
style={{
display: 'flex',
alignItems: 'center',
padding: 20,
justifyContent: 'flex-start',
}}
onClick={() => {
console.log(index, 'index');
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
{/* <Image
width={96}
preview={false}
src={record.picture_path[0]}
/> */}
<ImageWithPopover
src={record.picture_path}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
reload={initList}
person_id={record.person_id}
// handleInvolved={handleInvolved}
></ImageWithPopover>
<div
style={{
marginLeft: 16,
height: 90,
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
color: '#666',
}}
>
{/* <div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(record.appear_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div> */}
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{record.video_name}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(record.classify_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
</div>
</div>
</ProCard>
),
};
});
}
setdataTestList(() => [...finalList]);
}
// 初始化加载
async function initList(tabId: string = '1') {
const reqParams = {
page: currentPage,
pageSize: currentPageSize,
// desc: false,
classify: tabId,
// ...rest,
};
const resp = await getUploadInvolvedList({ ...reqParams });
// console.log(resp,'resp');
// setCurrentPageSize(resp?.data?.count)
setTotal(resp?.data?.count);
initDataTestList(resp?.data?.results);
// request={async (params = {}, sort) => {
// const { current, ...rest } = params;
// const reqParams = {
// page: current,
// desc: false,
// warning_type: tab,
// ...rest,
// };
// if (sort && Object.keys(sort).length) {
// reqParams.orderKey = Object.keys(sort)[0];
// let sort_select = sort[reqParams.orderKey];
// reqParams.desc = sort_select === 'descend';
// }
// // TODO 联调查询设备状态接口
// console.log(reqParams, 'reqParams');
// let resp = await postAlarmList({ ...reqParams });
// console.log(resp, 'postAlarmList_result');
// initDataTestList(resp.result);
// // return {
// // data: resp.result,
// // success: resp.success,
// // total: resp.count,
// // current: resp.count,
// // pageSize: resp.count,
// // };
// }}
}
useEffect(() => {
// 模拟异步请求数据
initList();
}, [currentPage, currentPageSize]);
return (
<PageContainer
// title={false}
// content={
// <div style={{
// display: 'flex',
// justifyContent: 'space-between'
// }}>
// <div style={{
// fontWeight: 600,
// fontSize: 20,
// color: '#333'
// }}></div>
// </div>
// }
>
<ProCard
className="gn"
bodyStyle={{ padding: 10, margin: 0 }}
style={{ padding: 0, margin: 0 }}
>
{/* <Tabs
activeKey={tab}
items={tabs}
onChange={(key) => {
changeProjectTab(key);
}}
></Tabs> */}
<ProList<any>
className="gn"
ghost={true}
itemCardProps={{
ghost: true,
bodyStyle: { padding: 0, margin: 0 },
style: {
width: '100%',
border: 0,
// minHeight: 700
// padding: 0, margin: 0
},
}}
cardProps={{
bodyStyle: {
padding: '8px 16px 16px',
borderRadius: 8,
},
}}
pagination={{
...proTablePaginationOptions,
total: total,
current: currentPage,
pageSize: currentPageSize,
showSizeChanger: true,
onChange: (page, pageSize) => {
console.log(page, pageSize);
setCurrentPage(page);
setCurrentPageSize(pageSize);
},
}}
showActions="hover"
rowSelection={false}
grid={{ gutter: 16, xs: 1, md: 2, lg: 2, xl: 3, xxl: 4 }}
metas={{
type: {
// 不展示在筛选项
hideInSearch: true,
},
content: {
hideInSearch: true,
},
actions: {
cardActionProps: 'extra',
},
}}
dataSource={dataTestList}
/>
</ProCard>
{/* <CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={actionRef.current?.reload}
/> */}
<InvolvedDetails
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={initList}
/>
</PageContainer>
);
};
export default InvolvedUploadList;

@ -1,85 +0,0 @@
.alarmImgBox {
// display: flex;
// justify-content: flex-start;
.alarmImgLeft {
position: relative;
width: 120px;
margin-right: 32px;
// height: 600px;
.alarmImgLeftBox {
width: 112px;
height: 112px;
border-radius: 4px;
// background: skyblue;
}
.alarmImgLeftBoxActive {
width: 112px;
height: 112px;
border: 1.5px solid #081fa8;
border-radius: 4px;
}
.shadowBox {
position: absolute;
bottom: 0px;
left: 0;
z-index: 999;
width: 112px;
height: 20px;
background: #fff;
}
}
.alarmImgRight {
position: relative;
flex: 1;
.alarmImgRightTopBox {
width: 640px;
height: 640px;
background: skyblue;
}
.alarmDetails {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 38px;
margin-bottom: 16px;
padding-left: 24px;
color: #ffffff;
font-weight: 400;
font-size: 16px;
font-family: PingFang SC;
line-height: 38px;
background: rgba(0, 0, 0, 0.6);
.alarmSpan {
// color: #333;
margin-right: 24px;
}
}
}
.alarmImgDescribe {
margin-bottom: 12px;
color: #666;
font-weight: 500;
font-size: 16px;
font-family: PingFang SC;
span {
color: #333;
}
}
.alarmImgContent {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
box-sizing: border-box;
width: 784px;
margin-bottom: 24px;
padding: 16px 0 16px 16px;
// height: 172px;
background: #f7f7f7;
border: 1px dashed #dcdcdc;
border-radius: 4px;
}
}
.myButtonDisabled {
visibility: hidden;
}

@ -1,297 +0,0 @@
import { postUploadIgnoringvents } from '@/services/realTime/alarmlist';
import { postUploadRecognition } from '@/services/realTime/involved';
import { ModalForm } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Form, message } from 'antd';
import moment from 'moment';
import React, { useEffect, useState } from 'react';
import styles from './AlarmDetails.less';
import ImageSinglePopover from './ImageSinglePopover';
import ImageWithPopover from './ImageWithPopover';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.AlarmDetailsParams>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.AlarmDetailsParams>;
reload: any;
warning_type: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.AlarmDetailsParams>();
// const [isActive, setIsActive] = useState(0);
// const [visible, setVisible] = useState(false);
const [involved, setInvolved] = useState(0);
// const [involvedInfo, setInvolvedInfo] = useState([...(props?.values?.person_list || [])]);
const [involvedInfo, setInvolvedInfo] = useState<any[]>([]);
// useEffect(() => {
// if (props.values?.person_list) {
// setInvolvedInfo([...props.values.person_list]);
// }
// }, [props.values?.person_list]);
// console.log(object);
// if(props.warning_type === '1') {
// console.log('props.values?.warning_type1');
// setInvolved(props.values.person_list[0][2]);
// }else {
// console.log('props.values?.warning_type2');
// // setInvolvedInfo([...props.values.person_list]);
// }
const handlePostRecognition = (person_id: any, classify: any) => {
postUploadRecognition({
person_id: person_id,
classify: classify,
})
.then((res) => {
console.log(res.data.classify, 'res.data.classify');
if (res.data.classify === 1) {
message.success('此人已被设为重点关注');
} else {
message.success('此人已被移除重点关注');
}
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
};
/** 多人告警组件 */
const handleInvolved = (value: any, index: any) => {
const updatedInvolvedInfo = [...involvedInfo];
console.log(updatedInvolvedInfo);
updatedInvolvedInfo[index][2] = value;
setInvolvedInfo(updatedInvolvedInfo);
handlePostRecognition(updatedInvolvedInfo[index][0], value);
};
/** 单人告警组件 */
// const handleSingleInvolved = () => {
// if (involved === 1) {
// setInvolved(0);
// handlePostRecognition(props.values?.person_id, 0)
// } else {
// setInvolved(1);
// handlePostRecognition(props.values?.person_id, 1)
// }
// }
// const [open, setOpen] = useState(false);
useEffect(() => {
// console.log(Array.isArray(props.values?.person_id),'Array.isArray(props.values?.person_id)');
if (props.updateModalOpen) {
if (props.warning_type === '1') {
console.log('props.values?.warning_type1');
setInvolved(props.values.person_list[0][2]);
} else {
console.log('props.values?.warning_type2');
setInvolvedInfo([...props.values.person_list]);
}
}
}, [props.updateModalOpen]);
return (
<ModalForm<any>
width={832}
title={`${props.values.warning_name}告警`}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
setInvolved(0);
props.handleModal();
},
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitter={{
// resetButtonProps: {
// style: {
// display: 'none',
// },
// },
// searchConfig: {
// submitText: '忽略此事件',
// },
render: (prop) => {
return [
<Button
key="ok"
style={{ backgroundColor: '#E80D0D', color: '#FFF', borderBlockColor: '#E80D0D' }}
onClick={() => {
prop.submit();
}}
>
</Button>,
props.warning_type === '2' ? null : (
<Button
key="involved"
style={{ backgroundColor: '#FAAD14', color: '#FFF', borderBlockColor: '#FAAD14' }}
onClick={() => {
// console.log(props.updateModalOpen);
setInvolved(1);
handlePostRecognition(props.values?.person_list[0][0], 1);
}}
>
</Button>
),
props.warning_type === '2' ? null : (
<Button
key="noInvolved"
style={{ background: '#FFF', color: '#E80D0D', borderColor: '#E80D0D' }}
onClick={() => {
// console.log(props.updateModalOpen);
setInvolved(0);
handlePostRecognition(props.values?.person_list[0][0], 0);
}}
>
</Button>
),
];
},
}}
submitTimeout={2000}
onFinish={async (values) => {
values.is_ignore = true;
values.id = props.values.id;
// console.log(props.values);
postUploadIgnoringvents(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
{/* <ProForm.Group> */}
<div className={styles.alarmImgBox}>
<div className={styles.alarmImgDescribe}>
: <span>{props.values.origin}</span>
</div>
<div className={styles.alarmImgDescribe}>
:{' '}
<span className={styles.alarmSpan}>
{moment(props.values.trigger_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
<div className={styles.alarmImgContent}>
{Array.isArray(props.values?.person_id_list)}
{props.warning_type === '2'
? Array.isArray(involvedInfo) && involvedInfo.length
? involvedInfo.map((item: any, index: any) => {
return (
<ImageWithPopover
src={item?.[1]}
involved={involvedInfo[index][2]}
key={index}
indexId={index}
handleInvolved={handleInvolved}
time={props.values.trigger_time}
></ImageWithPopover>
);
})
: Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length
? props.values.picture_path.map((item: any, index: any) => {
return (
<ImageSinglePopover
src={item}
involved={involved}
key={index}
// handleInvolved={handleSingleInvolved}
reload={props.reload} // 将reload方法作为prop传递给ImageSinglePopover组件
time={props.values.trigger_time}
></ImageSinglePopover>
);
})
: null
: Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length
? props.values.picture_path.map((item: any, index: any) => {
return (
<ImageSinglePopover
src={item}
involved={involved}
key={index}
// handleInvolved={handleSingleInvolved}
reload={props.reload} // 将reload方法作为prop传递给ImageSinglePopover组件
time={props.values.trigger_time}
></ImageSinglePopover>
);
})
: null}
{/* { Array.isArray(involvedInfo) && involvedInfo.length && involvedInfo.map((item: any, index: any) => {
console.log(involvedInfo,'item');
return(<ImageWithPopover src={item?.[1]} involved={involvedInfo[index][2]} key={index} indexId={index} handleInvolved={handleInvolved}></ImageWithPopover>)
})} */}
</div>
{/* <div className={styles.alarmImgLeft}>
<Swiper
style={{height:660}}
slidesPerView={5}
spaceBetween={20}
direction='vertical'
mousewheel={true}
modules={[Mousewheel]}
onSlideChange={() => {
console.log(111);
}}
// pagination={{
// clickable: true,
// }}
// modules={[Pagination]}
>
{ Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length && props?.values?.picture_path.map((item: any, index: any) => {
return (<SwiperSlide key={index} virtualIndex={index} onClick={() => {
console.log(index);
setIsActive(index)
setImageSrc(item)
}}>
<div className={ styles.alarmImgLeftBox }>
<Image
style={{
width: 112,
height: 112,
borderRadius: 4
}}
className={ index === isActive ? styles.alarmImgLeftBoxActive : '' }
preview={false}
src={item}
/>
</div>
</SwiperSlide>)
})}
</Swiper>
<div className={styles.shadowBox}></div>
</div>
<div className={styles.alarmImgRight}>
<div className={styles.alarmImgRightTopBox}>
<Image
width={640}
height={640}
preview={false}
src={imageSrc}
/>
</div>
<div className={styles.alarmDetails}>
: <span className={styles.alarmSpan}>{props.values.device_name}</span>: <span className={styles.alarmSpan}>{moment(props.values.trigger_time).format('YYYY-MM-DD hh:mm:ss')}</span>
</div>
</div> */}
</div>
{/* </ProForm.Group> */}
</ModalForm>
);
};
export default UpdateForm;

@ -1,146 +0,0 @@
import { EyeOutlined } from '@ant-design/icons';
import { Image } from 'antd';
import moment from 'moment';
import React, { useState } from 'react';
interface ImageSinglePopoverProps {
src: string;
involved: any;
// handleInvolved: () => void;
reload: any;
time: any;
}
const ImageSinglePopover: React.FC<ImageSinglePopoverProps> = ({ src, involved, time }) => {
const [visible, setVisible] = useState(false);
// const [open, setOpen] = useState(false);
// 定义一个方法,用于生成自定义的遮罩层
const generateMask = (text: any) => (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#fff',
}}
>
<div style={{ display: 'flex', alignItems: 'center', fontSize: 12 }}>
<EyeOutlined style={{ marginRight: 8, fontSize: 12 }} />
<div>{text}</div>
</div>
</div>
);
// const content = (
// <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center',alignItems: 'center', height: 56}}>
// {/* <div>选项1</div>
// <div>选项2</div> */}
// <Button
// type="text"
// style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
// icon={<InfoCircleOutlined style={{ color: '#FAAD14',fontSize: 12}} />}
// onClick={()=>{
// // setInvolved(true)
// // handleInvolved();
// // reload()
// setOpen(false)
// }}
// >加入重点关注</Button>
// <Button
// type="text"
// style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
// icon={<CloseCircleOutlined style={{ color: '#E80D0D',fontSize: 12}} />}
// onClick={()=>{
// // setInvolved(false)
// // handleInvolved();
// // reload()
// setOpen(false)
// }}
// >移除重点关注</Button>
// </div>
// );
const handleVisibleChange = (value: boolean) => {
setVisible(value);
};
// const handleOpenChange = (value: boolean) => {
// setOpen(value);
// };
return (
<div
style={{
position: 'relative',
boxSizing: 'border-box',
width: 140,
height: 170,
marginRight: 12,
}}
>
<Image
style={{ borderRadius: 4 }}
width={140}
height={140}
preview={{
visible,
src,
onVisibleChange: handleVisibleChange,
mask: generateMask('点击可预览大图'),
}}
src={src}
/>
<div
style={{
height: 30,
textAlign: 'center',
lineHeight: '30px',
fontWeight: 500,
color: '#333',
}}
>
{moment(time).format('YYYY-MM-DD hh:mm:ss')}
</div>
{/* <Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 64 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 64, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 8, right: 0 }}
type="text"
icon={<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />}
/>
</Popover> */}
{involved === 1 && (
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px',
}}
>
</div>
)}
</div>
);
};
export default ImageSinglePopover;

@ -1,170 +0,0 @@
import {
CloseCircleOutlined,
EllipsisOutlined,
EyeOutlined,
InfoCircleOutlined,
} from '@ant-design/icons';
import { Button, Image, Popover } from 'antd';
import moment from 'moment';
import React, { useState } from 'react';
interface ImageWithPopoverProps {
src: string;
involved: any;
indexId: any;
handleInvolved: (value: any, index: any) => void;
time: any;
}
const ImageWithPopover: React.FC<ImageWithPopoverProps> = ({
src,
involved,
indexId,
handleInvolved,
time,
}) => {
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
// 定义一个方法,用于生成自定义的遮罩层
const generateMask = (text: any) => (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#fff',
}}
>
<div style={{ display: 'flex', alignItems: 'center', fontSize: 12 }}>
<EyeOutlined style={{ marginRight: 8, fontSize: 12 }} />
<div>{text}</div>
</div>
</div>
);
const content = (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: 56,
}}
>
{/* <div>1</div>
<div>2</div> */}
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF', marginBottom: 4 }}
icon={<InfoCircleOutlined style={{ color: '#FAAD14', fontSize: 12 }} />}
onClick={() => {
// setInvolved(true)
handleInvolved(1, indexId);
setOpen(false);
}}
>
</Button>
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF' }}
icon={<CloseCircleOutlined style={{ color: '#E80D0D', fontSize: 12 }} />}
onClick={() => {
// setInvolved(false)
handleInvolved(0, indexId);
setOpen(false);
}}
>
</Button>
</div>
);
const handleVisibleChange = (value: boolean) => {
setVisible(value);
};
const handleOpenChange = (value: boolean) => {
setOpen(value);
};
return (
<div
style={{
position: 'relative',
boxSizing: 'border-box',
width: 140,
height: 170,
marginRight: 12,
}}
>
<Image
style={{ borderRadius: 4 }}
width={140}
height={140}
preview={{
visible,
src,
onVisibleChange: handleVisibleChange,
mask: generateMask('点击可预览大图'),
}}
src={src}
/>
<Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 64 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 68, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 30, right: 0 }}
type="text"
icon={
<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />
}
/>
</Popover>
<div
style={{
height: 30,
textAlign: 'center',
lineHeight: '30px',
fontWeight: 500,
color: '#333',
}}
>
{moment(time).format('YYYY-MM-DD hh:mm:ss')}
</div>
{involved === 1 && (
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px',
}}
>
</div>
)}
</div>
);
};
export default ImageWithPopover;

@ -1,376 +0,0 @@
import { alarmVideoAnalysis } from '@/enums/status';
import { PageContainer, ProCard, ProList } from '@ant-design/pro-components';
import { Button, DatePicker, Image, Tabs } from 'antd';
import React, { useEffect, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
// import DeviceStatusCard from './components/DeviceStatusCard';
// import CreateForm from './components/CreateForm';
import { postUploadAlarmList } from '@/services/realTime/alarmlist';
import type { DatePickerProps } from 'antd';
import locale from 'antd/es/date-picker/locale/zh_CN';
import moment from 'moment';
import AlarmDetails from './components/AlarmDetails';
// import dayjs from 'dayjs';
// import 'dayjs/locale/zh-cn';
/**
* @
* 1
*/
export type DeleteBoxProps = {
modalOpen: boolean;
handleModal: () => void;
values: any;
reload: any;
};
const OfflineAlarmList: React.FC = () => {
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
/**
* @en-US International configuration
* @zh-CN
* */
// const access = useAccess();
// const intl = useIntl();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentPage, setCurrentPage] = useState<number>(1);
const [total, setTotal] = useState<number>(0);
const [dataTestList, setdataTestList] = useState<any>([]);
const [tab, setTab] = useState<string>(alarmVideoAnalysis[0].key);
const [tabs, setTabs] = useState<any>([]);
const [importDate, setImportDate] = useState<any>(null);
const [innerDate, setInnerDate] = useState<any>(null);
const changeProjectTab = (key: string) => {
setTab(key);
console.log(key);
// eslint-disable-next-line @typescript-eslint/no-use-before-define
initList(key);
};
const getTabs = () => {
// if (alarmVideoAnalysis.length) {
// setTab(alarmVideoAnalysis[0].key);
// }
setTabs(alarmVideoAnalysis);
};
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
// 处理初始值
function initDataTestList(dataList: Record<string, any>[]) {
console.log(dataList, 'initDataTestList');
let finalList: { content: React.JSX.Element }[] = [];
if (Array.isArray(dataList) && dataList.length) {
finalList = dataList.map((record) => {
return {
content: (
<ProCard
className="gn"
style={{ backgroundColor: '#F5F6FF', margin: 0, padding: 0, borderRadius: 4 }}
bodyStyle={{ margin: 0, padding: 0 }}
>
<div
style={{
display: 'flex',
alignItems: 'center',
padding: 20,
justifyContent: 'flex-start',
}}
onClick={() => {
console.log('11111111111111111');
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<Image width={96} height={96} preview={false} src={record.picture_path[0]} />
<div
style={{
marginLeft: 16,
height: 90,
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
color: '#666',
}}
>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{record.warning_name}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{record.origin}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(record.trigger_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
</div>
</div>
</ProCard>
),
};
});
}
setdataTestList(() => [...finalList]);
}
// 初始化加载
async function initList(tabId: string = tab, date: any = null) {
const reqParams = {
page: currentPage,
pageSize: currentPageSize,
// desc: false,
warning_type: tabId,
analyse_time: date,
// ...rest,
};
const resp = await postUploadAlarmList({ ...reqParams });
// console.log(resp,'resp');
// setCurrentPageSize(resp?.data?.count)
setTotal(resp?.data?.count);
initDataTestList(resp?.data?.results);
}
const onChange: DatePickerProps['onChange'] = (date, dateString) => {
console.log(dateString);
setImportDate(date);
setInnerDate(dateString);
console.log(importDate, 'importDate');
};
useEffect(() => {
getTabs();
}, []);
useEffect(() => {
// 模拟异步请求数据
initList();
}, [currentPage, currentPageSize]);
return (
<PageContainer
// title={false}
// content={
// <div style={{
// display: 'flex',
// justifyContent: 'space-between'
// }}>
// <div style={{
// fontWeight: 600,
// fontSize: 20,
// color: '#333'
// }}>视频分析</div>
// <Upload name="logo" action="/api/upload_warning_info/" showUploadList={false} onChange={handleChange}>
// <Button type="primary"
// onClick={() => {
// // setCreateModalOpen(true);
// }}
// >
// {loading ? <LoadingOutlined /> : null}
// 导入视频
// </Button>
// </Upload>
// </div>
// }
>
<ProCard
className="gn"
bodyStyle={{ padding: 10, margin: 0 }}
style={{ padding: 0, margin: 0 }}
>
<Tabs
activeKey={tab}
items={tabs}
onChange={(key) => {
changeProjectTab(key);
}}
></Tabs>
<div style={{ padding: '16px 16px 0' }}>
<DatePicker locale={locale} value={importDate} onChange={onChange} allowClear />
<Button
type="primary"
style={{ margin: '0 16px' }}
onClick={() => {
// setCreateModalOpen(true);
setImportDate(null);
initList(tab, null);
}}
>
</Button>
<Button
type="primary"
onClick={() => {
// setCreateModalOpen(true);
initList(tab, innerDate);
}}
>
</Button>
</div>
<ProList<any>
className="gn"
ghost={true}
itemCardProps={{
ghost: true,
bodyStyle: { padding: 0, margin: 0 },
style: {
width: '100%',
border: 0,
// minHeight: 700
// padding: 0, margin: 0
},
}}
// search={{
// labelWidth: proTableCommonOptions.searchLabelWidth,
// }}
// headerTitle={
// <>
// <div>
// {Object.keys(tabOptions).map((item, index) => {
// // eslint-disable-next-line react/jsx-key
// return (
// <Button
// style={{ marginRight: 12,border: 'none' }}
// // type={activeTabIndex === index ? 'primary' : 'default'}
// key={index}
// onClick={() => {
// setActiveTabIndex(index);
// }}
// >
// {Object.keys(alarmVideoAnalysis).includes(item)
// ? alarmVideoAnalysis[item].miniName
// : ''}
// {"("+tabOptions[item]+ ')'}
// </Button>
// );
// })}
// </div>
// </>
// }
cardProps={{
bodyStyle: {
padding: '8px 16px 16px',
borderRadius: 8,
},
}}
pagination={{
...proTablePaginationOptions,
total: total,
current: currentPage,
pageSize: currentPageSize,
showSizeChanger: true,
onChange: (page, pageSize) => {
console.log(page, pageSize);
setCurrentPage(page);
setCurrentPageSize(pageSize);
},
}}
showActions="hover"
rowSelection={false}
grid={{ gutter: 16, xs: 1, md: 2, lg: 2, xl: 3, xxl: 3 }}
metas={{
type: {
// 不展示在筛选项
hideInSearch: true,
},
content: {
hideInSearch: true,
},
actions: {
cardActionProps: 'extra',
},
// status1: {
// // 自己扩展的字段,主要用于筛选,不在列表中显示
// title: '设备组',
// valueType: 'select',
// valueEnum: {
// '0': { text: '全部设备分组', status: '0' },
// '1': {
// text: '设备分组1',
// status: '1',
// },
// '2': {
// text: '设备分组2',
// status: '2',
// },
// '3': {
// text: '设备分组3',
// status: '3',
// },
// },
// },
// status2: {
// // 自己扩展的字段,主要用于筛选,不在列表中显示
// title: '分类',
// valueType: 'select',
// valueEnum: {
// '0': { text: '全部分类', status: '0' },
// '1': {
// text: '外围监控',
// status: '1',
// },
// '2': {
// text: '室内监控',
// status: '2',
// },
// '3': {
// text: '违规监控',
// status: '3',
// },
// },
// },
}}
dataSource={dataTestList}
/>
</ProCard>
<AlarmDetails
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={initList}
warning_type={tab}
/>
</PageContainer>
);
};
export default OfflineAlarmList;

@ -1,196 +0,0 @@
import { postOfflineAlarmRules } from '@/services/realTime/alarmRules';
import { ModalForm, ProForm, ProFormSwitch, ProFormText } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateAlarmRulesForm>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateAlarmRulesForm>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateAlarmRulesForm>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'alarm_rules.page.form.title',
defaultMessage: `编辑单人徘徊告警`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
values.id = props.values.id;
values.is_use = values.is_use ? 1 : 0;
// console.log(values);
await postOfflineAlarmRules(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormSwitch
width={proFormSmallItemStyleProps.column2Width}
name="is_use"
label={
<FormattedMessage id="alarm_rules.page.form.isEnabled" defaultMessage="启用告警" />
}
checkedChildren="启用"
unCheckedChildren="关闭"
initialValue={props.values.is_use}
disabled={false}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="warning_name"
label={<FormattedMessage id="alarm_rules.page.form.name" defaultMessage="告警名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.name',
defaultMessage: '告警名称',
})}`}
required={true}
initialValue={props.values.warning_name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.name"
defaultMessage="请填写告警名称"
/>
),
},
]}
/>
<div></div>
<div
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
}}
>
<span style={{ marginRight: 6 }}></span>
<ProFormText
width={100}
name="time_period"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.time_period}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.time_interval"
defaultMessage="请填写时间"
/>
),
},
]}
/>
<span style={{ margin: '0 6px' }}></span>
<ProFormText
width={100}
name="time_interval"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.time_interval}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.time_interval"
defaultMessage="请填写时间"
/>
),
},
]}
/>
<span style={{ marginRight: 6 }}></span>
<ProFormText
width={100}
name="appear_number"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.appear_number}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.appear_number"
defaultMessage="请填写次数"
/>
),
},
]}
/>
<span style={{ marginLeft: 6 }}></span>
</div>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -1,230 +0,0 @@
import { postOfflineAlarmRules } from '@/services/realTime/alarmRules';
import { ModalForm, ProForm, ProFormSwitch, ProFormText } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateAlarmRulesForm>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateAlarmRulesForm>;
reload: any;
};
const UpdateMultiForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateAlarmRulesForm>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'alarm_rules.page.form.multiTitle',
defaultMessage: `编辑${props.values.warning_name}`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
values.id = props.values.id;
values.is_use = values.is_use ? 1 : 0;
// console.log(values);
await postOfflineAlarmRules(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
{/* <ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="alarm_rules.page.form.enabled" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.enabled',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.enabled}
disabled={false}
/> */}
<ProFormSwitch
width={proFormSmallItemStyleProps.column2Width}
name="is_use"
label={
<FormattedMessage id="alarm_rules.page.form.isEnabled" defaultMessage="启用告警" />
}
checkedChildren="启用"
unCheckedChildren="关闭"
initialValue={props.values.is_use}
disabled={false}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="warning_name"
label={<FormattedMessage id="alarm_rules.page.form.name" defaultMessage="告警名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.name',
defaultMessage: '告警名称',
})}`}
required={true}
initialValue={props.values.warning_name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.name"
defaultMessage="请填写告警名称"
/>
),
},
]}
/>
<div></div>
<div
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
}}
>
<span style={{ marginRight: 6 }}></span>
<ProFormText
width={100}
name="person_number"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.person_number}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.person_number"
defaultMessage="请填写人数"
/>
),
},
]}
/>
<span style={{ margin: '0 6px' }}></span>
<ProFormText
width={100}
name="time_interval"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.time_interval',
defaultMessage: '时间',
})}`}
required={true}
initialValue={props.values.time_interval}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.time_interval"
defaultMessage="请填写时间"
/>
),
},
]}
/>
<span style={{ marginLeft: 6 }}></span>
</div>
{/* { timeStatus &&
<ProFormFieldSet
name="list"
label="触发条件"
type='space'
transform={(value: any) => ({
// list: value,
// startTime: value[0],
// endTime: value[1],
time_period: value[0],
time_interval: value[1],
appear_number: value[2],
})}
className={styles}
>
<ProFormText
width={100}
name="trigger_start_time"
label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_start_time}
disabled={false}
/>
<ProFormText
width={100}
name="trigger_end_time"
label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_end_time}
disabled={false}
/>
</ProFormFieldSet>} */}
</ProForm.Group>
</ModalForm>
);
};
export default UpdateMultiForm;

@ -1,229 +0,0 @@
import { postOfflineAlarmRules } from '@/services/realTime/alarmRules';
import {
ModalForm,
ProForm,
ProFormSwitch,
ProFormText,
ProFormTimePicker,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateAlarmRulesForm>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateAlarmRulesForm>;
reload: any;
};
const UpdateTimeForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateAlarmRulesForm>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'alarm_rules.page.form.timeTitle',
defaultMessage: `编辑${props.values.warning_name}`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
values.id = props.values.id;
values.is_use = values.is_use ? 1 : 0;
// console.log(values);
await postOfflineAlarmRules(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
{/* <ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="alarm_rules.page.form.enabled" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.enabled',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.enabled}
disabled={false}
/> */}
<ProFormSwitch
width={proFormSmallItemStyleProps.column2Width}
name="is_use"
label={
<FormattedMessage id="alarm_rules.page.form.isEnabled" defaultMessage="启用告警" />
}
checkedChildren="启用"
unCheckedChildren="关闭"
initialValue={props.values.is_use}
disabled={false}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="warning_name"
label={<FormattedMessage id="alarm_rules.page.form.name" defaultMessage="告警名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.name',
defaultMessage: '告警名称',
})}`}
required={true}
initialValue={props.values.warning_name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.name"
defaultMessage="请填写告警名称"
/>
),
},
]}
/>
<div
style={{
marginBottom: 6,
}}
>
</div>
<div
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
}}
>
<span style={{ marginRight: 6 }}></span>
<ProFormTimePicker
style={{
padding: '0 6px',
}}
width={100}
name="trigger_start_time"
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.trigger_start_time',
defaultMessage: '敏感开始时间',
})}`}
required={true}
initialValue={props.values.trigger_start_time}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.trigger_start_time"
defaultMessage="请填写时间"
/>
),
},
]}
/>
{/* <ProFormText
width={100}
name="trigger_start_time"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_start_time}
disabled={false}
/> */}
<span style={{ margin: '0 6px' }}></span>
<ProFormTimePicker
width={100}
name="trigger_end_time"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.trigger_end_time}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.trigger_start_time"
defaultMessage="请填写时间"
/>
),
},
]}
/>
{/* <ProFormText
width={100}
name="trigger_end_time"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_end_time}
disabled={false}
/> */}
<span style={{ marginLeft: 6 }}></span>
{/* <span style={{ marginLeft: 6 }}></span> */}
</div>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateTimeForm;

@ -1,7 +0,0 @@
:global {
.ant-form-item-control-input-content {
.ant-space-gap-col-small {
align-items: center;
}
}
}

@ -1,212 +0,0 @@
import TableActionCard from '@/components/TableActionCard';
import { getOfflineAlarmRules } from '@/services/realTime/alarmRules';
import { EditOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { FormattedMessage } from '@umijs/max';
import { Button, Tag } from 'antd';
import React, { useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
import UpdateForm from './components/UpdateForm';
import UpdateMultiForm from './components/UpdateMultiForm';
import UpdateTimeForm from './components/UpdateTimeForm';
const OfflineAlarmRules: React.FC = () => {
/**
* @en-US International configuration
* @zh-CN
* */
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentRow, setCurrentRow] = useState<API.DeviceCategory>();
// 编辑弹框
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const [updateMultiModalOpen, setUpdateMultiModalOpen] = useState<boolean>(false);
const [updateTimeModalOpen, setUpdateTimeModalOpen] = useState<boolean>(false);
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
const handleUpdateMultiModal = () => {
if (updateMultiModalOpen) {
setUpdateMultiModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateMultiModalOpen(true);
}
};
const handleUpdateTimeModal = () => {
setCurrentRow(undefined);
if (updateTimeModalOpen) {
setUpdateTimeModalOpen(false);
} else {
setUpdateTimeModalOpen(true);
}
};
const columns: ProColumns<API.DeviceCategory>[] = [
{
title: <FormattedMessage id="alarm_rules.page.name" defaultMessage="告警规则" />,
dataIndex: 'warning_name',
hideInSearch: true,
},
{
title: <FormattedMessage id="alarm_rules.page.id" defaultMessage="规则ID" />,
dataIndex: 'id',
hideInSearch: true,
},
{
title: <FormattedMessage id="alarm_rules.page.status" defaultMessage="规则状态" />,
dataIndex: 'is_use',
hideInSearch: true,
render: (dom) => {
return (
<Tag
bordered={false}
color={dom === 1 ? 'success' : ''}
style={{
// fontSize:14,
color: dom === 1 ? '#52C41A' : '#999',
}}
>
{dom === 1 ? '已启用' : '未启用'}
</Tag>
);
},
},
{
title: <FormattedMessage id="alarm_rules.page.updateTime" defaultMessage="修改时间" />,
dataIndex: 'update_time',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="操作" />,
dataIndex: 'option',
valueType: 'option',
fixed: 'right',
render: (_, record) => [
<TableActionCard
key="TableActionCardRef"
renderActions={[
{
key: 'update',
renderDom: (
<Button
key="update"
type="link"
size="small"
style={{
color: '#081FA8',
}}
icon={
<EditOutlined
style={{
marginRight: 3,
}}
/>
}
onClick={() => {
console.log(record);
if (record.id === 1) {
setUpdateModalOpen(true);
} else if (record.id === 2) {
setUpdateMultiModalOpen(true);
} else {
setUpdateTimeModalOpen(true);
}
setCurrentRow(record);
}}
>
<FormattedMessage id="common.edit" defaultMessage="编辑" />
</Button>
),
},
]}
></TableActionCard>,
],
},
];
return (
<PageContainer>
<ProTable<API.DeviceCategory>
cardProps={{
bodyStyle: {
padding: 20,
},
}}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
actionRef={actionRef}
rowKey="key"
search={false}
showSorterTooltip={false}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'device_category_list',
persistenceType: 'localStorage',
}}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams = {
page: current,
desc: false,
orderKey: '',
...rest,
};
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
// let resp = await postDeviceCategoryGetDeviceCategoryList({ ...reqParams });
let resp = await getOfflineAlarmRules(reqParams);
console.log(resp);
return {
data: resp.data.results.map((v: API.DeviceCategory) => {
return { ...v, key: v.id };
}),
success: resp.success,
total: resp.data.count,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
columns={columns}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={actionRef.current?.reload}
/>
<UpdateMultiForm
updateModalOpen={updateMultiModalOpen}
values={currentRow || {}}
handleModal={handleUpdateMultiModal}
reload={actionRef.current?.reload}
/>
<UpdateTimeForm
updateModalOpen={updateTimeModalOpen}
values={currentRow || {}}
handleModal={handleUpdateTimeModal}
reload={actionRef.current?.reload}
/>
</PageContainer>
);
};
export default OfflineAlarmRules;

@ -1,60 +0,0 @@
import { postTestDevice } from '@/services/realTime/interfaces';
import { RedoOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Tag, message } from 'antd';
import moment from 'moment';
import React, { useState } from 'react';
interface ImageSinglePopoverProps {
values: any;
reload: any;
}
const CaptureButton: React.FC<ImageSinglePopoverProps> = (props) => {
const intl = useIntl();
const [loading, setLoading] = useState<boolean>(false);
const connection = () => {
setLoading(true);
postTestDevice({
device_ip: props.values.device_ip,
id: props.values.id,
})
.then((res) => {
if (res.success) {
message.success(res.msg);
}
props.reload();
setLoading(false);
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
setLoading(false);
});
};
return (
<div>
<Tag
bordered={false}
color={props.values.test_result === 1 ? 'success' : ''}
style={{
// fontSize:14,
color: props.values.test_result === 1 ? '#52C41A' : '#999',
}}
>
{props.values.test_result === 1 ? '在线' : '离线'}
</Tag>
<span>{moment(props.values.test_time).format('YYYY-MM-DD hh:mm:ss')}</span>
<Button
type="link"
icon={<RedoOutlined />}
loading={loading}
onClick={() => {
connection();
}}
/>
</div>
);
};
export default CaptureButton;

@ -1,84 +0,0 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-02 17:41:57
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-02 17:46:32
* @FilePath: \uighur-recognition-web2\src\pages\Offline\OfflineDeviceList\components\CaptureForm.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { postInterfaces } from '@/services/realTime/interfaces';
import { ModalForm } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Form, Image, message } from 'antd';
import moment from 'moment';
import React from 'react';
import { proFormSmallModelWidth } from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateInterfacesParams>;
export type UpdateFormProps = {
captureModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateInterfacesParams>;
reload: any;
};
const CaptureForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateInterfacesParams>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device.interface_manage.table.list.capture',
defaultMessage: `最近拍摄`,
})}
open={props.captureModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
props.handleModal();
},
// okText: intl.formatMessage({ id: 'common.okText', defaultMessage: '确认' }),
// cancelText: intl.formatMessage({ id: 'common.cancelText', defaultMessage: '取消' }),
}}
submitTimeout={2000}
submitter={false}
onFinish={async (values) => {
console.log(values);
values.id = props.values.id;
postInterfaces(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<div>
<div>
: <span>{props.values.device_name}</span>
</div>
<div>
: <span>{moment(props.values.appear_time).format('YYYY-MM-DD hh:mm:ss')}</span>
</div>
<div>
<Image width={100} preview={false} src={props.values.picture_path} />
</div>
</div>
</ModalForm>
);
};
export default CaptureForm;

@ -1,698 +0,0 @@
/**
* @
*
*
*/
import { getInterfacesUpload, postInterfacesUpload } from '@/services/realTime/interfaces';
import {
ModalForm,
ProForm,
ProFormSelect,
ProFormText,
ProFormTextArea,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React, { useEffect, useState } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateInterfacesParams>;
export type CreateFormProps = {
createModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateInterfacesParams>;
reload: any;
};
const CreateForm: React.FC<CreateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateInterfacesParams>();
// const [loading, setLoading] = useState<boolean>(false);
const [fileType, setFileType] = useState<string>('1');
const [fileMethod, setFileMethod] = useState<number>(2);
const [methodName, setMethodName] = useState<string>('1');
const handleChangeFileType = async (value: number) => {
setFileMethod(value);
// 根据选择的获取方式更新第二个下拉框的值
if (value === 2) {
setMethodName('1'); // 设置为初始值 '0'只展示FTP选项
form.setFieldsValue({
operate_mode: '1', // 设置第二个下拉框的值
device_ip: '',
device_port: '',
device_username: '',
device_password: '',
source_directory: '',
});
} else if (value === 1) {
setMethodName('2'); // 设置为 '2'只展示FTP上传选项
form.setFieldsValue({
operate_mode: '2', // 设置第二个下拉框的值
});
await getInterfacesUpload({ templet: true }).then((resp) => {
const { data } = resp;
form.setFieldsValue({
device_ip: data.device_ip,
device_port: data.device_port,
device_username: data.device_username,
device_password: data.device_password,
destination_directory: data.destination_directory,
});
});
}
};
const handleChangeFile = (value: string) => {
setMethodName(value);
};
useEffect(() => {
if (fileMethod === 1 && methodName === '2') {
setFileType(() => {
return '3';
});
} else if (fileMethod === 2 && methodName === '3') {
setFileType(() => {
return '2';
});
} else {
setFileType(() => {
return '1';
});
}
}, [methodName, fileMethod]);
return (
<ModalForm<API.UpdateInterfacesParams>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device.interface_manage.table.list.addVideoSource',
defaultMessage: '新建视频源',
})}
open={props.createModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
// setLoading(false);
setFileMethod(2);
setMethodName('1');
props.handleModal();
},
okText: intl.formatMessage({ id: 'common.okText', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.cancelText', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values);
postInterfacesUpload(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
setFileMethod(2);
setMethodName('1');
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_name"
label={
<FormattedMessage
id="device.interface_manage.table.list.name"
defaultMessage="接口名称"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.name',
defaultMessage: '接口名称',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.name"
defaultMessage="接口名称为必填项"
/>
),
},
]}
/>
<div style={{ width: proFormSmallItemStyleProps.width }}>
<div style={{ marginBottom: 8 }}></div>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<ProFormSelect
width={250}
options={[
{
value: 2,
label: '文件拉取',
},
{
value: 1,
label: '文件上传',
},
]}
onChange={handleChangeFileType}
initialValue={fileMethod}
name="upload_or_download"
// label="获取方式"
/>
{/* <ProFormSelect
width={250}
options={
fileMethod === '2'
? [
{
value: '0',
label: 'FTP',
},
{
value: '1',
label: '文件系统',
},
]
: [
{
value: '2',
label: 'FTP上传',
},
]
}
initialValue={methodName}
onChange={handleChangeFile}
name="file"
// label="获取方式"
/> */}
<ProFormSelect
width={250}
options={[
{ value: '1', label: 'FTP' },
{ value: '3', label: '文件系统' },
{ value: '2', label: 'FTP上传' },
].filter((option) =>
fileMethod === 2 ? option.value !== '2' : option.value === '2',
)}
initialValue={methodName}
onChange={handleChangeFile}
name="operate_mode"
// label="获取方式"
/>
</div>
</div>
{/* <ProFormText
width={proFormSmallItemStyleProps.width - 96}
name="device_ip"
label={
<FormattedMessage id="device.interface_manage.table.list.ip" defaultMessage="IP地址" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.ip',
defaultMessage: 'IP地址',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.ip"
defaultMessage="IP地址为必填项"
/>
),
},
]}
addonAfter={
<Button
style={{ width:86,height:32,border:'1px solid #081FA8',borderRadius:4,fontSize: 14,color:'#081FA8' }}
loading={loading}
onClick={() => connection()}>
{ loading ? '' : '连接测试'}
</Button>
}
/> */}
{fileType === '1' && (
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_ip"
label={
<FormattedMessage
id="device.interface_manage.table.list.ip"
defaultMessage="IP地址"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.ip',
defaultMessage: '接口地址',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.ip"
defaultMessage="接口地址为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_port"
label={
<FormattedMessage
id="device.interface_manage.table.list.port"
defaultMessage="端口"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.port',
defaultMessage: '端口',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.port"
defaultMessage="端口为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_username"
label={
<FormattedMessage
id="device.interface_manage.table.list.loginName"
defaultMessage="登录名"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.loginName',
defaultMessage: '登录名',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.loginName"
defaultMessage="登录名为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_password"
label={
<FormattedMessage
id="device.interface_manage.table.list.password"
defaultMessage="密码"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.password',
defaultMessage: '密码',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.password"
defaultMessage="密码为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="source_directory"
label={
<FormattedMessage
id="device.interface_manage.table.list.fileDirectory"
defaultMessage="文件目录"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.fileDirectory',
defaultMessage: '文件目录',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.fileDirectory"
defaultMessage="文件目录为必填项"
/>
),
},
]}
/>
</ProForm.Group>
)}
{fileType === '2' && (
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_ip"
label={
<FormattedMessage
id="device.interface_manage.table.list.requestAddress"
defaultMessage="请求地址"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.requestAddress',
defaultMessage: '请求地址',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.requestAddress"
defaultMessage="请求地址为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="access_key_id"
label={
<FormattedMessage
id="device.interface_manage.table.list.requestKey"
defaultMessage="请求Key"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.requestKey',
defaultMessage: '请求Key',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.requestKey"
defaultMessage="请求Key为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="access_key_secret"
label={
<FormattedMessage
id="device.interface_manage.table.list.secretKey"
defaultMessage="秘钥"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.secretKey',
defaultMessage: '秘钥',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.secretKey"
defaultMessage="秘钥为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="bucket"
label={
<FormattedMessage
id="device.interface_manage.table.list.bucket"
defaultMessage="Bucket"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.bucket',
defaultMessage: 'Bucket',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.bucket"
defaultMessage="Bucket为必填项"
/>
),
},
]}
/>
</ProForm.Group>
)}
{fileType === '3' && (
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_ip"
label={
<FormattedMessage id="device.interface_manage.table.list.ip" defaultMessage="ip" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.ip',
defaultMessage: 'ip',
})}`}
disabled
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.ip"
defaultMessage="ip为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_port"
label={
<FormattedMessage
id="device.interface_manage.table.list.port"
defaultMessage="端口"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.port',
defaultMessage: '端口',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.port"
defaultMessage="端口为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_username"
label={
<FormattedMessage
id="device.interface_manage.table.list.loginName"
defaultMessage="登录名"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.loginName',
defaultMessage: '登录名',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.loginName"
defaultMessage="登录名为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_password"
label={
<FormattedMessage
id="device.interface_manage.table.list.password"
defaultMessage="密码"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.password',
defaultMessage: '密码',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.password"
defaultMessage="密码为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="destination_directory"
label={
<FormattedMessage
id="device.interface_manage.table.list.fileDirectory"
defaultMessage="文件目录"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.fileDirectory',
defaultMessage: '文件目录',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.fileDirectory"
defaultMessage="文件目录为必填项"
/>
),
},
]}
/>
</ProForm.Group>
)}
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="note"
label={
<FormattedMessage
id="device.interface_manage.table.list.remark"
defaultMessage="备注"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.remark',
defaultMessage: '备注',
})}`}
required={false}
/>
</ProForm.Group>
</ModalForm>
);
};
export default CreateForm;

@ -1,694 +0,0 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-02 17:57:23
* @FilePath: \general-ai-platform-web\src\pages\Device\DeviceCategoryList\components\UpdateForm.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { getInterfacesUpload, postInterfacesUpload } from '@/services/realTime/interfaces';
import {
ModalForm,
ProForm,
ProFormSelect,
ProFormText,
ProFormTextArea,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React, { useEffect, useState } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateInterfacesParams>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateInterfacesParams>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateInterfacesParams>();
const [fileType, setFileType] = useState<string>('1');
const [fileMethod, setFileMethod] = useState<number>(props.values.upload_or_download);
const [methodName, setMethodName] = useState<number>(props.values.operate_mode);
const handleChangeFileType = async (value: number) => {
setFileMethod(value);
// 根据选择的获取方式更新第二个下拉框的值
if (value === 2) {
setMethodName(1); // 设置为初始值 '0'只展示FTP选项
form.setFieldsValue({
operate_mode: 1, // 设置第二个下拉框的值
device_ip: props.values.device_ip,
device_port: props.values.device_port,
device_username: props.values.device_username,
device_password: props.values.device_password,
source_directory: props.values.source_directory,
});
} else if (value === 1) {
setMethodName(2); // 设置为 '2'只展示FTP上传选项
form.setFieldsValue({
operate_mode: 2, // 设置第二个下拉框的值
});
await getInterfacesUpload({ templet: true }).then((resp) => {
const { data } = resp;
form.setFieldsValue({
device_ip: data.device_ip,
device_port: data.device_port,
device_username: data.device_username,
device_password: data.device_password,
destination_directory: data.destination_directory,
});
});
}
};
const handleChangeFile = (value: number) => {
setMethodName(value);
};
useEffect(() => {
if (fileMethod === 1 && methodName === 2) {
setFileType(() => {
return '3';
});
} else if (fileMethod === 2 && methodName === 3) {
setFileType(() => {
return '2';
});
} else {
setFileType(() => {
return '1';
});
}
}, [methodName, fileMethod]);
useEffect(() => {
setFileMethod(props.values.upload_or_download);
setMethodName(props.values.operate_mode);
if (fileMethod === 1 && methodName === 2) {
setFileType(() => {
return '3';
});
} else if (fileMethod === 2 && methodName === 3) {
setFileType(() => {
return '2';
});
} else {
setFileType(() => {
return '1';
});
}
}, [props.updateModalOpen]);
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device.interface_manage.table.list.updatVideoSource',
defaultMessage: `编辑${props.values.device_name}`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
props.handleModal();
},
okText: intl.formatMessage({ id: 'common.okText', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.cancelText', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values);
values.id = props.values.id;
postInterfacesUpload(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_name"
label={
<FormattedMessage
id="device.interface_manage.table.list.name"
defaultMessage="接口名称"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.name',
defaultMessage: '接口名称',
})}`}
initialValue={props.values.device_name}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.name"
defaultMessage="接口名称为必填项"
/>
),
},
]}
/>
<div style={{ width: proFormSmallItemStyleProps.width }}>
<div style={{ marginBottom: 8 }}></div>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<ProFormSelect
width={250}
options={[
{
value: 2,
label: '文件拉取',
},
{
value: 1,
label: '文件上传',
},
]}
onChange={handleChangeFileType}
initialValue={props.values.upload_or_download}
name="upload_or_download"
// label="获取方式"
/>
{/* <ProFormSelect
width={250}
options={
fileMethod === 2
? [
{
value: 0,
label: 'FTP',
},
{
value: 1,
label: '文件系统',
},
]
: [
{
value: 2,
label: 'FTP上传',
},
]
}
initialValue={props.values.operate_mode}
onChange={handleChangeFile}
name="file"
// label="获取方式"
/> */}
<ProFormSelect
width={250}
options={[
{ value: 1, label: 'FTP' },
{ value: 2, label: 'FTP上传' },
{ value: 3, label: '文件系统' },
].filter((option) => (fileMethod === 2 ? option.value !== 2 : option.value === 2))}
initialValue={props.values.operate_mode}
onChange={handleChangeFile}
name="operate_mode"
// label="获取方式"
/>
</div>
</div>
{fileType === '1' && (
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_ip"
label={
<FormattedMessage
id="device.interface_manage.table.list.ip"
defaultMessage="IP地址"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.ip',
defaultMessage: '接口地址',
})}`}
required={true}
initialValue={props.values.device_ip}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.ip"
defaultMessage="接口地址为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_port"
label={
<FormattedMessage
id="device.interface_manage.table.list.port"
defaultMessage="端口"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.port',
defaultMessage: '端口',
})}`}
initialValue={props.values.device_port}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.port"
defaultMessage="端口为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_username"
label={
<FormattedMessage
id="device.interface_manage.table.list.loginName"
defaultMessage="登录名"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.loginName',
defaultMessage: '登录名',
})}`}
initialValue={props.values.device_username}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.loginName"
defaultMessage="登录名为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_password"
label={
<FormattedMessage
id="device.interface_manage.table.list.password"
defaultMessage="密码"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.password',
defaultMessage: '密码',
})}`}
initialValue={props.values.device_password}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.password"
defaultMessage="密码为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="source_directory"
label={
<FormattedMessage
id="device.interface_manage.table.list.fileDirectory"
defaultMessage="文件目录"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.fileDirectory',
defaultMessage: '文件目录',
})}`}
initialValue={props.values.source_directory}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.fileDirectory"
defaultMessage="文件目录为必填项"
/>
),
},
]}
/>
</ProForm.Group>
)}
{fileType === '2' && (
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_ip"
label={
<FormattedMessage
id="device.interface_manage.table.list.requestAddress"
defaultMessage="请求地址"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.requestAddress',
defaultMessage: '请求地址',
})}`}
initialValue={props.values.device_ip}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.requestAddress"
defaultMessage="请求地址为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="access_key_id"
label={
<FormattedMessage
id="device.interface_manage.table.list.requestKey"
defaultMessage="请求Key"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.requestKey',
defaultMessage: '请求Key',
})}`}
initialValue={props.values.access_key_id}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.requestKey"
defaultMessage="请求Key为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="access_key_secret"
label={
<FormattedMessage
id="device.interface_manage.table.list.secretKey"
defaultMessage="秘钥"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.secretKey',
defaultMessage: '秘钥',
})}`}
initialValue={props.values.access_key_secret}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.secretKey"
defaultMessage="秘钥为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="bucket"
label={
<FormattedMessage
id="device.interface_manage.table.list.bucket"
defaultMessage="Bucket"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.bucket',
defaultMessage: 'Bucket',
})}`}
initialValue={props.values.bucket}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.bucket"
defaultMessage="Bucket为必填项"
/>
),
},
]}
/>
</ProForm.Group>
)}
{fileType === '3' && (
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_ip"
label={
<FormattedMessage id="device.interface_manage.table.list.ip" defaultMessage="ip" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.ip',
defaultMessage: 'ip',
})}`}
disabled
initialValue={props.values.device_ip}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.ip"
defaultMessage="ip为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_port"
label={
<FormattedMessage
id="device.interface_manage.table.list.port"
defaultMessage="端口"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.port',
defaultMessage: '端口',
})}`}
initialValue={props.values.device_port}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.port"
defaultMessage="端口为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_username"
label={
<FormattedMessage
id="device.interface_manage.table.list.loginName"
defaultMessage="登录名"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.loginName',
defaultMessage: '登录名',
})}`}
initialValue={props.values.device_username}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.loginName"
defaultMessage="登录名为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width / 2 - 8}
name="device_password"
label={
<FormattedMessage
id="device.interface_manage.table.list.password"
defaultMessage="密码"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.password',
defaultMessage: '密码',
})}`}
initialValue={props.values.device_password}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.password"
defaultMessage="密码为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="destination_directory"
label={
<FormattedMessage
id="device.interface_manage.table.list.fileDirectory"
defaultMessage="文件目录"
/>
}
disabled
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.fileDirectory',
defaultMessage: '文件目录',
})}`}
initialValue={props.values.destination_directory}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.fileDirectory"
defaultMessage="文件目录为必填项"
/>
),
},
]}
/>
</ProForm.Group>
)}
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="note"
label={
<FormattedMessage
id="device.interface_manage.table.list.remark"
defaultMessage="备注"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.remark',
defaultMessage: '备注',
})}`}
initialValue={props.values.note}
required={false}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -1,348 +0,0 @@
import TableActionCard from '@/components/TableActionCard';
import IsDelete from '@/components/TableActionCard/isDelete';
import { getInterfacesUpload, postInterfacesUpload } from '@/services/realTime/interfaces';
import { EditOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Button, Tag, message } from 'antd';
import moment from 'moment';
import React, { useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
import CaptureForm from './components/CaptureForm';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
const OfflineDeviceList: React.FC = () => {
/**
* @en-US International configuration
* @zh-CN
* */
const intl = useIntl();
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const handleDestroy = async (selectedRow: API.UpdateInterfacesParams) => {
postInterfacesUpload({ id: selectedRow.id, device_status: '3' })
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
actionRef.current?.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
};
const [currentRow, setCurrentRow] = useState<API.UpdateInterfacesParams>();
/**
* @en-US Pop-up window of new window
* @zh-CN
* */
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
const handleCreateModal = () => {
if (createModalOpen) {
setCreateModalOpen(false);
setCurrentRow(undefined);
} else {
setCreateModalOpen(true);
}
};
// 编辑弹框
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
// 最近拍摄
const [captureModalOpen, setCaptureModalOpen] = useState<boolean>(false);
const handleCaptureModal = () => {
console.log(captureModalOpen);
if (captureModalOpen) {
setCaptureModalOpen(false);
setCurrentRow(undefined);
} else {
setCaptureModalOpen(true);
}
};
// 测试连接
// const [loading, setLoading] = useState<boolean>(false);
const columns: ProColumns<API.UpdateInterfacesParams>[] = [
{
title: (
<FormattedMessage
id="device.interface_manage.table.list.videoName"
defaultMessage="接口名称"
/>
),
dataIndex: 'device_name',
hideInSearch: true,
},
{
title: (
<FormattedMessage
id="device.interface_manage.table.list.obtainMode"
defaultMessage="获取方式"
/>
),
dataIndex: 'operate_mode',
hideInSearch: true,
render: (dom) => {
return (
<div>
{dom === 1 && 'FTP'}
{dom === 2 && 'FTP上传'}
{dom === 3 && '文件系统'}
</div>
);
},
},
{
title: (
<FormattedMessage
id="device.interface_manage.table.list.obtainStatus"
defaultMessage="设备状态"
/>
),
dataIndex: 'test_result',
hideInSearch: true,
render: (dom, entity) => {
return (
<div>
<Tag
bordered={false}
color={dom === 1 ? 'success' : ''}
style={{
// fontSize:14,
color: dom === 1 ? '#52C41A' : '#999',
}}
>
{dom === 1 ? '获取成功' : '获取失败'}
</Tag>
<span>{moment(entity.create_time).format('YYYY-MM-DD hh:mm:ss')}</span>
{/* <Button
type="link"
icon={<RedoOutlined />}
loading={loading}
onClick={() => {
connection(entity)
}}
/> */}
</div>
// <CaptureButton
// values={entity || {}}
// reload={actionRef.current?.reload}
// />
);
},
},
// {
// title: <FormattedMessage id="device.interface_manage.table.list.address" defaultMessage="接口地址" />,
// dataIndex: 'device_api',
// hideInSearch: true,
// },
// {
// title: <FormattedMessage id="device.interface_manage.table.list.testTime" defaultMessage="状态查询时间" />,
// dataIndex: 'test_time',
// sorter: true,
// hideInSearch: true,
// valueType: 'dateTime',
// },
{
title: (
<FormattedMessage
id="device.interface_manage.table.list.createTime"
defaultMessage="创建时间"
/>
),
dataIndex: 'create_time',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="操作" />,
dataIndex: 'option',
valueType: 'option',
width: '260px',
fixed: 'right',
render: (_, record) => [
<TableActionCard
key="TableActionCardRef"
renderActions={[
// {
// key: 'capture',
// renderDom: (
// <Button
// key="capture"
// type="link"
// size="small"
// style={{
// color:"#081FA8",
// }}
// icon={<InstagramOutlined style={{
// marginRight: 3
// }} />}
// onClick={() => {
// console.log('11');
// setCaptureModalOpen(true);
// setCurrentRow(record);
// }}
// >
// {/* 最近拍摄 */}
// <FormattedMessage id="device.interface_manage.table.list.capture" defaultMessage="最近拍摄" />
// </Button>
// ),
// },
{
key: 'update',
renderDom: (
<Button
key="update"
type="link"
size="small"
style={{
color: '#081FA8',
}}
icon={
<EditOutlined
style={{
marginRight: 3,
}}
/>
}
onClick={() => {
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<FormattedMessage id="common.edit" defaultMessage="编辑" />
</Button>
),
},
{
key: 'destroy',
renderDom: (
<IsDelete
deleteApi={() => {
handleDestroy(record).then(() => {});
}}
></IsDelete>
),
},
]}
></TableActionCard>,
],
},
];
return (
<PageContainer
title={false}
content={
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
<div
style={{
fontWeight: 600,
fontSize: 20,
color: '#333',
}}
>
线
</div>
<Button
type="primary"
onClick={() => {
setCreateModalOpen(true);
}}
>
<FormattedMessage
id="device.interface_manage.table.list.addVideoSource"
defaultMessage="新建视频源"
/>
</Button>
</div>
}
>
<ProTable<API.DeviceCategory>
cardProps={{
bodyStyle: {
padding: 20,
},
}}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
actionRef={actionRef}
rowKey="key"
search={false}
showSorterTooltip={false}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'device_category_list',
persistenceType: 'localStorage',
}}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams = {
page: current,
desc: false,
orderKey: '',
...rest,
};
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
// let resp = await postDeviceCategoryGetDeviceCategoryList({ ...reqParams });
let resp = await getInterfacesUpload({ ...reqParams });
return {
data: resp.data.results.map((v: API.DeviceCategory) => {
return { ...v, key: v.id };
}),
success: resp.success,
total: resp.data.count,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
columns={columns}
/>
<CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={actionRef.current?.reload}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={actionRef.current?.reload}
/>
<CaptureForm
captureModalOpen={captureModalOpen}
values={currentRow || {}}
handleModal={handleCaptureModal}
reload={actionRef.current?.reload}
/>
</PageContainer>
);
};
export default OfflineDeviceList;

@ -2,17 +2,18 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-19 14:24:57
* @LastEditTime: 2024-04-22 10:15:41
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\businessCard.tsx
* @Description:
*/
import TableActionCard, { actionsProps } from '@/components/TableActionCard';
import { useBusinessInfo } from '@/hooks/useBusinessInfo';
import { useMoment } from '@/hooks/useMoment';
import { history } from '@umijs/max';
import { ReactComponent as BusinessLogoIcon } from '/public/home/business_logo.svg';
import { ReactComponent as DeviceCountIcon } from '/public/home/device_count_icon.svg';
import { ReactComponent as ModelCountIcon } from '/public/home/model_count_icon.svg';
import { ReactComponent as TimeIcon } from '/public/home/time_icon.svg';
// import { history } from '@umijs/max';
type BusinessCardProps = {
info: Record<string, any>;
@ -21,11 +22,13 @@ type BusinessCardProps = {
const BusinessCard: React.FC<BusinessCardProps> = ({ info, renderActions }) => {
const { formatTimeByDateType } = useMoment();
const { setStoreBusinessInfo } = useBusinessInfo();
return (
<div
className="w-full bp_card_box"
onClick={() => {
// history.push(`/realTime/involved-list?id=${info.id}`)
setStoreBusinessInfo(info);
history.push(`/business/index?id=${info.id}`);
console.log('跳转企业');
}}
>

@ -1,84 +0,0 @@
.alarmImgBox {
// display: flex;
// justify-content: flex-start;
.alarmImgLeft {
position: relative;
width: 120px;
margin-right: 32px;
// height: 600px;
.alarmImgLeftBox {
width: 112px;
height: 112px;
border-radius: 4px;
// background: skyblue;
}
.alarmImgLeftBoxActive {
width: 112px;
height: 112px;
border: 1.5px solid #081fa8;
border-radius: 4px;
}
.shadowBox {
position: absolute;
bottom: 0px;
left: 0;
z-index: 999;
width: 112px;
height: 20px;
background: #fff;
}
}
.alarmImgRight {
position: relative;
flex: 1;
.alarmImgRightTopBox {
width: 640px;
height: 640px;
background: skyblue;
}
.alarmDetails {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 38px;
margin-bottom: 16px;
padding-left: 24px;
color: #ffffff;
font-weight: 400;
font-size: 16px;
font-family: PingFang SC;
line-height: 38px;
background: rgba(0, 0, 0, 0.6);
.alarmSpan {
// color: #333;
margin-right: 24px;
}
}
}
.alarmImgDescribe {
margin-bottom: 12px;
color: #666;
font-weight: 500;
font-size: 16px;
font-family: PingFang SC;
span {
color: #333;
}
}
.alarmImgContent {
display: flex;
justify-content: center;
box-sizing: border-box;
width: 784px;
margin-bottom: 24px;
padding: 16px;
// height: 172px;
background: #f7f7f7;
border: 1px dashed #dcdcdc;
border-radius: 4px;
}
}
.myButtonDisabled {
visibility: hidden;
}

@ -1,293 +0,0 @@
import { postIgnoringvents } from '@/services/realTime/alarmlist';
import { postRecognition } from '@/services/realTime/involved';
import { ModalForm } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Form, message } from 'antd';
import React, { useEffect, useState } from 'react';
// Import Swiper React components
// import { Swiper, SwiperSlide } from 'swiper/react';
// import { Navigation, Pagination, Mousewheel } from 'swiper/modules';
// Import Swiper styles
// import 'swiper/css';
// import 'swiper/css/navigation';
// import 'swiper/css/pagination';
import moment from 'moment';
import styles from './AlarmDetails.less';
import ImageSinglePopover from './ImageSinglePopover';
import ImageWithPopover from './ImageWithPopover';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.AlarmDetailsParams>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.AlarmDetailsParams>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.AlarmDetailsParams>();
// const [isActive, setIsActive] = useState(0);
// const [imageSrc, setImageSrc] = useState('');
// const [visible, setVisible] = useState(false);
const [involved, setInvolved] = useState(0);
// const [involvedInfo, setInvolvedInfo] = useState([...(props?.values?.person_list || [])]);
const [involvedInfo, setInvolvedInfo] = useState<any[]>([]);
useEffect(() => {
if (props.values?.person_list) {
setInvolvedInfo([...props.values.person_list]);
}
}, [props.values?.person_list]);
useEffect(() => {
if (props.values?.person_classify) {
setInvolved(props.values.person_classify);
console.log(involved);
}
}, [props.values?.person_classify]);
const handlePostRecognition = (person_id: any, classify: any) => {
postRecognition({
person_id: person_id,
classify: classify,
})
.then((res) => {
console.log(res.data.classify, 'res.data.classify');
if (res.data.classify === 1) {
message.success('此人已被设为重点关注');
} else {
message.success('此人已被移除重点关注');
}
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
};
/** 多人告警组件 */
const handleInvolved = (value: any, index: any) => {
const updatedInvolvedInfo = [...involvedInfo];
console.log(updatedInvolvedInfo);
updatedInvolvedInfo[index][2] = value;
setInvolvedInfo(updatedInvolvedInfo);
handlePostRecognition(updatedInvolvedInfo[index][0], value);
};
/** 单人告警组件 */
// const handleSingleInvolved = () => {
// if (involved === 1) {
// setInvolved(0);
// handlePostRecognition(props.values?.person_id, 0)
// } else {
// setInvolved(1);
// handlePostRecognition(props.values?.person_id, 1)
// }
// }
// const [open, setOpen] = useState(false);
// useEffect(() => {
// // console.log(Array.isArray(props.values?.person_id),'Array.isArray(props.values?.person_id)');
// setImageSrc(props?.values?.picture_path?.[0]);
// }, [props.updateModalOpen]);
return (
<ModalForm<any>
width={832}
title={`${props.values.warning_name}告警`}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
setInvolved(0);
props.handleModal();
},
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitter={{
// resetButtonProps: {
// style: {
// display: 'none',
// },
// },
// searchConfig: {
// submitText: '忽略此事件',
// },
render: (prop) => {
return [
<Button
key="ok"
style={{ backgroundColor: '#E80D0D', color: '#FFF', borderBlockColor: '#E80D0D' }}
onClick={() => {
prop.submit();
}}
>
</Button>,
props.values?.person_list ? null : (
<Button
key="involved"
style={{ backgroundColor: '#FAAD14', color: '#FFF', borderBlockColor: '#FAAD14' }}
onClick={() => {
// console.log(props.updateModalOpen);
setInvolved(1);
handlePostRecognition(props.values?.person_id, 1);
}}
>
</Button>
),
props.values?.person_list ? null : (
<Button
key="noInvolved"
style={{ background: '#FFF', color: '#E80D0D', borderColor: '#E80D0D' }}
onClick={() => {
// console.log(props.updateModalOpen);
setInvolved(0);
handlePostRecognition(props.values?.person_id, 0);
}}
>
</Button>
),
];
},
}}
submitTimeout={2000}
onFinish={async (values) => {
values.is_ignore = true;
values.person_id = props.values.person_id;
// console.log(values);
postIgnoringvents(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
{/* <ProForm.Group> */}
<div className={styles.alarmImgBox}>
<div className={styles.alarmImgDescribe}>
: <span>{props.values.device_name}</span>
</div>
<div className={styles.alarmImgDescribe}>
:{' '}
<span className={styles.alarmSpan}>
{moment(props.values.trigger_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
<div className={styles.alarmImgContent}>
{Array.isArray(props.values?.person_id)
? Array.isArray(involvedInfo) && involvedInfo.length
? involvedInfo.map((item: any, index: any) => {
return (
<ImageWithPopover
src={item?.[1]}
involved={involvedInfo[index][2]}
key={index}
indexId={index}
handleInvolved={handleInvolved}
time={props.values.trigger_time}
></ImageWithPopover>
);
})
: Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length
? props.values.picture_path.map((item: any, index: any) => {
return (
<ImageSinglePopover
src={item}
involved={involved}
key={index}
// handleInvolved={handleSingleInvolved}
reload={props.reload} // 将reload方法作为prop传递给ImageSinglePopover组件
time={props.values.trigger_time}
></ImageSinglePopover>
);
})
: null
: Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length
? props.values.picture_path.map((item: any, index: any) => {
return (
<ImageSinglePopover
src={item}
involved={involved}
key={index}
// handleInvolved={handleSingleInvolved}
reload={props.reload} // 将reload方法作为prop传递给ImageSinglePopover组件
time={props.values.trigger_time}
></ImageSinglePopover>
);
})
: null}
{/* { Array.isArray(involvedInfo) && involvedInfo.length && involvedInfo.map((item: any, index: any) => {
console.log(involvedInfo,'item');
return(<ImageWithPopover src={item?.[1]} involved={involvedInfo[index][2]} key={index} indexId={index} handleInvolved={handleInvolved}></ImageWithPopover>)
})} */}
</div>
{/* <div className={styles.alarmImgLeft}>
<Swiper
style={{height:660}}
slidesPerView={5}
spaceBetween={20}
direction='vertical'
mousewheel={true}
modules={[Mousewheel]}
onSlideChange={() => {
console.log(111);
}}
// pagination={{
// clickable: true,
// }}
// modules={[Pagination]}
>
{ Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length && props?.values?.picture_path.map((item: any, index: any) => {
return (<SwiperSlide key={index} virtualIndex={index} onClick={() => {
console.log(index);
setIsActive(index)
setImageSrc(item)
}}>
<div className={ styles.alarmImgLeftBox }>
<Image
style={{
width: 112,
height: 112,
borderRadius: 4
}}
className={ index === isActive ? styles.alarmImgLeftBoxActive : '' }
preview={false}
src={item}
/>
</div>
</SwiperSlide>)
})}
</Swiper>
<div className={styles.shadowBox}></div>
</div>
<div className={styles.alarmImgRight}>
<div className={styles.alarmImgRightTopBox}>
<Image
width={640}
height={640}
preview={false}
src={imageSrc}
/>
</div>
<div className={styles.alarmDetails}>
: <span className={styles.alarmSpan}>{props.values.device_name}</span>: <span className={styles.alarmSpan}>{moment(props.values.trigger_time).format('YYYY-MM-DD hh:mm:ss')}</span>
</div>
</div> */}
</div>
{/* </ProForm.Group> */}
</ModalForm>
);
};
export default UpdateForm;

@ -1,147 +0,0 @@
import { EyeOutlined } from '@ant-design/icons';
import { Image } from 'antd';
import moment from 'moment';
import React, { useState } from 'react';
interface ImageSinglePopoverProps {
src: string;
involved: any;
// handleInvolved: () => void;
reload: any;
time: any;
}
const ImageSinglePopover: React.FC<ImageSinglePopoverProps> = ({ src, involved, time }) => {
const [visible, setVisible] = useState(false);
// const [open, setOpen] = useState(false);
// 定义一个方法,用于生成自定义的遮罩层
const generateMask = (text: any) => (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#fff',
}}
>
<div style={{ display: 'flex', alignItems: 'center', fontSize: 12 }}>
<EyeOutlined style={{ marginRight: 8, fontSize: 12 }} />
<div>{text}</div>
</div>
</div>
);
// const content = (
// <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center',alignItems: 'center', height: 56}}>
// {/* <div>选项1</div>
// <div>选项2</div> */}
// <Button
// type="text"
// style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
// icon={<InfoCircleOutlined style={{ color: '#FAAD14',fontSize: 12}} />}
// onClick={()=>{
// // setInvolved(true)
// // handleInvolved();
// // reload()
// setOpen(false)
// }}
// >加入重点关注</Button>
// <Button
// type="text"
// style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
// icon={<CloseCircleOutlined style={{ color: '#E80D0D',fontSize: 12}} />}
// onClick={()=>{
// // setInvolved(false)
// // handleInvolved();
// // reload()
// setOpen(false)
// }}
// >移除重点关注</Button>
// </div>
// );
const handleVisibleChange = (value: boolean) => {
setVisible(value);
};
// const handleOpenChange = (value: boolean) => {
// setOpen(value);
// };
return (
<div
style={{
position: 'relative',
boxSizing: 'border-box',
width: 140,
height: 160,
marginRight: 12,
}}
>
<Image
style={{ borderRadius: 4 }}
width={140}
height={140}
preview={{
visible,
src,
onVisibleChange: handleVisibleChange,
mask: generateMask('点击可预览大图'),
}}
src={src}
/>
<div
style={{
height: 30,
textAlign: 'center',
lineHeight: '30px',
fontWeight: 500,
color: '#333',
}}
>
{moment(time).format('YYYY-MM-DD hh:mm:ss')}
</div>
{/* <Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 64 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 64, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 8, right: 0 }}
type="text"
icon={<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />}
/>
</Popover> */}
{involved === 1 && (
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px',
}}
>
</div>
)}
</div>
);
};
export default ImageSinglePopover;

@ -1,170 +0,0 @@
import {
CloseCircleOutlined,
EllipsisOutlined,
EyeOutlined,
InfoCircleOutlined,
} from '@ant-design/icons';
import { Button, Image, Popover } from 'antd';
import moment from 'moment';
import React, { useState } from 'react';
interface ImageWithPopoverProps {
src: string;
involved: any;
indexId: any;
handleInvolved: (value: any, index: any) => void;
time: any;
}
const ImageWithPopover: React.FC<ImageWithPopoverProps> = ({
src,
involved,
indexId,
handleInvolved,
time,
}) => {
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
// 定义一个方法,用于生成自定义的遮罩层
const generateMask = (text: any) => (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: '#fff',
}}
>
<div style={{ display: 'flex', alignItems: 'center', fontSize: 12 }}>
<EyeOutlined style={{ marginRight: 8, fontSize: 12 }} />
<div>{text}</div>
</div>
</div>
);
const content = (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: 56,
}}
>
{/* <div>1</div>
<div>2</div> */}
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF', marginBottom: 4 }}
icon={<InfoCircleOutlined style={{ color: '#FAAD14', fontSize: 12 }} />}
onClick={() => {
// setInvolved(true)
handleInvolved(1, indexId);
setOpen(false);
}}
>
</Button>
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF' }}
icon={<CloseCircleOutlined style={{ color: '#E80D0D', fontSize: 12 }} />}
onClick={() => {
// setInvolved(false)
handleInvolved(0, indexId);
setOpen(false);
}}
>
</Button>
</div>
);
const handleVisibleChange = (value: boolean) => {
setVisible(value);
};
const handleOpenChange = (value: boolean) => {
setOpen(value);
};
return (
<div
style={{
position: 'relative',
boxSizing: 'border-box',
width: 140,
height: 160,
marginRight: 12,
}}
>
<Image
style={{ borderRadius: 4 }}
width={140}
height={140}
preview={{
visible,
src,
onVisibleChange: handleVisibleChange,
mask: generateMask('点击可预览大图'),
}}
src={src}
/>
<Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 64 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 68, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 20, right: 0 }}
type="text"
icon={
<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />
}
/>
</Popover>
<div
style={{
height: 30,
textAlign: 'center',
lineHeight: '30px',
fontWeight: 500,
color: '#333',
}}
>
{moment(time).format('YYYY-MM-DD hh:mm:ss')}
</div>
{involved === 1 && (
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px',
}}
>
</div>
)}
</div>
);
};
export default ImageWithPopover;

@ -1,425 +0,0 @@
import { alarmRulesEnums } from '@/enums/status';
import { PageContainer, ProCard, ProList } from '@ant-design/pro-components';
import { Image, Tabs } from 'antd';
import React, { useEffect, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
// import DeviceStatusCard from './components/DeviceStatusCard';
// import CreateForm from './components/CreateForm';
import { useMoment } from '@/hooks/useMoment';
import { postAlarmList } from '@/services/realTime/alarmlist';
import AlarmDetails from './components/AlarmDetails';
/**
* @
* 1
*/
// const tabOptions: Record<string, any> = {
// singlePersonHoveringAlarm: 90,
// multiplePersonGatheringAlarm: 20,
// sensitiveTimePeriodAlarm: 20,
// ignored: 2,
// // processingStatus: 10,
// // errorStatus: 20,
// };
// export type DeleteBoxProps = {
// modalOpen: boolean;
// handleModal: () => void;
// values: any;
// reload: any;
// };
// eslint-disable-next-line react-hooks/rules-of-hooks
const { formatTimeByDateType } = useMoment();
const AlarmList: React.FC = () => {
/**
* @en-US Pop-up window of new window
* @zh-CN
* */
// const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
// const [modalOpen, setModalOpen] = useState(false);
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
/**
* @en-US International configuration
* @zh-CN
* */
// const access = useAccess();
// const intl = useIntl();
// const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentPage, setCurrentPage] = useState<number>(1);
const [total, setTotal] = useState<number>(0);
// const [activeTabIndex, setActiveTabIndex] = useState<number>(0);
const [dataTestList, setdataTestList] = useState<any>([]);
const [tab, setTab] = useState<string>(alarmRulesEnums[0].key);
const [tabs, setTabs] = useState<any>([]);
const changeProjectTab = (key: string) => {
setTab(key);
console.log(key);
// eslint-disable-next-line @typescript-eslint/no-use-before-define
initList(key);
};
const getTabs = () => {
// if (alarmRulesEnums.length) {
// setTab(alarmRulesEnums[0].key);
// }
setTabs(alarmRulesEnums);
};
// useEffect(() => {
// getTabs();
// }, []);
// const handleCreateModal = () => {
// if (createModalOpen) {
// setCreateModalOpen(false);
// setCurrentRow(undefined);
// } else {
// setCreateModalOpen(true);
// }
// };
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
// const handleDestroy = async () => {
// if (modalOpen) {
// setModalOpen(false);
// setCurrentRow(undefined);
// } else {
// setModalOpen(true);
// }
// // deleteBusinessImageDeleteBusinessImage({ id: selectedRow.id })
// // .then(() => {
// // message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
// // actionRef.current?.reload();
// // })
// // .catch(() => {
// // message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
// // });
// };
// const { confirm } = Modal;
// const showConfirm = (record: any) => {
// confirm({
// title: `确定删除${record.name}吗`,
// icon: <QuestionCircleFilled />,
// content: '确定删除服务器1吗删除后将找不到此服务器请谨慎操作.',
// okText: '确认',
// cancelText: '取消',
// width: 560,
// onOk() {
// console.log('OK');
// },
// onCancel() {
// console.log('Cancel');
// },
// });
// };
// 处理初始值
function initDataTestList(dataList: Record<string, any>[]) {
console.log(dataList, 'initDataTestList');
let finalList: { content: React.JSX.Element }[] = [];
if (Array.isArray(dataList) && dataList.length) {
finalList = dataList.map((record, index) => {
return {
content: (
<ProCard
className="gn"
style={{ backgroundColor: '#F5F6FF', margin: 0, padding: 0, borderRadius: 4 }}
bodyStyle={{ margin: 0, padding: 0 }}
>
<div
style={{
display: 'flex',
alignItems: 'center',
padding: 20,
justifyContent: 'flex-start',
}}
onClick={() => {
console.log(index, 'index');
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<Image width={96} height={96} preview={false} src={record.picture_path[0]} />
<div
style={{
marginLeft: 16,
height: 90,
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
color: '#666',
}}
>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{record.warning_name}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{record.device_name}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{formatTimeByDateType(record.trigger_time)}
</span>
</div>
</div>
</div>
</ProCard>
),
};
});
}
setdataTestList(() => [...finalList]);
}
// 初始化加载
async function initList(tabId: string = tab) {
const reqParams = {
page: currentPage,
pageSize: currentPageSize,
// desc: false,
warning_type: tabId,
// ...rest,
};
const resp = await postAlarmList({ ...reqParams });
// console.log(resp,'resp');
// setCurrentPageSize(resp?.data?.count)
setTotal(resp?.data?.count);
initDataTestList(resp?.data?.results);
// request={async (params = {}, sort) => {
// const { current, ...rest } = params;
// const reqParams = {
// page: current,
// desc: false,
// warning_type: tab,
// ...rest,
// };
// if (sort && Object.keys(sort).length) {
// reqParams.orderKey = Object.keys(sort)[0];
// let sort_select = sort[reqParams.orderKey];
// reqParams.desc = sort_select === 'descend';
// }
// // TODO 联调查询设备状态接口
// console.log(reqParams, 'reqParams');
// let resp = await postAlarmList({ ...reqParams });
// console.log(resp, 'postAlarmList_result');
// initDataTestList(resp.result);
// // return {
// // data: resp.result,
// // success: resp.success,
// // total: resp.count,
// // current: resp.count,
// // pageSize: resp.count,
// // };
// }}
}
useEffect(() => {
getTabs();
// initList();
}, []);
useEffect(() => {
// 模拟异步请求数据
initList();
}, [currentPage, currentPageSize]);
return (
<PageContainer
// title={false}
// content={
// <div style={{
// display: 'flex',
// justifyContent: 'space-between'
// }}>
// <div style={{
// fontWeight: 600,
// fontSize: 20,
// color: '#333'
// }}></div>
// </div>
// }
>
<ProCard
className="gn"
bodyStyle={{ padding: 10, margin: 0 }}
style={{ padding: 0, margin: 0 }}
>
<Tabs
activeKey={tab}
items={tabs}
onChange={(key) => {
changeProjectTab(key);
}}
></Tabs>
<ProList<any>
className="gn"
ghost={true}
itemCardProps={{
ghost: true,
bodyStyle: { padding: 0, margin: 0 },
style: {
width: '100%',
border: 0,
// minHeight: 700
// padding: 0, margin: 0
},
}}
// search={{
// labelWidth: proTableCommonOptions.searchLabelWidth,
// }}
// headerTitle={
// <>
// <div>
// {Object.keys(tabOptions).map((item, index) => {
// // eslint-disable-next-line react/jsx-key
// return (
// <Button
// style={{ marginRight: 12,border: 'none' }}
// // type={activeTabIndex === index ? 'primary' : 'default'}
// key={index}
// onClick={() => {
// setActiveTabIndex(index);
// }}
// >
// {Object.keys(alarmRulesEnums).includes(item)
// ? alarmRulesEnums[item].miniName
// : ''}
// {"("+tabOptions[item]+ ')'}
// </Button>
// );
// })}
// </div>
// </>
// }
cardProps={{
bodyStyle: {
padding: '8px 16px 16px',
borderRadius: 8,
},
}}
pagination={{
...proTablePaginationOptions,
total: total,
current: currentPage,
pageSize: currentPageSize,
showSizeChanger: true,
onChange: (page, pageSize) => {
console.log(page, pageSize);
setCurrentPage(page);
setCurrentPageSize(pageSize);
},
}}
showActions="hover"
rowSelection={false}
grid={{ gutter: 16, xs: 1, md: 2, lg: 2, xl: 3, xxl: 3 }}
metas={{
type: {
// 不展示在筛选项
hideInSearch: true,
},
content: {
hideInSearch: true,
},
actions: {
cardActionProps: 'extra',
},
// status1: {
// // 自己扩展的字段,主要用于筛选,不在列表中显示
// title: '设备组',
// valueType: 'select',
// valueEnum: {
// '0': { text: '全部设备分组', status: '0' },
// '1': {
// text: '设备分组1',
// status: '1',
// },
// '2': {
// text: '设备分组2',
// status: '2',
// },
// '3': {
// text: '设备分组3',
// status: '3',
// },
// },
// },
// status2: {
// // 自己扩展的字段,主要用于筛选,不在列表中显示
// title: '分类',
// valueType: 'select',
// valueEnum: {
// '0': { text: '全部分类', status: '0' },
// '1': {
// text: '外围监控',
// status: '1',
// },
// '2': {
// text: '室内监控',
// status: '2',
// },
// '3': {
// text: '违规监控',
// status: '3',
// },
// },
// },
}}
dataSource={dataTestList}
/>
</ProCard>
{/* <CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={actionRef.current?.reload}
/> */}
<AlarmDetails
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={initList}
/>
</PageContainer>
);
};
export default AlarmList;

@ -1,196 +0,0 @@
import { postAlarmRules } from '@/services/realTime/alarmRules';
import { ModalForm, ProForm, ProFormSwitch, ProFormText } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateAlarmRulesForm>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateAlarmRulesForm>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateAlarmRulesForm>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'alarm_rules.page.form.title',
defaultMessage: `编辑单人徘徊告警`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
values.id = props.values.id;
values.is_use = values.is_use ? 1 : 0;
// console.log(values);
await postAlarmRules(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormSwitch
width={proFormSmallItemStyleProps.column2Width}
name="is_use"
label={
<FormattedMessage id="alarm_rules.page.form.isEnabled" defaultMessage="启用告警" />
}
checkedChildren="启用"
unCheckedChildren="关闭"
initialValue={props.values.is_use}
disabled={false}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="warning_name"
label={<FormattedMessage id="alarm_rules.page.form.name" defaultMessage="告警名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.name',
defaultMessage: '告警名称',
})}`}
required={true}
initialValue={props.values.warning_name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.name"
defaultMessage="请填写告警名称"
/>
),
},
]}
/>
<div></div>
<div
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
}}
>
<span style={{ marginRight: 6 }}></span>
<ProFormText
width={100}
name="time_period"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.time_period}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.time_interval"
defaultMessage="请填写时间"
/>
),
},
]}
/>
<span style={{ margin: '0 6px' }}></span>
<ProFormText
width={100}
name="time_interval"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.time_interval}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.time_interval"
defaultMessage="请填写时间"
/>
),
},
]}
/>
<span style={{ marginRight: 6 }}></span>
<ProFormText
width={100}
name="appear_number"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.appear_number}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.appear_number"
defaultMessage="请填写次数"
/>
),
},
]}
/>
<span style={{ marginLeft: 6 }}></span>
</div>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -1,230 +0,0 @@
import { postAlarmRules } from '@/services/realTime/alarmRules';
import { ModalForm, ProForm, ProFormSwitch, ProFormText } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateAlarmRulesForm>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateAlarmRulesForm>;
reload: any;
};
const UpdateMultiForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateAlarmRulesForm>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'alarm_rules.page.form.multiTitle',
defaultMessage: `编辑${props.values.warning_name}`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
values.id = props.values.id;
values.is_use = values.is_use ? 1 : 0;
// console.log(values);
await postAlarmRules(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
{/* <ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="alarm_rules.page.form.enabled" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.enabled',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.enabled}
disabled={false}
/> */}
<ProFormSwitch
width={proFormSmallItemStyleProps.column2Width}
name="is_use"
label={
<FormattedMessage id="alarm_rules.page.form.isEnabled" defaultMessage="启用告警" />
}
checkedChildren="启用"
unCheckedChildren="关闭"
initialValue={props.values.is_use}
disabled={false}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="warning_name"
label={<FormattedMessage id="alarm_rules.page.form.name" defaultMessage="告警名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.name',
defaultMessage: '告警名称',
})}`}
required={true}
initialValue={props.values.warning_name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.name"
defaultMessage="请填写告警名称"
/>
),
},
]}
/>
<div></div>
<div
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
}}
>
<span style={{ marginRight: 6 }}></span>
<ProFormText
width={100}
name="person_number"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.person_number}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.person_number"
defaultMessage="请填写人数"
/>
),
},
]}
/>
<span style={{ margin: '0 6px' }}></span>
<ProFormText
width={100}
name="time_interval"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.time_interval',
defaultMessage: '时间',
})}`}
required={true}
initialValue={props.values.time_interval}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.time_interval"
defaultMessage="请填写时间"
/>
),
},
]}
/>
<span style={{ marginLeft: 6 }}></span>
</div>
{/* { timeStatus &&
<ProFormFieldSet
name="list"
label="触发条件"
type='space'
transform={(value: any) => ({
// list: value,
// startTime: value[0],
// endTime: value[1],
time_period: value[0],
time_interval: value[1],
appear_number: value[2],
})}
className={styles}
>
<ProFormText
width={100}
name="trigger_start_time"
label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_start_time}
disabled={false}
/>
<ProFormText
width={100}
name="trigger_end_time"
label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_end_time}
disabled={false}
/>
</ProFormFieldSet>} */}
</ProForm.Group>
</ModalForm>
);
};
export default UpdateMultiForm;

@ -1,229 +0,0 @@
import { postAlarmRules } from '@/services/realTime/alarmRules';
import {
ModalForm,
ProForm,
ProFormSwitch,
ProFormText,
ProFormTimePicker,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateAlarmRulesForm>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateAlarmRulesForm>;
reload: any;
};
const UpdateTimeForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateAlarmRulesForm>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'alarm_rules.page.form.timeTitle',
defaultMessage: `编辑${props.values.warning_name}`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
values.id = props.values.id;
values.is_use = values.is_use ? 1 : 0;
// console.log(values);
await postAlarmRules(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
{/* <ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="alarm_rules.page.form.enabled" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.enabled',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.enabled}
disabled={false}
/> */}
<ProFormSwitch
width={proFormSmallItemStyleProps.column2Width}
name="is_use"
label={
<FormattedMessage id="alarm_rules.page.form.isEnabled" defaultMessage="启用告警" />
}
checkedChildren="启用"
unCheckedChildren="关闭"
initialValue={props.values.is_use}
disabled={false}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="warning_name"
label={<FormattedMessage id="alarm_rules.page.form.name" defaultMessage="告警名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.name',
defaultMessage: '告警名称',
})}`}
required={true}
initialValue={props.values.warning_name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.name"
defaultMessage="请填写告警名称"
/>
),
},
]}
/>
<div
style={{
marginBottom: 6,
}}
>
</div>
<div
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'flex-start',
alignItems: 'baseline',
}}
>
<span style={{ marginRight: 6 }}></span>
<ProFormTimePicker
style={{
padding: '0 6px',
}}
width={100}
name="trigger_start_time"
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.trigger_start_time',
defaultMessage: '敏感开始时间',
})}`}
required={true}
initialValue={props.values.trigger_start_time}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.trigger_start_time"
defaultMessage="请填写时间"
/>
),
},
]}
/>
{/* <ProFormText
width={100}
name="trigger_start_time"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_start_time}
disabled={false}
/> */}
<span style={{ margin: '0 6px' }}></span>
<ProFormTimePicker
width={100}
name="trigger_end_time"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '触发条件',
})}`}
required={true}
initialValue={props.values.trigger_end_time}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="alarm_rules.page.rule.required.trigger_start_time"
defaultMessage="请填写时间"
/>
),
},
]}
/>
{/* <ProFormText
width={100}
name="trigger_end_time"
// label={<FormattedMessage id="alarm_rules.page.form.triggerConditions" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'alarm_rules.page.form.triggerConditions',
defaultMessage: '$$$',
})}`}
required={false}
initialValue={props.values.trigger_end_time}
disabled={false}
/> */}
<span style={{ marginLeft: 6 }}></span>
{/* <span style={{ marginLeft: 6 }}></span> */}
</div>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateTimeForm;

@ -1,7 +0,0 @@
:global {
.ant-form-item-control-input-content {
.ant-space-gap-col-small {
align-items: center;
}
}
}

@ -1,234 +0,0 @@
import TableActionCard from '@/components/TableActionCard';
import { getAlarmRules } from '@/services/realTime/alarmRules';
import { EditOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { FormattedMessage } from '@umijs/max';
import { Button, Tag } from 'antd';
import React, { useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
import UpdateForm from './components/UpdateForm';
import UpdateMultiForm from './components/UpdateMultiForm';
import UpdateTimeForm from './components/UpdateTimeForm';
const AlarmRules: React.FC = () => {
/**
* @en-US International configuration
* @zh-CN
* */
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
// const handleDestroy = async (selectedRow: API.DeviceCategory) => {
// // deleteDeviceCategoryDeleteDeviceCategory({ id: selectedRow.id })
// // .then(() => {
// // message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
// // actionRef.current?.reload();
// // })
// // .catch(() => {
// // message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
// // });
// };
const [currentRow, setCurrentRow] = useState<API.DeviceCategory>();
// 编辑弹框
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const [updateMultiModalOpen, setUpdateMultiModalOpen] = useState<boolean>(false);
const [updateTimeModalOpen, setUpdateTimeModalOpen] = useState<boolean>(false);
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
const handleUpdateMultiModal = () => {
if (updateMultiModalOpen) {
setUpdateMultiModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateMultiModalOpen(true);
}
};
const handleUpdateTimeModal = () => {
setCurrentRow(undefined);
if (updateTimeModalOpen) {
setUpdateTimeModalOpen(false);
} else {
setUpdateTimeModalOpen(true);
}
};
const columns: ProColumns<API.DeviceCategory>[] = [
{
title: <FormattedMessage id="alarm_rules.page.name" defaultMessage="告警规则" />,
dataIndex: 'warning_name',
hideInSearch: true,
},
{
title: <FormattedMessage id="alarm_rules.page.id" defaultMessage="规则ID" />,
dataIndex: 'id',
hideInSearch: true,
},
{
title: <FormattedMessage id="alarm_rules.page.status" defaultMessage="规则状态" />,
dataIndex: 'is_use',
hideInSearch: true,
render: (dom) => {
return (
<Tag
bordered={false}
color={dom === 1 ? 'success' : ''}
style={{
// fontSize:14,
color: dom === 1 ? '#52C41A' : '#999',
}}
>
{dom === 1 ? '已启用' : '未启用'}
</Tag>
);
},
},
{
title: <FormattedMessage id="alarm_rules.page.updateTime" defaultMessage="修改时间" />,
dataIndex: 'update_time',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="操作" />,
dataIndex: 'option',
valueType: 'option',
fixed: 'right',
render: (_, record) => [
<TableActionCard
key="TableActionCardRef"
renderActions={[
{
key: 'update',
renderDom: (
<Button
key="update"
type="link"
size="small"
style={{
color: '#081FA8',
}}
icon={
<EditOutlined
style={{
marginRight: 3,
}}
/>
}
onClick={() => {
console.log(record);
if (record.id === 1) {
setUpdateModalOpen(true);
} else if (record.id === 2) {
setUpdateMultiModalOpen(true);
} else {
setUpdateTimeModalOpen(true);
}
setCurrentRow(record);
}}
>
<FormattedMessage id="common.edit" defaultMessage="编辑" />
</Button>
),
},
// {
// key: 'destroy',
// renderDom: (
// <IsDelete
// deleteApi={() => {
// handleDestroy(record).then(() => {});
// }}
// ></IsDelete>
// ),
// },
]}
></TableActionCard>,
],
},
];
return (
<PageContainer>
<ProTable<API.DeviceCategory>
cardProps={{
bodyStyle: {
padding: 20,
},
}}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
actionRef={actionRef}
rowKey="key"
search={false}
showSorterTooltip={false}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'device_category_list',
persistenceType: 'localStorage',
}}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams = {
page: current,
desc: false,
orderKey: '',
...rest,
};
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
// let resp = await postDeviceCategoryGetDeviceCategoryList({ ...reqParams });
let resp = await getAlarmRules(reqParams);
console.log(resp);
return {
data: resp.data.results.map((v: API.DeviceCategory) => {
return { ...v, key: v.id };
}),
success: resp.success,
total: resp.data.count,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
columns={columns}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={actionRef.current?.reload}
/>
<UpdateMultiForm
updateModalOpen={updateMultiModalOpen}
values={currentRow || {}}
handleModal={handleUpdateMultiModal}
reload={actionRef.current?.reload}
/>
<UpdateTimeForm
updateModalOpen={updateTimeModalOpen}
values={currentRow || {}}
handleModal={handleUpdateTimeModal}
reload={actionRef.current?.reload}
/>
</PageContainer>
);
};
export default AlarmRules;

@ -1,60 +0,0 @@
import { postTestDevice } from '@/services/realTime/interfaces';
import { RedoOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Tag, message } from 'antd';
import moment from 'moment';
import React, { useState } from 'react';
interface ImageSinglePopoverProps {
values: any;
reload: any;
}
const CaptureButton: React.FC<ImageSinglePopoverProps> = (props) => {
const intl = useIntl();
const [loading, setLoading] = useState<boolean>(false);
const connection = () => {
setLoading(true);
postTestDevice({
device_ip: props.values.device_ip,
id: props.values.id,
})
.then((res) => {
if (res.success) {
message.success(res.msg);
}
props.reload();
setLoading(false);
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
setLoading(false);
});
};
return (
<div>
<Tag
bordered={false}
color={props.values.test_result === 1 ? 'success' : ''}
style={{
// fontSize:14,
color: props.values.test_result === 1 ? '#52C41A' : '#999',
}}
>
{props.values.test_result === 1 ? '在线' : '离线'}
</Tag>
<span>{moment(props.values.test_time).format('YYYY-MM-DD hh:mm:ss')}</span>
<Button
type="link"
icon={<RedoOutlined />}
loading={loading}
onClick={() => {
connection();
}}
/>
</div>
);
};
export default CaptureButton;

@ -1,24 +0,0 @@
.captureImgBox {
.captureImgDescribe {
margin-bottom: 12px;
color: #666;
font-weight: 500;
font-size: 16px;
font-family: PingFang SC;
span {
color: #333;
}
}
.captureImgContent {
display: flex;
justify-content: center;
box-sizing: border-box;
width: 100%;
margin-bottom: 24px;
padding: 16px;
// height: 172px;
background: #f7f7f7;
border: 1px dashed #dcdcdc;
border-radius: 4px;
}
}

@ -1,85 +0,0 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-03 13:15:26
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-03 13:17:18
* @FilePath: \uighur-recognition-web2\src\pages\RealTime\DeviceList\components\CaptureForm.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { postInterfaces } from '@/services/realTime/interfaces';
import { ModalForm } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Form, Image, message } from 'antd';
import moment from 'moment';
import React from 'react';
import { proFormSmallModelWidth } from '../../../../../config/defaultForm';
import styles from './CaptureForm.less';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateInterfacesParams>;
export type UpdateFormProps = {
captureModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateInterfacesParams>;
reload: any;
};
const CaptureForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateInterfacesParams>();
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device.interface_manage.table.list.capture',
defaultMessage: `最近拍摄`,
})}
open={props.captureModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
props.handleModal();
},
// okText: intl.formatMessage({ id: 'common.okText', defaultMessage: '确认' }),
// cancelText: intl.formatMessage({ id: 'common.cancelText', defaultMessage: '取消' }),
}}
submitTimeout={2000}
submitter={false}
onFinish={async (values) => {
console.log(values);
values.id = props.values.id;
postInterfaces(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<div className={styles.captureImgBox}>
<div className={styles.captureImgDescribe}>
: <span>{props.values.device_name}</span>
</div>
<div className={styles.captureImgDescribe}>
: <span>{moment(props.values.appear_time).format('YYYY-MM-DD hh:mm:ss')}</span>
</div>
<div className={styles.captureImgContent}>
<Image width={100} preview={false} src={props.values.picture_path} />
</div>
</div>
</ModalForm>
);
};
export default CaptureForm;

@ -1,212 +0,0 @@
/**
*
*
*/
import { postInterfaces, postTestDevice } from '@/services/realTime/interfaces';
import { ModalForm, ProForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Button, Form, message } from 'antd';
import React, { useState } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateInterfacesParams>;
export type CreateFormProps = {
createModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateInterfacesParams>;
reload: any;
};
const CreateForm: React.FC<CreateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateInterfacesParams>();
const [loading, setLoading] = useState<boolean>(false);
const connection = async () => {
setLoading(true);
console.log(form.getFieldsValue());
postTestDevice({
device_ip: form.getFieldsValue().device_ip,
})
.then((res) => {
// message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
// props.reload();
console.log(res);
if (res.success) {
message.success(res.msg);
}
setLoading(false);
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
// setTimeout(() => {
// setLoading(false);
// }, 6000);
};
return (
<ModalForm<API.UpdateInterfacesParams>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device.interface_manage.table.list.addPic',
defaultMessage: '新建图像获取接口',
})}
open={props.createModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
setLoading(false);
props.handleModal();
},
okText: intl.formatMessage({ id: 'common.okText', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.cancelText', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values);
postInterfaces(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_name"
label={
<FormattedMessage
id="device.interface_manage.table.list.name"
defaultMessage="接口名称"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.name',
defaultMessage: '接口名称',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.name"
defaultMessage="接口名称为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_api"
label={
<FormattedMessage
id="device.interface_manage.table.list.address"
defaultMessage="接口地址"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.address',
defaultMessage: '接口地址',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.address"
defaultMessage="接口地址为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width - 96}
name="device_ip"
label={
<FormattedMessage id="device.interface_manage.table.list.ip" defaultMessage="IP地址" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.ip',
defaultMessage: 'IP地址',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.ip"
defaultMessage="IP地址为必填项"
/>
),
},
]}
addonAfter={
<Button
style={{
width: 86,
height: 32,
border: '1px solid #081FA8',
borderRadius: 4,
fontSize: 14,
color: '#081FA8',
}}
loading={loading}
onClick={() => connection()}
>
{loading ? '' : '连接测试'}
</Button>
}
/>
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="note"
label={
<FormattedMessage
id="device.interface_manage.table.list.remark"
defaultMessage="备注"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.remark',
defaultMessage: '备注',
})}`}
required={false}
/>
</ProForm.Group>
</ModalForm>
);
};
export default CreateForm;

@ -1,222 +0,0 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-03 13:17:58
* @FilePath: \general-ai-platform-web\src\pages\Device\DeviceCategoryList\components\UpdateForm.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { postInterfaces, postTestDevice } from '@/services/realTime/interfaces';
import { ModalForm, ProForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Button, Form, message } from 'antd';
import React, { useState } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.UpdateInterfacesParams>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.UpdateInterfacesParams>;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.UpdateInterfacesParams>();
const [loading, setLoading] = useState<boolean>(false);
const connection = () => {
setLoading(true);
console.log(props.values);
postTestDevice({
device_ip: form.getFieldsValue().device_ip,
id: props.values.id,
})
.then((res) => {
// message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
// props.reload();
console.log(res);
if (res.success) {
message.success(res.msg);
}
setLoading(false);
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
setLoading(false);
});
};
return (
<ModalForm<any>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'device.interface_manage.table.list.updatePic',
defaultMessage: `编辑${props.values.device_name}`,
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
setLoading(false);
props.handleModal();
},
okText: intl.formatMessage({ id: 'common.okText', defaultMessage: '确认' }),
cancelText: intl.formatMessage({ id: 'common.cancelText', defaultMessage: '取消' }),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values);
values.id = props.values.id;
postInterfaces(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_name"
label={
<FormattedMessage
id="device.interface_manage.table.list.name"
defaultMessage="接口名称"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.name',
defaultMessage: '接口名称',
})}`}
required={true}
initialValue={props.values.device_name}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.name"
defaultMessage="接口名称为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="device_api"
label={
<FormattedMessage
id="device.interface_manage.table.list.address"
defaultMessage="接口地址"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.address',
defaultMessage: '接口地址',
})}`}
required={true}
initialValue={props.values.device_api}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.address"
defaultMessage="接口地址为必填项"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width - 96}
name="device_ip"
label={
<FormattedMessage id="device.interface_manage.table.list.ip" defaultMessage="IP地址" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.ip',
defaultMessage: 'IP地址',
})}`}
required={true}
initialValue={props.values.device_ip}
rules={[
{
required: true,
message: (
<FormattedMessage
id="device.interface_manage.table.rule.required.ip"
defaultMessage="IP地址为必填项"
/>
),
},
]}
addonAfter={
<Button
style={{
width: 86,
height: 32,
border: '1px solid #081FA8',
borderRadius: 4,
fontSize: 14,
color: '#081FA8',
}}
loading={loading}
onClick={() => connection()}
>
{loading ? '' : '连接测试'}
</Button>
}
/>
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="note"
label={
<FormattedMessage
id="device.interface_manage.table.list.remark"
defaultMessage="备注"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '请输入',
})}${intl.formatMessage({
id: 'device.interface_manage.table.list.remark',
defaultMessage: '备注',
})}`}
initialValue={props.values.note}
required={false}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -1,298 +0,0 @@
import TableActionCard from '@/components/TableActionCard';
import IsDelete from '@/components/TableActionCard/isDelete';
import { getInterfaces, postInterfaces } from '@/services/realTime/interfaces';
import { EditOutlined, InstagramOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Button, message } from 'antd';
import React, { useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
import CaptureButton from './components/CaptureButton';
import CaptureForm from './components/CaptureForm';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
const DeviceList: React.FC = () => {
/**
* @en-US International configuration
* @zh-CN
* */
const intl = useIntl();
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const handleDestroy = async (selectedRow: API.UpdateInterfacesParams) => {
postInterfaces({ id: selectedRow.id, device_status: '3' })
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
actionRef.current?.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
};
const [currentRow, setCurrentRow] = useState<API.UpdateInterfacesParams>();
/**
* @en-US Pop-up window of new window
* @zh-CN
* */
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
const handleCreateModal = () => {
if (createModalOpen) {
setCreateModalOpen(false);
setCurrentRow(undefined);
} else {
setCreateModalOpen(true);
}
};
// 编辑弹框
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
// 最近拍摄
const [captureModalOpen, setCaptureModalOpen] = useState<boolean>(false);
const handleCaptureModal = () => {
console.log(captureModalOpen);
if (captureModalOpen) {
setCaptureModalOpen(false);
setCurrentRow(undefined);
} else {
setCaptureModalOpen(true);
}
};
const columns: ProColumns<API.UpdateInterfacesParams>[] = [
{
title: (
<FormattedMessage id="device.interface_manage.table.list.name" defaultMessage="接口名称" />
),
dataIndex: 'device_name',
hideInSearch: true,
},
{
title: <FormattedMessage id="alarm_rules.page.status" defaultMessage="设备状态" />,
dataIndex: 'test_result',
hideInSearch: true,
render: (dom, entity) => {
return <CaptureButton values={entity || {}} reload={actionRef.current?.reload} />;
},
},
// {
// title: <FormattedMessage id="device.interface_manage.table.list.address" defaultMessage="接口地址" />,
// dataIndex: 'device_api',
// hideInSearch: true,
// },
// {
// title: <FormattedMessage id="device.interface_manage.table.list.testTime" defaultMessage="状态查询时间" />,
// dataIndex: 'test_time',
// sorter: true,
// hideInSearch: true,
// valueType: 'dateTime',
// },
{
title: (
<FormattedMessage
id="device.interface_manage.table.list.createTime"
defaultMessage="创建时间"
/>
),
dataIndex: 'create_time',
sorter: true,
hideInSearch: true,
valueType: 'dateTime',
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="操作" />,
dataIndex: 'option',
valueType: 'option',
width: '260px',
fixed: 'right',
render: (_, record) => [
<TableActionCard
key="TableActionCardRef"
renderActions={[
{
key: 'capture',
renderDom: (
<Button
key="capture"
type="link"
size="small"
style={{
color: '#081FA8',
}}
icon={
<InstagramOutlined
style={{
marginRight: 3,
}}
/>
}
onClick={() => {
console.log('11');
setCaptureModalOpen(true);
setCurrentRow(record);
}}
>
{/* 最近拍摄 */}
<FormattedMessage
id="device.interface_manage.table.list.capture"
defaultMessage="最近拍摄"
/>
</Button>
),
},
{
key: 'update',
renderDom: (
<Button
key="update"
type="link"
size="small"
style={{
color: '#081FA8',
}}
icon={
<EditOutlined
style={{
marginRight: 3,
}}
/>
}
onClick={() => {
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<FormattedMessage id="common.edit" defaultMessage="编辑" />
</Button>
),
},
{
key: 'destroy',
renderDom: (
<IsDelete
deleteApi={() => {
handleDestroy(record).then(() => {});
}}
></IsDelete>
),
},
]}
></TableActionCard>,
],
},
];
return (
<PageContainer
title={false}
content={
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
<div
style={{
fontWeight: 600,
fontSize: 20,
color: '#333',
}}
>
</div>
<Button
type="primary"
onClick={() => {
setCreateModalOpen(true);
}}
>
<FormattedMessage
id="device.interface_manage.table.list.add"
defaultMessage="新建设备/输入源"
/>
</Button>
</div>
}
>
<ProTable<API.DeviceCategory>
cardProps={{
bodyStyle: {
padding: 20,
},
}}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
actionRef={actionRef}
rowKey="key"
search={false}
showSorterTooltip={false}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'device_category_list',
persistenceType: 'localStorage',
}}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams = {
page: current,
desc: false,
orderKey: '',
...rest,
};
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
let resp = await getInterfaces({ ...reqParams });
return {
data: resp.data.results.map((v: API.DeviceCategory) => {
return { ...v, key: v.id };
}),
success: resp.success,
total: resp.data.count,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
columns={columns}
/>
<CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={actionRef.current?.reload}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={actionRef.current?.reload}
/>
<CaptureForm
captureModalOpen={captureModalOpen}
values={currentRow || {}}
handleModal={handleCaptureModal}
reload={actionRef.current?.reload}
/>
</PageContainer>
);
};
export default DeviceList;

@ -1,100 +0,0 @@
import { postRecognition } from '@/services/realTime/involved';
import { CloseCircleOutlined, EllipsisOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Image, Popover, message } from 'antd';
import React, { useState } from 'react';
interface ImageWithPopoverProps {
src: string;
reload: any;
person_id: any;
}
const ImageWithPopover: React.FC<ImageWithPopoverProps> = ({ src, person_id, reload }) => {
const intl = useIntl();
const [open, setOpen] = useState(false);
const content = (
<div
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}
>
{/* <div>1</div>
<div>2</div> */}
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF' }}
icon={<CloseCircleOutlined style={{ color: '#E80D0D', fontSize: 12 }} />}
onClick={(event) => {
event.stopPropagation();
postRecognition({
person_id: person_id,
classify: '0',
})
.then(() => {
message.success('此人已被移除重点关注');
reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
setOpen(false);
}}
>
</Button>
</div>
);
const handleOpenChange = (value: boolean) => {
setOpen(value);
};
const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation(); // 阻止事件冒泡到父组件并阻止默认事件触发
};
return (
<div style={{ position: 'relative', boxSizing: 'border-box', width: 96, height: 96 }}>
<Image style={{ borderRadius: 4 }} width={96} height={96} preview={false} src={src} />
<Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 32 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 32, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 0, right: -4 }}
type="text"
icon={
<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />
}
onClick={handleButtonClick}
/>
</Popover>
{/* {involved.state && (
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px'
}}
>
</div>
)} */}
</div>
);
};
export default ImageWithPopover;

@ -1,26 +0,0 @@
.InvolvedImgBox {
box-sizing: border-box;
// display: flex;
// justify-content: flex-start;
padding: 16px 32px;
border-top: 1px solid #e0e0e0;
.involvedImgList {
position: relative;
span {
position: absolute;
bottom: -30px;
left: 15px;
width: 2px;
height: 30px;
border-left: 2px dashed #081fa8;
}
}
}
.myButtonDisabled {
visibility: hidden;
}
.involvedModalForm {
.ant-modal .ant-modal-content {
padding: 0 !important;
}
}

@ -1,318 +0,0 @@
import { getInvolvedTravelList, postRecognition } from '@/services/realTime/involved';
import { CloseCircleOutlined, EllipsisOutlined } from '@ant-design/icons';
import { ModalForm } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Form, Image, List, Popover, message } from 'antd';
import moment from 'moment';
import VirtualList from 'rc-virtual-list';
import React, { useEffect, useState } from 'react';
import trajectoryBottom from '../../../../../public/images/involved/trajectoryBottom.png';
import './InvolvedDetails.less';
import styles from './InvolvedDetails.less';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.InvolvedDetailsParams>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.InvolvedDetailsParams>;
reload: any;
};
const InvolvedDetails: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.InvolvedDetailsParams>();
const [dataFlag, setDataFlag] = useState(false);
const [open, setOpen] = useState(false);
const [trajectoryData, setTrajectoryData] = useState([]);
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentPage, setCurrentPage] = useState<number>(1);
const [total, setTotal] = useState<number>(0);
const ContainerHeight = 630;
const content = (
<div
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}
>
{/* <div>1</div>
<div>2</div> */}
<Button
type="text"
style={{ height: 22, padding: 0, fontSize: 12, color: '#FFF' }}
icon={<CloseCircleOutlined style={{ color: '#E80D0D', fontSize: 12 }} />}
onClick={(event) => {
event.stopPropagation();
postRecognition({
person_id: props.values.person_id,
classify: '0',
})
.then(() => {
message.success('此人已被移除重点关注');
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
});
setOpen(false);
props.handleModal();
}}
>
</Button>
</div>
);
const handleOpenChange = (value: boolean) => {
setOpen(value);
};
const appendData = (page: any, pageSize: any) => {
const reqParams = {
page: page,
pageSize: pageSize,
// desc: false,
person_id: props.values.person_id,
// ...rest,
};
getInvolvedTravelList(reqParams)
.then((res) => {
console.log(res);
if (res.data.results) {
setTrajectoryData(trajectoryData.concat(res.data.results));
setTotal(res.data.count);
if (res.data.next) {
setDataFlag(true);
} else {
setDataFlag(false);
// setTrajectoryData([]); // 重置trajectoryData数据为空数组
}
}
})
.catch(() => {
// setLoading(false);
setDataFlag(false);
// setTrajectoryData([]); // 重置trajectoryData数据为空数组
});
};
const onScroll = (e: React.UIEvent<HTMLElement, UIEvent>) => {
// Refer to: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#problems_and_solutions
console.log(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - ContainerHeight);
if (Math.abs(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - ContainerHeight) <= 1) {
if (dataFlag) {
const nextPage = currentPage + 1;
setCurrentPage(nextPage);
appendData(nextPage, 10);
}
}
};
useEffect(() => {
if (props.updateModalOpen) {
// 调用接口获取数据
setTrajectoryData([]); // 重置trajectoryData数据为空数组
setCurrentPage(1);
setCurrentPageSize(10);
appendData(currentPage, currentPageSize);
}
}, [props.updateModalOpen]);
return (
<ModalForm<any>
width={615}
title={
<div
style={{
display: 'flex',
alignItems: 'center',
padding: '24px 32px 0px',
justifyContent: 'flex-start',
}}
>
<div style={{ position: 'relative', boxSizing: 'border-box', width: 120, height: 120 }}>
<Image
style={{ borderRadius: 4 }}
width={120}
height={120}
preview={false}
src={props?.values?.picture_path}
/>
<Popover
placement="right"
content={content}
trigger="click"
style={{ width: 104, height: 32 }}
color="rgba(0, 0, 0, 0.6)"
overlayInnerStyle={{ width: 104, height: 32, padding: 4, borderRadius: 2 }}
open={open}
onOpenChange={handleOpenChange}
>
<Button
style={{ position: 'absolute', bottom: 0, right: -4 }}
type="text"
icon={
<EllipsisOutlined
style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }}
/>
}
// onClick={handleButtonClick}
/>
</Popover>
<div
style={{
position: 'absolute',
top: 0,
right: 0,
width: 64,
height: 24,
background: '#FAAD14',
borderRadius: '0px 4px 0px 4px',
color: '#FFF',
fontSize: 12,
textAlign: 'center',
lineHeight: '24px',
fontWeight: 400,
}}
>
</div>
</div>
<div
style={{
marginLeft: 12,
height: 98,
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
color: '#666',
fontSize: 14,
fontWeight: 400,
}}
>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(props?.values?.classify_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(props?.values?.appear_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{props?.values?.device_name}
</span>
</div>
</div>
</div>
}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => {
setTrajectoryData([]);
setCurrentPage(1);
setCurrentPageSize(10);
props.handleModal();
},
wrapClassName: 'involvedModalForm',
}}
submitter={false}
submitTimeout={2000}
onFinish={async (values) => {
values.is_ignore = true;
values.person_id = props.values.person_id;
// console.log(values);
// postIgnoringvents(values)
// .then(() => {
// message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
// props.reload();
// })
// .catch(() => {
// message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
// });
setTrajectoryData([]);
setCurrentPage(1);
setCurrentPageSize(10);
props.handleModal();
return true;
}}
>
{/* <ProForm.Group> */}
{/* <div className={styles.alarmDetails}>
: <span className={styles.alarmSpan}></span>: <span className={styles.alarmSpan}>广1#</span>: <span className={styles.alarmSpan}>2023-01-15 22:00:03</span>
</div> */}
<div className={styles.InvolvedImgBox}>
<List>
<VirtualList
data={trajectoryData}
height={ContainerHeight}
itemHeight={64}
itemKey="id"
onScroll={onScroll}
>
{(item: any, index: any) => (
<div key={item.person_id + index}>
<List.Item style={{ borderBottom: 0, height: 64, padding: 0 }}>
<List.Item.Meta
avatar={
<div className={styles.involvedImgList}>
<img style={{ width: 32, height: 32 }} src={trajectoryBottom} />
{index + 1 !== total && <span />}
</div>
}
title={
<div style={{ lineHeight: '30px', color: '#666' }}>
:{' '}
<span style={{ color: '#333', marginRight: 16 }}>
{moment(item.appear_time).format('YYYY-MM-DD hh:mm:ss')}
</span>{' '}
: <span style={{ color: '#333' }}>{item.device_name}</span>
</div>
}
/>
<div>
<Image
style={{ borderRadius: 4 }}
width={48}
height={48}
preview={{
mask: '',
}}
src={item.picture_path}
/>
</div>
</List.Item>
{index === total - 1 && (
<div style={{ textAlign: 'center', color: '#999' }}>~</div>
)}
</div>
)}
</VirtualList>
</List>
</div>
{/* </ProForm.Group> */}
</ModalForm>
);
};
export default InvolvedDetails;

@ -1,470 +0,0 @@
import { alarmRulesEnums } from '@/enums/status';
import { PageContainer, ProCard, ProList } from '@ant-design/pro-components';
import { Button, DatePicker } from 'antd';
import React, { useEffect, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
// import DeviceStatusCard from './components/DeviceStatusCard';
// import CreateForm from './components/CreateForm';
import { getInvolvedList } from '@/services/realTime/involved';
import locale from 'antd/es/date-picker/locale/zh_CN';
import moment from 'moment';
import ImageWithPopover from './components/ImageWithPopover';
import InvolvedDetails from './components/InvolvedDetails';
/**
* @
* 1
*/
// const tabOptions: Record<string, any> = {
// singlePersonHoveringAlarm: 90,
// multiplePersonGatheringAlarm: 20,
// sensitiveTimePeriodAlarm: 20,
// ignored: 2,
// // processingStatus: 10,
// // errorStatus: 20,
// };
// export type DeleteBoxProps = {
// modalOpen: boolean;
// handleModal: () => void;
// values: any;
// reload: any;
// };
const InvolvedList: React.FC = () => {
// const [cardActionProps, setCardActionProps] = useState<'actions' | 'extra'>('extra');
/**
* @en-US Pop-up window of new window
* @zh-CN
* */
// const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
// const [modalOpen, setModalOpen] = useState(false);
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
/**
* @en-US International configuration
* @zh-CN
* */
// const access = useAccess();
// const intl = useIntl();
// const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentPage, setCurrentPage] = useState<number>(1);
const [total, setTotal] = useState<number>(0);
// const [activeTabIndex, setActiveTabIndex] = useState<number>(0);
const [dataTestList, setdataTestList] = useState<any>([]);
const [tab] = useState<string>(alarmRulesEnums[0].key);
// const [tabs, setTabs] = useState<any>([]);
const [importDate, setImportDate] = useState<any>(null);
const [innerDate, setInnerDate] = useState<any>(null);
// const changeProjectTab = (key: string) => {
// setTab(key);
// console.log(key);
// // eslint-disable-next-line @typescript-eslint/no-use-before-define
// initList(key)
// };
// const getTabs = () => {
// // if (alarmRulesEnums.length) {
// // setTab(alarmRulesEnums[0].key);
// // }
// setTabs(alarmRulesEnums);
// };
// useEffect(() => {
// getTabs();
// }, []);
// const handleCreateModal = () => {
// if (createModalOpen) {
// setCreateModalOpen(false);
// setCurrentRow(undefined);
// } else {
// setCreateModalOpen(true);
// }
// };
const handleUpdateModal = () => {
if (updateModalOpen) {
setUpdateModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateModalOpen(true);
}
};
// const handleDestroy = async () => {
// if (modalOpen) {
// setModalOpen(false);
// setCurrentRow(undefined);
// } else {
// setModalOpen(true);
// }
// // deleteBusinessImageDeleteBusinessImage({ id: selectedRow.id })
// // .then(() => {
// // message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
// // actionRef.current?.reload();
// // })
// // .catch(() => {
// // message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
// // });
// };
// const { confirm } = Modal;
// const showConfirm = (record: any) => {
// confirm({
// title: `确定删除${record.name}吗`,
// icon: <QuestionCircleFilled />,
// content: '确定删除服务器1吗删除后将找不到此服务器请谨慎操作.',
// okText: '确认',
// cancelText: '取消',
// width: 560,
// onOk() {
// console.log('OK');
// },
// onCancel() {
// console.log('Cancel');
// },
// });
// };
// 处理初始值
function initDataTestList(dataList: Record<string, any>[]) {
console.log(dataList, 'initDataTestList');
let finalList: { content: React.JSX.Element }[] = [];
if (Array.isArray(dataList) && dataList.length) {
finalList = dataList.map((record, index) => {
return {
content: (
<ProCard
className="gn"
style={{ backgroundColor: '#F5F6FF', margin: 0, padding: 0, borderRadius: 4 }}
bodyStyle={{ margin: 0, padding: 0 }}
>
<div
style={{
display: 'flex',
alignItems: 'center',
padding: 20,
justifyContent: 'flex-start',
}}
onClick={() => {
console.log(index, 'index');
setUpdateModalOpen(true);
setCurrentRow(record);
}}
>
{/* <Image
width={96}
preview={false}
src={record.picture_path[0]}
/> */}
<ImageWithPopover
src={record.picture_path}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
reload={initList}
person_id={record.person_id}
// handleInvolved={handleInvolved}
></ImageWithPopover>
<div
style={{
marginLeft: 16,
height: 90,
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
color: '#666',
}}
>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(record.classify_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{moment(record.appear_time).format('YYYY-MM-DD hh:mm:ss')}
</span>
</div>
<div>
:{' '}
<span
style={{
color: '#333',
}}
>
{record.device_name}
</span>
</div>
</div>
</div>
</ProCard>
),
};
});
}
setdataTestList(() => [...finalList]);
}
// 初始化加载
async function initList(tabId: string = '1', date: any = null) {
const reqParams = {
page: currentPage,
pageSize: currentPageSize,
// desc: false,
classify: tabId,
analyse_time: date,
// ...rest,
};
const resp = await getInvolvedList({ ...reqParams });
// console.log(resp,'resp');
// setCurrentPageSize(resp?.data?.count)
setTotal(resp?.data?.count);
initDataTestList(resp?.data?.results);
// request={async (params = {}, sort) => {
// const { current, ...rest } = params;
// const reqParams = {
// page: current,
// desc: false,
// warning_type: tab,
// ...rest,
// };
// if (sort && Object.keys(sort).length) {
// reqParams.orderKey = Object.keys(sort)[0];
// let sort_select = sort[reqParams.orderKey];
// reqParams.desc = sort_select === 'descend';
// }
// // TODO 联调查询设备状态接口
// console.log(reqParams, 'reqParams');
// let resp = await postAlarmList({ ...reqParams });
// console.log(resp, 'postAlarmList_result');
// initDataTestList(resp.result);
// // return {
// // data: resp.result,
// // success: resp.success,
// // total: resp.count,
// // current: resp.count,
// // pageSize: resp.count,
// // };
// }}
}
const onChange: DatePickerProps['onChange'] = (date, dateString) => {
console.log(dateString);
setImportDate(date);
setInnerDate(dateString);
console.log(importDate, 'importDate');
};
// useEffect(() => {
// // getTabs();
// // initList();
// }, []);
useEffect(() => {
// 模拟异步请求数据
initList();
}, [currentPage, currentPageSize]);
return (
<PageContainer
// title={false}
// content={
// <div style={{
// display: 'flex',
// justifyContent: 'space-between'
// }}>
// <div style={{
// fontWeight: 600,
// fontSize: 20,
// color: '#333'
// }}></div>
// </div>
// }
>
<ProCard
className="gn"
bodyStyle={{ padding: 10, margin: 0 }}
style={{ padding: 0, margin: 0 }}
>
{/* <Tabs
activeKey={tab}
items={tabs}
onChange={(key) => {
changeProjectTab(key);
}}
></Tabs> */}
<div style={{ padding: '16px 16px 0' }}>
<DatePicker locale={locale} value={importDate} onChange={onChange} allowClear />
<Button
type="primary"
style={{ margin: '0 16px' }}
onClick={() => {
// setCreateModalOpen(true);
setImportDate(null);
initList(tab, null);
}}
>
</Button>
<Button
type="primary"
onClick={() => {
// setCreateModalOpen(true);
initList(tab, innerDate);
}}
>
</Button>
</div>
<ProList<any>
className="gn"
ghost={true}
itemCardProps={{
ghost: true,
bodyStyle: { padding: 0, margin: 0 },
style: {
width: '100%',
border: 0,
// minHeight: 700
// padding: 0, margin: 0
},
}}
// search={{
// labelWidth: proTableCommonOptions.searchLabelWidth,
// }}
// headerTitle={
// <>
// <div>
// {Object.keys(tabOptions).map((item, index) => {
// // eslint-disable-next-line react/jsx-key
// return (
// <Button
// style={{ marginRight: 12,border: 'none' }}
// // type={activeTabIndex === index ? 'primary' : 'default'}
// key={index}
// onClick={() => {
// setActiveTabIndex(index);
// }}
// >
// {Object.keys(alarmRulesEnums).includes(item)
// ? alarmRulesEnums[item].miniName
// : ''}
// {"("+tabOptions[item]+ ')'}
// </Button>
// );
// })}
// </div>
// </>
// }
cardProps={{
bodyStyle: {
padding: '8px 16px 16px',
borderRadius: 8,
},
}}
pagination={{
...proTablePaginationOptions,
total: total,
current: currentPage,
pageSize: currentPageSize,
showSizeChanger: true,
onChange: (page, pageSize) => {
console.log(page, pageSize);
setCurrentPage(page);
setCurrentPageSize(pageSize);
},
}}
showActions="hover"
rowSelection={false}
grid={{ gutter: 16, xs: 1, md: 2, lg: 2, xl: 3, xxl: 4 }}
metas={{
type: {
// 不展示在筛选项
hideInSearch: true,
},
content: {
hideInSearch: true,
},
actions: {
cardActionProps: 'extra',
},
// status1: {
// // 自己扩展的字段,主要用于筛选,不在列表中显示
// title: '设备组',
// valueType: 'select',
// valueEnum: {
// '0': { text: '全部设备分组', status: '0' },
// '1': {
// text: '设备分组1',
// status: '1',
// },
// '2': {
// text: '设备分组2',
// status: '2',
// },
// '3': {
// text: '设备分组3',
// status: '3',
// },
// },
// },
// status2: {
// // 自己扩展的字段,主要用于筛选,不在列表中显示
// title: '分类',
// valueType: 'select',
// valueEnum: {
// '0': { text: '全部分类', status: '0' },
// '1': {
// text: '外围监控',
// status: '1',
// },
// '2': {
// text: '室内监控',
// status: '2',
// },
// '3': {
// text: '违规监控',
// status: '3',
// },
// },
// },
}}
dataSource={dataTestList}
/>
</ProCard>
{/* <CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={actionRef.current?.reload}
/> */}
<InvolvedDetails
updateModalOpen={updateModalOpen}
values={currentRow || {}}
handleModal={handleUpdateModal}
reload={initList}
/>
</PageContainer>
);
};
export default InvolvedList;

@ -852,7 +852,7 @@ exports[`Login Page should show login form 1`] = `
class="ant-form-item-control-input-content"
>
<span
class="ant-input-affix-wrapper ant-input-password ant-input-password-large ant-input-affix-wrapper-lg"
class="ant-input-affix-wrapper ant-input-psw ant-input-psw-large ant-input-affix-wrapper-lg"
>
<span
class="ant-input-prefix"
@ -879,9 +879,9 @@ exports[`Login Page should show login form 1`] = `
</span>
<input
class="ant-input ant-input-lg"
id="password"
id="psw"
placeholder="Password: ant.design"
type="password"
type="psw"
value=""
/>
<span
@ -889,7 +889,7 @@ exports[`Login Page should show login form 1`] = `
>
<span
aria-label="eye-invisible"
class="anticon anticon-eye-invisible ant-input-password-icon"
class="anticon anticon-eye-invisible ant-input-psw-icon"
role="img"
tabindex="-1"
>

@ -1,10 +1,10 @@
// import Footer from '@/components/Footer';
import zhCN from '@/locales/zh-CN';
import { postBaseLogin } from '@/services/system/Base';
import { postMenuGetMenu } from '@/services/system/Menu';
import { getAllRouteNameTile, replaceMenuWithRoutesData } from '@/utils/common';
import { getLocale } from '@@/exports';
import { addLocale } from '@@/plugin-locale';
import { innerMenuRoutes } from '../../../../config/routes';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import {
@ -120,11 +120,11 @@ const Login: React.FC = () => {
// }, []);
const fetchUserInfo = async () => {
const userInfo = await initialState?.fetchUserInfo?.();
const menus = await postMenuGetMenu();
const menusData = innerMenuRoutes;
if (userInfo) {
// console.log("fetchUserInfo_userInfo", userInfo);
if (getLocale() === 'zh-CN') {
let localData = getAllRouteNameTile(menus.data.routes, '');
let localData = getAllRouteNameTile(menusData, '');
let localRes: any = {};
localData.forEach((v) => {
localRes[`menu${v.name}`] = v.title;
@ -139,7 +139,7 @@ const Login: React.FC = () => {
setInitialState((s) => ({
...s,
currentUser: userInfo,
menuData: replaceMenuWithRoutesData(menus.data.routes),
menuData: replaceMenuWithRoutesData(menusData),
}));
});
}
@ -190,7 +190,8 @@ const Login: React.FC = () => {
const [form] = Form.useForm<Record<string, any>>();
useEffect(() => {
form.setFieldsValue({ username: 'admin', password: 'Sju2984?' });
// localStorage.removeItem('access')
form.setFieldsValue({ username: 'admin', psw: 'Sju2984?' });
// console.log(form.getFieldsValue(), 'login_form');
}, []);
@ -244,9 +245,11 @@ const Login: React.FC = () => {
},
}}
title="欢迎登录"
initialValues={{
autoLogin: false,
}}
initialValues={
{
// autoLogin: false,
}
}
loading={loginLoading}
onFinish={async (values) => {
await handleSubmit(values as API.LoginParams);
@ -277,7 +280,7 @@ const Login: React.FC = () => {
]}
></ProFormText>
<ProFormText.Password
name="password"
name="psw"
fieldProps={{
size: 'large',
prefix: (
@ -338,9 +341,7 @@ const Login: React.FC = () => {
marginBlockEnd: 24,
}}
>
<ProFormCheckbox noStyle name="autoLogin">
</ProFormCheckbox>
<ProFormCheckbox noStyle></ProFormCheckbox>
<a
style={{
float: 'right',

@ -63,7 +63,7 @@ declare namespace API {
type LoginParams = {
username?: string;
password?: string;
psw?: string;
autoLogin?: boolean;
type?: string;
};

@ -54,8 +54,8 @@ declare namespace API {
type loginUserParams = {
/** The user name for login */
username: string;
/** The password for login in clear text */
password: string;
/** The psw for login in clear text */
psw: string;
};
type Order = {
@ -104,7 +104,7 @@ declare namespace API {
firstName?: string;
lastName?: string;
email?: string;
password?: string;
psw?: string;
phone?: string;
/** User Status */
userStatus?: number;

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-01 11:20:09
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-19 16:36:08
* @LastEditTime: 2024-04-19 17:27:42
* @FilePath: \uighur-recognition-web2\src\services\system\Base.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -27,6 +27,7 @@ export async function postBaseLogin(body: API.Login, options?: { [key: string]:
method: 'POST',
headers: {
'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),

@ -93,7 +93,7 @@ declare namespace API {
/** 新密码 */
newPassword?: string;
/** 密码 */
password?: string;
psw?: string;
};
type CORS = {
@ -374,7 +374,7 @@ declare namespace API {
/** DB initial langauge // added by mohamed hassan to support multilanguage */
language?: string;
/** 数据库密码 */
password?: string;
psw?: string;
/** 数据库连接端口 */
port?: string;
/** 数据库用户名 */
@ -407,7 +407,7 @@ declare namespace API {
type Login = {
captcha?: string;
captchaId?: string;
password?: string;
psw?: string;
username?: string;
};
@ -456,7 +456,7 @@ declare namespace API {
/** 打开到数据库的最大连接数 */
'max-open-conns'?: number;
/** 数据库密码 */
password?: string;
psw?: string;
/** 服务器地址:端口 */
path?: string;
/** :端口 */
@ -485,7 +485,7 @@ declare namespace API {
/** 打开到数据库的最大连接数 */
'max-open-conns'?: number;
/** 数据库密码 */
password?: string;
psw?: string;
/** 服务器地址:端口 */
path?: string;
/** :端口 */
@ -544,7 +544,7 @@ declare namespace API {
/** 打开到数据库的最大连接数 */
'max-open-conns'?: number;
/** 数据库密码 */
password?: string;
psw?: string;
/** 服务器地址:端口 */
path?: string;
/** :端口 */
@ -589,7 +589,7 @@ declare namespace API {
/** 打开到数据库的最大连接数 */
'max-open-conns'?: number;
/** 数据库密码 */
password?: string;
psw?: string;
/** 服务器地址:端口 */
path?: string;
/** :端口 */
@ -645,7 +645,7 @@ declare namespace API {
/** redis的哪个数据库 */
db?: number;
/** 密码 */
password?: string;
psw?: string;
};
type Register = {
@ -824,7 +824,7 @@ declare namespace API {
/** 打开到数据库的最大连接数 */
'max-open-conns'?: number;
/** 数据库密码 */
password?: string;
psw?: string;
/** 服务器地址:端口 */
path?: string;
/** :端口 */
@ -854,7 +854,7 @@ declare namespace API {
/** 打开到数据库的最大连接数 */
'max-open-conns'?: number;
/** 数据库密码 */
password?: string;
psw?: string;
/** 服务器地址:端口 */
path?: string;
/** :端口 */

@ -37,6 +37,7 @@ import {
WarningOutlined,
} from '@ant-design/icons';
import { MenuDataItem } from '@ant-design/pro-layout';
import { ReactComponent as TestIcon } from '../../public/icons/testIcon.svg';
const iconMap: any = {
CarOutlined: <CarOutlined />,
@ -62,6 +63,7 @@ const iconMap: any = {
GatewayOutlined: <GatewayOutlined />,
BellOutlined: <BellOutlined />,
PictureOutlined: <PictureOutlined />,
TestIcon: <TestIcon />,
};
// FIX从接口获取菜单时icon为string类型
const fixMenuItemIcon = (menus: MenuDataItem[]): MenuDataItem[] => {

2
types/index.d.ts vendored

@ -102,7 +102,7 @@ export namespace API {
/** example: admin */
username: string;
/** example: ant.design */
password: string;
psw: string;
/** example: true */
autoLogin: boolean;
/** example: account */

Loading…
Cancel
Save