Просмотр исходного кода

✨ feat(FinancialDashboard): 实现3D柱状图视觉效果

- 添加ProfitTotalBar和ProfitNetBar两个自定义3D柱状图组件
- 替换原有的普通柱状图为自定义3D柱状图组件
- 移除旧的渐变定义,使用新的3D SVG路径和渐变效果
- 调整柱状图尺寸和样式以匹配3D视觉效果
yourname 2 месяцев назад
Родитель
Сommit
240bd27dd5
1 измененных файлов с 108 добавлено и 16 удалено
  1. 108 16
      src/client/home/pages/FinancialDashboard/components/ProfitMetrics.tsx

+ 108 - 16
src/client/home/pages/FinancialDashboard/components/ProfitMetrics.tsx

@@ -23,6 +23,112 @@ const chartData = profitData.map(item => ({
   '净利润': item.profitNet
 }));
 
+// 自定义 3D 柱状图组件 - 利润总额
+const ProfitTotalBar = (props: any) => {
+  const { x, y, width, height } = props;
+
+  // 将Recharts的坐标系转换为SVG的坐标系
+  const svgWidth = 50;
+  const svgHeight = 165;
+  const scaleX = width / svgWidth;
+  const scaleY = height / svgHeight;
+
+  return (
+    <g transform={`translate(${x},${y}) scale(${scaleX},${scaleY})`}>
+      <path d="M24.5 163H0L0 3L24.5 3L24.5 163Z" fill="url(#paint0_linear_1977_58918)"/>
+      <rect x="24.5" y="3" width="1" height="160" fill="url(#paint1_linear_1977_58918)"/>
+      <path d="M50 163H25.5L25.5 3L50 3L50 163Z" fill="url(#paint2_linear_1977_58918)"/>
+      <path d="M0 162.998L25 165L50 162.998L25 160.667L0 162.998Z" fill="url(#paint3_linear_1977_58918)" fillOpacity="0.6"/>
+      <path d="M24.5 159.5H25.5V164.5H24.5V159.5Z" fill="url(#paint4_linear_1977_58918)"/>
+      <path d="M25 0L0 2.99636L25 6L50 2.99636L25 0Z" fill="url(#paint5_linear_1977_58918)"/>
+      <path d="M0 3C4.26855 3.36748 8.47493 3.78174 12.6813 4.20267C14.7949 4.40312 16.867 4.63697 18.9598 4.85746L25.2383 5.52561H24.7617L31.0402 4.85746C33.133 4.63697 35.2051 4.40312 37.3187 4.20267C41.5251 3.78174 45.7315 3.36748 50 3C45.9387 3.54788 41.8152 4.049 37.6917 4.54343C35.6403 4.79733 33.5475 5.0245 31.4753 5.25835L25.2383 5.96659L24.9896 6L24.7617 5.97327L18.5247 5.26503C16.4525 5.0245 14.3597 4.80401 12.3083 4.54343C8.18483 4.049 4.06133 3.54788 0 3Z" fill="url(#paint6_linear_1977_58918)"/>
+      <defs>
+        <linearGradient id="paint0_linear_1977_58918" x1="12.2445" y1="162.179" x2="12.2445" y2="3.00425" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#0058FF" stopOpacity="0.2"/>
+          <stop offset="1" stopColor="#0093DD"/>
+        </linearGradient>
+        <linearGradient id="paint1_linear_1977_58918" x1="25" y1="3" x2="25" y2="163" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#C2E6FF"/>
+          <stop offset="1" stopColor="#0044AA" stopOpacity="0.3"/>
+        </linearGradient>
+        <linearGradient id="paint2_linear_1977_58918" x1="37.7445" y1="165.002" x2="37.7445" y2="1.63682" gradientUnits="userSpaceOnUse">
+          <stop offset="0.00462963" stopColor="#0138DE" stopOpacity="0.2"/>
+          <stop offset="1" stopColor="#006BBC"/>
+        </linearGradient>
+        <linearGradient id="paint3_linear_1977_58918" x1="25" y1="160.667" x2="25" y2="165" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#0A316C"/>
+          <stop offset="1" stopColor="#1B659B"/>
+        </linearGradient>
+        <linearGradient id="paint4_linear_1977_58918" x1="25.5" y1="159.885" x2="25.5" y2="164.885" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#1F3453"/>
+          <stop offset="1" stopColor="#40558D" stopOpacity="0"/>
+        </linearGradient>
+        <linearGradient id="paint5_linear_1977_58918" x1="25.0039" y1="5.9965" x2="25.0039" y2="0" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#81E4FF"/>
+          <stop offset="1" stopColor="#0072DD"/>
+        </linearGradient>
+        <linearGradient id="paint6_linear_1977_58918" x1="24.9936" y1="5.99719" x2="24.9936" y2="2.5" gradientUnits="userSpaceOnUse">
+          <stop stopColor="white"/>
+          <stop offset="1" stopColor="white" stopOpacity="0.3"/>
+        </linearGradient>
+      </defs>
+    </g>
+  );
+};
+
+// 自定义 3D 柱状图组件 - 净利润
+const ProfitNetBar = (props: any) => {
+  const { x, y, width, height } = props;
+
+  // 将Recharts的坐标系转换为SVG的坐标系
+  const svgWidth = 50;
+  const svgHeight = 134;
+  const scaleX = width / svgWidth;
+  const scaleY = height / svgHeight;
+
+  return (
+    <g transform={`translate(${x},${y}) scale(${scaleX},${scaleY})`}>
+      <path d="M24.5 132H0L0 3L24.5 3L24.5 132Z" fill="url(#paint0_linear_1977_58932)"/>
+      <rect x="24.5" y="3" width="1" height="129" fill="url(#paint1_linear_1977_58932)"/>
+      <path d="M50 132H25.5L25.5 3L50 3V132Z" fill="url(#paint2_linear_1977_58932)"/>
+      <path d="M0 131.998L25 134L50 131.998L25 129.667L0 131.998Z" fill="url(#paint3_linear_1977_58932)" fillOpacity="0.6"/>
+      <path d="M24.5 128.5H25.5V133.5H24.5V128.5Z" fill="url(#paint4_linear_1977_58932)"/>
+      <path d="M25 0L0 2.99636L25 6L50 2.99636L25 0Z" fill="url(#paint5_linear_1977_58932)"/>
+      <path d="M0 3C4.26855 3.36748 8.47493 3.78174 12.6813 4.20267C14.7949 4.40312 16.867 4.63697 18.9598 4.85746L25.2383 5.52561H24.7617L31.0402 4.85746C33.133 4.63697 35.2051 4.40312 37.3187 4.20267C41.5251 3.78174 45.7315 3.36748 50 3C45.9387 3.54788 41.8152 4.049 37.6917 4.54343C35.6403 4.79733 33.5475 5.0245 31.4753 5.25835L25.2383 5.96659L24.9896 6L24.7617 5.97327L18.5247 5.26503C16.4525 5.0245 14.3597 4.80401 12.3083 4.54343C8.18483 4.049 4.06133 3.54788 0 3Z" fill="url(#paint6_linear_1977_58932)"/>
+      <defs>
+        <linearGradient id="paint0_linear_1977_58932" x1="12.2445" y1="131.719" x2="12.2445" y2="3.00436" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#907EFF" stopOpacity="0.2"/>
+          <stop offset="1" stopColor="#7B65FF"/>
+        </linearGradient>
+        <linearGradient id="paint1_linear_1977_58932" x1="25" y1="3" x2="25" y2="132" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#DCCFFF"/>
+          <stop offset="1" stopColor="#7E52FA" stopOpacity="0.3"/>
+        </linearGradient>
+        <linearGradient id="paint2_linear_1977_58932" x1="37.7445" y1="131.719" x2="37.7445" y2="3.00436" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#826DFF" stopOpacity="0.2"/>
+          <stop offset="1" stopColor="#6E3AFF"/>
+        </linearGradient>
+        <linearGradient id="paint3_linear_1977_58932" x1="25" y1="129.667" x2="25" y2="134" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#493FB5"/>
+          <stop offset="1" stopColor="#7454CF"/>
+        </linearGradient>
+        <linearGradient id="paint4_linear_1977_58932" x1="25.5" y1="128.885" x2="25.5" y2="133.885" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#4A3C72"/>
+          <stop offset="1" stopColor="#5351B8"/>
+        </linearGradient>
+        <linearGradient id="paint5_linear_1977_58932" x1="25.0039" y1="5.9965" x2="25.0039" y2="0" gradientUnits="userSpaceOnUse">
+          <stop stopColor="#CDC7FF"/>
+          <stop offset="1" stopColor="#5A25F0"/>
+        </linearGradient>
+        <linearGradient id="paint6_linear_1977_58932" x1="24.9936" y1="5.99719" x2="24.9936" y2="2.5" gradientUnits="userSpaceOnUse">
+          <stop stopColor="white"/>
+          <stop offset="1" stopColor="white" stopOpacity="0.3"/>
+        </linearGradient>
+      </defs>
+    </g>
+  );
+};
+
 export function ProfitMetrics({ className }: ProfitMetricsProps) {
   return (
     <div className={`h-[480px] overflow-clip relative shrink-0 w-full ${className || ''}`}>
@@ -97,28 +203,14 @@ export function ProfitMetrics({ className }: ProfitMetricsProps) {
                 />
                 <Bar
                   dataKey="利润总额"
-                  fill="url(#profitTotalGradient)"
-                  radius={[2, 2, 0, 0]}
+                  shape={<ProfitTotalBar />}
                   barSize={35}
                 />
                 <Bar
                   dataKey="净利润"
-                  fill="url(#profitNetGradient)"
-                  radius={[2, 2, 0, 0]}
+                  shape={<ProfitNetBar />}
                   barSize={35}
                 />
-                <defs>
-                  {/* 利润总额渐变 - 匹配figma-jsx.md的黄色渐变 */}
-                  <linearGradient id="profitTotalGradient" x1="0" y1="0" x2="0" y2="1">
-                    <stop offset="0%" stopColor="#feffc2" stopOpacity={0.8}/>
-                    <stop offset="100%" stopColor="#feffc2" stopOpacity={0}/>
-                  </linearGradient>
-                  {/* 净利润渐变 - 匹配figma-jsx.md的紫色渐变 */}
-                  <linearGradient id="profitNetGradient" x1="0" y1="0" x2="0" y2="1">
-                    <stop offset="0%" stopColor="#dccfff" stopOpacity={0.8}/>
-                    <stop offset="100%" stopColor="#dccfff" stopOpacity={0}/>
-                  </linearGradient>
-                </defs>
               </BarChart>
             </ResponsiveContainer>
           </div>