Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
5e26754e
提交
5e26754e
authored
1月 23, 2026
作者:
朱亚刚
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
pdf写报(未完成)
上级
08966e42
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
519 行增加
和
184 行删除
+519
-184
index.vue
src/views/writtingAsstaint/index.vue
+508
-184
vite.config.js
vite.config.js
+11
-0
没有找到文件。
src/views/writtingAsstaint/index.vue
浏览文件 @
5e26754e
...
...
@@ -31,39 +31,24 @@
</div>
<div
class=
"writting-main"
>
<div
class=
"sider"
>
<div
class=
"sider-box
1
"
>
<div
class=
"sider-box
"
v-if=
"false
"
>
<div
class=
"header"
>
报文主题
</div>
<div
class=
"title-box"
>
<div
class=
"title"
>
主题名称
</div>
<el-input
style=
"width: 476px; height: 32px"
class=
"title-input"
placeholder=
"输入主题名称,如:大而美法案"
v-model=
"writtingTitle"
/>
<el-input
:disabled=
"true"
style=
"width: 476px; height: 32px"
class=
"title-input"
placeholder=
"输入主题名称,如:大而美法案"
v-model=
"writtingTitle"
/>
</div>
<div
class=
"description-box"
>
<div
class=
"title"
>
主题描述
</div>
<el-input
class=
"description-input"
type=
"textarea"
style=
"width: 476px"
:rows=
"8"
placeholder=
"输入报文主题描述,如:从科技领域方面分析大而美法案通过后对中国可能产生的影响"
v-model=
"descText"
/>
<el-input
:disabled=
"true"
class=
"description-input"
type=
"textarea"
style=
"width: 476px"
:rows=
"8"
placeholder=
"输入报文主题描述,如:从科技领域方面分析大而美法案通过后对中国可能产生的影响"
v-model=
"descText"
/>
</div>
</div>
<div
class=
"sider-box
2
"
>
<div
class=
"sider-box"
>
<div
class=
"header"
>
报文模板
</div>
<div
class=
"template-box"
>
<div
class=
"template"
:class=
"
{ tempActive: tempActiveIndex === index }"
v-for="(temp, index) in tempList"
:key="index"
@click="handleClickTemp(temp, index)"
>
<div
class=
"template"
:class=
"
{ tempActive: tempActiveIndex === index }"
v-for="(temp, index) in tempList" :key="index" @click="handleClickTemp(temp, index)">
<div
class=
"header"
>
<div
class=
"title"
>
{{
temp
.
title
}}
</div>
<div
class=
"icon"
>
...
...
@@ -79,14 +64,32 @@
</div>
</div>
</div>
</div>
<div
class=
"sider-box"
>
<div
class=
"header"
>
加载本地文件
</div>
<el-upload
action=
""
:auto-upload=
"false"
accept=
".pdf"
limit=
"1"
:on-exceed=
"handleExceed"
ref=
"upload"
:on-change=
"handleFileChange"
>
<el-button
class=
"sider-upload-btn"
type=
"primary"
>
<el-icon
class=
"sider-upload-btn-text"
>
<Upload
/>
</el-icon>
<span
class=
"sider-upload-btn-text"
>
上传文件
</span>
</el-button>
<template
#
tip
>
<div
class=
"sider-upload-btn-tip"
>
支持扩展名:.doc .docx .pdf
</div>
</
template
>
</el-upload>
</div>
<div
class=
"submit-btn"
@
click=
"getStreamChat"
>
<div
class=
"tips"
>
<div
class=
"tips-icon"
>
<img
src=
"./assets/images/tips-icon.png"
alt=
""
/>
</div>
<div
class=
"tips-text"
>
内容由AI生成,无法确保真实准确,仅供参考
</div>
</div>
</div>
<div
class=
"submit-btn"
@
click=
"getStreamChat"
>
<div
class=
"submit-icon"
>
<img
src=
"./assets/images/ai.png"
alt=
""
/>
</div>
...
...
@@ -95,10 +98,9 @@
</div>
<div
class=
"process-box"
v-if=
"isShowProcess"
>
<div
class=
"back"
@
click=
"handleBack"
>
{{
"< 返回"
}}
</div>
<div
class=
"process-main-box"
>
<!--
<div
class=
"analysis-box"
>
{{ "
<
返回"
}}
</
div
>
<div
class=
"process-main-box"
>
<!-- <div class="analysis-box">
<div class="analysis-header">
<div class="icon">
<img src="./assets/images/right-arrow.png" alt="" />
...
...
@@ -111,55 +113,50 @@
}}
</div>
</div> -->
<div
class=
"steps-box"
>
<div
class=
"steps-header"
>
<div
class=
"icon"
>
<img
src=
"./assets/images/right-arrow.png"
alt=
""
/>
<div
class=
"steps-box"
>
<div
class=
"steps-header"
>
<div
class=
"icon"
>
<img
src=
"./assets/images/right-arrow.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{ "执行步骤:" }}
</div>
</div>
<div
class=
"steps-content"
ref=
"scrollProcessContainer"
v-html=
"renderedProcess"
></div>
</div>
<div
class=
"text"
>
{{
"执行步骤:"
}}
</div>
</div>
<div
class=
"steps-content"
ref=
"scrollProcessContainer"
v-html=
"renderedProcess"
></div>
</div>
<!--
<div
class=
"doing-box"
>
<!-- <div class="doing-box">
{{ "正在执行步骤1/7:根据制图主题生成关键词" }}
</div> -->
<div
class=
"tool-box"
>
<div
class=
"tool-header"
>
{{
"工具调用"
}}
</div>
<div
class=
"tool-main"
>
当前智能体工具:
{{
curAgentTool
?
curAgentTool
:
"无"
}}
</div>
</div>
</div>
<div
class=
"process-tips-box"
>
<div
class=
"tips-icon"
>
<img
src=
"./assets/images/tips-icon.png"
alt=
""
/>
</div>
<div
class=
"tips-text"
>
内容由AI生成,无法确保真实准确,仅供参考
</div>
<div
class=
"tool-box"
>
<div
class=
"tool-header"
>
{{ "工具调用" }}
</div>
<div
class=
"tool-main"
>
当前智能体工具:{{ curAgentTool ? curAgentTool : "无" }}
</div>
</div>
</div>
<div
class=
"process-tips-box"
>
<div
class=
"tips-icon"
>
<img
src=
"./assets/images/tips-icon.png"
alt=
""
/>
</div>
<div
class=
"tips-text"
>
内容由AI生成,无法确保真实准确,仅供参考
</div>
</div>
<div
class=
"process-footer-box"
>
<div
class=
"footer-left"
>
{{ isGenerating ? "报文生成中..." : "报文已生成" }}
</div>
<div
class=
"footer-right"
>
<div
class=
"icon"
></div>
<div
class=
"text"
@
click=
"handleGenerate"
>
{{ "停止" }}
</div>
</div>
</div>
</div>
<div
class=
"process-footer-box"
>
<div
class=
"footer-left"
>
{{
isGenerating
?
"报文生成中..."
:
"报文已生成"
}}
</div>
<div
class=
"footer-right"
>
<div
class=
"icon"
></div>
<div
class=
"text"
@
click=
"handleGenerate"
>
{{
"停止"
}}
</div>
<div
class=
"main-box"
>
<div
v-if=
"isEditMode"
class=
"edit-panel"
>
<v-md-editor
v-model=
"reportContent"
height=
"calc(100% - 40px)"
:disabled-menus=
"[]"
@
upload-image=
"handleUploadImage"
@
save=
"handleSave"
left-toolbar=
"undo redo clear | h bold italic strikethrough quote | ul ol table hr | link image code | save"
right-toolbar=
"preview toc sync-scroll fullscreen"
/>
</div>
<div
v-else
class=
"content-box"
ref=
"scrollContainer"
v-html=
"renderedContent"
></div>
</div>
</div>
<div
class=
"main-box"
>
<div
v-if=
"isEditMode"
class=
"edit-panel"
>
<v-md-editor
v-model=
"reportContent"
height=
"calc(100% - 40px)"
:disabled-menus=
"[]"
@
upload-image=
"handleUploadImage"
@
save=
"handleSave"
left-toolbar=
"undo redo clear | h bold italic strikethrough quote | ul ol table hr | link image code | save"
right-toolbar=
"preview toc sync-scroll fullscreen"
/>
</div>
<div
v-else
class=
"content-box"
ref=
"scrollContainer"
v-html=
"renderedContent"
></div>
</div>
</div>
</div>
</template>
<
script
setup
>
...
...
@@ -175,6 +172,7 @@ import "@kangc/v-md-editor/lib/theme/style/vuepress.css";
// 引入 Prism 相关依赖
import
Prism
from
"prismjs"
;
import
{
ElButton
,
ElIcon
,
ElInput
,
ElMessage
,
ElUpload
,
genFileId
}
from
"element-plus"
;
VMdEditor
.
use
(
vuepressTheme
,
{
Prism
...
...
@@ -182,6 +180,28 @@ VMdEditor.use(vuepressTheme, {
const
isGenerating
=
ref
(
false
);
const
isShowProcess
=
ref
(
false
);
const
uploadFileList
=
ref
([])
const
upload
=
ref
()
//新上传文件替换
const
handleExceed
=
(
files
)
=>
{
if
(
upload
.
value
)
{
upload
.
value
.
clearFiles
()
const
file
=
files
[
0
]
file
.
uid
=
genFileId
()
upload
.
value
.
handleStart
(
file
)
}
}
const
handleFileChange
=
(
file
,
files
)
=>
{
// 只保留最后选中的1个文件(覆盖原有文件)
if
(
files
.
length
>
1
)
{
uploadFileList
.
value
=
[
file
];
}
else
{
uploadFileList
.
value
=
files
;
}
};
const
handleBack
=
()
=>
{
isShowProcess
.
value
=
false
;
...
...
@@ -219,7 +239,6 @@ const steps = [
];
const
isEditMode
=
ref
(
false
);
const
handleSwitchMode
=
()
=>
{
isEditMode
.
value
=
!
isEditMode
.
value
;
if
(
!
isEditMode
.
value
)
{
...
...
@@ -269,59 +288,77 @@ const handleGenerate = () => {
const
curAgentTool
=
ref
(
"报告整体优化工具"
);
const
getStreamChat
=
async
(
search
,
inputValue
)
=>
{
const
params
=
{
query
:
writtingTitle
.
value
,
// "输出一篇报文"
desc
:
descText
.
value
,
topic
:
curTempTitle
.
value
// 政令、智库、法案、清单
};
if
(
uploadFileList
.
value
.
length
>
0
)
{
const
rawFile
=
uploadFileList
.
value
[
0
].
raw
;
if
(
!
rawFile
)
{
ElMessage
.
error
(
'文件解析失败,请重新选择'
);
return
;
}
callSseApi
(
rawFile
)
}
else
{
abortController
.
value
=
new
AbortController
();
const
params
=
{
query
:
writtingTitle
.
value
,
// "输出一篇报文"
desc
:
descText
.
value
,
topic
:
curTempTitle
.
value
// 政令、智库、法案、清单
};
abortController
.
value
=
new
AbortController
();
fetchEventSource
(
"/sseWrite/api/v1/workflow/invoke"
,
{
method
:
"POST"
,
headers
:
{
"Content-Type"
:
"application/json"
},
body
:
JSON
.
stringify
(
params
),
signal
:
abortController
.
value
.
signal
,
openWhenHidden
:
true
,
async
onopen
(
res
)
{
console
.
log
(
"流式回答开始"
,
res
);
isGenerating
.
value
=
true
;
isShowProcess
.
value
=
true
;
},
async
onmessage
(
res
)
{
let
msgData
=
JSON
.
parse
(
res
.
data
);
console
.
log
(
"resss"
,
msgData
.
data
);
console
.
log
(
"msgData"
,
msgData
);
let
str
=
msgData
.
data
;
if
(
msgData
.
event_type
===
"stream_agent_out"
)
{
if
(
str
!==
"[DONE]"
)
{
reportContent
.
value
+=
str
;
if
(
reportContent
.
value
.
includes
(
"./out/img"
))
{
reportContent
.
value
=
reportContent
.
value
.
replaceAll
(
"./out/img"
,
"http://8.140.26.4:10017/out/img"
);
// console.log(111, reportContent.value);
fetchEventSource
(
"/sseWrite/api/v1/workflow/invoke"
,
{
method
:
"POST"
,
headers
:
{
"Content-Type"
:
"application/json"
},
body
:
JSON
.
stringify
(
params
),
signal
:
abortController
.
value
.
signal
,
openWhenHidden
:
true
,
async
onopen
(
res
)
{
console
.
log
(
"流式回答开始"
,
res
);
isGenerating
.
value
=
true
;
isShowProcess
.
value
=
true
;
},
async
onmessage
(
res
)
{
let
msgData
=
JSON
.
parse
(
res
.
data
);
console
.
log
(
"resss"
,
msgData
.
data
);
console
.
log
(
"msgData"
,
msgData
);
let
str
=
msgData
.
data
;
if
(
msgData
.
event_type
===
"stream_agent_out"
)
{
if
(
str
!==
"[DONE]"
)
{
reportContent
.
value
+=
str
;
if
(
reportContent
.
value
.
includes
(
"./out/img"
))
{
reportContent
.
value
=
reportContent
.
value
.
replaceAll
(
"./out/img"
,
"http://8.140.26.4:10017/out/img"
);
// console.log(111, reportContent.value);
}
updateContent
(
reportContent
.
value
,
scrollContainer
.
value
);
}
else
{
isGenerating
.
value
=
false
;
ElMessage
.
success
(
"报文生成结束"
);
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
}
updateContent
(
reportContent
.
value
,
scrollContainer
.
value
);
}
else
{
isGenerating
.
value
=
false
;
}
else
if
(
msgData
.
event_type
===
"workflow_complete"
)
{
ElMessage
.
success
(
"报文生成结束"
);
isGenerating
.
value
=
false
;
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
}
else
if
(
msgData
.
event_type
.
toLowerCase
().
includes
(
"error"
))
{
}
else
{
processContent
.
value
+=
str
;
curAgentTool
.
value
=
msgData
.
tool
;
updateProcess
(
processContent
.
value
,
scrollProcessContainer
.
value
);
}
}
else
if
(
msgData
.
event_type
===
"workflow_complete"
)
{
ElMessage
.
success
(
"报文生成结束"
);
isGenerating
.
value
=
false
;
},
onerror
(
error
)
{
ElMessage
({
message
:
"写报生成报错!"
,
type
:
"warning"
});
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
}
else
if
(
msgData
.
event_type
.
toLowerCase
().
includes
(
"error"
))
{
}
else
{
processContent
.
value
+=
str
;
curAgentTool
.
value
=
msgData
.
tool
;
updateProcess
(
processContent
.
value
,
scrollProcessContainer
.
value
);
throw
new
Error
(
error
);
}
},
onerror
(
error
)
{
}).
catch
(
error
=>
{
ElMessage
({
message
:
"写报生成报错!"
,
type
:
"warning"
...
...
@@ -329,18 +366,205 @@ const getStreamChat = async (search, inputValue) => {
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
throw
new
Error
(
error
);
}
}).
catch
(
error
=>
{
ElMessage
({
message
:
"写报生成报错!"
,
type
:
"warning"
});
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
throw
new
Error
(
error
);
}
};
const
callSseApi
=
async
(
selectedFile
)
=>
{
abortController
.
value
=
new
AbortController
();
try
{
const
formData
=
new
FormData
();
formData
.
append
(
'pdf'
,
selectedFile
);
const
response
=
await
fetch
(
'/pdfSse/api/v1/order/pdf/extract/report/sse'
,
{
method
:
'POST'
,
body
:
formData
,
signal
:
abortController
.
value
.
signal
,
// 绑定中断信号
});
if
(
!
response
.
ok
)
{
throw
new
Error
(
`请求失败:
${
response
.
status
}
${
response
.
statusText
}
`
);
}
console
.
log
(
"流式回答开始"
,
res
);
isGenerating
.
value
=
true
;
isShowProcess
.
value
=
true
;
// 读取流式响应
const
reader
=
response
.
body
.
getReader
();
const
decoder
=
new
TextDecoder
();
let
buffer
=
''
;
// 消息缓冲区
// 定义SSE消息回调(和原生onmessage用法一致)
const
onmessage
=
(
res
)
=>
{
const
{
type
,
data
}
=
res
if
(
type
===
"progress"
)
{
processContent
.
value
+=
data
.
message
;
updateProcess
(
processContent
.
value
,
scrollProcessContainer
.
value
);
}
};
// 错误回调
const
onerror
=
(
error
)
=>
{
};
// 连接关闭回调
const
onclose
=
()
=>
{
};
// 循环读取并解析SSE消息(核心修复换行符兼容)
while
(
true
)
{
try
{
const
{
done
,
value
}
=
await
reader
.
read
();
// 连接正常关闭
if
(
done
)
{
onclose
();
break
;
}
// 1. 解码二进制流为文本,追加到缓冲区
buffer
+=
decoder
.
decode
(
value
,
{
stream
:
true
});
// 2. 分割完整消息(兼容 \r\n\r\n 和 \n\n 换行符)
const
fullMessages
=
buffer
.
split
(
/
(\r\n
|
\n){2}
/
);
// 过滤空字符串,只保留有效消息
const
validMessages
=
fullMessages
.
filter
(
msg
=>
msg
.
trim
()
!==
''
);
// 3. 最后一条可能是不完整消息,放回缓冲区
let
remainingBuffer
=
''
;
if
(
validMessages
.
length
>
0
)
{
remainingBuffer
=
validMessages
.
pop
()
||
''
;
}
// 4. 逐条解析有效消息
validMessages
.
forEach
(
fullMsg
=>
{
const
sseMsg
=
parseSSEMessage
(
fullMsg
);
// 过滤心跳/注释消息(以:开头的消息)
if
(
sseMsg
.
isComment
)
return
;
// 触发onmessage回调
if
(
sseMsg
.
data
)
{
debugger
onmessage
({
type
:
sseMsg
.
event
||
'message'
,
data
:
JSON
.
parse
(
sseMsg
.
data
),
// 解析为JSON对象
timeStamp
:
Date
.
now
()
});
}
});
// 重置缓冲区(只保留不完整的消息)
buffer
=
remainingBuffer
;
}
catch
(
error
)
{
// 排除主动中断的情况
if
(
error
.
name
!==
'AbortError'
)
{
onerror
(
error
);
}
break
;
}
}
}
catch
(
error
)
{
// 捕获请求级别的错误
if
(
error
.
name
!==
'AbortError'
)
{
ElMessage
.
error
(
`请求异常:
${
error
.
message
}
`
);
isLoading
.
value
=
false
;
}
}
};
// 工具函数:严格按SSE协议解析单条消息
const
parseSSEMessage
=
(
rawMsg
)
=>
{
// 兼容 \r\n 和 \n 分割行
const
lines
=
rawMsg
.
split
(
/
\r\n
|
\n
/
);
const
result
=
{
event
:
'progress'
,
// 默认事件类型
data
:
''
,
// 消息数据
isComment
:
false
// 是否是注释/心跳消息
};
lines
.
forEach
(
line
=>
{
line
=
line
.
trimEnd
();
// 去掉行尾空白符
// 注释行(以:开头):心跳消息,标记为注释
if
(
line
.
startsWith
(
':'
))
{
result
.
isComment
=
true
;
return
;
}
// 解析event行(event: xxx)
if
(
line
.
startsWith
(
'event:'
))
{
result
.
event
=
line
.
slice
(
6
).
trim
();
return
;
}
// 解析data行(data: xxx),支持多行data拼接
if
(
line
.
startsWith
(
'data:'
))
{
result
.
data
+=
line
.
slice
(
5
).
trim
();
return
;
}
// 空行忽略
if
(
line
===
''
)
return
;
});
return
result
;
};
const
ele
=
()
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
// 转换FormData为Blob(适配SSE的POST请求体)
const
formDataBlob
=
new
Blob
([
// 模拟multipart/form-data的边界符(简化版,实际可复用浏览器自动生成的)
...
Array
.
from
(
formData
.
entries
()).
map
(([
key
,
value
])
=>
{
return
`--boundary\r\nContent-Disposition: form-data; name="
${
key
}
"
${
value
instanceof
File
?
`; filename="
${
value
.
name
}
"\r\nContent-Type:
${
value
.
type
}
`
:
''
}
\r\n\r\n
${
value
instanceof
File
?
value
:
value
}
\r\n`
;
}),
'--boundary--
\
r
\
n'
]);
fetchEventSource
(
'/pdfSse/api/v1/order/pdf/extract/report/sse'
,
{
method
:
'POST'
,
headers
:
{
// 关键:设置multipart/form-data头,包含边界符
'Content-Type'
:
`multipart/form-data; boundary=boundary`
,
},
// 注意:fetchEventSource的body仅支持字符串/ArrayBuffer/Blob,这里传FormData转换后的Blob
body
:
formDataBlob
,
signal
:
abortController
.
value
.
signal
,
openWhenHidden
:
true
,
// SSE连接开启
async
onopen
(
res
)
{
console
.
log
(
"流式回答开始"
,
res
);
isGenerating
.
value
=
true
;
isShowProcess
.
value
=
true
;
},
async
onmessage
(
res
)
{
debugger
const
{
event
,
data
}
=
res
let
jsonData
=
JSON
.
parse
(
data
);
if
(
event
===
"progress"
)
{
processContent
.
value
+=
jsonData
.
message
;
updateProcess
(
processContent
.
value
,
scrollProcessContainer
.
value
);
}
},
onerror
(
error
)
{
ElMessage
({
message
:
"写报生成报错!"
,
type
:
"warning"
});
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
throw
new
Error
(
error
);
}
}).
catch
((
error
)
=>
{
reject
(
error
);
isProcessing
.
value
=
false
;
});
});
}
const
writtingTitle
=
ref
(
""
);
const
descText
=
ref
(
""
);
const
tabList
=
ref
([
...
...
@@ -381,7 +605,7 @@ const tempActiveIndex = ref(0);
const
handleClickTemp
=
(
item
,
index
)
=>
{
tempActiveIndex
.
value
=
index
;
curTempTitle
.
value
=
item
.
title
;
};
// 导出
...
...
@@ -395,7 +619,7 @@ const exportContent = () => {
URL
.
revokeObjectURL
(
url
);
};
onMounted
(()
=>
{});
onMounted
(()
=>
{
});
onUnmounted
(()
=>
{
if
(
abortController
.
value
)
{
...
...
@@ -408,6 +632,7 @@ onUnmounted(() => {
.writting-wrapper
{
width
:
100%
;
height
:
100%
;
.writting-header
{
height
:
60px
;
box-sizing
:
border-box
;
...
...
@@ -417,6 +642,7 @@ onUnmounted(() => {
background
:
rgba
(
255
,
255
,
255
,
1
);
display
:
flex
;
position
:
relative
;
.tab-box
{
display
:
flex
;
margin-left
:
130px
;
...
...
@@ -424,6 +650,7 @@ onUnmounted(() => {
width
:
260px
;
height
:
46px
;
justify-content
:
space-between
;
.tab
{
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
...
...
@@ -431,6 +658,7 @@ onUnmounted(() => {
font-weight
:
400
;
line-height
:
30px
;
}
.tabActive
{
color
:
rgba
(
5
,
95
,
194
,
1
);
font-family
:
Microsoft
YaHei
;
...
...
@@ -440,12 +668,14 @@ onUnmounted(() => {
border-bottom
:
4px
solid
rgba
(
5
,
95
,
194
,
1
);
}
}
.btn-box
{
position
:
absolute
;
top
:
12px
;
right
:
39px
;
display
:
flex
;
gap
:
12px
;
.btn
{
display
:
flex
;
justify-content
:
center
;
...
...
@@ -458,14 +688,17 @@ onUnmounted(() => {
border-radius
:
6px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
cursor
:
pointer
;
.icon
{
width
:
16px
;
height
:
16px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
32px
;
height
:
24px
;
...
...
@@ -475,19 +708,23 @@ onUnmounted(() => {
font-weight
:
400
;
line-height
:
24px
;
}
.text1
{
color
:
#fff
;
}
}
.btn1
{
background
:
rgba
(
5
,
95
,
194
,
1
);
}
}
}
.writting-main
{
display
:
flex
;
height
:
calc
(
100%
-
60px
);
position
:
relative
;
.process-box
{
position
:
absolute
;
left
:
0
;
...
...
@@ -496,6 +733,7 @@ onUnmounted(() => {
height
:
100%
;
z-index
:
9999
;
background
:
#fff
;
.back
{
margin-top
:
21px
;
height
:
24px
;
...
...
@@ -508,24 +746,29 @@ onUnmounted(() => {
line-height
:
24px
;
cursor
:
pointer
;
}
.process-main-box
{
margin-top
:
20px
;
margin-left
:
22px
;
width
:
476px
;
height
:
900px
;
// background: orange;
.analysis-box
{
.analysis-header
{
display
:
flex
;
.icon
{
margin-top
:
5px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
height
:
30px
;
line-height
:
30px
;
...
...
@@ -536,6 +779,7 @@ onUnmounted(() => {
margin-left
:
5px
;
}
}
.analysis-content
{
height
:
90px
;
line-height
:
30px
;
...
...
@@ -546,19 +790,24 @@ onUnmounted(() => {
text-indent
:
32px
;
}
}
.steps-box
{
margin-top
:
20px
;
.steps-header
{
display
:
flex
;
.icon
{
margin-top
:
5px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
height
:
30px
;
line-height
:
30px
;
...
...
@@ -569,6 +818,7 @@ onUnmounted(() => {
margin-left
:
5px
;
}
}
.steps-content
{
height
:
560px
;
width
:
100%
;
...
...
@@ -597,6 +847,7 @@ onUnmounted(() => {
// }
}
}
.doing-box
{
height
:
40px
;
line-height
:
40px
;
...
...
@@ -606,18 +857,21 @@ onUnmounted(() => {
font-weight
:
400
;
margin-left
:
20px
;
}
.tool-box
{
width
:
440px
;
height
:
160px
;
margin
:
10px
auto
;
background
:
#f6f9fe
;
border-radius
:
10px
;
.tool-header
{
height
:
30px
;
line-height
:
30px
;
margin-left
:
20px
;
color
:
var
(
--
color-main-active
);
}
.tool-main
{
height
:
110px
;
width
:
400px
;
...
...
@@ -631,21 +885,25 @@ onUnmounted(() => {
}
}
}
.process-tips-box
{
position
:
absolute
;
left
:
22px
;
bottom
:
81px
;
height
:
22px
;
display
:
flex
;
.tips-icon
{
width
:
14px
;
height
:
16px
;
margin-top
:
3px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.tips-text
{
margin-left
:
8px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
...
...
@@ -655,12 +913,14 @@ onUnmounted(() => {
line-height
:
22px
;
}
}
.process-footer-box
{
height
:
36px
;
display
:
flex
;
position
:
absolute
;
left
:
22px
;
bottom
:
29px
;
.footer-left
{
width
:
348px
;
height
:
36px
;
...
...
@@ -673,6 +933,7 @@ onUnmounted(() => {
text-align
:
center
;
line-height
:
36px
;
}
.footer-right
{
margin-left
:
8px
;
display
:
flex
;
...
...
@@ -686,12 +947,14 @@ onUnmounted(() => {
align-items
:
center
;
gap
:
8px
;
cursor
:
pointer
;
.icon
{
width
:
8px
;
height
:
8px
;
border-radius
:
2px
;
background
:
var
(
--
color-main-active
);
}
.text
{
color
:
var
(
--
color-main-active
);
font-family
:
Microsoft
YaHei
;
...
...
@@ -702,6 +965,7 @@ onUnmounted(() => {
}
}
}
.sider
{
width
:
520px
;
box-sizing
:
border-box
;
...
...
@@ -709,62 +973,28 @@ onUnmounted(() => {
border-top
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
.sider-box1
{
margin-top
:
21px
;
margin-left
:
22px
;
.header
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
24px
;
}
.title-box
{
margin-top
:
15px
;
.title
{
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
}
.title-input
{
margin-top
:
15px
;
}
}
.description-box
{
margin-top
:
24px
;
.title
{
height
:
24px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
}
.description-input
{
margin-top
:
12px
;
height
:
200px
;
}
}
}
.sider-box2
{
margin-top
:
24px
;
margin-left
:
22px
;
padding
:
21px
21px
;
display
:
flex
;
flex-direction
:
column
;
gap
:
23px
;
.sider-box
{
.header
{
height
:
24px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
24px
;
}
.template-box
{
margin-top
:
19px
;
height
:
260px
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
16px
;
.template
{
width
:
230px
;
height
:
120px
;
...
...
@@ -773,6 +1003,7 @@ onUnmounted(() => {
border-radius
:
4px
;
position
:
relative
;
cursor
:
pointer
;
.active-icon
{
width
:
24px
;
height
:
24px
;
...
...
@@ -780,11 +1011,13 @@ onUnmounted(() => {
top
:
0
;
right
:
0
;
z-index
:
99
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.selected-icon
{
width
:
8px
;
height
:
6px
;
...
...
@@ -792,15 +1025,18 @@ onUnmounted(() => {
top
:
-4px
;
right
:
3px
;
z-index
:
100
;
img
{
width
:
8px
;
height
:
6px
;
}
}
.header
{
display
:
flex
;
justify-content
:
space-between
;
height
:
50px
;
.title
{
height
:
24px
;
// color: rgba(59, 65, 75, 1);
...
...
@@ -812,6 +1048,7 @@ onUnmounted(() => {
margin-left
:
15px
;
margin-top
:
16px
;
}
.icon
{
margin-top
:
15px
;
margin-right
:
16px
;
...
...
@@ -819,6 +1056,7 @@ onUnmounted(() => {
height
:
30px
;
border-radius
:
15px
;
background
:
rgba
(
231
,
243
,
255
,
1
);
img
{
width
:
17px
;
height
:
14px
;
...
...
@@ -827,6 +1065,7 @@ onUnmounted(() => {
}
}
}
.content
{
margin
:
0
auto
;
width
:
200px
;
...
...
@@ -839,24 +1078,117 @@ onUnmounted(() => {
line-height
:
24px
;
}
}
.tempActive
{
border
:
1px
solid
rgba
(
5
,
95
,
194
,
1
);
background
:
rgba
(
246
,
250
,
255
,
1
);
}
}
.tips
{
.title-box
{
margin-top
:
15px
;
.title
{
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
}
.title-input
{
margin-top
:
15px
;
}
}
.description-box
{
margin-top
:
24px
;
.title
{
height
:
24px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
}
.description-input
{
margin-top
:
12px
;
height
:
200px
;
}
}
.sider-upload-btn
{
width
:
476px
;
height
:
36px
;
box-sizing
:
border-box
;
border
:
1px
dashed
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
6px
;
background
:
rgba
(
247
,
248
,
249
,
1
);
margin-top
:
19px
;
}
.sider-upload-btn-text
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-style
:
Regular
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
22px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
.sider-upload-btn-tip
{
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-style
:
Regular
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
22px
;
letter-spacing
:
0px
;
text-align
:
left
;
margin-top
:
8px
;
}
}
.submit-btn
{
position
:
absolute
;
left
:
22px
;
bottom
:
13px
;
width
:
476px
;
height
:
36px
;
border-radius
:
4px
;
background
:
rgba
(
5
,
95
,
194
,
1
);
display
:
flex
;
justify-content
:
center
;
cursor
:
pointer
;
&
:hover
{
background
:
rgba
(
5
,
95
,
194
,
0
.8
);
}
.tips
{
height
:
22px
;
display
:
flex
;
position
:
absolute
;
top
:
-30px
;
left
:
0px
;
.tips-icon
{
width
:
14px
;
height
:
16px
;
margin-top
:
3px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.tips-text
{
margin-left
:
8px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
...
...
@@ -866,31 +1198,19 @@ onUnmounted(() => {
line-height
:
22px
;
}
}
}
.submit-btn
{
position
:
absolute
;
left
:
22px
;
bottom
:
13px
;
width
:
476px
;
height
:
36px
;
border-radius
:
4px
;
background
:
rgba
(
5
,
95
,
194
,
1
);
display
:
flex
;
justify-content
:
center
;
cursor
:
pointer
;
&
:hover
{
background
:
rgba
(
5
,
95
,
194
,
0
.8
);
}
.submit-icon
{
/* AI-logo */
width
:
21px
;
height
:
15px
;
margin-top
:
10px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.submit-text
{
height
:
24px
;
margin-top
:
5px
;
...
...
@@ -903,14 +1223,17 @@ onUnmounted(() => {
}
}
}
.main-box
{
flex
:
1
;
background
:
#f7f8f9
;
.edit-panel
{
width
:
calc
(
100%
-
100px
);
height
:
calc
(
100%
-
40px
);
margin
:
20px
50px
;
}
.content-box
{
width
:
calc
(
100%
-
100px
);
height
:
calc
(
100%
-
40px
);
...
...
@@ -924,7 +1247,8 @@ onUnmounted(() => {
line-height
:
1
.7
;
// font-size: 20px;
font-size
:
16px
;
img
{
img
{
width
:
300px
;
height
:
auto
;
}
...
...
vite.config.js
浏览文件 @
5e26754e
...
...
@@ -80,6 +80,17 @@ export default defineConfig({
target
:
'http://8.140.26.4:15000/'
,
changeOrigin
:
true
,
rewrite
:
(
path
)
=>
path
.
replace
(
/^
\/
temporarySearch/
,
''
)
},
'/pdfSse'
:
{
target
:
'http://8.140.26.4:10020/'
,
changeOrigin
:
true
,
rewrite
:
(
path
)
=>
path
.
replace
(
/^
\/
pdfSse/
,
''
),
configure
:
(
proxy
)
=>
{
proxy
.
on
(
'proxyReq'
,
(
proxyReq
)
=>
{
proxyReq
.
setHeader
(
'Connection'
,
'keep-alive'
);
proxyReq
.
setHeader
(
'Cache-Control'
,
'no-cache'
);
});
}
}
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论