提交 58dd1d06 authored 作者: 安云鹏's avatar 安云鹏

修改 底部 侧边栏 分析 报文

上级 581d2dec
差异被折叠。
......@@ -50,7 +50,11 @@ if(route.path){
navPath.value=route.path
}
const onNavListClick=(path)=>{
navPath.value=path
if(path=='/writtingAsstaint'){
navPath.value=path
}else{
ElMessage.error('正在开发中')
}
}
</script>
<style lang="scss" scoped>
......
......@@ -295,13 +295,16 @@ export function useMarkdownStream() {
// 预处理内容
// const processedContent = preprocessMarkdown(rawContent.value)
let content = rawContent.value || ''
// 将 ==n== 转换为按钮样式的 HTML
// 使用正向预读和反向预读确保只匹配被 == 包裹的数字
content = content.replace(/==(\d+)==/g, (match, p1) => {
return `<button class="clause-ref-btn" data-clause="${p1}">${p1}</button>`
})
// content = content.replace(/==(\d+)、==/g, (match, p1) => {
// return `<button class="clause-ref-btn" data-clause="${p1}">${p1}</button>`
// })
content = content.replace(/==\s*(\d+)、.*?==/g, (match, p1) => {
return `<button class="clause-ref-btn" data-clause="${match.replace(/==/g, '') }">${p1}</button>`;
});
return md.render(content)
})
......
......@@ -2,7 +2,7 @@
<div class="writtingBottom">
<!-- 文档停止解析 -->
<div class="parsed" v-if="store.bottomProgressNum>0&&store.bottomProgressNum<100">
<div class="parsed" v-if="store.bottomProgressNum>0&&store.bottomProgressNum!=100&&store.writeProgressNum<10">
<div class="analysis" @click="store.resetGenerateState">
<div class="icon"></div>
<span class="text-tip-2-bold">停止</span>
......@@ -10,7 +10,9 @@
<div class="progress">
<div class="login">
<el-progress type="circle" :percentage="store.bottomProgressNum" :width="24" :height="24" style="margin-right: 15px;" :show-text="false" color="rgb(5, 95, 194)"/>
<span class="text-tip-2-bold">文档翻译中</span>
<span class="text-tip-2-bold">
文档翻译中
</span>
</div>
<div class="text-tip-2" >
<div ref="processContainerRef" v-html="renderedProcess"></div>
......@@ -21,7 +23,7 @@
<!-- 开始写报 -->
<!-- -->
<div class="parsed" v-else-if="store.bottomProgressNum>=100">
<div class="analysis" v-if="store.isWriteStart&&store.writeProgressNum<100" @click="store.writeGenerateState">
<div class="analysis" v-if="store.writeProgressNum>0&&store.writeProgressNum!=100" @click="store.writeGenerateState">
<div class="icon"></div>
<span class="text-tip-2-bold">停止</span>
</div>
......@@ -35,10 +37,21 @@
</div>
<div class="progress">
<div class="login">
<!-- 如果store.writeProgressNum>=1 点击了写报 否则是思维导图已完成 -->
<div class="login" v-if="store.writeProgressNum>=1&&store.writeProgressNum<100">
<el-progress type="circle" :percentage="store.writeProgressNum" :width="24" :height="24" style="margin-right: 15px;" :show-text="false" color="rgb(5, 95, 194)"/>
<span class="text-tip-2-bold">智能写报中</span>
<span class="text-tip-2-bold"> 智能写报中</span>
</div>
<div class="login" v-else-if="store.writeProgressNum>=100">
<el-icon style="width: 24px;height: 24px;margin-right: 4px;"><CircleCheckFilled style="width: 24px;height: 24px;" class="var(--color-primary-35)" /></el-icon>
<span class="text-tip-2-bold"> 文档解析完成</span>
</div>
<div class="login" v-else-if="store.bottomProgressNum>=100">
<el-icon style="width: 24px;height: 24px;margin-right: 4px;"><CircleCheckFilled style="width: 24px;height: 24px;" class="var(--color-primary-35)" /></el-icon>
<!-- <el-progress type="circle" :percentage="store.writeProgressNum" :width="24" :height="24" style="margin-right: 15px;" :show-text="false" color="rgb(5, 95, 194)"/> -->
<span class="text-tip-2-bold"> 思维导图已完成</span>
</div>
<div class="text-tip-2" >
<div ref="processWriteLogRef" v-html="renderedProcess"> </div>
</div>
......@@ -76,6 +89,8 @@ const onAnalysisClick=()=>{
}
const onWriteClick=()=>{
store.isShowSteps = false
emit("write");
}
const { renderedProcess, updateProcess, clearContent } = useStream();
......
......@@ -159,7 +159,7 @@
<!-- </div>
</div> -->
<!-- 条款翻译侧边栏 srot -->
<div class="left-box translation-box" :class="{ 'has-back-btn': store.isGenerating }" v-if="store.isShowClauseTranslation&&store.headerTabType=='message'">
<div class="left-box translation-box" :class="{ 'has-back-btn': store.isGenerating }" v-if="store.isShowSteps&&store.headerTabType=='message'">
<div class="translation-main-box">
<!-- <div class="translation-actions" v-if="!store.isGenerating">
<div class="back-input-btn" @click="store.backToInputAndClear">返回输入栏</div>
......@@ -198,9 +198,9 @@
</div>
</div>
<!-- 步骤侧边栏显隐按钮 -->
<!-- <div class="toggle-steps-btn" @click="store.isShowSteps = !store.isShowSteps">
<div class="toggle-steps-btn" @click="store.isShowSteps = !store.isShowSteps">
<div class="arrow" :class="{ 'is-active': store.isShowSteps }"></div>
</div> -->
</div>
</div>
</div>
</template>
......@@ -245,16 +245,27 @@ watch(
async (newId) => {
if (!newId || !translationContentRef.value) return;
await nextTick();
const container = translationContentRef.value;
const item = container.querySelector(`.translation-item[data-clause-number="${newId}"]`);
const result = newId.replace(/^\d+、/, '');
const item = container.querySelector(`.translation-item[data-clause-number="${newId.match(/^(\d+)/)[1]}"]`);
const itemHtml=item.querySelector(`.translated-text`);
if (!item) return;
// 你已经拿到的 外层大标签
const element =itemHtml
// 你要找的文字
const targetText = result
const location=findTextInElement(element, targetText);
const containerRect = container.getBoundingClientRect();
const itemRect = item.getBoundingClientRect();
const itemRect = location;
const delta = itemRect.top - containerRect.top;
const targetTop = container.scrollTop + delta;
const targetTop = container.scrollTop + delta;
console.log(delta)
// 让高亮条款的“标题区域”贴到容器顶部
container.scrollTo({
top: Math.max(0, targetTop),
......@@ -262,6 +273,77 @@ watch(
});
}
);
// 👇 核心:在 element 内部找文字位置
// =========================================
function findTextInElement(element, targetText ) {
// 遍历标签内的所有内容
const nodes = element.childNodes;
let rect =''
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
// 只找纯文字
if (node.nodeType === 3) {
const originalText = node.textContent;
function cleanText(str) {
return str
.replace(/(/g, '(')
.replace(/)/g, ')')
.replace(/,/g, ',')
.replace(/。/g, '.')
.replace(/:/g, ':')
.replace(/;/g, ';');
}
// 清理后的文字(无标点)
const nodeClean = cleanText(originalText);
const targetClean = cleanText(targetText);
console.log(nodeClean)
console.log(targetClean)
console.log(nodeClean.includes(targetClean))
// 用干净文字对比
if (nodeClean.includes(targetClean)) {
// 找到真实位置(用原始文本定位,不影响)
const index = originalText.indexOf(
originalText.includes(targetText) ? targetText : originalText
);
const range = document.createRange();
range.setStart(node, index);
range.setEnd(node, index + targetText.length);
// 拿到位置
rect = range.getBoundingClientRect();
const marks = element.querySelectorAll('mark');
marks.forEach(mark => {
// 把 mark 里的文字放回原位,删除标签
const parent = mark.parentNode;
while (mark.firstChild) {
parent.insertBefore(mark.firstChild, mark);
}
parent.removeChild(mark);
// 合并相邻文本节点(恢复页面原貌)
parent.normalize();
});
const mark = document.createElement("mark");
mark.style.backgroundColor = '#055FC2';
mark.style.color = "#fff"; // 文字颜色
range.surroundContents(mark);
break;
}
}
}
return rect
}
// 监听 store.processLog 变化,更新步骤内容并滚动
watch(
......@@ -1024,4 +1106,4 @@ defineExpose({
}
}
}
</style>
\ No newline at end of file
</style>
......@@ -42,6 +42,8 @@ const handleGlobalClick = (e) => {
if (clauseId) {
store.highlightClauseId = clauseId;
// 翻译栏一直显示,所以这里只需要确保它在视图内
store.isShowSteps = true;
console.log(store.highlightClauseId )
}
}
};
......@@ -88,6 +90,7 @@ watch(
},
{ immediate: true }
);
</script>
<style lang="scss" scoped>
......
......@@ -33,24 +33,25 @@
<div class="writting-main">
<!-- 左侧子组件:绑定ref -->
<!-- <writtingleftBox ref="leftBoxRef" @generate="handleGenerate" /> -->
<!-- <writtingleftBox ref="leftBoxRef" /> -->
<WrittingLeftBox ref="leftBoxRef" />
<!-- 翻译 -->
<!-- <WrittingTranslate v-if="store.isShowClauseTranslation&&store.headerTabType=='translate'"></WrittingTranslate> -->
<!-- 思维导图 v-else-if="store.isShowClauseTranslation&&store.headerTabType=='mind'"-->
<WrittingMind ></WrittingMind>
<WrittingTranslate v-if="store.isShowClauseTranslation&&store.headerTabType=='translate'"></WrittingTranslate>
<!-- 思维导图 " -->
<WrittingMind v-else-if="store.isShowClauseTranslation&&store.headerTabType=='mind' "></WrittingMind>
<!-- 写报 -->
<!-- <WrittingMessage v-else-if="store.isShowClauseTranslation&&store.headerTabType=='message'"></WrittingMessage> -->
<WrittingMessage v-else-if="store.isShowClauseTranslation&&store.headerTabType=='message'"></WrittingMessage>
<!-- 无数据时显示占位图 -->
<!-- <div v-else class="main-placeholder">
<div v-else class="main-placeholder">
<img src="./assets/images/container-image.png" alt="无数据占位图" />
<div class="placeholder-text">
<div v-if="store.isGenerating">智能体写报任务执行中...</div>
<div v-else>上传文件后点击“生成报文”开始写报...</div>
</div>
</div> -->
</div>
<!-- 右侧子组件:绑定ref -->
<!-- <writtingMainBox v-show="!!store.reportContent" ref="mainBoxRef" :report-content="store.reportContent" /> -->
......@@ -66,7 +67,7 @@ import { onMounted, onUnmounted, ref, nextTick } from "vue";
import { useRoute } from "vue-router";
import { ElMessage } from "element-plus";
import { useWrittingAsstaintStore } from "@/stores/writtingAsstaintStore";
import writtingleftBox from "./components/WrittingLeftBox.vue";
import WrittingLeftBox from "./components/WrittingLeftBox.vue";
import WrittingHeader from "./components/WrittingHeader.vue"; //头
import WrittingBottom from "./components/WrittingBottom.vue"; //底部
......@@ -105,11 +106,12 @@ const handleGenerate = async () => {
};
const handleWrite=async ()=>{
try {
console.log(1)
// // 等待DOM更新(确保子组件DOM已挂载)
store.tabList[2].active=true //写报生成之后放开写报按钮
store.headerTabType='translate'
await nextTick();
await store.generateWrite()
console.log(2)
} catch (error) {
ElMessage.error(error.message);
console.error("生成写报失败:", error);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论