停车场项目web, 互联网仓库, 开发完成后, 需要将代码回传云桌面.
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

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;