From 57a7d3b9e700d8ebd75c2e6937746d43ef079d57 Mon Sep 17 00:00:00 2001
From: zdl <3489966805@qq.com>
Date: Thu, 30 Oct 2025 11:13:09 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8B=86=E5=88=86=20EventList.js/?=
=?UTF-8?q?=E6=8F=90=E5=8F=96=E4=BB=B7=E6=A0=BC=E7=9B=B8=E5=85=B3=E5=B7=A5?=
=?UTF-8?q?=E5=85=B7=E5=87=BD=E6=95=B0=E5=88=B0=20utils/priceFormatters.js?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.claude/settings.local.json | 3 +-
src/constants/animations.js | 72 ++++++++++++++
src/utils/priceFormatters.js | 105 ++++++++++++++++++++
src/views/Community/components/EventList.js | 97 ++----------------
4 files changed, 190 insertions(+), 87 deletions(-)
create mode 100644 src/constants/animations.js
create mode 100644 src/utils/priceFormatters.js
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 95814f11..8e92b5b9 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -12,7 +12,8 @@
"Bash(npm run start:mock)",
"Bash(npm install fsevents@latest --save-optional --force)",
"Bash(python -m py_compile:*)",
- "Bash(ps -p 20502,53360 -o pid,command)"
+ "Bash(ps -p 20502,53360 -o pid,command)",
+ "Bash(mkdir -p /Users/qiye/Desktop/jzqy/vf_react/docs/graduation)"
],
"deny": [],
"ask": []
diff --git a/src/constants/animations.js b/src/constants/animations.js
new file mode 100644
index 00000000..92c6d27d
--- /dev/null
+++ b/src/constants/animations.js
@@ -0,0 +1,72 @@
+// src/constants/animations.js
+// 通用动画定义 - 使用 @emotion/react 的 keyframes
+
+import { keyframes } from '@emotion/react';
+
+/**
+ * 脉冲动画 - 用于S/A级重要性标签
+ * 从中心向外扩散的阴影效果
+ */
+export const pulseAnimation = keyframes`
+ 0% {
+ box-shadow: 0 0 0 0 rgba(255, 77, 79, 0.7);
+ }
+ 70% {
+ box-shadow: 0 0 0 10px rgba(255, 77, 79, 0);
+ }
+ 100% {
+ box-shadow: 0 0 0 0 rgba(255, 77, 79, 0);
+ }
+`;
+
+/**
+ * 渐入动画
+ */
+export const fadeIn = keyframes`
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+`;
+
+/**
+ * 从下往上滑入动画
+ */
+export const slideInUp = keyframes`
+ from {
+ transform: translateY(20px);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
+`;
+
+/**
+ * 缩放进入动画
+ */
+export const scaleIn = keyframes`
+ from {
+ transform: scale(0.9);
+ opacity: 0;
+ }
+ to {
+ transform: scale(1);
+ opacity: 1;
+ }
+`;
+
+/**
+ * 旋转动画(用于Loading Spinner)
+ */
+export const spin = keyframes`
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+`;
diff --git a/src/utils/priceFormatters.js b/src/utils/priceFormatters.js
new file mode 100644
index 00000000..e93d4dfb
--- /dev/null
+++ b/src/utils/priceFormatters.js
@@ -0,0 +1,105 @@
+// src/utils/priceFormatters.js
+// 价格相关的工具函数 - 中国A股配色:红涨绿跌
+
+import React from 'react';
+import { TriangleUpIcon, TriangleDownIcon } from '@chakra-ui/icons';
+
+/**
+ * 获取价格变化的文字颜色
+ * @param {number|null|undefined} value - 涨跌幅百分比
+ * @returns {string} Chakra UI 颜色值
+ */
+export const getPriceChangeColor = (value) => {
+ if (value === null || value === undefined) return 'gray.500';
+
+ const absValue = Math.abs(value);
+
+ if (value > 0) {
+ // 上涨用红色,根据涨幅大小使用不同深浅
+ if (absValue >= 3) return 'red.600'; // 深红色:3%以上
+ if (absValue >= 1) return 'red.500'; // 中红色:1-3%
+ return 'red.400'; // 浅红色:0-1%
+ } else if (value < 0) {
+ // 下跌用绿色,根据跌幅大小使用不同深浅
+ if (absValue >= 3) return 'green.600'; // 深绿色:3%以上
+ if (absValue >= 1) return 'green.500'; // 中绿色:1-3%
+ return 'green.400'; // 浅绿色:0-1%
+ }
+ return 'gray.500';
+};
+
+/**
+ * 获取价格变化的背景颜色
+ * @param {number|null|undefined} value - 涨跌幅百分比
+ * @returns {string} Chakra UI 颜色值
+ */
+export const getPriceChangeBg = (value) => {
+ if (value === null || value === undefined) return 'gray.50';
+
+ const absValue = Math.abs(value);
+
+ if (value > 0) {
+ // 上涨背景色
+ if (absValue >= 3) return 'red.100'; // 深色背景:3%以上
+ if (absValue >= 1) return 'red.50'; // 中色背景:1-3%
+ return 'red.50'; // 浅色背景:0-1%
+ } else if (value < 0) {
+ // 下跌背景色
+ if (absValue >= 3) return 'green.100'; // 深色背景:3%以上
+ if (absValue >= 1) return 'green.50'; // 中色背景:1-3%
+ return 'green.50'; // 浅色背景:0-1%
+ }
+ return 'gray.50';
+};
+
+/**
+ * 获取价格变化的边框颜色
+ * @param {number|null|undefined} value - 涨跌幅百分比
+ * @returns {string} Chakra UI 颜色值
+ */
+export const getPriceChangeBorderColor = (value) => {
+ if (value === null || value === undefined) return 'gray.300';
+
+ const absValue = Math.abs(value);
+
+ if (value > 0) {
+ // 上涨边框色
+ if (absValue >= 3) return 'red.500'; // 深边框:3%以上
+ if (absValue >= 1) return 'red.400'; // 中边框:1-3%
+ return 'red.300'; // 浅边框:0-1%
+ } else if (value < 0) {
+ // 下跌边框色
+ if (absValue >= 3) return 'green.500'; // 深边框:3%以上
+ if (absValue >= 1) return 'green.400'; // 中边框:1-3%
+ return 'green.300'; // 浅边框:0-1%
+ }
+ return 'gray.300';
+};
+
+/**
+ * 格式化价格变化为字符串
+ * @param {number|null|undefined} value - 涨跌幅百分比
+ * @param {number} decimals - 小数位数,默认2位
+ * @returns {string} 格式化后的字符串,例如 "+5.23%" 或 "-2.10%"
+ */
+export const formatPriceChange = (value, decimals = 2) => {
+ if (value === null || value === undefined) return '--%';
+
+ const sign = value > 0 ? '+' : '';
+ return `${sign}${value.toFixed(decimals)}%`;
+};
+
+/**
+ * 价格涨跌箭头组件
+ * @param {Object} props
+ * @param {number|null|undefined} props.value - 涨跌幅百分比
+ * @returns {JSX.Element|null}
+ */
+export const PriceArrow = ({ value }) => {
+ if (value === null || value === undefined) return null;
+
+ const Icon = value > 0 ? TriangleUpIcon : TriangleDownIcon;
+ const color = value > 0 ? 'red.500' : 'green.500';
+
+ return ;
+};
diff --git a/src/views/Community/components/EventList.js b/src/views/Community/components/EventList.js
index 71a31750..9208c8de 100644
--- a/src/views/Community/components/EventList.js
+++ b/src/views/Community/components/EventList.js
@@ -1,6 +1,5 @@
// src/views/Community/components/EventList.js
import React, { useState, useEffect } from 'react';
-import { keyframes } from '@emotion/react';
import {
Box,
VStack,
@@ -45,14 +44,14 @@ import {
WarningIcon,
WarningTwoIcon,
CheckCircleIcon,
- TriangleUpIcon,
- TriangleDownIcon,
ArrowForwardIcon,
ExternalLinkIcon,
ViewOffIcon,
} from '@chakra-ui/icons';
import { useNavigate } from 'react-router-dom';
import moment from 'moment';
+
+// 导入工具函数和常量
import { logger } from '../../../utils/logger';
import { getApiBase } from '../../../utils/apiConfig';
import { useEventNotifications } from '../../../hooks/useEventNotifications';
@@ -60,90 +59,16 @@ import { getImportanceConfig, getAllImportanceLevels } from '../../../constants/
import { browserNotificationService } from '../../../services/browserNotificationService';
import { useNotification } from '../../../contexts/NotificationContext';
-// ========== 动画定义 ==========
-// 脉冲动画 - 用于S/A级重要性标签
-const pulseAnimation = keyframes`
- 0% {
- box-shadow: 0 0 0 0 rgba(255, 77, 79, 0.7);
- }
- 70% {
- box-shadow: 0 0 0 10px rgba(255, 77, 79, 0);
- }
- 100% {
- box-shadow: 0 0 0 0 rgba(255, 77, 79, 0);
- }
-`;
+// 导入价格相关工具函数
+import {
+ getPriceChangeColor,
+ getPriceChangeBg,
+ getPriceChangeBorderColor,
+ PriceArrow,
+} from '../../../utils/priceFormatters';
-// ========== 工具函数定义在组件外部 ==========
-// 涨跌颜色配置(中国A股配色:红涨绿跌)- 分档次显示
-const getPriceChangeColor = (value) => {
- if (value === null || value === undefined) return 'gray.500';
-
- const absValue = Math.abs(value);
-
- if (value > 0) {
- // 上涨用红色,根据涨幅大小使用不同深浅
- if (absValue >= 3) return 'red.600'; // 深红色:3%以上
- if (absValue >= 1) return 'red.500'; // 中红色:1-3%
- return 'red.400'; // 浅红色:0-1%
- } else if (value < 0) {
- // 下跌用绿色,根据跌幅大小使用不同深浅
- if (absValue >= 3) return 'green.600'; // 深绿色:3%以上
- if (absValue >= 1) return 'green.500'; // 中绿色:1-3%
- return 'green.400'; // 浅绿色:0-1%
- }
- return 'gray.500';
-};
-
-const getPriceChangeBg = (value) => {
- if (value === null || value === undefined) return 'gray.50';
-
- const absValue = Math.abs(value);
-
- if (value > 0) {
- // 上涨背景色
- if (absValue >= 3) return 'red.100'; // 深色背景:3%以上
- if (absValue >= 1) return 'red.50'; // 中色背景:1-3%
- return 'red.50'; // 浅色背景:0-1%
- } else if (value < 0) {
- // 下跌背景色
- if (absValue >= 3) return 'green.100'; // 深色背景:3%以上
- if (absValue >= 1) return 'green.50'; // 中色背景:1-3%
- return 'green.50'; // 浅色背景:0-1%
- }
- return 'gray.50';
-};
-
-const getPriceChangeBorderColor = (value) => {
- if (value === null || value === undefined) return 'gray.300';
-
- const absValue = Math.abs(value);
-
- if (value > 0) {
- // 上涨边框色
- if (absValue >= 3) return 'red.500'; // 深边框:3%以上
- if (absValue >= 1) return 'red.400'; // 中边框:1-3%
- return 'red.300'; // 浅边框:0-1%
- } else if (value < 0) {
- // 下跌边框色
- if (absValue >= 3) return 'green.500'; // 深边框:3%以上
- if (absValue >= 1) return 'green.400'; // 中边框:1-3%
- return 'green.300'; // 浅边框:0-1%
- }
- return 'gray.300';
-};
-
-// 重要性等级配置已移至 src/constants/importanceLevels.js
-
-// 自定义的涨跌箭头组件(修复颜色问题)
-const PriceArrow = ({ value }) => {
- if (value === null || value === undefined) return null;
-
- const Icon = value > 0 ? TriangleUpIcon : TriangleDownIcon;
- const color = value > 0 ? 'red.500' : 'green.500';
-
- return ;
-};
+// 导入动画定义
+import { pulseAnimation } from '../../../constants/animations';
// ========== 主组件 ==========
const EventList = ({ events, pagination, onPageChange, onEventClick, onViewDetail }) => {