Skip to content
Snippets Groups Projects
Commit c36b6fe9 authored by 汤绍坚's avatar 汤绍坚
Browse files

tsj: 餐饮油烟左侧的第一个版本

parent dd9045b8
Branches
Tags
No related merge requests found
src/assets/images/V-2504/RestaurantOil-logo-1.png

20.7 KiB

src/assets/images/V-2504/RestaurantOil-logo-2.png

18.1 KiB

.container {
display: flex;
width: 242px;
height: 140px;
background: linear-gradient(180.00deg, rgba(77, 107, 178, 0.3), rgba(8, 153, 255, 0.01) 100%);
border-radius: 15px;
box-shadow: inset 0px 0px 23px 0px rgba(31, 87, 222, 0.5);
position: relative;
}
.iconWrapper {
width: 100px;
height: 142px;
background: linear-gradient(180.00deg, rgba(73, 118, 255, 0.06), rgba(0, 255, 246, 0.2) 100%);
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
top: -1px;
left: -2px;
}
.icon {
width: 100px;
height: 142px;
object-fit: contain;
}
.content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding: 16px;
}
.label {
color: rgb(188, 206, 233);
font-family: 微软雅黑;
font-size: 16px;
font-weight: 400;
line-height: 21px;
margin-bottom: 8px;
}
.valueWrapper {
display: flex;
align-items: flex-end;
}
.value {
font-family: 'D-DIN';
font-size: 28px;
font-weight: 700;
line-height: 1.2;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.unit {
color: rgb(188, 206, 233);
font-family: 微软雅黑;
font-size: 16px;
font-weight: 400;
line-height: 21px;
margin-left: 4px;
}
\ No newline at end of file
import React from 'react';
import styles from './index.less';
interface DualBackgroundCardProps {
icon: string;
label: string;
value: number;
unit: string;
valueColor: string;
}
const DualBackgroundCard: React.FC<DualBackgroundCardProps> = ({
icon,
label,
value,
unit,
valueColor
}) => {
return (
<div className={styles.container}>
<div className={styles.iconWrapper}>
<img src={icon} className={styles.icon} alt={label} />
</div>
<div className={styles.content}>
<div className={styles.label}>{label}</div>
<div className={styles.valueWrapper}>
<span className={styles.value} style={{ background: valueColor, WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}>
{value}
</span>
<span className={styles.unit}>{unit}</span>
</div>
</div>
</div>
);
};
export default DualBackgroundCard;
\ No newline at end of file
.container {
width: 1105px;
height: 928px;
// width: 100%;
// height: 100%;
display: flex;
flex-direction: column;
// background: url('@/assets/images/V-2504/subpage-bg.png') no-repeat center center;
// background-size: 100% 100%;
background-image: url('~@/assets/images/V-2504/subpage-bg.png');
background-size: cover;
background-position: center;
border-radius: 20px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.contentWrapper {
display: flex;
gap: 20px;
width: 100%;
height: calc(100% - 50px);
padding: 0 16px 0 15px;
}
.leftSection {
display: flex;
flex-direction: column;
gap: 20px;
width: 530px;
}
.rightSection {
flex: 1;
}
/* 整体情况样式 */
.overallSection {
width: 530px;
height: 227px;
background: linear-gradient(180.00deg, rgba(77, 107, 178, 0.3), rgba(8, 153, 255, 0.01) 100%);
border-radius: 15px;
box-shadow: inset 0px 0px 23px 0px rgba(31, 87, 222, 0.5);
padding: 16px;
}
.overallContent {
display: flex;
justify-content: space-between;
margin-top: 16px;
height: calc(100% - 52px);
}
/* 告警趋势样式 */
.alertTrendSection {
width: 530px;
height: 200px;
background: linear-gradient(180.00deg, rgba(77, 107, 178, 0.3), rgba(8, 153, 255, 0.01) 100%);
border-radius: 15px;
box-shadow: inset 0px 0px 23px 0px rgba(31, 87, 222, 0.5);
padding: 16px;
}
.alertTrendContent {
height: calc(100% - 52px);
}
/* 告警区域样式 */
.alertAreaSection {
width: 530px;
height: 380px;
background: linear-gradient(180.00deg, rgba(77, 107, 178, 0.3), rgba(8, 153, 255, 0.01) 100%);
border-radius: 15px;
box-shadow: inset 0px 0px 23px 0px rgba(31, 87, 222, 0.5);
padding: 16px;
}
.alertAreaContent {
height: calc(100% - 52px);
}
/* 告警排行样式 */
.alertRankingSection {
width: 530px;
height: 844px;
background: linear-gradient(180.00deg, rgba(77, 107, 178, 0.3), rgba(8, 153, 255, 0.01) 100%);
border-radius: 15px;
box-shadow: inset 0px 0px 23px 0px rgba(31, 87, 222, 0.5);
padding: 16px;
}
.alertRankingContent {
height: calc(100% - 52px);
overflow-y: auto;
}
\ No newline at end of file
import React, { useCallback, useState } from 'react';
import PanelTitle from '@/pages/Home_v_2504/components/common/PanelTitle';
import DateSelector from '@/components/V2504/DateSelector';
import ModuleTitleWithTabs from '@/pages/Home_v_2504/components/common/ModuleTitleWithTabs';
import SmoothLineChart from '@/components/V2504/SmoothLineChart';
import AreaBarList from '@/components/V2504/AreaBarList';
import DualBackgroundCard from './components/DualBackgroundCard';
import styles from './index.less';
// 导入图标
import logo1 from '@/assets/images/V-2504/RestaurantOil-logo-1.png';
import logo2 from '@/assets/images/V-2504/RestaurantOil-logo-2.png';
// 类型定义
type AreaType = 'all' | 'urban' | 'central' | 'county';
interface AreaData {
name: string;
percentage: number;
count: number;
}
const LeftContent: React.FC = () => {
// 状态
const [dateType, setDateType] = useState<string>('day');
const [dateRange, setDateRange] = useState<{ startTime: string; endTime: string }>({
startTime: '',
endTime: '',
});
const [alertTrendData, setAlertTrendData] = useState<{ time: string; value: number }[]>([]);
const [activeAreaType, setActiveAreaType] = useState<AreaType>('all');
const [activeRankingType, setActiveRankingType] = useState<AreaType>('all');
const [alertAreaData, setAlertAreaData] = useState<AreaData[]>([
{ name: '锦江区', percentage: 37.2, count: 456 },
{ name: '金牛区', percentage: 33.5, count: 400 },
{ name: '成华区', percentage: 20.8, count: 322 },
{ name: '青羊区', percentage: 15.6, count: 186 },
{ name: '双流区', percentage: 12.9, count: 152 },
]);
const [alertRankingData, setAlertRankingData] = useState<AreaData[]>([
{ name: '成都麻辣传奇火锅店', percentage: 87.2, count: 7582 },
{ name: '宽窄巷子老灶火锅', percentage: 83.5, count: 7277 },
{ name: '锦鲤古街风情火锅', percentage: 70.8, count: 7004 },
{ name: '辣斗拉火锅春熙路店', percentage: 65.6, count: 6985 },
{ name: '川西坝子火锅', percentage: 62.9, count: 6932 },
{ name: '蜀九香火锅', percentage: 60.6, count: 6820 },
{ name: '巴蜀大将火锅', percentage: 58.5, count: 6755 },
{ name: '龙抄手火锅', percentage: 55.4, count: 6666 },
{ name: '老妈蹄花火锅', percentage: 50.3, count: 6338 },
{ name: '钢管厂老火锅', percentage: 48.2, count: 6000 },
{ name: '洞子口张老二凉粉', percentage: 45.1, count: 5882 },
{ name: '川西印象火锅', percentage: 42.0, count: 5661 },
]);
// 处理日期变化
const handleDateChange = useCallback((params: { type: string; startTime: string; endTime: string }) => {
setDateType(params.type);
setDateRange({
startTime: params.startTime,
endTime: params.endTime,
});
}, []);
// 生成趋势数据
React.useEffect(() => {
const now = new Date();
const getMonthDays = () => {
return new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
};
const mockData = Array.from({ length: getMonthDays() }, (_, i) => ({
time: `${now.getMonth() + 1}${i + 1}日`,
value: Math.floor(Math.random() * 50) + 10
}));
setAlertTrendData(mockData);
}, []);
return (
<div className={styles.container}>
{/* 标题 */}
<div className={styles.header}>
<PanelTitle title="餐饮油烟事件" />
<DateSelector
onChange={handleDateChange}
defaultType="month"
/>
</div>
<div className={styles.contentWrapper}>
{/* 左侧内容区域 */}
<div className={styles.leftSection}>
{/* 整体情况 */}
<div className={styles.overallSection}>
<ModuleTitleWithTabs title="整体情况" />
<div className={styles.overallContent}>
<DualBackgroundCard
icon={logo1}
label="设备数量"
value={5.98}
unit="万个"
valueColor="linear-gradient(180.00deg, rgb(170, 255, 246), rgb(37, 187, 255))"
/>
<DualBackgroundCard
icon={logo2}
label="告警次数"
value={5.98}
unit="万个"
valueColor="linear-gradient(180.00deg, rgb(255, 118, 108), rgb(255, 79, 79))"
/>
</div>
</div>
{/* 告警趋势 */}
<div className={styles.alertTrendSection}>
<ModuleTitleWithTabs title="告警趋势" />
<div className={styles.alertTrendContent}>
<SmoothLineChart
data={alertTrendData}
unitText="单位:件"
lineColor="rgb(255, 100, 89)"
lineColorStop1="rgba(255, 100, 89, 0)"
lineColorStop2="rgba(255, 100, 89, 0.36)"
style={{ height: '158px', width: '100%' }}
/>
</div>
</div>
{/* 告警区域 */}
<div className={styles.alertAreaSection}>
<ModuleTitleWithTabs
title="告警区域"
tabs={[
{ key: 'all', label: '全部' },
{ key: 'urban', label: '城市新区' },
{ key: 'central', label: '中心城区' },
{ key: 'county', label: '县市新城' },
]}
activeKey={activeAreaType}
onTabChange={(key) => setActiveAreaType(key as AreaType)}
/>
<div className={styles.alertAreaContent}>
<AreaBarList
data={alertAreaData}
showCount={true}
height={290}
progressColor={{ from: 'rgb(255, 204, 122)', to: 'rgb(255, 148, 148)' }}
/>
</div>
</div>
</div>
{/* 右侧内容区域 */}
<div className={styles.rightSection}>
{/* 告警排行 */}
<div className={styles.alertRankingSection}>
<ModuleTitleWithTabs
title="告警排行"
tabs={[
{ key: 'all', label: '全部' },
{ key: 'urban', label: '城市新区' },
{ key: 'central', label: '中心城区' },
{ key: 'county', label: '县市新城' },
]}
activeKey={activeRankingType}
onTabChange={(key) => setActiveRankingType(key as AreaType)}
/>
<div className={styles.alertRankingContent}>
<AreaBarList
data={alertRankingData}
showCount={true}
height={754}
progressColor={{ from: 'rgb(0, 185, 255)', to: 'rgb(121, 255, 209)' }}
/>
</div>
</div>
</div>
</div>
</div>
);
};
export default LeftContent;
\ No newline at end of file
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
.leftSidebar { .leftSidebar {
width: 1105px; width: 1105px;
margin-left: 40px;
// height: 100%; // height: 100%;
// height: 928px; // height: 928px;
pointer-events: auto; // Make the sidebar respond to events pointer-events: auto; // Make the sidebar respond to events
......
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useDashboard } from '../../context'; import { useDashboard } from '../../context';
import RightContent from './components/RightContent'; import RightContent from './components/RightContent';
import LeftContent from './components/LeftContent';
import styles from './index.less'; import styles from './index.less';
interface RestaurantOilProps { interface RestaurantOilProps {
...@@ -24,7 +25,7 @@ const RestaurantOil: React.FC<RestaurantOilProps> = ({ visible }) => { ...@@ -24,7 +25,7 @@ const RestaurantOil: React.FC<RestaurantOilProps> = ({ visible }) => {
<div className={styles.container}> <div className={styles.container}>
{/* 左侧内容区域 - 通过CSS设置pointer-events为auto,仅在有内容的区域启用事件 */} {/* 左侧内容区域 - 通过CSS设置pointer-events为auto,仅在有内容的区域启用事件 */}
<div className={styles.leftSidebar}> <div className={styles.leftSidebar}>
{/* 左侧内容将在后续实现 */} <LeftContent />
</div> </div>
{/* 中间区域 - 保持pointer-events: none让地图可交互 */} {/* 中间区域 - 保持pointer-events: none让地图可交互 */}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment