Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
bf04ed1e
提交
bf04ed1e
authored
1月 28, 2026
作者:
coderBryanFu
浏览文件
操作
浏览文件
下载
差异文件
update
上级
afe87dfb
11e49b19
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
1007 行增加
和
760 行删除
+1007
-760
index.vue
src/views/bill/billLayout/index.vue
+57
-52
index.vue
src/views/decree/decreeLayout/index.vue
+24
-8
btn-icon3.png
...ews/exportControl/v2.0SingleSanction/assets/btn-icon3.png
+0
-0
index.vue
src/views/exportControl/v2.0SingleSanction/index.vue
+308
-268
index.vue
src/views/thinkTank/ReportDetail/index.vue
+13
-2
index.vue
src/views/writtingAsstaint/index.vue
+605
-430
没有找到文件。
src/views/bill/billLayout/index.vue
浏览文件 @
bf04ed1e
...
...
@@ -3,63 +3,60 @@
<!-- 导航菜单 -->
<div
class=
"layout-main"
>
<div
class=
"header-main"
>
<div
class=
"layout-main-header"
>
<div
class=
"layout-main-header-left-box"
>
<div
class=
"left-box-top"
>
<div
class=
"icon"
>
<img
:src=
"billInfoGlobal.imageUrl || USALogo"
alt=
""
/>
</div>
<div
class=
"info"
>
<div
class=
"info-box1"
>
{{
billInfoGlobal
.
billName
}}
</div>
<div
class=
"info-box2"
>
{{
billInfoGlobal
.
description
}}
{{
billInfoGlobal
.
billNameEn
}}
</div>
</div>
</div>
<div
class=
"left-box-bottom"
>
<div
class=
"left-box-bottom-item"
:class=
"
{ leftBoxBottomItemActive: activeTitle === item.name }"
v-for="(item, index) in mainHeaderBtnList"
:key="index"
@click="handleClickMainHeaderBtn(item)"
>
<div
class=
"layout-main-header-left-box"
>
<div
class=
"left-box-top"
>
<div
class=
"icon"
>
<img
v-if=
"activeTitle === item.name"
:src=
"item.activeIcon"
alt=
""
/>
<img
v-else
:src=
"item.icon"
alt=
""
/>
<img
:src=
"billInfoGlobal.imageUrl || USALogo"
alt=
""
/>
</div>
<div
class=
"name"
:class=
"
{ nameActive: activeTitle === item.name }">
{{
item
.
name
}}
<div
class=
"info"
>
<div
class=
"info-box1"
>
{{
billInfoGlobal
.
billName
}}
</div>
<div
class=
"info-box2"
>
{{
billInfoGlobal
.
description
}}
{{
billInfoGlobal
.
billNameEn
}}
</div>
</div>
</div>
</div>
</div>
<div
class=
"layout-main-header-right-box"
>
<div
class=
"right-box-top"
>
<div
class=
"time"
>
{{
billInfoGlobal
.
introductionDate
}}
</div>
<div
class=
"name"
>
{{
billInfoGlobal
.
tarName
}}
</div>
</div>
<div
class=
"right-box-bottom"
>
<div
class=
"btn1"
@
click=
"handleSwitchActiveName('法案原文')"
>
<div
class=
"icon"
>
<img
src=
"./assets/icons/btn-icon1.png"
alt=
""
/>
<div
class=
"left-box-bottom"
>
<div
class=
"left-box-bottom-item"
:class=
"
{ leftBoxBottomItemActive: activeTitle === item.name }"
v-for="(item, index) in mainHeaderBtnList"
:key="index"
@click="handleClickMainHeaderBtn(item)"
>
<div
class=
"icon"
>
<img
v-if=
"activeTitle === item.name"
:src=
"item.activeIcon"
alt=
""
/>
<img
v-else
:src=
"item.icon"
alt=
""
/>
</div>
<div
class=
"name"
:class=
"
{ nameActive: activeTitle === item.name }">
{{
item
.
name
}}
</div>
</div>
<div
class=
"text"
>
{{
"法案原文"
}}
</div>
</div>
<!--
<div
class=
"btn2"
>
</div>
<div
class=
"layout-main-header-right-box"
>
<div
class=
"right-box-top"
>
<div
class=
"time"
>
{{
billInfoGlobal
.
introductionDate
}}
</div>
<div
class=
"name"
>
{{
billInfoGlobal
.
tarName
}}
</div>
</div>
<div
class=
"right-box-bottom"
>
<div
class=
"btn1"
@
click=
"handleSwitchActiveName('法案原文')"
>
<div
class=
"icon"
>
<img
src=
"./assets/icons/btn-icon1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"法案原文"
}}
</div>
</div>
<!--
<div
class=
"btn2"
>
<div
class=
"icon"
>
<img
src=
"./assets/icons/btn-icon2.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"查看官网"
}}
</div>
</div>
-->
<div
class=
"btn3"
>
<div
class=
"icon"
>
<img
src=
"./assets/icons/btn-icon3.png"
alt=
""
/>
<div
class=
"btn3"
@
click=
"handleAnalysisClick"
>
<div
class=
"icon"
>
<img
src=
"./assets/icons/btn-icon3.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"分析报告"
}}
</div>
</div>
<div
class=
"text"
>
{{
"分析报告"
}}
</div>
</div>
<!--
<div
class=
"btn4"
>
<!--
<div
class=
"btn4"
>
<div
class=
"icon"
>
<img
src=
"./assets/icons/btn-icon4.png"
alt=
""
/>
</div>
...
...
@@ -68,11 +65,11 @@
<img
src=
"./assets/icons/btn-icon5.png"
alt=
""
/>
</div>
</div>
-->
</div>
</div>
</div>
</div>
</div>
<div
class=
"layout-main-center"
>
<router-view
/>
</div>
...
...
@@ -150,7 +147,6 @@ import icon4 from "./assets/icons/icon4.svg";
import
icon4Active
from
"./assets/icons/icon4_active.svg"
;
import
USALogo
from
"./assets/images/USA-logo.png"
;
// 法案原文
const
billFullText
=
ref
(
""
);
const
getBillFullTextFn
=
async
()
=>
{
...
...
@@ -213,7 +209,7 @@ const mainHeaderBtnList = ref([
activeIcon
:
icon2Active
,
name
:
"深度挖掘"
,
path
:
"/billLayout/deepDig"
}
,
}
// {
// icon: icon3,
// activeIcon: icon3Active,
...
...
@@ -241,6 +237,16 @@ const handleClickMainHeaderBtn = item => {
});
};
const
handleAnalysisClick
=
()
=>
{
router
.
push
({
path
:
"/writtingAsstaint"
,
query
:
{
topic
:
"法案"
,
fileId
:
route
.
query
.
billId
}
});
};
onMounted
(()
=>
{
getBillInfoGlobalFn
();
if
(
window
.
sessionStorage
.
getItem
(
"activeTitle"
))
{
...
...
@@ -375,12 +381,11 @@ onMounted(() => {
// margin-right: 150px;
// margin-top: 19px;
.right-box-top
{
height
:
64px
;
display
:
flex
;
align-items
:
right
;
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
right
;
flex-direction
:
column
;
justify-content
:
center
;
.time
{
// height: 24px;
// line-height: 24px;
...
...
src/views/decree/decreeLayout/index.vue
浏览文件 @
bf04ed1e
...
...
@@ -3,23 +3,29 @@
<!-- 导航菜单 -->
<div
class=
"layout-main"
>
<div
class=
"header-main"
>
<div
class=
"layout-main-header"
>
<div
class=
"layout-main-header-container"
>
<div
class=
"layout-main-header-left-box"
>
<div
class=
"left-box-top"
>
<div
class=
"icon"
>
<img
v-if=
"summaryInfo.imageUrl"
:src=
"summaryInfo.imageUrl"
alt=
""
style=
"height: 40px;margin-top: 12px;"
/>
<img
v-if=
"summaryInfo.imageUrl"
:src=
"summaryInfo.imageUrl"
alt=
""
style=
"height: 40px; margin-top: 12px"
/>
<img
v-else
:src=
"USALogo"
alt=
""
/>
</div>
<div
class=
"info"
>
<div
class=
"info-box1"
>
{{
summaryInfo
.
name
}}
</div>
<div
class=
"info-box2"
>
<div
class=
"info-box2-item item1"
v-if=
"summaryInfo.order"
>
{{
summaryInfo
.
order
+
" | "
}}
</div>
<div
class=
"info-box2-item item2"
v-if=
"summaryInfo.type"
>
{{
summaryInfo
.
type
+
" | "
}}
</div>
<div
class=
"info-box2-item item1"
v-if=
"summaryInfo.order"
>
{{
summaryInfo
.
order
+
" | "
}}
</div>
<div
class=
"info-box2-item item2"
v-if=
"summaryInfo.type"
>
{{
summaryInfo
.
type
+
" | "
}}
</div>
<div
class=
"info-box2-item item3"
v-if=
"summaryInfo.ename"
>
{{
summaryInfo
.
ename
}}
</div>
</div>
</div>
...
...
@@ -54,7 +60,7 @@
</div>
<div
class=
"text"
>
{{
"政令原文"
}}
</div>
</div>
<div
class=
"btn-active"
>
<div
class=
"btn-active"
@
click=
"handleAnalysisClick"
>
<div
class=
"icon-active"
>
<img
src=
"./assets/icons/edit-icon.png"
alt=
""
/>
</div>
...
...
@@ -265,6 +271,16 @@ const handleShowReport = () => {
window
.
open
(
curRoute
.
href
,
"_blank"
);
};
const
handleAnalysisClick
=
()
=>
{
router
.
push
({
path
:
"/writtingAsstaint"
,
query
:
{
topic
:
"政令"
,
fileId
:
route
.
query
.
id
}
});
};
onMounted
(()
=>
{
handleGetSummary
();
console
.
log
(
route
.
path
);
...
...
src/views/exportControl/v2.0SingleSanction/assets/btn-icon3.png
0 → 100644
浏览文件 @
bf04ed1e
796 Bytes
src/views/exportControl/v2.0SingleSanction/index.vue
浏览文件 @
bf04ed1e
<
template
>
<div
class=
"entity-list"
>
<div
class=
"header"
>
<div
class=
"header-title"
>
<img
:src=
"headerTitle.img"
alt=
""
>
<div>
<div
class=
"title"
>
{{
headerTitle
.
title
}}
<!--
<span>
{{
headerTitle
.
titleEn
}}
</span>
-->
</div>
<div
class=
"department"
>
{{
headerTitle
.
department
}}
</div>
</div>
<div
class=
"btn"
>
<img
:src=
"icon01"
alt=
""
>
切换
</div>
</div>
<div
class=
"header-nav"
>
<div
class=
"nav-item"
v-for=
"(item, index) in headerNavList"
:key=
"index"
:class=
"
{ active: activeIndex === index }"
@click="activeIndex = index"
>
<img
:src=
"activeIndex === index ? item.imgActive : item.img"
alt=
""
>
<span>
{{
item
.
title
}}
</span>
<div
class=
"active-line"
v-if=
"activeIndex === index"
></div>
</div>
<div
class=
"original-text-btn"
@
click=
"handleClickOriginalText"
>
<img
:src=
"icon1"
alt=
""
>
<span>
实体清单原文
</span>
</div>
</div>
</div>
<div
class=
"main"
>
<sanctions-overview
v-if=
"activeIndex === 0"
:data=
"singleSanctionOverview"
></sanctions-overview>
<data-statistics
v-if=
"activeIndex === 1"
></data-statistics>
<deep-mining
v-if=
"activeIndex === 2"
></deep-mining>
<impact-analysis
v-if=
"activeIndex === 3"
></impact-analysis>
</div>
</div>
<div
class=
"entity-list"
>
<div
class=
"header"
>
<div
class=
"header-title"
>
<img
:src=
"headerTitle.img"
alt=
""
/>
<div>
<div
class=
"title"
>
{{
headerTitle
.
title
}}
<!--
<span>
{{
headerTitle
.
titleEn
}}
</span>
-->
</div>
<div
class=
"department"
>
{{
headerTitle
.
department
}}
</div>
</div>
<div
class=
"btn"
><img
:src=
"icon01"
alt=
""
/>
切换
</div>
</div>
<div
class=
"header-nav"
>
<div
class=
"nav-item"
v-for=
"(item, index) in headerNavList"
:key=
"index"
:class=
"
{ active: activeIndex === index }"
@click="activeIndex = index"
>
<img
:src=
"activeIndex === index ? item.imgActive : item.img"
alt=
""
/>
<span>
{{
item
.
title
}}
</span>
<div
class=
"active-line"
v-if=
"activeIndex === index"
></div>
</div>
<div
class=
"original-text-btn"
@
click=
"handleClickOriginalText"
>
<img
:src=
"icon1"
alt=
""
/>
<span>
实体清单原文
</span>
</div>
<div
class=
"btn3"
@
click=
"handleAnalysisClick"
>
<div
class=
"icon"
>
<img
src=
"./assets/btn-icon3.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"分析报告"
}}
</div>
</div>
</div>
</div>
<div
class=
"main"
>
<sanctions-overview
v-if=
"activeIndex === 0"
:data=
"singleSanctionOverview"
></sanctions-overview>
<data-statistics
v-if=
"activeIndex === 1"
></data-statistics>
<deep-mining
v-if=
"activeIndex === 2"
></deep-mining>
<impact-analysis
v-if=
"activeIndex === 3"
></impact-analysis>
</div>
</div>
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
'vue'
import
{
ref
,
onMounted
}
from
"vue"
;
import
sanctionsOverview
from
"./components/sanctionsOverview/index.vue"
import
dataStatistics
from
"./components/dataStatistics/index.vue"
import
deepMining
from
"./components/deepMining/index.vue"
import
impactAnalysis
from
"./components/impactAnalysis/index.vue"
import
sanctionsOverview
from
"./components/sanctionsOverview/index.vue"
;
import
dataStatistics
from
"./components/dataStatistics/index.vue"
;
import
deepMining
from
"./components/deepMining/index.vue"
;
import
impactAnalysis
from
"./components/impactAnalysis/index.vue"
;
import
title
from
"./assets/title.png"
import
icon01
from
"./assets/icon01.png"
import
title
from
"./assets/title.png"
;
import
icon01
from
"./assets/icon01.png"
;
import
icon1
from
"../assets/icons/icon1.png"
;
import
icon1Active
from
"../assets/icons/icon1_active.png"
;
import
icon5
from
"../assets/icons/icon5.png"
;
...
...
@@ -65,249 +66,288 @@ import icon2Active from "../assets/icons/icon2_active.png";
import
icon3
from
"../assets/icons/icon3.png"
;
import
icon3Active
from
"../assets/icons/icon3_active.png"
;
import
{
getSingleSanctionOverview
}
from
"@/api/exportControlV2.0.js"
import
{
getSingleSanctionOverview
}
from
"@/api/exportControlV2.0.js"
;
import
router
from
"@/router"
;
// 处理点击实体清单原文按钮
const
handleClickOriginalText
=
()
=>
{
// 打开新标签页
window
.
open
(
`/exportControl/origin?id=
${
sanRecordId
.
value
}
`
,
"_blank"
)
}
// 打开新标签页
window
.
open
(
`/exportControl/origin?id=
${
sanRecordId
.
value
}
`
,
"_blank"
);
}
;
// 获取URL参数
const
sanRecordId
=
ref
(
""
)
const
sanRecordId
=
ref
(
""
)
;
const
getUrlParams
=
()
=>
{
const
urlParams
=
new
URLSearchParams
(
window
.
location
.
search
);
sanRecordId
.
value
=
urlParams
.
get
(
"id"
)
||
""
}
const
urlParams
=
new
URLSearchParams
(
window
.
location
.
search
);
sanRecordId
.
value
=
urlParams
.
get
(
"id"
)
||
""
;
}
;
// console.log(sanRecordId.value)
// 单次制裁-制裁概况-基本信息
const
singleSanctionOverview
=
ref
({})
const
singleSanctionOverview
=
ref
({})
;
const
getSingleSanctionOverviewData
=
async
()
=>
{
if
(
!
sanRecordId
.
value
)
return
try
{
const
res
=
await
getSingleSanctionOverview
({
sanRecordId
:
sanRecordId
.
value
})
if
(
res
.
code
===
200
)
{
singleSanctionOverview
.
value
=
res
.
data
||
{}
// 格式化日期
let
dateStr
=
""
;
if
(
singleSanctionOverview
.
value
.
postDate
)
{
const
date
=
new
Date
(
singleSanctionOverview
.
value
.
postDate
);
if
(
!
isNaN
(
date
.
getTime
()))
{
dateStr
=
`
${
date
.
getFullYear
()}
年
${
date
.
getMonth
()
+
1
}
月
${
date
.
getDate
()}
日`
;
}
else
{
dateStr
=
singleSanctionOverview
.
value
.
postDate
;
}
}
// 更新头部信息
headerTitle
.
value
=
{
...
headerTitle
.
value
,
title
:
`
${
dateStr
}
《
${
singleSanctionOverview
.
value
.
sanTitleZh
||
singleSanctionOverview
.
value
.
sanTitle
}
》`
,
titleEn
:
singleSanctionOverview
.
value
.
sanTitle
||
""
,
department
:
singleSanctionOverview
.
value
.
fileCode
||
""
}
}
}
catch
(
error
)
{
console
.
error
(
"获取制裁概况失败:"
,
error
)
}
}
if
(
!
sanRecordId
.
value
)
return
;
try
{
const
res
=
await
getSingleSanctionOverview
({
sanRecordId
:
sanRecordId
.
value
});
if
(
res
.
code
===
200
)
{
singleSanctionOverview
.
value
=
res
.
data
||
{};
// 格式化日期
let
dateStr
=
""
;
if
(
singleSanctionOverview
.
value
.
postDate
)
{
const
date
=
new
Date
(
singleSanctionOverview
.
value
.
postDate
);
if
(
!
isNaN
(
date
.
getTime
()))
{
dateStr
=
`
${
date
.
getFullYear
()}
年
${
date
.
getMonth
()
+
1
}
月
${
date
.
getDate
()}
日`
;
}
else
{
dateStr
=
singleSanctionOverview
.
value
.
postDate
;
}
}
// 更新头部信息
headerTitle
.
value
=
{
...
headerTitle
.
value
,
title
:
`
${
dateStr
}
《
${
singleSanctionOverview
.
value
.
sanTitleZh
||
singleSanctionOverview
.
value
.
sanTitle
}
》`
,
titleEn
:
singleSanctionOverview
.
value
.
sanTitle
||
""
,
department
:
singleSanctionOverview
.
value
.
fileCode
||
""
};
}
}
catch
(
error
)
{
console
.
error
(
"获取制裁概况失败:"
,
error
);
}
};
const
headerTitle
=
ref
({
img
:
title
,
})
img
:
title
})
;
const
activeIndex
=
ref
(
0
)
const
activeIndex
=
ref
(
0
)
;
const
headerNavList
=
ref
([
{
img
:
icon1
,
imgActive
:
icon1Active
,
title
:
"制裁概况"
},
{
img
:
icon5
,
imgActive
:
icon5Active
,
title
:
"数据统计"
},
{
img
:
icon2
,
imgActive
:
icon2Active
,
title
:
"深度挖掘"
},
{
img
:
icon3
,
imgActive
:
icon3Active
,
title
:
"影响分析"
}
])
{
img
:
icon1
,
imgActive
:
icon1Active
,
title
:
"制裁概况"
},
{
img
:
icon5
,
imgActive
:
icon5Active
,
title
:
"数据统计"
},
{
img
:
icon2
,
imgActive
:
icon2Active
,
title
:
"深度挖掘"
},
{
img
:
icon3
,
imgActive
:
icon3Active
,
title
:
"影响分析"
}
])
;
const
handleAnalysisClick
=
()
=>
{
router
.
push
({
path
:
"/writtingAsstaint"
,
query
:
{
topic
:
"清单"
,
fileId
:
singleSanctionOverview
.
value
.
postDate
}
});
};
onMounted
(()
=>
{
getUrlParams
()
getSingleSanctionOverviewData
()
})
getUrlParams
();
getSingleSanctionOverviewData
();
})
;
</
script
>
<
style
scoped
lang=
"scss"
>
*
{
margin
:
0
;
padding
:
0
;
*
{
margin
:
0
;
padding
:
0
;
}
.entity-list
{
width
:
100%
;
height
:
100%
;
overflow-y
:
auto
;
.header
{
width
:
100%
;
height
:
148px
;
background-color
:
#fff
;
padding-top
:
16px
;
position
:
sticky
;
top
:
0
;
z-index
:
1000
;
box-shadow
:
0px
4px
10px
rgba
(
0
,
0
,
0
,
0
.05
);
.header-title
{
width
:
1601px
;
height
:
72px
;
background-color
:
rgba
(
246
,
250
,
255
,
1
);
margin
:
0
auto
;
border-radius
:
10px
;
border
:
2px
solid
rgba
(
174
,
214
,
255
,
1
);
display
:
flex
;
align-items
:
center
;
margin-bottom
:
12px
;
position
:
relative
;
img
{
width
:
54px
;
height
:
54px
;
margin-left
:
15px
;
margin-right
:
11px
;
}
.title
{
font-size
:
20px
;
font-weight
:
700
;
font-family
:
"Microsoft YaHei"
;
line-height
:
26px
;
color
:
rgb
(
59
,
65
,
75
);
span
{
font-size
:
16px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
color
:
rgb
(
95
,
101
,
108
);
margin-left
:
11px
;
}
}
.department
{
font-size
:
16px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
color
:
rgb
(
95
,
101
,
108
);
}
.btn
{
cursor
:
pointer
;
display
:
flex
;
align-items
:
center
;
position
:
absolute
;
right
:
16px
;
top
:
25px
;
font-size
:
18px
;
font-weight
:
700
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
color
:
rgb
(
5
,
95
,
194
);
img
{
width
:
20px
;
height
:
20px
;
margin-right
:
7px
;
}
}
}
.header-nav
{
width
:
1601px
;
margin
:
0
auto
;
height
:
48px
;
display
:
flex
;
align-items
:
center
;
.nav-item
{
display
:
flex
;
align-items
:
center
;
height
:
100%
;
margin-right
:
32px
;
cursor
:
pointer
;
position
:
relative
;
font-size
:
18px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
color
:
rgb
(
59
,
65
,
75
);
&
:last-child
{
margin-right
:
0
;
}
.entity-list
{
width
:
100%
;
height
:
100%
;
overflow-y
:
auto
;
.header
{
width
:
100%
;
height
:
148px
;
background-color
:
#fff
;
padding-top
:
16px
;
position
:
sticky
;
top
:
0
;
z-index
:
1000
;
box-shadow
:
0px
4px
10px
rgba
(
0
,
0
,
0
,
0
.05
);
.header-title
{
width
:
1601px
;
height
:
72px
;
background-color
:
rgba
(
246
,
250
,
255
,
1
);
margin
:
0
auto
;
border-radius
:
10px
;
border
:
2px
solid
rgba
(
174
,
214
,
255
,
1
);
display
:
flex
;
align-items
:
center
;
margin-bottom
:
12px
;
position
:
relative
;
img
{
width
:
54px
;
height
:
54px
;
margin-left
:
15px
;
margin-right
:
11px
;
}
.title
{
font-size
:
20px
;
font-weight
:
700
;
font-family
:
"Microsoft YaHei"
;
line-height
:
26px
;
color
:
rgb
(
59
,
65
,
75
);
span
{
font-size
:
16px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
color
:
rgb
(
95
,
101
,
108
);
margin-left
:
11px
;
}
}
.department
{
font-size
:
16px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
color
:
rgb
(
95
,
101
,
108
);
}
.btn
{
cursor
:
pointer
;
display
:
flex
;
align-items
:
center
;
position
:
absolute
;
right
:
16px
;
top
:
25px
;
font-size
:
18px
;
font-weight
:
700
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
color
:
rgb
(
5
,
95
,
194
);
img
{
width
:
20px
;
height
:
20px
;
margin-right
:
7px
;
}
}
}
.header-nav
{
width
:
1601px
;
margin
:
0
auto
;
height
:
48px
;
display
:
flex
;
align-items
:
center
;
.nav-item
{
display
:
flex
;
align-items
:
center
;
height
:
100%
;
margin-right
:
32px
;
cursor
:
pointer
;
position
:
relative
;
font-size
:
18px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
color
:
rgb
(
59
,
65
,
75
);
&
:last-child
{
margin-right
:
0
;
}
img
{
width
:
16px
;
height
:
16px
;
margin-right
:
4px
;
}
&
.active
{
color
:
rgb
(
5
,
95
,
194
);
font-weight
:
700
;
}
.active-line
{
position
:
absolute
;
bottom
:
0
;
left
:
0
;
width
:
100%
;
height
:
3px
;
background-color
:
#055fc2
;
border-radius
:
1
.5px
;
}
}
img
{
width
:
16px
;
height
:
16px
;
margin-right
:
4px
;
}
.original-text-btn
{
margin-left
:
auto
;
width
:
152px
;
height
:
36px
;
background
:
#ffffff
;
border-radius
:
4px
;
border
:
1px
solid
rgba
(
230
,
231
,
232
,
1
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
&
.active
{
color
:
rgb
(
5
,
95
,
194
);
font-weight
:
700
;
}
img
{
width
:
16px
;
height
:
16px
;
margin-right
:
8px
;
}
.active-line
{
position
:
absolute
;
bottom
:
0
;
left
:
0
;
width
:
100%
;
height
:
3px
;
background-color
:
#055fc2
;
border-radius
:
1
.5px
;
}
}
span
{
font-size
:
16px
;
font-weight
:
400
;
color
:
rgb
(
95
,
101
,
108
);
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
}
}
.original-text-btn
{
margin-left
:
auto
;
width
:
152px
;
height
:
36px
;
background
:
#FFFFFF
;
border-radius
:
4px
;
border
:
1px
solid
rgba
(
230
,
231
,
232
,
1
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
img
{
width
:
16px
;
height
:
16px
;
margin-right
:
8px
;
}
span
{
font-size
:
16px
;
font-weight
:
400
;
color
:
rgb
(
95
,
101
,
108
);
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
}
}
}
}
.main
{
width
:
100%
;
height
:
auto
;
min-height
:
calc
(
100%
-
148px
);
background-color
:
#F7F8F9
;
}
.btn3
{
cursor
:
pointer
;
width
:
120px
;
height
:
36px
;
border-radius
:
6px
;
background
:
rgba
(
5
,
95
,
194
,
1
);
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
gap
:
8px
;
margin-left
:
8px
;
.icon
{
width
:
16px
;
height
:
16px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
height
:
24px
;
color
:
rgba
(
255
,
255
,
255
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
}
}
}
.main
{
width
:
100%
;
height
:
auto
;
min-height
:
calc
(
100%
-
148px
);
background-color
:
#f7f8f9
;
}
}
</
style
>
src/views/thinkTank/ReportDetail/index.vue
浏览文件 @
bf04ed1e
...
...
@@ -57,7 +57,7 @@
</div>
<div
class=
"text"
>
{{
"文档下载"
}}
</div>
</div>
<div
class=
"btn btn1"
>
<div
class=
"btn btn1"
@
click=
"handleAnalysisClick"
>
<div
class=
"icon"
>
<img
src=
"./images/btn-icon4.png"
alt=
""
/>
</div>
...
...
@@ -79,8 +79,9 @@ import { ref, onMounted } from "vue";
import
ReportAnalysis
from
"./reportAnalysis/index.vue"
;
import
PolicyTracking
from
"./policyTracking/index.vue"
;
import
{
getThinkTankReportSummary
}
from
"@/api/thinkTank/overview"
;
import
{
useRouter
}
from
"vue-router"
;
import
{
useRoute
,
useRoute
r
}
from
"vue-router"
;
const
router
=
useRouter
();
const
route
=
useRoute
();
const
reportUrl
=
ref
(
""
);
const
thinkInfo
=
ref
({});
...
...
@@ -113,6 +114,16 @@ const tabActiveName = ref("报告分析");
const
switchTab
=
name
=>
{
tabActiveName
.
value
=
name
;
};
const
handleAnalysisClick
=
()
=>
{
router
.
push
({
path
:
"/writtingAsstaint"
,
query
:
{
topic
:
"智库"
,
fileId
:
router
.
currentRoute
.
_value
.
params
.
id
}
});
};
onMounted
(
async
()
=>
{
handleGetThinkTankReportSummary
();
});
...
...
src/views/writtingAsstaint/index.vue
浏览文件 @
bf04ed1e
...
...
@@ -31,98 +31,108 @@
</div>
<div
class=
"writting-main"
>
<div
class=
"left-box"
>
<div
class=
"process-box"
v-if=
"isShowProcess"
>
<div
class=
"back"
@
click=
"handleBack"
>
{{
"< 返回"
}}
</div>
<div
class=
"process-main-box"
>
<div
class=
"steps-box"
>
<div
class=
"steps-header"
>
<div
class=
"icon"
>
<img
src=
"./assets/images/right-arrow.png"
alt=
""
/>
<div
class=
"left-box-input"
>
<div
class=
"process-box"
v-if=
"isShowProcess"
>
<div
class=
"back"
@
click=
"handleBack"
>
{{
"< 返回"
}}
</div>
<div
class=
"process-main-box"
>
<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=
"text"
>
{{
"执行步骤:"
}}
</div>
<div
class=
"steps-content"
ref=
"scrollProcessContainer"
v-html=
"renderedProcess"
></div>
</div>
<div
class=
"tool-box"
>
<div
class=
"tool-header"
>
{{
"工具调用"
}}
</div>
<div
class=
"tool-main"
>
当前智能体工具:
{{
curAgentTool
?
curAgentTool
:
"无"
}}
</div>
</div>
<div
class=
"steps-content"
ref=
"scrollProcessContainer"
v-html=
"renderedProcess"
></div>
</div>
<div
class=
"tool-box"
>
<div
class=
"tool-header"
>
{{
"工具调用"
}}
</div>
<div
class=
"tool-main"
>
当前智能体工具:
{{
curAgentTool
?
curAgentTool
:
"无"
}}
</div>
</div>
</div>
</div
>
<div
class=
"sider"
v-else
>
<div
class=
"sider-box"
v-if=
"false"
>
<div
class=
"header"
>
报文主题
</div
>
<div
class=
"title-box"
>
<div
class=
"title"
>
主题名称
</div>
<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
:disabled=
"true
"
class=
"description-input
"
type=
"textarea
"
style=
"width: 476px
"
:rows=
"8
"
placeholder=
"输入报文主题描述,如:从科技领域方面分析大而美法案通过后对中国可能产生的影响
"
v-model=
"descText"
/
>
<div
class=
"sider"
v-else
>
<div
class=
"sider-box"
>
<div
class=
"header"
>
报文主题
</div
>
<div
class=
"title-box"
>
<div
class=
"title"
>
主题名称
</div
>
<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
:disabled=
"true"
class=
"description-input
"
type=
"textarea
"
style=
"width: 476px
"
:rows=
"8
"
placeholder=
"输入报文主题描述,如:从科技领域方面分析大而美法案通过后对中国可能产生的影响
"
v-model=
"descText
"
/>
</div
>
</div>
</div>
<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=
"header"
>
<div
class=
"title"
>
{{
temp
.
title
}}
</div>
<div
class=
"icon"
>
<img
src=
"./assets/images/template-icon.png"
alt=
""
/>
<div
class=
"sider-box"
>
<div
class=
"header"
>
报文模板
</div>
<div
class=
"template-box"
>
<div
class=
"template"
:class=
"
{
tempActive: tempActiveIndex === index,
disableTemplate: tempActiveIndex !== index
&&
Object.keys(route.query).length > 0
}"
v-for="(temp, index) in tempList"
:key="index"
@click="handleClickTemp(temp, index)"
>
<div
class=
"header"
>
<div
class=
"title"
>
{{
temp
.
title
}}
</div>
<div
class=
"icon"
>
<img
src=
"./assets/images/template-icon.png"
alt=
""
/>
</div>
</div>
<div
class=
"content"
>
{{
temp
.
desc
}}
</div>
<div
class=
"active-icon"
v-if=
"tempActiveIndex === index"
>
<img
src=
"./assets/images/active-icon.png"
alt=
""
/>
</div>
<div
class=
"selected-icon"
v-if=
"tempActiveIndex === index"
>
<img
src=
"./assets/images/selected-icon.png"
alt=
""
/>
</div>
</div>
<div
class=
"content"
>
{{
temp
.
desc
}}
</div>
<div
class=
"active-icon"
v-if=
"tempActiveIndex === index"
>
<img
src=
"./assets/images/active-icon.png"
alt=
""
/>
</div>
<div
class=
"selected-icon"
v-if=
"tempActiveIndex === index"
>
<img
src=
"./assets/images/selected-icon.png"
alt=
""
/>
</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"
:file-list=
"uploadFileList"
>
<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
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"
:file-list=
"uploadFileList"
:disabled=
"Object.keys(route.query).length !== 0"
>
<el-button
class=
"sider-upload-btn"
type=
"primary"
:disabled=
"Object.keys(route.query).length !== 0"
>
<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>
</div>
<div
class=
"submit-area"
>
...
...
@@ -182,14 +192,61 @@ import "@kangc/v-md-editor/lib/theme/style/vuepress.css";
import
Prism
from
"prismjs"
;
import
{
ElButton
,
ElIcon
,
ElInput
,
ElMessage
,
ElUpload
,
genFileId
}
from
"element-plus"
;
VMdEditor
.
use
(
vuepressTheme
,
{
Prism
});
import
{
useRoute
}
from
"vue-router"
;
const
route
=
useRoute
();
const
isGenerating
=
ref
(
false
);
const
isShowProcess
=
ref
(
false
);
const
uploadFileList
=
ref
([]);
const
upload
=
ref
();
// 流程
const
scrollProcessContainer
=
ref
(
null
);
const
processContent
=
ref
(
""
);
// 报文
const
scrollContainer
=
ref
(
null
);
const
reportContent
=
ref
(
""
);
const
curTempTitle
=
ref
(
"政令"
);
const
abortController
=
ref
(
null
);
// 当前调用工具
const
curAgentTool
=
ref
(
""
);
const
writtingTitle
=
ref
(
""
);
const
descText
=
ref
(
""
);
const
tabList
=
ref
([
{
name
:
"写报"
,
active
:
true
},
{
name
:
"收藏"
,
active
:
false
},
{
name
:
"问答"
,
active
:
false
}
]);
const
tempList
=
ref
([
{
title
:
"政令"
,
desc
:
"基于政令内容生成各维度的综合分析报告"
},
{
title
:
"法案"
,
desc
:
"基于政令内容生成各维度的综合分析报告"
},
{
title
:
"智库"
,
desc
:
"基于智库内容生成各维度的综合分析报告"
},
{
title
:
"清单"
,
desc
:
"基于清单内容生成各维度的综合分析报告"
}
]);
const
tempActiveIndex
=
ref
(
0
);
VMdEditor
.
use
(
vuepressTheme
,
{
Prism
});
//新上传文件替换
const
handleExceed
=
files
=>
{
...
...
@@ -214,7 +271,7 @@ const handleBack = () => {
handleGenerate
();
};
const
isEditMode
=
ref
(
fals
e
);
const
isEditMode
=
ref
(
tru
e
);
const
handleSwitchMode
=
()
=>
{
isEditMode
.
value
=
!
isEditMode
.
value
;
if
(
!
isEditMode
.
value
)
{
...
...
@@ -241,20 +298,9 @@ const saveToLocalStorage = text => {
localStorage
.
setItem
(
"markdown-content"
,
text
);
};
const
abortController
=
ref
(
null
);
const
{
renderedContent
,
updateContent
}
=
useMarkdownStream
();
const
{
renderedProcess
,
updateProcess
}
=
useStream
();
// 流程
const
scrollProcessContainer
=
ref
(
null
);
const
processContent
=
ref
(
""
);
// 报文
const
scrollContainer
=
ref
(
null
);
const
reportContent
=
ref
(
""
);
const
curTempTitle
=
ref
(
"法案"
);
// 停止生成
const
handleGenerate
=
()
=>
{
isShowProcess
.
value
=
false
;
...
...
@@ -262,87 +308,160 @@ const handleGenerate = () => {
abortController
.
value
.
abort
();
};
// 当前调用工具
const
curAgentTool
=
ref
(
"报告整体优化工具"
);
const
getStreamChat
=
async
(
search
,
inputValue
)
=>
{
if
(
uploadFileList
.
value
.
length
>
0
)
{
const
rawFile
=
uploadFileList
.
value
[
0
].
raw
;
if
(
!
rawFile
)
{
ElMessage
.
error
(
"文件解析失败,请重新选择"
);
return
;
}
callSseWithPdf
(
rawFile
);
}
else
{
if
(
Object
.
keys
(
route
.
query
).
length
!==
0
)
{
const
params
=
{
query
:
writtingTitle
.
value
,
// "输出一篇报文"
desc
:
descText
.
value
,
topic
:
curTempTitle
.
value
// 政令、智库、法案、清单
topic
:
curTempTitle
.
value
,
report_id
:
route
.
query
.
fileId
// 政令、智库、法案、清单
};
callSseWithAi
(
params
);
}
else
{
if
(
curTempTitle
.
value
===
"政令"
)
{
if
(
uploadFileList
.
value
.
length
===
0
)
{
ElMessage
.
error
(
"请上传政令文件"
);
return
;
}
const
rawFile
=
uploadFileList
.
value
[
0
].
raw
;
if
(
!
rawFile
)
{
ElMessage
.
error
(
"文件解析失败,请重新选择"
);
return
;
}
callSseWithPdf
(
rawFile
);
}
else
{
const
params
=
{
query
:
writtingTitle
.
value
,
// "输出一篇报文"
desc
:
descText
.
value
,
topic
:
curTempTitle
.
value
// 政令、智库、法案、清单
};
callSseWithAi
(
params
);
}
}
};
const
getFormattedTime
=
()
=>
{
const
now
=
new
Date
();
// 补零函数:确保单个数字补为两位(如 1 → 01,9 → 09)
const
pad
=
n
=>
n
.
toString
().
padStart
(
2
,
"0"
);
return
`
${
now
.
getFullYear
()}
-
${
pad
(
now
.
getMonth
()
+
1
)}
-
${
pad
(
now
.
getDate
())}
${
pad
(
now
.
getHours
())}
:
${
pad
(
now
.
getMinutes
()
)}
:
${
pad
(
now
.
getSeconds
())}
`
;
};
// 核心SSE调用函数(修复后)
const
callSseWithPdf
=
async
selectedFile
=>
{
// 重置中断控制器
if
(
abortController
.
value
)
{
abortController
.
value
.
abort
();
}
abortController
.
value
=
new
AbortController
();
// 状态重置
isGenerating
.
value
=
false
;
isShowProcess
.
value
=
false
;
try
{
// 构造FormData(和后端字段名保持一致)
const
formData
=
new
FormData
();
formData
.
append
(
"pdf"
,
selectedFile
);
// 调用fetchEventSource(核心:支持POST+FormData+SSE)
await
fetchEventSource
(
"/pdfSse/api/v1/order/pdf/extract/report/sse"
,
{
method
:
"POST"
,
// 关键:设置POST方法
body
:
formData
,
// 关键:传递PDF文件的FormData
signal
:
abortController
.
value
.
signal
,
// 中断信号
method
:
"POST"
,
body
:
formData
,
signal
:
abortController
.
value
.
signal
,
headers
:
{
// 禁用默认的SSE协议头(避免和文件上传冲突)
Accept
:
"text/event-stream"
,
"Cache-Control"
:
"no-cache"
,
Connection
:
"keep-alive"
"Cache-Control"
:
"no-cache"
},
openWhenHidden
:
true
,
// 核心:原生onmessage回调(无需手动分割/解析)
async
onopen
(
res
)
{
console
.
log
(
"流式回答开始"
,
res
);
isGenerating
.
value
=
true
;
isShowProcess
.
value
=
true
;
retryDelay
:
1000
,
maxRetries
:
3
,
// 连接打开回调
async
onopen
(
response
)
{
console
.
log
(
"流式回答开始"
,
response
);
// 校验响应状态
if
(
response
.
ok
&&
response
.
headers
.
get
(
"content-type"
)?.
includes
(
"text/event-stream"
))
{
isGenerating
.
value
=
true
;
isShowProcess
.
value
=
true
;
}
else
{
ElMessage
.
warning
(
"SSE连接格式异常,即将断开"
);
abortController
.
value
.
abort
();
}
},
async
onmessage
(
res
)
{
const
{
data
,
event
}
=
res
;
const
jsonData
=
JSON
.
parse
(
data
);
switch
(
event
)
{
// 核心修复:消息处理回调
async
onmessage
(
event
)
{
// 1. 严格过滤空消息(解决失焦时空消息问题)
if
(
!
event
||
!
event
.
data
||
event
.
data
.
trim
()
===
""
)
{
console
.
debug
(
"收到空SSE消息,忽略"
,
event
);
return
;
}
let
jsonData
=
null
;
try
{
// 2. 容错处理:防止非JSON格式的消息导致解析报错
jsonData
=
JSON
.
parse
(
event
.
data
.
trim
());
}
catch
(
parseError
)
{
console
.
warn
(
"SSE消息JSON解析失败"
,
parseError
,
event
.
data
);
return
;
}
// 3. 按事件类型处理业务逻辑
switch
(
event
.
event
)
{
case
"progress"
:
processContent
.
value
+=
`
${
getFormattedTime
()}
:
${
jsonData
.
message
}
\r\n`
;
updateProcess
(
processContent
.
value
,
scrollProcessContainer
.
value
);
// 校验数据完整性
if
(
jsonData
.
message
)
{
processContent
.
value
+=
`
${
getFormattedTime
()}
:
${
jsonData
.
message
}
\r\n`
;
updateProcess
(
processContent
.
value
,
scrollProcessContainer
.
value
);
}
break
;
case
"result"
:
callSseWithAi
({
query
:
writtingTitle
.
value
,
// "输出一篇报文"
desc
:
descText
.
value
,
topic
:
"政令"
,
result
:
data
// 政令、智库、法案、清单
});
// 确保result数据有效
if
(
jsonData
&&
Object
.
keys
(
jsonData
).
length
)
{
await
callSseWithAi
({
query
:
writtingTitle
.
value
,
desc
:
descText
.
value
,
topic
:
curTempTitle
.
value
,
result
:
jsonData
// 传递解析后的对象而非原始字符串
});
}
break
;
default
:
console
.
debug
(
"未处理的SSE事件类型"
,
event
.
event
);
break
;
}
},
// 错误处理优化
onerror
(
error
)
{
ElMessage
({
message
:
"写报生成报错!"
,
type
:
"warning"
});
console
.
error
(
"SSE连接错误"
,
error
);
ElMessage
.
warning
(
"写报生成报错!"
);
// 只在非主动中断时重连/终止
if
(
error
.
name
!==
"AbortError"
)
{
// 触发库的自动重连机制(返回true)
return
true
;
}
// 主动中断时清理控制器
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
throw
new
Error
(
error
);
},
// 连接关闭回调
onclose
()
{
console
.
log
(
"SSE连接正常关闭"
);
isGenerating
.
value
=
false
;
}
});
}
catch
(
error
)
{
// 全局异常捕获
if
(
error
.
name
!==
"AbortError"
)
{
ElMessage
.
error
(
`请求失败:
${
error
.
message
}
`
);
isLoading
.
value
=
false
;
console
.
error
(
"SSE请求异常"
,
error
)
;
}
// 重置状态
isGenerating
.
value
=
false
;
isShowProcess
.
value
=
false
;
// 清理控制器
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
}
};
...
...
@@ -412,54 +531,8 @@ const callSseWithAi = async params => {
});
};
const
getFormattedTime
=
()
=>
{
const
now
=
new
Date
();
// 补零函数:确保单个数字补为两位(如 1 → 01,9 → 09)
const
pad
=
n
=>
n
.
toString
().
padStart
(
2
,
"0"
);
return
`
${
now
.
getFullYear
()}
-
${
pad
(
now
.
getMonth
()
+
1
)}
-
${
pad
(
now
.
getDate
())}
${
pad
(
now
.
getHours
())}
:
${
pad
(
now
.
getMinutes
()
)}
:
${
pad
(
now
.
getSeconds
())}
`
;
};
const
writtingTitle
=
ref
(
""
);
const
descText
=
ref
(
""
);
const
tabList
=
ref
([
{
name
:
"写报"
,
active
:
true
},
{
name
:
"收藏"
,
active
:
false
},
{
name
:
"问答"
,
active
:
false
}
]);
const
tempList
=
ref
([
{
title
:
"法案1"
,
desc
:
"基于法案内容生成各维度的综合分析报告"
},
{
title
:
"智库"
,
desc
:
"基于智库内容生成各维度的综合分析报告"
},
{
title
:
"政令"
,
desc
:
"基于政令内容生成各维度的综合分析报告"
},
{
title
:
"清单"
,
desc
:
"基于清单内容生成各维度的综合分析报告"
}
]);
const
tempActiveIndex
=
ref
(
0
);
const
handleClickTemp
=
(
item
,
index
)
=>
{
if
(
Object
.
keys
(
route
.
query
).
length
!==
0
)
return
;
tempActiveIndex
.
value
=
index
;
curTempTitle
.
value
=
item
.
title
;
};
...
...
@@ -475,7 +548,16 @@ const exportContent = () => {
URL
.
revokeObjectURL
(
url
);
};
onMounted
(()
=>
{});
onMounted
(()
=>
{
if
(
route
&&
Object
.
keys
(
route
.
query
).
length
!==
0
)
{
const
{
topic
,
fileId
}
=
route
.
query
;
if
(
!
topic
||
!
fileId
)
return
;
curTempTitle
.
value
=
topic
;
tempActiveIndex
.
value
=
tempList
.
value
.
findIndex
((
item
,
index
)
=>
{
return
item
.
title
===
topic
;
});
}
});
onUnmounted
(()
=>
{
if
(
abortController
.
value
)
{
...
...
@@ -584,321 +666,413 @@ onUnmounted(() => {
.left-box
{
display
:
flex
;
flex-direction
:
column
;
width
:
520px
;
padding
:
21px
21px
29px
22px
;
width
:
525px
;
padding-top
:
22px
;
padding-bottom
:
29px
;
box-sizing
:
border-box
;
border-right
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-top
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
.process-box
{
display
:
flex
;
flex-direction
:
column
;
gap
:
20px
;
.left-box-input
{
overflow-y
:
scroll
;
overflow-x
:
hidden
;
scrollbar-width
:
none
;
padding-inline
:
22px
;
.back
{
height
:
24px
;
line-height
:
24px
;
color
:
var
(
--
color-main-active
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
cursor
:
pointer
;
}
.process-box
{
display
:
flex
;
flex-direction
:
column
;
gap
:
20px
;
.process-main-box
{
width
:
476px
;
.back
{
height
:
24px
;
line-height
:
24px
;
color
:
var
(
--
color-main-active
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
cursor
:
pointer
;
}
.analysis-box
{
.analysis-header
{
display
:
flex
;
.process-main-box
{
width
:
476px
;
.analysis-box
{
.analysis-header
{
display
:
flex
;
.icon
{
margin-top
:
5px
;
width
:
20px
;
height
:
20px
;
.icon
{
margin-top
:
5px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
height
:
30px
;
line-height
:
30px
;
font-family
:
Microsoft
YaHei
;
color
:
#333
;
font-size
:
20px
;
font-weight
:
700
;
margin-left
:
5px
;
}
}
.
tex
t
{
height
:
3
0px
;
.
analysis-conten
t
{
height
:
9
0px
;
line-height
:
30px
;
color
:
#555
;
font-family
:
Microsoft
YaHei
;
color
:
#333
;
font-size
:
20px
;
font-weight
:
700
;
margin-left
:
5px
;
font-size
:
16px
;
font-weight
:
400
;
text-indent
:
32px
;
}
}
.analysis-content
{
height
:
90px
;
line-height
:
30px
;
color
:
#555
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
text-indent
:
32px
;
}
}
.steps-box
{
.steps-header
{
display
:
flex
;
.steps-box
{
.steps-header
{
display
:
flex
;
.icon
{
margin-top
:
5px
;
width
:
20px
;
height
:
20px
;
.icon
{
margin-top
:
5px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
img
{
width
:
100%
;
height
:
100%
;
.text
{
height
:
30px
;
line-height
:
30px
;
font-family
:
Microsoft
YaHei
;
color
:
#333
;
font-size
:
20px
;
font-weight
:
700
;
margin-left
:
5px
;
}
}
.text
{
height
:
30px
;
line-height
:
30px
;
font-family
:
Microsoft
YaHei
;
color
:
#333
;
font-size
:
20px
;
font-weight
:
700
;
margin-left
:
5px
;
.steps-content
{
width
:
100%
;
min-height
:
20px
;
max-height
:
480px
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
}
}
.steps-content
{
width
:
100%
;
min-height
:
20px
;
max-height
:
480px
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
.doing-box
{
height
:
40px
;
line-height
:
40px
;
color
:
#555
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
margin-left
:
20px
;
}
}
.doing-box
{
height
:
40px
;
line-height
:
40px
;
color
:
#555
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
margin-left
:
20px
;
}
.tool-box
{
width
:
440px
;
height
:
160px
;
margin
:
10px
auto
;
background
:
#f6f9fe
;
border-radius
:
10px
;
.tool-box
{
width
:
44
0px
;
height
:
16
0px
;
margin
:
10px
auto
;
background
:
#f6f9fe
;
border-radius
:
10px
;
.tool-header
{
height
:
3
0px
;
line-height
:
3
0px
;
margin-left
:
20px
;
color
:
var
(
--
color-main-active
)
;
}
.tool-header
{
height
:
30px
;
line-height
:
30px
;
margin-left
:
20px
;
color
:
var
(
--
color-main-active
);
.tool-main
{
height
:
110px
;
width
:
400px
;
margin
:
0
auto
;
background
:
#fff
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
40px
;
}
}
}
}
.tool-main
{
height
:
110px
;
width
:
400px
;
margin
:
0
auto
;
background
:
#fff
;
color
:
rgba
(
95
,
101
,
108
,
1
);
.sider
{
box-sizing
:
border-box
;
display
:
flex
;
flex-direction
:
column
;
gap
:
23px
;
.sider-box
{
.header
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
4
00
;
line-height
:
40
px
;
font-weight
:
7
00
;
line-height
:
24
px
;
}
}
}
}
.sider
{
box-sizing
:
border-box
;
display
:
flex
;
flex-direction
:
column
;
gap
:
23px
;
.template-box
{
margin-top
:
19px
;
height
:
260px
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
16px
;
.template
{
width
:
230px
;
height
:
120px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
4px
;
position
:
relative
;
cursor
:
pointer
;
.active-icon
{
width
:
24px
;
height
:
24px
;
position
:
absolute
;
top
:
0
;
right
:
0
;
z-index
:
99
;
.sider-box
{
.header
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
24px
;
}
img
{
width
:
100%
;
height
:
100%
;
}
}
.template-box
{
margin-top
:
19px
;
height
:
260px
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
16px
;
.selected-icon
{
width
:
8px
;
height
:
6px
;
position
:
absolute
;
top
:
-4px
;
right
:
3px
;
z-index
:
100
;
.template
{
width
:
230px
;
height
:
120px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
4px
;
position
:
relative
;
cursor
:
pointer
;
img
{
width
:
8px
;
height
:
6px
;
}
}
.active-icon
{
width
:
24px
;
height
:
24px
;
position
:
absolute
;
top
:
0
;
right
:
0
;
z-index
:
99
;
img
{
width
:
100%
;
height
:
100%
;
.header
{
display
:
flex
;
justify-content
:
space-between
;
height
:
50px
;
.title
{
height
:
24px
;
// color: rgba(59, 65, 75, 1);
color
:
#333
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
24px
;
margin-left
:
15px
;
margin-top
:
16px
;
}
.icon
{
margin-top
:
15px
;
margin-right
:
16px
;
width
:
30px
;
height
:
30px
;
border-radius
:
15px
;
background
:
rgba
(
231
,
243
,
255
,
1
);
img
{
width
:
17px
;
height
:
14px
;
margin-top
:
8px
;
margin-left
:
7px
;
}
}
}
.content
{
margin
:
0
auto
;
width
:
200px
;
height
:
48px
;
margin-top
:
10px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
}
}
.selected-icon
{
width
:
8px
;
height
:
6px
;
position
:
absolute
;
top
:
-4px
;
right
:
3px
;
z-index
:
100
;
.disableTemplate
{
width
:
230px
;
height
:
120px
;
box-sizing
:
border-box
;
border
:
1px
solid
#e4e7ed
;
border-radius
:
4px
;
position
:
relative
;
cursor
:
not
-
allowed
;
background-color
:
#f5f7fa
;
.active-icon
{
width
:
24px
;
height
:
24px
;
position
:
absolute
;
top
:
0
;
right
:
0
;
z-index
:
99
;
img
{
img
{
width
:
100%
;
height
:
100%
;
}
}
.selected-icon
{
width
:
8px
;
height
:
6px
;
position
:
absolute
;
top
:
-4px
;
right
:
3px
;
z-index
:
100
;
img
{
width
:
8px
;
height
:
6px
;
}
}
}
.header
{
display
:
flex
;
justify-content
:
space-between
;
height
:
50px
;
.header
{
display
:
flex
;
justify-content
:
space-between
;
height
:
50px
;
.title
{
height
:
24px
;
color
:
#c0c4cc
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
24px
;
margin-left
:
15px
;
margin-top
:
16px
;
}
.title
{
height
:
24px
;
// color: rgba(59, 65, 75, 1);
color
:
#333
;
.icon
{
margin-top
:
15px
;
margin-right
:
16px
;
width
:
30px
;
height
:
30px
;
border-radius
:
15px
;
background
:
#f0f2f5
;
img
{
width
:
17px
;
height
:
14px
;
margin-top
:
8px
;
margin-left
:
7px
;
opacity
:
0
.5
;
}
}
}
.content
{
margin
:
0
auto
;
width
:
200px
;
height
:
48px
;
margin-top
:
10px
;
color
:
#dcdfe6
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
7
00
;
font-weight
:
4
00
;
line-height
:
24px
;
margin-left
:
15px
;
margin-top
:
16px
;
}
}
.icon
{
margin-top
:
15px
;
margin-right
:
16px
;
width
:
30px
;
height
:
30px
;
border-radius
:
15px
;
background
:
rgba
(
231
,
243
,
255
,
1
);
img
{
width
:
17px
;
height
:
14px
;
margin-top
:
8px
;
margin-left
:
7px
;
}
}
.tempActive
{
border
:
1px
solid
rgba
(
5
,
95
,
194
,
1
);
background
:
rgba
(
246
,
250
,
255
,
1
);
}
}
.content
{
margin
:
0
auto
;
width
:
200px
;
height
:
48px
;
margin-top
:
10px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
.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
;
}
}
.tempActive
{
border
:
1px
solid
rgba
(
5
,
95
,
194
,
1
)
;
background
:
rgba
(
246
,
250
,
255
,
1
);
.title-input
{
margin-top
:
15px
;
}
}
}
.title
-box
{
margin-top
:
15
px
;
.description
-box
{
margin-top
:
24
px
;
.title
{
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
}
.title
{
height
:
24px
;
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-input
{
margin-top
:
12px
;
height
:
200px
;
}
}
}
.description-box
{
margin-top
:
24px
;
.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
;
}
.title
{
height
:
24px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
.sider-upload-btn-text
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-style
:
Regular
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
24px
;
line-height
:
22px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
.description-input
{
margin-top
:
12px
;
height
:
200px
;
.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
;
}
}
.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
;
}
}
}
...
...
@@ -906,6 +1080,7 @@ onUnmounted(() => {
margin-top
:
auto
;
width
:
100%
;
min-height
:
74px
;
padding-inline
:
22px
;
.tips
{
height
:
22px
;
...
...
@@ -1026,7 +1201,7 @@ onUnmounted(() => {
background
:
#f7f8f9
;
.edit-panel
{
width
:
calc
(
100%
-
1
0
0px
);
width
:
calc
(
100%
-
1
7
0px
);
height
:
calc
(
100%
-
40px
);
margin
:
20px
50px
;
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论