Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
6b4028a9
提交
6b4028a9
authored
4月 02, 2026
作者:
朱政
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'pre' into zz-dev
上级
1a528d62
2c66e151
流水线
#310
已通过 于阶段
in 1 分 28 秒
变更
24
流水线
1
隐藏空白字符变更
内嵌
并排
正在显示
24 个修改的文件
包含
2116 行增加
和
1216 行删除
+2116
-1216
index.js
src/api/comprehensiveSearch/index.js
+8
-0
newOriginal.vue
src/components/base/DecreeOriginal/newOriginal.vue
+463
-0
bill-tokens.scss
src/styles/bill-tokens.scss
+35
-0
BILL_LAYOUT_UNIFICATION_PLAN.md
src/views/bill/BILL_LAYOUT_UNIFICATION_PLAN.md
+201
-0
index.vue
src/views/bill/background/index.vue
+127
-101
BillHeader.vue
src/views/bill/billLayout/components/BillHeader.vue
+6
-4
index.vue
src/views/bill/billLayout/index.vue
+34
-5
BillPageShell.vue
src/views/bill/components/layout/BillPageShell.vue
+51
-0
BillPanel.vue
src/views/bill/components/layout/BillPanel.vue
+117
-0
BillTwoColumn.vue
src/views/bill/components/layout/BillTwoColumn.vue
+108
-0
index.js
src/views/bill/components/layout/index.js
+9
-0
index.vue
src/views/bill/deepDig/processAnalysis/index.vue
+9
-6
index.vue
src/views/bill/deepDig/processOverview/index.vue
+6
-11
index.vue
src/views/bill/introdoction/index.vue
+25
-14
index.vue
src/views/bill/template/index.vue
+121
-121
index.vue
src/views/dataLibrary/bill/countryBill/index.vue
+52
-12
index.vue
src/views/dataLibrary/decree/index.vue
+21
-15
index.vue
src/views/dataLibrary/thinkTank/index.vue
+415
-451
index.vue
src/views/decree/decreeHome/index.vue
+6
-1
index.vue
src/views/decree/decreeOriginal/index.vue
+6
-16
SurveyHistory.vue
src/views/marketAccessRestrictions/com/SurveyHistory.vue
+3
-5
index.vue
...tAccessRestrictions/marketAccessLayout/case/232/index.vue
+87
-128
index.vue
...tAccessRestrictions/marketAccessLayout/case/301/index.vue
+95
-160
index.vue
...tAccessRestrictions/marketAccessLayout/case/337/index.vue
+111
-166
没有找到文件。
src/api/comprehensiveSearch/index.js
浏览文件 @
6b4028a9
...
@@ -17,4 +17,11 @@ export function getThinkTankList() {
...
@@ -17,4 +17,11 @@ export function getThinkTankList() {
method
:
'GET'
,
method
:
'GET'
,
url
:
`/temporarySearch/search-info/all-organization-names`
,
url
:
`/temporarySearch/search-info/all-organization-names`
,
})
})
}
export
function
getStatusList
()
{
return
request
({
method
:
'GET'
,
url
:
`/temporarySearch/search-info/dBillStage`
,
})
}
}
\ No newline at end of file
src/components/base/DecreeOriginal/newOriginal.vue
0 → 100644
浏览文件 @
6b4028a9
<
template
>
<div
class=
"layout-container"
>
<div
class=
"layout-main"
>
<div
class=
"layout-main-center"
>
<div
class=
"report-header"
>
<div
class=
"report-title"
>
政令原文
</div>
<el-switch
v-model=
"isHighlight"
@
change=
"handleHighlight"
/>
<div
class=
"switch-label switch-label-left"
>
高亮实体
</div>
<el-switch
v-model=
"isTranslate"
@
change=
"handleTranslate"
/>
<div
class=
"switch-label"
>
译文显示
</div>
<div
class=
"btn"
@
click=
"emits('download')"
>
<div
class=
"icon icon-gap-4"
>
<img
src=
"./assets/icons/download.png"
alt=
""
/>
</div>
<div
class=
"text"
>
下载
</div>
</div>
<div
class=
"btn"
@
click=
"handleFindWord('open')"
>
<div
class=
"icon icon-gap-6"
>
<img
src=
"./assets/icons/search.png"
alt=
""
/>
</div>
<div
class=
"text"
>
查找
</div>
</div>
<div
class=
"find-word-box"
v-if=
"findWordBox"
>
<div
class=
"find-word-input"
>
<el-input
v-model=
"findWordTxt"
placeholder=
"查找原文内容"
@
input=
"handleUpdateWord"
/>
</div>
<div
class=
"find-word-limit"
>
{{
findWordNum
}}
/
{{
findWordMax
}}
</div>
<div
class=
"find-word-icon"
@
click=
"handleFindWord('last')"
>
<el-icon><ArrowUp
/></el-icon>
</div>
<div
class=
"find-word-icon"
@
click=
"handleFindWord('next')"
>
<el-icon><ArrowDown
/></el-icon>
</div>
<div
class=
"find-word-icon"
@
click=
"handleFindWord('close')"
>
<el-icon><Close
/></el-icon>
</div>
</div>
</div>
<div
:class=
"['report-main',
{'is-highlight': isHighlight}]">
<div
v-if=
"!formatData.length"
class=
"no-content"
>
暂无数据
</div>
<el-scrollbar
v-else
height=
"100%"
>
<div
v-for=
"(item, index) in formatData"
:key=
"index"
class=
"content-row"
>
<div
class=
"content-en"
:class=
"
{ 'only-show': !isTranslate }">
<template
v-for=
"(node, num) in item.contentEn"
:key=
"num"
>
<el-icon
v-if=
"node.icon && isHighlight"
color=
"#508fd4"
size=
"14"
><Search
/></el-icon>
<span
v-else-if=
"node.point"
class=
"find-light-point"
></span>
<span
v-else-if=
"node.fill"
:class=
"node.class"
@
click=
"handleHighLight(node)"
>
{{
node
.
txt
}}
</span>
<span
v-else
:class=
"node.class"
>
{{
node
.
txt
}}
</span>
</
template
>
</div>
<div
class=
"content-ch"
v-if=
"isTranslate"
>
<
template
v-for=
"(node, num) in item.contentCh"
:key=
"num"
>
<el-icon
v-if=
"node.icon && isHighlight"
color=
"#508fd4"
size=
"14"
><Search
/></el-icon>
<span
v-else-if=
"node.point"
class=
"find-light-point"
></span>
<span
v-else-if=
"node.fill"
:class=
"node.class"
@
click=
"handleHighLight(node)"
>
{{
node
.
txt
}}
</span>
<span
v-else
:class=
"node.class"
>
{{
node
.
txt
}}
</span>
</
template
>
</div>
</div>
</el-scrollbar>
</div>
</div>
</div>
</div>
</template>
<
script
setup
>
import
{
nextTick
,
ref
}
from
"vue"
;
import
{
debounce
}
from
"lodash"
;
import
{
extractTextEntity
}
from
"@/api/intelligent"
;
const
emits
=
defineEmits
([
"download"
]);
const
isHighlight
=
ref
(
true
);
// 是否高亮实体
const
isTranslate
=
ref
(
true
);
// 是否显示译文
const
handleTranslate
=
()
=>
{
if
(
findWordTxt
.
value
?.
trim
())
handleUpdateWord
()
}
const
findWordTxt
=
ref
(
""
);
const
findWordBox
=
ref
(
false
);
const
findWordNum
=
ref
(
0
);
const
findWordMax
=
ref
(
0
);
const
formatData
=
ref
([])
const
handleUpdateWord
=
debounce
(()
=>
{
findWordNum
.
value
=
0
;
findWordMax
.
value
=
0
;
formatData
.
value
=
originData
.
map
(
item
=>
{
return
{
contentEn
:
onHighlightedText
(
item
.
contentEn
,
keywordEn
),
contentCh
:
isTranslate
.
value
?
onHighlightedText
(
item
.
contentCh
,
keywordCh
)
:
[],
}
})
if
(
findWordMax
.
value
)
{
findWordNum
.
value
=
1
;
nextTick
(
updateActiveHighlight
)
}
},
300
);
function
handleFindWord
(
event
)
{
switch
(
event
)
{
case
"open"
:
findWordBox
.
value
=
true
;
break
;
case
"last"
:
if
(
findWordMax
.
value
>
1
)
{
findWordNum
.
value
=
findWordNum
.
value
===
1
?
findWordMax
.
value
:
findWordNum
.
value
-
1
;
updateActiveHighlight
();
}
break
;
case
"next"
:
if
(
findWordMax
.
value
>
1
)
{
findWordNum
.
value
=
findWordNum
.
value
===
findWordMax
.
value
?
1
:
findWordNum
.
value
+
1
;
updateActiveHighlight
();
}
break
;
case
"close"
:
findWordBox
.
value
=
false
;
findWordTxt
.
value
=
""
;
handleUpdateWord
();
break
;
}
}
const
updateActiveHighlight
=
()
=>
{
if
(
!
findWordNum
.
value
)
return
const
spans
=
document
.
querySelectorAll
(
"span.find-light-point"
);
spans
.
forEach
((
span
,
index
)
=>
{
if
(
index
+
1
===
findWordNum
.
value
)
span
.
scrollIntoView
({});
});
}
// 政令原文信息
let
originData
=
[]
let
keywordCh
=
[]
let
keywordEn
=
[]
const
setOriginalData
=
(
data
)
=>
{
originData
=
[]
let
num
=
Math
.
max
(
data
.
content
.
length
,
data
.
contentEn
.
length
)
for
(
let
i
=
0
;
i
<
num
;
i
++
)
{
let
obj
=
{
contentCh
:
data
.
content
[
i
]
||
""
,
contentEn
:
data
.
contentEn
[
i
]
||
""
,
}
originData
.
push
(
obj
);
}
let
allEn
=
""
let
allCh
=
""
formatData
.
value
=
originData
.
map
(
item
=>
{
allEn
+=
item
.
contentEn
+
"。"
allCh
+=
item
.
contentCh
+
"。"
return
{
contentEn
:
[{
txt
:
item
.
contentEn
,
class
:
""
}],
contentCh
:
[{
txt
:
item
.
contentCh
,
class
:
""
}]
}
})
extractTextEntity
(
allEn
||
""
).
then
(
res
=>
{
if
(
res
?.
result
?.
length
)
keywordEn
=
res
.
result
||
[]
originData
.
forEach
((
item
,
index
)
=>
{
formatData
.
value
[
index
].
contentEn
=
onHighlightedText
(
item
.
contentEn
,
keywordEn
);
})
})
extractTextEntity
(
allCh
||
""
).
then
(
res
=>
{
if
(
res
?.
result
?.
length
)
keywordCh
=
res
.
result
||
[]
if
(
isTranslate
.
value
)
{
originData
.
forEach
((
item
,
index
)
=>
{
formatData
.
value
[
index
].
contentCh
=
onHighlightedText
(
item
.
contentCh
,
keywordCh
);
})
}
})
}
defineExpose
({
setOriginalData
})
// 文本分割
const
onHighlightedText
=
(
text
,
nounList
)
=>
{
if
(
text
===
""
)
return
[]
// 获取区间(合并相邻/重叠),并自动过滤空关键词
const
getIntervals
=
(
str
,
keywords
)
=>
{
const
intervals
=
[];
for
(
const
kw
of
keywords
)
{
if
(
!
kw
)
continue
;
// 跳过空字符串,防止无限循环
let
idx
=
0
;
while
((
idx
=
str
.
indexOf
(
kw
,
idx
))
!==
-
1
)
{
intervals
.
push
({
start
:
idx
,
end
:
idx
+
kw
.
length
});
idx
+=
kw
.
length
;
}
}
if
(
!
intervals
.
length
)
return
[];
intervals
.
sort
((
a
,
b
)
=>
a
.
start
-
b
.
start
);
const
merged
=
[
intervals
[
0
]];
for
(
let
i
=
1
;
i
<
intervals
.
length
;
i
++
)
{
const
prev
=
merged
[
merged
.
length
-
1
];
const
curr
=
intervals
[
i
];
if
(
curr
.
start
<=
prev
.
end
)
{
prev
.
end
=
Math
.
max
(
prev
.
end
,
curr
.
end
);
}
else
{
merged
.
push
(
curr
);
}
}
return
merged
;
};
// 处理空搜索文本
let
textTrim
=
findWordTxt
.
value
.
trim
()
||
""
;
const
searchIntervals
=
textTrim
?
getIntervals
(
text
,
[
textTrim
])
:
[];
const
nounIntervals
=
getIntervals
(
text
,
nounList
.
map
(
n
=>
n
.
text_span
));
// 收集分割点
const
points
=
new
Set
([
0
,
text
.
length
]);
[...
searchIntervals
,
...
nounIntervals
].
forEach
(({
start
,
end
})
=>
{
points
.
add
(
start
);
points
.
add
(
end
);
});
const
sortedPoints
=
Array
.
from
(
points
).
sort
((
a
,
b
)
=>
a
-
b
);
const
list
=
[];
for
(
let
i
=
0
;
i
<
sortedPoints
.
length
-
1
;
i
++
)
{
const
start
=
sortedPoints
[
i
];
const
end
=
sortedPoints
[
i
+
1
];
if
(
start
===
end
)
continue
;
const
fragment
=
text
.
slice
(
start
,
end
);
const
findLight
=
searchIntervals
.
some
(
s
=>
start
>=
s
.
start
&&
end
<=
s
.
end
);
const
highLight
=
nounIntervals
.
some
(
n
=>
start
>=
n
.
start
&&
end
<=
n
.
end
);
const
classes
=
[];
if
(
findLight
)
classes
.
push
(
"find-light"
);
if
(
highLight
)
classes
.
push
(
"high-light"
);
const
textItem
=
{
txt
:
fragment
,
class
:
classes
.
join
(
" "
)
};
if
(
highLight
)
{
const
nounInterval
=
nounIntervals
.
find
(
n
=>
start
>=
n
.
start
&&
end
<=
n
.
end
);
if
(
nounInterval
)
{
textItem
.
fill
=
text
.
slice
(
nounInterval
.
start
,
nounInterval
.
end
);
}
}
list
.
push
(
textItem
);
// 实体区间结束后添加图标
const
iconAdded
=
new
Set
();
for
(
const
nounInterval
of
nounIntervals
)
{
const
key
=
`
${
nounInterval
.
start
}
-
${
nounInterval
.
end
}
`
;
if
(
end
===
nounInterval
.
end
&&
!
iconAdded
.
has
(
key
))
{
list
.
push
({
icon
:
true
,
class
:
""
});
iconAdded
.
add
(
key
);
break
;
}
}
// 搜索区间结束后添加锚点
const
pointAdded
=
new
Set
();
for
(
const
searchInterval
of
searchIntervals
)
{
const
key
=
`
${
searchInterval
.
start
}
-
${
searchInterval
.
end
}
`
;
if
(
end
===
searchInterval
.
end
&&
!
pointAdded
.
has
(
key
))
{
findWordMax
.
value
++
;
list
.
push
({
point
:
true
,
class
:
""
});
pointAdded
.
add
(
key
);
break
;
}
}
}
return
list
;
};
// 点击高亮实体
import
{
useGotoSearchResults
}
from
"@/router/modules/comprehensiveSearch"
;
const
gotoSearchResults
=
useGotoSearchResults
();
const
handleHighLight
=
(
node
)
=>
{
gotoSearchResults
(
node
.
fill
,
''
)
}
</
script
>
<
style
lang=
"scss"
scoped
>
.is-highlight
.high-light
{
color
:
var
(
--
color-primary-100
);
cursor
:
pointer
;
}
.find-light
{
background-color
:
#ffff00
;
}
.layout-container
{
width
:
100%
;
height
:
100%
;
background-color
:
#f7f8f9
;
.layout-main
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
.layout-main-center
{
width
:
1600px
;
background-color
:
white
;
padding
:
0
60px
;
flex
:
auto
;
height
:
100%
;
min-height
:
0
;
display
:
flex
;
flex-direction
:
column
;
.report-header
{
height
:
80px
;
display
:
flex
;
align-items
:
center
;
border-bottom
:
solid
1px
rgba
(
234
,
236
,
238
,
1
);
margin
:
0
20px
10px
;
position
:
relative
;
.find-word-box
{
position
:
absolute
;
top
:
-50px
;
right
:
0px
;
width
:
430px
;
height
:
60px
;
border
:
1px
solid
rgba
(
230
,
231
,
232
,
1
);
background-color
:
white
;
border-radius
:
6px
;
display
:
flex
;
align-items
:
center
;
.find-word-input
{
flex
:
auto
;
}
.find-word-limit
{
border-right
:
solid
1px
rgba
(
230
,
231
,
232
,
1
);
color
:
#5f656c
;
padding-right
:
16px
;
}
.find-word-icon
{
padding
:
10px
12px
;
margin
:
0
2px
;
cursor
:
pointer
;
}
}
.report-title
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
20px
;
line-height
:
20px
;
font-weight
:
700
;
flex
:
1
;
}
.btn
{
margin-left
:
10px
;
width
:
88px
;
height
:
32px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
230
,
231
,
232
,
1
);
border-radius
:
6px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
cursor
:
pointer
;
.text
{
height
:
24px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-style
:
Regular
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
.icon
{
width
:
16px
;
height
:
16px
;
font-size
:
0px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.icon-gap-4
{
margin-right
:
4px
;
}
.icon-gap-6
{
margin-right
:
6px
;
}
}
}
.report-main
{
flex
:
auto
;
height
:
20px
;
padding
:
10px
0
;
:deep
(
.el-scrollbar
)
{
height
:
100%
;
}
.no-content
{
height
:
100%
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-style
:
Regular
;
font-size
:
20px
;
font-weight
:
400
;
}
.content-row
{
display
:
flex
;
width
:
100%
;
padding
:
0
20px
;
min-height
:
100px
;
gap
:
80px
;
.content-en
,
.content-ch
{
width
:
50%
;
flex
:
auto
;
padding-bottom
:
40px
;
box-sizing
:
border-box
;
font-size
:
16px
;
line-height
:
1
.8
;
color
:
#3b414b
;
font-family
:
Microsoft
YaHei
;
text-align
:
justify
;
white-space
:
pre-wrap
;
}
.only-show
{
padding-bottom
:
10px
;
}
}
}
}
}
}
.switch-label
{
margin-left
:
6px
;
}
.switch-label-left
{
margin-right
:
10px
;
}
:deep
(
.el-scrollbar__bar.is-vertical
)
{
right
:
0px
;
width
:
4px
;
background
:
transparent
;
border-radius
:
2px
;
&
>
div
{
background
:
#c5c7c9
;
opacity
:
1
;
}
&
>
div
:hover
{
background
:
#505357
;
}
}
</
style
>
src/styles/bill-tokens.scss
0 → 100644
浏览文件 @
6b4028a9
// Bill layout & visual tokens
// 统一用于 bill 板块布局改造,后续可并入全局设计变量体系
// spacing
$bill-space-8
:
8px
;
$bill-space-12
:
12px
;
$bill-space-16
:
16px
;
$bill-space-24
:
24px
;
$bill-space-30
:
30px
;
// layout
$bill-column-gap
:
16px
;
$bill-left-column-width
:
1064px
;
$bill-right-column-width
:
520px
;
// typography
$bill-title-font-size
:
16px
;
$bill-title-font-weight
:
600
;
$bill-body-font-size
:
14px
;
$bill-body-font-weight
:
400
;
// surface
$bill-panel-radius
:
8px
;
$bill-panel-border-color
:
#e8ecf3
;
$bill-panel-shadow
:
0
2px
8px
rgba
(
15
,
35
,
95
,
0
.06
);
$bill-panel-bg
:
#ffffff
;
// text & color
$bill-text-primary
:
#1f2a44
;
$bill-text-secondary
:
#5b6b88
;
$bill-text-muted
:
#8b97ad
;
$bill-color-accent
:
#2f66ff
;
$bill-color-success
:
#19be6b
;
$bill-color-warning
:
#ff9f43
;
$bill-color-danger
:
#f56c6c
;
src/views/bill/BILL_LAYOUT_UNIFICATION_PLAN.md
0 → 100644
浏览文件 @
6b4028a9
# Bill 板块布局统一改造计划
> 目标:统一 `@src/views/bill` 下页面布局与视觉风格,解决“底部 30px 留白不稳定”问题,并沉淀可复用布局组件,便于后续新会话直接接续执行。
## 1. 背景与问题
当前
`bill`
板块存在以下共性问题:
1.
页面布局实现不统一(外层滚动、内层滚动、固定高度混用)。
2.
多数页面为“左右两列 + 多卡片”结构,但容器命名、间距、宽高策略不一致。
3.
`30px`
底部留白在不同页面生效机制不同,容易出现:
-
某页不生效
-
增加占位后挤压布局
-
Header(Tab/操作按钮)受影响
4.
样式硬编码较多(固定宽高、局部 margin/padding),复用性低。
## 2. 总体改造策略
采用“
**分层统一 + 渐进迁移**
”策略,避免一次性大改风险:
-
**第一层:板块承载层统一**
-
统一滚动、内容宽度、底部安全留白机制。
-
**第二层:页面布局骨架统一**
-
抽象“页面壳 + 双列布局 + 卡片容器”组件。
-
**第三层:业务页迁移**
-
先迁移典型页,再批量替换。
## 3. 分阶段计划
### 阶段 A:基线确认与止血(进行中)
-
修复当前试错引入的结构问题(例如模板闭合错误、布局挤压)。
-
保证关键页面可用:
-
`background`
-
`processAnalysis`
-
`introdoction`
### 阶段 B:新增通用布局组件(进行中)
#### 完成备注(2026-04-02)
-
[
x
]
第一步已完成并通过验收:完成布局组件目录与基础文件脚手架
-
`src/views/bill/components/layout/BillPageShell.vue`
-
`src/views/bill/components/layout/BillTwoColumn.vue`
-
`src/views/bill/components/layout/BillPanel.vue`
-
`src/views/bill/components/layout/index.js`
-
[
x
]
第二步已完成并通过验收:实现
`BillPageShell`
滚动容器与底部
`30px`
安全留白机制
-
[
x
]
第三步已完成并通过验收:实现
`BillTwoColumn`
统一双列布局(1064/520 + gap 16 + 响应式堆叠)
-
[
x
]
第四步已完成并通过验收:实现
`BillPanel`
统一卡片结构与基础样式(header/body/footer + 可配置边框/圆角/阴影)
-
[
x
]
第五步已完成并通过验收:
`bill-tokens.scss`
接入
`BillPageShell/BillTwoColumn/BillPanel`
并替换关键样式硬编码
-
[
x
]
第六步已完成并通过验收:试点页
`background/index.vue`
已迁移到统一布局骨架(
`BillPageShell + BillTwoColumn`
)
-
[
x
]
第六步修正项(验收反馈已落实):
-
修正 1:移除
`.right-panel`
的
`margin-left/margin-right`
,避免右列偏移与原样式不一致
-
修正 2:
`BillPageShell`
不再使用内部滚动容器;页面滚动回到外层
`layout-main`
,确保 Header 与内容一起滚动
-
[
x
]
第七步已完成并通过验收:
`introdoction/index.vue`
迁移到统一布局骨架(
`BillPageShell + BillTwoColumn`
)
-
[
x
]
第七步修正项(验收反馈已落实):
-
修正 1:移除
`.introduction-wrap-right`
的
`margin-left/margin-right`
,消除右列偏移
-
修正 2:在
`.introduction-wrap-content`
增加
`margin-bottom: 30px`
,确保外层滚动时可见底部留白
-
[
x
]
第八步已完成并通过验收:
`template/index.vue`
迁移到统一布局骨架(
`BillPageShell + BillTwoColumn`
)
-
[
x
]
第八步注意点(已沉淀):
-
删除
`page-bottom-gap`
占位节点,避免与统一留白策略重复
-
在双列容器
`.content-row`
增加
`margin-bottom: 30px`
,适配“外层
`layout-main`
滚动”模式
-
迁移后需检查未使用变量并清理,避免 lint 噪音影响后续页面迁移
-
[
x
]
第九步已完成并通过验收:
`deepDig/processOverview/index.vue`
迁移到统一页面壳(
`BillPageShell`
)
-
[
x
]
第九步注意点(已沉淀):
-
保留页面内部横向滚动容器(
`.main`
),仅替换页面根壳,避免时间轴布局回归风险
-
删除
`page-bottom-gap`
,改用页面容器底部留白(
`margin-bottom: 30px`
)适配外层滚动
-
[
x
]
第十步已完成并通过验收:
`deepDig/processAnalysis/index.vue`
迁移到统一页面壳(
`BillPageShell`
)
-
[
x
]
第十步注意点(已沉淀):
-
保持原双列业务结构与内部滚动策略不变,仅替换页面根壳
-
页面底部留白统一为容器
`margin-bottom: 30px`
,与外层
`layout-main`
滚动机制一致
新增组件建议放在:
`src/views/bill/components/layout/`
#### 计划新增组件索引
1.
`src/views/bill/components/layout/BillPageShell.vue`
-
作用:统一页面根容器、内容区、底部留白(30px)机制。
2.
`src/views/bill/components/layout/BillTwoColumn.vue`
-
作用:统一左右列布局(默认 1064 / 520)、列间距、响应式策略。
3.
`src/views/bill/components/layout/BillPanel.vue`
-
作用:统一卡片容器(header/body/footer)结构、间距、基础样式。
4.
`src/views/bill/components/layout/index.js`
-
作用:导出布局组件,便于页面统一引入。
> 可选(后续):
> - `BillPanelGroup.vue`(同列多卡片统一间距)
> - `BillPageSection.vue`(统一页面内 section 标题与辅助动作区)
### 阶段 C:样式 Token 统一(计划)
新增:
`src/styles/bill-tokens.scss`
(或接入现有变量体系)
-
间距:
`8/12/16/24/30`
-
列间距:
`16`
-
标题字号/字重
-
卡片边框、阴影、圆角
-
统一颜色 token(主文字、次文字、强调色)
### 阶段 D:页面迁移(计划)
按“先典型、后批量”执行:
1.
试点页(先迁移)
-
`background/index.vue`
(典型双列 + 卡片 + 多交互)
2.
法案概况组
-
`introdoction/index.vue`
-
`template/index.vue`
-
`background/index.vue`
3.
深度挖掘组
-
`deepDig/processOverview/index.vue`
-
`deepDig/processAnalysis/index.vue`
-
`deepDig/poliContribution/index.vue`
4.
影响分析组
-
`influence/industry/index.vue`
-
`influence/scientificResearch/index.vue`
-
`influence/index.vue`
(承载层)
### 阶段 E:收口与回归(计划)
-
清理临时样式补丁(历史试错
`gap/margin-bottom`
等)。
-
回归检查:
1.
所有页面底部留白可见
2.
无横向滚动条
3.
Header 不丢失
4.
双列不挤压
## 4. 现有页面索引(改造范围)
### 4.1 板块承载与导航层
-
`src/views/bill/billLayout/index.vue`
-
`src/views/bill/billLayout/components/BillHeader.vue`
-
`src/views/bill/index.vue`
-
`src/views/bill/deepDig/index.vue`
-
`src/views/bill/influence/index.vue`
### 4.2 法案概况(Bill)
-
`src/views/bill/introdoction/index.vue`
-
`src/views/bill/background/index.vue`
-
`src/views/bill/template/index.vue`
-
`src/views/bill/billOriginalText/index.vue`
### 4.3 深度挖掘(DeepDig)
-
`src/views/bill/deepDig/processOverview/index.vue`
-
`src/views/bill/deepDig/processAnalysis/index.vue`
-
`src/views/bill/deepDig/poliContribution/index.vue`
### 4.4 影响分析(Influence)
-
`src/views/bill/influence/industry/index.vue`
-
`src/views/bill/influence/scientificResearch/index.vue`
-
`src/views/bill/influence/ProgressForecast/index.vue`
### 4.5 其他相关页面
-
`src/views/bill/relevantCircumstance/index.vue`
-
`src/views/bill/versionCompare/index.vue`
-
`src/views/bill/billHome/index.vue`
## 5. 迁移原则(执行时必须遵守)
1.
不改变业务逻辑(API、状态、路由行为)
2.
先替换布局骨架,再替换样式细节
3.
每次只迁移少量页面,保证可回滚
4.
对“固定高度 + 内部滚动”页面优先保守改造
5.
若页面是横向 flex 主体,禁止直接插入会改变横向布局的占位节点
## 6. 验收标准
1.
`@bill`
目标页面滚动到底统一可见
`30px`
留白
2.
页面核心布局(左右列、卡片)不变形
3.
`BillHeader`
的 Tab 与功能按钮稳定显示
4.
不新增横向滚动条
5.
关键路由刷新后视觉一致
## 7. 新会话接续建议
新会话可直接按以下顺序继续:
1.
先读取本文件:
-
`src/views/bill/BILL_LAYOUT_UNIFICATION_PLAN.md`
2.
先完成组件脚手架:
-
`BillPageShell.vue`
-
`BillTwoColumn.vue`
-
`BillPanel.vue`
3.
首个迁移页:
-
`src/views/bill/background/index.vue`
4.
迁移完成后逐页扩展到
`introdoction/template/processOverview/processAnalysis`
---
最后更新:2026-04-02
src/views/bill/background/index.vue
浏览文件 @
6b4028a9
<
template
>
<
template
>
<div
class=
"background-wrap"
>
<BillPageShell
class=
"background-page"
>
<div
class=
"background-wrap-left"
>
<BillTwoColumn
class=
"background-content"
:stack-on-narrow=
"false"
>
<AnalysisBox
class=
"left-box left-box--background"
title=
"立法背景"
:showAllBtn=
"false"
:devTip=
"true"
>
<template
#
left
>
<template
#
header-btn
>
<div
class=
"background-wrap-left"
>
<div
class=
"header-btn-box"
>
<AnalysisBox
class=
"left-box left-box--background"
title=
"立法背景"
:showAllBtn=
"false"
:devTip=
"true"
>
<el-button
:type=
"box1Btn1Type"
plain
@
click=
"handleClickBox1Btn(1)"
>
涉华背景
</el-button>
<template
#
header-btn
>
<el-button
:type=
"box1Btn2Type"
plain
@
click=
"handleClickBox1Btn(2)"
>
全部背景
</el-button>
<div
class=
"header-btn-box"
>
</div>
<el-button
:type=
"box1Btn1Type"
plain
@
click=
"handleClickBox1Btn(1)"
>
涉华背景
</el-button>
</
template
>
<el-button
:type=
"box1Btn2Type"
plain
@
click=
"handleClickBox1Btn(2)"
>
全部背景
</el-button>
<div
class=
"box1-main"
v-loading=
"backgroundLoading"
>
</div>
<div
class=
"box1-main-center"
>
</
template
>
<div
class=
"box1-main-item"
v-for=
"item in backgroundDisplayList"
:key=
"item.id"
>
<div
class=
"box1-main"
v-loading=
"backgroundLoading"
>
<div
class=
"id"
>
{{ item.displayIndex }}
</div>
<div
class=
"box1-main-center"
>
<div
class=
"title"
>
{{ item.backgroundTitle }}
</div>
<div
class=
"box1-main-item"
v-for=
"item in backgroundDisplayList"
:key=
"item.id"
>
<div
class=
"share"
>
<div
class=
"id"
>
{{ item.displayIndex }}
</div>
<img
src=
"./assets/icons/open.png"
alt=
"打开"
/>
<div
class=
"title"
>
{{ item.backgroundTitle }}
</div>
<div
class=
"share"
>
<img
src=
"./assets/icons/open.png"
alt=
"打开"
/>
</div>
</div>
</div>
<div
class=
"box1-main-footer"
>
<div
class=
"info"
>
{{ totalText }}
</div>
<el-pagination
background
layout=
"prev, pager, next"
:total=
"total"
v-model:current-page=
"currentPage"
@
current-change=
"handleGetBillBackground"
/>
</div>
</div>
</div>
</div>
</div>
</AnalysisBox>
<div
class=
"box1-main-footer"
>
<div
class=
"info"
>
{{ totalText }}
</div>
<el-pagination
background
layout=
"prev, pager, next"
:total=
"total"
v-model:current-page=
"currentPage"
@
current-change=
"handleGetBillBackground"
/>
</div>
</div>
</AnalysisBox>
<AnalysisBox
class=
"left-box left-box--event"
title=
"相关事件"
:showAllBtn=
"false"
:devTip=
"true"
>
<AnalysisBox
class=
"left-box left-box--event"
title=
"相关事件"
:showAllBtn=
"false"
:devTip=
"true"
>
<div
class=
"box2-main"
>
<div
class=
"box2-main"
>
<div
class=
"box2-main-item"
v-for=
"item in eventDisplayList"
:key=
"item.id"
@
click=
"handleClickEvent(item)"
>
<div
class=
"box2-main-item"
v-for=
"item in eventDisplayList"
:key=
"item.id"
@
click=
"handleClickEvent(item)"
>
<div
class=
"left"
>
<div
class=
"left"
>
<img
:src=
"item.imgSrc"
@
error=
"handleNewsImgError"
alt=
""
/>
<img
:src=
"item.imgSrc"
@
error=
"handleNewsImgError"
alt=
""
/>
</div>
</div>
<div
class=
"center"
>
<div
class=
"center"
>
<CommonPrompt
:content=
"item.sjbt"
>
<CommonPrompt
:content=
"item.sjbt"
>
<div
class=
"title"
>
{{ item.sjbt }}
</div>
<div
class=
"title"
>
{{ item.sjbt }}
</div>
</CommonPrompt>
</CommonPrompt>
<CommonPrompt
:content=
"item.sjnr"
>
<CommonPrompt
:content=
"item.sjnr"
>
<div
class=
"content"
>
{{ item.sjnr }}
</div>
<div
class=
"content"
>
{{ item.sjnr }}
</div>
</CommonPrompt>
</CommonPrompt>
</div>
<div
class=
"right"
>
{{ item.sjsj }}
</div>
</div>
</div>
</div>
<div
class=
"right"
>
{{ item.sjsj }}
</div>
</AnalysisBox>
</div>
</div>
</AnalysisBox>
</div>
<AnalysisBox
class=
"right-panel"
title=
"议员相关性分析"
:showAllBtn=
"false"
:devTip=
"true"
>
<
template
#
header-btn
>
<div
class=
"header-btn-box"
>
<el-button
:type=
"box2Btn1Type"
plain
@
click=
"handleClickBox2Btn(1)"
>
赞成议员
</el-button>
<el-button
:type=
"box2Btn2Type"
plain
@
click=
"handleClickBox2Btn(2)"
>
反对议员
</el-button>
</div>
</div>
</template>
</template>
<div
class=
"background-wrap-right-main"
>
<div
class=
"right-box1"
>
<
template
#
right
>
<div
class=
"right-box1-main-top"
>
<AnalysisBox
class=
"right-panel"
title=
"议员相关性分析"
:showAllBtn=
"false"
:devTip=
"true"
>
<el-icon
class=
"nav-icon"
size=
"20"
:color=
"prevIconColor"
@
click=
"handlePrev"
>
<template
#
header-btn
>
<CaretLeft
/>
<div
class=
"header-btn-box"
>
</el-icon>
<el-button
:type=
"box2Btn1Type"
plain
@
click=
"handleClickBox2Btn(1)"
>
赞成议员
</el-button>
<div
class=
"user-list-container"
>
<el-button
:type=
"box2Btn2Type"
plain
@
click=
"handleClickBox2Btn(2)"
>
反对议员
</el-button>
<div
class=
"user-list-wrapper"
:style=
"userListWrapperStyle"
>
</div>
<div
class=
"user-box"
v-for=
"item in personList"
:key=
"item.id"
@
click=
"handleClickUser(item)"
>
</
template
>
<div
class=
"img-box"
>
<div
class=
"background-wrap-right-main"
>
<img
:src=
"item.image"
alt=
""
/>
<div
class=
"right-box1"
>
<div
class=
"icon1"
>
<div
class=
"right-box1-main-top"
>
<img
:src=
"item.icon"
alt=
""
/>
<el-icon
class=
"nav-icon"
size=
"20"
:color=
"prevIconColor"
@
click=
"handlePrev"
>
</div>
<CaretLeft
/>
<div
class=
"icon2"
>
</el-icon>
<img
:src=
"item.icon1"
alt=
""
/>
<div
class=
"user-list-container"
>
<div
class=
"user-list-wrapper"
:style=
"userListWrapperStyle"
>
<div
class=
"user-box"
v-for=
"item in personList"
:key=
"item.id"
@
click=
"handleClickUser(item)"
>
<div
class=
"img-box"
>
<img
:src=
"item.image"
alt=
""
/>
<div
class=
"icon1"
>
<img
:src=
"item.icon"
alt=
""
/>
</div>
<div
class=
"icon2"
>
<img
:src=
"item.icon1"
alt=
""
/>
</div>
</div>
<CommonPrompt
:content=
"item.name"
>
<div
class=
"name"
>
{{ item.name }}
</div>
</CommonPrompt>
</div>
</div>
</div>
</div>
<CommonPrompt
:content=
"item.name"
>
<div
class=
"name"
>
{{ item.name }}
</div>
</CommonPrompt>
</div>
</div>
<el-icon
class=
"nav-icon"
size=
"20"
:color=
"nextIconColor"
@
click=
"handleNext"
>
<CaretRight
/>
</el-icon>
</div>
<div
class=
"right-box1-main-bottom"
>
<WordCloudMap
:data=
"wordCloudData"
:selectedName=
"selectedIndustryName"
shape=
"circle"
@
wordClick=
"handleWordClick"
/>
</div>
</div>
</div>
</div>
<el-icon
class=
"nav-icon"
size=
"20"
:color=
"nextIconColor"
@
click=
"handleNext"
>
<div
class=
"right-box2"
>
<CaretRight
/>
<div
class=
"right-box2-header"
>
</el-icon>
<div
class=
"title"
>
</div>
<span
class=
"title-active"
>
"{{ selectedIndustryName }}"
</span>
涉及议员动态 >
<div
class=
"right-box1-main-bottom"
>
<WordCloudMap
:data=
"wordCloudData"
:selectedName=
"selectedIndustryName"
shape=
"circle"
@
wordClick=
"handleWordClick"
/>
</div>
</div>
<div
class=
"right-box2"
>
<div
class=
"right-box2-header"
>
<div
class=
"title"
>
<span
class=
"title-active"
>
"{{ selectedIndustryName }}"
</span>
涉及议员动态 >
</div>
</div>
<div
class=
"right-box2-center"
>
<div
class=
"user-box"
v-for=
"item in aboutUserList"
:key=
"item.id"
@
click=
"handleClickUser(item)"
>
<div
class=
"user-left"
>
<div
class=
"img-box"
>
<img
:src=
"item.img"
alt=
""
/>
</div>
</div>
</div>
</div>
<div
class=
"user-right"
>
<div
class=
"right-box2-center"
>
<div
class=
"name"
>
{{ item.name }}
</div>
<div
class=
"user-box"
v-for=
"item in aboutUserList"
:key=
"item.id"
@
click=
"handleClickUser(item)"
>
<CommonPrompt
:content=
"item.content"
>
<div
class=
"user-left"
>
<div
class=
"content"
>
{{ item.content }}
</div>
<div
class=
"img-box"
>
</CommonPrompt>
<img
:src=
"item.img"
alt=
""
/>
</div>
</div>
<div
class=
"user-right"
>
<div
class=
"name"
>
{{ item.name }}
</div>
<CommonPrompt
:content=
"item.content"
>
<div
class=
"content"
>
{{ item.content }}
</div>
</CommonPrompt>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</
div
>
</
AnalysisBox
>
</
div
>
</
template
>
</
AnalysisBox
>
</
BillTwoColumn
>
</
div
>
</
BillPageShell
>
</template>
</template>
<
script
setup
>
<
script
setup
>
...
@@ -119,6 +130,7 @@ import { computed, onMounted, ref } from "vue";
...
@@ -119,6 +130,7 @@ import { computed, onMounted, ref } from "vue";
import
{
useRoute
,
useRouter
}
from
"vue-router"
;
import
{
useRoute
,
useRouter
}
from
"vue-router"
;
import
WordCloudMap
from
"./WordCloudMap.vue"
;
import
WordCloudMap
from
"./WordCloudMap.vue"
;
import
CommonPrompt
from
"../commonPrompt/index.vue"
;
import
CommonPrompt
from
"../commonPrompt/index.vue"
;
import
{
BillPageShell
,
BillTwoColumn
}
from
"../components/layout"
;
import
userIcon
from
"./assets/icons/user-icon.png"
;
import
userIcon
from
"./assets/icons/user-icon.png"
;
import
userIcon1
from
"./assets/icons/user-icon1.png"
;
import
userIcon1
from
"./assets/icons/user-icon1.png"
;
import
userIcon2
from
"./assets/icons/user-icon2.png"
;
import
userIcon2
from
"./assets/icons/user-icon2.png"
;
...
@@ -400,16 +412,31 @@ onMounted(() => {
...
@@ -400,16 +412,31 @@ onMounted(() => {
}
}
}
}
.background-
wrap
{
.background-
page
{
width
:
100%
;
width
:
100%
;
height
:
100%
;
height
:
100%
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
display
:
flex
;
}
.background-content
{
width
:
100%
;
height
:
auto
;
box-sizing
:
border-box
;
align-items
:
flex-start
;
align-items
:
flex-start
;
:deep
(
.bill-two-column__left
)
{
width
:
1064px
;
}
:deep
(
.bill-two-column__right
)
{
width
:
520px
;
margin-right
:
18px
;
}
.background-wrap-left
{
.background-wrap-left
{
width
:
1064px
;
width
:
1064px
;
margin-top
:
16px
;
margin-top
:
16px
;
margin-bottom
:
30px
;
.left-box
{
.left-box
{
width
:
1064px
;
width
:
1064px
;
...
@@ -600,9 +627,8 @@ onMounted(() => {
...
@@ -600,9 +627,8 @@ onMounted(() => {
}
}
}
}
.right-panel
{
.right-panel
{
margin-right
:
18px
;
margin-left
:
16px
;
margin-top
:
16px
;
margin-top
:
16px
;
width
:
520px
;
width
:
520px
;
max-height
:
824px
;
max-height
:
824px
;
...
...
src/views/bill/billLayout/components/BillHeader.vue
浏览文件 @
6b4028a9
...
@@ -61,7 +61,7 @@
...
@@ -61,7 +61,7 @@
</div>
</div>
<div
class=
"right-box-bottom"
v-if=
"showActions"
>
<div
class=
"right-box-bottom"
v-if=
"showActions"
>
<div
class=
"btn2"
@
click=
"emit('open-analysis', 'forsee')"
>
<div
class=
"btn2"
v-if=
"showForsee"
@
click=
"emit('open-analysis', 'forsee')"
>
<div
class=
"icon"
>
<div
class=
"icon"
>
<img
:src=
"btnIconForsee"
alt=
""
/>
<img
:src=
"btnIconForsee"
alt=
""
/>
</div>
</div>
...
@@ -108,6 +108,10 @@ const props = defineProps({
...
@@ -108,6 +108,10 @@ const props = defineProps({
showActions
:
{
showActions
:
{
type
:
Boolean
,
type
:
Boolean
,
default
:
true
default
:
true
},
showForsee
:
{
type
:
Boolean
,
default
:
true
}
}
});
});
...
@@ -154,9 +158,7 @@ const emit = defineEmits(["tab-click", "open-analysis"]);
...
@@ -154,9 +158,7 @@ const emit = defineEmits(["tab-click", "open-analysis"]);
}
}
.header-main
{
.header-main
{
position
:
sticky
;
position
:
relative
;
top
:
0
;
z-index
:
1000
;
width
:
100%
;
width
:
100%
;
background-color
:
#fff
;
background-color
:
#fff
;
box-shadow
:
0px
4px
10px
0px
rgba
(
0
,
0
,
0
,
0
.05
);
box-shadow
:
0px
4px
10px
0px
rgba
(
0
,
0
,
0
,
0
.05
);
...
...
src/views/bill/billLayout/index.vue
浏览文件 @
6b4028a9
...
@@ -4,7 +4,8 @@
...
@@ -4,7 +4,8 @@
<div
class=
"layout-main"
>
<div
class=
"layout-main"
>
<BillHeader
:billInfo=
"billInfoGlobal"
:defaultLogo=
"USALogo"
:tabs=
"mainHeaderBtnList"
<BillHeader
:billInfo=
"billInfoGlobal"
:defaultLogo=
"USALogo"
:tabs=
"mainHeaderBtnList"
:activeTitle=
"activeTitle"
:showTabs=
"showHeaderTabs"
:showActions=
"showHeaderActions"
:activeTitle=
"activeTitle"
:showTabs=
"showHeaderTabs"
:showActions=
"showHeaderActions"
@
tab-click=
"handleClickMainHeaderBtn"
@
open-analysis=
"handleAnalysisClick"
/>
:showForsee=
"showForseeAction"
@
tab-click=
"handleClickMainHeaderBtn"
@
open-analysis=
"handleAnalysisClick"
/>
<div
class=
"layout-main-center"
>
<div
class=
"layout-main-center"
>
<router-view
/>
<router-view
/>
...
@@ -14,10 +15,10 @@
...
@@ -14,10 +15,10 @@
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
,
watch
}
from
"vue"
;
import
{
ref
,
onMounted
,
watch
,
computed
}
from
"vue"
;
import
router
from
"@/router"
;
import
router
from
"@/router"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
getBillInfoGlobal
}
from
"@/api/bill"
;
import
{
getBillInfoGlobal
,
getBillInfo
}
from
"@/api/bill"
;
import
BillHeader
from
"./components/BillHeader.vue"
;
import
BillHeader
from
"./components/BillHeader.vue"
;
const
route
=
useRoute
();
const
route
=
useRoute
();
...
@@ -77,6 +78,25 @@ const activeTitle = ref("法案概况");
...
@@ -77,6 +78,25 @@ const activeTitle = ref("法案概况");
const
showHeaderTabs
=
ref
(
true
);
const
showHeaderTabs
=
ref
(
true
);
const
showHeaderActions
=
ref
(
true
);
const
showHeaderActions
=
ref
(
true
);
const
billBasicInfo
=
ref
({});
const
getBillBasicInfoFn
=
async
()
=>
{
const
billId
=
route
.
query
.
billId
;
if
(
!
billId
)
return
;
try
{
const
res
=
await
getBillInfo
({
id
:
billId
});
billBasicInfo
.
value
=
res
?.
data
||
{};
}
catch
(
error
)
{
console
.
error
(
error
);
billBasicInfo
.
value
=
{};
}
};
const
showForseeAction
=
computed
(()
=>
{
const
stageList
=
Array
.
isArray
(
billBasicInfo
.
value
?.
stageList
)
?
billBasicInfo
.
value
.
stageList
:
[];
const
latestStage
=
stageList
.
length
?
String
(
stageList
[
stageList
.
length
-
1
]
||
""
).
trim
()
:
""
;
return
!
latestStage
.
includes
(
"完成立法"
);
});
const
getActiveTitleByRoutePath
=
path
=>
{
const
getActiveTitleByRoutePath
=
path
=>
{
if
(
path
.
startsWith
(
"/billLayout/deepDig"
))
return
"深度挖掘"
;
if
(
path
.
startsWith
(
"/billLayout/deepDig"
))
return
"深度挖掘"
;
if
(
path
.
startsWith
(
"/billLayout/influence"
))
return
"影响分析"
;
if
(
path
.
startsWith
(
"/billLayout/influence"
))
return
"影响分析"
;
...
@@ -132,6 +152,7 @@ const handleAnalysisClick = analysisType => {
...
@@ -132,6 +152,7 @@ const handleAnalysisClick = analysisType => {
onMounted
(()
=>
{
onMounted
(()
=>
{
getBillInfoGlobalFn
();
getBillInfoGlobalFn
();
getBillBasicInfoFn
();
// 以当前路由为准,避免 sessionStorage 造成高亮错乱
// 以当前路由为准,避免 sessionStorage 造成高亮错乱
syncHeaderStateFromRoute
();
syncHeaderStateFromRoute
();
// 兜底:如果未来出现未知路由且有缓存,再用缓存
// 兜底:如果未来出现未知路由且有缓存,再用缓存
...
@@ -143,6 +164,14 @@ watch(
...
@@ -143,6 +164,14 @@ watch(
()
=>
route
.
path
,
()
=>
route
.
path
,
()
=>
{
()
=>
{
syncHeaderStateFromRoute
();
syncHeaderStateFromRoute
();
}
);
watch
(
()
=>
route
.
query
.
billId
,
()
=>
{
getBillInfoGlobalFn
();
getBillBasicInfoFn
();
},
},
{
immediate
:
true
}
{
immediate
:
true
}
);
);
...
@@ -160,12 +189,12 @@ watch(
...
@@ -160,12 +189,12 @@ watch(
width
:
100%
;
width
:
100%
;
height
:
100vh
;
height
:
100vh
;
overflow-y
:
auto
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
.layout-main-center
{
.layout-main-center
{
// height: calc(100% - 137px);
width
:
1600px
;
width
:
1600px
;
max-width
:
100%
;
margin
:
0
auto
;
margin
:
0
auto
;
padding-bottom
:
20px
;
}
}
}
}
}
}
...
...
src/views/bill/components/layout/BillPageShell.vue
0 → 100644
浏览文件 @
6b4028a9
<
template
>
<div
class=
"bill-page-shell"
:class=
"shellClass"
:style=
"shellStyle"
>
<div
class=
"bill-page-shell__content"
:class=
"contentClass"
>
<slot
/>
</div>
</div>
</
template
>
<
script
>
const
BILL_DEFAULT_BOTTOM_SAFE_SPACE
=
30
export
default
{
name
:
'BillPageShell'
,
props
:
{
bottomSafeSpace
:
{
type
:
Number
,
default
:
BILL_DEFAULT_BOTTOM_SAFE_SPACE
},
shellClass
:
{
type
:
[
String
,
Array
,
Object
],
default
:
''
},
contentClass
:
{
type
:
[
String
,
Array
,
Object
],
default
:
''
}
},
computed
:
{
shellStyle
()
{
return
{
paddingBottom
:
`
${
this
.
bottomSafeSpace
}
px`
}
}
}
}
</
script
>
<
style
scoped
lang=
"scss"
>
@import
'@/styles/bill-tokens.scss'
;
.bill-page-shell
{
width
:
100%
;
min-height
:
0
;
box-sizing
:
border-box
;
}
.bill-page-shell__content
{
width
:
100%
;
color
:
$bill-text-primary
;
}
</
style
>
src/views/bill/components/layout/BillPanel.vue
0 → 100644
浏览文件 @
6b4028a9
<
template
>
<section
class=
"bill-panel"
:class=
"panelClass"
:style=
"panelStyle"
>
<header
v-if=
"$slots.header"
class=
"bill-panel__header"
:class=
"headerClass"
:style=
"sectionStyle"
>
<slot
name=
"header"
/>
</header>
<div
class=
"bill-panel__body"
:class=
"bodyClass"
:style=
"sectionStyle"
>
<slot
/>
</div>
<footer
v-if=
"$slots.footer"
class=
"bill-panel__footer"
:class=
"footerClass"
:style=
"sectionStyle"
>
<slot
name=
"footer"
/>
</footer>
</section>
</
template
>
<
script
>
const
BILL_DEFAULT_PANEL_PADDING
=
16
const
BILL_DEFAULT_PANEL_RADIUS
=
8
export
default
{
name
:
'BillPanel'
,
props
:
{
panelClass
:
{
type
:
[
String
,
Array
,
Object
],
default
:
''
},
headerClass
:
{
type
:
[
String
,
Array
,
Object
],
default
:
''
},
bodyClass
:
{
type
:
[
String
,
Array
,
Object
],
default
:
''
},
footerClass
:
{
type
:
[
String
,
Array
,
Object
],
default
:
''
},
padding
:
{
type
:
Number
,
default
:
BILL_DEFAULT_PANEL_PADDING
},
borderRadius
:
{
type
:
Number
,
default
:
BILL_DEFAULT_PANEL_RADIUS
},
bordered
:
{
type
:
Boolean
,
default
:
true
},
shadow
:
{
type
:
Boolean
,
default
:
false
},
background
:
{
type
:
String
,
default
:
'#fff'
}
},
computed
:
{
panelStyle
()
{
return
{
background
:
this
.
background
,
borderRadius
:
`
${
this
.
borderRadius
}
px`
,
border
:
this
.
bordered
?
'1px solid #e8ecf3'
:
'none'
,
boxShadow
:
this
.
shadow
?
'0 2px 8px rgba(15, 35, 95, 0.06)'
:
'none'
}
},
sectionStyle
()
{
return
{
padding
:
`
${
this
.
padding
}
px`
}
}
}
}
</
script
>
<
style
scoped
lang=
"scss"
>
@import
'@/styles/bill-tokens.scss'
;
.bill-panel
{
width
:
100%
;
box-sizing
:
border-box
;
color
:
$bill-text-primary
;
}
.bill-panel__header
,
.bill-panel__body
,
.bill-panel__footer
{
width
:
100%
;
box-sizing
:
border-box
;
}
.bill-panel__header
{
padding-bottom
:
$bill-space-12
;
}
.bill-panel__footer
{
padding-top
:
$bill-space-12
;
}
.bill-panel__header
:empty
,
.bill-panel__footer
:empty
{
display
:
none
;
}
</
style
>
src/views/bill/components/layout/BillTwoColumn.vue
0 → 100644
浏览文件 @
6b4028a9
<
template
>
<div
class=
"bill-two-column"
:class=
"wrapperClass"
:style=
"wrapperStyle"
>
<div
class=
"bill-two-column__left"
:style=
"leftStyle"
>
<slot
name=
"left"
/>
</div>
<div
class=
"bill-two-column__right"
:style=
"rightStyle"
>
<slot
name=
"right"
/>
</div>
</div>
</
template
>
<
script
>
const
BILL_DEFAULT_LEFT_WIDTH
=
1064
const
BILL_DEFAULT_RIGHT_WIDTH
=
520
const
BILL_DEFAULT_COLUMN_GAP
=
16
const
BILL_DEFAULT_MIN_STACK_WIDTH
=
1660
export
default
{
name
:
'BillTwoColumn'
,
props
:
{
leftWidth
:
{
type
:
Number
,
default
:
BILL_DEFAULT_LEFT_WIDTH
},
rightWidth
:
{
type
:
Number
,
default
:
BILL_DEFAULT_RIGHT_WIDTH
},
gap
:
{
type
:
Number
,
default
:
BILL_DEFAULT_COLUMN_GAP
},
minStackWidth
:
{
type
:
Number
,
default
:
BILL_DEFAULT_MIN_STACK_WIDTH
},
stackOnNarrow
:
{
type
:
Boolean
,
default
:
true
},
wrapperClass
:
{
type
:
[
String
,
Array
,
Object
],
default
:
''
}
},
computed
:
{
shouldStack
()
{
if
(
!
this
.
stackOnNarrow
||
typeof
window
===
'undefined'
)
{
return
false
}
return
window
.
innerWidth
<
this
.
minStackWidth
},
wrapperStyle
()
{
if
(
this
.
shouldStack
)
{
return
{
display
:
'flex'
,
flexDirection
:
'column'
,
gap
:
`
${
this
.
gap
}
px`
}
}
return
{
display
:
'grid'
,
gridTemplateColumns
:
`
${
this
.
leftWidth
}
px
${
this
.
rightWidth
}
px`
,
columnGap
:
`
${
this
.
gap
}
px`
,
alignItems
:
'start'
}
},
leftStyle
()
{
if
(
this
.
shouldStack
)
{
return
{
width
:
'100%'
}
}
return
{
minWidth
:
'0'
}
},
rightStyle
()
{
if
(
this
.
shouldStack
)
{
return
{
width
:
'100%'
}
}
return
{
minWidth
:
'0'
}
}
}
}
</
script
>
<
style
scoped
lang=
"scss"
>
@import
'@/styles/bill-tokens.scss'
;
.bill-two-column
{
width
:
100%
;
min-width
:
0
;
color
:
$bill-text-primary
;
}
.bill-two-column__left
,
.bill-two-column__right
{
min-width
:
0
;
}
</
style
>
src/views/bill/components/layout/index.js
0 → 100644
浏览文件 @
6b4028a9
import
BillPageShell
from
'./BillPageShell.vue'
import
BillTwoColumn
from
'./BillTwoColumn.vue'
import
BillPanel
from
'./BillPanel.vue'
export
{
BillPageShell
,
BillTwoColumn
,
BillPanel
}
src/views/bill/deepDig/processAnalysis/index.vue
浏览文件 @
6b4028a9
<
template
>
<
template
>
<
div
class=
"wrap"
>
<
BillPageShell
class=
"wrap"
>
<div
class=
"left"
>
<div
class=
"left"
>
<div
class=
"box1"
>
<div
class=
"box1"
>
<!--
<div
class=
"box-header"
>
<!--
<div
class=
"box-header"
>
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
</div>
</div>
</div>
</div>
</div>
-->
</div>
-->
<AnalysisBox
title=
"典型阶段耗时"
>
<AnalysisBox
title=
"典型阶段耗时
分析
"
>
<div
class=
"analysis-ai-wrapper analysis-ai-wrapper--box1"
>
<div
class=
"analysis-ai-wrapper analysis-ai-wrapper--box1"
>
<div
class=
"box1-main"
:class=
"
{ 'box1-main--full': !timeFooterText }">
<div
class=
"box1-main"
:class=
"
{ 'box1-main--full': !timeFooterText }">
<div
class=
"box1-main-center"
id=
"chart1"
></div>
<div
class=
"box1-main-center"
id=
"chart1"
></div>
...
@@ -48,7 +48,7 @@
...
@@ -48,7 +48,7 @@
</div>
</div>
</div>
</div>
<div
v-if=
"!aiPaneVisible.box1"
class=
"analysis-ai-tip-row"
>
<div
v-if=
"!aiPaneVisible.box1"
class=
"analysis-ai-tip-row"
>
<TipTab
class=
"analysis-ai-tip"
/>
<TipTab
class=
"analysis-ai-tip"
:text=
"'与历史同类法案的典型阶段耗时对比分析,数据来源:美国国会官网'"
/>
<AiButton
class=
"analysis-ai-tip-action"
@
mouseenter=
"handleShowAiPane('box1')"
/>
<AiButton
class=
"analysis-ai-tip-action"
@
mouseenter=
"handleShowAiPane('box1')"
/>
</div>
</div>
<div
v-if=
"aiPaneVisible.box1"
class=
"analysis-ai-pane"
@
mouseleave=
"handleHideAiPane('box1')"
>
<div
v-if=
"aiPaneVisible.box1"
class=
"analysis-ai-pane"
@
mouseleave=
"handleHideAiPane('box1')"
>
...
@@ -105,7 +105,7 @@
...
@@ -105,7 +105,7 @@
</div>
</div>
</div>
</div>
<div
v-if=
"!aiPaneVisible.box2"
class=
"analysis-ai-tip-row"
>
<div
v-if=
"!aiPaneVisible.box2"
class=
"analysis-ai-tip-row"
>
<TipTab
class=
"analysis-ai-tip"
/>
<TipTab
class=
"analysis-ai-tip"
:text=
"'与历史同类法案的修正案次数对比分析,数据来源:美国国会官网'"
/>
<AiButton
class=
"analysis-ai-tip-action"
@
mouseenter=
"handleShowAiPane('box2')"
/>
<AiButton
class=
"analysis-ai-tip-action"
@
mouseenter=
"handleShowAiPane('box2')"
/>
</div>
</div>
<div
v-if=
"aiPaneVisible.box2"
class=
"analysis-ai-pane"
@
mouseleave=
"handleHideAiPane('box2')"
>
<div
v-if=
"aiPaneVisible.box2"
class=
"analysis-ai-pane"
@
mouseleave=
"handleHideAiPane('box2')"
>
...
@@ -716,7 +716,7 @@
...
@@ -716,7 +716,7 @@
<
/AnalysisBox
>
<
/AnalysisBox
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/
div
>
<
/
BillPageShell
>
<
/template
>
<
/template
>
<
script
setup
>
<
script
setup
>
...
@@ -728,6 +728,7 @@ import { getChartAnalysis } from "@/api/aiAnalysis/index";
...
@@ -728,6 +728,7 @@ import { getChartAnalysis } from "@/api/aiAnalysis/index";
import
TipTab
from
"@/components/base/TipTab/index.vue"
;
import
TipTab
from
"@/components/base/TipTab/index.vue"
;
import
AiButton
from
"@/components/base/Ai/AiButton/index.vue"
;
import
AiButton
from
"@/components/base/Ai/AiButton/index.vue"
;
import
AiPane
from
"@/components/base/Ai/AiPane/index.vue"
;
import
AiPane
from
"@/components/base/Ai/AiPane/index.vue"
;
import
{
BillPageShell
}
from
"../../components/layout"
;
import
icon1
from
"./assets/images/icon1.png"
;
import
icon1
from
"./assets/images/icon1.png"
;
import
icon2
from
"./assets/images/icon2.png"
;
import
icon2
from
"./assets/images/icon2.png"
;
...
@@ -1160,7 +1161,7 @@ onMounted(async () => {
...
@@ -1160,7 +1161,7 @@ onMounted(async () => {
min
:
"最小次数"
,
min
:
"最小次数"
,
current
:
"该法案修正案数量"
current
:
"该法案修正案数量"
}
;
}
;
let
chart2
=
getBoxPlotChcart
(
chartData2
.
value
,
"
次
"
,
countLabels
);
let
chart2
=
getBoxPlotChcart
(
chartData2
.
value
,
"
项
"
,
countLabels
);
setChart
(
chart2
,
"chart2"
);
setChart
(
chart2
,
"chart2"
);
}
);
}
);
<
/script
>
<
/script
>
...
@@ -1168,6 +1169,8 @@ onMounted(async () => {
...
@@ -1168,6 +1169,8 @@ onMounted(async () => {
<
style
lang
=
"scss"
scoped
>
<
style
lang
=
"scss"
scoped
>
.
wrap
{
.
wrap
{
display
:
flex
;
display
:
flex
;
margin
-
bottom
:
30
px
;
.
box
-
header
{
.
box
-
header
{
height
:
56
px
;
height
:
56
px
;
...
...
src/views/bill/deepDig/processOverview/index.vue
浏览文件 @
6b4028a9
<
template
>
<
template
>
<
div
class=
"process-overview-wrap"
>
<
BillPageShell
class=
"process-overview-wrap"
>
<AnalysisBox
title=
"流程概要"
:showAllBtn=
"false"
>
<AnalysisBox
title=
"流程概要"
:showAllBtn=
"false"
>
<div
class=
"main"
>
<div
class=
"main"
>
<div
class=
"left"
:style=
"
{ width: boardWidth + 'px' }">
<div
class=
"left"
:style=
"
{ width: boardWidth + 'px' }">
...
@@ -194,7 +194,7 @@
...
@@ -194,7 +194,7 @@
:position=
"dialogPos"
:position=
"dialogPos"
@
close=
"handleClickDetail(false)"
@
close=
"handleClickDetail(false)"
/>
/>
</
div
>
</
BillPageShell
>
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
...
@@ -202,6 +202,7 @@ import { ref, onMounted, computed, nextTick } from "vue";
...
@@ -202,6 +202,7 @@ import { ref, onMounted, computed, nextTick } from "vue";
import
{
getBillDyqkSummary
}
from
"@/api/bill"
;
import
{
getBillDyqkSummary
}
from
"@/api/bill"
;
import
CommonPrompt
from
"../../commonPrompt/index.vue"
;
import
CommonPrompt
from
"../../commonPrompt/index.vue"
;
import
ProcessOverviewDetailDialog
from
"../../ProcessOverviewDetailDialog.vue"
;
import
ProcessOverviewDetailDialog
from
"../../ProcessOverviewDetailDialog.vue"
;
import
{
BillPageShell
}
from
"../../components/layout"
;
const
actionList
=
ref
([]);
const
actionList
=
ref
([]);
const
isShowDetailDialog
=
ref
(
false
);
const
isShowDetailDialog
=
ref
(
false
);
...
@@ -499,6 +500,7 @@ const updateRightTop = () => {
...
@@ -499,6 +500,7 @@ const updateRightTop = () => {
width
:
1600px
;
width
:
1600px
;
height
:
848px
;
height
:
848px
;
margin-top
:
16px
;
margin-top
:
16px
;
margin-bottom
:
30px
;
position
:
relative
;
position
:
relative
;
.main
{
.main
{
...
@@ -799,20 +801,13 @@ const updateRightTop = () => {
...
@@ -799,20 +801,13 @@ const updateRightTop = () => {
.text
{
.text
{
width
:
240px
;
width
:
240px
;
max-width
:
100%
;
color
:
rgb
(
59
,
65
,
75
);
color
:
rgb
(
59
,
65
,
75
);
font-size
:
16px
;
font-size
:
16px
;
line-height
:
24px
;
line-height
:
24px
;
display
:
-
webkit-box
;
white-space
:
nowrap
;
line-clamp
:
2
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
overflow
:
hidden
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
height
:
48px
;
}
:deep
(
.text-ellipsis
)
{
white-space
:
normal
!
important
;
}
}
}
}
}
}
...
...
src/views/bill/introdoction/index.vue
浏览文件 @
6b4028a9
<
template
>
<
template
>
<
div
class=
"introduction-wrap"
>
<
BillPageShell
class=
"introduction-wrap"
>
<WarningPane
v-if=
"riskSignal"
class=
"risk-signal-pane-top"
:warnningLevel=
"riskSignal.riskLevel"
<WarningPane
v-if=
"riskSignal"
class=
"risk-signal-pane-top"
:warnningLevel=
"riskSignal.riskLevel"
:warnningContent=
"riskSignal.riskContent"
/>
:warnningContent=
"riskSignal.riskContent"
/>
<div
class=
"introduction-wrap-content"
>
<BillTwoColumn
class=
"introduction-wrap-content"
:stack-on-narrow=
"false"
>
<div
class=
"introduction-wrap-left"
>
<template
#
left
>
<div
class=
"introduction-wrap-left"
>
<div
class=
"introduction-wrap-left-box1"
>
<div
class=
"introduction-wrap-left-box1"
>
<AnalysisBox
title=
"基本信息"
:showAllBtn=
"false"
>
<AnalysisBox
title=
"基本信息"
:showAllBtn=
"false"
>
...
@@ -69,10 +70,12 @@
...
@@ -69,10 +70,12 @@
<
/div
>
<
/div
>
<
/AnalysisBox
>
<
/AnalysisBox
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"introduction-wrap-right"
>
<
/template
>
<
AnalysisBox
title
=
"提出人"
:
showAllBtn
=
"false"
>
<
template
#
right
>
<
div
class
=
"introduction-wrap-right-main"
>
<
div
class
=
"introduction-wrap-right"
>
<
AnalysisBox
title
=
"提出人"
:
showAllBtn
=
"false"
>
<
div
class
=
"introduction-wrap-right-main"
>
<
div
class
=
"right-main-box1"
>
<
div
class
=
"right-main-box1"
>
<
div
class
=
"name-box"
>
<
div
class
=
"name-box"
>
<
div
class
=
"person-box"
>
<
div
class
=
"person-box"
>
...
@@ -139,10 +142,11 @@
...
@@ -139,10 +142,11 @@
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/AnalysisBox
>
<
/AnalysisBox
>
<
/div
>
<
/div
>
<
/div
>
<
/template
>
<
/div
>
<
/BillTwoColumn
>
<
/BillPageShell
>
<
/template
>
<
/template
>
<
script
setup
>
<
script
setup
>
...
@@ -151,6 +155,7 @@ import { useRoute, useRouter } from "vue-router";
...
@@ -151,6 +155,7 @@ import { useRoute, useRouter } from "vue-router";
import
WordCloudMap
from
"./WordCloudMap.vue"
;
import
WordCloudMap
from
"./WordCloudMap.vue"
;
import
STimeline
from
"./STimeline.vue"
;
import
STimeline
from
"./STimeline.vue"
;
import
WarningPane
from
"@/components/base/WarningPane/index.vue"
;
import
WarningPane
from
"@/components/base/WarningPane/index.vue"
;
import
{
BillPageShell
,
BillTwoColumn
}
from
"../components/layout"
;
import
{
getBillInfo
,
getBillPerson
,
getBillEvent
,
getBillDyqk
}
from
"@/api/bill"
;
import
{
getBillInfo
,
getBillPerson
,
getBillEvent
,
getBillDyqk
}
from
"@/api/bill"
;
import
{
getPersonSummaryInfo
}
from
"@/api/common/index"
;
import
{
getPersonSummaryInfo
}
from
"@/api/common/index"
;
import
defaultAvatar
from
"../assets/images/default-icon1.png"
;
import
defaultAvatar
from
"../assets/images/default-icon1.png"
;
...
@@ -338,6 +343,14 @@ onMounted(() => {
...
@@ -338,6 +343,14 @@ onMounted(() => {
height
:
auto
;
height
:
auto
;
display
:
flex
;
display
:
flex
;
flex
-
direction
:
column
;
flex
-
direction
:
column
;
box
-
sizing
:
border
-
box
;
.
page
-
bottom
-
gap
{
height
:
30
px
;
width
:
100
%
;
flex
-
shrink
:
0
;
pointer
-
events
:
none
;
}
.
progress
-
header
-
btns
{
.
progress
-
header
-
btns
{
display
:
flex
;
display
:
flex
;
...
@@ -432,6 +445,7 @@ onMounted(() => {
...
@@ -432,6 +445,7 @@ onMounted(() => {
.
introduction
-
wrap
-
content
{
.
introduction
-
wrap
-
content
{
display
:
flex
;
display
:
flex
;
margin
-
bottom
:
30
px
;
}
}
.
introduction
-
wrap
-
left
{
.
introduction
-
wrap
-
left
{
...
@@ -497,7 +511,6 @@ onMounted(() => {
...
@@ -497,7 +511,6 @@ onMounted(() => {
flex
-
wrap
:
wrap
;
flex
-
wrap
:
wrap
;
align
-
items
:
center
;
align
-
items
:
center
;
width
:
700
px
;
width
:
700
px
;
min
-
height
:
40
px
;
gap
:
8
px
;
gap
:
8
px
;
.
right1
-
item
{
.
right1
-
item
{
...
@@ -769,8 +782,6 @@ onMounted(() => {
...
@@ -769,8 +782,6 @@ onMounted(() => {
.
introduction
-
wrap
-
right
{
.
introduction
-
wrap
-
right
{
margin
-
top
:
16
px
;
margin
-
top
:
16
px
;
margin
-
left
:
16
px
;
margin
-
right
:
18
px
;
width
:
520
px
;
width
:
520
px
;
height
:
845
px
;
height
:
845
px
;
...
...
src/views/bill/template/index.vue
浏览文件 @
6b4028a9
<
template
>
<
template
>
<
div
class=
"temp-wrap"
>
<
BillPageShell
class=
"temp-wrap"
>
<div
class=
"tools-row"
>
<div
class=
"tools-row"
>
<div
class=
"tools-row-left"
>
<div
class=
"tools-row-left"
>
<el-select
v-model=
"curBill"
placeholder=
"请选择版本"
@
change=
"handleChangeBill"
<el-select
v-model=
"curBill"
placeholder=
"请选择版本"
@
change=
"handleChangeBill"
...
@@ -39,8 +39,9 @@
...
@@ -39,8 +39,9 @@
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"content-row"
>
<BillTwoColumn
class=
"content-row"
:left-width=
"520"
:right-width=
"1064"
:stack-on-narrow=
"false"
>
<div
class=
"side"
>
<
template
#
left
>
<div
class=
"side"
>
<div
class=
"side-box side-box-domain"
>
<div
class=
"side-box side-box-domain"
>
<AnalysisBox
title=
"涉及领域"
width=
"520px"
height=
"415px"
v-loading=
"domainLoading"
>
<AnalysisBox
title=
"涉及领域"
width=
"520px"
height=
"415px"
v-loading=
"domainLoading"
>
<div
class=
"chart-ai-wrap"
>
<div
class=
"chart-ai-wrap"
>
...
@@ -93,8 +94,10 @@
...
@@ -93,8 +94,10 @@
</div>
</div>
</AnalysisBox>
</AnalysisBox>
</div>
</div>
</div>
</div>
<div
class=
"terms"
>
</
template
>
<
template
#
right
>
<div
class=
"terms"
>
<div
class=
"terms-switch"
>
<div
class=
"terms-switch"
>
<span
class=
"terms-switch-label"
>
高亮实体
</span>
<span
class=
"terms-switch-label"
>
高亮实体
</span>
<el-switch
<el-switch
...
@@ -103,6 +106,10 @@
...
@@ -103,6 +106,10 @@
active-text=
"开"
active-text=
"开"
inactive-text=
"关"
inactive-text=
"关"
/>
/>
<span
v-if=
"termsEntityLoading"
class=
"terms-entity-loading"
>
<el-icon
class=
"is-loading"
><Loading
/></el-icon>
实体识别中(剩余
{{
termsEntityPendingCount
}}
条)
</span>
<span
class=
"terms-switch-divider"
></span>
<span
class=
"terms-switch-divider"
></span>
<span
class=
"terms-switch-label"
>
显示原文
</span>
<span
class=
"terms-switch-label"
>
显示原文
</span>
<el-switch
<el-switch
...
@@ -112,7 +119,7 @@
...
@@ -112,7 +119,7 @@
inactive-text=
"关"
inactive-text=
"关"
/>
/>
</div>
</div>
<AnalysisBox
title=
"主要条款"
:showAllBtn=
"false"
v-loading=
"termsLoading"
>
<AnalysisBox
title=
"主要条款"
:showAllBtn=
"false"
height=
"auto"
v-loading=
"termsLoading"
>
<div
class=
"left-main"
>
<div
class=
"left-main"
>
<div
class=
"left-main-item"
v-for=
"(term, index) in displayTermsList"
:key=
"getTermKey(term, index)"
>
<div
class=
"left-main-item"
v-for=
"(term, index) in displayTermsList"
:key=
"getTermKey(term, index)"
>
<div
class=
"term-body"
>
<div
class=
"term-body"
>
...
@@ -120,11 +127,23 @@
...
@@ -120,11 +127,23 @@
<div
class=
"term-main"
>
<div
class=
"term-main"
>
<div
class=
"term-row term-row-cn"
>
<div
class=
"term-row term-row-cn"
>
<div
class=
"term-no-cn"
>
第
{{
term
.
tkxh
}}
条.
</div>
<div
class=
"term-no-cn"
>
第
{{
term
.
tkxh
}}
条.
</div>
<div
class=
"term-content-cn"
v-html=
"getTermContentHtml(term, 'cn')"
></div>
<div
class=
"term-content-cn"
>
<IntelligentEntityText
:text=
"term?.fynr || ''"
:entities=
"termsHighlight ? getTermEntities(term, 'cn') : []"
@
on-entity-click=
"e => gotoSearchResults(e.text_span, '')"
/>
</div>
</div>
</div>
<div
class=
"term-row term-row-en"
v-if=
"termsShowOriginal"
>
<div
class=
"term-row term-row-en"
v-if=
"termsShowOriginal"
>
<div
class=
"term-no-en"
>
Sec.
{{
term
.
tkxh
}}
</div>
<div
class=
"term-no-en"
>
Sec.
{{
term
.
tkxh
}}
</div>
<div
class=
"term-content-en"
v-html=
"getTermContentHtml(term, 'en')"
></div>
<div
class=
"term-content-en"
>
<IntelligentEntityText
:text=
"term?.ywnr || ''"
:entities=
"termsHighlight ? getTermEntities(term, 'en') : []"
@
on-entity-click=
"e => gotoSearchResults(e.text_span, '')"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -144,16 +163,17 @@
...
@@ -144,16 +163,17 @@
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/AnalysisBox
>
<
/AnalysisBox
>
</div>
<
/div
>
</div>
<
/template
>
</div>
<
/BillTwoColumn
>
<
/BillPageShell
>
<
/template
>
<
/template
>
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
,
onBeforeUnmount
,
computed
,
watch
}
from
"vue"
;
import
{
ref
,
onMounted
,
onBeforeUnmount
,
computed
,
watch
}
from
"vue"
;
import
{
useRoute
,
onBeforeRouteLeave
}
from
"vue-router"
;
import
{
useRoute
,
onBeforeRouteLeave
}
from
"vue-router"
;
import
*
as
echarts
from
"echarts"
;
import
*
as
echarts
from
"echarts"
;
import
{
Search
}
from
"@element-plus/icons-vue"
;
import
{
Search
,
Loading
}
from
"@element-plus/icons-vue"
;
import
getPieChart
from
"./utils/piechart"
;
import
getPieChart
from
"./utils/piechart"
;
import
{
getBillContentId
,
getBillContentTk
,
getBillContentXzfs
,
getBillHyly
}
from
"@/api/bill"
;
import
{
getBillContentId
,
getBillContentTk
,
getBillContentXzfs
,
getBillHyly
}
from
"@/api/bill"
;
import
{
getChartAnalysis
}
from
"@/api/aiAnalysis/index"
;
import
{
getChartAnalysis
}
from
"@/api/aiAnalysis/index"
;
...
@@ -162,9 +182,12 @@ import AiButton from "@/components/base/Ai/AiButton/index.vue";
...
@@ -162,9 +182,12 @@ import AiButton from "@/components/base/Ai/AiButton/index.vue";
import
AiPane
from
"@/components/base/Ai/AiPane/index.vue"
;
import
AiPane
from
"@/components/base/Ai/AiPane/index.vue"
;
import
{
MUTICHARTCOLORS
}
from
"@/common/constant"
;
import
{
MUTICHARTCOLORS
}
from
"@/common/constant"
;
import
{
extractTextEntity
}
from
"@/api/intelligent/index"
;
import
{
extractTextEntity
}
from
"@/api/intelligent/index"
;
import
{
useGotoSearchResults
}
from
"@/router/modules/comprehensiveSearch"
;
import
IntelligentEntityText
from
"@/components/base/texts/IntelligentEntityText.vue"
;
import
{
BillPageShell
,
BillTwoColumn
}
from
"../components/layout"
;
const
route
=
useRoute
();
const
route
=
useRoute
();
const
gotoSearchResults
=
useGotoSearchResults
();
const
pageAbortController
=
new
AbortController
();
const
pageAbortController
=
new
AbortController
();
const
isRequestCanceled
=
error
=>
{
const
isRequestCanceled
=
error
=>
{
...
@@ -186,6 +209,8 @@ const stopCurrentPageRequests = () => {
...
@@ -186,6 +209,8 @@ const stopCurrentPageRequests = () => {
hylyRequestToken
.
value
+=
1
;
hylyRequestToken
.
value
+=
1
;
entityRequestToken
.
value
+=
1
;
entityRequestToken
.
value
+=
1
;
termsLoading
.
value
=
false
;
termsLoading
.
value
=
false
;
termsEntityLoading
.
value
=
false
;
termsEntityPendingCount
.
value
=
0
;
limitLoading
.
value
=
false
;
limitLoading
.
value
=
false
;
domainLoading
.
value
=
false
;
domainLoading
.
value
=
false
;
aiPaneLoading
.
value
=
{
domain
:
false
,
limit
:
false
}
;
aiPaneLoading
.
value
=
{
domain
:
false
,
limit
:
false
}
;
...
@@ -214,16 +239,8 @@ const termsShowOriginal = ref(true);
...
@@ -214,16 +239,8 @@ const termsShowOriginal = ref(true);
const
entityRequestToken
=
ref
(
0
);
const
entityRequestToken
=
ref
(
0
);
const
termEntityCache
=
ref
(
new
Map
());
const
termEntityCache
=
ref
(
new
Map
());
const
termsEntityLoading
=
ref
(
false
);
const
escapeHtml
=
value
=>
{
const
termsEntityPendingCount
=
ref
(
0
);
const
str
=
String
(
value
??
""
);
return
str
.
replace
(
/&/g
,
"&"
)
.
replace
(
/</g
,
"<"
)
.
replace
(
/>/g
,
">"
)
.
replace
(
/"/g
,
"""
)
.
replace
(
/'/g
,
"'"
);
};
const
normalizeEntities
=
entities
=>
{
const
normalizeEntities
=
entities
=>
{
const
list
=
Array
.
isArray
(
entities
)
?
entities
:
[];
const
list
=
Array
.
isArray
(
entities
)
?
entities
:
[];
...
@@ -237,69 +254,23 @@ const normalizeEntities = entities => {
...
@@ -237,69 +254,23 @@ const normalizeEntities = entities => {
.
filter
(
item
=>
item
.
text_span
);
.
filter
(
item
=>
item
.
text_span
);
}
;
}
;
const
getEntityRanges
=
(
text
,
entities
)
=>
{
const
ranges
=
[];
const
rawText
=
String
(
text
??
""
);
if
(
!
rawText
)
return
ranges
;
const
list
=
normalizeEntities
(
entities
).
sort
((
a
,
b
)
=>
b
.
text_span
.
length
-
a
.
text_span
.
length
);
for
(
const
ent
of
list
)
{
let
startIndex
=
0
;
while
(
startIndex
<
rawText
.
length
)
{
const
idx
=
rawText
.
indexOf
(
ent
.
text_span
,
startIndex
);
if
(
idx
===
-
1
)
break
;
ranges
.
push
({
start
:
idx
,
end
:
idx
+
ent
.
text_span
.
length
,
ent
});
startIndex
=
idx
+
ent
.
text_span
.
length
;
}
}
ranges
.
sort
((
a
,
b
)
=>
a
.
start
-
b
.
start
||
b
.
end
-
a
.
end
);
const
merged
=
[];
let
lastEnd
=
0
;
for
(
const
r
of
ranges
)
{
if
(
r
.
start
<
lastEnd
)
continue
;
merged
.
push
(
r
);
lastEnd
=
r
.
end
;
}
return
merged
;
};
const
buildHighlightedHtml
=
(
text
,
entities
,
enableHighlight
)
=>
{
const
rawText
=
String
(
text
??
""
);
if
(
!
rawText
)
return
""
;
const
safeText
=
escapeHtml
(
rawText
).
replace
(
/
\n
/g
,
"<br />"
);
if
(
!
enableHighlight
)
return
safeText
;
const
ranges
=
getEntityRanges
(
rawText
,
entities
);
if
(
!
ranges
.
length
)
return
safeText
;
let
html
=
""
;
let
cursor
=
0
;
for
(
const
r
of
ranges
)
{
if
(
cursor
<
r
.
start
)
{
html
+=
escapeHtml
(
rawText
.
slice
(
cursor
,
r
.
start
));
}
const
spanText
=
rawText
.
slice
(
r
.
start
,
r
.
end
);
const
type
=
escapeHtml
(
r
.
ent
?.
type
??
""
);
html
+=
`<span class="term-entity" data-entity-type="
${
type
}
">
${
escapeHtml
(
spanText
)}
</span>`
;
cursor
=
r
.
end
;
}
if
(
cursor
<
rawText
.
length
)
{
html
+=
escapeHtml
(
rawText
.
slice
(
cursor
));
}
return
html
.
replace
(
/
\n
/g
,
"<br />"
);
};
const
getTermEntityKey
=
(
term
,
lang
)
=>
{
const
getTermEntityKey
=
(
term
,
lang
)
=>
{
const
baseKey
=
getTermKey
(
term
,
-
1
);
const
baseKey
=
getTermKey
(
term
,
-
1
);
return
`${baseKey
}
__${lang
}
`
;
return
`${baseKey
}
__${lang
}
`
;
}
;
}
;
const
ensureEntitiesForTerms
=
async
terms
=>
{
const
ensureEntitiesForTerms
=
async
terms
=>
{
if
(
!
termsHighlight
.
value
)
return
;
if
(
!
termsHighlight
.
value
)
{
termsEntityLoading
.
value
=
false
;
termsEntityPendingCount
.
value
=
0
;
return
;
}
const
list
=
Array
.
isArray
(
terms
)
?
terms
:
[];
const
list
=
Array
.
isArray
(
terms
)
?
terms
:
[];
if
(
!
list
.
length
)
return
;
if
(
!
list
.
length
)
{
termsEntityLoading
.
value
=
false
;
termsEntityPendingCount
.
value
=
0
;
return
;
}
const
currentToken
=
++
entityRequestToken
.
value
;
const
currentToken
=
++
entityRequestToken
.
value
;
...
@@ -314,30 +285,40 @@ const ensureEntitiesForTerms = async terms => {
...
@@ -314,30 +285,40 @@ const ensureEntitiesForTerms = async terms => {
tasks
.
push
({
key
:
enKey
,
text
:
term
.
ywnr
}
);
tasks
.
push
({
key
:
enKey
,
text
:
term
.
ywnr
}
);
}
}
}
}
if
(
!
tasks
.
length
)
return
;
if
(
!
tasks
.
length
)
{
termsEntityLoading
.
value
=
false
;
termsEntityPendingCount
.
value
=
0
;
return
;
}
try
{
termsEntityLoading
.
value
=
true
;
const
results
=
await
Promise
.
all
(
termsEntityPendingCount
.
value
=
tasks
.
length
;
tasks
.
map
(
async
item
=>
{
const
res
=
await
extractTextEntity
(
item
.
text
,
{
signal
:
getPageSignal
()
});
const
fetchOne
=
async
item
=>
{
const
entities
=
normalizeEntities
(
res
?.
result
??
res
?.
data
?.
result
??
res
?.
data
??
res
);
try
{
return
{
key
:
item
.
key
,
entities
};
const
res
=
await
extractTextEntity
(
item
.
text
,
{
signal
:
getPageSignal
()
}
);
})
if
(
currentToken
!==
entityRequestToken
.
value
)
return
;
);
const
entities
=
normalizeEntities
(
res
?.
result
??
res
?.
data
?.
result
??
res
?.
data
??
res
);
if
(
currentToken
!==
entityRequestToken
.
value
)
return
;
const
nextCache
=
new
Map
(
termEntityCache
.
value
);
for
(
const
r
of
results
)
{
nextCache
.
set
(
item
.
key
,
entities
);
termEntityCache
.
value
.
set
(
r
.
key
,
r
.
entities
);
termEntityCache
.
value
=
nextCache
;
}
catch
(
error
)
{
if
(
currentToken
!==
entityRequestToken
.
value
)
return
;
}
finally
{
if
(
currentToken
!==
entityRequestToken
.
value
)
return
;
termsEntityPendingCount
.
value
=
Math
.
max
(
0
,
termsEntityPendingCount
.
value
-
1
);
if
(
termsEntityPendingCount
.
value
===
0
)
{
termsEntityLoading
.
value
=
false
;
}
}
}
}
catch
(
error
)
{
}
;
if
(
currentToken
!==
entityRequestToken
.
value
)
return
;
}
await
Promise
.
all
(
tasks
.
map
(
item
=>
fetchOne
(
item
)));
}
;
}
;
const
getTermContentHtml
=
(
term
,
lang
)
=>
{
const
getTermEntities
=
(
term
,
lang
)
=>
{
const
raw
=
lang
===
"en"
?
term
?.
ywnr
:
term
?.
fynr
;
const
key
=
getTermEntityKey
(
term
,
lang
);
const
key
=
getTermEntityKey
(
term
,
lang
);
const
entities
=
termEntityCache
.
value
.
get
(
key
)
||
[];
return
termEntityCache
.
value
.
get
(
key
)
||
[];
return
buildHighlightedHtml
(
raw
,
entities
,
termsHighlight
.
value
);
}
;
}
;
const
tkRequestToken
=
ref
(
0
);
const
tkRequestToken
=
ref
(
0
);
...
@@ -347,10 +328,6 @@ const hylyRequestToken = ref(0);
...
@@ -347,10 +328,6 @@ const hylyRequestToken = ref(0);
const
mainTermsList
=
ref
([]);
const
mainTermsList
=
ref
([]);
const
domainFooterText
=
ref
(
""
);
const
domainFooterText
=
ref
(
""
);
const
limitFooterText
=
ref
(
""
);
const
limitFooterText
=
ref
(
""
);
const
btnActiveIndex
=
ref
(
1
);
const
handleSelectBtn
=
index
=>
{
btnActiveIndex
.
value
=
index
;
};
const
getTermKey
=
(
term
,
index
)
=>
{
const
getTermKey
=
(
term
,
index
)
=>
{
return
term
?.
ywid
??
term
?.
id
??
term
?.
tkxh
??
index
;
return
term
?.
ywid
??
term
?.
id
??
term
?.
tkxh
??
index
;
...
@@ -576,7 +553,16 @@ const handleChangeCheckbox = val => {
...
@@ -576,7 +553,16 @@ const handleChangeCheckbox = val => {
handleGetBillHyly
();
handleGetBillHyly
();
}
;
}
;
/** 法案布局主区域可滚动容器(.layout-main)滚回顶部 */
const
scrollBillLayoutMainToTop
=
()
=>
{
const
mainEl
=
document
.
querySelector
(
".layout-main"
);
if
(
mainEl
)
{
mainEl
.
scrollTo
({
top
:
0
,
behavior
:
"smooth"
}
);
}
}
;
const
handleCurrentChange
=
val
=>
{
const
handleCurrentChange
=
val
=>
{
scrollBillLayoutMainToTop
();
currentPage
.
value
=
val
;
currentPage
.
value
=
val
;
handleGetBillContentTk
(
checkedValue
.
value
?
"Y"
:
"N"
);
handleGetBillContentTk
(
checkedValue
.
value
?
"Y"
:
"N"
);
}
;
}
;
...
@@ -925,8 +911,11 @@ onBeforeUnmount(() => {
...
@@ -925,8 +911,11 @@ onBeforeUnmount(() => {
.
content
-
row
{
.
content
-
row
{
display
:
flex
;
display
:
flex
;
align
-
items
:
flex
-
start
;
margin
-
bottom
:
30
px
;
}
}
.
box
-
header
{
.
box
-
header
{
display
:
flex
;
display
:
flex
;
position
:
relative
;
position
:
relative
;
...
@@ -988,9 +977,7 @@ onBeforeUnmount(() => {
...
@@ -988,9 +977,7 @@ onBeforeUnmount(() => {
.
terms
{
.
terms
{
margin
-
top
:
16
px
;
margin
-
top
:
16
px
;
margin-left
:
16px
;
width
:
1064
px
;
width
:
1064
px
;
height
:
1232px
;
position
:
relative
;
position
:
relative
;
.
terms
-
switch
{
.
terms
-
switch
{
...
@@ -1007,6 +994,14 @@ onBeforeUnmount(() => {
...
@@ -1007,6 +994,14 @@ onBeforeUnmount(() => {
color
:
var
(
--
text
-
primary
-
65
-
color
);
color
:
var
(
--
text
-
primary
-
65
-
color
);
}
}
.
terms
-
entity
-
loading
{
display
:
inline
-
flex
;
align
-
items
:
center
;
gap
:
4
px
;
font
-
size
:
12
px
;
color
:
var
(
--
text
-
primary
-
65
-
color
);
}
.
terms
-
switch
-
divider
{
.
terms
-
switch
-
divider
{
display
:
inline
-
block
;
display
:
inline
-
block
;
width
:
1
px
;
width
:
1
px
;
...
@@ -1022,17 +1017,21 @@ onBeforeUnmount(() => {
...
@@ -1022,17 +1017,21 @@ onBeforeUnmount(() => {
}
}
}
}
:
deep
(.
analysis
-
box
-
wrapper
)
{
height
:
auto
;
}
:
deep
(.
wrapper
-
main
)
{
:
deep
(.
wrapper
-
main
)
{
display
:
flex
;
display
:
flex
;
flex
-
direction
:
column
;
flex
-
direction
:
column
;
height
:
calc
(
100%
-
45px
);
height
:
auto
;
gap
:
16px
;
min
-
height
:
0
;
overflow
:
visible
;
gap
:
16
px
;
}
}
.
left
-
main
{
.
left
-
main
{
flex
:
1
;
flex
:
0
0
auto
;
min-height
:
0
;
overflow-y
:
auto
;
display
:
flex
;
display
:
flex
;
flex
-
direction
:
column
;
flex
-
direction
:
column
;
gap
:
12
px
;
gap
:
12
px
;
...
@@ -1112,12 +1111,12 @@ onBeforeUnmount(() => {
...
@@ -1112,12 +1111,12 @@ onBeforeUnmount(() => {
line
-
height
:
24
px
;
line
-
height
:
24
px
;
color
:
var
(
--
text
-
primary
-
80
-
color
);
color
:
var
(
--
text
-
primary
-
80
-
color
);
:deep
(
.
term-entity
)
{
:
deep
(.
entity
-
link
)
{
display
:
inline
;
color
:
var
(
--
color
-
primary
-
100
)
;
padding
:
0
2px
;
}
border-radius
:
4px
;
background
:
rgba
(
255
,
213
,
79
,
0
.35
);
:
deep
(.
entity
-
link
:
hover
)
{
box-shadow
:
inset
0
0
0
1px
rgba
(
255
,
193
,
7
,
0
.25
)
;
cursor
:
pointer
;
}
}
}
}
...
@@ -1128,12 +1127,12 @@ onBeforeUnmount(() => {
...
@@ -1128,12 +1127,12 @@ onBeforeUnmount(() => {
line
-
height
:
24
px
;
line
-
height
:
24
px
;
color
:
var
(
--
text
-
primary
-
65
-
color
);
color
:
var
(
--
text
-
primary
-
65
-
color
);
:deep
(
.
term-entity
)
{
:
deep
(.
entity
-
link
)
{
display
:
inline
;
color
:
var
(
--
color
-
primary
-
100
)
;
padding
:
0
2px
;
}
border-radius
:
4px
;
background
:
rgba
(
255
,
213
,
79
,
0
.28
);
:
deep
(.
entity
-
link
:
hover
)
{
box-shadow
:
inset
0
0
0
1px
rgba
(
255
,
193
,
7
,
0
.2
)
;
cursor
:
pointer
;
}
}
}
}
...
@@ -1196,6 +1195,7 @@ onBeforeUnmount(() => {
...
@@ -1196,6 +1195,7 @@ onBeforeUnmount(() => {
display
:
flex
;
display
:
flex
;
align
-
items
:
center
;
align
-
items
:
center
;
justify
-
content
:
center
;
justify
-
content
:
center
;
padding
-
left
:
20
px
;
}
}
.
overview
-
tip
-
action
{
.
overview
-
tip
-
action
{
...
...
src/views/dataLibrary/bill/countryBill/index.vue
浏览文件 @
6b4028a9
...
@@ -165,7 +165,7 @@ import { useRoute } from "vue-router";
...
@@ -165,7 +165,7 @@ import { useRoute } from "vue-router";
import
router
from
'@/router'
import
router
from
'@/router'
import
{
getPostOrgList
,
getPostMemberList
}
from
'@/api/bill/billHome'
import
{
getPostOrgList
,
getPostMemberList
}
from
'@/api/bill/billHome'
import
{
search
}
from
'@/api/comprehensiveSearch'
import
{
search
,
getStatusList
}
from
'@/api/comprehensiveSearch'
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
getDateRange
from
'@/utils/getDateRange'
import
getDateRange
from
'@/utils/getDateRange'
...
@@ -345,10 +345,13 @@ const activeTagList = computed(() => {
...
@@ -345,10 +345,13 @@ const activeTagList = computed(() => {
)
)
}
}
if
(
selectedStatus
.
value
&&
selectedStatus
.
value
!==
'全部阶段'
)
{
if
(
selectedStatus
.
value
&&
selectedStatus
.
value
!==
'全部阶段'
)
{
const
statusName
=
statusList
.
value
.
filter
(
item
=>
{
return
item
.
id
===
selectedStatus
.
value
}
)[
0
].
name
arr
.
push
(
arr
.
push
(
{
{
tag
:
'所处阶段'
,
tag
:
'所处阶段'
,
name
:
s
electedStatus
.
valu
e
name
:
s
tatusNam
e
}
}
)
)
}
}
...
@@ -711,6 +714,31 @@ const statusList = ref([
...
@@ -711,6 +714,31 @@ const statusList = ref([
}
,
}
,
])
])
const
handleGetStatusList
=
async
()
=>
{
try
{
const
res
=
await
getStatusList
()
console
.
log
(
'获取立法阶段列表'
,
res
);
if
(
res
.
code
===
200
)
{
const
arr
=
res
.
data
.
map
(
item
=>
{
return
{
name
:
item
.
name
,
id
:
item
.
number
}
}
)
statusList
.
value
=
[
{
name
:
'全部阶段'
,
id
:
'全部阶段'
}
,
...
arr
]
}
}
catch
(
error
)
{
}
}
const
selectedStatus
=
ref
(
'全部阶段'
)
const
selectedStatus
=
ref
(
'全部阶段'
)
const
statusPlaceHolder
=
ref
(
'请选择立法阶段'
)
const
statusPlaceHolder
=
ref
(
'请选择立法阶段'
)
const
handleSelectStauts
=
value
=>
{
const
handleSelectStauts
=
value
=>
{
...
@@ -737,6 +765,7 @@ const handleClear = () => {
...
@@ -737,6 +765,7 @@ const handleClear = () => {
// 确定
// 确定
const
handleConfirm
=
()
=>
{
const
handleConfirm
=
()
=>
{
currentPage
.
value
=
1
fetchTableData
()
fetchTableData
()
}
}
...
@@ -785,6 +814,9 @@ const fetchTableData = async () => {
...
@@ -785,6 +814,9 @@ const fetchTableData = async () => {
// isSelectedAll.value = false
// isSelectedAll.value = false
// selectedMap.value.clear()
// selectedMap.value.clear()
// 调用接口获取数据...
// 调用接口获取数据...
loading
.
value
=
true
const
params
=
{
const
params
=
{
page
:
currentPage
.
value
,
page
:
currentPage
.
value
,
size
:
pageSize
.
value
,
size
:
pageSize
.
value
,
...
@@ -843,12 +875,10 @@ const fetchTableData = async () => {
...
@@ -843,12 +875,10 @@ const fetchTableData = async () => {
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
]
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
]
curChartData
.
value
=
curDemensionItem
.
data
curChartData
.
value
=
curDemensionItem
.
data
}
)
}
)
loading
.
value
=
false
}
catch
(
error
)
{
}
catch
(
error
)
{
loading
.
value
=
false
}
}
// tableData.value = res.data
// tableData.value = res.data
// total.value = res.total
// total.value = res.total
...
@@ -867,6 +897,12 @@ const allData = ref([])
...
@@ -867,6 +897,12 @@ const allData = ref([])
// 获取筛选条件下全部表格数据
// 获取筛选条件下全部表格数据
const
fetchAllData
=
async
()
=>
{
const
fetchAllData
=
async
()
=>
{
let
statusParam
=
null
if
(
selectedStatus
.
value
!==
'全部阶段'
)
{
statusParam
=
statusList
.
value
.
filter
(
item
=>
{
return
item
.
name
===
selectedStatus
.
value
}
)[
0
].
id
}
const
params
=
{
const
params
=
{
page
:
1
,
page
:
1
,
size
:
9999
,
size
:
9999
,
...
@@ -879,7 +915,7 @@ const fetchAllData = async () => {
...
@@ -879,7 +915,7 @@ const fetchAllData = async () => {
originChamber
:
selectedCongress
.
value
===
'全部议院'
?
null
:
selectedCongress
.
value
,
originChamber
:
selectedCongress
.
value
===
'全部议院'
?
null
:
selectedCongress
.
value
,
originDepart
:
selectedOrg
.
value
===
'全部委员会'
?
null
:
selectedOrg
.
value
,
originDepart
:
selectedOrg
.
value
===
'全部委员会'
?
null
:
selectedOrg
.
value
,
sponsorPersonName
:
selectedmember
.
value
===
'全部议员'
?
null
:
selectedmember
.
value
,
sponsorPersonName
:
selectedmember
.
value
===
'全部议员'
?
null
:
selectedmember
.
value
,
status
:
selectedStatus
.
value
===
'
通过'
?
1
:
0
,
status
:
selectedStatus
.
value
===
'
全部阶段'
?
null
:
selectedStatus
.
value
,
isInvolveCn
:
isInvolveCn
.
value
?
'Y'
:
'N'
,
isInvolveCn
:
isInvolveCn
.
value
?
'Y'
:
'N'
,
sort
:
isSort
.
value
?
0
:
1
// 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
sort
:
isSort
.
value
?
0
:
1
// 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
}
...
@@ -1038,8 +1074,10 @@ const initParam = () => {
...
@@ -1038,8 +1074,10 @@ const initParam = () => {
customTime
.
value
=
JSON
.
parse
(
route
.
query
.
selectedDate
)
customTime
.
value
=
JSON
.
parse
(
route
.
query
.
selectedDate
)
}
}
isInvolveCn
.
value
=
route
.
query
.
isInvolveCn
?
true
:
false
isInvolveCn
.
value
=
route
.
query
.
isInvolveCn
?
true
:
false
if
(
route
.
query
.
selectedStatus
)
{
if
(
route
.
query
.
selectedStatus
&&
route
.
query
.
selectedStatus
!==
'全部阶段'
)
{
selectedStatus
.
value
=
route
.
query
.
selectedStatus
selectedStatus
.
value
=
statusList
.
value
.
filter
(
item
=>
{
return
item
.
name
===
route
.
query
.
selectedStatus
}
)[
0
].
id
}
else
{
}
else
{
selectedStatus
.
value
=
'全部阶段'
selectedStatus
.
value
=
'全部阶段'
}
}
...
@@ -1054,7 +1092,7 @@ const initParam = () => {
...
@@ -1054,7 +1092,7 @@ const initParam = () => {
}
else
{
}
else
{
const
savedQuery
=
JSON
.
parse
(
sessionStorage
.
getItem
(
'routeQuery'
)
||
'{
}
'
);
const
savedQuery
=
JSON
.
parse
(
sessionStorage
.
getItem
(
'routeQuery'
)
||
'{
}
'
);
selectedArea
.
value
=
savedQuery
.
domains
?
savedQuery
.
domains
:
'全部领域'
selectedArea
.
value
=
savedQuery
.
domains
?
savedQuery
.
domains
:
'全部领域'
if
(
Array
.
isArray
(
JSON
.
parse
(
savedQuery
.
selectedDate
))
&&
JSON
.
parse
(
savedQuery
.
selectedDate
).
length
)
{
if
(
savedQuery
.
selectedDate
&&
Array
.
isArray
(
JSON
.
parse
(
savedQuery
.
selectedDate
))
&&
JSON
.
parse
(
savedQuery
.
selectedDate
).
length
)
{
selectedDate
.
value
=
'自定义'
selectedDate
.
value
=
'自定义'
customTime
.
value
=
JSON
.
parse
(
savedQuery
.
selectedDate
)
customTime
.
value
=
JSON
.
parse
(
savedQuery
.
selectedDate
)
}
}
...
@@ -1123,9 +1161,11 @@ const handleExport = () => {
...
@@ -1123,9 +1161,11 @@ const handleExport = () => {
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
handleGetOrgList
()
handleGetOrgList
()
handleGetMemberList
()
handleGetMemberList
()
initParam
()
await
handleGetStatusList
()
// 初始化
// 初始化
await
fetchTableData
()
initParam
()
fetchTableData
()
}
)
}
)
onBeforeUnmount
(()
=>
{
onBeforeUnmount
(()
=>
{
...
...
src/views/dataLibrary/decree/index.vue
浏览文件 @
6b4028a9
...
@@ -124,13 +124,13 @@
...
@@ -124,13 +124,13 @@
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"data-main-box-main-content"
v
-
loading
=
"loading"
element
-
loading
-
text
=
"
全部
数据加载中,请稍候..."
>
<
div
class
=
"data-main-box-main-content"
v
-
loading
=
"loading"
element
-
loading
-
text
=
"数据加载中,请稍候..."
>
<
el
-
table
ref
=
"tableRef"
:
data
=
"tableData"
row
-
key
=
"id"
@
selection
-
change
=
"handleSelectionChange"
<
el
-
table
ref
=
"tableRef"
:
data
=
"tableData"
row
-
key
=
"id"
@
selection
-
change
=
"handleSelectionChange"
@
select
=
"handleSelect"
@
select
-
all
=
"handleSelectAll"
style
=
"width: 100%"
:
row
-
style
=
"{ height: '52px'
}
"
>
@
select
=
"handleSelect"
@
select
-
all
=
"handleSelectAll"
style
=
"width: 100%"
:
row
-
style
=
"{ height: '52px'
}
"
>
<
el
-
table
-
column
type
=
"selection"
width
=
"40"
/>
<
el
-
table
-
column
type
=
"selection"
width
=
"40"
/>
<
el
-
table
-
column
label
=
"政令名称"
width
=
"720"
>
<
el
-
table
-
column
label
=
"政令名称"
width
=
"720"
>
<
template
#
default
=
"scope"
>
<
template
#
default
=
"scope"
>
<
span
class
=
"title-item text-compact-bold"
@
click
=
"handleClickToDetail(scope.row)"
>
{{
scope
.
row
.
t
itle
<
span
class
=
"title-item text-compact-bold"
@
click
=
"handleClickToDetail(scope.row)"
>
{{
scope
.
row
.
originalT
itle
}}
<
/span
>
}}
<
/span
>
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
...
@@ -139,7 +139,7 @@
...
@@ -139,7 +139,7 @@
<
/el-table-column
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"发布机构"
>
<
el
-
table
-
column
label
=
"发布机构"
>
<
template
#
default
=
"scope"
>
<
template
#
default
=
"scope"
>
<
span
class
=
"person-item text-compact"
@
click
=
"handle
Per
Click(scope.row)"
>
{{
scope
.
row
.
organizationName
<
span
class
=
"person-item text-compact"
@
click
=
"handle
Org
Click(scope.row)"
>
{{
scope
.
row
.
organizationName
}}
<
/span
>
}}
<
/span
>
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
...
@@ -675,6 +675,7 @@ const handleClear = () => {
...
@@ -675,6 +675,7 @@ const handleClear = () => {
// 确定
// 确定
const
handleConfirm
=
()
=>
{
const
handleConfirm
=
()
=>
{
currentPage
.
value
=
1
fetchTableData
()
fetchTableData
()
}
}
...
@@ -718,6 +719,7 @@ const selectedCount = computed(() => selectedMap.value.size)
...
@@ -718,6 +719,7 @@ const selectedCount = computed(() => selectedMap.value.size)
const
fetchTableData
=
async
()
=>
{
const
fetchTableData
=
async
()
=>
{
// isSelectedAll.value = false
// isSelectedAll.value = false
// selectedMap.value.clear()
// selectedMap.value.clear()
loading
.
value
=
true
// 调用接口获取数据...
// 调用接口获取数据...
const
params
=
{
const
params
=
{
page
:
currentPage
.
value
,
page
:
currentPage
.
value
,
...
@@ -772,8 +774,9 @@ const fetchTableData = async () => {
...
@@ -772,8 +774,9 @@ const fetchTableData = async () => {
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
]
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
]
curChartData
.
value
=
curDemensionItem
.
data
curChartData
.
value
=
curDemensionItem
.
data
}
)
}
)
loading
.
value
=
false
}
catch
(
error
)
{
}
catch
(
error
)
{
loading
.
value
=
false
}
}
// tableData.value = res.data
// tableData.value = res.data
// total.value = res.total
// total.value = res.total
...
@@ -1003,17 +1006,18 @@ const handleClickToDetail = (curDecree) => {
...
@@ -1003,17 +1006,18 @@ const handleClickToDetail = (curDecree) => {
window
.
open
(
route
.
href
,
"_blank"
);
window
.
open
(
route
.
href
,
"_blank"
);
}
;
}
;
// 跳转人物详情
// 跳转机构详情
const
handlePerClick
=
item
=>
{
const
handleOrgClick
=
item
=>
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
sponsorPersonName
);
console
.
log
(
'item'
,
item
);
const
route
=
router
.
resolve
({
path
:
"/characterPage"
,
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
organizationName
);
query
:
{
const
route
=
router
.
resolve
({
type
:
2
,
path
:
"/institution"
,
personId
:
item
.
personId
query
:
{
}
id
:
item
.
organizationId
}
);
}
window
.
open
(
route
.
href
,
"_blank"
);
}
);
window
.
open
(
route
.
href
,
"_blank"
);
}
;
}
;
// 导出
// 导出
...
@@ -1216,6 +1220,8 @@ onMounted(async () => {
...
@@ -1216,6 +1220,8 @@ onMounted(async () => {
.
header
-
left
-
item2
{
.
header
-
left
-
item2
{
color
:
var
(
--
color
-
primary
-
100
);
color
:
var
(
--
color
-
primary
-
100
);
display
:
flex
;
gap
:
8
px
;
}
}
...
...
src/views/dataLibrary/thinkTank/index.vue
浏览文件 @
6b4028a9
...
@@ -15,18 +15,18 @@
...
@@ -15,18 +15,18 @@
placeholder-name=
"请输入智库报告名称"
/>
placeholder-name=
"请输入智库报告名称"
/>
<div
class=
"check-box"
>
<div
class=
"check-box"
>
<div
class=
"check-box-left text-tip-1"
>
<div
class=
"check-box-left text-tip-1"
>
{{
'是否涉华:'
}}
{{
"是否涉华:"
}}
</div>
</div>
<div
class=
"check-box-right"
>
<div
class=
"check-box-right"
>
<el-checkbox
v-model=
"isInvolveCn"
class=
"involve-checkbox"
>
<el-checkbox
v-model=
"isInvolveCn"
class=
"involve-checkbox"
>
{{
'只看涉华智库报告'
}}
{{
"只看涉华智库报告"
}}
</el-checkbox>
</el-checkbox>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"header-footer"
>
<div
class=
"header-footer"
>
<div
class=
"header-footer-left"
>
<div
class=
"header-footer-left"
>
<ActiveTag
v-for=
"
tag, index
in activeTagList"
:key=
"index"
:tagName=
"tag.name"
<ActiveTag
v-for=
"
(tag, index)
in activeTagList"
:key=
"index"
:tagName=
"tag.name"
@
close=
"handleCloseCurTag(tag, index)"
/>
@
close=
"handleCloseCurTag(tag, index)"
/>
</div>
</div>
<div
class=
"header-footer-right"
>
<div
class=
"header-footer-right"
>
...
@@ -38,7 +38,7 @@
...
@@ -38,7 +38,7 @@
<div
class=
"chart-main-box"
v-if=
"isShowChart"
>
<div
class=
"chart-main-box"
v-if=
"isShowChart"
>
<div
class=
"info-box"
>
<div
class=
"info-box"
>
<div
class=
"switch-box"
@
click=
"handleSwitchChartData"
>
<div
class=
"switch-box"
@
click=
"handleSwitchChartData"
>
<img
src=
"@/views/dataLibrary/assets/icons/chart-active.svg"
alt=
""
>
<img
src=
"@/views/dataLibrary/assets/icons/chart-active.svg"
alt=
""
/
>
</div>
</div>
<div
class=
"num-box text-title-3-bold"
>
<div
class=
"num-box text-title-3-bold"
>
{{
`共 ${totalNum
}
条数据`
}}
{{
`共 ${totalNum
}
条数据`
}}
...
@@ -52,7 +52,6 @@
...
@@ -52,7 +52,6 @@
@
change
=
"handleChangeTime"
>
@
change
=
"handleChangeTime"
>
<
el
-
option
v
-
for
=
"item in timeList"
:
key
=
"item.value"
:
label
=
"item.label"
:
value
=
"item.value"
/>
<
el
-
option
v
-
for
=
"item in timeList"
:
key
=
"item.value"
:
label
=
"item.label"
:
value
=
"item.value"
/>
<
/el-select
>
<
/el-select
>
<
/template
>
<
/template
>
<
/ChartHeader
>
<
/ChartHeader
>
<
/div
>
<
/div
>
...
@@ -66,14 +65,13 @@
...
@@ -66,14 +65,13 @@
<
RaderChart
v
-
if
=
"activeChart === '雷达图'"
:
radarChartData
=
"curChartData"
/>
<
RaderChart
v
-
if
=
"activeChart === '雷达图'"
:
radarChartData
=
"curChartData"
/>
<
/template
>
<
/template
>
<
/ChartContainer
>
<
/ChartContainer
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"data-main-box"
v
-
else
>
<
div
class
=
"data-main-box"
v
-
else
>
<
div
class
=
"data-main-box-header"
>
<
div
class
=
"data-main-box-header"
>
<
div
class
=
"switch-box"
@
click
=
"handleSwitchChartData"
>
<
div
class
=
"switch-box"
@
click
=
"handleSwitchChartData"
>
<
img
src
=
"@/views/dataLibrary/assets/icons/data-active.svg"
alt
=
""
>
<
img
src
=
"@/views/dataLibrary/assets/icons/data-active.svg"
alt
=
""
/
>
<
/div
>
<
/div
>
<
div
class
=
"num-box text-title-3-bold"
>
<
div
class
=
"num-box text-title-3-bold"
>
{{
`共 ${totalNum
}
条数据`
}}
{{
`共 ${totalNum
}
条数据`
}}
...
@@ -86,17 +84,19 @@
...
@@ -86,17 +84,19 @@
<
el
-
checkbox
v
-
model
=
"isSelectedAll"
label
=
"全选"
@
change
=
"handleSelectAllChange"
size
=
"large"
/>
<
el
-
checkbox
v
-
model
=
"isSelectedAll"
label
=
"全选"
@
change
=
"handleSelectAllChange"
size
=
"large"
/>
<
/div
>
<
/div
>
<
div
class
=
"header-left-item2 text-tip-1"
>
{{
`已选择${selectedCount
}
项`
}}
<
/div
>
<
div
class
=
"header-left-item2 text-tip-1"
>
{{
`已选择${selectedCount
}
项`
}}
<
/div
>
<
div
class
=
"header-left-item2 text-tip-1 cancel"
@
click
=
"handleClearAll"
v
-
show
=
"selectedCount"
>
{{
'取消'
}}
<
div
class
=
"header-left-item2 text-tip-1 cancel"
@
click
=
"handleClearAll"
v
-
show
=
"selectedCount"
>
<
div
class
=
"header-left-item3 text-tip-1"
v
-
if
=
"isShowAllDataMaxLengthTip"
>
{{
`(当前最大选择不能超过1万条!)`
}}
<
/div
>
{{
"取消"
}}
<
div
class
=
"header-left-item3 text-tip-1"
v
-
if
=
"isShowAllDataMaxLengthTip"
>
{{
`(当前最大选择不能超过1万条!)`
}}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"header-right"
>
<
div
class
=
"header-right"
>
<
div
class
=
"header-right-item item1"
>
<
div
class
=
"header-right-item item1"
>
<
div
class
=
"icon"
>
<
div
class
=
"icon"
>
<
img
src
=
"../assets/icons/download.svg"
alt
=
""
>
<
img
src
=
"../assets/icons/download.svg"
alt
=
""
/
>
<
/div
>
<
/div
>
<
div
class
=
"text text-tip-1"
@
click
=
"handleExport"
>
{{
'导出'
}}
<
/div
>
<
div
class
=
"text text-tip-1"
@
click
=
"handleExport"
>
{{
"导出"
}}
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"header-right-item2 item2"
>
<
div
class
=
"header-right-item2 item2"
>
<
el
-
select
v
-
model
=
"curOperation"
placeholder
=
"批量操作"
style
=
"width: 120px"
>
<
el
-
select
v
-
model
=
"curOperation"
placeholder
=
"批量操作"
style
=
"width: 120px"
>
...
@@ -121,7 +121,8 @@
...
@@ -121,7 +121,8 @@
<
el
-
table
-
column
type
=
"selection"
width
=
"40"
/>
<
el
-
table
-
column
type
=
"selection"
width
=
"40"
/>
<
el
-
table
-
column
label
=
"报告名称"
width
=
"720"
>
<
el
-
table
-
column
label
=
"报告名称"
width
=
"720"
>
<
template
#
default
=
"scope"
>
<
template
#
default
=
"scope"
>
<
span
class
=
"title-item text-compact-bold"
@
click
=
"handleClickToDetail(scope.row)"
>
{{
scope
.
row
.
originalTitle
<
span
class
=
"title-item text-compact-bold"
@
click
=
"handleClickToDetail(scope.row)"
>
{{
scope
.
row
.
originalTitle
}}
<
/span
>
}}
<
/span
>
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
...
@@ -130,16 +131,16 @@
...
@@ -130,16 +131,16 @@
<
/el-table-column
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"发布智库"
>
<
el
-
table
-
column
label
=
"发布智库"
>
<
template
#
default
=
"scope"
>
<
template
#
default
=
"scope"
>
<
span
class
=
"person-item text-compact"
@
click
=
"handlePerClick(scope.row)"
>
{{
scope
.
row
.
organizationName
<
span
class
=
"person-item text-compact"
@
click
=
"handlePerClick(scope.row)"
>
{{
scope
.
row
.
organizationName
}}
<
/span
>
}}
<
/span
>
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"涉及领域"
width
=
"350"
class
-
name
=
"date-column"
>
<
el
-
table
-
column
label
=
"涉及领域"
width
=
"350"
class
-
name
=
"date-column"
>
<
template
#
default
=
"scope"
>
<
template
#
default
=
"scope"
>
<
div
class
=
"tag-box"
>
<
div
class
=
"tag-box"
>
<
AreaTag
v
-
for
=
"
tag, index
in scope.row.domains"
:
key
=
"index"
:
tagName
=
"tag"
/>
<
AreaTag
v
-
for
=
"
(tag, index)
in scope.row.domains"
:
key
=
"index"
:
tagName
=
"tag"
/>
<
/div
>
<
/div
>
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"类型"
width
=
"100"
>
<
el
-
table
-
column
label
=
"类型"
width
=
"100"
>
...
@@ -157,64 +158,64 @@
...
@@ -157,64 +158,64 @@
<
/template
>
<
/template
>
<
script
setup
>
<
script
setup
>
import
{
ref
,
computed
,
watch
,
onMounted
,
nextTick
}
from
'vue'
import
{
ref
,
computed
,
watch
,
onMounted
,
nextTick
}
from
"vue"
;
import
ChartContainer
from
'../components/ChartContainer/index.vue'
import
ChartContainer
from
"../components/ChartContainer/index.vue"
;
import
ChartHeader
from
'../components/ChartHeader/index.vue'
import
ChartHeader
from
"../components/ChartHeader/index.vue"
;
import
ActiveTag
from
'../components/ActiveTag/index.vue'
import
ActiveTag
from
"../components/ActiveTag/index.vue"
;
import
HeaderBtnBox
from
'../components/HeaderBtnBox/index.vue'
import
HeaderBtnBox
from
"../components/HeaderBtnBox/index.vue"
;
import
LineChart
from
'../components/LineChart/index.vue'
import
LineChart
from
"../components/LineChart/index.vue"
;
import
PieChart
from
'../components/PieChart/index.vue'
import
PieChart
from
"../components/PieChart/index.vue"
;
import
BarChart
from
'../components/BarChart/index.vue'
import
BarChart
from
"../components/BarChart/index.vue"
;
import
RaderChart
from
'../components/RadarChart/idnex.vue'
import
RaderChart
from
"../components/RadarChart/idnex.vue"
;
import
SelectBox
from
'../components/SelectBox/index.vue'
import
SelectBox
from
"../components/SelectBox/index.vue"
;
import
InputBox
from
'../components/InputBox/index.vue'
import
InputBox
from
"../components/InputBox/index.vue"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
useRoute
}
from
"vue-router"
;
import
router
from
'@/router'
import
router
from
"@/router"
;
import
{
search
,
getThinkTankList
}
from
'@/api/comprehensiveSearch'
import
{
search
,
getThinkTankList
}
from
"@/api/comprehensiveSearch"
;
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
"element-plus"
;
import
getDateRange
from
'@/utils/getDateRange'
import
getDateRange
from
"@/utils/getDateRange"
;
import
{
getDepartmentList
}
from
"@/api/decree/home"
;
import
{
getDepartmentList
}
from
"@/api/decree/home"
;
const
route
=
useRoute
();
const
route
=
useRoute
();
// 图表/数据
// 图表/数据
const
isShowChart
=
ref
(
false
)
const
isShowChart
=
ref
(
false
)
;
// 点击切换数据/图表
// 点击切换数据/图表
const
handleSwitchChartData
=
()
=>
{
const
handleSwitchChartData
=
()
=>
{
isShowChart
.
value
=
!
isShowChart
.
value
isShowChart
.
value
=
!
isShowChart
.
value
;
if
(
isShowChart
.
value
)
{
if
(
isShowChart
.
value
)
{
const
curDemensionItem
=
staticsDemensionList
.
value
.
filter
(
item
=>
{
const
curDemensionItem
=
staticsDemensionList
.
value
.
filter
(
item
=>
{
return
item
.
name
===
curDemension
.
value
return
item
.
name
===
curDemension
.
value
;
}
)[
0
]
}
)[
0
]
;
setTimeout
(()
=>
{
setTimeout
(()
=>
{
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
]
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
]
;
if
(
curDemension
.
value
===
'发布时间'
)
{
if
(
curDemension
.
value
===
"发布时间"
)
{
if
(
selectedTime
.
value
===
'按月度统计'
)
{
if
(
selectedTime
.
value
===
"按月度统计"
)
{
curChartData
.
value
=
curDemensionItem
.
data
curChartData
.
value
=
curDemensionItem
.
data
;
}
else
if
(
selectedTime
.
value
===
'按季度统计'
)
{
}
else
if
(
selectedTime
.
value
===
"按季度统计"
)
{
curChartData
.
value
=
curDemensionItem
.
quatarData
curChartData
.
value
=
curDemensionItem
.
quatarData
;
}
else
{
}
else
{
curChartData
.
value
=
curDemensionItem
.
yearData
curChartData
.
value
=
curDemensionItem
.
yearData
;
}
}
}
else
{
}
else
{
curChartData
.
value
=
curDemensionItem
.
data
curChartData
.
value
=
curDemensionItem
.
data
;
}
}
}
)
}
)
;
}
}
}
}
;
// 总计数据
// 总计数据
const
totalNum
=
ref
(
0
)
const
totalNum
=
ref
(
0
)
;
// 统计维度列表
// 统计维度列表
const
staticsDemensionList
=
ref
([
const
staticsDemensionList
=
ref
([
{
{
name
:
'发布时间'
,
name
:
"发布时间"
,
active
:
true
,
active
:
true
,
chartTypeList
:
[
'折线图'
,
'柱状图'
],
chartTypeList
:
[
"折线图"
,
"柱状图"
],
chartTitle
:
'美国智库报告数量随时间变化趋势'
,
chartTitle
:
"美国智库报告数量随时间变化趋势"
,
data
:
{
data
:
{
dataX
:
[],
dataX
:
[],
dataY
:
[]
dataY
:
[]
...
@@ -229,207 +230,192 @@ const staticsDemensionList = ref([
...
@@ -229,207 +230,192 @@ const staticsDemensionList = ref([
}
}
}
,
}
,
{
{
name
:
'科技领域'
,
name
:
"科技领域"
,
active
:
false
,
active
:
false
,
chartTypeList
:
[
'饼状图'
],
chartTypeList
:
[
"饼状图"
],
chartTitle
:
'美国智库报告领域分布'
,
chartTitle
:
"美国智库报告领域分布"
,
data
:
[]
data
:
[]
}
,
}
,
{
{
name
:
'发布智库'
,
name
:
"发布智库"
,
active
:
false
,
active
:
false
,
chartTypeList
:
[
'饼状图'
],
chartTypeList
:
[
"饼状图"
],
chartTitle
:
'美国智库报告发布智库分布'
,
chartTitle
:
"美国智库报告发布智库分布"
,
data
:
[]
data
:
[]
}
}
])
])
;
// 当前维度下的图表列表
// 当前维度下的图表列表
const
curChartTypeList
=
computed
(()
=>
{
const
curChartTypeList
=
computed
(()
=>
{
let
arr
=
staticsDemensionList
.
value
.
filter
(
item
=>
item
.
active
)
let
arr
=
staticsDemensionList
.
value
.
filter
(
item
=>
item
.
active
)
;
return
arr
[
0
].
chartTypeList
return
arr
[
0
].
chartTypeList
;
}
)
}
)
;
// 当前图表标题
// 当前图表标题
const
curChartTitle
=
computed
(()
=>
{
const
curChartTitle
=
computed
(()
=>
{
let
arr
=
staticsDemensionList
.
value
.
filter
(
item
=>
item
.
active
)
let
arr
=
staticsDemensionList
.
value
.
filter
(
item
=>
item
.
active
)
;
return
arr
[
0
].
chartTitle
return
arr
[
0
].
chartTitle
;
}
)
}
)
;
// 当前维度
// 当前维度
const
curDemension
=
ref
(
'发布时间'
)
const
curDemension
=
ref
(
"发布时间"
);
// 点击维度item
// 点击维度item
const
handleClickDemensionItem
=
(
val
)
=>
{
const
handleClickDemensionItem
=
val
=>
{
activeChart
.
value
=
''
activeChart
.
value
=
""
;
staticsDemensionList
.
value
.
forEach
(
item
=>
{
staticsDemensionList
.
value
.
forEach
(
item
=>
{
item
.
active
=
false
item
.
active
=
false
;
}
)
}
)
;
val
.
active
=
true
val
.
active
=
true
;
curDemension
.
value
=
val
.
name
curDemension
.
value
=
val
.
name
;
setTimeout
(()
=>
{
setTimeout
(()
=>
{
activeChart
.
value
=
val
.
chartTypeList
[
0
]
activeChart
.
value
=
val
.
chartTypeList
[
0
]
;
if
(
curDemension
.
value
===
'发布时间'
&&
selectedTime
.
value
===
'按年度统计'
)
{
if
(
curDemension
.
value
===
"发布时间"
&&
selectedTime
.
value
===
"按年度统计"
)
{
curChartData
.
value
=
val
.
yearData
curChartData
.
value
=
val
.
yearData
;
}
else
if
(
curDemension
.
value
===
'发布时间'
&&
selectedTime
.
value
===
'按季度统计'
)
{
}
else
if
(
curDemension
.
value
===
"发布时间"
&&
selectedTime
.
value
===
"按季度统计"
)
{
curChartData
.
value
=
val
.
quatarData
curChartData
.
value
=
val
.
quatarData
;
}
else
{
}
else
{
curChartData
.
value
=
val
.
data
curChartData
.
value
=
val
.
data
;
}
}
}
)
}
)
;
}
}
;
// 时间图表 当前选择时间
// 时间图表 当前选择时间
const
selectedTime
=
ref
(
'按月统计'
)
const
selectedTime
=
ref
(
"按月统计"
);
// 时间图表-时间列表
// 时间图表-时间列表
const
timeList
=
ref
([
const
timeList
=
ref
([
{
{
label
:
'按年度统计'
,
label
:
"按年度统计"
,
value
:
'按年度统计'
value
:
"按年度统计"
}
,
}
,
{
{
label
:
'按季度统计'
,
label
:
"按季度统计"
,
value
:
'按季度统计'
value
:
"按季度统计"
}
,
}
,
{
{
label
:
'按月度统计'
,
label
:
"按月度统计"
,
value
:
'按月度统计'
value
:
"按月度统计"
}
,
}
])
])
;
const
handleChangeTime
=
value
=>
{
const
handleChangeTime
=
value
=>
{
let
curChart
=
activeChart
.
value
let
curChart
=
activeChart
.
value
;
activeChart
.
value
=
''
activeChart
.
value
=
""
;
if
(
value
===
'按月度统计'
)
{
if
(
value
===
"按月度统计"
)
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
activeChart
.
value
=
curChart
activeChart
.
value
=
curChart
;
curChartData
.
value
=
staticsDemensionList
.
value
[
0
].
data
curChartData
.
value
=
staticsDemensionList
.
value
[
0
].
data
;
}
)
}
)
;
}
else
if
(
value
===
'按季度统计'
)
{
}
else
if
(
value
===
"按季度统计"
)
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
activeChart
.
value
=
curChart
activeChart
.
value
=
curChart
;
curChartData
.
value
=
staticsDemensionList
.
value
[
0
].
quatarData
curChartData
.
value
=
staticsDemensionList
.
value
[
0
].
quatarData
;
}
)
}
)
;
}
else
{
}
else
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
activeChart
.
value
=
curChart
activeChart
.
value
=
curChart
;
curChartData
.
value
=
staticsDemensionList
.
value
[
0
].
yearData
curChartData
.
value
=
staticsDemensionList
.
value
[
0
].
yearData
;
}
)
}
)
;
}
}
}
}
;
// 激活的标签列表
// 激活的标签列表
const
activeTagList
=
computed
(()
=>
{
const
activeTagList
=
computed
(()
=>
{
const
arr
=
[]
const
arr
=
[];
if
(
selectedArea
.
value
&&
selectedArea
.
value
!==
'全部领域'
)
{
if
(
selectedArea
.
value
&&
selectedArea
.
value
!==
"全部领域"
)
{
arr
.
push
(
arr
.
push
({
{
tag
:
"科技领域"
,
tag
:
'科技领域'
,
name
:
selectedArea
.
value
name
:
selectedArea
.
value
}
);
}
)
}
}
if
(
selectedDate
.
value
===
'自定义'
)
{
if
(
selectedDate
.
value
===
"自定义"
)
{
arr
.
push
(
arr
.
push
({
{
tag
:
"发布时间"
,
tag
:
'发布时间'
,
name
:
customTime
.
value
.
join
(
"至"
)
name
:
customTime
.
value
.
join
(
'至'
)
}
);
}
)
}
}
if
(
selectedThinkTank
.
value
&&
selectedThinkTank
.
value
!==
'全部智库'
)
{
if
(
selectedThinkTank
.
value
&&
selectedThinkTank
.
value
!==
"全部智库"
)
{
arr
.
push
(
arr
.
push
({
{
tag
:
"发布智库"
,
tag
:
'发布智库'
,
name
:
selectedThinkTank
.
value
name
:
selectedThinkTank
.
value
}
);
}
)
}
}
if
(
reportName
.
value
)
{
if
(
reportName
.
value
)
{
arr
.
push
(
arr
.
push
({
{
tag
:
"报告名称"
,
tag
:
'报告名称'
,
name
:
reportName
.
value
name
:
reportName
.
value
}
);
}
)
}
}
if
(
isInvolveCn
.
value
)
{
if
(
isInvolveCn
.
value
)
{
const
involveStr
=
'涉华'
const
involveStr
=
"涉华"
;
arr
.
push
(
arr
.
push
({
{
tag
:
"是否涉华"
,
tag
:
'是否涉华'
,
name
:
involveStr
name
:
involveStr
}
);
}
)
}
}
return
arr
return
arr
;
}
);
}
)
// 关闭当前标签
// 关闭当前标签
const
handleCloseCurTag
=
(
tag
,
index
)
=>
{
const
handleCloseCurTag
=
(
tag
,
index
)
=>
{
switch
(
tag
.
tag
)
{
switch
(
tag
.
tag
)
{
case
'科技领域'
:
case
"科技领域"
:
selectedArea
.
value
=
'全部领域'
selectedArea
.
value
=
"全部领域"
;
break
break
;
case
'发布时间'
:
case
"发布时间"
:
selectedDate
.
value
=
''
selectedDate
.
value
=
""
;
customTime
.
value
=
[]
customTime
.
value
=
[];
break
break
;
case
'发布智库'
:
case
"发布智库"
:
selectedThinkTank
.
value
=
'全部智库'
selectedThinkTank
.
value
=
"全部智库"
;
break
break
;
case
'报告名称'
:
case
"报告名称"
:
reportName
.
value
=
''
reportName
.
value
=
""
;
break
break
;
case
'是否涉华'
:
case
"是否涉华"
:
isInvolveCn
.
value
=
false
isInvolveCn
.
value
=
false
;
break
break
;
}
}
}
;
}
const
activeChart
=
ref
(
""
);
// 当前激活的图表
const
activeChart
=
ref
(
''
)
// 当前激活的图表
// 切换当前图表
// 切换当前图表
const
handleSwitchActiveChart
=
val
=>
{
const
handleSwitchActiveChart
=
val
=>
{
activeChart
.
value
=
val
.
name
activeChart
.
value
=
val
.
name
;
}
}
;
// 雷达图数据
// 雷达图数据
const
radarChartData
=
ref
({
const
radarChartData
=
ref
({
title
:
[
title
:
[
{
{
name
:
'航空航天'
,
name
:
"航空航天"
,
max
:
10
max
:
10
}
,
}
,
{
{
name
:
'先进制造'
,
name
:
"先进制造"
,
max
:
10
max
:
10
}
,
}
,
{
{
name
:
'量子科技'
,
name
:
"量子科技"
,
max
:
10
max
:
10
}
,
}
,
{
{
name
:
'人工智能'
,
name
:
"人工智能"
,
max
:
10
max
:
10
}
,
}
,
{
{
name
:
'新材料'
,
name
:
"新材料"
,
max
:
10
max
:
10
}
,
}
,
{
{
name
:
'集成电路'
,
name
:
"集成电路"
,
max
:
10
max
:
10
}
,
}
],
],
data
:
[
data
:
[
{
{
name
:
"337调查"
,
name
:
"337调查"
,
value
:
[
10
,
5
,
2
,
8
,
5
,
7
value
:
[
10
,
5
,
2
,
8
,
5
,
7
]
]
}
,
}
,
{
{
name
:
"232调查"
,
name
:
"232调查"
,
...
@@ -440,151 +426,148 @@ const radarChartData = ref({
...
@@ -440,151 +426,148 @@ const radarChartData = ref({
value
:
[
5
,
8
,
2
,
9
,
1
,
5
]
value
:
[
5
,
8
,
2
,
9
,
1
,
5
]
}
}
]
]
}
}
);
)
// 数据- 是否全选
// 数据- 是否全选
const
isSelectedAll
=
ref
(
false
)
const
isSelectedAll
=
ref
(
false
)
;
// 批量操作-当前操作
// 批量操作-当前操作
const
curOperation
=
ref
(
''
)
const
curOperation
=
ref
(
""
);
const
operationList
=
ref
([
const
operationList
=
ref
([
{
{
name
:
'aaa'
,
name
:
"aaa"
,
id
:
'aaa'
id
:
"aaa"
}
,
}
,
{
{
name
:
'bbb'
,
name
:
"bbb"
,
id
:
'bbb'
id
:
"bbb"
}
,
}
,
{
{
name
:
'ccc'
,
name
:
"ccc"
,
id
:
'ccc'
id
:
"ccc"
}
,
}
])
])
;
// 科技领域
// 科技领域
const
areaPlaceHolder
=
ref
(
'请选择领域'
)
const
areaPlaceHolder
=
ref
(
"请选择领域"
);
const
selectedArea
=
ref
(
'全部领域'
)
const
selectedArea
=
ref
(
"全部领域"
);
const
areaList
=
ref
([
const
areaList
=
ref
([
{
{
name
:
'全部领域'
,
name
:
"全部领域"
,
id
:
'全部领域'
id
:
"全部领域"
}
,
}
,
{
{
name
:
'人工智能'
,
name
:
"人工智能"
,
id
:
'人工智能'
id
:
"人工智能"
}
,
}
,
{
{
name
:
'生物科技'
,
name
:
"生物科技"
,
id
:
'生物科技'
id
:
"生物科技"
}
,
}
,
{
{
name
:
'新一代通信网络'
,
name
:
"新一代通信网络"
,
id
:
'新一代通信网络'
id
:
"新一代通信网络"
}
,
}
,
{
{
name
:
'量子科技'
,
name
:
"量子科技"
,
id
:
'量子科技'
id
:
"量子科技"
}
,
}
,
{
{
name
:
'新能源'
,
name
:
"新能源"
,
id
:
'新能源'
id
:
"新能源"
}
,
}
,
{
{
name
:
'集成电路'
,
name
:
"集成电路"
,
id
:
'集成电路'
id
:
"集成电路"
}
,
}
,
{
{
name
:
'海洋'
,
name
:
"海洋"
,
id
:
'海洋'
id
:
"海洋"
}
,
}
,
{
{
name
:
'先进制造'
,
name
:
"先进制造"
,
id
:
'先进制造'
id
:
"先进制造"
}
,
}
,
{
{
name
:
'新材料'
,
name
:
"新材料"
,
id
:
'新材料'
id
:
"新材料"
}
,
}
,
{
{
name
:
'航空航天'
,
name
:
"航空航天"
,
id
:
'航空航天'
id
:
"航空航天"
}
,
}
,
{
{
name
:
'太空'
,
name
:
"太空"
,
id
:
'太空'
id
:
"太空"
}
,
}
,
{
{
name
:
'深海'
,
name
:
"深海"
,
id
:
'深海'
id
:
"深海"
}
,
}
,
{
{
name
:
'极地'
,
name
:
"极地"
,
id
:
'极地'
id
:
"极地"
}
,
}
,
{
{
name
:
'核'
,
name
:
"核"
,
id
:
'核'
id
:
"核"
}
,
}
,
{
{
name
:
'其他'
,
name
:
"其他"
,
id
:
'其他'
id
:
"其他"
}
,
}
])
])
;
const
handleSelectArea
=
(
value
)
=>
{
const
handleSelectArea
=
value
=>
{
selectedArea
.
value
=
value
selectedArea
.
value
=
value
;
}
}
;
// 提出时间
// 提出时间
const
DatePlaceHolder
=
ref
(
'请选择时间'
)
const
DatePlaceHolder
=
ref
(
"请选择时间"
);
const
selectedDate
=
ref
(
''
)
const
selectedDate
=
ref
(
""
);
const
dateList
=
ref
([
const
dateList
=
ref
([
{
{
name
:
'自定义'
,
name
:
"自定义"
,
id
:
'自定义'
id
:
"自定义"
}
,
}
,
{
{
name
:
'近一年'
,
name
:
"近一年"
,
id
:
'近一年'
id
:
"近一年"
}
,
}
,
{
{
name
:
'近半年'
,
name
:
"近半年"
,
id
:
'近半年'
id
:
"近半年"
}
,
}
,
{
{
name
:
'近三月'
,
name
:
"近三月"
,
id
:
'近三月'
id
:
"近三月"
}
,
}
,
{
{
name
:
'近一月'
,
name
:
"近一月"
,
id
:
'近一月'
id
:
"近一月"
}
}
])
])
;
const
customTime
=
ref
([])
// 自定义时间
const
customTime
=
ref
([])
;
// 自定义时间
const
handleCustomDate
=
value
=>
{
const
handleCustomDate
=
value
=>
{
customTime
.
value
=
value
customTime
.
value
=
value
;
}
}
;
const
handleSelectDate
=
(
value
)
=>
{
const
handleSelectDate
=
value
=>
{
selectedDate
.
value
=
value
selectedDate
.
value
=
value
;
if
(
selectedDate
.
value
!==
'自定义'
)
{
if
(
selectedDate
.
value
!==
"自定义"
)
{
customTime
.
value
=
getDateRange
(
selectedDate
.
value
)
customTime
.
value
=
getDateRange
(
selectedDate
.
value
)
;
}
}
}
}
;
// 发布智库
// 发布智库
const
thinkTankList
=
ref
([
const
thinkTankList
=
ref
([
{
{
name
:
'全部智库'
,
name
:
"全部智库"
,
id
:
'全部智库'
id
:
"全部智库"
}
,
}
])
])
;
const
selectedThinkTank
=
ref
(
'全部智库'
)
const
selectedThinkTank
=
ref
(
"全部智库"
);
const
thinkTankPlaceHolder
=
ref
(
'请选择发布智库'
)
const
thinkTankPlaceHolder
=
ref
(
"请选择发布智库"
);
const
handleSelectThinkTank
=
value
=>
{
const
handleSelectThinkTank
=
value
=>
{
selectedThinkTank
.
value
=
value
selectedThinkTank
.
value
=
value
;
}
}
;
const
handleGetThinkTankList
=
async
()
=>
{
const
handleGetThinkTankList
=
async
()
=>
{
try
{
try
{
...
@@ -594,65 +577,60 @@ const handleGetThinkTankList = async () => {
...
@@ -594,65 +577,60 @@ const handleGetThinkTankList = async () => {
return
{
return
{
name
:
item
,
name
:
item
,
id
:
item
id
:
item
}
}
;
}
)
}
);
thinkTankList
.
value
=
[...
thinkTankList
.
value
,
...
arr
]
thinkTankList
.
value
=
[...
thinkTankList
.
value
,
...
arr
];
}
catch
(
error
)
{
}
}
catch
(
error
)
{
}
;
}
}
// 作者
// 作者
const
authorList
=
ref
([
const
authorList
=
ref
([
{
{
name
:
'全部作者'
,
name
:
"全部作者"
,
id
:
'全部作者'
id
:
"全部作者"
}
,
}
])
])
;
const
selectedAuthor
=
ref
(
'暂无作者信息'
)
const
selectedAuthor
=
ref
(
"暂无作者信息"
);
const
authorPlaceHolder
=
ref
(
'请选择发布智库'
)
const
authorPlaceHolder
=
ref
(
"请选择发布智库"
);
const
handleSelectAuthor
=
value
=>
{
const
handleSelectAuthor
=
value
=>
{
selectedAuthor
.
value
=
value
selectedAuthor
.
value
=
value
;
}
}
;
// 报告名称列表
// 报告名称列表
const
reportName
=
ref
(
''
)
const
reportName
=
ref
(
""
);
const
handleInputReportName
=
(
value
)
=>
{
const
handleInputReportName
=
value
=>
{
reportName
.
value
=
value
reportName
.
value
=
value
;
}
}
;
// 是否涉华
// 是否涉华
const
isInvolveCn
=
ref
(
false
)
const
isInvolveCn
=
ref
(
false
)
;
// 清空条件
// 清空条件
const
handleClear
=
()
=>
{
const
handleClear
=
()
=>
{
selectedArea
.
value
=
'全部领域'
selectedArea
.
value
=
"全部领域"
;
selectedDate
.
value
=
''
selectedDate
.
value
=
""
;
customTime
.
value
=
[]
customTime
.
value
=
[]
;
selectedThinkTank
.
value
=
'全部智库'
selectedThinkTank
.
value
=
"全部智库"
;
reportName
.
value
=
''
reportName
.
value
=
""
;
isInvolveCn
.
value
=
false
isInvolveCn
.
value
=
false
;
ElMessage
.
success
(
'已清空条件!'
)
ElMessage
.
success
(
"已清空条件!"
);
}
}
;
// 确定
// 确定
const
handleConfirm
=
()
=>
{
const
handleConfirm
=
()
=>
{
fetchTableData
()
fetchTableData
()
;
}
}
;
// 展开全部 / 收起
// 展开全部 / 收起
const
isFolderAll
=
ref
(
false
)
const
isFolderAll
=
ref
(
false
)
;
const
handleSwitchFolderAll
=
()
=>
{
const
handleSwitchFolderAll
=
()
=>
{
isFolderAll
.
value
=
!
isFolderAll
.
value
isFolderAll
.
value
=
!
isFolderAll
.
value
;
}
}
;
const
tableRef
=
ref
(
null
)
const
tableRef
=
ref
(
null
)
;
// 表格数据
// 表格数据
const
tableData
=
ref
([
const
tableData
=
ref
([]);
])
const
releaseTimeList
=
ref
([
const
releaseTimeList
=
ref
([
{
{
...
@@ -666,17 +644,17 @@ const releaseTimeList = ref([
...
@@ -666,17 +644,17 @@ const releaseTimeList = ref([
]);
]);
const
isSort
=
ref
(
true
);
// true 倒序 false 升序
const
isSort
=
ref
(
true
);
// true 倒序 false 升序
const
handlePxChange
=
val
=>
{
const
handlePxChange
=
val
=>
{
fetchTableData
()
fetchTableData
()
;
}
;
}
;
const
currentPage
=
ref
(
1
);
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
)
const
pageSize
=
ref
(
10
)
;
// 存储选中的数据(跨页)[citation:3][citation:8]
// 存储选中的数据(跨页)[citation:3][citation:8]
const
selectedMap
=
ref
(
new
Map
())
// 使用 Map 存储,key 为唯一 id
const
selectedMap
=
ref
(
new
Map
())
;
// 使用 Map 存储,key 为唯一 id
// 计算已选中的条数
// 计算已选中的条数
const
selectedCount
=
computed
(()
=>
selectedMap
.
value
.
size
)
const
selectedCount
=
computed
(()
=>
selectedMap
.
value
.
size
)
;
// 获取当前页表格数据(示例)
// 获取当前页表格数据(示例)
const
fetchTableData
=
async
()
=>
{
const
fetchTableData
=
async
()
=>
{
...
@@ -686,326 +664,318 @@ const fetchTableData = async () => {
...
@@ -686,326 +664,318 @@ const fetchTableData = async () => {
const
params
=
{
const
params
=
{
page
:
currentPage
.
value
,
page
:
currentPage
.
value
,
size
:
pageSize
.
value
,
size
:
pageSize
.
value
,
keyword
:
''
,
//
keyword: '',
type
:
4
,
// type 1= 法案 2= 政令 3 =智库 4=智库报告 5=实体清单 6= 人物 7= 机构 8=新闻 9= 社媒
type
:
4
,
// type 1= 法案 2= 政令 3 =智库 4=智库报告 5=实体清单 6= 人物 7= 机构 8=新闻 9= 社媒
domains
:
selectedArea
.
value
===
'全部领域'
?
null
:
[
selectedArea
.
value
],
// 领域
domains
:
selectedArea
.
value
===
"全部领域"
?
null
:
[
selectedArea
.
value
],
// 领域
proposedDateStart
:
customTime
.
value
[
0
]
?
customTime
.
value
[
0
]
:
null
,
// 开始日期
proposedDateStart
:
customTime
.
value
[
0
]
?
customTime
.
value
[
0
]
:
null
,
// 开始日期
proposedDateEnd
:
customTime
.
value
[
1
]
?
customTime
.
value
[
1
]
:
null
,
// 结束日期
proposedDateEnd
:
customTime
.
value
[
1
]
?
customTime
.
value
[
1
]
:
null
,
// 结束日期
organizationName
:
selectedThinkTank
.
value
===
'全部智库'
?
null
:
selectedThinkTank
.
value
,
// 智库名称
organizationName
:
selectedThinkTank
.
value
===
"全部智库"
?
null
:
selectedThinkTank
.
value
,
// 智库名称
reportNameZh
:
reportName
.
value
?
reportName
.
value
:
null
,
// 报告名称
reportNameZh
:
reportName
.
value
?
reportName
.
value
:
null
,
// 报告名称
isInvolveCn
:
isInvolveCn
.
value
?
'Y'
:
null
,
// 是否涉华
isInvolveCn
:
isInvolveCn
.
value
?
"Y"
:
null
,
// 是否涉华
sort
:
isSort
.
value
?
0
:
1
// 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
sort
:
isSort
.
value
?
0
:
1
// 0 先按分数降序 后按时间降序 1 先按分数降序,再按时间升序
}
}
;
try
{
try
{
const
res
=
await
search
(
params
)
const
res
=
await
search
(
params
)
;
console
.
log
(
'搜索结果'
,
res
);
console
.
log
(
"搜索结果"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
tableData
.
value
=
res
.
data
.
records
tableData
.
value
=
res
.
data
.
records
;
totalNum
.
value
=
res
.
data
.
total
totalNum
.
value
=
res
.
data
.
total
;
staticsDemensionList
.
value
[
0
].
data
=
{
staticsDemensionList
.
value
[
0
].
data
=
{
dataX
:
Object
.
keys
(
res
.
data
.
aggregationsDate
),
dataX
:
Object
.
keys
(
res
.
data
.
aggregationsDate
),
dataY
:
Object
.
values
(
res
.
data
.
aggregationsDate
).
map
(
value
=>
Number
(
value
))
dataY
:
Object
.
values
(
res
.
data
.
aggregationsDate
).
map
(
value
=>
Number
(
value
))
}
}
;
staticsDemensionList
.
value
[
0
].
quatarData
=
{
staticsDemensionList
.
value
[
0
].
quatarData
=
{
dataX
:
Object
.
keys
(
res
.
data
.
aggregationsQuarter
),
dataX
:
Object
.
keys
(
res
.
data
.
aggregationsQuarter
),
dataY
:
Object
.
values
(
res
.
data
.
aggregationsQuarter
).
map
(
value
=>
Number
(
value
))
dataY
:
Object
.
values
(
res
.
data
.
aggregationsQuarter
).
map
(
value
=>
Number
(
value
))
}
}
;
staticsDemensionList
.
value
[
0
].
yearData
=
{
staticsDemensionList
.
value
[
0
].
yearData
=
{
dataX
:
Object
.
keys
(
res
.
data
.
aggregationsYear
),
dataX
:
Object
.
keys
(
res
.
data
.
aggregationsYear
),
dataY
:
Object
.
values
(
res
.
data
.
aggregationsYear
).
map
(
value
=>
Number
(
value
))
dataY
:
Object
.
values
(
res
.
data
.
aggregationsYear
).
map
(
value
=>
Number
(
value
))
}
}
;
staticsDemensionList
.
value
[
1
].
data
=
Object
.
entries
(
res
.
data
.
aggregationsDomain
).
map
(([
key
,
value
])
=>
({
staticsDemensionList
.
value
[
1
].
data
=
Object
.
entries
(
res
.
data
.
aggregationsDomain
).
map
(([
key
,
value
])
=>
({
name
:
key
,
name
:
key
,
value
:
Number
(
value
)
value
:
Number
(
value
)
}
))
}
))
;
staticsDemensionList
.
value
[
2
].
data
=
Object
.
entries
(
res
.
data
.
aggregationsorganizationName
).
map
(([
key
,
value
])
=>
({
staticsDemensionList
.
value
[
2
].
data
=
Object
.
entries
(
res
.
data
.
aggregationsorganizationName
).
map
(([
key
,
value
])
=>
({
name
:
key
,
name
:
key
,
value
:
Number
(
value
)
value
:
Number
(
value
)
}
))
}
));
}
}
const
curDemensionItem
=
staticsDemensionList
.
value
.
filter
(
item
=>
{
const
curDemensionItem
=
staticsDemensionList
.
value
.
filter
(
item
=>
{
return
item
.
name
===
curDemension
.
value
return
item
.
name
===
curDemension
.
value
;
}
)[
0
]
}
)[
0
]
;
activeChart
.
value
=
''
activeChart
.
value
=
""
;
setTimeout
(()
=>
{
setTimeout
(()
=>
{
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
]
activeChart
.
value
=
curDemensionItem
.
chartTypeList
[
0
];
curChartData
.
value
=
curDemensionItem
.
data
curChartData
.
value
=
curDemensionItem
.
data
;
}
)
}
);
}
catch
(
error
)
{
}
catch
(
error
)
{
}
}
// tableData.value = res.data
// tableData.value = res.data
// total.value = res.total
// total.value = res.total
// 数据加载后,回显已选中的行
// 数据加载后,回显已选中的行
nextTick
(()
=>
{
nextTick
(()
=>
{
tableData
.
value
.
forEach
(
row
=>
{
tableData
.
value
.
forEach
(
row
=>
{
if
(
selectedMap
.
value
.
has
(
row
.
id
))
{
if
(
selectedMap
.
value
.
has
(
row
.
id
))
{
tableRef
.
value
?.
toggleRowSelection
(
row
,
true
)
tableRef
.
value
?.
toggleRowSelection
(
row
,
true
)
;
}
}
}
)
}
)
;
}
)
}
)
;
}
}
;
const
allData
=
ref
([])
const
allData
=
ref
([])
;
// 获取筛选条件下全部表格数据
// 获取筛选条件下全部表格数据
const
fetchAllData
=
async
()
=>
{
const
fetchAllData
=
async
()
=>
{
const
params
=
{
const
params
=
{
page
:
1
,
page
:
1
,
size
:
9999
,
size
:
9999
,
keyword
:
''
,
//
keyword: '',
type
:
4
,
// type 1= 法案 2= 政令 3 =智库 4=智库报告 5=实体清单【制裁记录】 6= 人物 7= 机构 8=新闻 9= 社媒
type
:
4
,
// type 1= 法案 2= 政令 3 =智库 4=智库报告 5=实体清单【制裁记录】 6= 人物 7= 机构 8=新闻 9= 社媒
domains
:
selectedArea
.
value
===
'全部领域'
?
null
:
[
selectedArea
.
value
],
domains
:
selectedArea
.
value
===
"全部领域"
?
null
:
[
selectedArea
.
value
],
proposedDateStart
:
customTime
.
value
[
0
],
proposedDateStart
:
customTime
.
value
[
0
],
proposedDateEnd
:
customTime
.
value
[
1
],
proposedDateEnd
:
customTime
.
value
[
1
],
organizationName
:
selectedThinkTank
.
value
===
'全部智库'
?
null
:
selectedThinkTank
.
value
,
organizationName
:
selectedThinkTank
.
value
===
"全部智库"
?
null
:
selectedThinkTank
.
value
,
reportNameZh
:
reportName
.
value
?
reportName
.
value
:
null
,
reportNameZh
:
reportName
.
value
?
reportName
.
value
:
null
,
isInvolveCn
:
isInvolveCn
.
value
?
'Y'
:
'N'
,
isInvolveCn
:
isInvolveCn
.
value
?
"Y"
:
"N"
,
sort
:
isSort
.
value
?
0
:
1
sort
:
isSort
.
value
?
0
:
1
}
}
;
try
{
try
{
const
res
=
await
search
(
params
)
const
res
=
await
search
(
params
)
;
console
.
log
(
'搜索结果'
,
res
);
console
.
log
(
"搜索结果"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
allData
.
value
=
res
.
data
.
records
allData
.
value
=
res
.
data
.
records
;
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
ElMessage
.
error
(
'加载全部数据出错!'
)
ElMessage
.
error
(
"加载全部数据出错!"
);
}
}
}
}
;
// 单选事件
// 单选事件
const
handleSelect
=
(
selection
,
row
)
=>
{
const
handleSelect
=
(
selection
,
row
)
=>
{
if
(
selection
.
some
(
item
=>
item
.
id
===
row
.
id
))
{
if
(
selection
.
some
(
item
=>
item
.
id
===
row
.
id
))
{
// 选中:添加到 Map
// 选中:添加到 Map
selectedMap
.
value
.
set
(
row
.
id
,
row
)
selectedMap
.
value
.
set
(
row
.
id
,
row
)
;
}
else
{
}
else
{
// 取消选中:从 Map 移除
// 取消选中:从 Map 移除
selectedMap
.
value
.
delete
(
row
.
id
)
selectedMap
.
value
.
delete
(
row
.
id
)
;
}
}
}
}
;
// 表格自带 当前页 全选/全不选事件
// 表格自带 当前页 全选/全不选事件
const
handleSelectAll
=
(
selection
)
=>
{
const
handleSelectAll
=
selection
=>
{
if
(
selection
.
length
>
0
)
{
if
(
selection
.
length
>
0
)
{
// 全选:将当前页所有数据添加到 Map
// 全选:将当前页所有数据添加到 Map
tableData
.
value
.
forEach
(
row
=>
{
tableData
.
value
.
forEach
(
row
=>
{
if
(
!
selectedMap
.
value
.
has
(
row
.
id
))
{
if
(
!
selectedMap
.
value
.
has
(
row
.
id
))
{
selectedMap
.
value
.
set
(
row
.
id
,
row
)
selectedMap
.
value
.
set
(
row
.
id
,
row
)
;
}
}
}
)
}
)
;
}
else
{
}
else
{
// 全不选:从 Map 中移除当前页的所有数据
// 全不选:从 Map 中移除当前页的所有数据
tableData
.
value
.
forEach
(
row
=>
{
tableData
.
value
.
forEach
(
row
=>
{
selectedMap
.
value
.
delete
(
row
.
id
)
selectedMap
.
value
.
delete
(
row
.
id
)
;
}
)
}
)
;
}
}
}
}
;
// 处理选择变化(用于统计)
// 处理选择变化(用于统计)
const
handleSelectionChange
=
(
val
)
=>
{
const
handleSelectionChange
=
val
=>
{
// 这里可以做一些额外的处理,但主要统计使用 selectedMap
// 这里可以做一些额外的处理,但主要统计使用 selectedMap
console
.
log
(
'当前页选中数量:'
,
val
.
length
)
console
.
log
(
"当前页选中数量:"
,
val
.
length
);
}
}
;
// 全选当前页按钮
// 全选当前页按钮
const
handleSelectAllPage
=
()
=>
{
const
handleSelectAllPage
=
()
=>
{
if
(
tableData
.
value
.
length
===
0
)
return
if
(
tableData
.
value
.
length
===
0
)
return
;
// 检查当前页是否已全选
// 检查当前页是否已全选
const
currentPageSelected
=
tableData
.
value
.
every
(
row
=>
const
currentPageSelected
=
tableData
.
value
.
every
(
row
=>
selectedMap
.
value
.
has
(
row
.
id
));
selectedMap
.
value
.
has
(
row
.
id
)
)
if
(
currentPageSelected
)
{
if
(
currentPageSelected
)
{
// 已全选,则不动当前页的全选
// 已全选,则不动当前页的全选
tableData
.
value
.
forEach
(
row
=>
{
tableData
.
value
.
forEach
(
row
=>
{
tableRef
.
value
.
toggleRowSelection
(
row
,
false
)
tableRef
.
value
.
toggleRowSelection
(
row
,
false
)
;
// selectedMap.value.delete(row.id)
// selectedMap.value.delete(row.id)
}
)
}
)
;
}
else
{
}
else
{
// 未全选,则全选当前页
// 未全选,则全选当前页
tableData
.
value
.
forEach
(
row
=>
{
tableData
.
value
.
forEach
(
row
=>
{
tableRef
.
value
.
toggleRowSelection
(
row
,
true
)
tableRef
.
value
.
toggleRowSelection
(
row
,
true
)
;
if
(
!
selectedMap
.
value
.
has
(
row
.
id
))
{
if
(
!
selectedMap
.
value
.
has
(
row
.
id
))
{
selectedMap
.
value
.
set
(
row
.
id
,
row
)
selectedMap
.
value
.
set
(
row
.
id
,
row
)
;
}
}
}
)
}
)
;
}
}
}
}
;
// 全选最大1万条提示
// 全选最大1万条提示
const
isShowAllDataMaxLengthTip
=
ref
(
false
)
const
isShowAllDataMaxLengthTip
=
ref
(
false
)
;
const
loading
=
ref
(
false
)
// 加载数据loading
const
loading
=
ref
(
false
)
;
// 加载数据loading
// 处理 全选(全部数据)
// 处理 全选(全部数据)
const
handleSelectAllChange
=
async
()
=>
{
const
handleSelectAllChange
=
async
()
=>
{
if
(
isSelectedAll
.
value
)
{
if
(
isSelectedAll
.
value
)
{
if
(
totalNum
.
value
>
10000
)
{
if
(
totalNum
.
value
>
10000
)
{
isShowAllDataMaxLengthTip
.
value
=
true
isShowAllDataMaxLengthTip
.
value
=
true
;
}
}
loading
.
value
=
true
loading
.
value
=
true
;
await
fetchAllData
()
await
fetchAllData
()
;
handleSelectAllPage
()
handleSelectAllPage
()
;
allData
.
value
.
forEach
(
row
=>
{
allData
.
value
.
forEach
(
row
=>
{
if
(
!
selectedMap
.
value
.
has
(
row
.
id
))
{
if
(
!
selectedMap
.
value
.
has
(
row
.
id
))
{
selectedMap
.
value
.
set
(
row
.
id
,
row
)
selectedMap
.
value
.
set
(
row
.
id
,
row
)
;
}
}
}
)
}
)
;
loading
.
value
=
false
loading
.
value
=
false
;
}
else
{
}
else
{
handleClearAll
()
handleClearAll
()
;
}
}
}
;
}
// 清空所有选择
// 清空所有选择
const
handleClearAll
=
()
=>
{
const
handleClearAll
=
()
=>
{
isSelectedAll
.
value
=
false
isSelectedAll
.
value
=
false
;
selectedMap
.
value
.
clear
()
selectedMap
.
value
.
clear
()
;
tableRef
.
value
?.
clearSelection
()
tableRef
.
value
?.
clearSelection
()
;
}
}
;
// 翻页
// 翻页
const
handleCurrentChange
=
async
(
val
)
=>
{
const
handleCurrentChange
=
async
val
=>
{
currentPage
.
value
=
val
currentPage
.
value
=
val
;
await
fetchTableData
()
await
fetchTableData
()
;
if
(
isSelectedAll
.
value
)
{
if
(
isSelectedAll
.
value
)
{
handleSelectAllPage
()
handleSelectAllPage
()
;
}
}
}
}
;
// 监听数据变化,回显选中状态 [citation:4][citation:8]
// 监听数据变化,回显选中状态 [citation:4][citation:8]
watch
(
tableData
,
()
=>
{
watch
(
tableData
,
()
=>
{
nextTick
(()
=>
{
nextTick
(()
=>
{
tableData
.
value
.
forEach
(
row
=>
{
tableData
.
value
.
forEach
(
row
=>
{
if
(
selectedMap
.
value
.
has
(
row
.
id
))
{
if
(
selectedMap
.
value
.
has
(
row
.
id
))
{
tableRef
.
value
?.
toggleRowSelection
(
row
,
true
)
tableRef
.
value
?.
toggleRowSelection
(
row
,
true
)
;
}
}
}
)
}
)
;
}
)
}
)
;
}
)
}
)
;
// 当前图表数据
// 当前图表数据
const
curChartData
=
ref
(
null
)
const
curChartData
=
ref
(
null
)
;
// 下载当前图表数据
// 下载当前图表数据
const
handleDownloadCurChartData
=
()
=>
{
const
handleDownloadCurChartData
=
()
=>
{
const
jsonStr
=
JSON
.
stringify
(
curChartData
.
value
,
null
,
2
);
const
jsonStr
=
JSON
.
stringify
(
curChartData
.
value
,
null
,
2
);
const
blob
=
new
Blob
([
jsonStr
],
{
type
:
'application/json'
}
);
const
blob
=
new
Blob
([
jsonStr
],
{
type
:
"application/json"
}
);
const
url
=
URL
.
createObjectURL
(
blob
);
const
url
=
URL
.
createObjectURL
(
blob
);
const
link
=
document
.
createElement
(
'a'
);
const
link
=
document
.
createElement
(
"a"
);
link
.
href
=
url
;
link
.
href
=
url
;
link
.
download
=
'chartData.json'
;
link
.
download
=
"chartData.json"
;
link
.
click
();
link
.
click
();
URL
.
revokeObjectURL
(
url
);
URL
.
revokeObjectURL
(
url
);
}
}
;
// 跳转到当前页 初始化筛选条件
// 跳转到当前页 初始化筛选条件
const
initParam
=
()
=>
{
const
initParam
=
()
=>
{
const
hasQuery
=
Object
.
keys
(
route
.
query
).
length
>
0
;
const
hasQuery
=
Object
.
keys
(
route
.
query
).
length
>
0
;
if
(
hasQuery
)
{
if
(
hasQuery
)
{
selectedArea
.
value
=
route
.
query
.
domains
?
route
.
query
.
domains
:
'全部领域'
selectedArea
.
value
=
route
.
query
.
domains
?
route
.
query
.
domains
:
"全部领域"
;
if
(
route
.
query
.
selectedDate
&&
Array
.
isArray
(
JSON
.
parse
(
route
.
query
.
selectedDate
))
&&
JSON
.
parse
(
route
.
query
.
selectedDate
).
length
)
{
if
(
selectedDate
.
value
=
'自定义'
route
.
query
.
selectedDate
&&
customTime
.
value
=
JSON
.
parse
(
route
.
query
.
selectedDate
)
Array
.
isArray
(
JSON
.
parse
(
route
.
query
.
selectedDate
))
&&
JSON
.
parse
(
route
.
query
.
selectedDate
).
length
)
{
selectedDate
.
value
=
"自定义"
;
customTime
.
value
=
JSON
.
parse
(
route
.
query
.
selectedDate
);
}
}
selectedThinkTank
.
value
=
route
.
query
.
orgnizationName
?
route
.
query
.
orgnizationName
:
'全部智库'
selectedThinkTank
.
value
=
route
.
query
.
orgnizationName
?
route
.
query
.
orgnizationName
:
"全部智库"
;
isInvolveCn
.
value
=
route
.
query
.
isInvolveCn
?
true
:
false
isInvolveCn
.
value
=
route
.
query
.
isInvolveCn
?
true
:
false
;
reportName
.
value
=
route
.
query
.
reportName
?
route
.
query
.
reportName
:
""
;
reportName
.
value
=
route
.
query
.
reportName
?
route
.
query
.
reportName
:
''
const
query
=
route
.
query
;
const
query
=
route
.
query
;
if
(
Object
.
keys
(
query
).
length
>
0
)
{
if
(
Object
.
keys
(
query
).
length
>
0
)
{
sessionStorage
.
setItem
(
'thinktankRouteQuery'
,
JSON
.
stringify
(
query
));
sessionStorage
.
setItem
(
"thinktankRouteQuery"
,
JSON
.
stringify
(
query
));
}
}
}
else
{
}
else
{
const
savedQuery
=
JSON
.
parse
(
sessionStorage
.
getItem
(
'thinktankRouteQuery'
)
||
'{
}
'
);
const
savedQuery
=
JSON
.
parse
(
sessionStorage
.
getItem
(
"thinktankRouteQuery"
)
||
"{
}
"
);
selectedArea
.
value
=
savedQuery
.
domains
?
savedQuery
.
domains
:
'全部领域'
selectedArea
.
value
=
savedQuery
.
domains
?
savedQuery
.
domains
:
"全部领域"
;
if
(
savedQuery
.
selectedDate
&&
Array
.
isArray
(
JSON
.
parse
(
savedQuery
.
selectedDate
))
&&
JSON
.
parse
(
savedQuery
.
selectedDate
).
length
)
{
if
(
selectedDate
.
value
=
'自定义'
savedQuery
.
selectedDate
&&
customTime
.
value
=
JSON
.
parse
(
savedQuery
.
selectedDate
)
Array
.
isArray
(
JSON
.
parse
(
savedQuery
.
selectedDate
))
&&
JSON
.
parse
(
savedQuery
.
selectedDate
).
length
)
{
selectedDate
.
value
=
"自定义"
;
customTime
.
value
=
JSON
.
parse
(
savedQuery
.
selectedDate
);
}
}
isInvolveCn
.
value
=
savedQuery
.
isInvolveCn
?
true
:
false
isInvolveCn
.
value
=
savedQuery
.
isInvolveCn
?
true
:
false
;
reportName
.
value
=
savedQuery
.
reportName
?
savedQuery
.
reportName
:
''
reportName
.
value
=
savedQuery
.
reportName
?
savedQuery
.
reportName
:
""
;
}
}
}
;
}
// 跳转政令详情
// 跳转政令详情
const
handleClickToDetail
=
(
curDecree
)
=>
{
const
handleClickToDetail
=
curReport
=>
{
console
.
log
(
'curDecree'
,
curDecree
);
console
.
log
(
"curReport"
,
curReport
);
window
.
sessionStorage
.
setItem
(
"billId"
,
cur
Decree
.
id
);
window
.
sessionStorage
.
setItem
(
"billId"
,
cur
Report
.
id
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
cur
Decree
.
title
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
cur
Report
.
title
);
const
route
=
router
.
resolve
({
const
route
=
router
.
resolve
({
path
:
"/decreeLayout
"
,
name
:
"ReportDetail
"
,
query
:
{
params
:
{
billId
:
curDecree
.
id
id
:
curReport
.
id
}
}
}
);
}
);
window
.
open
(
route
.
href
,
"_blank"
);
window
.
open
(
route
.
href
,
"_blank"
);
}
;
}
;
// 跳转
人物
详情
// 跳转
智库
详情
const
handlePerClick
=
item
=>
{
const
handlePerClick
=
item
=>
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
sponsorPersonName
);
const
curRoute
=
router
.
resolve
({
const
route
=
router
.
resolve
({
name
:
"ThinkTankDetail"
,
path
:
"/characterPage"
,
params
:
{
query
:
{
id
:
item
.
organizationId
,
type
:
2
,
name
:
item
.
organizationName
personId
:
item
.
personId
}
}
}
);
}
);
window
.
open
(
r
oute
.
href
,
"_blank"
);
window
.
open
(
curR
oute
.
href
,
"_blank"
);
}
;
}
;
// 导出
// 导出
const
handleExport
=
()
=>
{
const
handleExport
=
()
=>
{
if
(
!
selectedCount
.
value
)
{
if
(
!
selectedCount
.
value
)
{
ElMessage
.
warning
(
'请选择至少一项数据!'
)
ElMessage
.
warning
(
"请选择至少一项数据!"
);
return
return
;
}
}
console
.
log
(
selectedMap
.
value
);
console
.
log
(
selectedMap
.
value
);
const
arr
=
Array
.
from
(
selectedMap
.
value
);
const
arr
=
Array
.
from
(
selectedMap
.
value
);
const
jsonStr
=
JSON
.
stringify
(
arr
,
null
,
2
);
const
jsonStr
=
JSON
.
stringify
(
arr
,
null
,
2
);
const
blob
=
new
Blob
([
jsonStr
],
{
type
:
'application/json'
}
);
const
blob
=
new
Blob
([
jsonStr
],
{
type
:
"application/json"
}
);
const
url
=
URL
.
createObjectURL
(
blob
);
const
url
=
URL
.
createObjectURL
(
blob
);
const
link
=
document
.
createElement
(
'a'
);
const
link
=
document
.
createElement
(
"a"
);
link
.
href
=
url
;
link
.
href
=
url
;
link
.
download
=
'export.json'
;
link
.
download
=
"export.json"
;
link
.
click
();
link
.
click
();
URL
.
revokeObjectURL
(
url
);
URL
.
revokeObjectURL
(
url
);
}
;
}
;
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
handleGetThinkTankList
()
handleGetThinkTankList
()
;
initParam
()
initParam
()
;
// 初始化
// 初始化
await
fetchTableData
()
await
fetchTableData
();
}
);
}
)
<
/script
>
<
/script
>
<
style
lang
=
"scss"
scoped
>
<
style
lang
=
"scss"
scoped
>
...
@@ -1055,7 +1025,6 @@ onMounted(async () => {
...
@@ -1055,7 +1025,6 @@ onMounted(async () => {
}
}
}
}
.
header
-
footer
{
.
header
-
footer
{
margin
-
top
:
16
px
;
margin
-
top
:
16
px
;
display
:
flex
;
display
:
flex
;
...
@@ -1176,7 +1145,6 @@ onMounted(async () => {
...
@@ -1176,7 +1145,6 @@ onMounted(async () => {
.
header
-
left
-
item2
{
.
header
-
left
-
item2
{
color
:
var
(
--
color
-
primary
-
100
);
color
:
var
(
--
color
-
primary
-
100
);
}
}
.
header
-
left
-
item3
{
.
header
-
left
-
item3
{
...
@@ -1256,7 +1224,6 @@ onMounted(async () => {
...
@@ -1256,7 +1224,6 @@ onMounted(async () => {
flex
-
wrap
:
wrap
;
flex
-
wrap
:
wrap
;
gap
:
8
px
;
gap
:
8
px
;
width
:
340
px
;
width
:
340
px
;
}
}
}
}
...
@@ -1285,12 +1252,9 @@ onMounted(async () => {
...
@@ -1285,12 +1252,9 @@ onMounted(async () => {
}
}
}
}
:
deep
(.
el
-
table__header
-
wrapper
)
{
:
deep
(.
el
-
table__header
-
wrapper
)
{
// background-color: #f5f7fa;
// background-color: #f5f7fa;
height
:
48
px
;
height
:
48
px
;
}
}
:
deep
(.
el
-
table__header
th
)
{
:
deep
(.
el
-
table__header
th
)
{
...
...
src/views/decree/decreeHome/index.vue
浏览文件 @
6b4028a9
...
@@ -42,7 +42,12 @@
...
@@ -42,7 +42,12 @@
<img
:src=
"item.imgUrl || DefaultIcon2"
alt=
""
/>
<img
:src=
"item.imgUrl || DefaultIcon2"
alt=
""
/>
</div>
</div>
<div
class=
"item-right one-line-ellipsis"
@
click=
"handleToInstitution(item)"
>
{{
item
.
orgName
}}
</div>
<div
class=
"item-right one-line-ellipsis"
@
click=
"handleToInstitution(item)"
>
{{
item
.
orgName
}}
</div>
<div
class=
"item-total"
@
click=
"handleToDataLibrary(item)"
>
{{
item
.
totalOrderNum
}}
项
</div>
<el-popover
content=
"跳转至数据资源库"
placement=
"top"
>
<template
#
reference
>
<div
class=
"item-total"
@
click=
"handleToDataLibrary(item)"
>
{{
item
.
totalOrderNum
}}
项
</div>
</
template
>
</el-popover>
<el-icon
color=
"var(--color-primary-100)"
>
<el-icon
color=
"var(--color-primary-100)"
>
<ArrowRightBold
/>
<ArrowRightBold
/>
</el-icon>
</el-icon>
...
...
src/views/decree/decreeOriginal/index.vue
浏览文件 @
6b4028a9
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
</div>
</div>
<div
class=
"layout-main-center"
>
<div
class=
"layout-main-center"
>
<
BaseDecreeOriginal
:report-data=
"reportData"
@
download=
"handleDownload"
/
>
<
newOriginal
ref=
"refNewOriginal"
@
download=
"handleDownload"
></newOriginal
>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -38,7 +38,7 @@ import { useRoute } from "vue-router";
...
@@ -38,7 +38,7 @@ import { useRoute } from "vue-router";
import
{
ElMessage
}
from
"element-plus"
;
import
{
ElMessage
}
from
"element-plus"
;
import
{
getDecreeSummary
}
from
"@/api/decree/introduction"
;
import
{
getDecreeSummary
}
from
"@/api/decree/introduction"
;
import
{
getDecreeReport
}
from
"@/api/decree/introduction"
;
import
{
getDecreeReport
}
from
"@/api/decree/introduction"
;
import
BaseDecreeOriginal
from
"@/components/base/DecreeOriginal/index
.vue"
;
import
newOriginal
from
"@/components/base/DecreeOriginal/newOriginal
.vue"
;
const
route
=
useRoute
();
const
route
=
useRoute
();
let
pdfUrl
=
""
;
let
pdfUrl
=
""
;
...
@@ -98,26 +98,16 @@ const handleGetSummary = async () => {
...
@@ -98,26 +98,16 @@ const handleGetSummary = async () => {
};
};
// 获取报告原文 - 修改为获取分段数组
// 获取报告原文 - 修改为获取分段数组
const
re
portData
=
ref
([]
);
const
re
fNewOriginal
=
ref
(
null
);
const
handleGetReport
=
async
()
=>
{
const
handleGetReport
=
async
()
=>
{
try
{
try
{
const
res
=
await
getDecreeReport
({
id
:
route
.
query
.
id
});
const
res
=
await
getDecreeReport
({
id
:
route
.
query
.
id
});
console
.
log
(
"报告原文"
,
res
);
console
.
log
(
"报告原文"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
)
{
pdfUrl
=
res
.
data
.
pdfUrl
;
pdfUrl
=
res
.
data
.
pdfUrl
;
const
originData
=
[];
refNewOriginal
.
value
.
setOriginalData
({...
res
.
data
});
let
num
=
Math
.
max
(
res
.
data
.
content
.
length
,
res
.
data
.
contentEn
.
length
)
for
(
let
i
=
0
;
i
<
num
;
i
++
)
{
let
obj
=
{
content
:
res
.
data
.
content
[
i
]
||
""
,
contentEn
:
res
.
data
.
contentEn
[
i
]
||
""
,
num
:
i
+
1
,
}
originData
.
push
(
obj
);
}
reportData
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
originData
));
}
}
}
catch
(
error
)
{
}
}
catch
(
error
)
{}
};
};
onMounted
(()
=>
{
onMounted
(()
=>
{
...
...
src/views/marketAccessRestrictions/com/SurveyHistory.vue
浏览文件 @
6b4028a9
...
@@ -16,14 +16,12 @@
...
@@ -16,14 +16,12 @@
<div
class=
"timeline-content-card"
>
<div
class=
"timeline-content-card"
>
<div
class=
"item-head"
>
<div
class=
"item-head"
>
<div
:class=
"`item-tag tag-$
{item.sortcode}`">
{{
item
.
sortcode
}}
</div>
<div
:class=
"`item-tag tag-$
{item.sortcode}`">
{{
item
.
sortcode
}}
</div>
<div
class=
"item-name"
>
{{
item
.
searchname
}}
</div>
<div
class=
"item-name
one-line-ellipsis
"
>
{{
item
.
searchname
}}
</div>
<div
class=
"item-state"
>
<div
class=
"item-state"
>
<span
class=
"dot"
>
•
</span>
{{
item
.
casestatus
}}
<span
class=
"dot"
>
•
</span>
{{
item
.
casestatus
}}
</div>
</div>
</div>
</div>
<div
class=
"card-body"
>
<div
class=
"card-body"
>
{{
item
.
content
}}
</div>
{{
item
.
content
}}
</div>
<div
class=
"card-footer"
>
<div
class=
"card-footer"
>
<div
class=
"footer-left-tags"
>
<div
class=
"footer-left-tags"
>
<AreaTag
v-for=
"(name, num) in item.searchArea"
:key=
"num"
:tagName=
"name"
></AreaTag>
<AreaTag
v-for=
"(name, num) in item.searchArea"
:key=
"num"
:tagName=
"name"
></AreaTag>
...
@@ -129,7 +127,7 @@ const onNavigateToDetail = item => {
...
@@ -129,7 +127,7 @@ const onNavigateToDetail = item => {
.timeline-content-card
{
.timeline-content-card
{
width
:
20px
;
width
:
20px
;
flex
:
auto
;
flex
:
auto
;
padding
:
2
px
16px
0
;
padding
:
4
px
16px
0
;
margin-bottom
:
30px
;
margin-bottom
:
30px
;
&
:hover
.item-head
.item-name
{
&
:hover
.item-head
.item-name
{
...
...
src/views/marketAccessRestrictions/marketAccessLayout/case/232/index.vue
浏览文件 @
6b4028a9
...
@@ -32,39 +32,26 @@
...
@@ -32,39 +32,26 @@
<div
class=
"wrapper-main"
>
<div
class=
"wrapper-main"
>
<div
class=
"left"
>
<div
class=
"left"
>
<!-- 科技领域 -->
<!-- 科技领域 -->
<div
class=
"left-box"
>
<div
class=
"check-box"
>
<div
class=
"left-header"
>
<div
class=
"check-head"
>
<div
class=
"icon"
></div>
<div
class=
"head-name"
>
{{
"科技领域"
}}
</div>
<div
class=
"title"
>
{{
"科技领域"
}}
</div>
</div>
<div
class=
"left-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"checkedAreaList"
@
change=
"handleCheckedAreasChange"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部领域"
>
全部领域
</el-checkbox>
<el-checkbox
v-for=
"area in surveyAreaList"
:key=
"area.id"
:label=
"area.id"
class=
"filter-checkbox"
>
{{
area
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<el-checkbox-group
class=
"check-list"
v-model=
"checkedAreaList"
@
change=
"handleCheckedAreasChange"
>
<el-checkbox
class=
"check-item"
v-for=
"item in surveyAreaList"
:key=
"item.id"
:label=
"item.id"
>
{{
item
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<!-- 发布时间 -->
<!-- 发布时间 -->
<div
class=
"left-box"
>
<div
class=
"check-box"
>
<div
class=
"left-header"
>
<div
class=
"check-head"
>
<div
class=
"icon"
></div>
<div
class=
"head-name"
>
{{
"发布时间"
}}
</div>
<div
class=
"title"
>
{{
"发布时间"
}}
</div>
</div>
</div>
<div
class=
"left-main"
>
<div
class=
"left-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"checkedSurveyYears"
@
change=
"handleCheckedYearsChange"
>
<el-checkbox-group
class=
"check-list"
v-model=
"checkedYearList"
@
change=
"handleCheckedYearsChange"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部时间"
>
全部时间
</el-checkbox>
<el-checkbox
class=
"check-item"
v-for=
"year in surveyYearList"
:key=
"year.id"
:label=
"year.id"
>
<el-checkbox
v-for=
"year in displayedYearList"
:key=
"year.id"
:label=
"year.id"
class=
"filter-checkbox"
>
{{
year
.
name
}}
{{
year
.
name
}}
</el-checkbox>
</el-checkbox>
<div
v-if=
"surveyYearList.length > 6"
class=
"expand-btn"
@
click=
"isYearExpanded = !isYearExpanded"
>
{{
isYearExpanded
?
"收起"
:
"更早"
}}
<el-icon>
<ArrowUp
v-if=
"isYearExpanded"
/>
<ArrowDown
v-else
/>
</el-icon>
</div>
</el-checkbox-group>
</el-checkbox-group>
</div>
</div>
</div>
</div>
...
@@ -98,8 +85,8 @@
...
@@ -98,8 +85,8 @@
<
/template
>
<
/template
>
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
,
watch
,
computed
}
from
"vue"
;
import
{
ref
,
onMounted
,
watch
}
from
"vue"
;
import
{
Search
,
ArrowDown
,
ArrowUp
}
from
"@element-plus/icons-vue"
;
import
{
Search
}
from
"@element-plus/icons-vue"
;
import
{
getSearchAllArea
,
getSearchAllYear
,
getSurveyList
}
from
"@/api/marketAccessRestrictions"
;
import
{
getSearchAllArea
,
getSearchAllYear
,
getSurveyList
}
from
"@/api/marketAccessRestrictions"
;
import
SurveyHistory
from
"@/views/marketAccessRestrictions/com/SurveyHistory.vue"
import
SurveyHistory
from
"@/views/marketAccessRestrictions/com/SurveyHistory.vue"
...
@@ -116,42 +103,49 @@ const handleSwithSort = () => {
...
@@ -116,42 +103,49 @@ const handleSwithSort = () => {
// 科技领域过滤
// 科技领域过滤
const
surveyAreaList
=
ref
([]);
const
surveyAreaList
=
ref
([]);
const
checkedAreaList
=
ref
([]);
const
checkedAreaList
=
ref
([
''
]);
const
checkAllAreas
=
ref
(
true
);
const
handleGetSearchAllArea
=
async
()
=>
{
const
isIndeterminateAreas
=
ref
(
false
);
try
{
const
res
=
await
getSearchAllArea
({
sortCode
:
"232"
}
);
const
handleCheckAllAreasChange
=
val
=>
{
if
(
res
.
code
===
200
)
{
checkedAreaList
.
value
=
val
?
surveyAreaList
.
value
.
map
(
a
=>
a
.
id
)
:
[];
surveyAreaList
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
AREANAME
,
id
:
item
.
AREACODE
}
));
isIndeterminateAreas
.
value
=
false
;
}
}
catch
(
error
)
{
}
surveyAreaList
.
value
.
unshift
({
name
:
"全部领域"
,
id
:
""
}
);
}
;
}
;
const
handleCheckedAreasChange
=
event
=>
{
const
handleCheckedAreasChange
=
value
=>
{
if
(
event
.
length
&&
event
[
event
.
length
-
1
]
!==
""
)
{
const
checkedCount
=
value
.
length
;
checkedAreaList
.
value
=
event
.
filter
(
item
=>
item
!==
""
);
checkAllAreas
.
value
=
checkedCount
===
surveyAreaList
.
value
.
length
;
}
else
{
isIndeterminateAreas
.
value
=
checkedCount
>
0
&&
checkedCount
<
surveyAreaList
.
value
.
length
;
checkedAreaList
.
value
=
[
""
];
}
currentPage
.
value
=
1
;
handleFetchSurveyList
();
}
;
}
;
// 发布时间过滤
// 发布时间过滤
const
surveyYearList
=
ref
([]);
const
surveyYearList
=
ref
([]);
const
checkedSurveyYears
=
ref
([]);
const
checkedYearList
=
ref
([
''
]);
const
checkAllYears
=
ref
(
true
);
const
handleGetSearchAllYear
=
async
()
=>
{
const
isIndeterminateYears
=
ref
(
false
);
try
{
const
isYearExpanded
=
ref
(
false
);
const
res
=
await
getSearchAllYear
({
sortCode
:
"232"
}
);
if
(
res
.
code
===
200
)
{
const
displayedYearList
=
computed
(()
=>
{
let
allYear
=
res
.
data
.
sort
((
a
,
b
)
=>
(
b
-
a
));
if
(
isYearExpanded
.
value
)
return
surveyYearList
.
value
;
let
beforeYear
=
allYear
.
slice
(
6
).
join
(
','
);
return
surveyYearList
.
value
.
slice
(
0
,
6
);
surveyYearList
.
value
=
allYear
.
slice
(
0
,
6
).
map
(
item
=>
({
name
:
item
+
"年"
,
id
:
item
}
));
}
);
if
(
beforeYear
)
surveyYearList
.
value
.
push
({
name
:
"更早"
,
id
:
beforeYear
}
);
}
const
handleCheckAllYearsChange
=
val
=>
{
}
catch
(
error
)
{
}
checkedSurveyYears
.
value
=
val
?
surveyYearList
.
value
.
map
(
y
=>
y
.
id
)
:
[];
surveyYearList
.
value
.
unshift
({
name
:
"全部时间"
,
id
:
""
}
);
isIndeterminateYears
.
value
=
false
;
}
;
}
;
const
handleCheckedYearsChange
=
event
=>
{
const
handleCheckedYearsChange
=
value
=>
{
if
(
event
.
length
&&
event
[
event
.
length
-
1
]
!==
""
)
{
const
checkedCount
=
value
.
length
;
checkedYearList
.
value
=
event
.
filter
(
item
=>
item
!==
""
);
checkAllYears
.
value
=
checkedCount
===
surveyYearList
.
value
.
length
;
}
else
{
isIndeterminateYears
.
value
=
checkedCount
>
0
&&
checkedCount
<
surveyYearList
.
value
.
length
;
checkedYearList
.
value
=
[
""
];
}
currentPage
.
value
=
1
;
handleFetchSurveyList
();
}
;
}
;
// 数据列表
// 数据列表
...
@@ -169,8 +163,8 @@ const handleFetchSurveyList = async () => {
...
@@ -169,8 +163,8 @@ const handleFetchSurveyList = async () => {
currentPage
:
currentPage
.
value
-
1
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
pageSize
.
value
,
pageSize
:
pageSize
.
value
,
sortCode
:
"232"
,
sortCode
:
"232"
,
publishYear
:
check
AllYears
.
value
?
""
:
checkedSurveyYears
.
value
.
toString
()
,
publishYear
:
check
edYearList
.
value
.
join
(
','
)
||
null
,
Area
:
check
AllAreas
.
value
?
""
:
checkedAreaList
.
value
.
toString
()
,
Area
:
check
edAreaList
.
value
.
join
(
','
)
||
null
,
caseStatus
:
filterStage
.
value
,
caseStatus
:
filterStage
.
value
,
keywords
:
searchText
.
value
,
keywords
:
searchText
.
value
,
sortField
:
"date"
,
sortField
:
"date"
,
...
@@ -199,39 +193,12 @@ const handleSearch = () => {
...
@@ -199,39 +193,12 @@ const handleSearch = () => {
}
;
}
;
// 监听过滤条件
// 监听过滤条件
watch
([
checkedSurveyYears
,
checkedAreaList
,
isSort
,
filterStage
,
filterParty
,
filterReason
],
()
=>
{
watch
([
isSort
,
filterStage
,
filterParty
,
filterReason
],
()
=>
{
if
(
isInitializing
.
value
)
return
;
if
(
isInitializing
.
value
)
return
;
currentPage
.
value
=
1
;
currentPage
.
value
=
1
;
handleFetchSurveyList
();
handleFetchSurveyList
();
}
);
}
);
const
handleGetSearchAllArea
=
async
()
=>
{
try
{
const
res
=
await
getSearchAllArea
({
sortCode
:
"232"
}
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
surveyAreaList
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
AREANAME
,
id
:
item
.
AREACODE
}
));
handleCheckAllAreasChange
(
true
);
}
}
catch
(
error
)
{
}
}
;
const
handleGetSearchAllYear
=
async
()
=>
{
try
{
const
res
=
await
getSearchAllYear
({
sortCode
:
"232"
}
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
sortedYears
=
res
.
data
.
sort
((
a
,
b
)
=>
b
-
a
);
surveyYearList
.
value
=
sortedYears
.
map
(
item
=>
({
name
:
item
+
"年"
,
id
:
item
}
));
handleCheckAllYearsChange
(
true
);
}
}
catch
(
error
)
{
}
}
;
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
Promise
.
all
([
handleGetSearchAllArea
(),
handleGetSearchAllYear
()]);
await
Promise
.
all
([
handleGetSearchAllArea
(),
handleGetSearchAllYear
()]);
isInitializing
.
value
=
false
;
isInitializing
.
value
=
false
;
...
@@ -306,58 +273,50 @@ onMounted(async () => {
...
@@ -306,58 +273,50 @@ onMounted(async () => {
.
left
{
.
left
{
width
:
360
px
;
width
:
360
px
;
min
-
height
:
56
0
px
;
min
-
height
:
30
0
px
;
height
:
fit
-
content
;
height
:
fit
-
content
;
padding
-
bottom
:
20
px
;
padding
-
bottom
:
20
px
;
border
-
radius
:
10
px
;
border
-
radius
:
10
px
;
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
60
,
87
,
126
,
0.2
);
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
60
,
87
,
126
,
0.2
);
background
:
#
fff
;
background
:
#
fff
;
.
left
-
box
{
.
check
-
box
{
margin
-
top
:
17
px
;
margin
-
top
:
18
px
;
.
check
-
head
{
.
left
-
header
{
position
:
relative
;
display
:
flex
;
margin
-
bottom
:
12
px
;
align
-
items
:
center
;
&
::
before
{
content
:
""
;
.
icon
{
position
:
absolute
;
top
:
0
px
;
left
:
0
px
;
width
:
8
px
;
width
:
8
px
;
height
:
1
6
px
;
height
:
1
00
%
;
background
:
var
(
--
color
-
main
-
active
);
background
:
var
(
--
color
-
primary
-
100
);
border
-
radius
:
0
2
px
2
px
0
;
border
-
radius
:
0
2
px
2
px
0
;
}
}
.
head
-
name
{
.
title
{
margin
-
left
:
25
px
;
margin
-
left
:
17
px
;
color
:
var
(
--
color
-
primary
-
100
);
color
:
var
(
--
color
-
main
-
active
);
font
-
size
:
16
px
;
font
-
size
:
16
px
;
font
-
weight
:
700
;
line
-
height
:
16
px
;
font
-
family
:
Source
Han
Sans
CN
;
font
-
weight
:
bold
;
}
}
}
}
}
.
check
-
list
{
padding
:
0
10
px
0
25
px
;
.
checkbox
-
group
{
display
:
grid
;
padding
:
10
px
0
0
25
px
;
grid
-
template
-
columns
:
repeat
(
2
,
1
fr
);
.
filter
-
checkbox
{
grid
-
gap
:
0
12
px
;
width
:
130
px
;
.
check
-
item
{
margin
-
bottom
:
8
px
;
width
:
100
%
;
height
:
32
px
;
height
:
32
px
;
:
deep
(.
el
-
checkbox__label
)
{
:
deep
(.
el
-
checkbox__label
)
{
font
-
size
:
16
px
;
font
-
family
:
Source
Han
Sans
CN
;
color
:
#
5
f656c
;
font
-
size
:
16
px
;
}
color
:
var
(
--
text
-
primary
-
65
-
color
);
}
}
.
expand
-
btn
{
color
:
var
(
--
color
-
main
-
active
);
font
-
size
:
14
px
;
cursor
:
pointer
;
display
:
flex
;
align
-
items
:
center
;
margin
-
top
:
4
px
;
.
el
-
icon
{
margin
-
left
:
4
px
;
}
}
}
}
}
}
...
...
src/views/marketAccessRestrictions/marketAccessLayout/case/301/index.vue
浏览文件 @
6b4028a9
...
@@ -21,39 +21,26 @@
...
@@ -21,39 +21,26 @@
<div
class=
"wrapper-main"
>
<div
class=
"wrapper-main"
>
<div
class=
"left"
>
<div
class=
"left"
>
<!-- 科技领域 -->
<!-- 科技领域 -->
<div
class=
"left-box"
>
<div
class=
"check-box"
>
<div
class=
"left-header"
>
<div
class=
"check-head"
>
<div
class=
"icon"
></div>
<div
class=
"head-name"
>
{{
"科技领域"
}}
</div>
<div
class=
"title"
>
{{
"科技领域"
}}
</div>
</div>
<div
class=
"left-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"checkedAreaList"
@
change=
"handleCheckedAreasChange"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部领域"
>
全部领域
</el-checkbox>
<el-checkbox
v-for=
"area in surveyAreaList"
:key=
"area.id"
:label=
"area.id"
class=
"filter-checkbox"
>
{{
area
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<el-checkbox-group
class=
"check-list"
v-model=
"checkedAreaList"
@
change=
"handleCheckedAreasChange"
>
<el-checkbox
class=
"check-item"
v-for=
"item in surveyAreaList"
:key=
"item.id"
:label=
"item.id"
>
{{
item
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<!-- 发布时间 -->
<!-- 发布时间 -->
<div
class=
"left-box"
>
<div
class=
"check-box"
>
<div
class=
"left-header"
>
<div
class=
"check-head"
>
<div
class=
"icon"
></div>
<div
class=
"head-name"
>
{{
"发布时间"
}}
</div>
<div
class=
"title"
>
{{
"发布时间"
}}
</div>
</div>
</div>
<div
class=
"left-main"
>
<div
class=
"left-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"checkedSurveyYears"
@
change=
"handleCheckedYearsChange"
>
<el-checkbox-group
class=
"check-list"
v-model=
"checkedYearList"
@
change=
"handleCheckedYearsChange"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部时间"
>
全部时间
</el-checkbox>
<el-checkbox
class=
"check-item"
v-for=
"year in surveyYearList"
:key=
"year.id"
:label=
"year.id"
>
<el-checkbox
v-for=
"year in displayedYearList"
:key=
"year.id"
:label=
"year.id"
class=
"filter-checkbox"
>
{{
year
.
name
}}
{{
year
.
name
}}
</el-checkbox>
</el-checkbox>
<div
v-if=
"surveyYearList.length > 6"
class=
"expand-btn"
@
click=
"isYearExpanded = !isYearExpanded"
>
{{
isYearExpanded
?
"收起"
:
"更早"
}}
<el-icon>
<ArrowUp
v-if=
"isYearExpanded"
/>
<ArrowDown
v-else
/>
</el-icon>
</div>
</el-checkbox-group>
</el-checkbox-group>
</div>
</div>
</div>
</div>
...
@@ -78,8 +65,8 @@
...
@@ -78,8 +65,8 @@
<
/template
>
<
/template
>
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
,
watch
,
computed
}
from
"vue"
;
import
{
ref
,
onMounted
,
watch
}
from
"vue"
;
import
{
Search
,
ArrowDown
,
ArrowUp
}
from
"@element-plus/icons-vue"
;
import
{
Search
}
from
"@element-plus/icons-vue"
;
import
{
getSearchAllArea
,
getSearchAllYear
,
getSurveyList
}
from
"@/api/marketAccessRestrictions"
;
import
{
getSearchAllArea
,
getSearchAllYear
,
getSurveyList
}
from
"@/api/marketAccessRestrictions"
;
import
SurveyHistory
from
"@/views/marketAccessRestrictions/com/SurveyHistory.vue"
import
SurveyHistory
from
"@/views/marketAccessRestrictions/com/SurveyHistory.vue"
...
@@ -88,46 +75,51 @@ const handleSwithSort = () => {
...
@@ -88,46 +75,51 @@ const handleSwithSort = () => {
isSort
.
value
=
!
isSort
.
value
;
isSort
.
value
=
!
isSort
.
value
;
}
;
}
;
const
surveyYearList
=
ref
([]);
// 科技领域过滤
const
checkedSurveyYears
=
ref
([]);
const
surveyAreaList
=
ref
([]);
const
isYearExpanded
=
ref
(
false
);
const
checkedAreaList
=
ref
([
''
]);
const
handleGetSearchAllArea
=
async
()
=>
{
const
displayedYearList
=
computed
(()
=>
{
try
{
if
(
isYearExpanded
.
value
)
{
const
res
=
await
getSearchAllArea
({
sortCode
:
"301"
}
);
return
surveyYearList
.
value
;
if
(
res
.
code
===
200
)
{
}
surveyAreaList
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
AREANAME
,
id
:
item
.
AREACODE
}
));
return
surveyYearList
.
value
.
slice
(
0
,
6
);
}
}
);
}
catch
(
error
)
{
}
surveyAreaList
.
value
.
unshift
({
name
:
"全部领域"
,
id
:
""
}
);
const
checkAllYears
=
ref
(
false
);
const
isIndeterminateYears
=
ref
(
false
);
const
handleCheckAllYearsChange
=
(
val
)
=>
{
checkedSurveyYears
.
value
=
val
?
surveyYearList
.
value
.
map
(
y
=>
y
.
id
)
:
[];
isIndeterminateYears
.
value
=
false
;
}
;
}
;
const
handleCheckedAreasChange
=
event
=>
{
const
handleCheckedYearsChange
=
(
value
)
=>
{
if
(
event
.
length
&&
event
[
event
.
length
-
1
]
!==
""
)
{
const
checkedCount
=
value
.
length
;
checkedAreaList
.
value
=
event
.
filter
(
item
=>
item
!==
""
);
checkAllYears
.
value
=
checkedCount
===
surveyYearList
.
value
.
length
;
}
else
{
isIndeterminateYears
.
value
=
checkedCount
>
0
&&
checkedCount
<
surveyYearList
.
value
.
length
;
checkedAreaList
.
value
=
[
""
];
}
currentPage
.
value
=
1
;
handleFetchSurveyList
();
}
;
}
;
const
surveyAreaList
=
ref
([]);
// 发布时间过滤
const
checkedAreaList
=
ref
([]);
const
surveyYearList
=
ref
([]);
const
checkedYearList
=
ref
([
''
]);
const
checkAllAreas
=
ref
(
false
);
const
handleGetSearchAllYear
=
async
()
=>
{
const
isIndeterminateAreas
=
ref
(
false
);
try
{
const
res
=
await
getSearchAllYear
({
sortCode
:
"301"
}
);
const
handleCheckAllAreasChange
=
(
val
)
=>
{
if
(
res
.
code
===
200
)
{
checkedAreaList
.
value
=
val
?
surveyAreaList
.
value
.
map
(
a
=>
a
.
id
)
:
[];
let
allYear
=
res
.
data
.
sort
((
a
,
b
)
=>
(
b
-
a
));
isIndeterminateAreas
.
value
=
false
;
let
beforeYear
=
allYear
.
slice
(
6
).
join
(
','
);
surveyYearList
.
value
=
allYear
.
slice
(
0
,
6
).
map
(
item
=>
({
name
:
item
+
"年"
,
id
:
item
}
));
if
(
beforeYear
)
surveyYearList
.
value
.
push
({
name
:
"更早"
,
id
:
beforeYear
}
);
}
}
catch
(
error
)
{
}
surveyYearList
.
value
.
unshift
({
name
:
"全部时间"
,
id
:
""
}
);
}
;
}
;
const
handleCheckedYearsChange
=
event
=>
{
const
handleCheckedAreasChange
=
(
value
)
=>
{
if
(
event
.
length
&&
event
[
event
.
length
-
1
]
!==
""
)
{
const
checkedCount
=
value
.
length
;
checkedYearList
.
value
=
event
.
filter
(
item
=>
item
!==
""
);
checkAllAreas
.
value
=
checkedCount
===
surveyAreaList
.
value
.
length
;
}
else
{
isIndeterminateAreas
.
value
=
checkedCount
>
0
&&
checkedCount
<
surveyAreaList
.
value
.
length
;
checkedYearList
.
value
=
[
""
];
}
currentPage
.
value
=
1
;
handleFetchSurveyList
();
}
;
}
;
const
totalDiscussNum
=
ref
(
0
);
const
totalDiscussNum
=
ref
(
0
);
...
@@ -145,8 +137,8 @@ const handleFetchSurveyList = async () => {
...
@@ -145,8 +137,8 @@ const handleFetchSurveyList = async () => {
currentPage
:
currentPage
.
value
-
1
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
pageSize
.
value
,
pageSize
:
pageSize
.
value
,
sortCode
:
"301"
,
sortCode
:
"301"
,
publishYear
:
check
AllYears
.
value
?
""
:
checkedSurveyYears
.
value
.
toString
()
,
publishYear
:
check
edYearList
.
value
.
join
(
','
)
||
null
,
Area
:
check
AllAreas
.
value
?
""
:
checkedAreaList
.
value
.
toString
()
,
Area
:
check
edAreaList
.
value
.
join
(
','
)
||
null
,
// keywords: searchText.value,
// keywords: searchText.value,
sortField
:
"date"
,
sortField
:
"date"
,
sortOrder
:
isSort
.
value
?
"asc"
:
"desc"
sortOrder
:
isSort
.
value
?
"asc"
:
"desc"
...
@@ -173,60 +165,11 @@ const handleSearch = () => {
...
@@ -173,60 +165,11 @@ const handleSearch = () => {
handleFetchSurveyList
();
handleFetchSurveyList
();
}
;
}
;
watch
(
watch
([
isSort
],
()
=>
{
[
checkedSurveyYears
,
checkedAreaList
,
isSort
],
if
(
isInitializing
.
value
)
return
;
()
=>
{
currentPage
.
value
=
1
;
if
(
isInitializing
.
value
)
return
;
handleFetchSurveyList
();
currentPage
.
value
=
1
;
}
);
handleFetchSurveyList
();
}
,
{
deep
:
true
}
);
const
handleGetSearchAllArea
=
async
()
=>
{
try
{
const
res
=
await
getSearchAllArea
({
sortCode
:
'301'
}
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
surveyAreaList
.
value
=
res
.
data
.
map
(
item
=>
{
return
{
name
:
item
.
AREANAME
,
id
:
item
.
AREACODE
}
;
}
);
// 默认选中全部
checkAllAreas
.
value
=
true
;
handleCheckAllAreasChange
(
true
);
}
}
catch
(
error
)
{
}
}
const
handleGetSearchAllYear
=
async
()
=>
{
try
{
const
res
=
await
getSearchAllYear
({
sortCode
:
'301'
}
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 排序并格式化
const
sortedYears
=
res
.
data
.
sort
((
a
,
b
)
=>
b
-
a
);
surveyYearList
.
value
=
sortedYears
.
map
(
item
=>
{
return
{
name
:
item
+
'年'
,
id
:
item
}
;
}
);
// 默认选中全部
checkAllYears
.
value
=
true
;
handleCheckAllYearsChange
(
true
);
}
}
catch
(
error
)
{
}
}
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
Promise
.
all
([
handleGetSearchAllArea
(),
handleGetSearchAllYear
()]);
await
Promise
.
all
([
handleGetSearchAllArea
(),
handleGetSearchAllYear
()]);
...
@@ -309,58 +252,50 @@ onMounted(async () => {
...
@@ -309,58 +252,50 @@ onMounted(async () => {
.
left
{
.
left
{
width
:
360
px
;
width
:
360
px
;
min
-
height
:
56
0
px
;
min
-
height
:
30
0
px
;
height
:
fit
-
content
;
height
:
fit
-
content
;
padding
-
bottom
:
20
px
;
padding
-
bottom
:
20
px
;
border
-
radius
:
10
px
;
border
-
radius
:
10
px
;
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
60
,
87
,
126
,
0.2
);
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
60
,
87
,
126
,
0.2
);
background
:
#
fff
;
background
:
#
fff
;
.
left
-
box
{
.
check
-
box
{
margin
-
top
:
17
px
;
margin
-
top
:
18
px
;
.
check
-
head
{
.
left
-
header
{
position
:
relative
;
display
:
flex
;
margin
-
bottom
:
12
px
;
align
-
items
:
center
;
&
::
before
{
content
:
""
;
.
icon
{
position
:
absolute
;
top
:
0
px
;
left
:
0
px
;
width
:
8
px
;
width
:
8
px
;
height
:
1
6
px
;
height
:
1
00
%
;
background
:
var
(
--
color
-
main
-
active
);
background
:
var
(
--
color
-
primary
-
100
);
border
-
radius
:
0
2
px
2
px
0
;
border
-
radius
:
0
2
px
2
px
0
;
}
}
.
head
-
name
{
.
title
{
margin
-
left
:
25
px
;
margin
-
left
:
17
px
;
color
:
var
(
--
color
-
primary
-
100
);
color
:
var
(
--
color
-
main
-
active
);
font
-
size
:
16
px
;
font
-
size
:
16
px
;
font
-
weight
:
700
;
line
-
height
:
16
px
;
font
-
family
:
Source
Han
Sans
CN
;
font
-
weight
:
bold
;
}
}
}
}
}
.
check
-
list
{
padding
:
0
10
px
0
25
px
;
.
checkbox
-
group
{
display
:
grid
;
padding
:
10
px
0
0
25
px
;
grid
-
template
-
columns
:
repeat
(
2
,
1
fr
);
.
filter
-
checkbox
{
grid
-
gap
:
0
12
px
;
width
:
130
px
;
.
check
-
item
{
margin
-
bottom
:
8
px
;
width
:
100
%
;
height
:
32
px
;
height
:
32
px
;
:
deep
(.
el
-
checkbox__label
)
{
:
deep
(.
el
-
checkbox__label
)
{
font
-
size
:
16
px
;
font
-
family
:
Source
Han
Sans
CN
;
color
:
#
5
f656c
;
font
-
size
:
16
px
;
}
color
:
var
(
--
text
-
primary
-
65
-
color
);
}
}
.
expand
-
btn
{
color
:
var
(
--
color
-
main
-
active
);
font
-
size
:
14
px
;
cursor
:
pointer
;
display
:
flex
;
align
-
items
:
center
;
margin
-
top
:
4
px
;
.
el
-
icon
{
margin
-
left
:
4
px
;
}
}
}
}
}
}
...
...
src/views/marketAccessRestrictions/marketAccessLayout/case/337/index.vue
浏览文件 @
6b4028a9
...
@@ -33,53 +33,37 @@
...
@@ -33,53 +33,37 @@
<div
class=
"wrapper-main"
>
<div
class=
"wrapper-main"
>
<div
class=
"left"
>
<div
class=
"left"
>
<!-- 科技领域 -->
<!-- 科技领域 -->
<div
class=
"left-box"
>
<div
class=
"check-box"
>
<div
class=
"left-header"
>
<div
class=
"check-head"
>
<div
class=
"icon"
></div>
<div
class=
"head-name"
>
{{ "科技领域" }}
</div>
<div
class=
"title"
>
{{ "科技领域" }}
</div>
</div>
<div
class=
"left-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"checkedAreaList"
@
change=
"handleCheckedAreasChange"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部领域"
>
全部领域
</el-checkbox>
<el-checkbox
v-for=
"area in surveyAreaList"
:key=
"area.id"
:label=
"area.id"
class=
"filter-checkbox"
>
{{ area.name }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<el-checkbox-group
class=
"check-list"
v-model=
"checkedAreaList"
@
change=
"handleCheckedAreasChange"
>
<el-checkbox
class=
"check-item"
v-for=
"item in surveyAreaList"
:key=
"item.id"
:label=
"item.id"
>
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<!-- 发布时间 -->
<!-- 发布时间 -->
<div
class=
"left-box"
>
<div
class=
"check-box"
>
<div
class=
"left-header"
>
<div
class=
"check-head"
>
<div
class=
"icon"
></div>
<div
class=
"head-name"
>
{{ "发布时间" }}
</div>
<div
class=
"title"
>
{{ "发布时间" }}
</div>
</div>
</div>
<div
class=
"left-main"
>
<div
class=
"left-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"checkedSurveyYears"
@
change=
"handleCheckedYearsChange"
>
<el-checkbox-group
class=
"check-list"
v-model=
"checkedYearList"
@
change=
"handleCheckedYearsChange"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部时间"
>
全部时间
</el-checkbox>
<el-checkbox
class=
"check-item"
v-for=
"year in surveyYearList"
:key=
"year.id"
:label=
"year.id"
>
<el-checkbox
v-for=
"year in displayedYearList"
:key=
"year.id"
:label=
"year.id"
class=
"filter-checkbox"
>
{{ year.name }}
{{ year.name }}
</el-checkbox>
</el-checkbox>
<div
v-if=
"surveyYearList.length > 6"
class=
"expand-btn"
@
click=
"isYearExpanded = !isYearExpanded"
>
{{ isYearExpanded ? "收起" : "更早" }}
<el-icon>
<ArrowUp
v-if=
"isYearExpanded"
/>
<ArrowDown
v-else
/>
</el-icon>
</div>
</el-checkbox-group>
</el-checkbox-group>
</div>
</div>
</div>
</div>
<!-- 受调查国家/地区 -->
<!-- 受调查国家/地区 -->
<div
class=
"left-box"
>
<div
class=
"check-box"
>
<div
class=
"left-header"
>
<div
class=
"check-head"
>
<div
class=
"icon"
></div>
<div
class=
"head-name"
>
{{ "受调查国家/地区" }}
</div>
<div
class=
"title"
>
{{ "受调查国家/地区" }}
</div>
</div>
</div>
<div
class=
"left-main"
>
<div
class=
"left-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"checkedCountryList"
<el-checkbox-group
class=
"check-list"
v-model=
"checkedCountryList"
@
change=
"handleCheckedCountriesChange"
>
@
change=
"handleCheckedCountriesChange"
>
<el-checkbox
class=
"check-item"
v-for=
"area in surveyCountryList"
:key=
"area.id"
:label=
"area.id"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部"
>
全部
</el-checkbox>
<el-checkbox
v-for=
"area in surveyCountryList"
:key=
"area.id"
:label=
"area.id"
class=
"filter-checkbox"
>
{{ area.name }}
{{ area.name }}
</el-checkbox>
</el-checkbox>
</el-checkbox-group>
</el-checkbox-group>
...
@@ -103,8 +87,8 @@
...
@@ -103,8 +87,8 @@
</template>
</template>
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
,
watch
,
computed
}
from
"vue"
;
import
{
ref
,
onMounted
,
watch
}
from
"vue"
;
import
{
Search
,
ArrowDown
,
ArrowUp
}
from
"@element-plus/icons-vue"
;
import
{
Search
}
from
"@element-plus/icons-vue"
;
import
{
getSearchAllArea
,
getSearchAllYear
,
getSurveyList
,
getSearchAllCountry
}
from
"@/api/marketAccessRestrictions"
;
import
{
getSearchAllArea
,
getSearchAllYear
,
getSurveyList
,
getSearchAllCountry
}
from
"@/api/marketAccessRestrictions"
;
import
AnalysisBox
from
"@/components/base/boxBackground/analysisBox.vue"
import
AnalysisBox
from
"@/components/base/boxBackground/analysisBox.vue"
...
@@ -131,61 +115,71 @@ const releaseTimeList = ref([
...
@@ -131,61 +115,71 @@ const releaseTimeList = ref([
// 科技领域过滤
// 科技领域过滤
const
surveyAreaList
=
ref
([]);
const
surveyAreaList
=
ref
([]);
const
checkedAreaList
=
ref
([
'全部领域'
]);
const
checkedAreaList
=
ref
([
''
]);
const
handleGetSearchAllArea
=
async
()
=>
{
const
handleCheckedAreasChange
=
val
=>
{
try
{
if
(
val
.
includes
(
"全部领域"
)
&&
val
.
length
>
1
)
{
const
res
=
await
getSearchAllArea
({
sortCode
:
"337"
});
if
(
val
[
val
.
length
-
1
]
===
"全部领域"
)
{
if
(
res
.
code
===
200
)
{
checkedAreaList
.
value
=
[
"全部领域"
];
surveyAreaList
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
AREANAME
,
id
:
item
.
AREACODE
}));
}
else
{
checkedAreaList
.
value
=
val
.
filter
(
item
=>
item
!==
"全部领域"
);
}
}
}
else
if
(
val
.
length
===
0
)
{
}
catch
(
error
)
{}
checkedAreaList
.
value
=
[
"全部领域"
];
surveyAreaList
.
value
.
unshift
({
name
:
"全部领域"
,
id
:
""
});
};
const
handleCheckedAreasChange
=
event
=>
{
if
(
event
.
length
&&
event
[
event
.
length
-
1
]
!==
""
)
{
checkedAreaList
.
value
=
event
.
filter
(
item
=>
item
!==
""
);
}
else
{
checkedAreaList
.
value
=
[
""
];
}
}
currentPage
.
value
=
1
;
handleFetchSurveyList
();
};
};
// 发布时间过滤
// 发布时间过滤
const
surveyYearList
=
ref
([]);
const
surveyYearList
=
ref
([]);
const
checkedSurveyYears
=
ref
([
'全部时间'
]);
const
checkedYearList
=
ref
([
''
]);
const
handleGetSearchAllYear
=
async
()
=>
{
const
isYearExpanded
=
ref
(
false
);
try
{
const
res
=
await
getSearchAllYear
({
sortCode
:
"337"
});
const
displayedYearList
=
computed
(()
=>
{
if
(
res
.
code
===
200
)
{
if
(
isYearExpanded
.
value
)
return
surveyYearList
.
value
;
let
allYear
=
res
.
data
.
sort
((
a
,
b
)
=>
(
b
-
a
));
return
surveyYearList
.
value
.
slice
(
0
,
6
);
let
beforeYear
=
allYear
.
slice
(
6
).
join
(
','
);
});
surveyYearList
.
value
=
allYear
.
slice
(
0
,
6
).
map
(
item
=>
({
name
:
item
+
"年"
,
id
:
item
}));
if
(
beforeYear
)
surveyYearList
.
value
.
push
({
name
:
"更早"
,
id
:
beforeYear
});
const
handleCheckedYearsChange
=
value
=>
{
// const checkedCount = value.length;
// checkAllYears.value = checkedCount === surveyYearList.value.length;
// isIndeterminateYears.value = checkedCount > 0 && checkedCount
<
surveyYearList
.
value
.
length
;
if
(
val
.
includes
(
"全部时间"
)
&&
val
.
length
>
1
)
{
if
(
val
[
val
.
length
-
1
]
===
"全部时间"
)
{
checkedSurveyYears
.
value
=
[
"全部时间"
];
}
else
{
checkedSurveyYears
.
value
=
val
.
filter
(
item
=>
item
!==
"全部时间"
);
}
}
}
else
if
(
val
.
length
===
0
)
{
}
catch
(
error
)
{}
checkedSurveyYears
.
value
=
[
"全部时间"
];
surveyYearList
.
value
.
unshift
({
name
:
"全部时间"
,
id
:
""
});
};
const
handleCheckedYearsChange
=
event
=>
{
if
(
event
.
length
&&
event
[
event
.
length
-
1
]
!==
""
)
{
checkedYearList
.
value
=
event
.
filter
(
item
=>
item
!==
""
);
}
else
{
checkedYearList
.
value
=
[
""
];
}
}
currentPage
.
value
=
1
;
handleFetchSurveyList
();
};
};
// 受调查国家/地区过滤
// 受调查国家/地区过滤
const
surveyCountryList
=
ref
([]);
const
surveyCountryList
=
ref
([]);
const
checkedCountryList
=
ref
([
'全部'
]);
const
checkedCountryList
=
ref
([
''
]);
const
handleGetSearchAllCountry
=
async
()
=>
{
try
{
const
handleCheckedCountriesChange
=
val
=>
{
const
res
=
await
getSearchAllCountry
();
if
(
val
.
includes
(
"全部"
)
&&
val
.
length
>
1
)
{
if
(
res
.
code
===
200
)
{
if
(
val
[
val
.
length
-
1
]
===
"全部"
)
{
surveyCountryList
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
COUNTRYNAME
,
id
:
item
.
COUNTRYID
}));
checkedCountryList
.
value
=
[
"全部"
];
}
else
{
checkedCountryList
.
value
=
val
.
filter
(
item
=>
item
!==
"全部"
);
}
}
}
else
if
(
val
.
length
===
0
)
{
}
catch
(
error
)
{}
checkedCountryList
.
value
=
[
"全部"
];
surveyCountryList
.
value
.
unshift
({
name
:
"全部"
,
id
:
""
});
};
const
handleCheckedCountriesChange
=
event
=>
{
if
(
event
.
length
&&
event
[
event
.
length
-
1
]
!==
""
)
{
checkedCountryList
.
value
=
event
.
filter
(
item
=>
item
!==
""
);
}
else
{
checkedCountryList
.
value
=
[
""
];
}
}
currentPage
.
value
=
1
;
handleFetchSurveyList
();
};
};
// 数据列表
// 数据列表
...
@@ -203,9 +197,9 @@ const handleFetchSurveyList = async () => {
...
@@ -203,9 +197,9 @@ const handleFetchSurveyList = async () => {
currentPage
:
currentPage
.
value
-
1
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
pageSize
.
value
,
pageSize
:
pageSize
.
value
,
sortCode
:
"337"
,
sortCode
:
"337"
,
publishYear
:
checked
SurveyYears
.
value
[
0
]
===
'全部时间'
?
null
:
checkedSurveyYears
.
value
.
toString
()
,
publishYear
:
checked
YearList
.
value
.
join
(
','
)
||
null
,
Area
:
checkedAreaList
.
value
[
0
]
===
'全部领域'
?
null
:
checkedAreaList
.
value
.
toString
()
,
Area
:
checkedAreaList
.
value
.
join
(
','
)
||
null
,
searchCountry
:
checkedCountryList
.
value
[
0
]
===
'全部'
?
null
:
checkedCountryList
.
value
.
toString
()
,
searchCountry
:
checkedCountryList
.
value
.
join
(
','
)
||
null
,
caseStatus
:
filterStage
.
value
?
filterStage
.
value
:
null
,
caseStatus
:
filterStage
.
value
?
filterStage
.
value
:
null
,
keywords
:
searchText
.
value
?
searchText
.
value
:
null
,
keywords
:
searchText
.
value
?
searchText
.
value
:
null
,
sortField
:
"date"
,
sortField
:
"date"
,
...
@@ -234,52 +228,11 @@ const handleSearch = () => {
...
@@ -234,52 +228,11 @@ const handleSearch = () => {
};
};
// 监听过滤条件
// 监听过滤条件
watch
(
watch
([
isSort
,
filterStage
,
filterParty
,
filterReason
],
()
=>
{
[
checkedSurveyYears
,
checkedAreaList
,
checkedCountryList
,
isSort
,
filterStage
,
filterParty
,
filterReason
],
if
(
isInitializing
.
value
)
return
;
()
=>
{
currentPage
.
value
=
1
;
if
(
isInitializing
.
value
)
return
;
handleFetchSurveyList
();
currentPage
.
value
=
1
;
});
handleFetchSurveyList
();
}
);
const
handleGetSearchAllArea
=
async
()
=>
{
try
{
const
res
=
await
getSearchAllArea
({
sortCode
:
"337"
});
if
(
res
.
code
===
200
&&
res
.
data
)
{
surveyAreaList
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
AREANAME
,
id
:
item
.
AREACODE
}));
handleCheckAllAreasChange
(
true
);
}
}
catch
(
error
)
{
}
};
const
handleGetSearchAllYear
=
async
()
=>
{
try
{
const
res
=
await
getSearchAllYear
({
sortCode
:
"337"
});
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
sortedYears
=
res
.
data
.
sort
((
a
,
b
)
=>
b
-
a
);
surveyYearList
.
value
=
sortedYears
.
map
(
item
=>
({
name
:
item
+
"年"
,
id
:
item
}));
}
}
catch
(
error
)
{
}
};
const
handleGetSearchAllCountry
=
async
()
=>
{
try
{
const
res
=
await
getSearchAllCountry
();
if
(
res
.
code
===
200
&&
res
.
data
)
{
surveyCountryList
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
COUNTRYNAME
,
id
:
item
.
COUNTRYID
}));
}
}
catch
(
error
)
{
}
};
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
Promise
.
all
([
handleGetSearchAllArea
(),
handleGetSearchAllYear
(),
handleGetSearchAllCountry
()]);
await
Promise
.
all
([
handleGetSearchAllArea
(),
handleGetSearchAllYear
(),
handleGetSearchAllCountry
()]);
...
@@ -360,58 +313,50 @@ onMounted(async () => {
...
@@ -360,58 +313,50 @@ onMounted(async () => {
.left
{
.left
{
width
:
360px
;
width
:
360px
;
min-height
:
56
0px
;
min-height
:
30
0px
;
height
:
fit-content
;
height
:
fit-content
;
padding-bottom
:
20px
;
padding-bottom
:
20px
;
border-radius
:
10px
;
border-radius
:
10px
;
box-shadow
:
0px
0px
15px
0px
rgba
(
60
,
87
,
126
,
0
.2
);
box-shadow
:
0px
0px
15px
0px
rgba
(
60
,
87
,
126
,
0
.2
);
background
:
#fff
;
background
:
#fff
;
.left-box
{
.check-box
{
margin-top
:
17px
;
margin-top
:
18px
;
.check-head
{
.left-header
{
position
:
relative
;
display
:
flex
;
margin-bottom
:
12px
;
align-items
:
center
;
&
:
:
before
{
content
:
""
;
.icon
{
position
:
absolute
;
top
:
0px
;
left
:
0px
;
width
:
8px
;
width
:
8px
;
height
:
1
6px
;
height
:
1
00%
;
background
:
var
(
--
color-
main-active
);
background
:
var
(
--
color-
primary-100
);
border-radius
:
0
2px
2px
0
;
border-radius
:
0
2px
2px
0
;
}
}
.head-name
{
.title
{
margin-left
:
25px
;
margin-left
:
17px
;
color
:
var
(
--
color-primary-100
);
color
:
var
(
--
color-main-active
);
font-size
:
16px
;
font-weight
:
700
;
}
}
}
.checkbox-group
{
padding
:
10px
0
0
25px
;
.filter-checkbox
{
width
:
130px
;
margin-bottom
:
8px
;
height
:
32px
;
:deep
(
.el-checkbox__label
)
{
font-size
:
16px
;
font-size
:
16px
;
color
:
#5f656c
;
line-height
:
16px
;
font-family
:
Source
Han
Sans
CN
;
font-weight
:
bold
;
}
}
}
}
.check-list
{
.expand-btn
{
padding
:
0
10px
0
25px
;
color
:
var
(
--
color-main-active
);
display
:
grid
;
font-size
:
14px
;
grid-template-columns
:
repeat
(
2
,
1fr
);
cursor
:
pointer
;
grid-gap
:
0
12px
;
display
:
flex
;
.check-item
{
align-items
:
center
;
width
:
100%
;
margin-top
:
4px
;
height
:
32px
;
:deep
(
.el-checkbox__label
)
{
.el-icon
{
font-family
:
Source
Han
Sans
CN
;
margin-left
:
4px
;
font-size
:
16px
;
color
:
var
(
--
text-primary-65-color
);
}
}
}
}
}
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论