feat():监测站点开发

master
李神峰 2026-01-21 09:46:38 +08:00
parent b68fb59b8d
commit 41a6498a95
37 changed files with 2165 additions and 214 deletions

View File

@ -1,2 +1,2 @@
GENERATE_SOURCEMAP=true GENERATE_SOURCEMAP=true
PUBLIC_URL=/hszSystem PUBLIC_URL=/ssSystem

View File

@ -1,2 +1,2 @@
GENERATE_SOURCEMAP=false GENERATE_SOURCEMAP=false
PUBLIC_URL=/hszSystem PUBLIC_URL=/ssSystem

View File

@ -23,7 +23,7 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>黑石咀系统管理</title> <title>双石系统管理</title>
<style> <style>
.lf{ .lf{

View File

@ -27,7 +27,7 @@ const DashboardLayout: React.FC = () => {
localStorage.setItem('access_token', token); localStorage.setItem('access_token', token);
dispatch.auth.loadMenu(); dispatch.auth.loadMenu();
} else if(myUser){ } else if(myUser){
navigate('/mgr/home'); navigate('/mgr/sys/userInfo');
} else { } else {
navigate('/login') navigate('/login')
} }
@ -36,7 +36,7 @@ const DashboardLayout: React.FC = () => {
useEffect(() => { useEffect(() => {
//显示菜单 //显示菜单
dispatch.auth.loadMenu(); dispatch.auth.loadMenu();
document.title = "黑石咀水库现代化运行管理矩阵平台"; document.title = "双石水库现代化运行管理矩阵平台";
}, []); }, []);
const menuIndexes = useMemo(() => findMenu(menu, pathname), [menu, pathname]); const menuIndexes = useMemo(() => findMenu(menu, pathname), [menu, pathname]);
@ -56,7 +56,7 @@ const DashboardLayout: React.FC = () => {
<Header className="app-header clearFloat"> <Header className="app-header clearFloat">
<span className="app-title lf"> <span className="app-title lf">
<img src={`${process.env.PUBLIC_URL}/assets/shuili.png`} alt=""/> <img src={`${process.env.PUBLIC_URL}/assets/shuili.png`} alt=""/>
<span></span> <span></span>
</span> </span>
<div className="topMenu lf"> <div className="topMenu lf">
<TopMenu menu={menu} menuIndexes={menuIndexes} /> <TopMenu menu={menu} menuIndexes={menuIndexes} />

View File

@ -0,0 +1,105 @@
import React, { useState, useEffect, useRef } from 'react'
import { Form, Button, Input, Row, Upload, Col, Table, DatePicker, InputNumber, message, Image, Modal, Typography, Select } from 'antd';
import { DeleteOutlined, FileWordOutlined, FilePdfOutlined, FileZipOutlined, FileExcelOutlined } from '@ant-design/icons';
import moment from 'moment'
import apiurl from '../../../service/apiurl';
import PdfView from './pdfView';
// import './index.less'
const baseFileView = "http://223.75.53.141:9100/gs-ss"
const FileView = ({mode, fileList, setFileList,downloadUrl}) => {
const childRef = useRef(null);
const download = (params) => {
let downloadLink = document.createElement("a");
downloadLink.href = process.env.REACT_APP_API_URL+downloadUrl+params
downloadLink.download = `${params.fileName}`;
downloadLink.style.display = "none";
// 将链接添加到页面中
document.body.appendChild(downloadLink);
// 模拟点击事件,开始下载
downloadLink.click();
}
const deleteFile = (fileId) => {
let filterFile = fileList.filter(item => item.response?.data?.fileId !== fileId);
setFileList(filterFile)
}
const viewPdf = (params) => {
if (childRef.current) {
childRef.current.callChildMethod(params);
}
}
return (
<>
<Row gutter={[16]}>
{
fileList.map(file=>(
<Col span={12}>
<div className="file-item" style={{ width: "100%",marginTop:5 }}>
<div className='file-description'>
{
(()=>{
if(file.name.indexOf('.doc') > -1){
return (
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileWordOutlined style={{ fontSize: 40 }}/>
</div>
)
}else if(file.name.indexOf('.pdf') > -1){
return (
<div
onClick={() => { viewPdf(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FilePdfOutlined style={{ fontSize: 40 }} />
</div>
)
}else if(file.name.indexOf('.zip') > -1){
return (
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileZipOutlined style={{ fontSize: 40 }} />
</div>
)
}else if(file.name.indexOf('.xls') > -1){
return (
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileExcelOutlined style={{ fontSize: 40 }} />
</div>
)
}else{
return (
<Image width={60} src={baseFileView + file.response?.data?.filePath} alt='' />
)
}
})()
}
<span style={{display: 'inline-block',maxWidth: '180px',overflow: 'hidden',textOverflow: 'ellipsis',whiteSpace: 'nowrap'}}>{file.name}</span>
</div>
<div className={mode == "view" ? 'delete-icon disable-icon' : 'delete-icon'} onClick={() => {
deleteFile(file.response?.data?.fileId)
}}>
<DeleteOutlined />
</div>
</div>
</Col>
))
}
</Row>
<PdfView ref={childRef} downloadUrl={downloadUrl}/>
</>
)
}
export default FileView

View File

@ -0,0 +1,85 @@
import React, { useState, useEffect } from 'react'
import { Form, Button, Input, Row, Upload, Col, Table, DatePicker, InputNumber, message, Image, Modal, Typography, Select } from 'antd';
import { DeleteOutlined, FileWordOutlined, FilePdfOutlined, FileZipOutlined, FileExcelOutlined } from '@ant-design/icons';
import moment from 'moment'
import FileView from './fileView';
import apiurl from '../../../service/apiurl';
const { Dragger } = Upload;
const FileUpload = ({mode, fileNum=1, value, onChange,uploadUrl,onLoadingChange,downloadUrl, accept, tip}) => {
const [fileList, setFileList] = useState([]) //上传文件列表
const [loading, setLoading] = useState(false)
const fileChange = (info) => {
if (info.file.status === "done") {
setLoading(false);
if(onLoadingChange) onLoadingChange(false);
}
if (info.file.status === "uploading") {
setLoading(true);
if(onLoadingChange) onLoadingChange(true);
}
if (info.file.status === "error") {
message.error("文件上传失败")
setLoading(false);
if(onLoadingChange) onLoadingChange(false);
}
setFileList(info.fileList)
}
useEffect(() => {
if (mode != 'save' ) {
const imgFile = value?.map(o => ({
name: o.fileName,
response: {
data: {
filePath: o.filePath,
fileId: o.fileId
}
},
}))
setFileList(imgFile)
}
}, [])
useEffect(()=>{
if(onChange && fileList){
// let oldFiles = fileList.map(item => (item.response?.data.fileId))
// onChange(oldFiles.join(','))
let oldFiles = fileList.map(item => ({
fileId: item.response?.data?.fileId,
filePath: item.response?.data?.filePath,
fileName:item.response?.data?.fileName
}))
onChange(oldFiles)
}
},[fileList])
return (
<>
{
mode!=='view' &&
<Dragger
name='file'
action={uploadUrl}
onChange={fileChange}
onDrop={(info) => { console.log(info.dataTransfer.files); }}
fileList={fileList}
disabled={loading}
maxCount={fileNum}
accept={accept}
// onSuccess={handleSuccess}
>
<p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p className="ant-upload-hint">
{tip || '支持扩展名:.doc .docx .xls .pdf .jpg .png .ppt'}
</p>
</Dragger>
}
<FileView fileList={fileList} setFileList={setFileList} mode={mode} downloadUrl={downloadUrl}/>
</>
)
}
export default FileUpload

View File

@ -0,0 +1,46 @@
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import { Modal } from 'antd';
import apiurl from '../../../service/apiurl';
const PdfView = forwardRef((props,ref) => {
const [pdfViewOPen, setPdfViewOPen] = useState(false)
const [iframeSrc, setIframeSrc] = useState('')
useImperativeHandle(ref, () => ({
callChildMethod: showPdf
}));
const showPdf = (url) => {
setIframeSrc(url)
setPdfViewOPen(true)
};
return (
<>
<Modal
open={pdfViewOPen}
width={1000}
title=""
footer={null}
style={{ marginTop: "-5%" }}
onCancel={() => {
setPdfViewOPen(false)
setIframeSrc('')
}}
>
<iframe
style={{
height: '80vh',
width: '100%',
border: 0,
marginTop: 20,
}}
src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(props?.downloadUrl+iframeSrc)}`}
/>
</Modal>
</>
)
})
export default PdfView

View File

@ -51,8 +51,9 @@ class BasicCrudModal extends React.Component {
this.setState({ open: true, mode: 'imp' }); this.setState({ open: true, mode: 'imp' });
} }
onEdit = (path,values) => { onEdit = (path, values, type = 'put') => {
createCrudService(path).edit(values).then((result) => { const service = type == 'put' ? createCrudService(path).edit(values) : createCrudService(path).edit1(values);
service.then((result) => {
if (result?.code === 200) { if (result?.code === 200) {
message.success('修改成功'); message.success('修改成功');
this.setState({ open: false }); this.setState({ open: false });
@ -88,7 +89,7 @@ class BasicCrudModal extends React.Component {
onDelete = (path, values) => { onDelete = (path, values) => {
createCrudService(path).del(values).then((result) => { createCrudService(path).delGet(values).then((result) => {
if (result?.code === 200) { if (result?.code === 200) {
message.success('删除成功'); message.success('删除成功');
this.setState({ open: false }); this.setState({ open: false });

View File

@ -1,183 +1,88 @@
import { useState, useRef, useEffect } from 'react'; import { useState, useRef, useEffect } from 'react';
import { ListProps, TableProps } from 'antd'; import { ListProps, TableProps } from 'antd';
import { PageResult, SearchOption } from '../../service/def'; import { PageResult, SearchOption } from '../../service/def';
import { camel2UnderLine } from "../../utils/utils"; import { camel2UnderLine } from "../../utils/utils";
import { log } from 'console';
import moment from 'moment';
type TableState<T> = {
data: T[];
total: number;
loading: boolean;
pageSize: number;
pageNumber: number;
search: { [key: string]: string };
sortField?: string;
sortOrder?: 'asc' | 'desc';
}
export type PageTableContext<T> = { export type PageTableContext<T> = {
tableProps: TableProps<T>, tableProps: TableProps<T>,
listProps?: ListProps<T>, listProps?: ListProps<T>,
search: (params?: SearchOption) => void, search: (params?: SearchOption) => void,
refresh: () => void refresh: () => void
} }
//最基础版本的pageTable
function usePageTable<T>( function usePageTable<T>(
service: (params?: SearchOption) => Promise<PageResult<T>>, service: (params?: SearchOption) => Promise<PageResult<T>>,
options: SearchOption = {} options: SearchOption = {}
): PageTableContext<T> { ): PageTableContext<T> {
const [screenHeight, setScreenHeight] = useState(window.innerHeight); const [ state, setState ] = useState(()=>({
const [num, setNum] = useState(0); data: [],
useEffect(() => { total: 0,
const handleResize = () => { loading: false,
setScreenHeight(window.innerHeight); pageSize: options.pageSize ?? 10,
}; pageNumber: options.pageNumber ?? 1,
sortField: options.sortField,
window.addEventListener('resize', handleResize); sortOrder: options.sortOrder,
search: options.search || {},
return () => { }))
window.removeEventListener('resize', handleResize);
};
}, []);
useEffect(() => {
//console.log("screenHeight 15+++",screenHeight);
let a = parseInt(((Number(screenHeight) - 320)/39).toFixed(0));
//console.log("num 18+++",a);
if(a>=0 && a<15){
setNum(10);
}else if(a>=15 && a<20){
setNum(15);
}else if(a>=20){
setNum(20);
}
}, [screenHeight]);
// 写在一起避免异步之后多次setState导致多次重绘
const [state, setState] = useState<TableState<T>>(() => ({
data: [],
total: 0,
loading: false,
pageSize: options.pageSize ?? 10,
pageNumber: options.pageNumber ?? 1,
sortField: options.sortField,
sortOrder: options.sortOrder,
search: options.search || {},
}));
const abort = useRef(false);
useEffect(() => {
abort.current = false;
if(num>0){
console.log("num 78+++",num);
search({ pageSize: num });
}
return () => { abort.current = true; }
}, [num]);
const search = (opt: SearchOption = {}) => {
setState(s => ({ ...s, loading: true }));
const pageParams = {
pageNumber: opt?.pageNumber ?? state.pageNumber,
pageSize: opt?.pageSize ?? num,
sortField: opt?.sortField ?? state.sortField,
sortOrder: opt?.sortOrder ?? state.sortOrder,
search: opt?.search ?? state.search,
};
const { search, ...params } = pageParams;
// console.log('search',search);
// console.log('params',params);
service({ ...search, ...params }).then((data) => {
if (!abort.current) {
//从c里找到shortName加到data.list里
const c:any = sessionStorage.getItem('projectInformation')
const allproject = JSON.parse(c)
data.list?.map((itemD:any,index:any)=>{
if(allproject && allproject.length>0){
itemD.shortName = ''
//给每个数据加一个key
itemD.xcIndex = moment(new Date()).valueOf()+'index:'+index
allproject?.map((itemA:any)=>{
if(itemD.sn === itemA.sn){
itemD.shortName=itemA.shortName
}
})
}
})
const search = async(opt: SearchOption = {})=>{
setState(s => ({ ...s, loading: true }));
const pageParams = {
pageNumber: opt?.pageNumber ?? state.pageNumber,
pageSize: opt?.pageSize ?? state.pageSize,
sortField: opt?.sortField ?? state.sortField,
sortOrder: opt?.sortOrder ?? state.sortOrder,
search: opt?.search ?? state.search,
};
const { search, ...params } = pageParams;
const data:any = await service({ ...search, ...params })
////给每个数据加一个key
data.list.forEach((item:any,index:number) => {
item.dataIndex = new Date().getTime()+'_'+index
});
setState({ setState({
...pageParams, ...pageParams,
data: data.list, data: data.list,
total: data.totalRow, total: data.totalRow,
loading: false, loading: false,
}) })
}
});
};
const handleTableChange = (pagination: any, filters: any, sort: any) => {
const { field, order } = sort;
if (field && order) {
const sortOrder: any = order === 'ascend' ? 'asc' : 'desc';
const _field = camel2UnderLine(field);
search({ pageNumber: pagination.current, pageSize: num, sortOrder, sortField: _field });
return;
} }
search({ pageNumber: pagination.current, pageSize: pagination.pageSize });
};
let listProps = undefined; const handleTableChange = (pagination: any, filters: any, sort: any) => {
if (false) { const { field, order } = sort;
const handleListChange = (page: number, pageSize: number) => { if (field && order) {
search({ pageNumber: page, pageSize: pageSize }); const sortOrder = order === 'ascend' ? 'asc' : 'desc';
}; const _field = camel2UnderLine(field);
listProps = { search({ pageNumber: pagination.current, pageSize: state.pageSize, sortOrder, sortField: _field });
dataSource: state.data, return;
loading: state.loading, }
pagination: { search({ pageNumber: pagination.current, pageSize: pagination.pageSize });
showTotal: (totalRow: any) => `${totalRow}`, };
showSizeChanger: true,
showQuickJumper: true, return {
pageSize: state.pageSize, tableProps: {
current: state.pageNumber, size: 'small',
total: state.total, bordered: true,
pageSizeOptions: ['10', '20', '50', '100'], dataSource: state.data,
onChange: handleListChange pagination: {
} showTotal: (totalRow:any) => `${totalRow}`,
showSizeChanger: true,
showQuickJumper: true,
pageSize: state.pageSize,
current: state.pageNumber,
total: state.total,
pageSizeOptions: ['10', '15', '20', '50', '100'],
hideOnSinglePage: true,
},
loading: state.loading,
onChange: handleTableChange,
},
search: (params) => search({ ...params, pageNumber: 1 }),
refresh: search,
} }
}
return {
tableProps: {
size: 'small',
bordered: true,
dataSource: state.data,
pagination: {
showTotal: (totalRow: any) => `${totalRow}`,
showSizeChanger: true,
showQuickJumper: true,
pageSize: state.pageSize,
current: state.pageNumber,
total: state.total,
pageSizeOptions: ['10', '15', '20', '50', '100'],
hideOnSinglePage: true,
},
loading: state.loading,
onChange: handleTableChange,
},
listProps,
search: (params?: SearchOption) => search({ ...params, pageNumber: 1 }),
refresh: search,
}
} }
export default usePageTable export default usePageTable

View File

@ -19,7 +19,31 @@ code {
monospace; monospace;
} }
.ant-upload-list {
display: none !important;
}
.file-item{
display: flex;
width: 100%;
margin-top: 10px !important;
align-items: center;
border: 1px solid #dedede;
justify-content: space-between;
padding: 1%;
.file-description{
display: flex;
align-items: center;
column-gap: 10px;
img{
width: 40px;
height: 40px;
}
}
.delete-icon{
cursor: pointer;
}
}
#root { #root {
min-width: 1280px; min-width: 1280px;
} }

View File

@ -121,46 +121,60 @@ export async function loadMenu(): Promise<MenuItem[]> {
{ {
id: id(), id: id(),
title: '系统管理', title: '系统管理',
redirect: '/mgr/home', redirect: '/mgr/sys/userInfo',
icon: 'jbqk', icon: 'jbqk',
children: [ children: [
{ {
id: id(), id: id(),
title: '用户管理', title: '用户管理',
path: '/mgr/home', path: '/mgr/sys/userInfo',
}, },
{ {
id: id(), id: id(),
title: '部门管理', title: '部门管理',
path: '/mgr/home/department', path: '/mgr/sys/department',
}, },
{ {
id: id(), id: id(),
title: '角色管理', title: '角色管理',
path: '/mgr/home/role', path: '/mgr/sys/role',
}, },
{ {
id: id(), id: id(),
title: '菜单管理', title: '菜单管理',
path: '/mgr/home/menuM', path: '/mgr/sys/menuM',
}, },
{ {
id: id(), id: id(),
title: '登录日志', title: '登录日志',
path: '/mgr/home/loginLog', path: '/mgr/sys/loginLog',
}, },
{ {
id: id(), id: id(),
title: '用户行为分析', title: '用户行为分析',
path: '/mgr/home/actionAnlay', path: '/mgr/sys/actionAnlay',
} },
{
id: id(),
title: '用户行为日志',
path: '/mgr/sys/yhxwrz',
},
{
id: id(), title: '监测体系', redirect: '/mgr/sys/jctx/jczd',
children: [
{id: id(), title: '监测站点', path: '/mgr/sys/jctx/jczd'},
{id: id(), title: '视频点', path: '/mgr/sys/jctx/spd'},
{id: id(), title: '监测断面管理', path: '/mgr/sys/jctx/jcdmgl'},
{id: id(), title: '安全监测点', path: '/mgr/sys/jctx/aqjcd'},
]
},
] ]
}, },
] ]
} }
export function defaultHomePage() { export function defaultHomePage() {
return '/mgr/home' return '/mgr/sys/userInfo'
} }
export async function currentBreadcrumbs() { export async function currentBreadcrumbs() {

View File

@ -1,6 +1,6 @@
import { config } from '../config' import { config } from '../config'
const base = '/gunshiApp/hsz' const base = '/gunshiApp/ss'
const apiurl = { const apiurl = {
xytlogin: { xytlogin: {
@ -54,6 +54,42 @@ const apiurl = {
delete: base + '/system/role/', delete: base + '/system/role/',
} }
}, },
jctx: {
jczd: {
page: base + '/stStbprpB/page',
edit: base + '/stStbprpB/update',
save: base + "/stStbprpB/insert",
del: base + "/stStbprpB/del"
},
spd: {
page: base + '/attCctvBase/page',
edit: base + '/attCctvBase/update',
save: base + "/attCctvBase/insert",
del: base + "/attCctvBase/del",
tree: base + "/attCctvBase/menu/list",
deleteTree:base + "/attCctvBase/menu/del/",
saveTree:base + "/attCctvBase/menu/insert",
editTree:base + "/attCctvBase/menu/update",
},
jcdmgl: {
page: base + '/attDamProfile/page',
edit: base + '/attDamProfile/update',
save: base + "/attDamProfile/insert",
del: base + "/attDamProfile/del",
upload: base + "/attDamProfile/file/upload/singleSimple",
download: base + '/attDamProfile/file/download/',
},
aqjcd: {
page: base + '/jcskStation/page',
list:base + '/attDamProfile/list',
edit: base + '/jcskStation/update',
save: base + "/jcskStation/insert",
del: base + "/jcskStation/del",
}
},
yhxwrz: {
page:base + '/visitMenuLog/page'
}
} }
export default apiurl export default apiurl

View File

@ -2,7 +2,7 @@ const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) { module.exports = function (app) {
app.use( app.use(
'/gunshiApp/hsz', '/gunshiApp/ss',
createProxyMiddleware({ createProxyMiddleware({
target: 'http://223.75.53.141:83/',//正式环境 target: 'http://223.75.53.141:83/',//正式环境
changeOrigin: true, changeOrigin: true,

View File

@ -38,9 +38,9 @@ async function send(url, options) {
const { code } = res.data; const { code } = res.data;
if (code === 401) { if (code === 401) {
//debugger; //debugger;
//window.location.href = '/mgr/home';// /mgr/home /login //window.location.href = '/mgr/sys/userInfo';// /mgr/sys/userInfo /login
window.location.href = '/xfflood/#/login'; // window.location.href = '/xfflood/#/login';
// window.location.hash = '#/login'; window.location.hash = '#/login';
} }
return res.data; return res.data;
} catch (e) { } catch (e) {
@ -320,6 +320,7 @@ export function httppost2(url, data = {}) {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'adcd': localStorage.getItem('ADCD6'), 'adcd': localStorage.getItem('ADCD6'),
"gs-token": localStorage.getItem('access_token'), "gs-token": localStorage.getItem('access_token'),
"Authorization": localStorage.getItem('access_token'),
}, },
body: JSON.stringify(data), body: JSON.stringify(data),
}; };

View File

@ -10,7 +10,11 @@ import LoginLog from "./systemMange/loginLog"
import Dept from "./systemMange/dept2" import Dept from "./systemMange/dept2"
import Role from "./systemMange/role" import Role from "./systemMange/role"
import ActionAnyl from "./systemMange/actionAnlay" import ActionAnyl from "./systemMange/actionAnlay"
import Jczd from './jczd/jczdgl'
import Spd from './jczd/spd'
import Jcdmgl from './jczd/jcdmgl'
import Aqjcd from './jczd/aqjcd'
import Yhxwrz from './yhxwrz'
const AppRouters: React.FC = () => { const AppRouters: React.FC = () => {
const dispatch = useDispatch<Dispatch>() const dispatch = useDispatch<Dispatch>()
@ -26,12 +30,17 @@ const AppRouters: React.FC = () => {
{ {
path: '/mgr', element: <DashboardLayout />, children: [ path: '/mgr', element: <DashboardLayout />, children: [
{ path: 'home', element: <UserM /> }, { path: 'sys/userInfo', element: <UserM /> },
{ path: 'home/menuM', element: <MenuM /> }, { path: 'sys/menuM', element: <MenuM /> },
{ path: 'home/loginLog', element: <LoginLog /> }, { path: 'sys/loginLog', element: <LoginLog /> },
{ path: 'home/department', element: <Dept /> }, { path: 'sys/department', element: <Dept /> },
{ path: 'home/role', element: <Role /> }, { path: 'sys/role', element: <Role /> },
{ path: 'home/actionAnlay', element: <ActionAnyl /> }, { path: 'sys/actionAnlay', element: <ActionAnyl /> },
{ path: 'sys/jctx/jczd', element: <Jczd /> },
{ path: 'sys/jctx/spd', element: <Spd /> },
{ path: 'sys/jctx/jcdmgl', element: <Jcdmgl /> },
{ path: 'sys/jctx/aqjcd', element: <Aqjcd /> },
{ path: 'sys/yhxwrz', element: <Yhxwrz /> },
], ],
}, },
{ path: '/login', element: <LoginPage /> }, { path: '/login', element: <LoginPage /> },

View File

@ -42,7 +42,7 @@ const LoginPage = () => {
}else{ }else{
localStorage.removeItem('loginNamePwd') localStorage.removeItem('loginNamePwd')
} }
navigate('/mgr/home'); navigate('/mgr/sys/userInfo');
localStorage.setItem('userName', result1.user.nickName); localStorage.setItem('userName', result1.user.nickName);
localStorage.setItem('userId', result1.user.userId); localStorage.setItem('userId', result1.user.userId);
@ -71,7 +71,7 @@ const LoginPage = () => {
<div className='login-inner'> <div className='login-inner'>
<div className='login-form'> <div className='login-form'>
<div style={{ textAlign: 'center', marginBottom: 2 }}> <div style={{ textAlign: 'center', marginBottom: 2 }}>
<div className='login-title'></div> <div className='login-title'></div>
</div> </div>
<div className="loginFormBox"> <div className="loginFormBox">
<div className='loginName'></div> <div className='loginName'></div>

View File

@ -0,0 +1,232 @@
import React, { useEffect, useState, useRef } from 'react';
import apiurl from '../../../service/apiurl';
import { message, Tabs, Form, Input, Button, Col, Row, DatePicker, InputNumber, TreeSelect } from 'antd'
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
import { httppost2 } from '../../../utils/request';
const ModalForm = ({ mode, record, onEdit, onSave, onCrudSuccess, close }) => {
const dataList = [
{ label: '自动', value: 0 },
{ label: '手动', value: 1 },
]
const typeList = [
{ label: '渗流', value: 1 },
{ label: '水文', value: 2 },
{ label: '位移', value: 3 },
]
const statusList = [
{ label: '有效', value: 1 },
{ label: '无效', value: 0 },
]
const [form] = Form.useForm();
const [list, setList] = useState([])
const getDmList = async () => {
try {
const { data } = await httppost2(apiurl.jctx.aqjcd.list);
setList(data.map(item=>({label:item.profileName,value:item.profileCode})))
} catch (error) {
console.log(error);
}
}
const onFinish = (val) => {
const year = val.year ? (moment.isMoment(val.year) ? val.year.format('YYYY') : moment(val.year).format('YYYY')) : undefined;
val.year = year;
if (mode == 'save') {
onSave(apiurl.jctx.aqjcd.save,val)
}
if (mode == 'edit') {
onEdit(apiurl.jctx.aqjcd.edit,{...record,...val},'post')
}
}
useEffect(() => {
if (mode != "save" && record) {
const year = record.year ? moment(record.year) : null;
const obj = {...record,year}
form.setFieldsValue(obj);
}
}, [mode, record])
useEffect(() => {
getDmList();
}, [])
return (
<>
<Form form={form} {...formItemLayout} onFinish={onFinish} >
<Row>
<Col span={12}>
<Form.Item
label="测站编码"
name="code"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="监测类型"
name="type"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<NormalSelect options={typeList} disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="监测断面"
name="dm"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<NormalSelect options={list} disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="经度"
name="lgtd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="纬度"
name="lttd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="管口高程(m)"
name="pipeElevation"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="管底高程(m)"
name="pipeBottomElevation"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="数据采集方式"
name="dataCollection"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<NormalSelect options={dataList} disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="站点状态"
name="stationStatus"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<NormalSelect options={statusList} disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="建设年份"
name="year"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<DatePicker
picker="year"
style={{ width: '100%' }}
disabled={mode === 'view'}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="承建单位"
name="buildUnit"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="运维单位"
name="operateUnit"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="站址"
name="address"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="备注"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
{
mode === 'view' ? null : (
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
</>
)
}
export default ModalForm;

View File

@ -0,0 +1,91 @@
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card, Row, Col, Divider, Button } from 'antd';
import ToolBar from './toolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import React, { Fragment, useRef, useMemo, useEffect, useState } from 'react';
import usePageTable from '../../../components/crud/usePageTable';
import { paginate_get, paginate_noCode } from '../../../components/crud/_';
import { CrudOpRender_text } from '../../../components/crud/CrudOpRender';
import moment from 'moment';
const Page = () => {
const sourceObj = { 1: '渗流', 2: "水文", 3: "位移"};
const statusObj = { 1: '有效', 0: '无效' };
const dataObj = { 1: '手动', 0: '自动' };
const refModal = useRef();
const [toolVal, setToolVal] = useState({})
const { tableProps, search, refresh } = usePageTable((params) => paginate_noCode(apiurl.jctx.aqjcd.page, { ...params }), {});
const columns = [
{
title: '序号', key: 'inx', dataIndex: 'inx', width: 80, align: "center", render: (value, r, index) => (
index + 1
)
},
{ title: '测点编号', key: 'code', dataIndex: 'code', width: 220 },
{
title: '监测类型', key: 'type', dataIndex: 'type', width: 120,
render: (v) => <span>{sourceObj[v]}</span>
},
{ title: '监测断面', key: 'dm', dataIndex: 'dm', width: 200 },
{ title: '经度', key: 'lgtd', dataIndex: 'lgtd', width: 120 },
{ title: '纬度', key: 'lttd', dataIndex: 'lttd', width: 120 },
{ title: '站址', key: 'stlc', dataIndex: 'stlc', width: 200, ellipsis: true },
{
title: '数据采集方式', key: 'dataCollection', dataIndex: 'dataCollection', width: 200,
render: (v) => <span>{dataObj[v]}</span>
},
{
title: '站点状态', key: 'stationStatus', dataIndex: 'stationStatus', width: 200,
render: (v) => <span>{statusObj[v]}</span>
},
{
title: '操作', key: 'operation', width: 200, fixed: 'right', align: 'center',
render: (value, row, index) => (<CrudOpRender_text edit={true} del={true} command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
} else if (type === 'edit') {
refModal.current.showEdit(params)
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDelete(apiurl.jctx.aqjcd.del + `/${params.id}`);
}
}
useEffect(() => {
if (toolVal) {
search({ search: { ...toolVal } })
}
}, [toolVal])
return (
<div style={{ display: 'flex', height: '100%' }}>
<div className="ant-card-body" style={{ padding: "0px 0 0 0", minWidth: '1000px', background: "#fff", flex: 1, marginLeft: 10 }}>
<Card className='nonebox' style={{ marginTop: 10 }}>
<ToolBar setSearchVal={setToolVal} onSave={command('save')} />
</Card>
<Table
style={{ padding: '20px 10px' }}
columns={columns}
rowKey="inx"
scroll={{ x: width, y: "calc( 100vh - 400px )" }}
{...tableProps}
/>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={refresh}
/>
</div>
)
}
export default Page

View File

@ -0,0 +1,75 @@
import React, { useEffect, useState } from 'react';
import { Form, Input, Button, DatePicker, Popconfirm, Row, Col } from 'antd';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
import { ReloadOutlined, SearchOutlined, PlusOutlined } from '@ant-design/icons'
import { httppost2 } from '../../../utils/request';
import apiurl from '../../../service/apiurl';
const ToolBar = ({ setSearchVal, onSave, }) => {
const [form] = Form.useForm();
const [list, setList] = useState([])
const typeList = [
{ label: '渗流', value: 1 },
{ label: '水文', value: 2 },
{ label: '位移', value: 3 },
]
const dataList = [
{ label: '自动', value: 0 },
{ label: '手动', value: 1 },
]
const statusList = [
{ label: '有效', value: 1 },
{ label: '无效', value: 0 },
]
const getDmList = async () => {
try {
const { data } = await httppost2(apiurl.jctx.aqjcd.list);
setList(data.map(item=>({label:item.profileName,value:item.profileCode})))
} catch (error) {
console.log(error);
}
}
const onFinish = (val) => {
setSearchVal(val);
}
const getView = () => {
setSearchVal(form.getFieldsValue());
}
useEffect(() => {
getDmList();
}, [])
return (
<>
<div style={{ display: 'flex', alignItems: 'center' }}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish} style={{ alignItems: 'center' }}>
<Form.Item label="测站编号" name="code">
<Input allowClear style={{ width: 180 }} />
</Form.Item>
<Form.Item label="监测类型" name="type">
<NormalSelect options={typeList} allowClear={true} style={{ width: 150 }} />
</Form.Item>
<Form.Item label="监测断面" name="dm">
<NormalSelect options={list} allowClear={true} style={{ width: 150 }} />
</Form.Item>
<Form.Item label="数据采集方式" name="dataCollection">
<NormalSelect options={dataList} allowClear={true} style={{ width: 150 }} />
</Form.Item>
<Form.Item label="站点状态" name="stationStatus">
<NormalSelect options={statusList} allowClear={true} style={{ width: 150 }} />
</Form.Item>
<Button style={{ marginRight: '10px' }} type="primary" icon={<SearchOutlined />} onClick={() => getView()}>查询</Button>
<Button style={{ marginRight: '10px' }} icon={<ReloadOutlined />} onClick={() => form.resetFields()}>重置</Button>
<Button style={{ marginRight: '10px' }} icon={<PlusOutlined />} onClick={onSave}>新增</Button>
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,88 @@
import React, { useEffect, useState, useRef } from 'react';
import apiurl from '../../../service/apiurl';
import { message, Tabs, Form, Input, Button, Col, Row, DatePicker, InputNumber, TreeSelect } from 'antd'
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import FileUpload from '../../../components/Form/FileUpload';
const ModalForm = ({ mode, record, onEdit, onSave, onCrudSuccess, close }) => {
const [form] = Form.useForm();
const [fileUploading, setFileUploading] = useState(false)
const onFinish = (val) => {
if (mode == 'save') {
onSave(apiurl.jctx.jcdmgl.save,val)
}
if (mode == 'edit') {
onEdit(apiurl.jctx.jcdmgl.edit,{...record,...val},'post')
}
}
return (
<>
<Form form={form} {...formItemLayout} onFinish={onFinish} initialValues={record}>
<Row>
<Col span={24}>
<Form.Item
label="断面编号"
name="profileCode"
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="断面名称"
name="profileName"
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="附件"
name="files"
>
<FileUpload
uploadUrl={apiurl.jctx.jcdmgl.upload}
downloadUrl={apiurl.jctx.jcdmgl.download}
mode={mode}
fileNum={1}
onChange={()=>{}}
onLoadingChange={(isLoading) => setFileUploading(isLoading)}
accept=".jpg,.png,.jpeg"
tip="支持扩展名:.jpg .png"
/>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="描述"
name="remark"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
{
mode === 'view' ? null : (
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit" disabled={fileUploading}>
{fileUploading ? '文件上传中...' : (mode === 'save' ? '提交' : '修改')}
</Button>
</Form.Item>
</>
)
}
</Form>
</>
)
}
export default ModalForm;

View File

@ -0,0 +1,93 @@
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card, Row, Col, Divider, Button,Image } from 'antd';
import ToolBar from './toolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import React, { Fragment, useRef, useMemo, useEffect, useState } from 'react';
import usePageTable from '../../../components/crud/usePageTable';
import { paginate_get, paginate_noCode } from '../../../components/crud/_';
import { CrudOpRender_text } from '../../../components/crud/CrudOpRender';
import moment from 'moment';
const baseFileView = "http://223.75.53.141:9100/gs-ss"
const Page = () => {
const refModal = useRef();
const [toolVal, setToolVal] = useState({})
const [visible, setVisible] = useState(false);
const [fileItem, setFileItem] = useState([])
const { tableProps, search, refresh } = usePageTable((params) => paginate_noCode(apiurl.jctx.jcdmgl.page, { ...params }), {});
const columns = [
{
title: '序号', key: 'inx', dataIndex: 'inx', width: 80, align: "center", render: (value, r, index) => (
index + 1
)
},
{ title: '断面编号', key: 'profileCode', dataIndex: 'profileCode', width: 120 },
{ title: '断面名称', key: 'profileName', dataIndex: 'profileName', width: 120 },
{
title: '断面平面图', key: 'lgtd', dataIndex: 'lgtd', width:220,
render: (v, r) => { return r.files && r.files.length ? <Button type='link' onClick={() => { setFileItem(r.files[0]); setVisible(true)}}>{r.files[0]?.fileName}</Button>:null}
},
{ title: '描述', key: 'remark', dataIndex: 'remark', width: 320 },
{
title: '操作', key: 'operation', width: 100, fixed: 'right', align: 'center',
render: (value, row, index) => (<CrudOpRender_text edit={true} del={true} command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
} else if (type === 'edit') {
refModal.current.showEdit(params)
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDelete(apiurl.jctx.jcdmgl.del + `/${params.id}`);
}
}
useEffect(() => {
if (toolVal) {
search({ search: { ...toolVal } })
}
}, [toolVal])
return (
<div style={{ display: 'flex', height: '100%' }}>
<div className="ant-card-body" style={{ padding: "0px 0 0 0", minWidth: '1000px', background: "#fff", flex: 1, marginLeft: 10 }}>
<Card className='nonebox' style={{ marginTop: 10 }}>
<ToolBar setSearchVal={setToolVal} onSave={command('save')} />
</Card>
<Table
style={{ padding: '20px 10px' }}
columns={columns}
rowKey="inx"
scroll={{ x: width, y: "calc( 100vh - 400px )" }}
{...tableProps}
/>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={refresh}
/>
<Image
// width={200}
style={{
display: 'none',
}}
src={baseFileView + fileItem?.filePath}
preview={{
visible,
src: baseFileView + fileItem?.filePath,
onVisibleChange: (value) => {
setVisible(value);
},
}}
/>
</div>
)
}
export default Page

View File

@ -0,0 +1,38 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker, Popconfirm,Row,Col } from 'antd';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
import { ReloadOutlined,SearchOutlined,PlusOutlined } from '@ant-design/icons'
const ToolBar = ({ setSearchVal, onSave,}) => {
const [form] = Form.useForm();
const statusList = [
{label:'有效',value:1},
{label:'无效',value:0},
]
const onFinish = (val) => {
setSearchVal(val);
}
const getView=()=>{
setSearchVal(form.getFieldsValue());
}
return (
<>
<div style={{display:'flex',alignItems:'center'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish} style={{alignItems:'center'}}>
<Form.Item label="断面名称" name="profileName">
<Input allowClear style={{width:180}}/>
</Form.Item>
<Button style={{marginRight:'10px'}} type="primary" icon={<SearchOutlined />} onClick={()=>getView()}>查询</Button>
<Button style={{marginRight:'10px'}} icon={<ReloadOutlined />} onClick={()=>form.resetFields()}>重置</Button>
<Button style={{marginRight:'10px'}} icon={<PlusOutlined />} onClick={onSave}>新增</Button>
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,222 @@
import React, { useEffect, useState, useRef } from 'react';
import apiurl from '../../../service/apiurl';
import { message, Tabs, Form, Input, Button, Col, Row, DatePicker, InputNumber, TreeSelect } from 'antd'
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
const ModalForm = ({ mode, record, onEdit, onSave, onCrudSuccess, close }) => {
const sourceList = [
{ label: '山洪', value: 'SH' },
{ label: '水文', value: 'SW' },
{ label: '气象', value: 'QX' },
{ label: '水库', value: 'SK' },
]
const jcList = [
{ label: '雨量站', value: 'drp' },
{ label: '水库水文站', value: 'rz' },
{ label: '流量站', value: 'flow' },
]
const statusList = [
{ label: '有效', value: 1 },
{ label: '无效', value: 0 },
]
const [form] = Form.useForm();
const onFinish = (val) => {
const buildYear = val.buildYear ? (moment.isMoment(val.buildYear) ? val.buildYear.format('YYYY') : moment(val.buildYear).format('YYYY')) : undefined;
val.buildYear = buildYear;
if (mode == 'save') {
onSave(apiurl.jctx.jczd.save,val)
}
if (mode == 'edit') {
onEdit(apiurl.jctx.jczd.edit,{...record,...val},'post')
}
}
useEffect(() => {
if (mode != "save" && record) {
const buildYear = record.buildYear ? moment(record.buildYear) : null;
const obj = {...record,buildYear}
form.setFieldsValue(obj);
}
}, [mode,record])
return (
<>
<Form form={form} {...formItemLayout} onFinish={onFinish} >
<Row>
<Col span={12}>
<Form.Item
label="测站编码"
name="stcd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="测站名称"
name="stnm"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="来源"
name="source"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<NormalSelect options={sourceList} disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="经度"
name="lgtd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="纬度"
name="lttd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="站点状态"
name="status"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<NormalSelect options={statusList} disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="基础高程"
name="dtmel"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<InputNumber disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="建设年份"
name="buildYear"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<DatePicker
picker="year"
style={{ width: '100%' }}
disabled={mode === 'view'}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="承建单位"
name="buildUnit"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="管理单位"
name="managementUnit"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="运维单位"
name="operateUnit"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="监测项目"
name="elems"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<NormalSelect options={jcList} mode="multiple" disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="站址"
name="stlc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="备注"
name="comments"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
{
mode === 'view' ? null : (
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
</>
)
}
export default ModalForm;

View File

@ -0,0 +1,89 @@
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card, Row, Col, Divider, Button } from 'antd';
import ToolBar from './toolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import React, { Fragment, useRef, useMemo, useEffect, useState } from 'react';
import usePageTable from '../../../components/crud/usePageTable';
import { paginate_get, paginate_noCode } from '../../../components/crud/_';
import { CrudOpRender_text } from '../../../components/crud/CrudOpRender';
import moment from 'moment';
const Page = () => {
const sourceObj = { "SH": '山洪', "SW": "水文", "QX": "气象", "Sk": "水库" };
const sttpObj = { "PP": '雨量站', "ZZ": "河道水位站", "ZQ": "河道水文站", "RR": "水库水文站", "TX": "图像站" };
const statusObj = { 1: '有效', 0: '无效' };
const refModal = useRef();
const [searchVal, setSearchVal] = useState({})
const [toolVal, setToolVal] = useState({})
const { tableProps, search, refresh } = usePageTable((params) => paginate_noCode(apiurl.jctx.jczd.page, { ...params }), {});
const columns = [
{
title: '序号', key: 'inx', dataIndex: 'inx', width: 80, align: "center", render: (value, r, index) => (
index + 1
)
},
{ title: '测站编码', key: 'stcd', dataIndex: 'stcd', width: 220 },
{ title: '测站名称', key: 'stnm', dataIndex: 'stnm', width: 200 },
{
title: '来源', key: 'source', dataIndex: 'source', width: 120,
render: (v) => <span>{sourceObj[v]}</span>
},
{ title: '经度', key: 'lgtd', dataIndex: 'lgtd', width: 120 },
{ title: '纬度', key: 'lttd', dataIndex: 'lttd', width: 120 },
{ title: '站址', key: 'stlc', dataIndex: 'stlc', width: 200, ellipsis: true },
{
title: '站点状态', key: 'status', dataIndex: 'status', width: 200,
render: (v) => <span>{statusObj[v]}</span>
},
{
title: '操作', key: 'operation', width: 200, fixed: 'right', align: 'center',
render: (value, row, index) => (<CrudOpRender_text edit={true} del={true} command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
} else if (type === 'edit') {
refModal.current.showEdit(params)
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDelete(apiurl.jctx.jczd.del + `/${params.id}`);
}
}
useEffect(() => {
if (toolVal) {
search({ search: { ...toolVal } })
}
}, [toolVal])
return (
<div style={{ display: 'flex', height: '100%' }}>
<div className="ant-card-body" style={{ padding: "0px 0 0 0", minWidth: '1000px', background: "#fff", flex: 1, marginLeft: 10 }}>
<Card className='nonebox' style={{ marginTop: 10 }}>
<ToolBar setSearchVal={setToolVal} onSave={command('save')} />
</Card>
<Table
style={{ padding: '20px 10px' }}
columns={columns}
rowKey="inx"
scroll={{ x: width, y: "calc( 100vh - 400px )" }}
{...tableProps}
/>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={refresh}
/>
</div>
)
}
export default Page

View File

@ -0,0 +1,62 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker, Popconfirm,Row,Col } from 'antd';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
import { ReloadOutlined,SearchOutlined,PlusOutlined } from '@ant-design/icons'
const ToolBar = ({ setSearchVal, onSave,}) => {
const [form] = Form.useForm();
const sourceList = [
{label:'山洪',value:'SH'},
{label:'水文',value:'SW'},
{label:'气象',value:'QX'},
{label:'水库',value:'SK'},
]
const sttpList = [
{label:'雨量站',value:'PP'},
{label:'河道水位站',value:'ZZ'},
{label:'河道水文站',value:'ZQ'},
{label:'水库水文站',value:'RR'},
{label:'图像站',value:'TX'},
]
const statusList = [
{label:'有效',value:1},
{label:'无效',value:0},
]
const onFinish = (val) => {
setSearchVal(val);
}
const getView=()=>{
setSearchVal(form.getFieldsValue());
}
return (
<>
<div style={{display:'flex',alignItems:'center'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish} style={{alignItems:'center'}}>
<Form.Item label="测站编码" name="stcd">
<Input allowClear style={{width:180}}/>
</Form.Item>
<Form.Item label="测站名称" name="stnm">
<Input allowClear style={{width:180}}/>
</Form.Item>
<Form.Item label="站点状态" name="status">
<NormalSelect options={statusList} allowClear={true} style={{width:150}}/>
</Form.Item>
<Button style={{marginRight:'10px'}} type="primary" icon={<SearchOutlined />} onClick={()=>getView()}>查询</Button>
<Button style={{marginRight:'10px'}} icon={<ReloadOutlined />} onClick={()=>form.resetFields()}>重置</Button>
<Button style={{marginRight:'10px'}} icon={<PlusOutlined />} onClick={onSave}>新增</Button>
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,47 @@
li.ant-tree-treenode-disabled > span:not(.ant-tree-switcher),
li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper,
li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper span{
color: #000 !important;
font-weight: bold;
}
.treeBox1{
.ant-tree-node-content-wrapper{
position: static !important;
}
.hover-ele{
&:hover{
color:#259dff
}
}
}
.AdcdTreeSelectorStyle{
.ant-input-wrapper{
.ant-input-affix-wrapper{
width: 98%;
}
.ant-input-group-addon{
.ant-btn{
width: 34px;
height: 34px;
}
}
}
.treeTitle {
display: flex;
justify-content: space-between;
.treeBtn {
display: none;
}
}
.treeTitle:hover {
.treeBtn {
display: flex;
}
}
}
.no-matter{
opacity: 0.5;
}

View File

@ -0,0 +1,312 @@
import React, { useState, useEffect } from 'react';
import { Tree, Input, Checkbox, Spin,Modal,Form,Col,Row,message,Space } from 'antd';
import { EditOutlined,PlusCircleOutlined, DeleteOutlined,ExclamationCircleOutlined} from '@ant-design/icons';
import './index.less';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import apiurl from '../../../../service/apiurl';
import { httppost2,httpget } from '../../../../utils/request';
const { Search } = Input;
type IProps = {
onSelectFun?: any;
setAdcd?: any;
showCheckbox: any;
tableName?: any;
onChangeOpen?: any;
hasAlertBox?: boolean;//顶部是否有预警条
isFetch?: boolean;
}
const { confirm } = Modal;
const AdcdTreeSelector: React.FC<IProps> = ({ onSelectFun, setAdcd, showCheckbox, tableName, hasAlertBox }) => {
const [loading, setLoading] = useState(true);
const [treeData, setTreeData] = useState([]);
const [newTreeData, setNewTreeData] = useState([]);
const [isFiter, setIsFiter] = useState(false);
const [expandedKeys, setExpandedKeys] = useState([]);
const [checkedKeys, setCheckedKeys] = useState([]);
const [selectedKeys, setSelectedKeys] = useState<any>([]);
const [selectedItem, setSelectedItem] = useState({});
const [autoExpandParent, setAutoExpandParent] = useState(true);
const [treeBoxHeight, setTreeBoxHeight] = useState({});
const [jdOpen, setJdOpen] = useState(false)
const [form] = Form.useForm();
const [mode, setMode] = useState('')
const [itemDetail, setItemDetail] = useState<any>({})
const [orderMax, setOrderMax] = useState<any>(0)
useEffect(() => {
getCustomerTreeData();
}, []);
useEffect(() => {
if(tableName){
setSelectedKeys([]);
}
}, [tableName]);
useEffect(()=>{
//根据预警条计/多选框计算高度
if(hasAlertBox){
if(showCheckbox){
setTreeBoxHeight({height:"calc( 100vh - 240px )"})
}else{
setTreeBoxHeight({height:"calc( 100vh - 210px )"})
}
}else{
if(showCheckbox){
setTreeBoxHeight({height:"calc( 100vh - 224px )"})
}else{
setTreeBoxHeight({height:"calc( 100vh - 194px )"})
}
}
},[hasAlertBox])
const getCustomerTreeData = async () => {
const {data} = await httpget(apiurl.jctx.spd.tree);
const item:any = data
if (item) {
setSelectedKeys([item[0]?.id])
setAdcd(item[0]?.id)
}
if (data.length > 0) {
handelTreeData(data);
setTreeData(data);
setLoading(false);
setOrderMax(Math.max(...data.map((item:any) => item?.orderIndex)))
} else {
setLoading(false);
setTreeData([]);
}
};
// @ts-ignore
const handelTreeData = (data) => {
if (data.length > 0) {
// @ts-ignore
data.forEach(item => {
item.title = item.name;
item.key = item.id;
if (item.children && item.children.length > 0) {
handelTreeData(item.children);
}
});
}
}
const onExpand = (expandedKeysValue:any) => {
setExpandedKeys(expandedKeysValue);
setAutoExpandParent(false);
};
const onSelect = (selectedKeysValue:any, info:any) => {
setSelectedKeys(selectedKeysValue);
setSelectedItem(info);
if (info.selectedNodes.length > 0) {
let selectData = info.selectedNodes[0];
let adcdVal = "";
adcdVal = selectData.key;
let params = { id: adcdVal };
if(onSelectFun){
onSelectFun(params);
}
if(setAdcd){
setAdcd(adcdVal)
}
} else {
let params = { id: "" };
if(onSelectFun){
onSelectFun(params);
}
if(setAdcd){
setAdcd("")
}
}
};
// 删除
const deleteJd = (v: any) => {
confirm({
title: '删除',
icon: <ExclamationCircleOutlined />,
content: '确认删除此数据',
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk: async() => {
try {
const res = await httpget(apiurl.jctx.spd.deleteTree + `${v.id}`)
if (res.code === 200) {
message.success('删除成功');
getCustomerTreeData();
}
if (res.code === 400) {
message.error(res.description);
}
} catch (error) {
console.log(error);
}
},
onCancel() {
console.log('Cancel');
},
});
}
// 新增节点
const saveJd = (v: any) => {
if (v) {
// form.setFieldValue('name', v.title);
setItemDetail(v);
}
setJdOpen(true);
setMode("save");
}
// 编辑节点
const editJd = (v: any) => {
setJdOpen(true);
form.setFieldsValue(v);
setMode("edit");
setItemDetail(v);
}
const onOk = async () => {
const name = form.getFieldValue('name');
const url = mode == "save" ? apiurl.jctx.spd.saveTree : apiurl.jctx.spd.editTree;
let saveParams = {
name,
parentId: itemDetail?.id || undefined,
orderIndex:itemDetail?.orderIndex || orderMax
}
let editParams = {
...itemDetail,
name
}
try {
const res = await httppost2(url, mode == "save" ? saveParams:editParams)
if (res.code == 200) {
message.success(mode == "save" ? '新增成功' : '编辑成功');
setJdOpen(false);
getCustomerTreeData();
form.resetFields();
} else if (res.code == 400) {
message.error(res.description);
}
} catch (error) {
console.log(error);
}
}
return (
<div className='AdcdTreeSelectorStyle'>
<div
style={{
padding: '10px',
color: "#409eff",
borderBottom: "1px solid #dfdfdf",
marginBottom: 20,
cursor: "pointer"
}}
onClick={saveJd}
></div>
{
loading?
<div style={{position:"absolute",top:"200px",left:"35%",background:"#fff",padding:"20px 30px",borderRadius:"10px"}}>
<Spin tip="正在加载..." size="large" spinning={loading} />
</div>:null
}
<div className="treeBox1" style={{...treeBoxHeight,marginTop:"10px"}}>
<div style={{ width: "300px"}}>
{
treeData.length > 0 &&
<Tree
defaultExpandAll={true}
blockNode={false}
onExpand={onExpand}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={isFiter ? newTreeData : treeData}
showLine={true}
titleRender={(v: any) => {
return (
<div
style={{width:200}}
className='treeTitle'
>
<span>{v.title}</span>
<Space
size={4}
className='treeBtn'
>
{/* <PlusCircleOutlined
style={{ fontSize: 15 }}
title='新增'
onClick={(e) => {
e.stopPropagation();
saveJd(v);
}}
className='hover-ele'
/> */}
<EditOutlined
title='编辑'
style={{ fontSize: 15 }}
onClick={(e) => {
e.stopPropagation();
editJd(v);
}}
className='hover-ele'
/>
<DeleteOutlined
title='删除'
style={{ fontSize: 15 }}
onClick={(e) => {
e.stopPropagation();
deleteJd(v);
}}
className='hover-ele'
/>
</Space>
</div>
)
}}
/>
}
</div>
</div>
<Modal
open={jdOpen}
title={mode == "save" ? "新增" : '编辑'}
destroyOnClose
onCancel={() => { setJdOpen(false); form.resetFields()}}
onOk={onOk}
>
<Form form={form} {...formItemLayout}>
<Row>
<Col span={24}>
<Form.Item
label="区域"
name="name"
rules={[{required: true}]}
>
<Input allowClear/>
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
</div>
);
};
export default AdcdTreeSelector;

184
src/views/jczd/spd/form.js Normal file
View File

@ -0,0 +1,184 @@
import React, { useEffect, useState, useRef } from 'react';
import apiurl from '../../../service/apiurl';
import { message, Tabs, Form, Input, Button, Col, Row, DatePicker, InputNumber, TreeSelect } from 'antd'
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
import {httpget } from '../../../utils/request';
const ModalForm = ({ mode, record, onEdit, onSave, onCrudSuccess, close }) => {
const sourceList = [
{ label: '球机', value: 1 },
{ label: '枪机', value: 2 },
]
const [form] = Form.useForm();
const getMenuList = async () => {
try {
const { data } = await httpget(apiurl.jctx.spd.tree);
const menuName = data.find(item => item.id == record?.code)?.name
form.setFieldValue('menuName',menuName)
} catch (error) {
console.log(error);
}
}
const onFinish = (val) => {
if (mode == 'save') {
onSave(apiurl.jctx.spd.save,{...val,menuId:record?.code})
}
if (mode == 'edit') {
onEdit(apiurl.jctx.spd.edit,{...record,...val},'post')
}
}
useEffect(() => {
getMenuList();
}, [])
return (
<>
<Form form={form} {...formItemLayout} onFinish={onFinish} initialValues={record}>
<Row>
<Col span={12}>
<Form.Item
label="视频点名称"
name="name"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="所在区域"
name="menuName"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={true} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="监控点类型"
name="type"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<NormalSelect options={sourceList} disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="ip及端口号"
name="ipAddress"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="通道号"
name="chan"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="建成日期"
name="buildDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
>
<DatePicker
format={'YYYY-MM-DD HH:mm:ss'}
showTime
style={{ width: '100%' }}
disabled={mode === 'view'}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="经度"
name="lgtd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="纬度"
name="lttd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="视频序列号"
name="indexCode"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="备注"
name="comments"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="排序"
name="order"
labelCol={{ span: 6 }}
wrapperCol={{ span: 14 }}
rules={[{ required: true }]}
>
<InputNumber disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
{
mode === 'view' ? null : (
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
</>
)
}
export default ModalForm;

View File

@ -0,0 +1,92 @@
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card, Row, Col, Divider, Button } from 'antd';
import ToolBar from './toolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import React, { Fragment, useRef, useMemo, useEffect, useState } from 'react';
import usePageTable from '../../../components/crud/usePageTable';
import { paginate_get, paginate_noCode } from '../../../components/crud/_';
import { CrudOpRender_text } from '../../../components/crud/CrudOpRender';
import AdcdTreeSelector from './AdcdTreeSelector';
import moment from 'moment';
const Page = () => {
const sourceObj = { 1: '球机', 2: "枪机"};
const refModal = useRef();
const [toolVal, setToolVal] = useState({})
const [code, setCode] = useState()
const { tableProps, search, refresh } = usePageTable((params) => paginate_noCode(apiurl.jctx.spd.page, { ...params }), {});
const columns = [
{
title: '序号', key: 'inx', dataIndex: 'inx', width: 80, align: "center", render: (value, r, index) => (
index + 1
)
},
{ title: '视频点名称', key: 'name', dataIndex: 'name', width: 150 },
{ title: '所在区域', key: 'menuName', dataIndex: 'menuName', width: 150 },
{
title: '监控点类型', key: 'type', dataIndex: 'type', width: 120,
render: (v) => <span>{sourceObj[v]}</span>
},
{ title: 'ip及端口号', key: 'ipAddress', dataIndex: 'ipAddress', width: 150, ellipsis: true },
{ title: '通道号', key: 'chan', dataIndex: 'chan', width: 150 },
{ title: '建成日期', key: 'buildDate', dataIndex: 'buildDate', width: 150 },
{ title: '经度', key: 'lgtd', dataIndex: 'lgtd', width: 120 },
{ title: '纬度', key: 'lttd', dataIndex: 'lttd', width: 120 },
{ title: '视频序列号', key: 'indexCode', dataIndex: 'indexCode', width: 120 },
{ title: '视频序列号', key: 'indexCode', dataIndex: 'indexCode', width: 120 },
{
title: '排序', key: 'order', dataIndex: 'order', width: 120,
},
{
title: '操作', key: 'operation', width: 200, fixed: 'right', align: 'center',
render: (value, row, index) => (<CrudOpRender_text edit={true} del={true} command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave({code});
} else if (type === 'edit') {
refModal.current.showEdit({ ...params,code })
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDelete(apiurl.jctx.spd.del + `/${params.id}`);
}
}
useEffect(() => {
if (toolVal && code) {
search({ search: { ...toolVal,menuId:code } })
}
}, [toolVal,code])
return (
<div style={{ display: 'flex', height: '100%' }}>
<div className='lf adcdTreeSelectorBox' style={{width:'310px',height:'100%',margin:0}}>
<AdcdTreeSelector hasAlertBox={false} setAdcd={setCode}/>
</div>
<div className="ant-card-body" style={{ padding: "0px 0 0 0", minWidth: '1000px', background: "#fff", flex: 1, marginLeft: 10 }}>
<Card className='nonebox' style={{ marginTop: 10 }}>
<ToolBar setSearchVal={setToolVal} onSave={command('save')} />
</Card>
<Table
style={{ padding: '20px 10px' }}
columns={columns}
rowKey="inx"
scroll={{ x: width, y: "calc( 100vh - 400px )" }}
{...tableProps}
/>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={refresh}
/>
</div>
)
}
export default Page

View File

@ -0,0 +1,41 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker, Popconfirm,Row,Col } from 'antd';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
import { ReloadOutlined,SearchOutlined,PlusOutlined } from '@ant-design/icons'
const ToolBar = ({ setSearchVal, onSave,}) => {
const [form] = Form.useForm();
const sourceList = [
{ label: '球机', value: 1 },
{ label: '枪机', value: 2 },
]
const onFinish = (val) => {
setSearchVal(val);
}
const getView=()=>{
setSearchVal(form.getFieldsValue());
}
return (
<>
<div style={{display:'flex',alignItems:'center'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish} style={{alignItems:'center'}}>
<Form.Item label="视频点名称" name="name">
<Input allowClear style={{width:180}}/>
</Form.Item>
<Form.Item label="监控点类型" name="type">
<NormalSelect options={sourceList} allowClear={true} style={{width:150}}/>
</Form.Item>
<Button style={{marginRight:'10px'}} type="primary" icon={<SearchOutlined />} onClick={()=>getView()}>查询</Button>
<Button style={{marginRight:'10px'}} icon={<ReloadOutlined />} onClick={()=>form.resetFields()}>重置</Button>
<Button style={{marginRight:'10px'}} icon={<PlusOutlined />} onClick={onSave}>新增</Button>
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -123,7 +123,7 @@ const Page = () => {
</div> </div>
<div className='data-panel'> <div className='data-panel'>
<div className='panel-item'> <div className='panel-item'>
<span className='name'>WEB端访问次数</span> <span className='name'>WEB端访问用户</span>
<p className='value'>{todayData?.web1Count || '-' }</p> <p className='value'>{todayData?.web1Count || '-' }</p>
</div> </div>
<Divider type="vertical" style={{fontSize:100,background:"#d7d7d7"}}/> <Divider type="vertical" style={{fontSize:100,background:"#d7d7d7"}}/>
@ -139,7 +139,7 @@ const Page = () => {
</div> </div>
<Divider type="vertical" style={{fontSize:100,background:"#d7d7d7"}} /> <Divider type="vertical" style={{fontSize:100,background:"#d7d7d7"}} />
<div className='panel-item'> <div className='panel-item'>
<span className='name'>移动端访问次数</span> <span className='name'>移动端访问用户</span>
<p className='value'>{todayData?.app1Count || '-'}</p> <p className='value'>{todayData?.app1Count || '-'}</p>
</div> </div>
<Divider type="vertical" style={{fontSize:100,background:"#d7d7d7"}}/> <Divider type="vertical" style={{fontSize:100,background:"#d7d7d7"}}/>
@ -166,7 +166,7 @@ const Page = () => {
<div className='left-top'> <div className='left-top'>
<div className='comomn-title'> <div className='comomn-title'>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} /> <img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span>访问用户前十</span> <span>浏览次数前十</span>
</div> </div>
<div className='left-top-charts'> <div className='left-top-charts'>
<ReactEcharts <ReactEcharts

View File

@ -49,7 +49,7 @@ export default function userBarOption(data) {
yAxis: [ yAxis: [
{ {
type: "value", type: "value",
name:"访问次数", name:"浏览次数",
min:minY - 1, min:minY - 1,
max:maxY + 1, max:maxY + 1,
axisLine: { axisLine: {

View File

@ -8,7 +8,7 @@ import moment from 'moment';
import { httpget2 } from '../../../utils/request'; import { httpget2 } from '../../../utils/request';
const Page = () => { const Page = () => {
const [searchVal, setSearchVal] = useState(false) const [searchVal, setSearchVal] = useState({})
const columns = [ const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" }, { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '日志内容', key: 'content', dataIndex: 'content', width: 250,align:"center" }, { title: '日志内容', key: 'content', dataIndex: 'content', width: 250,align:"center" },

View File

@ -60,17 +60,17 @@ const Page = () => {
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.systemManagement.role.list).xyt_find_noCode); const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.systemManagement.role.list).xyt_find_noCode);
// useEffect(()=>{ useEffect(()=>{
// if(searchVal){ if(searchVal){
// const params = { const params = {
// search: { search: {
// ...searchVal ...searchVal
// } }
// }; };
// search(params) search(params)
// } }
// },[searchVal]) },[searchVal])
return ( return (

View File

@ -11,7 +11,7 @@ const { confirm } = Modal;
const Page = () => { const Page = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const refModal = useRef(); const refModal = useRef();
const [searchVal, setSearchVal] = useState(false) const [searchVal, setSearchVal] = useState({})
const columns = [ const columns = [
{ title: '用户帐号', key: 'userName', dataIndex: 'userName', width: 150, align:"center" }, { title: '用户帐号', key: 'userName', dataIndex: 'userName', width: 150, align:"center" },
{ title: '用户姓名', key: 'nickName', dataIndex: 'nickName', width: 150,align:"center" }, { title: '用户姓名', key: 'nickName', dataIndex: 'nickName', width: 150,align:"center" },

View File

@ -8,7 +8,7 @@ const ToolBar = ({ setSearchVal, onSave}) => {
<div style={{display:'flex',justifyContent:'space-between'}}> <div style={{display:'flex',justifyContent:'space-between'}}>
<Form className='toolbarBox' layout="inline" onFinish={(v) => setSearchVal(v)}> <Form className='toolbarBox' layout="inline" onFinish={(v) => setSearchVal(v)}>
<Form.Item label="用户" name="userName"> <Form.Item label="用户" name="userName">
<Input allowClear placeholder='请输入账号/姓名/手机号查询' style={{ width: '250px' }} /> <Input allowClear placeholder='请输入账号查询' style={{ width: '250px' }} />
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit">查询</Button> <Button type="primary" htmlType="submit">查询</Button>

59
src/views/yhxwrz/index.js Normal file
View File

@ -0,0 +1,59 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import { Table, Card, Row, Col, Divider, Empty } from 'antd';
import apiurl from '../../service/apiurl';
import usePageTable from '../../components/crud/usePageTable';
import { paginate_noCode } from '../../components/crud/_';
// 页面初始默认查询参数
const options = {
search:{
// year:moment().format('YYYY')
},
};
const Page = () => {
const refModal = useRef();
const isRender = useRef(true)
const [searchVal, setSearchVal] = useState({year:options.search.year})
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 100, align:"center" },
{ title: '用户', key: 'name', dataIndex: 'name', width: 200 },
{ title: '页面', key: 'menu1', dataIndex: 'menu1', width: 300, render:(i,row)=>{
return (row.menu1?row.menu1:'')+(row.menu2?('-'+row.menu2):'')+(row.menu3?('-'+row.menu3):'')
}},
{ title: '时间', key: 'createTime', dataIndex: 'createTime', width: 150},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const { tableProps, search, refresh } = usePageTable((params)=>paginate_noCode(apiurl.yhxwrz.page,params),options);
useEffect(()=>{
const params = {
search: {
...searchVal
}
};
search(params)
},[searchVal])
return (
<>
<div className='content-root clearFloat xybm' style={{paddingRight:"10px",paddingBottom:"0",height:"98%"}}>
<div className='AdcdTreeTableBox'>
<div className="ant-card-body" style={{padding:"20px 0 0 0"}}>
<Table
columns={columns}
rowKey="inx"
{...tableProps}
scroll={{ x: width, y: "calc( 100vh - 400px )" }} />
</div>
</div>
</div>
</>
);
}
export default Page;