You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
618 lines
25 KiB
618 lines
25 KiB
import React, { useState, useEffect } from "react";
|
|
import { ResultFlowResult } from "@/components";
|
|
import { Select, Input, Button, Table, message, Pagination, DatePicker, Modal, Cascader, Tooltip } from "antd";
|
|
import { useSessionStorageState } from "ahooks";
|
|
import { lineChartOption, ringChartOption } from "../echarts.config";
|
|
import { dictionary } from "@/config/common";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { setTabList } from "@/store/common.js";
|
|
import { useSelector, useDispatch } from "react-redux";
|
|
import { QuestionCircleFilled } from "@ant-design/icons"
|
|
import moment from "moment";
|
|
import ReactEcharts from "echarts-for-react";
|
|
import "./index.scss";
|
|
import ajax from "@/services";
|
|
|
|
function ParkTurnoverAly() {
|
|
// session缓存
|
|
const [defaultParams, setDefaultParams] = useSessionStorageState(
|
|
"formData_parkTurnoverAly",
|
|
{ defaultValue: null }
|
|
);
|
|
//区域的下拉数据
|
|
const [areaList, setAreaList] = useState([]);
|
|
// 默认数据
|
|
const defaultData = {
|
|
start_time: moment().subtract('days').startOf('day').format("YYYY-MM-DD"),
|
|
end_time: moment().endOf("day").format("YYYY-MM-DD"),
|
|
date_type: '1', //
|
|
car_parking_type:'3'
|
|
};
|
|
// 分页数据
|
|
const [pageInfo, setPageInfo] = useState({
|
|
pn: defaultParams ? defaultParams?.pn : 1,
|
|
page_size: defaultParams ? defaultParams?.page_size : 15,
|
|
});
|
|
// 表单数据
|
|
const [formData, setFormData] = useState({
|
|
...defaultData,
|
|
...defaultParams,
|
|
});
|
|
// 搜索提交数据-存储
|
|
const [holdData, setHoldData] = useState(formData);
|
|
// 访问接口,isAjax改变时执行
|
|
const [isAjax, setIsAjax] = useState(false);
|
|
// 检索按钮加载状态
|
|
const [loading, setLoading] = useState(false);
|
|
// 表格加载状态
|
|
const [tabLoading, setTabLoading] = useState(false);
|
|
// 表格返回数据
|
|
const [resultData, setResultData] = useState([]);
|
|
//泊位利用率
|
|
const [revenueData, setRevenueData] = useState({});
|
|
//进出场趋势
|
|
const [lineData, setLineData] = useState({});
|
|
const [searchSelectList, setSearchSelectList] = useState([]); //搜索下拉数据
|
|
const [sessionTabList, setSessionTabList] = useSessionStorageState('parkTurnoverAly', {
|
|
value: {
|
|
}
|
|
})
|
|
const columns = [
|
|
{
|
|
title: '时间',
|
|
dataIndex: 'time',
|
|
key: 'time',
|
|
// width: 100,
|
|
// fixed: 'left',
|
|
},
|
|
|
|
{
|
|
title: '入场次数',
|
|
dataIndex: 'in_num',
|
|
key: 'in_num',
|
|
},
|
|
{
|
|
title: '出场次数',
|
|
dataIndex: 'out_num',
|
|
key: 'out_num',
|
|
},
|
|
{
|
|
title: '总泊位数',
|
|
dataIndex: 'roads_num',
|
|
key: 'roads_num',
|
|
},
|
|
{
|
|
title: '周转次数',
|
|
dataIndex: 'rato',
|
|
key: 'rato',
|
|
},
|
|
]
|
|
useEffect(() => {
|
|
if (sessionTabList && Object.values(sessionTabList).length > 0) {
|
|
setFormData({
|
|
...formData, ...sessionTabList
|
|
})
|
|
getCheck({
|
|
...sessionTabList
|
|
})
|
|
} else {
|
|
getCheck()
|
|
}
|
|
}, [isAjax])
|
|
useEffect(() => {
|
|
setSessionTabList({
|
|
...formData
|
|
})
|
|
}, [formData])
|
|
useEffect(() => {
|
|
getSelectList();
|
|
}, []);
|
|
|
|
// 访问接口,获取表格
|
|
// useEffect(() => {
|
|
// getData();
|
|
// }, [isAjax]);
|
|
//时间状态切换
|
|
const TimeChange = () => {
|
|
let e = formData.date_type;
|
|
let str = "day";
|
|
let mat = "YYYY-MM-DD";
|
|
if (e == 4) {
|
|
str = "year";
|
|
mat = "YYYY";
|
|
} else if (e == 3) {
|
|
str = "month";
|
|
mat = "YYYY-MM";
|
|
} else if (e == 2) {
|
|
str = "week";
|
|
mat = "YYYY-MM-DD";
|
|
}
|
|
return { str, mat };
|
|
};
|
|
//切换时间变化
|
|
const SetTimeNow = (e) => {
|
|
let start = "";
|
|
let end = "";
|
|
if (e == 4) {
|
|
start = moment().format("YYYY");
|
|
end = moment().format("YYYY");
|
|
} else if (e == 3) {
|
|
start = moment().startOf('month').format("YYYY-MM-DD");
|
|
end = moment().endOf("month").format("YYYY-MM-DD");
|
|
} else if (e == 2) {
|
|
start = moment().day(1).format("YYYY-MM-DD");
|
|
end = moment().day(7).format("YYYY-MM-DD");
|
|
} else {
|
|
start = moment().startOf("day").format("YYYY-MM-DD");
|
|
end = moment().endOf("day").format("YYYY-MM-DD");
|
|
}
|
|
setFormData({
|
|
...formData,
|
|
date_type: e,
|
|
start_time: start,
|
|
end_time: end,
|
|
});
|
|
};
|
|
//泊位利用率变化趋势
|
|
const getRevenueOption = (data) => {
|
|
if(!data) return
|
|
console.log(data)
|
|
// 获取所有地区名称
|
|
data.sort((a, b) => {
|
|
return new Date(a.date) - new Date(b.date);
|
|
});
|
|
const areaNames = data[0].name ? [...new Set(data.map((item) => item.name))] : [''];
|
|
// 获取所有日期
|
|
const dates = [...new Set(data.map((item) => item.date))].sort(
|
|
(a, b) => a.date - b.date
|
|
);
|
|
// 构建数据对象
|
|
const seriesData = areaNames.map((areaName, index) => {
|
|
// 获取该地区的数据
|
|
const areaData = data[0].name ? data.filter((item) => item.name === areaName) : data
|
|
// 构建该地区的数据对象
|
|
return {
|
|
name: areaNames.length > 1 ? areaName : '',
|
|
type: "line",
|
|
itemStyle: {
|
|
label: {
|
|
show: true, //开启显示
|
|
position: 'top', //在上方显示
|
|
color: 'white',//字体颜色
|
|
fontSize: 10//字体大小
|
|
},
|
|
},
|
|
data: dates.map((item) => {
|
|
for (const { date, rato } of areaData) {
|
|
if (date === item) return rato;
|
|
}
|
|
return 0;
|
|
}),
|
|
};
|
|
});
|
|
console.log(seriesData)
|
|
// 构建X轴数据
|
|
const xAxisData = dates.map((date) => {
|
|
return {
|
|
value: date,
|
|
align: "center",
|
|
lineStyle: {
|
|
color: "skyblue", // 设置线的颜色为天蓝色
|
|
shadowBlur: 6,
|
|
},
|
|
|
|
};
|
|
});
|
|
setRevenueData(lineChartOption(areaNames, xAxisData, "周转次数(次)", seriesData));
|
|
};
|
|
//进出场趋势
|
|
const getLineOption = (data) => {
|
|
if(!data) return
|
|
// 获取所有地区名称
|
|
data.sort((a, b) => {
|
|
return new Date(a.date) - new Date(b.date);
|
|
});
|
|
const areaNames = data[0].name ? [...new Set(data.map((item) => item.name))] : ['入场次数','出场次数'];
|
|
// 获取所有日期
|
|
const dates = [...new Set(data.map((item) => item.date))].sort(
|
|
(a, b) => a.date - b.date
|
|
);
|
|
// 构建数据对象
|
|
const seriesData = areaNames.map((areaName, index) => {
|
|
let newsave = ''
|
|
if (index==0) {
|
|
newsave = data.map((item) => { return item.in_num })
|
|
}else{
|
|
newsave = data.map((item) => { return item.out_num })
|
|
}
|
|
// 数据
|
|
const areaData = data[0].name ? data.filter((item) => item.name === areaName) : data
|
|
// 构建数据对象
|
|
return {
|
|
name: areaNames.length > 1 ? areaName : '',
|
|
type: "line",
|
|
itemStyle: {
|
|
label: {
|
|
show: true, //开启显示
|
|
position: 'top', //在上方显示
|
|
color: 'white',//字体颜色
|
|
fontSize: 10//字体大小
|
|
},
|
|
},
|
|
data: newsave
|
|
};
|
|
});
|
|
console.log(seriesData)
|
|
// 构建X轴数据
|
|
const xAxisData = dates.map((date) => {
|
|
return {
|
|
value: date,
|
|
align: "center",
|
|
lineStyle: {
|
|
color: "skyblue", // 设置线的颜色为天蓝色
|
|
shadowBlur: 6,
|
|
},
|
|
|
|
};
|
|
});
|
|
setLineData(lineChartOption(areaNames, xAxisData, "数量(次)", seriesData));
|
|
};
|
|
function getParkingIncome(data) {
|
|
ajax
|
|
.getparkTurnoverAlyList(data)
|
|
.then((res) => {
|
|
if (res.status === 20000) {
|
|
console.log(res)
|
|
getRevenueOption(res.data.turnover);
|
|
getLineOption(res.data.in_out)
|
|
setResultData(res.data.chat)
|
|
}
|
|
})
|
|
.catch((err) => console.error(err));
|
|
}
|
|
|
|
// 获取下拉数据
|
|
const getSelectList = () => {
|
|
ajax.getOperator().then((e) => {
|
|
setSearchSelectList([
|
|
...searchSelectList,
|
|
...e.data
|
|
])
|
|
})
|
|
};
|
|
|
|
// 携带参数处理
|
|
const getCheck = (v) => {
|
|
let postData = { ...formData };
|
|
if (!loading) {
|
|
postData = { ...holdData };
|
|
}
|
|
setDefaultParams({ ...postData, ...pageInfo });
|
|
if (moment(formData.end_time) - moment(formData.start_time) > 1000 * 31 * 24 * 3600) {
|
|
message.error("时间范围限制为31天!")
|
|
setLoading(false);
|
|
setTabLoading(false);
|
|
return
|
|
}
|
|
setTabLoading(true);
|
|
setLoading(false);
|
|
let params = { ...postData, ...v, ...pageInfo }
|
|
//请求接口
|
|
getParkingIncome(params)
|
|
};
|
|
// 检索数据
|
|
const handleSearch = () => {
|
|
setLoading(true);
|
|
setPageInfo({ ...pageInfo, ...{ pn: 1 } });
|
|
setHoldData(formData);
|
|
setIsAjax(!isAjax);
|
|
};
|
|
|
|
// 导出
|
|
const handleExport = () => {
|
|
if (tableData.list.area_list?.length > 0) {
|
|
let { pn, page_size, ...params } = defaultParams;
|
|
ajax.getParkingAlyDurationParkingExp(defaultParams).then(
|
|
(res) => {
|
|
if (res) {
|
|
window.open(res.data.export_url)
|
|
} else {
|
|
message.error(res?.message);
|
|
}
|
|
},
|
|
(err) => {
|
|
console.log(err);
|
|
}
|
|
);
|
|
} else {
|
|
message.error("暂无数据");
|
|
}
|
|
};
|
|
//区域下拉框数据
|
|
useEffect(() => {
|
|
ajax
|
|
.getAreaTree()
|
|
.then((res) => {
|
|
if (res.status === 20000) {
|
|
setAreaList(res.data);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.error(err);
|
|
});
|
|
}, []);
|
|
return (
|
|
<>
|
|
<div className="edit-order-inquiry">
|
|
<div className="paid-search">
|
|
<div className="title">查询条件</div>
|
|
<div className="form-Wrap">
|
|
<div className="yisa-search">
|
|
<label>区域</label>
|
|
<Cascader
|
|
className="form-con"
|
|
popupClassName="start-exception-deal-cascader"
|
|
options={areaList}
|
|
placeholder="请选择区域"
|
|
expandTrigger="hover"
|
|
fieldNames={{
|
|
label: "name",
|
|
value: "id",
|
|
children: "children",
|
|
}}
|
|
value={formData.area_id}
|
|
onChange={(v, option) => {
|
|
setFormData({ ...formData, area_id: v ? v : null });
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="yisa-search">
|
|
<label>运营商</label>
|
|
<Select
|
|
className="form-con"
|
|
placeholder="请选择"
|
|
options={searchSelectList || []}
|
|
value={formData.operator_id}
|
|
onChange={(v) =>
|
|
setFormData({ ...formData, operator_id: v })
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="yisa-search">
|
|
<label>车场类型</label>
|
|
<Select
|
|
className="form-con"
|
|
placeholder="请选择车场类型"
|
|
options={[
|
|
{
|
|
label: '全部',
|
|
value: '3',
|
|
},
|
|
{
|
|
label: '路内车场',
|
|
value: '1',
|
|
},
|
|
{
|
|
label: '路外车场',
|
|
value: '2',
|
|
},
|
|
]}
|
|
value={formData.car_parking_type}
|
|
onChange={(v) =>
|
|
setFormData({ ...formData, car_parking_type: v })
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="yisa-search">
|
|
<label>停车场</label>
|
|
<Input
|
|
className="form-con"
|
|
placeholder="请输入"
|
|
value={formData?.road_name}
|
|
onChange={(e) =>
|
|
setFormData({ ...formData, road_name: e.target.value })
|
|
}
|
|
/>
|
|
</div>
|
|
{/* <div className="yisa-search">
|
|
<label>计费类型</label>
|
|
<Select
|
|
className="form-con"
|
|
placeholder="请选择计费类型"
|
|
options={[
|
|
{
|
|
label: '全部',
|
|
value: '0',
|
|
},
|
|
{
|
|
label: '一类区',
|
|
value: '1',
|
|
},
|
|
{
|
|
label: '二类区',
|
|
value: '2',
|
|
},
|
|
{
|
|
label: '三类区',
|
|
value: '3',
|
|
},
|
|
]}
|
|
value={formData.pay_merchant_id}
|
|
onChange={(v) =>
|
|
setFormData({ ...formData, pay_merchant_id: v })
|
|
}
|
|
/>
|
|
</div> */}
|
|
<div className="yisa-search">
|
|
<label>日期
|
|
<div className="daf">
|
|
<Select
|
|
value={formData.date_type}
|
|
// style={{
|
|
// width: "100%",
|
|
// }}
|
|
placeholder="请选择"
|
|
options={[
|
|
{
|
|
value: "1",
|
|
label: "日",
|
|
},
|
|
{
|
|
value: "2",
|
|
label: "周",
|
|
},
|
|
{
|
|
value: "3",
|
|
label: "月",
|
|
},
|
|
]}
|
|
onChange={(e) => SetTimeNow(e)}
|
|
/>
|
|
</div>
|
|
</label>
|
|
<DatePicker
|
|
style={{ width: "100%" }}
|
|
// showTime
|
|
format={TimeChange().mat}
|
|
picker={TimeChange().str}
|
|
allowClear={false}
|
|
value={formData.start_time ? moment(formData.start_time) : null}
|
|
onChange={(date, dateString) => {
|
|
if (TimeChange().str == "week") {
|
|
setFormData({
|
|
...formData,
|
|
start_time: date
|
|
? moment(date).day(1).format("YYYY-MM-DD")
|
|
: null,
|
|
});
|
|
} else if (TimeChange().str == "day") {
|
|
if (date > moment(formData.end_time)) {
|
|
setFormData({
|
|
...formData,
|
|
end_time: dateString,
|
|
start_time: formData.end_time,
|
|
});
|
|
} else {
|
|
setFormData({
|
|
...formData,
|
|
start_time: dateString,
|
|
});
|
|
}
|
|
} else if (TimeChange().str == "month") {
|
|
setFormData({ ...formData, start_time: moment(date).format("YYYY-MM-DD"), end_time: moment(date).endOf("month").format("YYYY-MM-DD") });
|
|
} else {
|
|
setFormData({ ...formData, start_time: dateString });
|
|
}
|
|
}}
|
|
disabledDate={(current) => current > moment(formData.end_time)}
|
|
/>
|
|
|
|
</div>
|
|
<div className="yisa-search">
|
|
<label>至</label>
|
|
<DatePicker
|
|
style={{ width: "100%" }}
|
|
// showTime
|
|
format={TimeChange().mat}
|
|
picker={TimeChange().str}
|
|
allowClear={false}
|
|
value={formData.end_time ? moment(formData.end_time) : null}
|
|
onChange={(date, dateString) => {
|
|
if (TimeChange().str == "week") {
|
|
setFormData({
|
|
...formData,
|
|
end_time: date
|
|
? moment(date).day(7).format("YYYY-MM-DD")
|
|
: null,
|
|
});
|
|
} else if (TimeChange().str == "day") {
|
|
if (date < moment(formData.start_time)) {
|
|
setFormData({
|
|
...formData,
|
|
start_time: dateString,
|
|
end_time: formData.start_time,
|
|
});
|
|
} else {
|
|
setFormData({
|
|
...formData,
|
|
end_time: dateString,
|
|
});
|
|
}
|
|
} else if (TimeChange().str == "month") {
|
|
setFormData({ ...formData, start_time: moment(date).startOf('month').format("YYYY-MM-DD"), end_time: moment(date).format("YYYY-MM-DD") });
|
|
} else {
|
|
setFormData({ ...formData, end_time: dateString });
|
|
}
|
|
}}
|
|
disabledDate={(current) =>
|
|
current < moment(formData.start_time)
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="form-btn">
|
|
<Button
|
|
className="reset"
|
|
onClick={() => setFormData(defaultData)}
|
|
>
|
|
重置
|
|
</Button>
|
|
<Button
|
|
className="submit"
|
|
type="primary"
|
|
onClick={handleSearch}
|
|
loading={loading}
|
|
>
|
|
查询
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="paid-result usage-result">
|
|
<div className="result">
|
|
<div className="result-box">
|
|
<div className="result-box-title">进出场趋势</div>
|
|
<Tooltip
|
|
placement="topLeft"
|
|
title={<span>展示统计时间段内的车辆入场与车辆出场次数变化趋势</span>}
|
|
>
|
|
<i>?</i>
|
|
</Tooltip>
|
|
<ReactEcharts
|
|
option={lineData}
|
|
style={{ height: "300px", width: "100%", overflow: "hidden" }}
|
|
/>
|
|
</div>
|
|
<div className="result-box">
|
|
<div className="result-box-title">泊位利用率变化趋势</div>
|
|
<Tooltip
|
|
placement="topLeft"
|
|
title={<span>展示统计时间段内的泊位利用率的趋势变化情况</span>}
|
|
>
|
|
<i>?</i>
|
|
</Tooltip>
|
|
<ReactEcharts
|
|
option={revenueData}
|
|
style={{ height: "300px", width: "100%", overflow: "hidden" }}
|
|
/>
|
|
</div>
|
|
<div className="result-box">
|
|
<Table
|
|
columns={columns}
|
|
dataSource={resultData||[]}
|
|
bordered
|
|
rowKey={"date"}
|
|
size="middle"
|
|
// scroll={{
|
|
// x: 'calc(700px + 50%)',
|
|
// y: 240,
|
|
// }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default ParkTurnoverAly;
|