1、上传新增图片类型

2、审计内容的AI生成恢复生成报告接口
This commit is contained in:
2026-06-04 21:29:00 +08:00
parent 0999c362b8
commit de4d6fe77c
2 changed files with 1626 additions and 1433 deletions

View File

@@ -12,7 +12,7 @@
已加入 {{ queuedFileNames.length }} 个文件
</div>
<a-upload-dragger
accept=".pdf,.doc,.docx,.txt,.md,.xls,.xlsx"
accept=".pdf,.doc,.docx,.txt,.md,.xls,.xlsx,.jpg,.png,.jpeg"
:show-upload-list="false"
:customRequest="doUpload"
:multiple="true"

View File

@@ -35,10 +35,19 @@
</a-descriptions>
</a-card>
<a-card style="margin-bottom: 20px; text-align: center; background: transparent" :bordered="false">
<a-card
style="margin-bottom: 20px; text-align: center; background: transparent"
:bordered="false"
>
<a-space>
<a-tooltip title="并行生成所有 9 个章节的内容(包含各小节)">
<a-button size="large" type="primary" @click="handleGenerateAll" :loading="generatingAll" class="generate-all-button">
<a-button
size="large"
type="primary"
@click="handleGenerateAll"
:loading="generatingAll"
class="generate-all-button"
>
<template #icon>
<UngroupOutlined />
</template>
@@ -61,7 +70,12 @@
加载草稿
</a-button>
</a-tooltip>
<a-button size="large" type="danger" class="export-button" @click="handleExport">
<a-button
size="large"
type="danger"
class="export-button"
@click="handleExport"
>
<template #icon>
<UploadOutlined />
</template>
@@ -73,10 +87,16 @@
<!-- 快速导航 -->
<a-card style="margin-bottom: 20px" :bordered="false">
<template #title>
<div style="display: flex; align-items: center; justify-content: space-between;">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<span>快速导航</span>
<a-tooltip title="快捷键Ctrl+1~9 快速跳转Ctrl+↑↓ 上下导航">
<QuestionCircleOutlined style="color: #999; cursor: help;"/>
<QuestionCircleOutlined style="color: #999; cursor: help" />
</a-tooltip>
</div>
</template>
@@ -90,7 +110,7 @@
size="small"
@click="scrollToSection(index)"
class="nav-button"
:class="{ 'active': currentSection === index }"
:class="{ active: currentSection === index }"
>
<span class="nav-number">{{ item.number }}</span>
<span class="nav-text">{{ item.name }}</span>
@@ -102,7 +122,11 @@
<div class="progress-bar">
<div
class="progress-fill"
:style="{ width: `${((currentSection + 1) / navigationItems.length) * 100}%` }"
:style="{
width: `${
((currentSection + 1) / navigationItems.length) * 100
}%`
}"
></div>
</div>
<div class="progress-text">
@@ -170,34 +194,72 @@
<!-- </div>-->
<!-- 单内容部分 -->
<template v-if="!item.children">
<div class="content-with-ai-button">
<!-- <div class="content-with-ai-button">-->
<!-- <a-textarea-->
<!-- v-model:value="item.content"-->
<!-- :rows="item.rows || 8"-->
<!-- :placeholder="'点击 (AI 生成) 按钮让 AI 为您生成该部分内容,或直接填入'"-->
<!-- class="content-textarea"-->
<!-- style="background-color: #f0fdf4"-->
<!-- />-->
<!-- <a-button-->
<!-- type="primary"-->
<!-- size="large"-->
<!-- @click="generateContent(index)"-->
<!-- :loading="item.generating"-->
<!-- class="ai-generate-btn"-->
<!-- >-->
<!-- <template #icon>-->
<!-- <RobotOutlined/>-->
<!-- </template>-->
<!-- AI 生成-->
<!-- </a-button>-->
<!-- </div>-->
<a-textarea
v-model:value="item.content"
:rows="item.rows || 8"
:placeholder="'点击(AI生成)按钮让AI为您生成该部分内容或直接填入'"
class="content-textarea"
style="background-color: #f0fdf4"
style="margin-top: 16px; background-color: #f0fdf4"
/>
<div style="margin-top: 12px">
<div class="question-prompt">AI小助手</div>
<div class="textarea-with-button" style="width: 600px">
<a-textarea
v-model:value="item.suggestion"
:rows="3"
placeholder="请输入您的要求并回车..."
class="suggestion-textarea-inner"
@pressEnter="generateContent(index)"
/>
<a-button
type="primary"
size="large"
type="danger"
size="small"
@click="generateContent(index)"
:loading="item.generating"
class="ai-generate-btn"
class="send-button-inner"
>
<template #icon>
<RobotOutlined />
</template>
AI 生成
发送
</a-button>
</div>
</div>
</template>
<!-- 多内容部分 -->
<template v-if="item.children">
<div v-for="(child, childIndex) in item.children" :key="childIndex" class="child-section">
<div
v-for="(child, childIndex) in item.children"
:key="childIndex"
class="child-section"
>
<div class="child-header">
<span class="child-title">{{ `${childIndex + 1}${child.name}` }}</span>
<span class="child-title">{{
`${childIndex + 1}${child.name}`
}}</span>
<a-space>
<a-button
type="primary"
@@ -260,7 +322,7 @@ import {ref, reactive, watch, onMounted, onUnmounted} from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject } from 'ele-admin-pro';
import { copyText } from '@/utils/common';
import {PwlProject} from "@/api/pwl/pwlProject/model";
import { PwlProject } from '@/api/pwl/pwlProject/model';
import {
UngroupOutlined,
DownloadOutlined,
@@ -271,7 +333,13 @@ import {
ReloadOutlined,
SaveOutlined
} from '@ant-design/icons-vue';
import {generateDefaultText, downloadAuditReport, queryAuditReport, saveAuditReport} from "@/api/ai/auditReport";
import {
generateDefaultText,
downloadAuditReport,
queryAuditReport,
saveAuditReport,
generateAuditReport
} from '@/api/ai/auditReport';
import { getPwlProjectLibraryByIds } from '@/api/pwl/pwlProjectLibrary';
const useForm = Form.useForm;
@@ -371,7 +439,8 @@ const navigationItems = ref([
},
{
name: '(四)审计期间合并口径年度资产负债及各项业务总体情况',
placeholder: '请输入审计期间合并口径年度资产负债及各项业务总体情况...',
placeholder:
'请输入审计期间合并口径年度资产负债及各项业务总体情况...',
content: '',
suggestion: '',
formCommit: 44,
@@ -398,7 +467,8 @@ const navigationItems = ref([
children: [
{
name: '(一)贯彻执行党和国家有关经济方针和上级决策部署情况',
placeholder: '请输入贯彻执行党和国家有关经济方针和上级决策部署情况...',
placeholder:
'请输入贯彻执行党和国家有关经济方针和上级决策部署情况...',
content: '',
suggestion: '',
formCommit: 51,
@@ -409,7 +479,8 @@ const navigationItems = ref([
},
{
name: '(二)公司发展战略规划的制定、执行和效果情况以及年度责任目标完成情况',
placeholder: '请输入公司发展战略规划的制定、执行和效果情况以及年度责任目标完成情况...',
placeholder:
'请输入公司发展战略规划的制定、执行和效果情况以及年度责任目标完成情况...',
content: '',
suggestion: '',
formCommit: 52,
@@ -431,7 +502,8 @@ const navigationItems = ref([
},
{
name: '(四)公司法人治理结构的建立、健全和运行情况,内部控制制度的制定和执行情况',
placeholder: '请输入公司法人治理结构的建立、健全和运行情况,内部控制制度的制定和执行情况...',
placeholder:
'请输入公司法人治理结构的建立、健全和运行情况,内部控制制度的制定和执行情况...',
content: '',
suggestion: '',
formCommit: 54,
@@ -442,7 +514,8 @@ const navigationItems = ref([
},
{
name: '(五)公司财务的真实合法效益情况,风险管控情况,境外资产管理情况',
placeholder: '请输入公司财务的真实合法效益情况,风险管控情况,境外资产管理情况...',
placeholder:
'请输入公司财务的真实合法效益情况,风险管控情况,境外资产管理情况...',
content: '',
suggestion: '',
formCommit: 55,
@@ -453,7 +526,8 @@ const navigationItems = ref([
},
{
name: '(六)在经济活动中落实有关党风廉政建设责任和遵守廉洁从业规定情况',
placeholder: '请输入在经济活动中落实有关党风廉政建设责任和遵守廉洁从业规定情况...',
placeholder:
'请输入在经济活动中落实有关党风廉政建设责任和遵守廉洁从业规定情况...',
content: '',
suggestion: '',
formCommit: 56,
@@ -490,7 +564,8 @@ const navigationItems = ref([
number: '六',
name: '重要风险的识别及应对',
title: '6、重要风险的识别及应对',
description: '点击"AI 生成"按钮让 AI 为您生成该部分内容,或直接在下方编辑',
description:
'点击"AI 生成"按钮让 AI 为您生成该部分内容,或直接在下方编辑',
generating: false,
children: [
{
@@ -654,7 +729,7 @@ const form = reactive<PwlProject>({
// 修改时间
updateTime: undefined,
// 知识库id
kbId: undefined,
kbId: undefined
});
// 请求状态
@@ -689,9 +764,9 @@ const handleGenerateAll = async () => {
generatingAll.value = true;
try {
// 先清空所有内容
navigationItems.value.forEach(item => {
navigationItems.value.forEach((item) => {
if (item.children) {
item.children.forEach(child => {
item.children.forEach((child) => {
child.content = '';
});
} else {
@@ -730,7 +805,7 @@ const hasContent = (index: number) => {
if (!section) return false;
if (section.children) {
return section.children.some(child => child.content?.trim());
return section.children.some((child) => child.content?.trim());
}
return !!section.content?.trim();
};
@@ -760,17 +835,25 @@ const saveAllDrafts = async () => {
tableType: 'audit_report',
content: '', // 主章节内容为空
formCommit: navItem.formCommit,
records: [{
records: [
{
name: child.name,
content: child.content || '',
formCommit: child.formCommit
}]
}
]
};
// 构建当前小节的预览 HTML
let previewHtml = '<div class="audit-report">';
previewHtml += `<h3>${currentChildData.number}${currentChildData.name}${currentChildData.title ? ' - ' + currentChildData.title : ''}</h3>`;
previewHtml += `<div><strong>${child.name}:</strong> ${child.content || ''}</div>`;
previewHtml += `<h3>${currentChildData.number}${
currentChildData.name
}${
currentChildData.title ? ' - ' + currentChildData.title : ''
}</h3>`;
previewHtml += `<div><strong>${child.name}:</strong> ${
child.content || ''
}</div>`;
previewHtml += '</div>';
await saveAuditReport({
@@ -787,7 +870,9 @@ const saveAllDrafts = async () => {
});
savedCount++;
console.log(`[保存草稿] 已保存:${navItem.number}${navItem.name} - ${child.name}, formCommit: ${child.formCommit}`);
console.log(
`[保存草稿] 已保存:${navItem.number}${navItem.name} - ${child.name}, formCommit: ${child.formCommit}`
);
}
} else {
// 无子项,直接保存主章节
@@ -803,7 +888,11 @@ const saveAllDrafts = async () => {
// 构建当前章节的预览 HTML
let previewHtml = '<div class="audit-report">';
previewHtml += `<h3>${currentSectionData.number}${currentSectionData.name}${currentSectionData.title ? ' - ' + currentSectionData.title : ''}</h3>`;
previewHtml += `<h3>${currentSectionData.number}${
currentSectionData.name
}${
currentSectionData.title ? ' - ' + currentSectionData.title : ''
}</h3>`;
if (currentSectionData.content) {
previewHtml += `<div>${currentSectionData.content}</div>`;
}
@@ -823,7 +912,9 @@ const saveAllDrafts = async () => {
});
savedCount++;
console.log(`[保存草稿] 已保存:${navItem.number}${navItem.name}, formCommit: ${navItem.formCommit}`);
console.log(
`[保存草稿] 已保存:${navItem.number}${navItem.name}, formCommit: ${navItem.formCommit}`
);
}
}
@@ -848,13 +939,13 @@ const loadDrafts = async () => {
// 收集所有的 formCommit 值(包括主章节和所有小节)
const formCommits: number[] = [];
navigationItems.value.forEach(item => {
navigationItems.value.forEach((item) => {
if (item.formCommit) {
// 主章节有 formCommit直接使用
formCommits.push(item.formCommit);
} else if (item.children && item.children.length > 0) {
// 有子项的章节,收集所有小节的 formCommit
item.children.forEach(child => {
item.children.forEach((child) => {
if (child.formCommit) {
formCommits.push(child.formCommit);
}
@@ -884,7 +975,7 @@ const loadDrafts = async () => {
// 解析并填充数据
let hasData = false;
results.forEach(result => {
results.forEach((result) => {
if (result.data) {
hasData = true;
const reportContent = JSON.parse(result.data.reportContent || '{}');
@@ -893,24 +984,40 @@ const loadDrafts = async () => {
const section = reportContent.sections[0];
if (section) {
// 找到对应的 navigationItem通过匹配任意一个 formCommit
const navItemIndex = navigationItems.value.findIndex(item =>
const navItemIndex = navigationItems.value.findIndex(
(item) =>
item.formCommit === result.formCommit ||
(item.children && item.children.some(child => child.formCommit === result.formCommit))
(item.children &&
item.children.some(
(child) => child.formCommit === result.formCommit
))
);
if (navItemIndex >= 0) {
const navItem = navigationItems.value[navItemIndex];
console.log(`[加载草稿] 恢复章节:${navItem.number}${navItem.name}, formCommit: ${result.formCommit}`);
console.log(
`[加载草稿] 恢复章节:${navItem.number}${navItem.name}, formCommit: ${result.formCommit}`
);
// 恢复内容
if (navItem.children && section.records && Array.isArray(section.records)) {
if (
navItem.children &&
section.records &&
Array.isArray(section.records)
) {
// 有子项,根据 formCommit 匹配每个小节
section.records.forEach((rec: any) => {
const childIndex = navItem.children.findIndex(child => child.formCommit === rec.formCommit);
const childIndex = navItem.children.findIndex(
(child) => child.formCommit === rec.formCommit
);
if (childIndex >= 0) {
navItem.children[childIndex].content = rec.content || '';
console.log(` - 恢复小节:${navItem.children[childIndex].name}, content length: ${rec.content?.length || 0}`);
console.log(
` - 恢复小节:${
navItem.children[childIndex].name
}, content length: ${rec.content?.length || 0}`
);
}
});
} else if (!navItem.children && section.content) {
@@ -918,7 +1025,10 @@ const loadDrafts = async () => {
navItem.content = section.content || '';
}
} else {
console.warn('[加载草稿] 未找到匹配的章节formCommit:', result.formCommit);
console.warn(
'[加载草稿] 未找到匹配的章节formCommit:',
result.formCommit
);
}
}
}
@@ -958,7 +1068,9 @@ const saveSectionContent = async (sectionIndex: number) => {
for (const child of section.children) {
// 检查内容是否为空,为空则跳过不保存
if (!child.content || !child.content.trim()) {
console.log(`[保存整章] 跳过空内容:${section.number}${section.name} - ${child.name}`);
console.log(
`[保存整章] 跳过空内容:${section.number}${section.name} - ${child.name}`
);
continue;
}
@@ -969,17 +1081,25 @@ const saveSectionContent = async (sectionIndex: number) => {
tableType: 'audit_report',
content: '', // 主章节内容为空
formCommit: section.formCommit,
records: [{
records: [
{
name: child.name,
content: child.content || '',
formCommit: child.formCommit
}]
}
]
};
// 构建当前小节的预览 HTML
let previewHtml = '<div class="audit-report">';
previewHtml += `<h3>${currentChildData.number}${currentChildData.name}${currentChildData.title ? ' - ' + currentChildData.title : ''}</h3>`;
previewHtml += `<div><strong>${child.name}:</strong> ${child.content || ''}</div>`;
previewHtml += `<h3>${currentChildData.number}${
currentChildData.name
}${
currentChildData.title ? ' - ' + currentChildData.title : ''
}</h3>`;
previewHtml += `<div><strong>${child.name}:</strong> ${
child.content || ''
}</div>`;
previewHtml += '</div>';
await saveAuditReport({
@@ -996,19 +1116,25 @@ const saveSectionContent = async (sectionIndex: number) => {
});
savedChildrenCount++;
console.log(`[保存整章] 已保存:${section.number}${section.name} - ${child.name}, formCommit: ${child.formCommit}`);
console.log(
`[保存整章] 已保存:${section.number}${section.name} - ${child.name}, formCommit: ${child.formCommit}`
);
}
if (savedChildrenCount === 0) {
message.info('该章节没有需要保存的内容(所有小节均为空)');
} else {
message.success(`${section.number}${section.name} 已保存(共 ${savedChildrenCount}/${section.children.length} 个小节)`);
message.success(
`${section.number}${section.name} 已保存(共 ${savedChildrenCount}/${section.children.length} 个小节)`
);
}
} else {
// 无子项,直接保存主章节
// 检查内容是否为空,为空则跳过不保存
if (!section.content || !section.content.trim()) {
console.log(`[保存整章] 跳过空内容:${section.number}${section.name}`);
console.log(
`[保存整章] 跳过空内容:${section.number}${section.name}`
);
message.info('该章节没有需要保存的内容');
sectionSaving[sectionIndex] = false;
return;
@@ -1026,7 +1152,11 @@ const saveSectionContent = async (sectionIndex: number) => {
// 只构建当前章节的预览 HTML
let previewHtml = '<div class="audit-report">';
previewHtml += `<h3>${currentSectionData.number}${currentSectionData.name}${currentSectionData.title ? ' - ' + currentSectionData.title : ''}</h3>`;
previewHtml += `<h3>${currentSectionData.number}${
currentSectionData.name
}${
currentSectionData.title ? ' - ' + currentSectionData.title : ''
}</h3>`;
if (currentSectionData.content) {
previewHtml += `<div>${currentSectionData.content}</div>`;
}
@@ -1087,17 +1217,23 @@ const saveChildContent = async (sectionIndex: number, childIndex: number) => {
tableType: 'audit_report',
content: '', // 主章节内容为空
formCommit: section.formCommit,
records: [{
records: [
{
name: child.name,
content: child.content || '',
formCommit: child.formCommit
}]
}
]
};
// 构建当前小节的预览 HTML
let previewHtml = '<div class="audit-report">';
previewHtml += `<h3>${currentChildData.number}${currentChildData.name}${currentChildData.title ? ' - ' + currentChildData.title : ''}</h3>`;
previewHtml += `<div><strong>${child.name}:</strong> ${child.content || ''}</div>`;
previewHtml += `<h3>${currentChildData.number}${currentChildData.name}${
currentChildData.title ? ' - ' + currentChildData.title : ''
}</h3>`;
previewHtml += `<div><strong>${child.name}:</strong> ${
child.content || ''
}</div>`;
previewHtml += '</div>';
// 调用保存接口(使用当前小节的 formCommit
@@ -1140,10 +1276,14 @@ const reloadSectionData = async (sectionIndex: number) => {
try {
// 如果章节有子项,需要查询所有子项的数据
if (section.children && section.children.length > 0) {
console.log(`[重载章节数据] 开始重载有子项的章节:${section.number}${section.name}`);
console.log(
`[重载章节数据] 开始重载有子项的章节:${section.number}${section.name}`
);
// 收集所有子项的 formCommit
const childFormCommits = section.children.map(child => child.formCommit).filter(fc => fc);
const childFormCommits = section.children
.map((child) => child.formCommit)
.filter((fc) => fc);
console.log(`[重载章节数据] 子项 formCommits:`, childFormCommits);
// 并行查询所有子项的数据
@@ -1165,16 +1305,25 @@ const reloadSectionData = async (sectionIndex: number) => {
// 解析并填充每个子项的数据
let loadedCount = 0;
results.forEach(result => {
results.forEach((result) => {
if (result.data) {
const reportContent = JSON.parse(result.data.reportContent || '{}');
if (reportContent.sections && Array.isArray(reportContent.sections)) {
if (
reportContent.sections &&
Array.isArray(reportContent.sections)
) {
const sectionData = reportContent.sections[0];
if (sectionData && sectionData.records && Array.isArray(sectionData.records)) {
if (
sectionData &&
sectionData.records &&
Array.isArray(sectionData.records)
) {
// 找到对应的子项并填充数据
sectionData.records.forEach((rec: any) => {
const childIndex = section.children.findIndex(child => child.formCommit === rec.formCommit);
const childIndex = section.children.findIndex(
(child) => child.formCommit === rec.formCommit
);
if (childIndex >= 0) {
section.children[childIndex].content = rec.content || '';
loadedCount++;
@@ -1185,18 +1334,24 @@ const reloadSectionData = async (sectionIndex: number) => {
}
});
console.log(`[重载章节数据] 已加载 ${loadedCount}/${section.children.length} 个小节的数据`);
console.log(
`[重载章节数据] 已加载 ${loadedCount}/${section.children.length} 个小节的数据`
);
if (loadedCount === 0) {
message.info('该章节暂无保存的数据');
} else {
message.success(`${section.number}${section.name} 数据已重新加载(共 ${loadedCount}/${section.children.length} 个小节)`);
message.success(
`${section.number}${section.name} 数据已重新加载(共 ${loadedCount}/${section.children.length} 个小节)`
);
}
} else {
// 无子项,直接加载主章节
const formCommitToUse = section.formCommit || 1;
console.log(`[重载章节数据] 开始重载主章节sectionIndex: ${sectionIndex}, formCommit: ${formCommitToUse}`);
console.log(
`[重载章节数据] 开始重载主章节sectionIndex: ${sectionIndex}, formCommit: ${formCommitToUse}`
);
const res: any = await queryAuditReport({
projectId: form.id,
@@ -1210,8 +1365,14 @@ const reloadSectionData = async (sectionIndex: number) => {
const sectionData = reportContent.sections[0];
if (sectionData) {
section.content = sectionData.content || '';
console.log(`[重载章节数据] 已加载主章节内容,长度:${section.content?.length || 0}`);
message.success(`${section.number}${section.name} 数据已重新加载`);
console.log(
`[重载章节数据] 已加载主章节内容,长度:${
section.content?.length || 0
}`
);
message.success(
`${section.number}${section.name} 数据已重新加载`
);
}
}
}
@@ -1228,7 +1389,10 @@ const reloadSectionData = async (sectionIndex: number) => {
/**
* 重载单个小节的数据
*/
const reloadChildContent = async (sectionIndex: number, childIndex: number) => {
const reloadChildContent = async (
sectionIndex: number,
childIndex: number
) => {
if (!form.id) {
message.warning('无项目信息');
return;
@@ -1251,9 +1415,15 @@ const reloadChildContent = async (sectionIndex: number, childIndex: number) => {
if (reportContent.sections && Array.isArray(reportContent.sections)) {
const sectionData = reportContent.sections[0]; // 取第一个章节
if (sectionData && sectionData.records && Array.isArray(sectionData.records)) {
if (
sectionData &&
sectionData.records &&
Array.isArray(sectionData.records)
) {
// 找到对应的小节记录
const record = sectionData.records.find((r: any) => r.formCommit === child.formCommit);
const record = sectionData.records.find(
(r: any) => r.formCommit === child.formCommit
);
if (record) {
child.content = record.content || '';
message.success(`${child.name} 数据已重新加载`);
@@ -1276,7 +1446,7 @@ const buildExportData = () => {
from00: form.code,
from10: navigationItems.value[0].content,
from20: navigationItems.value[1].content,
from30: navigationItems.value[2].content,
from30: navigationItems.value[2].content
};
// 被审计单位基本情况
@@ -1346,9 +1516,9 @@ const generateContent = async (sectionIndex: number, childIndex?: number) => {
if (childIndex === undefined && !section.formCommit && section.children) {
section.generating = true;
try {
await Promise.all(section.children.map((_, i) =>
generateContent(sectionIndex, i)
));
await Promise.all(
section.children.map((_, i) => generateContent(sectionIndex, i))
);
} finally {
section.generating = false;
}
@@ -1381,7 +1551,19 @@ const generateContent = async (sectionIndex: number, childIndex?: number) => {
formCommit: formCommit,
chapterTitle: chapterTitle
});
item.content = result;
// const content = result;
item.content = await generateAuditReport({
kbId: form.kbId || '',
kbIds: combinedKbIds.value,
formCommit: formCommit,
history: result || '',
suggestion: item.suggestion || '',
// 新增:传递完整的上下文数据
...contextData
});
// item.content = auditReportRes;
// console.log('auditReportRes', auditReportRes);
} finally {
item.generating = false;
}
@@ -1402,7 +1584,8 @@ const handleScroll = () => {
const section = sections[i];
if (section) {
const sectionTop = section.getBoundingClientRect().top - containerTop;
if (sectionTop <= 100) { // 100px 的偏移量
if (sectionTop <= 100) {
// 100px 的偏移量
currentSection.value = i;
break;
}
@@ -1416,7 +1599,11 @@ const handleKeydown = (event: KeyboardEvent) => {
if (!props.visible) return;
// Ctrl/Cmd + 数字键 1-9 快速跳转
if ((event.ctrlKey || event.metaKey) && event.key >= '1' && event.key <= '9') {
if (
(event.ctrlKey || event.metaKey) &&
event.key >= '1' &&
event.key <= '9'
) {
event.preventDefault();
const index = parseInt(event.key) - 1;
if (index < navigationItems.value.length) {
@@ -1431,14 +1618,16 @@ const handleKeydown = (event: KeyboardEvent) => {
scrollToSection(prevIndex);
} else if (event.key === 'ArrowDown' && event.ctrlKey) {
event.preventDefault();
const nextIndex = Math.min(navigationItems.value.length - 1, currentSection.value + 1);
const nextIndex = Math.min(
navigationItems.value.length - 1,
currentSection.value + 1
);
scrollToSection(nextIndex);
}
};
/* 保存编辑 */
const save = () => {
};
const save = () => {};
// 组件挂载时添加滚动监听和键盘监听
onMounted(() => {
@@ -1469,8 +1658,12 @@ watch(
// 获取知识库并拼接 kbIds
if (props.data.libraryIds?.length > 0) {
try {
const result = await getPwlProjectLibraryByIds(props.data.libraryIds);
const kbIds = result.map(lib => lib.kbId).filter(kbId => kbId);
const result = await getPwlProjectLibraryByIds(
props.data.libraryIds
);
const kbIds = result
.map((lib) => lib.kbId)
.filter((kbId) => kbId);
if (form.kbId) {
kbIds.unshift(form.kbId);
}
@@ -1596,7 +1789,8 @@ export default {
border: 2px solid #ff4d4f !important;
border-radius: 20px !important;
&:hover, &:focus {
&:hover,
&:focus {
border-color: #ff7875 !important;
box-shadow: 0 0 8px rgba(255, 77, 79, 0.3);
}
@@ -1858,5 +2052,4 @@ export default {
right: 30px;
bottom: 30px;
}
</style>