- 新增 renderers.js 通用渲染函数 - 新增 stockColumns.js 事件关联股票列 - 新增 sectorColumns.js 涨停板块列 - 新增 ztStockColumns.js 涨停个股列 - 新增 eventColumns.js 未来事件列 - 使用工厂函数模式,支持 useMemo 缓存 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
185 lines
3.7 KiB
JavaScript
185 lines
3.7 KiB
JavaScript
// HeroPanel 表格列渲染器
|
||
import { Tag, Space, Button, Typography, Tooltip } from "antd";
|
||
import {
|
||
ClockCircleOutlined,
|
||
LinkOutlined,
|
||
RobotOutlined,
|
||
StockOutlined,
|
||
StarFilled,
|
||
StarOutlined,
|
||
LineChartOutlined,
|
||
} from "@ant-design/icons";
|
||
import dayjs from "dayjs";
|
||
|
||
const { Text: AntText } = Typography;
|
||
|
||
/**
|
||
* 渲染星级评分
|
||
*/
|
||
export const renderStars = (star) => {
|
||
const level = parseInt(star, 10) || 0;
|
||
return (
|
||
<span>
|
||
{[1, 2, 3, 4, 5].map((i) => (
|
||
<span
|
||
key={i}
|
||
style={{
|
||
color: i <= level ? "#faad14" : "#d9d9d9",
|
||
fontSize: "14px",
|
||
}}
|
||
>
|
||
★
|
||
</span>
|
||
))}
|
||
</span>
|
||
);
|
||
};
|
||
|
||
/**
|
||
* 渲染涨跌幅
|
||
*/
|
||
export const renderChangePercent = (val) => {
|
||
if (val === null || val === undefined) return "-";
|
||
const num = parseFloat(val);
|
||
const color = num > 0 ? "#ff4d4f" : num < 0 ? "#52c41a" : "#888";
|
||
const prefix = num > 0 ? "+" : "";
|
||
return (
|
||
<span style={{ color, fontWeight: 600 }}>
|
||
{prefix}{num.toFixed(2)}%
|
||
</span>
|
||
);
|
||
};
|
||
|
||
/**
|
||
* 渲染时间
|
||
*/
|
||
export const renderTime = (time) => (
|
||
<Space>
|
||
<ClockCircleOutlined />
|
||
<AntText>{dayjs(time).format("HH:mm")}</AntText>
|
||
</Space>
|
||
);
|
||
|
||
/**
|
||
* 渲染标题(带tooltip)
|
||
*/
|
||
export const renderTitle = (text) => (
|
||
<Tooltip title={text}>
|
||
<AntText strong style={{ fontSize: "14px" }}>
|
||
{text}
|
||
</AntText>
|
||
</Tooltip>
|
||
);
|
||
|
||
/**
|
||
* 渲染排名样式
|
||
*/
|
||
export const getRankStyle = (index) => {
|
||
if (index === 0) {
|
||
return {
|
||
background: "linear-gradient(135deg, #FFD700 0%, #FFA500 100%)",
|
||
color: "#000",
|
||
};
|
||
}
|
||
if (index === 1) {
|
||
return {
|
||
background: "linear-gradient(135deg, #C0C0C0 0%, #A9A9A9 100%)",
|
||
color: "#000",
|
||
};
|
||
}
|
||
if (index === 2) {
|
||
return {
|
||
background: "linear-gradient(135deg, #CD7F32 0%, #8B4513 100%)",
|
||
color: "#fff",
|
||
};
|
||
}
|
||
return {
|
||
background: "rgba(255, 255, 255, 0.08)",
|
||
color: "#888",
|
||
};
|
||
};
|
||
|
||
/**
|
||
* 渲染排名徽章
|
||
*/
|
||
export const renderRankBadge = (index) => {
|
||
const style = getRankStyle(index);
|
||
return (
|
||
<div
|
||
style={{
|
||
display: "inline-flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
width: 24,
|
||
height: 24,
|
||
borderRadius: "50%",
|
||
fontSize: 12,
|
||
fontWeight: "bold",
|
||
...style,
|
||
}}
|
||
>
|
||
{index + 1}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
/**
|
||
* 创建查看按钮渲染器
|
||
*/
|
||
export const createViewButtonRenderer = (onClick, iconType = "link") => {
|
||
const icons = {
|
||
link: <LinkOutlined />,
|
||
robot: <RobotOutlined />,
|
||
stock: <StockOutlined />,
|
||
chart: <LineChartOutlined />,
|
||
};
|
||
|
||
return (text, record) => (
|
||
<Button
|
||
type="link"
|
||
size="small"
|
||
icon={icons[iconType] || icons.link}
|
||
onClick={() => onClick(text, record)}
|
||
disabled={!text}
|
||
>
|
||
{text ? "查看" : "无"}
|
||
</Button>
|
||
);
|
||
};
|
||
|
||
/**
|
||
* 创建自选按钮渲染器
|
||
*/
|
||
export const createWatchlistButtonRenderer = (isInWatchlist, onAdd) => {
|
||
return (_, record) => {
|
||
const inWatchlist = isInWatchlist(record.code);
|
||
return (
|
||
<Button
|
||
type={inWatchlist ? "primary" : "default"}
|
||
size="small"
|
||
icon={inWatchlist ? <StarFilled /> : <StarOutlined />}
|
||
onClick={() => onAdd(record)}
|
||
disabled={inWatchlist}
|
||
>
|
||
{inWatchlist ? "已添加" : "加自选"}
|
||
</Button>
|
||
);
|
||
};
|
||
};
|
||
|
||
/**
|
||
* 创建K线按钮渲染器
|
||
*/
|
||
export const createKlineButtonRenderer = (showKline) => {
|
||
return (_, record) => (
|
||
<Button
|
||
type="primary"
|
||
size="small"
|
||
icon={<LineChartOutlined />}
|
||
onClick={() => showKline(record)}
|
||
>
|
||
查看
|
||
</Button>
|
||
);
|
||
};
|