diff --git a/src/components/DashboardLayout/index.tsx b/src/components/DashboardLayout/index.tsx index b33127319..d04f13581 100644 --- a/src/components/DashboardLayout/index.tsx +++ b/src/components/DashboardLayout/index.tsx @@ -13,56 +13,124 @@ import { currentBreadcrumbs } from '../../models/auth/_'; import {page} from '../../service/warn'; import { qryBasicWatershedDetailApi } from "../../service/preplan"; import moment from "moment" -import { httppost2 } from '../../utils/request'; +import { httppostAuth } from '../../utils/request'; import apiurl from '../../service/apiurl'; const { Header, Content, Sider } = Layout; const meunObj:any = { - 'home':'基本情况', - 'fxzb':'防汛准备', - 'sxfd':'思想发动', - 'fxkhgzh':'防汛抗旱工作会', - 'fbzrh':'防办主任会', - 'fxpxb':'防汛培训班', - 'fxtj':'防汛图件', - 'zzjg':'组织机构', - 'zq':'政区', - 'gc':'工程', - 'gczx':'工程整修', + 'home':'水库一张图', + 'sq':'四全', + 'qfg':'全覆盖', + 'zcdjxx':'注册登记信息', + 'qys':'全要素', + 'kqys':'库区要素', + 'gcys':'工程要素', + 'xyys': '下游要素', + 'qth':"全天候", + 'sksq':"水库水情", + 'hdsq': "河道水情", + 'ssyq':'实时水情', + 'trsq':'土壤墒情', + 'skyh':'水库溢洪', + 'spjk':'视频监控', 'ytygc':'已投运工程', - 'zjgc':'在建工程', - 'hdqz':'河道清障', - 'yaxb':'预案修编', - 'zqya':'政区预案', - 'ytygcya':'已投运工程预案', - 'zjgcya':'在建工程预案', - 'hsddya':'洪水调度方案', - 'qxdw':'抢险队伍', - 'qxwl':'抢险物料', - 'jczw':'检测站网', - 'yqz':'雨情站', - 'sqz':'水情站', - 'zbb':'值班表', - 'txl':'通讯录', - 'ysgzq':'雨水工灾情', - 'ssyq':'实时雨情', - 'sssq':'实时水情', - 'ssgq':'实时工情', - 'yxqk':'运行情况', - 'gcxq':'工程险情', - 'dbaq':'大坝安全监测数据', - 'sszq':'实时灾情', - 'fxdd':'防汛调度', - 'dqxsfx':'当前形势分析', - 'tqyb':'天气预报', + 'qzq':'全周期', + 'gcdsj':'工程大事记', + 'qzqda':'全周期档案', + 'sz':'四制', + 'gltx':'管理体系', + 'zzjgck':'组织机构查看', + 'zrrgl': '责任人管理', + 'pxgl':'培训管理', + 'pxjhgl':'培训计划管理', + 'pxjlgl':'培训记录管理', + 'szzf':'水政执法', + 'ajdj':'案件登记', + 'ajtj':'案件统计', + 'clyj':'处理依据', + 'jdkh':'监督考核', + 'khtj':'考核统计', + 'khrwgl':'考核任务管理', + 'khwtzg':'考核问题整改', + 'khzbgl':'考核指标管理', + 'khmbgl':'考核模版管理', + 'zdgl':'制度管理', + 'flfg':'法律法规', + 'zsk':'知识库', + 'ddfa':'调度方案库', + 'ywgz':'业务规则库', + 'gcaq':'工程安全知识库', + 'sy':'四预', + 'fhxzfx': '防洪形式', + 'tqyb': '天气预报', 'hsyb':'洪水预报', - 'skhs':'水库洪水', - 'hdhs':'河道洪水', - 'ddjc':'调度决策', - 'yjxy':'应急响应', - 'ddzl':'调度指令', - 'videoSurveillance':'视频监控', - 'fxdp':'防汛大屏', + 'hyybjs':'洪水预报计算', + 'ybfagl':'预报方案管理', + 'csgl': '参数管理', + 'hsyj':'洪水预警', + 'yjxx':'预警信息', + 'gzpz': '规则配置', + 'hsyy':'洪水预演', + 'fxya':'防汛预案', + 'ddgc':'调度规程', + 'qxdw':'抢险队伍', + 'qxwl': '抢险物料', + 'sg':"四管", + 'xcxj':"巡查巡检", + 'xcrw':"巡查任务", + 'xjwtcl':"巡查问题处理", + 'xjxpz':"巡检项配置", + 'aqgl':"安全管理", + 'fxgkqd':"风险管控清单", + 'aqyhpc':"安全隐患排查", + 'aqjcgl':"安全检查管理", + 'aqsgdj':"安全事故登记", + 'aqjdtz':"安全鉴定台帐", + 'cxjgtz':"除险加固台帐", + 'byfz':"白蚁防治", + 'bypc':"白蚁监测", + 'byxc':"防治宣传", + 'zmjk':"闸门监控", + 'wxyh':"维修养护", + 'zbgl':"值班管理", + 'zbb':'值班表', + 'zbrz':'值班日志', + 'btbb':'报表管理', + 'sdjyrbb':'时段降雨日报表', + 'rjylnbb':'日降雨量年报表', + 'sdswbb':'时段水位日报表', + 'rjswbb':'日均水位年报表', + 'dbaq':'告警管理', + 'aigj':'AI告警', + 'gbyj':'广播预警', + 'gcaqjc':'工程安全监测', + 'bzt':'布置图', + 'gcaqfx':'工程安全分析', + 'jrx':'浸润线', + 'gcaqyj':'工程安全预警', + 'yhyj':'隐患预警', + 'yjgzpz':'预警规则配置', + 'sjtjcx':'数据统计查询', + 'sjlr':'人工监测数据录入', + 'czcx':'测值查询', + 'syjx':'渗压监测', + 'sljx':'渗流监测', + 'wyjx':'位移监测', + 'ndsytjb':'年度渗压统计表', + 'ndsltjb':'年度渗流统计表', + 'ndwytjb':'年度位移统计表', + 'szydd':'水资源调度', + 'gsnlfx':'供水能力分析', + 'diaodu':'调度记录', + 'gstjfx':'供水统计分析', + 'dxnjyzl':'典型年降雨资料', + 'skzfzl': '水库蒸发资料', + 'sys':'系统管理', + 'user':'用户管理', + 'department':'部门管理', + 'role':'角色管理', + 'menuM':'菜单管理', + 'loginLog':'登录日志', } @@ -113,31 +181,25 @@ const DashboardLayout: React.FC = () => { // 这个方法是统计菜单点击情况的 - // useEffect(()=>{ - // (async()=>{ - // const list = location.pathname.split('/') - // let menu1:any = meunObj?.[list[2]] - // let menu2:any = meunObj?.[list[3]] - // let menu3:any = meunObj?.[list[4]] - // if(menu1==='基本情况'){ - // menu2 = '基本情况' - // } - // if(menu1==='视频监控'){ - // menu2 = '视频监控' - // } - // if(menu1==='防汛大屏'){ - // menu2 = '防汛大屏' - // } + useEffect(()=>{ + (async()=>{ + const list = location.pathname.split('/') + let menu1:any = meunObj?.[list[2]] //一级菜单 + let menu2:any = meunObj?.[list[3]] //二级菜单 + let menu3:any = meunObj?.[list[4]] //三级菜单 + if(menu1==='水库一张图'){ + menu2 = '水库一张图' + } - // const res = await httppost2(apiurl.setMenu,{ - // createId:localStorage.getItem('userId'), - // loginType:0, - // menu1:menu1, - // menu2:menu2, - // menu3:menu3 - // }) - // })() - // },[location.pathname]) + const res = await httppostAuth(apiurl.setMenu,{ + createId:localStorage.getItem('userId'), + loginType:0, + menu1:menu1, + menu2:menu2, + menu3:menu3 + }) + })() + },[location.pathname]) const menuIndexes = useMemo(() => findMenu(menu, pathname), [menu, pathname]); diff --git a/src/service/apiurl.js b/src/service/apiurl.js index 6067a7769..27f6aa934 100644 --- a/src/service/apiurl.js +++ b/src/service/apiurl.js @@ -49,6 +49,15 @@ const apiurl = { view:baseFileView }, systemM: { + action: { + todayData: service_fxdd + "/userLoginLog/todayCount", + activeCount: service_fxdd + "/userLoginLog/userCount", + userCount: service_fxdd + "/userLoginLog/visitCount", + hotData:service_fxdd + "/visitMenuLog/count" + }, + yhxwrz:{ + page:service_fxdd + "/visitMenuLog/page", + }, userM: { updatePassword:service_xyt + '/system/user/profile/updatePwd' } diff --git a/src/utils/request.js b/src/utils/request.js index 985c2b7fa..b3d856eb5 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -21,6 +21,7 @@ function request(url, options,type) { const opt = { ...options }; opt.headers = opt.headers || {}; opt.headers.Accept = 'application/json'; + // opt.headers.Authorization = "Bearer" + ' ' + localStorage.getItem('access_token'); // opt.credentials = opt.credentials || 'include'; return fetch(url, opt) @@ -398,6 +399,21 @@ export function httppost2(url, data = {}) { return send(url, options); } +export function httppostAuth(url, data = {}) { + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'adcd': localStorage.getItem('ADCD6'), + "gs-token": localStorage.getItem('access_token'), + "Authorization":"Bearer" + ' ' + localStorage.getItem('access_token') + }, + body: JSON.stringify(data), + }; + + return send(url, options); +} + export function httppost5(url, data = {}) { const options = { method: 'POST', diff --git a/src/views/AppRouters.tsx b/src/views/AppRouters.tsx index c8b32ff25..5b0c679a9 100644 --- a/src/views/AppRouters.tsx +++ b/src/views/AppRouters.tsx @@ -123,6 +123,8 @@ import Ywgz from './sz/ywgz' import Gcaq from './sz/khzbgl' //系统管理 import SystemPage from './systemMange' +import Yhxwrz from './yhxwrz' +import Yhxwfx from './yhxwfx' const HomePage = lazy(() => import('./Home')) @@ -304,6 +306,8 @@ const AppRouters: React.FC = () => { { path: 'sys/role', element: }, { path: 'sys/menuM', element: }, { path: 'sys/loginLog', element: }, + { path: 'sys/yhxwrz', element: }, + { path: 'sys/yhxwfx', element: }, ], }, { path: '/login', element: }, diff --git a/src/views/fxzb/gzpz/index.js b/src/views/fxzb/gzpz/index.js index 05f2110b6..bbf811ce9 100644 --- a/src/views/fxzb/gzpz/index.js +++ b/src/views/fxzb/gzpz/index.js @@ -22,14 +22,20 @@ const Page = () => { 2: "橙色", 3: "红色", } + const statusObj = { + 0: "未启用", + 1: "启用", + } const refModal = useRef(); const [searchVal, setSearchVal] = useState(false) const columns = [ { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" }, - { title: '预警时间', key: 'createTime', dataIndex: 'createTime', width: 140, align: "center", }, { title: '规则名称', key: 'ruleName', dataIndex: 'ruleName', width: 140, align: "center", }, { title: '预警等级', key: 'warningLevel', dataIndex: 'warningLevel', width: 100, align: "center", render: (v) => {levelObj[v]} }, - { title: '预警信息', key: 'ruleDesc', dataIndex: 'ruleDesc', width: 300, align: "center", }, + { title: '状态', key: 'status', dataIndex: 'status', width: 100,align:"center",render: (v) => {statusObj[v]} }, + { title: '规则描述', key: 'ruleDesc', dataIndex: 'ruleDesc', width: 300, align: "center", }, + { title: '创建时间', key: 'createTime', dataIndex: 'createTime', width: 140, align: "center"}, + { title: '创建人', key: 'createName', dataIndex: 'createName', width: 140, align: "center"}, { title: '操作', key: 'operation', width: 100, fixed: 'right', align: 'center', render: (value, row, index) => ( () => command(cmd)(row)} />) diff --git a/src/views/yhxwfx/hotOption.js b/src/views/yhxwfx/hotOption.js new file mode 100644 index 000000000..a37a05017 --- /dev/null +++ b/src/views/yhxwfx/hotOption.js @@ -0,0 +1,72 @@ +export default function hotOption(data) { + const result = data.map(item => { + if (item.menu3 && item.menu3 == '布置图') item.menu2 = ''; + return{ + ...item, + menu: item.menu1 + "-" + item.menu2 + (item?.menu3 ? "-" + item.menu3 : '') + } + }) + const maxY = Math.ceil(Math.max(...data.map(item => item.count))) + const minY = Math.floor(Math.min(...data.map(item => item.count))) + return { + grid: { + left:"25%", + top: "0%", + bottom:"0%" + }, + tooltip: { + trigger: "axis", + }, + calculable: true, + xAxis: { + type: "value", + min:minY, + max: maxY, + + axisLine: { + show: false + }, + axisTick: { + show: false + }, + splitLine: { + show: false + } + }, + yAxis: { + type: "category", + inverse: true, + axisLine: { + show: false + }, + axisTick: { + show: false + }, + axisLabel: { + // textStyle: { + // color: '#999' + // }, + fontSize:14//调整坐标轴字体大小 + }, + data: result.map(item => item.menu), + }, + series: [ + { + name: "", + type: "bar", + barWidth:"30%", + label: { + normal: { + show: true, + // position: "insideRight", + }, + offset:[100,0] + }, + itemStyle: { + color:"#1283e3" + }, + data: result.map(item => item.count), + }, + ], + } +} diff --git a/src/views/yhxwfx/index.js b/src/views/yhxwfx/index.js new file mode 100644 index 000000000..bc00f4b3d --- /dev/null +++ b/src/views/yhxwfx/index.js @@ -0,0 +1,254 @@ +import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react'; +import { Divider,Tabs,Dropdown,Space} from 'antd'; +import ToolBar from './toolbar'; +import { DownOutlined,UpOutlined } from '@ant-design/icons'; +import apiurl from '../../service/apiurl'; +import moment from 'moment'; +import { httpget2, httppost2 } from '../../utils/request'; +import userBarOption from "./userBarOption" +import userLineOption from "./userLineOption" +import hotOption from './hotOption'; +import ReactEcharts from 'echarts-for-react'; +import "./index.less" + +const Page = () => { + + const [searchVal, setSearchVal] = useState(false) + const [todayData, setTodayData] = useState({}) + const [activeCount, setActiveCount] = useState() + const [userCountData, setUserCountData] = useState() + const [hotData, setHotData] = useState() + const [tabs, setTabs] = useState({active:0}) + const [showMore, setShowMore] = useState(false) + const [height, setHeight] = useState("100%") + const [hotWidth, setHotWidth] = useState("100%") + const dtoption = useMemo(() => { + if (userCountData) { + return userBarOption(userCountData) + } + }, [userCountData]) + + const lineoption = useMemo(() => { + if (activeCount) { + return userLineOption(activeCount) + } + }, [activeCount]) + + const hotoption = useMemo(() => { + if (hotData) { + let substrData = []; + if (!showMore) { + substrData = hotData.slice(0, 10) + } else { + substrData = hotData + } + setHeight(((substrData.length) * 10) + "%") + try { + const labels = substrData.map(item => ( + (item.menu1 || '') + '-' + (item.menu2 || '') + (item.menu3 ? '-' + item.menu3 : '') + )); + const maxLen = Math.max(...labels.map(l => (l || '').length), 0); + const px = Math.min(Math.max(maxLen * 12 + 600, 800), 2400); + setHotWidth(px + 'px'); + } catch (e) {} + return hotOption(substrData) + } + }, [hotData,showMore]) + + + +// 获取今日数据 + const getTodayData = async () => { + try { + const res = await httpget2(apiurl.systemM.action.todayData) + setTodayData(res.data) + } catch (error) { + console.log(error); + + } + } + + // 获取日活跃数 + const getActiveCount = async (params) => { + try { + const {data} = await httppost2(apiurl.systemM.action.activeCount,params) + const {appList,webList} = data + if(appList&&webList){ + setActiveCount({appList:appList,webList:webList}) + } + } catch (error) { + console.log(error); + + } + } + + // 获取前十用户活跃数 + const getUserActiveCount = async (params) => { + try { + const { data } = await httppost2(apiurl.systemM.action.userCount, params) + const {appList,webList} = data + if(appList&&webList){ + setUserCountData({appList:appList,webList:webList}) + } + } catch (error) { + console.log(error); + } + } + + // 获取热点数据 + const getHotData = async (data) => { + try { + const res = await httppost2(apiurl.systemM.action.hotData, data) + setHotData(res.data) + } catch (error) { + console.log(error); + + } + } + useEffect(() => { + getTodayData() + }, []) + + useEffect(() => { + if (searchVal) { + getActiveCount(searchVal) + getUserActiveCount(searchVal) + + } + }, [searchVal]) + + useEffect(() => { + if (searchVal && tabs) { + const params = { + ...searchVal, + loginType:Number(tabs?.active) + } + getHotData(params) + } + }, [searchVal,tabs]) + + + return ( + <> +
+
+
+ + 今日数据总览 +
+
+
+ WEB端访问次数 +

{todayData?.web1Count || '-' }

+
+ +
+ WEB端浏览次数 +

{todayData?.web2Count || '-' }

+
+ +
+ WEB端平均访问时长 +

{todayData?.web3Count || '-' } h

+ +
+ +
+ 移动端访问次数 +

{todayData?.app1Count || '-'}

+
+ +
+ 移动端浏览次数 +

{todayData?.app2Count || '-'}

+
+ +
+ 移动端平均访问时长 +

{todayData?.app3Count || '-'} h

+ +
+ +
+
+
+ +
+
+
+
+
+ + 访问用户前十 +
+
+ +
+
+
+
+ + 日活跃用户数 +
+
+ +
+
+
+
+
+
+ + 功能热度前十 +
+ { setTabs({ active: e }); setShowMore(false)}} + items={[ + { + label: `web端`, + key: 0, + children: ``, + }, + { + label: `移动端`, + key: 1, + children: ``, + }, + ]} + /> + +
+
+ +
+
+
+ +
+ + ); +} + +export default Page; diff --git a/src/views/yhxwfx/index.less b/src/views/yhxwfx/index.less new file mode 100644 index 000000000..8be8ff9f7 --- /dev/null +++ b/src/views/yhxwfx/index.less @@ -0,0 +1,93 @@ +.action-top{ + width: 100%; + height: 170px; + background-color: #fff; + + .data-panel{ + display: flex; + justify-content: center; + column-gap: 45px; + align-items: center; + .panel-item{ + display: flex; + flex-direction: column; + align-items: center; + .name{ + color: #999999; + font-weight: 400; + font-family: '微软雅黑', sans-serif; + font-size: 16px; + } + .value{ + font-size: 28px; + } + } + } +} +.action-middle{ + width: 100%; + height: 60px; + margin: 10px 0; + background-color: #fff; + padding-left: 30px; + display: flex; + align-items: center; +} + +.action-bottom{ + width: 100%; + display: flex; + column-gap: 10px; + .left{ + width: 50%; + .left-top{ + background-color: #fff; + .left-top-charts{ + width: 100%; + height: 250px; + } + } + .left-bottom{ + background-color: #fff; + margin-top: 10px; + .left-bottom-charts{ + width: 100%; + height: 248px; + } + } + } + .right{ + width: 50%; + background-color: #fff; + .right-title{ + position: relative; + display: flex; + align-items: center; + column-gap: 20px; + .ant-tabs-top > .ant-tabs-nav, .ant-tabs-bottom > .ant-tabs-nav, .ant-tabs-top > div > .ant-tabs-nav, .ant-tabs-bottom > div > .ant-tabs-nav{ + margin: 0; + } + .ant-tabs-top > .ant-tabs-nav::before, .ant-tabs-bottom > .ant-tabs-nav::before, .ant-tabs-top > div > .ant-tabs-nav::before, .ant-tabs-bottom > div > .ant-tabs-nav::before{ + border: none; + } + .more{ + position: absolute; + right: 6%; + top: 30%; + + } + } + .right-charts{ + width: 100%; + height: 552px; + overflow-y: auto; + overflow-x: auto; + } + } +} +.comomn-title{ + display: flex; + align-items: center; + column-gap: 10px; + padding: 20px 10px; +} diff --git a/src/views/yhxwfx/toolbar.js b/src/views/yhxwfx/toolbar.js new file mode 100644 index 000000000..5012b0c05 --- /dev/null +++ b/src/views/yhxwfx/toolbar.js @@ -0,0 +1,115 @@ +import React, { useEffect,useState } from 'react'; +import { Form, Input, Button, DatePicker } from 'antd'; +import NormalSelect from '../../components/Form/NormalSelect'; +import moment from 'moment'; +const { RangePicker } = DatePicker; +const ToolBar = ({ setSearchVal, onSave, storeData }) => { + + const optionsType = [ + { + label: "今日", + value:1 + }, + { + label: "近一周", + value:2 + }, + { + label:"近一月", + value:3 + }, + { + label:"近三月", + value:4 + }, + { + label:"近一年", + value:5 + }, + ] + const [form] = Form.useForm(); + + + const onValuesChange = (e) => { + switch (e.ranger) { + case 1: + form.setFieldValue("tm", [moment().startOf("day"), moment()]) + setSearchVal({ + stm: moment().startOf("day").format("YYYY-MM-DD 00:00:00"), + etm: moment().format("YYYY-MM-DD 23:59:59") + }) + break; + case 2: + form.setFieldValue("tm",[moment().subtract(7, 'days'),moment()]) + setSearchVal({ + stm: moment().subtract(7, 'days').format("YYYY-MM-DD 00:00:00"), + etm: moment().format("YYYY-MM-DD 23:59:59") + }) + break; + case 3: + form.setFieldValue("tm",[moment().subtract(1, 'months'),moment()]) + setSearchVal({ + stm: moment().subtract(1, 'months').format("YYYY-MM-DD 00:00:00"), + etm: moment().format("YYYY-MM-DD 23:59:59") + }) + break; + case 4: + form.setFieldValue("tm",[moment().subtract(3, 'months'),moment()]) + setSearchVal({ + stm: moment().subtract(3, 'months').format("YYYY-MM-DD 00:00:00"), + etm: moment().format("YYYY-MM-DD 23:59:59") + }) + break; + case 5: + form.setFieldValue("tm",[moment().subtract(1, 'years'),moment()]) + setSearchVal({ + stm: moment().subtract(1, 'years').format("YYYY-MM-DD 00:00:00"), + etm: moment().format("YYYY-MM-DD 23:59:59") + }) + break; + default: + break; + } + } + +useEffect(() => { + form.setFieldValue("tm", [moment().subtract(7, 'days'), moment()]) + setSearchVal({ + stm: moment().subtract(7, 'days').format("YYYY-MM-DD 00:00:00"), + etm: moment().format("YYYY-MM-DD 23:59:59") + }) +}, []) + + + + return ( + <> +
+
+ + { + setSearchVal({ + stm: e[0].format("YYYY-MM-DD 00:00:00"), + etm: e[1].format("YYYY-MM-DD 23:59:59") + }) + }} + /> + + + + +
+
+ + ); +} + +export default ToolBar; \ No newline at end of file diff --git a/src/views/yhxwfx/userBarOption.js b/src/views/yhxwfx/userBarOption.js new file mode 100644 index 000000000..f6c2b100a --- /dev/null +++ b/src/views/yhxwfx/userBarOption.js @@ -0,0 +1,87 @@ +import { rotate } from "ol/coordinate"; + + +export default function userBarOption(data) { + const appList = data.appList.map(item => ({ + ...item, appCount: item?.count + })) + const webList = data.webList.map(item => ({ + ...item, webCount: item?.count + })) + const arr = [...appList,...webList] + const compareLength = appList.length - webList.length; + // 找出长度大的数组 + const mapArr1 = compareLength >= 0 ? appList : webList; + // 找出长度小的数组 + const mapArr2 = compareLength < 0 ? appList : webList; + + const maxY = Math.ceil(Math.max(...arr.map(item => item.count))) + const minY = Math.floor(Math.min(...arr.map(item => item.count))) + const result = mapArr1.map(item => { + let filterData = mapArr2.find(o => item.name == o.name) + return { + ...item, + ...filterData, + } + }) + return { + grid: { + top: "15%", + bottom:"20%" + }, + tooltip: { + trigger: "axis", + }, + legend: { + show:true + }, + + calculable: true, + xAxis: [ + { + type: "category", + axisLabel:{ + interval:0, + rotate:15 + }, + data:result.map(item => item.name), + }, + ], + yAxis: [ + { + type: "value", + name:"访问次数", + min:minY - 1, + max:maxY + 1, + axisLine: { + show: false + }, + axisTick: { + show: false + }, + + }, + ], + series: [ + { + name: "WEB端", + type: "bar", + barWidth:"13%", + itemStyle: { + color:"#357efe" + }, + data:result.map(item => item?.webCount || 0), + }, + { + name: "移动端", + type: "bar", + barWidth:"13%", + + itemStyle: { + color:"#62dffe" + }, + data:result.map(item => item?.appCount || 0), + }, + ], + } +} \ No newline at end of file diff --git a/src/views/yhxwfx/userLineOption.js b/src/views/yhxwfx/userLineOption.js new file mode 100644 index 000000000..0ca246cb7 --- /dev/null +++ b/src/views/yhxwfx/userLineOption.js @@ -0,0 +1,92 @@ +export default function userLineOption(data) { + const appList = data.appList.map(item => ({ + ...item, appCount: item?.count + })) + const webList = data.webList.map(item => ({ + ...item, webCount: item?.count + })) + const arr = [...appList,...webList] + const compareLength = appList.length - webList.length; + // 找出长度大的数组 + const mapArr1 = compareLength >= 0 ? appList : webList; + // 找出长度小的数组 + const mapArr2 = compareLength < 0 ? appList : webList; + + const maxY = Math.ceil(Math.max(...arr.map(item => item.count))) + const minY = Math.floor(Math.min(...arr.map(item => item.count))) + const result = mapArr1.map(item => { + let filterData = mapArr2.find(o => item.createDate == o.createDate) + return { + ...item, + ...filterData, + } + }) + return { + grid: { + top: "15%", + bottom:"20%" + }, + tooltip: { + trigger: "axis", + }, + legend: { + show: true, + top:"0%" + }, + + calculable: true, + xAxis: [ + { + type: "category", + data: result.map(item => item.createDate), + }, + ], + yAxis: [ + { + type: "value", + min:minY - 1, + max:maxY + 1, + axisLine: { + show: false + }, + axisTick: { + show: false + }, + }, + ], + series: [ + { + name: "WEB端", + type: "line", + smooth:true, + itemStyle: { + color:"#357efe" + }, + label: { + normal: { + show: true, + position: "top", + }, + }, + + data: result.map(item => item?.webCount || 0), + }, + { + name: "移动端", + type: "line", + smooth:true, + itemStyle: { + color:"#62dffe" + }, + label: { + normal: { + show: true, + position: "top", + }, + }, + + data: result.map(item => item?.appCount || 0), + }, + ], + } +} \ No newline at end of file diff --git a/src/views/yhxwrz/index.js b/src/views/yhxwrz/index.js new file mode 100644 index 000000000..cb51cf1e1 --- /dev/null +++ b/src/views/yhxwrz/index.js @@ -0,0 +1,68 @@ +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/usePageTable2'; +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.systemM.yhxwrz.page,params),options); + + useEffect(()=>{ + // if(isRender.current){ + // isRender.current = false + // return + // } + + const params = { + search: { + ...searchVal + } + }; + search(params) + + },[searchVal]) + + + return ( + <> +
+
+ {/* + + */} +
+ + + + + + + ); +} + +export default Page;