From 73cb86f5033f719ba20ca51b950210c19828b28e Mon Sep 17 00:00:00 2001 From: lishenfeng Date: Fri, 21 Mar 2025 10:34:00 +0800 Subject: [PATCH] =?UTF-8?q?feat():=20=E5=A2=9E=E5=8A=A0=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/apiurl.js | 15 +- src/service/warn.js | 2 +- src/views/AppRouters.tsx | 2 + .../spBasicInfo/AdcdTreeSelector/index.less | 47 +++ .../spBasicInfo/AdcdTreeSelector/index.tsx | 329 ++++++++++++++++++ src/views/SystemMangant/spBasicInfo/form.js | 197 +++++++++++ src/views/SystemMangant/spBasicInfo/index.js | 108 ++++++ .../SystemMangant/spBasicInfo/index.less | 21 ++ .../SystemMangant/spBasicInfo/toolbar.js | 46 +++ 9 files changed, 765 insertions(+), 2 deletions(-) create mode 100644 src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.less create mode 100644 src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.tsx create mode 100644 src/views/SystemMangant/spBasicInfo/form.js create mode 100644 src/views/SystemMangant/spBasicInfo/index.js create mode 100644 src/views/SystemMangant/spBasicInfo/index.less create mode 100644 src/views/SystemMangant/spBasicInfo/toolbar.js diff --git a/src/service/apiurl.js b/src/service/apiurl.js index 607bdd9..08d0107 100644 --- a/src/service/apiurl.js +++ b/src/service/apiurl.js @@ -12,7 +12,20 @@ const apiurl = { router: service_ykz + '/getRouters', role: service_ykz + '/system/menu/list' }, - + dataResourcesCenter: { + basicData: { + spjbxx: { + page: service_ykz + "/attCctvBase/page", + update: service_ykz + "/attCctvBase/update", + save: service_ykz + "/attCctvBase/insert", + delete: service_ykz + "/attCctvBase/del", + tree: service_ykz + "/cctvBMenu/tree", + saveTree: service_ykz + "/cctvBMenu/insert", + editTree: service_ykz + "/cctvBMenu/update", + deleteTree: service_ykz + "/cctvBMenu/del" + } + } + }, home: { videoList: service_fxdd + "/gateValveCctvRel/list", videosrc: service_fxdd + "/attCctvBase/preview/", diff --git a/src/service/warn.js b/src/service/warn.js index 1c4f178..78f5779 100644 --- a/src/service/warn.js +++ b/src/service/warn.js @@ -19,7 +19,7 @@ export async function page(params = {}) { return { list: data.records, totalRow: data.total }; } export async function getVideoTreeData(params = {}) { - const { data, code, msg } = await httppost2(apiurl.rcgl.aqgl.fxgkqd.tree) || {}; + const { data, code, msg } = await httpget2(apiurl.dataResourcesCenter.basicData.spjbxx.tree) || {}; if (code !== 200) { message.error(msg || '请求失败'); return []; diff --git a/src/views/AppRouters.tsx b/src/views/AppRouters.tsx index 4c36daf..2991262 100644 --- a/src/views/AppRouters.tsx +++ b/src/views/AppRouters.tsx @@ -34,6 +34,7 @@ import Xjxpz from "./Gcyx/xcxj/xjxpz" import Dmgl from "./SafeWatch/Dmgl" import Cdgx from "./SafeWatch/cdgx" import Gzpz from './SafeWatch/Gzpz' +import Spjbxx from './SystemMangant/spBasicInfo' import TestLine from './TestLine' // const HomePage = lazy(() => import('./Home')) @@ -90,6 +91,7 @@ const AppRouters: React.FC = () => { { path: 'xtgl/bmgl', element: }, { path: 'xtgl/jsgl', element: }, { path: 'xtgl/cdgl', element: }, + { path: 'xtgl/spjbxx', element: }, // 测试曲线 { path: 'testLine/testLine', element: }, diff --git a/src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.less b/src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.less new file mode 100644 index 0000000..ac6ad25 --- /dev/null +++ b/src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.less @@ -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; +} \ No newline at end of file diff --git a/src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.tsx b/src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.tsx new file mode 100644 index 0000000..1f03684 --- /dev/null +++ b/src/views/SystemMangant/spBasicInfo/AdcdTreeSelector/index.tsx @@ -0,0 +1,329 @@ +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 { getVideoTreeData } from '../../../../service/warn'; +import apiurl from '../../../../service/apiurl'; +import { httppost3,httpget6 } 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 = ({ 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([]); + 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({}) + const [orderMax, setOrderMax] = useState(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 adcdTreedata: any = await getVideoTreeData(); + const item:any = adcdTreedata + if (item) { + setSelectedKeys([item[0]?.id]) + setAdcd(item[0]?.id) + } + if (adcdTreedata.length > 0) { + handelTreeData(adcdTreedata); + setTreeData(adcdTreedata); + setLoading(false); + setOrderMax(Math.max(...adcdTreedata.map((item:any) => item?.orderIndex))) + } + }; + // @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: , + content: '确认删除此数据', + okText: '确定', + okType: 'primary', + cancelText: '取消', + onOk: async() => { + try { + const res = await httpget6(apiurl.dataResourcesCenter.basicData.spjbxx.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.dataResourcesCenter.basicData.spjbxx.saveTree : apiurl.dataResourcesCenter.basicData.spjbxx.editTree; + let saveParams = { + name, + parentId: itemDetail?.id || undefined, + orderIndex:itemDetail?.orderIndex || orderMax + } + let editParams = { + ...itemDetail, + name + } + try { + const res = await httppost3(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 ( +
+
新增视频区域
+ { + loading? +
+ +
:null + } + +
+
+ { + treeData.length > 0 && + { + return ( +
+ {v.title} + + { + e.stopPropagation(); + saveJd(v); + }} + className='hover-ele' + /> + { + e.stopPropagation(); + editJd(v); + }} + className='hover-ele' + /> + { + e.stopPropagation(); + deleteJd(v); + }} + className='hover-ele' + /> + + +
+ ) + }} + /> + } +
+ +
+ { setJdOpen(false); form.resetFields()}} + onOk={onOk} + > +
+ + + + + + + +
+
+
+ ); +}; + +export default AdcdTreeSelector; diff --git a/src/views/SystemMangant/spBasicInfo/form.js b/src/views/SystemMangant/spBasicInfo/form.js new file mode 100644 index 0000000..62dca03 --- /dev/null +++ b/src/views/SystemMangant/spBasicInfo/form.js @@ -0,0 +1,197 @@ +import React,{useEffect,useState,useRef} from 'react'; +import { Form, Button, Input, Row, Col, DatePicker, TreeSelect,message,Image,Modal } from 'antd'; +import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps'; +import apiurl from '../../../service/apiurl'; +import './index.less' +import NormalSelect from '../../../components/Form/NormalSelect'; +import { httpget2, httppost2 } from '../../../utils/request'; + +import moment from 'moment'; + +const ModalForm = ({ mode, record, onEdit, onSave, onCrudSuccess }) => { + const [form] = Form.useForm(); + const [AdcdList, setAdcdList] = useState([]) + const handleData = (arr) => { + arr.forEach(item => { + item.value = item.id; + item.title = item.name; + if (item.children && item.children.length) { + handleData(item.children) + } + }) + } + const getAdcdList = async() => { + try { + const res = await httpget2(apiurl.dataResourcesCenter.basicData.spjbxx.tree) + handleData(res.data) + setAdcdList(res.data) + } catch (error) { + console.log(error); + + } + } + + const onFinish = async (values) => { + values.buildDate = values.buildDate ? moment(values.buildDate).format('YYYY-MM-DD 00:00:00'): ''; + + if (mode === 'edit') { + values.id = record.id; + onEdit(apiurl.dataResourcesCenter.basicData.spjbxx.update, values) + } + if (mode === 'save') { + onSave(apiurl.dataResourcesCenter.basicData.spjbxx.save,values) + } + } + + useEffect(() => { + getAdcdList() + }, []) + + return ( + <> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dateString} + getValueProps={value => ({ + value: value ? moment(value) : undefined + })} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + mode==='view'?null:( + <> + + + + + ) + } +
+ + ); +} + +export default ModalForm; diff --git a/src/views/SystemMangant/spBasicInfo/index.js b/src/views/SystemMangant/spBasicInfo/index.js new file mode 100644 index 0000000..8ab8d85 --- /dev/null +++ b/src/views/SystemMangant/spBasicInfo/index.js @@ -0,0 +1,108 @@ +import React, { useState, useEffect,useMemo,useRef } from 'react' +import { PlusOutlined,DeleteOutlined,FolderOpenOutlined,SearchOutlined,UndoOutlined } from '@ant-design/icons'; +import { Table, Card,Button,message,Form,Input,Modal,Popconfirm } from 'antd'; +import ToolBar from './toolbar'; +import ModalForm from './form'; +import AdcdTreeSelector from "./AdcdTreeSelector"; +import BasicCrudModal from '../../../components/crud/BasicCrudModal2'; +import UsePageTable from '../../../components/crud/usePageTable2'; +import { createCrudService } from '../../../components/crud/_'; +import { CrudOpRender_text } from '../../../components/crud/CrudOpRender'; +import apiurl from '../../../service/apiurl'; +import './index.less' +export default function Xmzlmb() { + const refModal = useRef(); + const [code, setCode] = useState() + const [searchVal, setSearchVal] = useState({}) + + + + const columns = [ + { title: '视频ID', key: 'id', dataIndex: 'id', width: 100, align:"center" }, + { title: '视频点名称', key: 'name', dataIndex: 'name', width: 300, align:"center" }, + {title: '所在区域', key: 'menuName', dataIndex: 'menuName', width: 300, align: "center",}, + { + title: '监控点类型', key: 'type', dataIndex: 'type', width: 200, align: "center", + render: (value, row) => {value == 1 ? "球机": value == 2 ? "枪机": ''} + }, + { title: '经度', key: 'lgtd', dataIndex: 'lgtd', width: 100, align:"center" }, + { title: '纬度', key: 'lttd', dataIndex: 'lttd', width: 100, align: "center" }, + { title: '视频序列号', key: 'indexCode', dataIndex: 'indexCode', width: 300, align:"center" }, + + { + title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center', + render: (value, row, index) => ( () => command(cmd)(row)} />) + }, + ]; + const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]); + const { tableProps, search, refresh } = UsePageTable(createCrudService(apiurl.dataResourcesCenter.basicData.spjbxx.page).find_noCode, {}); + 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.onDeleteGet(apiurl.dataResourcesCenter.basicData.spjbxx.delete + `/${params.id}`); + } + } + + + + + useEffect(() => { + if (searchVal && code) { + let params = { + search: { + ...searchVal, + menuId:code + } + }; + search(params) + } + }, [code,searchVal]); + + useEffect(() => { + console.log(code); + + }, [code]) + + + + + + + return ( +
+
+ +
+
+ + + + + + + + + + + + ) +} diff --git a/src/views/SystemMangant/spBasicInfo/index.less b/src/views/SystemMangant/spBasicInfo/index.less new file mode 100644 index 0000000..9d0ab3b --- /dev/null +++ b/src/views/SystemMangant/spBasicInfo/index.less @@ -0,0 +1,21 @@ + + .basci-title{ + display: flex; + column-gap: 20px; + align-items: center; + position: relative; + font-size: 16px; + margin-bottom: 20px; + padding:5px 25px; + border-bottom: 1px solid #eee; + &::before{ + position: absolute; + top:7px; + left:0; + content: ""; + display: block; + width: 5px; + height: 20px; + background-color: #0079fe; + } + } \ No newline at end of file diff --git a/src/views/SystemMangant/spBasicInfo/toolbar.js b/src/views/SystemMangant/spBasicInfo/toolbar.js new file mode 100644 index 0000000..c6ff5e8 --- /dev/null +++ b/src/views/SystemMangant/spBasicInfo/toolbar.js @@ -0,0 +1,46 @@ +import React, { useEffect,useState } from 'react'; +import { Form, Input, Button, DatePicker, Popconfirm } from 'antd'; +import { SearchOutlined,UndoOutlined } from '@ant-design/icons'; +import NormalSelect from '../../../components/Form/NormalSelect'; +import moment from 'moment'; +const { RangePicker } = DatePicker; +const ToolBar = ({ setSearchVal, onSave, }) => { + const [form] = Form.useForm(); + const onFinish = (val) => { + setSearchVal(val); + } + return ( + <> +
+
+ + + + + + + + + + + + + { + onSave && ( + + + + ) + } + +
+ + ); +} + +export default ToolBar; \ No newline at end of file