修复提示框文字换行问题

This commit is contained in:
2025-04-26 18:43:22 +08:00
parent 6c40c4d074
commit 9a22e9092f
5 changed files with 129 additions and 91 deletions
+6 -43
View File
@@ -255,54 +255,17 @@ export async function getReviewPoints(fileId: string) {
// console.log('result-------', result.evaluated_results?.result);
// console.log('datacontent-------', data);
if (data && typeof data === 'object') {
// try {
// const dataObj = data as Record<string, string>;
// // 检查是否是预期的格式 {'立案报告表-完整性检查''缺失部分内容'}
// for (const key in dataObj) {
// if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
// // 使用'-'分割获取前缀(如'立案报告表')
// const prefix = key.split('-')[0];
// // console.log('prefix-------', prefix);
// // 检查document.data中的ocrResult是否存在这个key
// if (documentData.data?.ocrResult &&
// typeof documentData.data.ocrResult === 'object') {
// // ocrResult可能有嵌套的ocr_result属性
// let ocrData: OcrData = documentData.data.ocrResult as OcrData;
// // 检查是否有嵌套的ocr_result对象
// if ('ocr_result' in ocrData &&
// ocrData.ocr_result &&
// typeof ocrData.ocr_result === 'object') {
// ocrData = ocrData.ocr_result as OcrData;
// }
// for (const ocrKey in ocrData) {
// // 如果找到匹配的key
// if (ocrKey === prefix &&
// ocrData[ocrKey] &&
// typeof ocrData[ocrKey] === 'object' &&
// 'pages' in ocrData[ocrKey]) {
// // 获取pages数组
// const pages = ocrData[ocrKey].pages;
// if (Array.isArray(pages)) {
// // 存储每个key对应的页码数组
// contentPage[key] = pages;
// }
// break;
// }
// }
// }
// }
// }
// }
// 4-22 更改数据结构:通过拿到的data数据(每一个key对应一个object),将object中的page提取出来
try{
const dataObj = data as Record<string, {page: number | string,value: string}>;
for (const key in dataObj) {
if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
contentPage[key] = dataObj[key].page.toString();
let newPage = dataObj[key].page.toString();
// 如果newPage里面有文本,则把文本去掉
if(newPage.match(/\d+/g)){
newPage = newPage.match(/\d+/g)?.map(Number).join('') || '';
}
contentPage[key] = newPage;
}
}
}
+2 -2
View File
@@ -111,7 +111,7 @@ export function AIAnalysis({ analysisData, score, onConfirmResults }: AIAnalysis
</div>
{/* 操作按钮 */}
<div className="mt-4 flex space-x-4">
{/* <div className="mt-4 flex space-x-4">
<button
className="ant-btn ant-btn-default flex items-center"
onClick={handleExportReport}
@@ -124,7 +124,7 @@ export function AIAnalysis({ analysisData, score, onConfirmResults }: AIAnalysis
>
<i className="ri-check-double-line mr-1"></i> 确认评查结果
</button>
</div>
</div> */}
</div>
</div>
</div>
+14 -11
View File
@@ -175,17 +175,20 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
// 如果有目标页码,并且与上次不同或activeReviewPointId变化了,则执行跳转
if (targetPage && numPages && targetPage <= numPages && (targetPage !== prevTargetPageRef.current || activeReviewPointResultId)) {
prevTargetPageRef.current = targetPage;
let newTargetPage = targetPage;
try {
// 安全地访问ocrResult
if (fileContent.ocrResult && fileContent.ocrResult.__meta && fileContent.ocrResult.__meta.page_offset) {
// 可以根据需要使用page_offset调整目标页面
newTargetPage = targetPage + fileContent.ocrResult.__meta.page_offset;
}
} catch (error) {
console.error("访问ocrResult时出错:", error);
toastService.error("访问ocrResult时出错:" + (error instanceof Error ? error.message : '未知错误'));
}
const newTargetPage = targetPage;
// let newTargetPage = targetPage;
// console.log("targetPage:", targetPage);
// console.log("fileContent:", fileContent);
// try {
// // 安全地访问ocrResult
// if (fileContent.ocrResult && fileContent.ocrResult.__meta && fileContent.ocrResult.__meta.page_offset) {
// // 可以根据需要使用page_offset调整目标页面
// newTargetPage = targetPage + fileContent.ocrResult.__meta.page_offset;
// }
// } catch (error) {
// console.error("访问ocrResult时出错:", error);
// toastService.error("访问ocrResult时出错:" + (error instanceof Error ? error.message : '未知错误'));
// }
const pageElement = document.getElementById(`page-${newTargetPage}`);
if (pageElement) {
+54 -7
View File
@@ -73,8 +73,14 @@ export function Toast({
// 计算消息行数(用于可能的额外样式调整)
useEffect(() => {
if (message) {
// 简单估算行数: 假设每行平均40个字符,+1确保有足够空间
const estimatedLines = Math.ceil(message.length / 40) + 1;
// 更好地估算中文文本行数:假设每行平均25个中文字符(或50个英文字符)
const estimatedChars = message.split('').reduce((count, char) => {
// 判断是否为中文字符(粗略判断)
const isChinese = /[\u4e00-\u9fa5]/.test(char);
return count + (isChinese ? 2 : 1); // 中文字符算2个宽度单位
}, 0);
const estimatedLines = Math.ceil(estimatedChars / 50);
setMessageLines(Math.max(1, Math.min(estimatedLines, 10))); // 最小1行,最大10行
}
}, [message]);
@@ -91,15 +97,20 @@ export function Toast({
// 自动关闭
useEffect(() => {
if (isOpen && autoClose && !isHovered) {
// 根据消息长度调整显示时间,长消息显示更长时间
// 根据消息长度调整显示时间,长消息显示更长时间
const messageLength = message.length;
const baseDelay = autoCloseDelay || DEFAULT_AUTO_CLOSE_DELAY;
// 按照文本长度比例延长显示时间
const adjustedDelay = Math.min(
autoCloseDelay + (message.length > 100 ? 2000 : 0),
10000 // 最长不超过10
baseDelay + (messageLength > 20 ? messageLength * 30 : 0),
15000 // 最长不超过15
);
const timer = setTimeout(() => {
handleClose();
}, adjustedDelay);
return () => clearTimeout(timer);
}
}, [isOpen, autoClose, autoCloseDelay, handleClose, message, isHovered]);
@@ -139,6 +150,42 @@ export function Toast({
}
}, [handleClose]);
// 处理长文本
const formatMessage = (text: string) => {
// 清理文本中的多余空白,但保留换行符
const cleanedText = text.replace(/[ \t]+/g, ' ');
// 处理中文文本最后两个字符换行问题
const fixChineseWrapping = (content: string) => {
// 如果内容长度小于3,或已有换行符,直接返回
if (content.length < 3 || content.includes('\n')) {
return content;
}
// 检测是否是中文文本
const isChinese = /[\u4e00-\u9fa5]/.test(content);
if (!isChinese) {
return content;
}
// 在中文文本中,添加零宽空格避免最后两个字符换行
// 在文本末尾前两个字符之间添加零宽不换行空格,防止它们被分开
return content.slice(0, -2) + '\u2060' + content.slice(-2);
};
// 如果文本包含换行符,按换行符分割
if (cleanedText.includes('\n')) {
return cleanedText.split('\n').map((line, index) => (
<div key={index} className="toast-message-line">
{fixChineseWrapping(line)}
</div>
));
}
// 如果没有换行符,直接返回整个文本,应用修复
return fixChineseWrapping(cleanedText);
};
// 如果通知未打开,不渲染
if (!isOpen || !portalElement) {
return null;
@@ -147,7 +194,7 @@ export function Toast({
// 使用 Portal 渲染通知
return createPortal(
<div
className={`toast toast-${type} ${isClosing ? 'closing' : ''} ${className} ${messageLines > 3 ? 'toast-multiline' : ''}`}
className={`toast toast-${type} ${isClosing ? 'closing' : ''} ${className} ${messageLines > 1 ? 'toast-multiline' : ''}`}
role="status"
aria-live="polite"
onMouseEnter={handleMouseEnter}
@@ -158,7 +205,7 @@ export function Toast({
{renderIcon()}
</div>
<div className="toast-message">
{message}
{formatMessage(message)}
</div>
</div>
<button
+53 -28
View File
@@ -27,17 +27,17 @@
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
padding: 12px 16px;
display: flex;
align-items: flex-start; /* 改为flex-start让图标和文本从顶部对齐,更好地支持多行文本 */
align-items: flex-start;
justify-content: space-between;
width: fit-content; /* 更好地适应内容宽度 */
min-width: 300px; /* 最小宽度 */
max-width: 100%; /* 相对于容器的最大宽度 */
width: max-content;
min-width: 300px;
max-width: 450px;
animation: slideInDown 0.3s ease forwards;
overflow: hidden;
overflow: visible;
pointer-events: auto;
border-left: 4px solid #1890ff;
margin: 0 auto; /* 水平居中 */
transition: width 0.2s ease-out; /* 添加平滑的宽度过渡效果 */
margin: 0 auto;
box-sizing: border-box;
}
/* 多行文本的Toast样式调整 */
@@ -52,25 +52,25 @@
.toast-content {
display: flex;
/* align-items: flex-start; 改为flex-start让图标和文本从顶部对齐 */
align-items: center;
align-items: flex-start;
flex: 1;
min-width: 0; /* 确保flex子项不会溢出父容器 */
margin-right: 8px; /* 给关闭按钮留出空间 */
min-width: 0;
margin-right: 8px;
}
/* 图标容器 */
.toast-icon-wrapper {
margin-right: 12px;
flex-shrink: 0;
margin-top: 2px; /* 微调图标位置,与文本第一行更好地对齐 */
margin-top: 2px;
width: 24px;
}
/* 通知图标 */
.toast-icon {
font-size: 20px;
height: 24px;
width: 24px;
height: 20px;
width: 20px;
display: flex;
align-items: center;
justify-content: center;
@@ -113,16 +113,39 @@
/* 消息样式 */
.toast-message {
font-size: 14px;
line-height: 1.5;
line-height: 1.6;
color: #333;
word-break: break-word; /* 允许在任何字符处换行 */
word-wrap: break-word; /* 长词自动换行 */
white-space: pre-wrap; /* 保留空格和换行,但允许文本换行 */
overflow-wrap: break-word; /* 确保长单词也能换行 */
flex: 1;
min-width: 0; /* 确保flex子项不会溢出父容器 */
max-height: none; /* 移除最大高度限制,让内容自然增长 */
max-width: calc(100% - 60px); /* 确保有足够空间给图标和关闭按钮 */
min-width: 0;
text-align: left;
padding: 1px 0;
/* 简化文本样式 */
white-space: normal;
}
/* 消息行样式 */
.toast-message-line {
display: block;
margin-bottom: 3px;
}
.toast-message-line:last-child {
margin-bottom: 0;
}
/* 对于中文文本特别处理 */
:lang(zh) .toast-message,
:lang(zh-CN) .toast-message,
:lang(zh-TW) .toast-message {
/* 中文特殊处理 */
text-indent: 0; /* 确保没有首行缩进 */
text-align-last: left; /* 确保最后一行也左对齐 */
}
/* 对于英文文本,特别处理 */
.toast-message:lang(en) {
word-break: normal;
}
/* 关闭按钮 */
@@ -141,8 +164,8 @@
margin-left: 8px;
flex-shrink: 0;
padding: 0;
align-self: flex-start; /* 按钮始终位于顶部 */
margin-top: 2px; /* 微调按钮位置 */
align-self: flex-start;
margin-top: 2px;
}
.toast-close:hover {
@@ -204,7 +227,8 @@
.toast {
min-width: 250px;
width: auto; /* 在平板上自动调整宽度 */
max-width: 400px;
width: auto;
}
}
@@ -218,8 +242,9 @@
.toast {
padding: 10px 12px;
min-width: 0; /* 移动设备上取消最小宽度限制 */
width: 100%; /* 在移动设备上占满容器宽度 */
min-width: 0;
max-width: 330px;
width: calc(100% - 20px);
}
.toast-icon {
@@ -230,7 +255,7 @@
.toast-message {
font-size: 13px;
max-width: calc(100% - 50px); /* 移动设备上调整最大宽度 */
max-width: calc(100% - 50px);
}
.toast-close {