优化评查结果的显示效果
This commit is contained in:
@@ -345,8 +345,25 @@ export async function getReviewPoints(fileId: string) {
|
||||
// evaluatedPointResultsLog: {
|
||||
// rules:[
|
||||
// {
|
||||
// "id": "0",
|
||||
// "type": "consistency",
|
||||
// "res": true,
|
||||
// "config": {
|
||||
// "logic": "all",
|
||||
// "pairs": [
|
||||
// {
|
||||
// "sourceField": {"证据先行登记保存批准书-负责人意见并签名-时间": {page: 1,value: ''}},
|
||||
// "targetField": {"证据先行登记保存批准书-负责人意见并签名-签名": {page: 2,value: '有无判断类型'}},
|
||||
// "compareMethod": "exact",
|
||||
// "res": true
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "id": "1",
|
||||
// "type": "consistency",
|
||||
// "res": false,
|
||||
// "config": {
|
||||
// "logic": "and",
|
||||
// "pairs": [
|
||||
|
||||
@@ -1,22 +1,7 @@
|
||||
import { postgrestGet, postgrestPut, postgrestPost, type PostgrestParams } from '../postgrest-client';
|
||||
import { postgrestGet, type PostgrestParams } from '../postgrest-client';
|
||||
import dayjs from 'dayjs';
|
||||
// import { API_BASE_URL } from '../client';
|
||||
|
||||
/**
|
||||
* 格式化日期
|
||||
* @param dateString 日期字符串
|
||||
* @returns 格式化后的日期字符串
|
||||
*/
|
||||
function formatDate(dateString: string): string {
|
||||
if (!dateString) return '';
|
||||
try {
|
||||
return dayjs(dateString).format('YYYY-MM-DD HH:mm:ss');
|
||||
} catch (error) {
|
||||
console.error('日期格式化失败:', error);
|
||||
return dateString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从不同格式的 API 响应中提取数据
|
||||
|
||||
@@ -20,13 +20,6 @@ export function Sidebar({ onToggle, collapsed }: SidebarProps) {
|
||||
const [expandedMenus, setExpandedMenus] = useState<Record<string, boolean>>({});
|
||||
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
id: 'contract-search',
|
||||
title: '智能搜索',
|
||||
path: '/contract-search',
|
||||
hideBreadcrumb: true,
|
||||
icon: 'ri-search-line'
|
||||
},
|
||||
{
|
||||
id: 'contract-template',
|
||||
title: '合同模板',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -105,7 +105,9 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
|
||||
>
|
||||
<i className="ri-lightbulb-line"></i> AI智能分析
|
||||
</button> */}
|
||||
{fileInfo.type === '1' && (
|
||||
{/* {fileInfo.type === '1' && ( */}
|
||||
{/* 隐藏结构比对 */}
|
||||
{fileInfo.type === '999999' && (
|
||||
<button
|
||||
className={`tab-nav-item ${activeTab === 'filecompare' ? 'active' : ''}`}
|
||||
onClick={() => onTabChange('filecompare')}
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
import { useState, useEffect, useRef, ReactNode } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import '../../styles/components/TooltipStyles.css';
|
||||
|
||||
// 提示框主题
|
||||
export type TooltipTheme = 'dark' | 'light' | 'primary' | 'success' | 'warning' | 'error' | 'info';
|
||||
|
||||
// 提示框位置
|
||||
export type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
|
||||
|
||||
// 提示框属性
|
||||
export interface TooltipProps {
|
||||
children: ReactNode; // 触发元素
|
||||
content: ReactNode; // 提示内容
|
||||
theme?: TooltipTheme; // 主题样式
|
||||
placement?: TooltipPlacement; // 显示位置
|
||||
rich?: boolean; // 是否为富文本提示
|
||||
header?: ReactNode; // 富文本提示标题
|
||||
footer?: ReactNode; // 富文本提示页脚
|
||||
trigger?: 'hover' | 'click'; // 触发方式
|
||||
visible?: boolean; // 是否显示(受控模式)
|
||||
showArrow?: boolean; // 是否显示箭头
|
||||
maxWidth?: number | string; // 最大宽度
|
||||
className?: string; // 自定义类名
|
||||
onVisibleChange?: (visible: boolean) => void; // 显示状态变化回调
|
||||
}
|
||||
|
||||
/**
|
||||
* Tooltip 组件
|
||||
*
|
||||
* 提供增强的悬浮提示功能,支持多种主题、位置和富文本模式
|
||||
*/
|
||||
export function Tooltip({
|
||||
children,
|
||||
content,
|
||||
theme = 'dark',
|
||||
placement = 'top',
|
||||
rich = false,
|
||||
header,
|
||||
footer,
|
||||
trigger = 'hover',
|
||||
visible: controlledVisible,
|
||||
showArrow = true,
|
||||
maxWidth = 320,
|
||||
className = '',
|
||||
onVisibleChange
|
||||
}: TooltipProps) {
|
||||
// 使用内部状态管理提示框显示状态(非受控模式)
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
// 判断是否为受控组件
|
||||
const isControlled = controlledVisible !== undefined;
|
||||
|
||||
// 获取实际显示状态
|
||||
const isVisible = isControlled ? controlledVisible : visible;
|
||||
|
||||
// 引用DOM元素
|
||||
const triggerRef = useRef<HTMLDivElement>(null);
|
||||
const tooltipRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// 处理显示状态变化
|
||||
const handleVisibleChange = (newVisible: boolean) => {
|
||||
if (!isControlled) {
|
||||
setVisible(newVisible);
|
||||
}
|
||||
onVisibleChange?.(newVisible);
|
||||
};
|
||||
|
||||
// 触发器事件处理
|
||||
const triggerEvents = trigger === 'hover'
|
||||
? {
|
||||
onMouseEnter: () => handleVisibleChange(true),
|
||||
onMouseLeave: () => handleVisibleChange(false),
|
||||
}
|
||||
: {
|
||||
onClick: () => handleVisibleChange(!isVisible),
|
||||
};
|
||||
|
||||
// 更新提示框位置的函数
|
||||
const updateTooltipPosition = () => {
|
||||
if (!isVisible || !triggerRef.current || !tooltipRef.current) return;
|
||||
|
||||
// 获取触发元素位置
|
||||
const triggerRect = triggerRef.current.getBoundingClientRect();
|
||||
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
||||
|
||||
// 设置最大宽度
|
||||
tooltipRef.current.style.maxWidth = typeof maxWidth === 'number'
|
||||
? `${maxWidth}px`
|
||||
: String(maxWidth);
|
||||
|
||||
// 计算各个方向的位置
|
||||
let top = 0, left = 0;
|
||||
let arrowTop = 0, arrowLeft = 0;
|
||||
const arrowSize = 8; // 箭头大小
|
||||
const gap = 10; // 提示框与触发元素的间距
|
||||
|
||||
switch (placement) {
|
||||
case 'top':
|
||||
left = triggerRect.left + (triggerRect.width / 2) - (tooltipRect.width / 2);
|
||||
top = triggerRect.top - tooltipRect.height - arrowSize;
|
||||
arrowLeft = tooltipRect.width / 2 - arrowSize;
|
||||
arrowTop = tooltipRect.height;
|
||||
break;
|
||||
case 'bottom':
|
||||
left = triggerRect.left + (triggerRect.width / 2) - (tooltipRect.width / 2);
|
||||
top = triggerRect.bottom + arrowSize;
|
||||
arrowLeft = tooltipRect.width / 2 - arrowSize;
|
||||
arrowTop = -arrowSize;
|
||||
break;
|
||||
case 'left':
|
||||
left = triggerRect.left - tooltipRect.width - arrowSize;
|
||||
top = triggerRect.top + (triggerRect.height / 2) - (tooltipRect.height / 2);
|
||||
arrowLeft = tooltipRect.width;
|
||||
arrowTop = tooltipRect.height / 2 - arrowSize;
|
||||
break;
|
||||
case 'right':
|
||||
left = triggerRect.right + arrowSize;
|
||||
top = triggerRect.top + (triggerRect.height / 2) - (tooltipRect.height / 2);
|
||||
arrowLeft = -arrowSize;
|
||||
arrowTop = tooltipRect.height / 2 - arrowSize;
|
||||
break;
|
||||
}
|
||||
|
||||
// 确保提示框不超出视口
|
||||
const viewportWidth = window.innerWidth;
|
||||
const viewportHeight = window.innerHeight;
|
||||
|
||||
// 调整位置,避免超出视口
|
||||
if (left < 0) {
|
||||
left = gap;
|
||||
arrowLeft = Math.max(triggerRect.left + (triggerRect.width / 2) - left - arrowSize, arrowSize * 2);
|
||||
} else if (left + tooltipRect.width > viewportWidth) {
|
||||
left = viewportWidth - tooltipRect.width - gap;
|
||||
arrowLeft = Math.min(triggerRect.left + (triggerRect.width / 2) - left - arrowSize, tooltipRect.width - arrowSize * 2);
|
||||
}
|
||||
|
||||
if (top < 0) {
|
||||
if (placement === 'top') {
|
||||
// 如果上方放不下,切换到下方
|
||||
top = triggerRect.bottom + arrowSize;
|
||||
arrowTop = -arrowSize;
|
||||
tooltipRef.current.classList.remove('tooltip-top');
|
||||
tooltipRef.current.classList.add('tooltip-bottom');
|
||||
} else {
|
||||
top = gap;
|
||||
arrowTop = Math.max(triggerRect.top + (triggerRect.height / 2) - top - arrowSize, arrowSize * 2);
|
||||
}
|
||||
} else if (top + tooltipRect.height > viewportHeight) {
|
||||
if (placement === 'bottom') {
|
||||
// 如果下方放不下,切换到上方
|
||||
top = triggerRect.top - tooltipRect.height - arrowSize;
|
||||
arrowTop = tooltipRect.height;
|
||||
tooltipRef.current.classList.remove('tooltip-bottom');
|
||||
tooltipRef.current.classList.add('tooltip-top');
|
||||
} else {
|
||||
top = viewportHeight - tooltipRect.height - gap;
|
||||
arrowTop = Math.min(triggerRect.top + (triggerRect.height / 2) - top - arrowSize, tooltipRect.height - arrowSize * 2);
|
||||
}
|
||||
}
|
||||
|
||||
// 应用位置样式
|
||||
tooltipRef.current.style.position = 'fixed';
|
||||
tooltipRef.current.style.top = `${top}px`;
|
||||
tooltipRef.current.style.left = `${left}px`;
|
||||
tooltipRef.current.style.transform = 'none'; // 重置任何变换
|
||||
|
||||
// 定位箭头
|
||||
const arrow = tooltipRef.current.querySelector('.tooltip-arrow') as HTMLElement;
|
||||
if (arrow && showArrow) {
|
||||
switch (placement) {
|
||||
case 'top':
|
||||
arrow.style.bottom = `-${arrowSize}px`;
|
||||
arrow.style.left = `${arrowLeft}px`;
|
||||
arrow.style.top = 'auto';
|
||||
arrow.style.right = 'auto';
|
||||
break;
|
||||
case 'bottom':
|
||||
arrow.style.top = `-${arrowSize}px`;
|
||||
arrow.style.left = `${arrowLeft}px`;
|
||||
arrow.style.bottom = 'auto';
|
||||
arrow.style.right = 'auto';
|
||||
break;
|
||||
case 'left':
|
||||
arrow.style.right = `-${arrowSize}px`;
|
||||
arrow.style.top = `${arrowTop}px`;
|
||||
arrow.style.bottom = 'auto';
|
||||
arrow.style.left = 'auto';
|
||||
break;
|
||||
case 'right':
|
||||
arrow.style.left = `-${arrowSize}px`;
|
||||
arrow.style.top = `${arrowTop}px`;
|
||||
arrow.style.bottom = 'auto';
|
||||
arrow.style.right = 'auto';
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 计算提示框位置
|
||||
useEffect(() => {
|
||||
if (!isVisible) return;
|
||||
|
||||
// 初始化位置
|
||||
updateTooltipPosition();
|
||||
|
||||
// 添加滚动和调整大小事件监听器
|
||||
window.addEventListener('scroll', updateTooltipPosition, true);
|
||||
window.addEventListener('resize', updateTooltipPosition);
|
||||
|
||||
// 定期更新位置(处理内容动态变化的情况)
|
||||
const intervalId = setInterval(updateTooltipPosition, 300);
|
||||
|
||||
// 清理函数
|
||||
return () => {
|
||||
window.removeEventListener('scroll', updateTooltipPosition, true);
|
||||
window.removeEventListener('resize', updateTooltipPosition);
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, [isVisible, placement, maxWidth, showArrow]);
|
||||
|
||||
// 处理点击外部关闭
|
||||
useEffect(() => {
|
||||
if (trigger !== 'click' || !isVisible) return;
|
||||
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
triggerRef.current &&
|
||||
!triggerRef.current.contains(event.target as Node) &&
|
||||
tooltipRef.current &&
|
||||
!tooltipRef.current.contains(event.target as Node)
|
||||
) {
|
||||
handleVisibleChange(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [trigger, isVisible]);
|
||||
|
||||
// 渲染提示框内容
|
||||
const renderTooltipContent = () => {
|
||||
if (rich) {
|
||||
return (
|
||||
<div className="tooltip-content">
|
||||
{header && <div className="tooltip-header">{header}</div>}
|
||||
<div className="tooltip-body">{content}</div>
|
||||
{footer && <div className="tooltip-footer">{footer}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tooltip-content">
|
||||
<div>{content}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// 生成提示框类名
|
||||
const tooltipClassNames = [
|
||||
'tooltip-container',
|
||||
`tooltip-${placement}`,
|
||||
`tooltip-${theme}`,
|
||||
rich ? 'tooltip-rich' : '',
|
||||
isVisible ? 'tooltip-visible' : '',
|
||||
className
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
// 使用Portal渲染提示框
|
||||
const tooltipPortal = isVisible && typeof document !== 'undefined'
|
||||
? createPortal(
|
||||
<div
|
||||
ref={tooltipRef}
|
||||
className={tooltipClassNames}
|
||||
style={{ maxWidth }}
|
||||
>
|
||||
{renderTooltipContent()}
|
||||
{showArrow && <div className="tooltip-arrow"></div>}
|
||||
</div>,
|
||||
document.body
|
||||
)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div className="tooltip-trigger" ref={triggerRef} {...triggerEvents}>
|
||||
{children}
|
||||
{tooltipPortal}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Tooltip;
|
||||
@@ -0,0 +1,35 @@
|
||||
// 导出所有UI组件,方便统一引入
|
||||
|
||||
// 核心组件
|
||||
export { Button } from './Button';
|
||||
export { Card } from './Card';
|
||||
export { Modal } from './Modal';
|
||||
export { toastService } from './Toast';
|
||||
export { Tooltip } from './Tooltip';
|
||||
|
||||
// 数据展示组件
|
||||
export { Table } from './Table';
|
||||
export { Pagination } from './Pagination';
|
||||
export { Tag } from './Tag';
|
||||
export { FileTag } from './FileTag';
|
||||
export { FileTypeTag } from './FileTypeTag';
|
||||
export { StatusBadge } from './StatusBadge';
|
||||
export { StatusDot } from './StatusDot';
|
||||
export { FileIcon } from './FileIcon';
|
||||
|
||||
// 数据输入组件
|
||||
export { SearchBox } from './SearchBox';
|
||||
export { DateRangePicker } from './DateRangePicker';
|
||||
export { FilterPanel } from './FilterPanel';
|
||||
export { UploadArea } from './UploadArea';
|
||||
|
||||
// 反馈组件
|
||||
export { Alert } from './Alert';
|
||||
export { MessageModal } from './MessageModal';
|
||||
export { LoadingBar } from './LoadingBar';
|
||||
export { RouteChangeLoader } from './RouteChangeLoader';
|
||||
export { FileProgress } from './FileProgress';
|
||||
export { ProcessingSteps } from './ProcessingSteps';
|
||||
|
||||
// 示例组件(开发环境使用)
|
||||
export { TooltipExample } from '../../routes/examples/TooltipExample';
|
||||
@@ -0,0 +1,236 @@
|
||||
import { Tooltip } from '../../components/ui/Tooltip';
|
||||
|
||||
/**
|
||||
* Tooltip 组件示例
|
||||
* 展示不同主题、位置和风格的提示框
|
||||
*/
|
||||
export function TooltipExample() {
|
||||
return (
|
||||
<div className="tooltip-examples p-4">
|
||||
<h2 className="text-lg font-bold mb-4">Tooltip 组件示例</h2>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
{/* 基础提示框 */}
|
||||
<div className="example-section">
|
||||
<h3 className="text-base font-semibold mb-2">基础提示框</h3>
|
||||
<div className="flex space-x-4 mb-4">
|
||||
<Tooltip content="这是一个基础提示框">
|
||||
<button className="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">
|
||||
鼠标悬停
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="点击显示的提示框" trigger="click">
|
||||
<button className="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">
|
||||
点击查看
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 不同位置 */}
|
||||
<div className="example-section">
|
||||
<h3 className="text-base font-semibold mb-2">不同位置</h3>
|
||||
<div className="flex space-x-4 mb-4">
|
||||
<Tooltip content="顶部提示" placement="top">
|
||||
<button className="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">
|
||||
顶部
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="底部提示" placement="bottom">
|
||||
<button className="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">
|
||||
底部
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="左侧提示" placement="left">
|
||||
<button className="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">
|
||||
左侧
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="右侧提示" placement="right">
|
||||
<button className="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">
|
||||
右侧
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 不同主题 */}
|
||||
<div className="example-section">
|
||||
<h3 className="text-base font-semibold mb-2">不同主题</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Tooltip content="深色主题" theme="dark">
|
||||
<span className="px-3 py-1 border border-gray-300 rounded cursor-default">
|
||||
深色
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="浅色主题" theme="light">
|
||||
<span className="px-3 py-1 border border-gray-300 rounded cursor-default">
|
||||
浅色
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="主题色" theme="primary">
|
||||
<span className="px-3 py-1 border border-gray-300 rounded cursor-default">
|
||||
主题色
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="成功提示" theme="success">
|
||||
<span className="px-3 py-1 border border-gray-300 rounded cursor-default">
|
||||
成功
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="警告提示" theme="warning">
|
||||
<span className="px-3 py-1 border border-gray-300 rounded cursor-default">
|
||||
警告
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="错误提示" theme="error">
|
||||
<span className="px-3 py-1 border border-gray-300 rounded cursor-default">
|
||||
错误
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content="信息提示" theme="info">
|
||||
<span className="px-3 py-1 border border-gray-300 rounded cursor-default">
|
||||
信息
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 富文本提示框 */}
|
||||
<div className="example-section">
|
||||
<h3 className="text-base font-semibold mb-2">富文本提示框</h3>
|
||||
<div className="flex space-x-4">
|
||||
<Tooltip
|
||||
content={
|
||||
<div>
|
||||
<div className="flex items-center mb-1">
|
||||
<span className="w-24 text-gray-500">CPU使用率:</span>
|
||||
<span className="text-green-500 font-medium">32%</span>
|
||||
</div>
|
||||
<div className="flex items-center mb-1">
|
||||
<span className="w-24 text-gray-500">内存使用率:</span>
|
||||
<span className="text-yellow-500 font-medium">76%</span>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<span className="w-24 text-gray-500">磁盘空间:</span>
|
||||
<span className="text-blue-500 font-medium">245GB/500GB</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
theme="light"
|
||||
rich={true}
|
||||
header="系统性能报告"
|
||||
footer="更新时间: 2023-10-15 15:30:42"
|
||||
showArrow={true}
|
||||
>
|
||||
<button className="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600">
|
||||
性能分析
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
content={
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span>本月销售额:</span>
|
||||
<span className="text-green-400 font-medium">¥258,432</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span>环比增长:</span>
|
||||
<span className="text-green-400 font-medium">+15.8%</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span>销售热点:</span>
|
||||
<span className="text-yellow-400 font-medium">电子产品</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
theme="dark"
|
||||
rich={true}
|
||||
header="销售数据分析"
|
||||
footer="数据来源: 销售管理系统"
|
||||
placement="bottom"
|
||||
>
|
||||
<button className="px-3 py-1 bg-green-500 text-white rounded hover:bg-green-600">
|
||||
销售趋势
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 条件渲染示例 */}
|
||||
<div className="example-section">
|
||||
<h3 className="text-base font-semibold mb-2">状态提示示例</h3>
|
||||
<div className="flex space-x-4">
|
||||
<Tooltip
|
||||
content="优秀:得分在90分以上"
|
||||
theme="success"
|
||||
>
|
||||
<span className="text-green-500 font-bold px-2">95</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
content="良好:得分在60-90分之间"
|
||||
theme="warning"
|
||||
>
|
||||
<span className="text-yellow-500 px-2">75</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
content="不及格:得分低于60分"
|
||||
theme="error"
|
||||
>
|
||||
<span className="text-red-500 px-2">45</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 自定义样式示例 */}
|
||||
<div className="example-section">
|
||||
<h3 className="text-base font-semibold mb-2">自定义样式</h3>
|
||||
<div className="flex space-x-4">
|
||||
<Tooltip
|
||||
content="带有自定义宽度的提示框"
|
||||
maxWidth={150}
|
||||
>
|
||||
<span className="border-b border-dotted border-gray-500 cursor-help">
|
||||
自定义宽度
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
content="没有箭头的提示框"
|
||||
showArrow={false}
|
||||
theme="primary"
|
||||
>
|
||||
<span className="border-b border-dotted border-blue-500 cursor-help">
|
||||
无箭头
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
content="自定义类名"
|
||||
className="custom-tooltip"
|
||||
>
|
||||
<span className="border-b border-dotted border-purple-500 cursor-help text-purple-500">
|
||||
自定义类名
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TooltipExample;
|
||||
@@ -548,7 +548,8 @@ export default function ReviewDetails() {
|
||||
)}
|
||||
{reviewData.fileInfo.uploadTime && (
|
||||
<div className="text-xs text-gray-500">
|
||||
| 上传时间:{reviewData.fileInfo.uploadTime} | 上传用户:{reviewData.fileInfo.uploadUser}
|
||||
| 上传时间:{reviewData.fileInfo.uploadTime}
|
||||
{/* | 上传用户:{reviewData.fileInfo.uploadUser} */}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
/* Tooltip 基础样式 */
|
||||
.tooltip-trigger {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip-container {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 9999;
|
||||
width: max-content;
|
||||
max-width: 320px;
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tooltip-visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.tooltip-content {
|
||||
position: relative;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.tooltip-arrow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Tooltip 主题 */
|
||||
.tooltip-dark .tooltip-content {
|
||||
background-color: #1e293b;
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.tooltip-dark .tooltip-arrow {
|
||||
border-color: #1e293b;
|
||||
}
|
||||
|
||||
.tooltip-light .tooltip-content {
|
||||
background-color: #ffffff;
|
||||
color: #334155;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.tooltip-light .tooltip-arrow {
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
.tooltip-primary .tooltip-content {
|
||||
background-color: #2563eb;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tooltip-primary .tooltip-arrow {
|
||||
border-color: #2563eb;
|
||||
}
|
||||
|
||||
.tooltip-success .tooltip-content {
|
||||
background-color: #22c55e;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tooltip-success .tooltip-arrow {
|
||||
border-color: #22c55e;
|
||||
}
|
||||
|
||||
.tooltip-warning .tooltip-content {
|
||||
background-color: #f59e0b;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tooltip-warning .tooltip-arrow {
|
||||
border-color: #f59e0b;
|
||||
}
|
||||
|
||||
.tooltip-error .tooltip-content {
|
||||
background-color: #ef4444;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tooltip-error .tooltip-arrow {
|
||||
border-color: #ef4444;
|
||||
}
|
||||
|
||||
.tooltip-info .tooltip-content {
|
||||
background-color: #3b82f6;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tooltip-info .tooltip-arrow {
|
||||
border-color: #3b82f6;
|
||||
}
|
||||
|
||||
/* Tooltip 位置基本样式 */
|
||||
.tooltip-top .tooltip-arrow {
|
||||
border-width: 8px 8px 0 8px;
|
||||
border-color: inherit transparent transparent transparent;
|
||||
}
|
||||
|
||||
.tooltip-bottom .tooltip-arrow {
|
||||
border-width: 0 8px 8px 8px;
|
||||
border-color: transparent transparent inherit transparent;
|
||||
}
|
||||
|
||||
.tooltip-left .tooltip-arrow {
|
||||
border-width: 8px 0 8px 8px;
|
||||
border-color: transparent transparent transparent inherit;
|
||||
}
|
||||
|
||||
.tooltip-right .tooltip-arrow {
|
||||
border-width: 8px 8px 8px 0;
|
||||
border-color: transparent inherit transparent transparent;
|
||||
}
|
||||
|
||||
/* 富文本提示框样式 */
|
||||
.tooltip-rich .tooltip-content {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tooltip-header {
|
||||
padding: 0.5rem 1rem;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tooltip-body {
|
||||
padding: 0.75rem 1rem;
|
||||
}
|
||||
|
||||
.tooltip-footer {
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
font-size: 0.75rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* 深色主题特定样式调整 */
|
||||
.tooltip-dark .tooltip-header {
|
||||
border-bottom-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tooltip-dark .tooltip-footer {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border-top-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
/* 浅色主题特定样式调整 */
|
||||
.tooltip-light .tooltip-header {
|
||||
border-bottom-color: #e2e8f0;
|
||||
}
|
||||
|
||||
.tooltip-light .tooltip-footer {
|
||||
background-color: #f8fafc;
|
||||
border-top-color: #e2e8f0;
|
||||
}
|
||||
|
||||
/* 浅色主题下的箭头样式修正 */
|
||||
.tooltip-light.tooltip-top .tooltip-arrow {
|
||||
border-color: #ffffff transparent transparent transparent;
|
||||
}
|
||||
|
||||
.tooltip-light.tooltip-bottom .tooltip-arrow {
|
||||
border-color: transparent transparent #ffffff transparent;
|
||||
}
|
||||
|
||||
.tooltip-light.tooltip-left .tooltip-arrow {
|
||||
border-color: transparent transparent transparent #ffffff;
|
||||
}
|
||||
|
||||
.tooltip-light.tooltip-right .tooltip-arrow {
|
||||
border-color: transparent #ffffff transparent transparent;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
.tooltip-content table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.tooltip-content table th,
|
||||
.tooltip-content table td {
|
||||
padding: 0.25rem 0.5rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.tooltip-content table th {
|
||||
font-weight: 600;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.tooltip-content table tr:nth-child(even) {
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
/* 深色主题下的表格样式 */
|
||||
.tooltip-dark .tooltip-content table th,
|
||||
.tooltip-dark .tooltip-content table td {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tooltip-dark .tooltip-content table th {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tooltip-dark .tooltip-content table tr:nth-child(even) {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
/* 动画效果 */
|
||||
@keyframes tooltip-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip-visible {
|
||||
animation: tooltip-fade-in 0.2s ease-out;
|
||||
}
|
||||
|
||||
/* 自定义偏移类 */
|
||||
.tooltip-custom-offset.tooltip-top {
|
||||
margin-top: 8px; /* 增加顶部边距 */
|
||||
pointer-events: auto; /* 允许鼠标事件 */
|
||||
}
|
||||
|
||||
/* 延长鼠标移入tooltip的路径 */
|
||||
.tooltip-custom-offset .tooltip-arrow {
|
||||
height: 12px; /* 增加箭头高度 */
|
||||
pointer-events: auto; /* 允许鼠标事件 */
|
||||
}
|
||||
+3
-2
@@ -26,6 +26,7 @@
|
||||
@import './components/file-tag.css';
|
||||
@import './components/message-modal.css';
|
||||
@import './components/toast.css';
|
||||
@import './components/TooltipStyles.css';
|
||||
|
||||
/* @import './components/modal.css'; */
|
||||
|
||||
@@ -132,7 +133,7 @@
|
||||
|
||||
/* === 侧边栏 === */
|
||||
.sidebar {
|
||||
@apply w-[280px] h-screen bg-white border-r border-gray-100 flex flex-col
|
||||
@apply w-[240px] h-screen bg-white border-r border-gray-100 flex flex-col
|
||||
transition-all duration-300 fixed left-0 top-0 z-[100] overflow-y-auto
|
||||
shadow-[0_0_15px_rgba(0,0,0,0.05)];
|
||||
}
|
||||
@@ -199,7 +200,7 @@
|
||||
|
||||
/* === 主内容区域 === */
|
||||
.main-content {
|
||||
@apply flex-1 ml-[280px] transition-all duration-300 min-h-screen flex flex-col;
|
||||
@apply flex-1 ml-[240px] transition-all duration-300 min-h-screen flex flex-col;
|
||||
}
|
||||
|
||||
.main-content.sidebar-collapsed {
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
.review-point-item:hover {
|
||||
/* background-color: #f5f5f5; */
|
||||
/* box-shadow: 10px 10px 10px 3px rgba(250, 173, 20, 0.6); */
|
||||
transform: translateX(-2px);
|
||||
/* transform: translateX(-2px); */
|
||||
box-shadow: 1px 4px 10px rgba(0, 0, 0, 0.08);
|
||||
|
||||
}
|
||||
@@ -294,8 +294,10 @@
|
||||
}
|
||||
|
||||
.status-success {
|
||||
background-color: #f6ffed;
|
||||
/* background-color: #f6ffed; */
|
||||
background-color: #e7ffcd;
|
||||
color: #52c41a;
|
||||
/* color: #143503; */
|
||||
}
|
||||
|
||||
.status-error {
|
||||
@@ -304,7 +306,7 @@
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
background-color: #fffbe6;
|
||||
background-color: #fff2aec7;
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user