Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
35d9d557
提交
35d9d557
authored
3月 05, 2026
作者:
张伊明
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor 新增数据卡片组件,新增查询列表组件
上级
5f3d772b
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
1209 行增加
和
0 行删除
+1209
-0
g2.mdc
.cursor/rules/g2.mdc
+53
-0
OverviewCard.vue
src/views/bill/billHome/OverviewCard.vue
+88
-0
ResourceLibrarySection.vue
src/views/bill/billHome/ResourceLibrarySection.vue
+1068
-0
没有找到文件。
.cursor/rules/g2.mdc
0 → 100644
浏览文件 @
35d9d557
---
alwaysApply: true
---
# Overview
Insert overview text here. The agent will only see this should they choose to apply the rule.
```markdown
---
alwaysApply: true
---
# 前端开发(Cursor 专用执行要点)
## 1. HTML / 模板
- 属性命名:统一用小写-中线分割。动态 class 也用这种格式,使用单引号:`:class="{ 'xxx-xxx': isXxx }"`
- v-for 必须有唯一 key,`v-for + :key`(如`:key="item.id"`),禁止仅凭索引。示例:`<li v-for="item in list" :key="item.id"></li>`
- 禁止 v-if 与 v-for 同时在同一节点;如需筛选请用计算属性/方法过滤后再 v-for
- 无内容组件或标签必须自闭合,如 `<MyComp />` `<img />` `<input />`
- HTML 属性用双引号,动态属性外已双引号则用单引号
- 模板表达式保持极简,只写取值或很简单的显示;任何有数据处理(如数组/字符串操作、三元、函数执行等)必须抽到方法或计算属性完成
## 2. CSS
- 样式模块优先通用组件,确需定制严格按设计来写
- 全部样式变量统一来源于全局(如 `:root { --color-main-primary: #055fC2; ... }`)
- `<style scoped>` 默认加 scoped
- 修改子组件样式用 `:deep()`(Vue3 推荐写法),如:`.xxx :deep(.el-xxx) { ... }`
- 严禁页面大量内联 style,样式尽量写到 class 或 :style 绑定表达式
## 3. 文件系统
- 文件夹采用小驼峰,无数字/无关字符
- 每个业务模块 API 独立放模块对应文件夹
- 静态资源分全局 assets 与模块 assets:全局图片 assets/images,icon 建议 SVG,模块区分子文件夹
## 4. 组件
- 组件名大驼峰(PascalCase)。组件类型目录小驼峰,具体组件目录(如 AreaTag)大驼峰
- 单文件组件名 index.vue,多组件文件按具体功能如 LeftBtn.vue
- 优先用通用组件,业务组件只能放业务模块,不得放全局
## 5. JS/TS
- 命名统一规范
- 变量:小驼峰 userName、isVisible
- 常量:大写+下划线,如 MAX_COUNT
- 枚举:枚举名大驼峰,枚举值全大写+下划线 enum Status { SUCCESS = 'SUCCESS' }
- 普通函数:小驼峰+动词前缀 getUser/formatTime
- 事件函数:小驼峰+handle/on handleSubmit/onClose
- 布尔型函数:is/has/should + 大驼峰,如 isValid()
- 异步强制 async/await,catch 错误。禁止 Promise.then 链式嵌套(如遇回调 hell 必须拆分/抽象重写)
- 一律用 const/let 替换 var,优先 const
- 注释:
- 单行注释:后加空格,如 `// 注释内容`
- 方法/复杂模块加 /** JSDoc 注释 */
## 6. 其它
- 所有复杂渲染逻辑逻辑一律抽到计算属性或方法,模板结构保持简洁
src/views/bill/billHome/OverviewCard.vue
0 → 100644
浏览文件 @
35d9d557
<
template
>
<div
class=
"overview-card"
>
<div
class=
"overview-card-header"
>
<div
class=
"overview-card-header-left"
>
<div
class=
"overview-card-header-icon"
>
<img
:src=
"icon"
alt=
""
/>
</div>
<div
class=
"overview-card-header-title"
>
{{
title
}}
</div>
</div>
<div
v-if=
"$slots.right"
class=
"overview-card-header-right"
>
<slot
name=
"right"
/>
</div>
</div>
<div
class=
"overview-card-main"
>
<slot
/>
</div>
</div>
</
template
>
<
script
setup
>
defineProps
({
title
:
{
type
:
String
,
default
:
""
},
icon
:
{
type
:
String
,
default
:
""
}
});
</
script
>
<
style
lang=
"scss"
scoped
>
.overview-card
{
height
:
450px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
overflow
:
hidden
;
.overview-card-header
{
height
:
53px
;
border-bottom
:
1px
solid
rgba
(
240
,
242
,
244
,
1
);
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
padding
:
0
27px
0
22px
;
.overview-card-header-left
{
display
:
flex
;
align-items
:
center
;
.overview-card-header-icon
{
width
:
19px
;
height
:
19px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.overview-card-header-title
{
margin-left
:
19px
;
height
:
26px
;
color
:
rgba
(
20
,
89
,
187
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
20px
;
font-weight
:
700
;
line-height
:
26px
;
}
}
.overview-card-header-right
{
display
:
flex
;
align-items
:
center
;
justify-content
:
flex-end
;
height
:
100%
;
}
}
.overview-card-main
{
height
:
calc
(
100%
-
53px
);
}
}
</
style
>
src/views/bill/billHome/ResourceLibrarySection.vue
0 → 100644
浏览文件 @
35d9d557
<
template
>
<div
class=
"resource-library-section"
>
<div
class=
"home-content-footer-header"
>
<div
class=
"btn-box"
>
<div
class=
"btn"
:class=
"
{ btnActive: activeTabName === cate.name, disabled: index > 2 }"
v-for="(cate, index) in tabList" :key="index" @click="index
<
=
2
&&
handleClickTab
(
cate
)"
>
{{
cate
.
name
}}
</div>
</div>
</div>
<div
class=
"home-content-footer-main"
>
<div
class=
"left"
v-if=
"['国会法案', '国会议员', '议员合作关系'].includes(activeTabName)"
>
<div
class=
"select-box"
>
<div
class=
"select-box-header"
>
<div
class=
"icon"
></div>
<div
class=
"title"
>
科技领域
</div>
</div>
<div
class=
"select-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"activeAreaList"
@
change=
"handleAreaChange"
>
<el-checkbox
class=
"filter-checkbox"
label=
"全部领域"
>
全部领域
</el-checkbox>
<el-checkbox
v-for=
"(area, index) in cateKuList"
:key=
"index"
:label=
"area.id"
class=
"filter-checkbox"
>
{{
area
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<div
class=
"select-box"
v-if=
"activeTabName !== '议员合作关系'"
>
<div
class=
"select-box-header"
>
<div
class=
"icon"
></div>
<div
class=
"title"
>
党派
</div>
</div>
<div
class=
"select-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"activeDpList"
@
change=
"handleDpChange"
>
<el-checkbox
v-for=
"(dp, index) in dpList"
:key=
"index"
:label=
"dp.id"
class=
"filter-checkbox"
>
{{
dp
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<div
class=
"select-box"
v-if=
"activeTabName !== '议员合作关系'"
>
<div
class=
"select-box-header"
>
<div
class=
"icon"
></div>
<div
class=
"title"
>
议院
</div>
</div>
<div
class=
"select-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"activeYyList"
@
change=
"handleYyChange"
>
<el-checkbox
v-for=
"(yy, index) in yyList"
:key=
"index"
:label=
"yy.id"
class=
"filter-checkbox"
>
{{
yy
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<div
class=
"select-box"
v-if=
"activeTabName === '国会法案'"
>
<div
class=
"select-box-header"
>
<div
class=
"icon"
></div>
<div
class=
"title"
>
发布时间
</div>
</div>
<div
class=
"select-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"activePubTime"
@
change=
"handlePubTimeChange"
>
<el-checkbox
v-for=
"(time, index) in pubTime"
:key=
"index"
:label=
"time.id"
class=
"filter-checkbox"
>
{{
time
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<div
class=
"select-box"
v-if=
"activeTabName === '议员合作关系'"
>
<div
class=
"select-box-header"
>
<div
class=
"icon"
></div>
<div
class=
"title"
>
合作关系
</div>
</div>
<div
class=
"select-main"
>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"activeCoopList"
@
change=
"handleCoopChange"
>
<el-checkbox
v-for=
"(coop, index) in coopList"
:key=
"index"
:label=
"coop.id"
class=
"filter-checkbox"
>
{{
coop
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</div>
<div
class=
"right"
>
<div
class=
"right-header"
>
<div
class=
"right-header-box"
>
<el-select
v-model=
"footerSelect1"
placeholder=
"选择委员会"
style=
"width: 240px"
@
change=
"handleFooterSelect1Change"
>
<el-option
v-for=
"item in postOrgList"
:key=
"item.departmentId"
:label=
"item.departmentName"
:value=
"item.departmentId"
/>
</el-select>
</div>
<template
v-if=
"activeTabName === '国会法案'"
>
<div
class=
"right-header-box"
>
<el-select
v-model=
"footerSelect2"
placeholder=
"选择提出议员"
style=
"width: 240px"
@
change=
"handleFooterSelect2Change"
>
<el-option
v-for=
"item in postMemberList"
:key=
"item.memberId"
:label=
"item.memberName"
:value=
"item.memberId"
/>
</el-select>
</div>
<div
class=
"right-header-box right-header-sort"
style=
"margin-left: auto"
>
<el-checkbox
v-model=
"isInvolveCn"
true-label=
"Y"
false-label=
"N"
class=
"involve-checkbox"
@
change=
"handleInvolveCnChange"
>
只看涉华法案
</el-checkbox>
<el-select
v-model=
"releaseTime"
placeholder=
"选择排序方式"
style=
"width: 120px"
@
change=
"handlePxChange"
>
<template
#
prefix
>
<div
style=
"display: flex; align-items: center; height: 100%"
>
<img
:src=
"desc"
style=
"width: 14px; height: 14px"
/>
</div>
</
template
>
<el-option
v-for=
"item in releaseTimeList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</div>
</template>
</div>
<div
class=
"right-main"
v-loading=
"loading"
>
<
template
v-if=
"activeTabName === '国会法案'"
>
<div
class=
"right-main-box"
v-for=
"(item, index) in bills"
:key=
"index"
>
<div
v-if=
"item.riskSignal"
class=
"risk-tag"
:class=
"getRiskTagClass(item.riskSignal)"
>
{{
item
.
riskSignal
}}
</div>
<div
class=
"header"
>
<div
class=
"title"
@
click=
"onClickToDetail(item)"
:title=
"item.name"
>
{{
item
.
name
}}
</div>
<div
class=
"en-title"
:title=
"item.eName"
>
{{
item
.
eName
}}
</div>
</div>
<div
class=
"main"
>
<div
class=
"item"
><div
class=
"item-left"
>
提案人:
</div><div
class=
"item-right"
>
{{
item
.
tcr
}}
</div></div>
<div
class=
"item"
><div
class=
"item-left"
>
委员会:
</div><div
class=
"item-right"
>
{{
item
.
wyh
}}
</div></div>
<div
class=
"item"
><div
class=
"item-left"
>
相关领域:
</div><div
class=
"item-right1"
><div
class=
"tag"
v-for=
"(val, idx) in item.areaList"
:key=
"idx"
>
{{
val
}}
</div></div></div>
<div
class=
"item"
><div
class=
"item-left"
>
最新动议:
</div><div
class=
"item-right"
><CommonPrompt
:content=
"item.zxdy"
/></div></div>
<div
class=
"item"
>
<div
class=
"item-left"
>
法案进展:
</div>
<div
class=
"item-right2"
>
<div
class=
"tag"
v-for=
"(val, idx) in [...item.progress].reverse()"
:key=
"idx"
:style=
"
{ zIndex: item.progress.length - idx }">
{{
val
}}
</div>
</div>
</div>
</div>
</div>
<div
class=
"right-footer"
>
<div
class=
"footer-left"
>
{{
`共 ${total
}
项`
}}
<
/div
>
<
div
class
=
"footer-right"
>
<
el
-
pagination
@
current
-
change
=
"handleCurrentChange"
:
page
-
size
=
"pageSize"
:
current
-
page
=
"currentPage"
background
layout
=
"prev, pager, next"
:
total
=
"total"
/>
<
/div
>
<
/div
>
<
/template
>
<
div
v
-
else
-
if
=
"activeTabName === '国会议员'"
>
<
div
class
=
"member-grid"
>
<
div
class
=
"member-card"
v
-
for
=
"item in memberList"
:
key
=
"item.id"
>
<
div
class
=
"member-card-top"
>
<
div
class
=
"member-avatar-wrap"
>
<
img
class
=
"member-avatar"
:
src
=
"item.avatar || defaultAvatar"
alt
=
"avatar"
/>
<
div
class
=
"member-icon-row"
>
<
img
v
-
if
=
"item.partyIcon"
class
=
"member-mini-icon-img"
:
src
=
"item.partyIcon"
alt
=
"party"
/>
<
img
v
-
if
=
"item.chamberIcon"
class
=
"member-mini-icon-img"
:
src
=
"item.chamberIcon"
alt
=
"chamber"
/>
<
/div
>
<
/div
>
<
div
class
=
"member-main"
>
<
div
class
=
"member-title-row"
>
<
div
class
=
"member-name"
>
{{
item
.
name
||
'-'
}}
<
/div
>
<
div
class
=
"member-link"
>
{{
item
.
billCountText
||
'0项提案 >'
}}
<
/div
>
<
/div
>
<
div
class
=
"member-meta"
>
{{
item
.
partyText
||
'-'
}}
·
{{
item
.
chamberText
||
'-'
}}
·
{{
item
.
termText
||
'-'
}}
<
/div
>
<
div
class
=
"member-committee"
>
{{
item
.
committeeText
||
'-'
}}
<
/div
>
<
div
class
=
"member-tags"
>
<
div
class
=
"member-tag"
v
-
for
=
"(tag, idx) in item.focusTags"
:
key
=
"idx"
>
{{
tag
}}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"member-card-bottom"
@
click
=
"handleClickLatestProposal(item)"
>
<
div
class
=
"member-latest"
>
最新提案:
{{
item
.
latestProposal
||
'-'
}}
<
/div
>
<
div
class
=
"member-arrow"
>><
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"right-footer"
>
<
div
class
=
"footer-left"
>
{{
`共 ${memberTotal
}
项`
}}
<
/div
>
<
div
class
=
"footer-right"
>
<
el
-
pagination
@
current
-
change
=
"handleMemberCurrentChange"
:
page
-
size
=
"memberPageSize"
:
current
-
page
=
"memberCurrentPage"
background
layout
=
"prev, pager, next"
:
total
=
"memberTotal"
/>
<
/div
>
<
/div
>
<
/div
>
<
div
v
-
else
-
if
=
"activeTabName === '议员合作关系'"
class
=
"coop-list"
>
<
div
class
=
"member-card"
v
-
for
=
"item in memberList"
:
key
=
"`coop-${item.id
}
`"
>
<
div
class
=
"member-name"
>
{{
item
.
name
||
'-'
}}
<
/div
>
<
div
class
=
"member-info"
>
党派:
{{
item
.
party
||
'-'
}}
<
/div
>
<
div
class
=
"member-info"
>
议院:
{{
item
.
chamber
||
'-'
}}
<
/div
>
<
div
class
=
"member-info"
>
任期:
{{
item
.
term
||
'-'
}}
<
/div
>
<
div
class
=
"member-info"
>
委员会:
{{
item
.
committee
||
'-'
}}
<
/div
>
<
div
class
=
"member-info"
>
关注领域:
{{
item
.
focus
||
'-'
}}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/template
>
<
script
setup
>
import
{
onMounted
,
ref
}
from
"vue"
;
import
{
getHylyList
,
getPostOrgList
,
getPostMemberList
,
getBills
,
getBillsPerson
}
from
"@/api/bill/billHome"
;
import
CommonPrompt
from
"../commonPrompt/index.vue"
;
import
desc
from
"./assets/icons/icon-desc.png"
;
import
defaultAvatar
from
"./assets/images/user.png"
;
import
zyyIcon
from
"@/assets/icons/zyy.png"
;
import
cyyIcon
from
"@/assets/icons/cyy.png"
;
import
ghdIcon
from
"@/assets/icons/ghd.png"
;
import
mzdIcon
from
"@/assets/icons/mzd.png"
;
const
props
=
defineProps
({
onClickToDetail
:
{
type
:
Function
,
required
:
true
}
,
onAfterPageChange
:
{
type
:
Function
,
default
:
null
}
}
);
const
tabList
=
ref
([
{
name
:
"国会法案"
,
active
:
true
}
,
{
name
:
"国会议员"
,
active
:
false
}
,
{
name
:
"议员合作关系"
,
active
:
false
}
,
{
name
:
"涉华委员会"
,
active
:
false
}
]);
const
activeTabName
=
ref
(
"国会法案"
);
const
handleClickTab
=
tab
=>
{
activeTabName
.
value
=
tab
.
name
;
if
(
tab
.
name
===
"国会议员"
)
{
memberCurrentPage
.
value
=
1
;
handleGetBillsPerson
();
return
;
}
if
(
tab
.
name
===
"国会法案"
)
{
currentPage
.
value
=
1
;
handleGetBills
();
}
}
;
const
releaseTime
=
ref
(
true
);
const
releaseTimeList
=
ref
([{
label
:
"正序"
,
value
:
true
}
,
{
label
:
"倒序"
,
value
:
false
}
]);
const
isInvolveCn
=
ref
(
"Y"
);
const
cateKuList
=
ref
([]);
const
activeAreaList
=
ref
([
"全部领域"
]);
const
dpList
=
ref
([{
id
:
"全部党派"
,
name
:
"全部党派"
}
,
{
id
:
"Democratic"
,
name
:
"民主党"
}
,
{
id
:
"Republican"
,
name
:
"共和党"
}
]);
const
activeDpList
=
ref
([
"全部党派"
]);
const
yyList
=
ref
([{
id
:
"全部议院"
,
name
:
"全部议院"
}
,
{
id
:
"S"
,
name
:
"参议院"
}
,
{
id
:
"H"
,
name
:
"众议院"
}
]);
const
activeYyList
=
ref
([
"全部议院"
]);
const
pubTime
=
ref
([{
id
:
"全部时间"
,
name
:
"全部时间"
}
,
{
id
:
"2025"
,
name
:
"2025年"
}
,
{
id
:
"2024"
,
name
:
"2024年"
}
,
{
id
:
"2023"
,
name
:
"2023年"
}
,
{
id
:
"2022"
,
name
:
"2022年"
}
,
{
id
:
"2021"
,
name
:
"2021年"
}
]);
const
activePubTime
=
ref
([
"全部时间"
]);
const
coopList
=
ref
([
{
id
:
"全部合作关系"
,
name
:
"全部合作关系"
}
,
{
id
:
"跨党派合作"
,
name
:
"跨党派合作"
}
,
{
id
:
"同党派合作"
,
name
:
"同党派合作"
}
,
{
id
:
"地域利益合作"
,
name
:
"地域利益合作"
}
,
{
id
:
"委员会内合作"
,
name
:
"委员会内合作"
}
]);
const
activeCoopList
=
ref
([
"全部合作关系"
]);
const
footerSelect1
=
ref
(
"全部委员会"
);
const
footerSelect2
=
ref
(
"全部提出议员"
);
const
postOrgList
=
ref
([{
departmentName
:
"全部委员会"
,
departmentId
:
"全部委员会"
}
]);
const
postMemberList
=
ref
([{
memberName
:
"全部提出议员"
,
memberId
:
"全部提出议员"
}
]);
const
memberList
=
ref
([]);
const
memberTotal
=
ref
(
0
);
const
memberPageSize
=
ref
(
15
);
const
memberCurrentPage
=
ref
(
1
);
const
bills
=
ref
([]);
const
total
=
ref
(
0
);
const
pageSize
=
ref
(
4
);
const
currentPage
=
ref
(
1
);
const
loading
=
ref
(
false
);
const
abortController
=
ref
(
null
);
const
getRiskTagClass
=
riskSignal
=>
{
if
(
riskSignal
===
"特别重大风险"
)
return
"risk-tag-critical"
;
if
(
riskSignal
===
"重大风险"
)
return
"risk-tag-high"
;
if
(
riskSignal
===
"较大风险"
)
return
"risk-tag-medium"
;
return
""
;
}
;
const
handleGetHylyList
=
async
()
=>
{
try
{
const
res
=
await
getHylyList
();
cateKuList
.
value
=
res
.
data
||
[];
}
catch
(
error
)
{
}
}
;
const
handleGetPostOrgList
=
async
()
=>
{
try
{
const
res
=
await
getPostOrgList
();
if
(
res
.
code
===
200
)
{
const
list
=
(
res
.
data
||
[]).
filter
(
item
=>
item
.
departmentId
);
postOrgList
.
value
=
[{
departmentName
:
"全部委员会"
,
departmentId
:
"全部委员会"
}
,
...
list
];
}
}
catch
(
error
)
{
}
}
;
const
handleGetPostMemberList
=
async
()
=>
{
try
{
const
res
=
await
getPostMemberList
();
if
(
res
.
code
===
200
)
{
const
list
=
(
res
.
data
||
[]).
filter
(
item
=>
item
.
memberId
);
postMemberList
.
value
=
[{
memberName
:
"全部提出议员"
,
memberId
:
"全部提出议员"
}
,
...
list
];
}
}
catch
(
error
)
{
}
}
;
// 获取资源库法案列表
const
handleGetBills
=
async
()
=>
{
if
(
abortController
.
value
)
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
loading
.
value
=
true
;
const
params
=
{
currentPage
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
,
isInvolveCn
:
isInvolveCn
.
value
}
;
if
(
!
activeYyList
.
value
.
includes
(
"全部议院"
))
params
.
congressIds
=
activeYyList
.
value
.
join
(
","
);
if
(
footerSelect1
.
value
!==
"全部委员会"
)
params
.
departmentId
=
footerSelect1
.
value
;
if
(
!
activeDpList
.
value
.
includes
(
"全部党派"
))
params
.
partyIds
=
activeDpList
.
value
.
join
(
","
);
if
(
footerSelect2
.
value
!==
"全部提出议员"
)
params
.
personId
=
footerSelect2
.
value
;
if
(
!
activeAreaList
.
value
.
includes
(
"全部领域"
))
params
.
researchIds
=
activeAreaList
.
value
.
join
(
","
);
if
(
releaseTime
.
value
!==
true
)
params
.
sortFun
=
releaseTime
.
value
;
if
(
!
activePubTime
.
value
.
includes
(
"全部时间"
))
params
.
years
=
activePubTime
.
value
.
join
(
","
);
try
{
const
res
=
await
getBills
(
params
,
abortController
.
value
.
signal
);
if
(
res
.
code
===
200
&&
res
.
data
&&
res
.
data
.
content
)
{
bills
.
value
=
res
.
data
.
content
.
map
(
item
=>
({
billId
:
item
.
billId
,
name
:
item
.
billName
,
eName
:
item
.
billNameEn
,
tcr
:
item
.
personName
,
wyh
:
item
.
congressName
,
areaList
:
item
.
hylyList
||
[],
zxdy
:
item
.
latestAction
,
progress
:
item
.
stageList
||
[],
riskSignal
:
item
.
riskSignal
||
""
}
));
total
.
value
=
res
.
data
.
totalElements
;
}
else
{
bills
.
value
=
[];
total
.
value
=
0
;
}
}
catch
(
error
)
{
if
(
error
.
name
!==
"AbortError"
)
{
bills
.
value
=
[];
total
.
value
=
0
;
}
}
finally
{
loading
.
value
=
false
;
}
}
;
// 获取资源库国会议员列表
const
handleGetBillsPerson
=
async
()
=>
{
if
(
abortController
.
value
)
abortController
.
value
.
abort
();
abortController
.
value
=
new
AbortController
();
loading
.
value
=
true
;
const
params
=
{
currentPage
:
memberCurrentPage
.
value
,
pageSize
:
memberPageSize
.
value
}
;
if
(
footerSelect1
.
value
!==
"全部委员会"
)
params
.
committeeId
=
footerSelect1
.
value
;
if
(
!
activeYyList
.
value
.
includes
(
"全部议院"
))
params
.
congressIds
=
activeYyList
.
value
;
if
(
!
activeDpList
.
value
.
includes
(
"全部党派"
))
params
.
partyIds
=
activeDpList
.
value
;
if
(
!
activeAreaList
.
value
.
includes
(
"全部领域"
))
params
.
domainIds
=
activeAreaList
.
value
;
const
formatDateYm
=
dateStr
=>
{
if
(
!
dateStr
)
return
""
;
const
date
=
String
(
dateStr
).
slice
(
0
,
10
);
const
parts
=
date
.
split
(
"-"
);
if
(
parts
.
length
<
2
)
return
dateStr
;
return
`${parts[0]
}
.${parts[1]
}
`
;
}
;
try
{
const
res
=
await
getBillsPerson
(
params
,
abortController
.
value
.
signal
);
if
(
res
.
code
===
200
&&
res
.
data
&&
res
.
data
.
content
)
{
memberList
.
value
=
res
.
data
.
content
.
map
(
item
=>
{
const
partyMap
=
{
Democratic
:
"民主党"
,
Republican
:
"共和党"
}
;
const
partyText
=
partyMap
[
item
.
partyId
]
||
item
.
partyId
||
"-"
;
const
chamberText
=
item
.
congressType
||
"-"
;
const
start
=
formatDateYm
(
item
.
startTime
);
const
end
=
formatDateYm
(
item
.
endTime
);
const
termText
=
start
||
end
?
`${start
}
${end ? `
-
$
{
end
}
` : ""
}
`
:
"-"
;
const
focusTags
=
(
item
.
domainNames
||
[]).
slice
(
0
,
3
);
const
proposalSize
=
Number
(
item
.
proposalSize
||
0
);
const
partyIcon
=
item
.
partyId
===
"Democratic"
?
mzdIcon
:
item
.
partyId
===
"Republican"
?
ghdIcon
:
""
;
const
chamberIcon
=
chamberText
===
"众议院"
?
zyyIcon
:
chamberText
===
"参议院"
?
cyyIcon
:
""
;
return
{
id
:
item
.
id
,
name
:
item
.
name
||
"-"
,
avatar
:
item
.
imageUrl
||
""
,
partyIcon
,
chamberIcon
,
billCountText
:
`${proposalSize.toLocaleString()
}
项提案 >`
,
partyText
,
chamberText
,
termText
,
committeeText
:
item
.
position
||
"-"
,
focusTags
,
latestProposal
:
item
.
latestBillInfo
?.
billName
||
"-"
,
latestProposalBillId
:
item
.
latestBillInfo
?.
billId
||
""
,
party
:
item
.
partyId
,
chamber
:
item
.
congressType
,
term
:
`${item.startTime || ""
}
${item.endTime ? `
至
$
{
item
.
endTime
}
` : ""
}
`
,
committee
:
item
.
position
,
focus
:
(
item
.
domainNames
||
[]).
join
(
"、"
)
}
;
}
);
memberTotal
.
value
=
res
.
data
.
totalElements
||
0
;
}
else
{
memberList
.
value
=
[];
memberTotal
.
value
=
0
;
}
}
catch
(
error
)
{
if
(
error
.
name
!==
"AbortError"
)
{
memberList
.
value
=
[];
memberTotal
.
value
=
0
;
}
}
finally
{
loading
.
value
=
false
;
}
}
;
const
normalizeWithAll
=
(
val
,
allLabel
,
targetRef
)
=>
{
if
(
val
.
includes
(
allLabel
)
&&
val
.
length
>
1
)
{
targetRef
.
value
=
val
[
val
.
length
-
1
]
===
allLabel
?
[
allLabel
]
:
val
.
filter
(
item
=>
item
!==
allLabel
);
}
else
if
(
val
.
length
===
0
)
{
targetRef
.
value
=
[
allLabel
];
}
else
{
targetRef
.
value
=
val
;
}
currentPage
.
value
=
1
;
memberCurrentPage
.
value
=
1
;
if
(
activeTabName
.
value
===
"国会议员"
)
{
handleGetBillsPerson
();
return
;
}
handleGetBills
();
}
;
const
handleAreaChange
=
val
=>
normalizeWithAll
(
val
,
"全部领域"
,
activeAreaList
);
const
handleDpChange
=
val
=>
normalizeWithAll
(
val
,
"全部党派"
,
activeDpList
);
const
handleYyChange
=
val
=>
normalizeWithAll
(
val
,
"全部议院"
,
activeYyList
);
const
handlePubTimeChange
=
val
=>
normalizeWithAll
(
val
,
"全部时间"
,
activePubTime
);
const
handleCoopChange
=
val
=>
normalizeWithAll
(
val
,
"全部合作关系"
,
activeCoopList
);
const
handleFooterSelect1Change
=
val
=>
{
footerSelect1
.
value
=
val
;
currentPage
.
value
=
1
;
memberCurrentPage
.
value
=
1
;
if
(
activeTabName
.
value
===
"国会议员"
)
{
handleGetBillsPerson
();
return
;
}
handleGetBills
();
}
;
const
handleFooterSelect2Change
=
val
=>
{
footerSelect2
.
value
=
val
;
currentPage
.
value
=
1
;
handleGetBills
();
}
;
const
handlePxChange
=
val
=>
{
releaseTime
.
value
=
val
;
currentPage
.
value
=
1
;
handleGetBills
();
}
;
const
handleInvolveCnChange
=
val
=>
{
isInvolveCn
.
value
=
val
;
currentPage
.
value
=
1
;
handleGetBills
();
}
;
const
handleCurrentChange
=
page
=>
{
currentPage
.
value
=
page
;
handleGetBills
();
props
.
onAfterPageChange
&&
props
.
onAfterPageChange
();
}
;
const
handleClickLatestProposal
=
item
=>
{
if
(
!
item
?.
latestProposalBillId
)
return
;
props
.
onClickToDetail
({
billId
:
item
.
latestProposalBillId
,
name
:
item
.
latestProposal
}
);
}
;
const
handleMemberCurrentChange
=
page
=>
{
memberCurrentPage
.
value
=
page
;
handleGetBillsPerson
();
props
.
onAfterPageChange
&&
props
.
onAfterPageChange
();
}
;
onMounted
(()
=>
{
handleGetHylyList
();
handleGetPostOrgList
();
handleGetPostMemberList
();
handleGetBills
();
}
);
<
/script
>
<
style
lang
=
"scss"
scoped
>
.
home
-
content
-
footer
-
header
{
width
:
1600
px
;
margin
:
0
auto
;
margin
-
top
:
37
px
;
margin
-
bottom
:
36
px
;
height
:
42
px
;
display
:
flex
;
justify
-
content
:
space
-
between
;
.
btn
-
box
{
display
:
flex
;
gap
:
24
px
;
width
:
1000
px
;
.
btn
{
height
:
42
px
;
line
-
height
:
42
px
;
padding
:
0
20
px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font
-
family
:
Microsoft
YaHei
;
font
-
size
:
20
px
;
font
-
weight
:
400
;
border
-
radius
:
21
px
;
cursor
:
pointer
;
&
:
hover
{
background
:
rgba
(
20
,
89
,
187
,
0.1
);
}
}
.
btnActive
{
background
:
var
(
--
color
-
main
-
active
);
color
:
#
fff
;
font
-
weight
:
700
;
&
:
hover
{
color
:
#
fff
;
background
:
var
(
--
color
-
main
-
active
);
}
}
.
disabled
{
cursor
:
not
-
allowed
;
opacity
:
0.5
;
&
:
hover
{
background
:
transparent
;
}
}
}
}
.
home
-
content
-
footer
-
main
{
width
:
1600
px
;
height
:
1401
px
;
margin
:
0
auto
;
display
:
flex
;
justify
-
content
:
space
-
between
;
align
-
items
:
flex
-
start
;
.
left
{
width
:
300
px
;
padding
-
bottom
:
33
px
;
box
-
sizing
:
border
-
box
;
border
:
1
px
solid
rgba
(
234
,
236
,
238
,
1
);
border
-
radius
:
10
px
;
box
-
shadow
:
0
px
0
px
20
px
0
px
rgba
(
25
,
69
,
130
,
0.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
.
select
-
box
{
margin
-
top
:
20
px
;
.
select
-
box
-
header
{
display
:
flex
;
gap
:
17
px
;
.
icon
{
margin
-
top
:
4
px
;
width
:
8
px
;
height
:
16
px
;
background
:
var
(
--
color
-
main
-
active
);
border
-
radius
:
0
4
px
4
px
0
;
}
.
title
{
color
:
var
(
--
color
-
main
-
active
);
font
-
family
:
Microsoft
YaHei
;
font
-
size
:
20
px
;
font
-
weight
:
700
;
line
-
height
:
26
px
;
letter
-
spacing
:
1
px
;
text
-
align
:
left
;
}
}
.
select
-
main
{
margin
-
left
:
25
px
;
margin
-
top
:
16
px
;
.
checkbox
-
group
{
display
:
flex
;
flex
-
wrap
:
wrap
;
.
filter
-
checkbox
{
width
:
50
%
;
margin
-
right
:
0
;
margin
-
bottom
:
4
px
;
:
deep
(.
el
-
checkbox__label
)
{
color
:
rgb
(
95
,
101
,
108
);
font
-
size
:
16
px
;
font
-
weight
:
400
;
font
-
family
:
"Microsoft YaHei"
;
line
-
height
:
24
px
;
}
}
}
}
}
}
.
right
{
margin
-
left
:
20
px
;
width
:
1280
px
;
.
right
-
header
{
height
:
48
px
;
display
:
flex
;
gap
:
18
px
;
.
right
-
header
-
sort
{
display
:
flex
;
align
-
items
:
center
;
gap
:
20
px
;
}
.
involve
-
checkbox
{
height
:
40
px
;
display
:
inline
-
flex
;
align
-
items
:
center
;
margin
-
right
:
0
;
:
deep
(.
el
-
checkbox__inner
)
{
width
:
18
px
;
height
:
18
px
;
border
-
radius
:
5
px
;
}
:
deep
(.
el
-
checkbox__input
.
is
-
checked
.
el
-
checkbox__inner
)
{
background
-
color
:
#
1677
ff
;
border
-
color
:
#
1677
ff
;
}
:
deep
(.
el
-
checkbox__inner
::
after
)
{
box
-
sizing
:
content
-
box
;
}
:
deep
(.
el
-
checkbox__label
)
{
color
:
#
5
f656c
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
16
px
;
font
-
weight
:
400
;
line
-
height
:
24
px
;
padding
-
left
:
10
px
;
}
}
}
.
right
-
main
{
height
:
1264
px
;
.
member
-
grid
,
.
coop
-
list
{
display
:
grid
;
column
-
gap
:
16
px
;
row
-
gap
:
16
px
;
.
member
-
card
{
height
:
200
px
;
padding
:
10
px
16
px
0
;
box
-
sizing
:
border
-
box
;
border
-
radius
:
10
px
;
box
-
shadow
:
0
px
0
px
20
px
0
px
rgba
(
25
,
69
,
130
,
0.1
);
background
:
#
fff
;
overflow
:
hidden
;
display
:
flex
;
flex
-
direction
:
column
;
justify
-
content
:
space
-
between
;
.
member
-
card
-
top
{
display
:
flex
;
gap
:
16
px
;
}
.
member
-
avatar
-
wrap
{
width
:
88
px
;
display
:
flex
;
flex
-
direction
:
column
;
align
-
items
:
center
;
flex
-
shrink
:
0
;
position
:
relative
;
/* padding-bottom: 22px; */
margin
-
top
:
5
px
;
}
.
member
-
avatar
{
width
:
88
px
;
height
:
88
px
;
border
-
radius
:
50
%
;
object
-
fit
:
cover
;
}
.
member
-
icon
-
row
{
position
:
absolute
;
left
:
50
%
;
bottom
:
18
px
;
transform
:
translateX
(
-
50
%
);
display
:
flex
;
gap
:
2
px
;
align
-
items
:
center
;
}
.
member
-
mini
-
icon
-
img
{
width
:
16
px
;
height
:
16
px
;
padding
:
2
px
;
box
-
sizing
:
border
-
box
;
object
-
fit
:
contain
;
border
-
radius
:
50
%
;
background
:
#
fff
;
}
.
member
-
main
{
flex
:
1
;
min
-
width
:
0
;
padding
-
top
:
2
px
;
}
.
member
-
title
-
row
{
display
:
flex
;
align
-
items
:
baseline
;
justify
-
content
:
space
-
between
;
align
-
items
:
center
;
gap
:
8
px
;
}
.
member
-
name
{
color
:
rgb
(
59
,
65
,
75
);
font
-
family
:
"Source Han Sans CN"
;
font
-
size
:
18
px
;
font
-
weight
:
700
;
line
-
height
:
24
px
;
white
-
space
:
nowrap
;
overflow
:
hidden
;
text
-
overflow
:
ellipsis
;
}
.
member
-
link
{
flex
-
shrink
:
0
;
color
:
#
1459
bb
;
font
-
size
:
16
px
;
line
-
height
:
24
px
;
}
.
member
-
meta
,
.
member
-
committee
{
margin
-
top
:
6
px
;
color
:
#
5
f656c
;
font
-
size
:
16
px
;
line
-
height
:
24
px
;
font
-
weight
:
400
;
white
-
space
:
nowrap
;
overflow
:
hidden
;
text
-
overflow
:
ellipsis
;
}
.
member
-
tags
{
margin
-
top
:
10
px
;
display
:
flex
;
gap
:
8
px
;
flex
-
wrap
:
wrap
;
}
.
member
-
tag
{
height
:
24
px
;
padding
:
5
px
8
px
;
border
-
radius
:
4
px
;
background
:
rgb
(
231
,
243
,
255
);
color
:
rgb
(
5
,
95
,
194
);
font
-
size
:
14
px
;
font
-
weight
:
400
;
line
-
height
:
14
px
;
}
.
member
-
card
-
bottom
{
height
:
52
px
;
margin
:
10
px
-
16
px
0
;
padding
:
0
16
px
;
display
:
flex
;
align
-
items
:
center
;
justify
-
content
:
space
-
between
;
border
-
top
:
1
px
solid
#
eaeced
;
color
:
#
5
f656c
;
font
-
size
:
16
px
;
cursor
:
pointer
;
&
:
hover
{
background
:
rgba
(
20
,
89
,
187
,
0.04
);
}
}
.
member
-
latest
{
flex
:
1
;
white
-
space
:
nowrap
;
overflow
:
hidden
;
text
-
overflow
:
ellipsis
;
padding
-
right
:
8
px
;
}
.
member
-
arrow
{
font
-
size
:
16
px
;
line
-
height
:
1
;
color
:
#
5
f656c
;
}
.
member
-
info
{
color
:
#
5
f656c
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
15
px
;
font
-
weight
:
400
;
line
-
height
:
28
px
;
}
}
}
.
member
-
grid
{
grid
-
template
-
columns
:
repeat
(
3
,
1
fr
);
}
.
coop
-
list
{
grid
-
template
-
columns
:
1
fr
;
}
.
right
-
main
-
box
{
position
:
relative
;
width
:
1280
px
;
height
:
300
px
;
padding
-
bottom
:
24
px
;
border
-
radius
:
10
px
;
box
-
shadow
:
0
px
0
px
20
px
0
px
rgba
(
25
,
69
,
130
,
0.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
margin
-
bottom
:
16
px
;
overflow
:
hidden
;
.
risk
-
tag
{
position
:
absolute
;
top
:
16
px
;
right
:
40
px
;
height
:
28
px
;
border
-
radius
:
20
px
;
display
:
inline
-
flex
;
align
-
items
:
center
;
gap
:
6
px
;
padding
:
0
10
px
;
box
-
sizing
:
border
-
box
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
14
px
;
font
-
weight
:
500
;
line
-
height
:
28
px
;
white
-
space
:
nowrap
;
&
::
before
{
content
:
""
;
width
:
5
px
;
height
:
5
px
;
border
-
radius
:
50
%
;
background
:
currentColor
;
flex
-
shrink
:
0
;
}
}
.
risk
-
tag
-
critical
{
background
:
rgba
(
206
,
79
,
81
,
0.1
);
color
:
rgb
(
206
,
79
,
81
);
}
.
risk
-
tag
-
high
{
background
:
rgba
(
255
,
149
,
77
,
0.1
);
color
:
rgb
(
255
,
149
,
77
);
}
.
risk
-
tag
-
medium
{
background
:
rgba
(
232
,
189
,
11
,
0.1
);
color
:
rgb
(
232
,
189
,
11
);
}
.
header
{
height
:
91
px
;
width
:
1200
px
;
margin
:
0
auto
;
border
-
bottom
:
1
px
solid
rgba
(
234
,
236
,
238
,
1
);
padding
-
top
:
19
px
;
.
title
{
cursor
:
pointer
;
height
:
26
px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font
-
family
:
Microsoft
YaHei
;
font
-
size
:
20
px
;
font
-
weight
:
700
;
line
-
height
:
26
px
;
letter
-
spacing
:
0
px
;
text
-
align
:
left
;
overflow
:
hidden
;
text
-
overflow
:
ellipsis
;
white
-
space
:
nowrap
;
}
.
en
-
title
{
margin
-
top
:
8
px
;
height
:
24
px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font
-
family
:
Microsoft
YaHei
;
font
-
size
:
16
px
;
font
-
weight
:
400
;
line
-
height
:
24
px
;
letter
-
spacing
:
0
px
;
text
-
align
:
left
;
overflow
:
hidden
;
text
-
overflow
:
ellipsis
;
white
-
space
:
nowrap
;
}
}
.
main
{
width
:
1200
px
;
margin
:
0
auto
;
margin
-
top
:
2
px
;
.
item
{
margin
-
top
:
12
px
;
display
:
flex
;
.
item
-
left
{
width
:
100
px
;
color
:
rgb
(
59
,
65
,
75
);
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
16
px
;
font
-
weight
:
700
;
line
-
height
:
24
px
;
letter
-
spacing
:
1
px
;
text
-
align
:
left
;
}
.
item
-
right
{
max
-
width
:
1000
px
;
margin
-
left
:
10
px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
16
px
;
font
-
weight
:
400
;
line
-
height
:
24
px
;
letter
-
spacing
:
0
px
;
text
-
align
:
left
;
}
.
item
-
right1
{
margin
-
left
:
10
px
;
display
:
flex
;
gap
:
8
px
;
.
tag
{
height
:
24
px
;
line
-
height
:
24
px
;
padding
:
0
8
px
;
border
-
radius
:
4
px
;
background
:
rgba
(
231
,
243
,
255
,
1
);
color
:
var
(
--
color
-
main
-
active
);
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
}
}
.
item
-
right2
{
margin
-
left
:
10
px
;
display
:
flex
;
align
-
items
:
center
;
.
tag
{
height
:
24
px
;
line
-
height
:
22
px
;
padding
:
0
10
px
0
30
px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
color
:
rgb
(
95
,
101
,
108
);
border
-
top
:
1
px
solid
rgb
(
234
,
236
,
238
);
border
-
bottom
:
1
px
solid
rgb
(
234
,
236
,
238
);
position
:
relative
;
margin
-
left
:
-
10
px
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
&
::
after
{
content
:
""
;
position
:
absolute
;
top
:
50
%
;
right
:
-
8.485
px
;
width
:
16.97
px
;
height
:
16.97
px
;
background
:
inherit
;
border
-
top
:
1
px
solid
rgb
(
234
,
236
,
238
);
border
-
right
:
1
px
solid
rgb
(
234
,
236
,
238
);
transform
:
translateY
(
-
50
%
)
rotate
(
45
deg
);
z
-
index
:
1
;
box
-
shadow
:
2
px
-
2
px
2
px
rgba
(
0
,
0
,
0
,
0.05
);
box
-
sizing
:
border
-
box
;
}
&
:
first
-
child
{
margin
-
left
:
0
;
padding
-
left
:
10
px
;
border
-
left
:
1
px
solid
rgb
(
234
,
236
,
238
);
border
-
radius
:
4
px
0
0
4
px
;
}
&
:
last
-
child
{
background
:
rgb
(
59
,
65
,
75
);
color
:
rgba
(
255
,
255
,
255
,
1
);
border
-
color
:
rgb
(
59
,
65
,
75
);
padding
-
right
:
10
px
;
border
-
radius
:
0
;
border
-
right
:
none
;
&
::
after
{
display
:
block
;
border
-
color
:
rgb
(
59
,
65
,
75
);
box
-
shadow
:
none
;
}
}
&
:
first
-
child
:
last
-
child
{
margin
-
left
:
0
;
padding
:
0
10
px
;
border
-
radius
:
4
px
0
0
4
px
;
background
:
rgb
(
59
,
65
,
75
);
color
:
rgba
(
255
,
255
,
255
,
1
);
border
:
1
px
solid
rgb
(
59
,
65
,
75
);
border
-
right
:
none
;
}
}
}
}
}
}
}
.
right
-
footer
{
height
:
85
px
;
display
:
flex
;
justify
-
content
:
space
-
between
;
box
-
sizing
:
border
-
box
;
padding
-
top
:
12
px
;
.
footer
-
left
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
16
px
;
font
-
weight
:
400
;
line
-
height
:
32
px
;
}
}
}
}
<
/style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论