Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
8e7d08ff
提交
8e7d08ff
authored
3月 25, 2026
作者:
coderBryanFu
浏览文件
操作
浏览文件
下载
差异文件
feat:更新数据资源库
上级
05beb3ae
8148dacc
流水线
#61
已失败 于阶段
in 43 秒
变更
37
流水线
1
全部展开
显示空白字符变更
内嵌
并排
正在显示
37 个修改的文件
包含
1238 行增加
和
476 行删除
+1238
-476
billHome.js
src/api/bill/billHome.js
+64
-33
background.js
src/api/decree/background.js
+11
-0
home.js
src/api/decree/home.js
+11
-1
introduction.js
src/api/decree/introduction.js
+2
-2
overview.js
src/api/innovationSubject/overview.js
+53
-55
index.vue
src/components/base/DecreeOriginal/index.vue
+6
-8
InnovationSubject.js
src/router/modules/InnovationSubject.js
+4
-6
decree.js
src/router/modules/decree.js
+7
-4
index.ts
src/views/bill/influence/ProgressForecast/api/index.ts
+0
-0
BillCard.vue
...s/bill/influence/ProgressForecast/components/BillCard.vue
+0
-3
FilterSection.vue
...l/influence/ProgressForecast/components/FilterSection.vue
+166
-47
PredictionPhaseCard.vue
...uence/ProgressForecast/components/PredictionPhaseCard.vue
+15
-12
ProposalInfoSection.vue
...uence/ProgressForecast/components/ProposalInfoSection.vue
+2
-12
Step1FilterCondition.vue
...ence/ProgressForecast/components/Step1FilterCondition.vue
+22
-80
Step2FilterBills.vue
...nfluence/ProgressForecast/components/Step2FilterBills.vue
+20
-21
Step3PredictionAnalysis.vue
...e/ProgressForecast/components/Step3PredictionAnalysis.vue
+19
-17
index.vue
src/views/bill/influence/ProgressForecast/index.vue
+0
-0
symbol.png
...erOfCongress/components/characterRelationships/symbol.png
+0
-0
BillCard.vue
...ess/components/historicalProposal/components/BillCard.vue
+17
-13
index.vue
src/views/characterPage/components/techLeader/index.vue
+15
-4
index.vue
src/views/characterPage/components/thinkTankPerson/index.vue
+16
-4
tips-icon.png
src/views/decree/allOrganization/assets/icons/tips-icon.png
+0
-0
index.vue
src/views/decree/allOrganization/index.vue
+322
-0
MindGraph.vue
src/views/decree/com/MindGraph.vue
+123
-0
index.vue
src/views/decree/decreeHome/index.vue
+45
-36
index.vue
src/views/decree/decreeLayout/deepdig/index.vue
+0
-1
index.vue
src/views/decree/decreeLayout/influence/index.vue
+1
-1
index.vue
src/views/decree/decreeLayout/overview/background/index.vue
+17
-8
index.vue
...views/decree/decreeLayout/overview/introduction/index.vue
+5
-12
edit-line.png
...ecreeLayout/overview/measures/assets/images/edit-line.png
+0
-0
index.vue
src/views/decree/decreeLayout/overview/measures/index.vue
+134
-2
index.vue
...ontrol/v2.0SingleSanction/components/deepMining/index.vue
+12
-13
ResourceLibrary.vue
...ews/innovationSubject/ResourceLibrary/ResourceLibrary.vue
+27
-15
index.vue
src/views/innovationSubject/innovativeInstitutions/index.vue
+9
-1
OtherInfo.vue
...novationSubject/innovativeInstitutions/tabs/OtherInfo.vue
+92
-65
ResearchStrength.vue
...nSubject/innovativeInstitutions/tabs/ResearchStrength.vue
+0
-0
vite.config.js
vite.config.js
+1
-0
没有找到文件。
src/api/bill/billHome.js
浏览文件 @
8e7d08ff
...
@@ -328,16 +328,20 @@ export function getProgressPrediction(billId) {
...
@@ -328,16 +328,20 @@ export function getProgressPrediction(billId) {
/**
/**
* 获取相似法案列表
* 获取相似法案列表
* @param {Object} params - 查询参数
* @param {Object} params - 查询参数
* @param {string} params.patternType - 政府结构类型,如 "统一政府"
* @param {string} params.billIds - 当前法案的ID
* @param {string} params.proposalType - 提案类型,默认 "两党共同提案"
* @param {string[]} params.domains - 领域名称列表
* @param {string} params.patternType - 政府结构类型,如 "统一政府"/"分裂政府"/"微弱多数"
* @param {string} params.proposalType - 提案类型,如 "两党共同提案"/"单政党提案(共和党提案)"/"单政党提案(民主党提案)"
* @returns {Promise<Object>} 相似法案列表
* @returns {Promise<Object>} 相似法案列表
*/
*/
export
function
getSimiBills
(
params
=
{})
{
export
function
getSimiBills
(
params
=
{})
{
return
request
(
'/api/BillProgressPrediction/simiBills'
,
{
return
request
(
'/api/BillProgressPrediction/simiBills'
,
{
method
:
'GET'
,
method
:
'GET'
,
params
:
{
params
:
{
patternType
:
params
.
patternType
||
'统一政府'
,
billIds
:
params
.
billIds
,
proposalType
:
params
.
proposalType
||
'两党共同提案'
,
domains
:
params
.
domains
,
patternType
:
params
.
patternType
,
proposalType
:
params
.
proposalType
,
...
params
...
params
}
}
})
})
...
@@ -400,31 +404,42 @@ export function transformSimiBillsData(apiData) {
...
@@ -400,31 +404,42 @@ export function transformSimiBillsData(apiData) {
const
transformedBills
=
bills
.
map
(
bill
=>
({
const
transformedBills
=
bills
.
map
(
bill
=>
({
id
:
bill
.
bill_id
,
id
:
bill
.
bill_id
,
title
:
bill
.
bill_name
||
bill
.
bill_id
,
title
:
bill
.
bill_name
||
bill
.
bill_id
,
tags
:
[
bill
.
poli_pattern_type
,
bill
.
bill_proposal_type
].
filter
(
Boolean
),
proposalDate
:
extractProposalDate
(
bill
.
poli_pattern_desc
),
passTime
:
extractPassTime
(
bill
.
bill_actions
),
areas
:
bill
.
domain_name
?
(
Array
.
isArray
(
bill
.
domain_name
)
?
bill
.
domain_name
:
[
bill
.
domain_name
])
:
[],
totalDays
:
calculateTotalDays
(
bill
.
bill_actions
),
proposer
:
extractProposer
(
bill
.
bill_sponsors
),
selected
:
true
,
// 默认全选
coProposers
:
bill
.
bill_proposal_desc
||
''
,
_raw
:
bill
governmentType
:
formatGovernmentType
(
bill
.
poli_pattern_type
,
bill
.
poli_pattern_desc
),
passDays
:
calculateTotalDays
(
bill
.
bill_actions
),
selected
:
true
// 默认全选
}))
}))
return
{
stats
,
bills
:
transformedBills
}
return
{
stats
,
bills
:
transformedBills
}
}
}
/**
/**
* 从
法案动作中提取通过
时间
* 从
政治格局描述中提取提案
时间
* @param {
Array} actions - 法案动作列表
* @param {
string} desc - 政治格局描述
* @returns {string}
通过
时间
* @returns {string}
提案
时间
*/
*/
function
extractPassTime
(
actions
)
{
function
extractProposalDate
(
desc
)
{
if
(
!
actions
||
actions
.
length
===
0
)
return
''
if
(
!
desc
)
return
''
// 找到最后一个动作的日期
const
match
=
desc
.
match
(
/
(\d{4})
-
(\d{2})
-
(\d{2})
/
)
const
lastAction
=
actions
[
actions
.
length
-
1
]
if
(
match
)
{
if
(
lastAction
&&
lastAction
.
action_date
)
{
return
`
${
match
[
1
]}
年
${
parseInt
(
match
[
2
])}
月
${
parseInt
(
match
[
3
])}
日`
const
date
=
new
Date
(
lastAction
.
action_date
)
return
`
${
date
.
getFullYear
()}
年
${
date
.
getMonth
()
+
1
}
月
${
date
.
getDate
()}
日`
}
}
return
''
return
''
}
}
/**
* 从提案人列表中提取主提案人
* @param {Array} sponsors - 提案人列表
* @returns {string} 主提案人姓名
*/
function
extractProposer
(
sponsors
)
{
if
(
!
sponsors
||
sponsors
.
length
===
0
)
return
''
const
mainProposer
=
sponsors
.
find
(
s
=>
s
.
sponsor_type
===
'提案人'
)
return
mainProposer
?
mainProposer
.
person_name
:
''
}
/**
/**
/**
* 计算法案总耗时
* 计算法案总耗时
...
@@ -488,29 +503,30 @@ export function transformProposalInfo(apiData) {
...
@@ -488,29 +503,30 @@ export function transformProposalInfo(apiData) {
}
}
return
{
return
{
// 提案标题
- 需要从其他 API 获取或使用默认值
// 提案标题
title
:
data
.
bill_title
||
'H.R.1-大而美法案'
,
title
:
data
.
bill_title
||
'H.R.1-大而美法案'
,
// 提案时间 - 从政治格局描述中提取
或使用默认值
// 提案时间 - 从政治格局描述中提取
date
:
extractDateFromDesc
(
data
.
poli_pattern_desc
)
||
'2025年5月20日'
,
date
:
extractDateFromDesc
(
data
.
poli_pattern_desc
)
||
'2025年5月20日'
,
// 涉及领域
// 涉及领域 TAG - 使用 domain_name
areas
:
data
.
domain_name
||
[],
areas
:
Array
.
isArray
(
data
.
domain_name
)
?
data
.
domain_name
:
(
data
.
domain_name
?
[
data
.
domain_name
]
:
[]),
// 选举周期阶段 - 从政治格局描述推断
// 政策领域完整选项列表 - 使用 bill_domain(用于筛选下拉框)
electionPhase
:
inferElectionPhase
(
data
.
poli_pattern_desc
)
||
'执政初期/蜜月期'
,
billDomain
:
Array
.
isArray
(
data
.
bill_domain
)
?
data
.
bill_domain
:
[],
// 政策领域默认已选项 - 使用 domain_name
defaultDomains
:
Array
.
isArray
(
data
.
domain_name
)
?
data
.
domain_name
:
(
data
.
domain_name
?
[
data
.
domain_name
]
:
[]),
// 提案人
// 提案人
proposer
:
mainProposer
?
`
${
mainProposer
.
person_name
}
`
:
''
,
proposer
:
mainProposer
?
mainProposer
.
person_name
:
''
,
// 共同提案人
// 共同提案人
coProposers
:
coProposersDesc
,
coProposers
:
coProposersDesc
,
// 提案人职务 - 需要从其他 API 获取
proposerPosition
:
data
.
proposer_position
||
'委员会主席'
,
// 政府结构类型
// 政府结构类型
governmentType
:
formatGovernmentType
(
data
.
poli_pattern_type
,
data
.
poli_pattern_desc
),
governmentType
:
formatGovernmentType
(
data
.
poli_pattern_type
,
data
.
poli_pattern_desc
),
//
法案预算规模 - 需要从其他 API 获取
//
政治格局类型(用于筛选条件默认值)
budgetScale
:
data
.
budget_scale
||
'4万亿美元
'
,
patternType
:
data
.
poli_pattern_type
||
'统一政府
'
,
// 原始数据,供筛选条件使用
// 原始数据,供筛选条件使用
_raw
:
data
_raw
:
data
}
}
}
}
/**
/**
* 从政治格局描述中提取日期
* 从政治格局描述中提取日期
* @param {string} desc - 政治格局描述
* @param {string} desc - 政治格局描述
...
@@ -579,8 +595,6 @@ export function generateDefaultFilters(proposalInfo) {
...
@@ -579,8 +595,6 @@ export function generateDefaultFilters(proposalInfo) {
proposerPosition
:
proposalInfo
.
proposerPosition
===
'委员会主席'
?
[
'chairman'
]
:
[],
proposerPosition
:
proposalInfo
.
proposerPosition
===
'委员会主席'
?
[
'chairman'
]
:
[],
// 政府结构类型
// 政府结构类型
governmentType
:
proposalInfo
.
governmentType
.
includes
(
'一致'
)
?
[
'unified'
]
:
[
'divided'
],
governmentType
:
proposalInfo
.
governmentType
.
includes
(
'一致'
)
?
[
'unified'
]
:
[
'divided'
],
// 选举周期阶段
electionPhase
:
proposalInfo
.
electionPhase
.
includes
(
'蜜月'
)
?
[
'honeymoon'
]
:
[],
// 法案预算规模
// 法案预算规模
budgetScale
:
[
'trillion_plus'
],
budgetScale
:
[
'trillion_plus'
],
// 对方党派提案人
// 对方党派提案人
...
@@ -589,3 +603,19 @@ export function generateDefaultFilters(proposalInfo) {
...
@@ -589,3 +603,19 @@ export function generateDefaultFilters(proposalInfo) {
proposalTime
:
[
'recent_5'
]
proposalTime
:
[
'recent_5'
]
}
}
}
}
/**
* 获取预测分析结果
* @param {Object} params - 请求参数
* @param {string} params.bill_id - 当前法案ID
* @param {string} params.bill_name - 当前法案名称
* @param {Array} params.bill_actions - 当前法案动作列表
* @param {Array} params.bill_sponsors - 当前法案提案人列表
* @param {Array} params.simi_bills - 用户勾选的相似法案列表
* @returns {Promise<Object>} 预测分析结果
*/
export
function
getPassProd
(
params
)
{
return
request
(
'/api/BillProgressPrediction/passProd'
,
{
method
:
'POST'
,
data
:
params
})
}
\ No newline at end of file
src/api/decree/background.js
浏览文件 @
8e7d08ff
...
@@ -60,6 +60,17 @@ export function getDecreeMainContent(params) {
...
@@ -60,6 +60,17 @@ export function getDecreeMainContent(params) {
})
})
}
}
// 思维导图
/**
* @param { id }
*/
export
function
getDecreeMindMap
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/administrativeOrderInfo/mindMap/
${
params
.
id
}
`
,
})
}
// 相关实体
// 相关实体
/**
/**
* @param { id }
* @param { id }
...
...
src/api/decree/home.js
浏览文件 @
8e7d08ff
...
@@ -91,10 +91,20 @@ export function getDecreeTypeList() {
...
@@ -91,10 +91,20 @@ export function getDecreeTypeList() {
}
}
// 关键机构
// 关键机构
export
function
getKeyOrganization
()
{
export
function
getKeyOrganization
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/commonFeature/keyOrganization`
,
url
:
`/api/commonFeature/keyOrganization`
,
params
})
}
// 所有机构
export
function
getAllOrganization
(
params
)
{
return
request
({
method
:
'POST'
,
url
:
`/api/administrativeOrderOverview/orderCount`
,
data
:
params
})
})
}
}
...
...
src/api/decree/introduction.js
浏览文件 @
8e7d08ff
...
@@ -80,10 +80,10 @@ export function getDecreeReport(params) {
...
@@ -80,10 +80,10 @@ export function getDecreeReport(params) {
}
}
// 政令关键词云
// 政令关键词云
export
function
getKeyWordUp
()
{
export
function
getKeyWordUp
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/
element/getKeyWordUp/2025-01-01
`
,
url
:
`/api/
administrativeOrderInfo/wordCloud/
${
params
.
id
}
`
,
})
})
}
}
...
...
src/api/innovationSubject/overview.js
浏览文件 @
8e7d08ff
...
@@ -139,119 +139,117 @@ export function getPersonList(params) {
...
@@ -139,119 +139,117 @@ export function getPersonList(params) {
})
})
}
}
//创新主体科研实力:专利数量统计
export
function
getPatentList
(
params
)
{
//合作情况:与中国合作数量变化
export
function
getCooperateNumWithChina
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/innovateSubject/
patentList
/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/
cooperateNumWithChina
/
${
params
.
id
}
`
,
params
params
})
})
}
}
// 合作情况:与中国合作类型变化
// 创新主体科研实力:论文数量统计
export
function
getCooperateTypeWithChina
(
params
)
{
export
function
getPaperList
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/innovateSubject/
paperList
/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/
cooperateTypeWithChina/
${
params
.
year
}
/
${
params
.
id
}
`
,
params
params
})
})
}
}
//
创新主体科研实力:领域实力分布
//
合作情况:与中国合作领域变化
export
function
get
StudyFieldList
(
params
)
{
export
function
get
CooperateAreaWithChina
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/innovateSubject/studyFieldList/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/cooperateAreaWithChina/
${
params
.
id
}
`
,
params
})
})
}
}
//
创新主体科研实力:经费增长情况
//
合作情况:与中国合作经费变化
export
function
get
FundGrowth
(
params
)
{
export
function
get
CooperateFundWithChina
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/innovateSubject/
fundGrowth
/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/
cooperateFundWithChina
/
${
params
.
id
}
`
,
params
params
})
})
}
}
//
创新主体科研实力:经费来源
//
合作情况:与中国合作事例
export
function
get
FundFromList
(
params
)
{
export
function
get
CooperateExampleWithChina
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/innovateSubject/
fundFromList
/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/
cooperateExampleWithChina
/
${
params
.
id
}
`
,
params
params
})
})
}
}
//创新主体科研实力:经费分配
export
function
getFundToList
(
params
)
{
// 专利数量统计
export
function
getPatentList
(
orgId
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
"GET"
,
url
:
`/api/innovateSubject/fundToList/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/patentList/
${
orgId
}
`
params
})
})
}
}
//
合作情况:与中国合作数量变化
//
论文数量统计
export
function
get
CooperateNumWithChina
(
params
)
{
export
function
get
PaperList
(
orgId
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
"GET"
,
url
:
`/api/innovateSubject/cooperateNumWithChina/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/paperList/
${
orgId
}
`
params
})
})
}
}
//
合作情况:与中国合作类型变化
//
领域实力分布
export
function
get
CooperateTypeWithChina
(
params
)
{
export
function
get
StudyFieldList
(
orgId
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
"GET"
,
url
:
`/api/innovateSubject/cooperateTypeWithChina/
${
params
.
year
}
/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/studyFieldList/
${
orgId
}
`
params
})
})
}
}
//
合作情况:与中国合作领域变化
//
经费增长情况
export
function
get
CooperateAreaWithChina
(
params
)
{
export
function
get
FundGrowth
(
orgId
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
"GET"
,
url
:
`/api/innovateSubject/cooperateAreaWithChina/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/fundGrowth/
${
orgId
}
`
params
})
})
}
}
//
合作情况:与中国合作经费变化
//
经费来源
export
function
get
CooperateFundWithChina
(
params
)
{
export
function
get
FundFromList
(
orgId
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
"GET"
,
url
:
`/api/innovateSubject/cooperateFundWithChina/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/fundFromList/
${
orgId
}
`
params
})
})
}
}
//
合作情况:与中国合作事例
//
经费分配
export
function
get
CooperateExampleWithChina
(
params
)
{
export
function
get
FundToList
(
orgId
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
"GET"
,
url
:
`/api/innovateSubject/cooperateExampleWithChina/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/fundToList/
${
orgId
}
`
params
})
})
}
}
// 获取实验室列表
//创新主体其他情况:重点实验室
export
function
getLabList
(
orgId
)
{
export
function
getLabList
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/innovateSubject/labList/
${
params
.
id
}
`
,
url
:
`/api/innovateSubject/labList/
${
orgId
}
`
})
})
}
}
//
创新主体其他情况:政策文件
//
获取政策文件列表
export
function
getPolicyList
(
params
)
{
export
function
getPolicyList
(
orgId
,
currentPage
=
1
,
pageSize
=
6
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/innovateSubject/policyList/
${
params
.
i
d
}
`
,
url
:
`/api/innovateSubject/policyList/
${
orgI
d
}
`
,
params
params
:
{
currentPage
,
pageSize
}
})
})
}
}
src/components/base/DecreeOriginal/index.vue
浏览文件 @
8e7d08ff
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
<div
class=
"switch-label switch-label-left"
>
高亮实体
</div>
<div
class=
"switch-label switch-label-left"
>
高亮实体
</div>
<el-switch
v-model=
"isTranslate"
/>
<el-switch
v-model=
"isTranslate"
/>
<div
class=
"switch-label"
>
原
文显示
</div>
<div
class=
"switch-label"
>
译
文显示
</div>
<div
<div
v-for=
"action in headerActions"
v-for=
"action in headerActions"
...
@@ -53,8 +53,8 @@
...
@@ -53,8 +53,8 @@
class=
"content-row"
class=
"content-row"
:class=
"
{ 'high-light': isHighlight }"
:class=
"
{ 'high-light': isHighlight }"
>
>
<div
class=
"content-
cn"
:class=
"
{ 'translate-cn': !isTranslate }" v-html="item.content" /
>
<div
class=
"content-
en"
v-html=
"item.contentEn"
:class=
"
{ 'translate-cn': !isTranslate }">
</div
>
<div
v-if=
"isTranslate"
class=
"content-en"
v-html=
"item.contentEn"
/
>
<div
class=
"content-cn"
v-html=
"item.content"
v-if=
"isTranslate"
></div
>
</div>
</div>
</el-scrollbar>
</el-scrollbar>
</div>
</div>
...
@@ -150,11 +150,9 @@ const doUpdateWord = () => {
...
@@ -150,11 +150,9 @@ const doUpdateWord = () => {
}
}
displayReportData
.
value
=
originReportData
.
value
.
map
((
item
)
=>
{
displayReportData
.
value
=
originReportData
.
value
.
map
((
item
)
=>
{
const
cn
=
applyHighlightToText
(
item
.
content
,
term
);
const
en
=
applyHighlightToText
(
item
.
contentEn
,
term
);
const
en
=
isTranslate
.
value
const
cn
=
isTranslate
.
value
?
applyHighlightToText
(
item
.
content
,
term
)
:
{
html
:
item
.
content
,
count
:
0
};
?
applyHighlightToText
(
item
.
contentEn
,
term
)
findWordMax
.
value
+=
en
.
count
+
cn
.
count
;
:
{
html
:
item
.
contentEn
,
count
:
0
};
findWordMax
.
value
+=
cn
.
count
+
en
.
count
;
return
{
return
{
...
item
,
...
item
,
content
:
cn
.
html
,
content
:
cn
.
html
,
...
...
src/router/modules/InnovationSubject.js
浏览文件 @
8e7d08ff
...
@@ -4,22 +4,20 @@ const InnovationInstitution = () => import('@/views/innovationSubject/innovative
...
@@ -4,22 +4,20 @@ const InnovationInstitution = () => import('@/views/innovationSubject/innovative
const
innovationSubjectRoutes
=
[
const
innovationSubjectRoutes
=
[
//创新主体
{
{
path
:
"/innovationSubject"
,
path
:
"/innovationSubject"
,
name
:
"InnovationSubject"
,
name
:
"InnovationSubject"
,
component
:
InnovationSubject
,
component
:
InnovationSubject
,
meta
:
{
meta
:
{
title
:
"M
国主要创新主体分析概览
"
title
:
"M
"
}
}
},
},
{
{
path
:
"/InnovativeInstitutions/:id"
,
path
:
"/InnovativeInstitutions/:id
/:type
"
,
name
:
"InnovativeInstitutions"
,
name
:
"InnovativeInstitutions"
,
component
:
InnovationInstitution
,
component
:
InnovationInstitution
,
// meta: {
// title: "学校详情"
// },
}
}
]
]
...
...
src/router/modules/decree.js
浏览文件 @
8e7d08ff
...
@@ -9,6 +9,7 @@ const DecreeDeepDig = () => import('@/views/decree/decreeLayout/deepdig/index.vu
...
@@ -9,6 +9,7 @@ const DecreeDeepDig = () => import('@/views/decree/decreeLayout/deepdig/index.vu
const
DecreeInfluence
=
()
=>
import
(
'@/views/decree/decreeLayout/influence/index.vue'
)
const
DecreeInfluence
=
()
=>
import
(
'@/views/decree/decreeLayout/influence/index.vue'
)
const
Institution
=
()
=>
import
(
'@/views/decree/institution/index.vue'
)
const
Institution
=
()
=>
import
(
'@/views/decree/institution/index.vue'
)
const
DecreeOriginal
=
()
=>
import
(
'@/views/decree/decreeOriginal/index.vue'
)
const
DecreeOriginal
=
()
=>
import
(
'@/views/decree/decreeOriginal/index.vue'
)
const
allOrganization
=
()
=>
import
(
'@/views/decree/allOrganization/index.vue'
)
const
decreeRoutes
=
[
const
decreeRoutes
=
[
...
@@ -93,11 +94,12 @@ const decreeRoutes = [
...
@@ -93,11 +94,12 @@ const decreeRoutes = [
path
:
"/decree/decreeOriginal"
,
path
:
"/decree/decreeOriginal"
,
name
:
"DecreeOriginal"
,
name
:
"DecreeOriginal"
,
component
:
DecreeOriginal
,
component
:
DecreeOriginal
,
// meta: {
// title: "政令原文"
// }
},
},
{
path
:
"/decree/allOrganization"
,
name
:
"allOrganization"
,
component
:
allOrganization
,
},
]
]
export
default
decreeRoutes
export
default
decreeRoutes
\ No newline at end of file
src/views/bill/influence/ProgressForecast/api/index.ts
浏览文件 @
8e7d08ff
差异被折叠。
点击展开。
src/views/bill/influence/ProgressForecast/components/BillCard.vue
浏览文件 @
8e7d08ff
...
@@ -50,12 +50,9 @@ const emit = defineEmits<{
...
@@ -50,12 +50,9 @@ const emit = defineEmits<{
const
billFields
=
[
const
billFields
=
[
{
key
:
'proposalDate'
,
label
:
'提案时间:'
},
{
key
:
'proposalDate'
,
label
:
'提案时间:'
},
{
key
:
'areas'
,
label
:
'涉及领域:'
},
{
key
:
'areas'
,
label
:
'涉及领域:'
},
{
key
:
'electionPhase'
,
label
:
'选举周期阶段:'
},
{
key
:
'proposer'
,
label
:
'提案人:'
},
{
key
:
'proposer'
,
label
:
'提案人:'
},
{
key
:
'coProposers'
,
label
:
'共同提案人:'
},
{
key
:
'coProposers'
,
label
:
'共同提案人:'
},
{
key
:
'proposerPosition'
,
label
:
'提案人职务:'
},
{
key
:
'governmentType'
,
label
:
'政府结构类型:'
},
{
key
:
'governmentType'
,
label
:
'政府结构类型:'
},
{
key
:
'budgetScale'
,
label
:
'法案预算规模:'
},
{
key
:
'passDays'
,
label
:
'通过耗时:'
}
{
key
:
'passDays'
,
label
:
'通过耗时:'
}
]
]
</
script
>
</
script
>
...
...
src/views/bill/influence/ProgressForecast/components/FilterSection.vue
浏览文件 @
8e7d08ff
...
@@ -5,56 +5,189 @@
...
@@ -5,56 +5,189 @@
<img
src=
"../assets/fitller.svg"
/>
<img
src=
"../assets/fitller.svg"
/>
<h2
class=
"section-title text-title-3-bold"
>
核心相似度维度筛选
</h2>
<h2
class=
"section-title text-title-3-bold"
>
核心相似度维度筛选
</h2>
</div>
</div>
<button
class=
"btn-outline"
@
click=
"
emit('setAsCurrent')
"
>
设置为当前提案
</button>
<button
class=
"btn-outline"
@
click=
"
setAsCurrent
"
>
设置为当前提案
</button>
</div>
</div>
<div
class=
"divider"
/>
<div
class=
"divider"
/>
<div
class=
"fields-grid"
>
<div
class=
"fields-grid"
>
<div
v-for=
"field in fields"
<!-- 政策领域 -->
:key=
"field.id"
<div
class=
"field-item"
>
class=
"field-item"
<span
class=
"field-label text-tip-1 text-primary-65-clor"
>
政策领域:
</span>
<div
class=
"field-content"
>
<el-select
v-model=
"localValues.policyArea"
multiple
placeholder=
"请选择"
style=
"width: 420px"
@
change=
"handleChange"
>
>
<div
class=
"field-label-wrapper"
>
<el-option
<span
class=
"field-label text-tip-1 text-primary-65-clor"
>
{{
field
.
label
}}
</span>
v-for=
"opt in fields.policyArea.options"
:key=
"opt.value"
:label=
"opt.label"
:value=
"opt.value"
/>
</el-select>
</div>
</div>
</div>
<!-- 政府结构类型 -->
<div
class=
"field-item"
>
<span
class=
"field-label text-tip-1 text-primary-65-clor"
>
政府结构类型:
</span>
<div
class=
"field-content"
>
<div
class=
"field-content"
>
<FilterSelect
<el-select
:options=
"field.options"
v-model=
"localValues.governmentType"
:model-value=
"field.selectedValues"
multiple
@
update:model-value=
"(val) => handleFieldUpdate(field.id, val)"
placeholder=
"请选择"
style=
"width: 420px"
@
change=
"handleChange"
>
<el-option
v-for=
"opt in fields.governmentType.options"
:key=
"opt.value"
:label=
"opt.label"
:value=
"opt.value"
/>
/>
<div
v-if=
"field.hint"
class=
"field-hint"
>
</el-select>
<div
v-if=
"fields.governmentType.hint"
class=
"field-hint"
>
<img
src=
"../assets/importent.svg"
/>
<img
src=
"../assets/importent.svg"
/>
<span
class=
"text-tip-2 text-primary-50-clor"
>
{{
field
.
hint
}}
</span>
<span
class=
"text-tip-2 text-primary-50-clor"
>
{{
field
s
.
governmentType
.
hint
}}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 对方党派提案人 -->
<div
class=
"field-item"
>
<span
class=
"field-label text-tip-1 text-primary-65-clor"
>
对方党派提案人:
</span>
<div
class=
"field-content"
>
<el-select
v-model=
"localValues.oppositionProposer"
multiple
placeholder=
"请选择"
style=
"width: 420px"
@
change=
"handleChange"
>
<el-option
v-for=
"opt in fields.oppositionProposer.options"
:key=
"opt.value"
:label=
"opt.label"
:value=
"opt.value"
/>
</el-select>
</div>
</div>
<!-- 提案时间 -->
<div
class=
"field-item"
>
<span
class=
"field-label text-tip-1 text-primary-65-clor"
>
提案时间:
</span>
<div
class=
"field-content"
>
<el-select
v-model=
"localValues.proposalTime"
multiple
placeholder=
"请选择"
style=
"width: 420px"
@
change=
"handleChange"
>
<el-option
v-for=
"opt in fields.proposalTime.options"
:key=
"opt.value"
:label=
"opt.label"
:value=
"opt.value"
/>
</el-select>
</div>
</div>
</div>
</div>
</section>
</section>
</
template
>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
type
{
FilterField
}
from
'../api
'
import
{
ref
,
computed
,
watch
}
from
'vue
'
import
FilterSelect
from
'./FilterSelect.vue
'
import
type
{
ProposalInfo
}
from
'../api
'
const
props
=
defineProps
<
{
const
props
=
defineProps
<
{
fields
:
FilterField
[]
proposalInfo
?:
ProposalInfo
|
null
defaultFilters
?:
Record
<
string
,
string
[]
>
}
>
()
}
>
()
const
emit
=
defineEmits
<
{
// 本地 v-model 值
'update:fields'
:
[
fields
:
FilterField
[]]
const
localValues
=
ref
({
setAsCurrent
:
[]
policyArea
:
[]
as
string
[],
}
>
()
governmentType
:
[]
as
string
[],
oppositionProposer
:
[]
as
string
[],
proposalTime
:
[]
as
string
[],
})
// 更新字段选中值
// 根据 proposalInfo 计算初始筛选值(即"设置为当前提案"的目标状态)
function
handleFieldUpdate
(
fieldId
:
string
,
newValues
:
string
[])
{
function
buildInitialValues
(
info
?:
ProposalInfo
|
null
):
Record
<
string
,
string
[]
>
{
const
updatedFields
=
props
.
fields
.
map
(
f
=>
if
(
!
info
)
return
{
policyArea
:
[],
governmentType
:
[],
oppositionProposer
:
[],
proposalTime
:
[]
}
f
.
id
===
fieldId
return
{
?
{
...
f
,
selectedValues
:
newValues
}
policyArea
:
info
.
defaultDomains
?.
length
?
[...
info
.
defaultDomains
]
:
[...(
info
.
areas
||
[])],
:
f
governmentType
:
info
.
patternType
?
[
info
.
patternType
]
:
[],
)
oppositionProposer
:
[],
emit
(
'update:fields'
,
updatedFields
)
proposalTime
:
[],
}
}
}
// 监听 proposalInfo 首次传入时设置初始值
watch
(
()
=>
props
.
proposalInfo
,
(
newInfo
)
=>
{
Object
.
assign
(
localValues
.
value
,
buildInitialValues
(
newInfo
))
},
{
immediate
:
true
}
)
// 重置:清空所有已选项
function
reset
()
{
localValues
.
value
=
{
policyArea
:
[],
governmentType
:
[],
oppositionProposer
:
[],
proposalTime
:
[],
}
}
// 设置为当前提案:恢复为 proposalInfo 的初始状态
function
setAsCurrent
()
{
Object
.
assign
(
localValues
.
value
,
buildInitialValues
(
props
.
proposalInfo
))
}
defineExpose
({
reset
,
setAsCurrent
,
getValues
:
()
=>
localValues
.
value
})
// 固定的字段配置,options 由 proposalInfo 动态注入
const
fields
=
computed
(()
=>
{
const
billDomain
=
props
.
proposalInfo
?.
billDomain
const
domainOptions
=
Array
.
isArray
(
billDomain
)
?
billDomain
.
map
(
d
=>
({
value
:
d
,
label
:
d
}))
:
[]
return
{
policyArea
:
{
options
:
domainOptions
},
governmentType
:
{
options
:
[
{
value
:
'统一政府'
,
label
:
'统一政府'
},
{
value
:
'分裂政府'
,
label
:
'分裂政府'
},
{
value
:
'微弱多数'
,
label
:
'微弱多数'
}
],
hint
:
'总统所属政党同时控制国会参众两院'
},
oppositionProposer
:
{
options
:
[
{
value
:
'两党共同提案'
,
label
:
'两党共同提案'
},
{
value
:
'单政党提案(共和党提案)'
,
label
:
'单政党提案(共和党提案)'
},
{
value
:
'单政党提案(民主党提案)'
,
label
:
'单政党提案(民主党提案)'
}
]
},
proposalTime
:
{
options
:
[
{
value
:
'近五年'
,
label
:
'近五年'
},
{
value
:
'近十年'
,
label
:
'近十年'
},
{
value
:
'全部'
,
label
:
'全部'
}
]
}
}
})
function
handleChange
()
{}
</
script
>
</
script
>
<
style
scoped
>
<
style
scoped
>
...
@@ -75,12 +208,6 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
...
@@ -75,12 +208,6 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
gap
:
12px
;
gap
:
12px
;
}
}
.section-icon
{
width
:
16px
;
height
:
16px
;
color
:
var
(
--text-primary-80-color
);
}
.btn-outline
{
.btn-outline
{
padding
:
6px
16px
;
padding
:
6px
16px
;
border
:
1px
solid
var
(
--bg-black-10
);
border
:
1px
solid
var
(
--bg-black-10
);
...
@@ -105,7 +232,7 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
...
@@ -105,7 +232,7 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
.fields-grid
{
.fields-grid
{
display
:
flex
;
display
:
flex
;
flex-wrap
:
wrap
;
flex-wrap
:
wrap
;
gap
:
24px
24px
;
gap
:
24px
;
padding-left
:
30px
;
padding-left
:
30px
;
}
}
...
@@ -113,15 +240,14 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
...
@@ -113,15 +240,14 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
width
:
580px
;
width
:
580px
;
display
:
flex
;
display
:
flex
;
align-items
:
flex-start
;
align-items
:
flex-start
;
}
gap
:
0
;
.field-label-wrapper
{
padding-top
:
4px
;
}
}
.field-label
{
.field-label
{
display
:
block
;
display
:
block
;
width
:
150px
;
width
:
140px
;
flex-shrink
:
0
;
padding-top
:
6px
;
}
}
.field-content
{
.field-content
{
...
@@ -135,11 +261,4 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
...
@@ -135,11 +261,4 @@ function handleFieldUpdate(fieldId: string, newValues: string[]) {
align-items
:
center
;
align-items
:
center
;
gap
:
8px
;
gap
:
8px
;
}
}
.hint-icon
{
width
:
16px
;
height
:
16px
;
flex-shrink
:
0
;
color
:
var
(
--text-primary-50-color
);
}
</
style
>
</
style
>
src/views/bill/influence/ProgressForecast/components/PredictionPhaseCard.vue
浏览文件 @
8e7d08ff
...
@@ -39,26 +39,19 @@
...
@@ -39,26 +39,19 @@
</p>
</p>
</div>
</div>
</div>
</div>
<div
class=
"facts-section"
>
<div
v-if=
"phase.predictionBasis"
class=
"facts-section"
>
<div
class=
"box-header flex-display-start"
>
<div
class=
"box-header flex-display-start"
>
<div
class=
"box-title-row flex-display-center"
>
<div
class=
"box-title-row flex-display-center"
>
<img
src=
"../assets/icon1.svg"
/>
<img
src=
"../assets/icon1.svg"
/>
<span
class=
"text-compact-bold"
>
{{
phase
.
supportingFacts
.
title
}}
</span>
<span
class=
"text-compact-bold"
>
通过性预测依据
</span>
</div>
</div>
<div
class=
"box-hint flex-display-center text-tip-2 text-primary-50-clor"
>
<div
class=
"box-hint flex-display-center text-tip-2 text-primary-50-clor"
>
<img
src=
"../assets/importent.svg"
/>
<img
src=
"../assets/importent.svg"
/>
<span>
{{
phase
.
supportingFacts
.
basedOn
}}
</span>
<span>
此阶段预测基于以下观点
</span>
</div>
</div>
</div>
</div>
<div
class=
"stats-grid"
>
<div
class=
"prediction-basis-content"
>
<div
<p
class=
"text-tip-2 text-primary-65-clor"
>
{{
phase
.
predictionBasis
}}
</p>
v-for=
"(stat, index) in phase.supportingFacts.stats"
:key=
"index"
class=
"stat-card"
>
<div
class=
"stat-value main-color"
>
{{
stat
.
value
}}
</div>
<div
class=
"text-tip-3 text-primary-65-clor"
>
{{
stat
.
label
}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -260,6 +253,16 @@ const riskLabel = computed(() => {
...
@@ -260,6 +253,16 @@ const riskLabel = computed(() => {
line-height
:
1.6
;
line-height
:
1.6
;
}
}
.prediction-basis-content
{
background-color
:
var
(
--bg-black-2
);
border-radius
:
var
(
--radius-10
);
padding
:
16px
;
}
.prediction-basis-content
p
{
line-height
:
1.6
;
}
.stats-grid
{
.stats-grid
{
display
:
grid
;
display
:
grid
;
grid-template-columns
:
repeat
(
4
,
1
fr
);
grid-template-columns
:
repeat
(
4
,
1
fr
);
...
...
src/views/bill/influence/ProgressForecast/components/ProposalInfoSection.vue
浏览文件 @
8e7d08ff
...
@@ -33,13 +33,6 @@
...
@@ -33,13 +33,6 @@
<span
class=
"info-label text-body-1"
>
{{
field
.
label
}}
</span>
<span
class=
"info-label text-body-1"
>
{{
field
.
label
}}
</span>
<template
v-if=
"field.key === 'areas'"
>
<template
v-if=
"field.key === 'areas'"
>
<div
class=
"area-tags"
>
<div
class=
"area-tags"
>
<!--
<span
v-for=
"area in info.areas"
:key=
"area"
class=
"area-tag"
>
{{
area
}}
</span>
-->
<AreaTag
v-for=
"area in info.areas"
:key=
"area"
:tagName=
"area"
/>
<AreaTag
v-for=
"area in info.areas"
:key=
"area"
:tagName=
"area"
/>
</div>
</div>
...
@@ -59,17 +52,14 @@ defineProps<{
...
@@ -59,17 +52,14 @@ defineProps<{
info
:
ProposalInfo
info
:
ProposalInfo
}
>
()
}
>
()
// 信息字段配置
// 信息字段配置
- 只保留:提案标题、提案时间、涉及领域、提案人、共同提案人、政府结构类型
const
infoFields
=
[
const
infoFields
=
[
{
key
:
'title'
,
label
:
'提案标题:'
},
{
key
:
'title'
,
label
:
'提案标题:'
},
{
key
:
'date'
,
label
:
'提案时间:'
},
{
key
:
'date'
,
label
:
'提案时间:'
},
{
key
:
'areas'
,
label
:
'涉及领域:'
},
{
key
:
'areas'
,
label
:
'涉及领域:'
},
{
key
:
'electionPhase'
,
label
:
'选举周期阶段:'
},
{
key
:
'proposer'
,
label
:
'提案人:'
},
{
key
:
'proposer'
,
label
:
'提案人:'
},
{
key
:
'coProposers'
,
label
:
'共同提案人:'
},
{
key
:
'coProposers'
,
label
:
'共同提案人:'
},
{
key
:
'proposerPosition'
,
label
:
'提案人职务:'
},
{
key
:
'governmentType'
,
label
:
'政府结构类型:'
}
{
key
:
'governmentType'
,
label
:
'政府结构类型:'
},
{
key
:
'budgetScale'
,
label
:
'法案预算规模:'
}
]
]
</
script
>
</
script
>
...
...
src/views/bill/influence/ProgressForecast/components/Step1FilterCondition.vue
浏览文件 @
8e7d08ff
...
@@ -7,9 +7,9 @@
...
@@ -7,9 +7,9 @@
<div
class=
"content-wrapper"
>
<div
class=
"content-wrapper"
>
<ProposalInfoSection
v-if=
"currentProposalInfo"
:info=
"currentProposalInfo"
/>
<ProposalInfoSection
v-if=
"currentProposalInfo"
:info=
"currentProposalInfo"
/>
<FilterSection
<FilterSection
:fields=
"filterFields
"
ref=
"filterSectionRef
"
@
update:fields=
"filterFields = $event
"
:proposal-info=
"currentProposalInfo
"
@
set-as-current=
"handleSetAsCurrent
"
:default-filters=
"defaultFilters
"
/>
/>
</div>
</div>
<ActionButtons
<ActionButtons
...
@@ -22,8 +22,7 @@
...
@@ -22,8 +22,7 @@
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
onMounted
,
watch
}
from
'vue'
import
{
ref
,
onMounted
,
watch
}
from
'vue'
import
type
{
ProposalInfo
,
FilterField
}
from
'../api'
import
type
{
ProposalInfo
}
from
'../api'
import
{
fetchProposalInfo
,
fetchFilterFields
}
from
'../api'
import
ProposalInfoSection
from
'./ProposalInfoSection.vue'
import
ProposalInfoSection
from
'./ProposalInfoSection.vue'
import
FilterSection
from
'./FilterSection.vue'
import
FilterSection
from
'./FilterSection.vue'
import
ActionButtons
from
'./ActionButtons.vue'
import
ActionButtons
from
'./ActionButtons.vue'
...
@@ -34,99 +33,42 @@ const props = defineProps<{
...
@@ -34,99 +33,42 @@ const props = defineProps<{
}
>
()
}
>
()
const
emit
=
defineEmits
<
{
const
emit
=
defineEmits
<
{
next
:
[]
next
:
[
selectedFilters
:
Record
<
string
,
string
[]
>
]
}
>
()
}
>
()
// 提案信息(优先使用 props
,否则从 API 获取
)
// 提案信息(优先使用 props)
const
currentProposalInfo
=
ref
<
ProposalInfo
|
null
>
(
null
)
const
currentProposalInfo
=
ref
<
ProposalInfo
|
null
>
(
null
)
//
筛选字段列表
//
FilterSection 组件引用
const
filter
Fields
=
ref
<
FilterField
[]
>
([]
)
const
filter
SectionRef
=
ref
<
InstanceType
<
typeof
FilterSection
>
|
null
>
(
null
)
// 加载状态
// 加载状态
const
loading
=
ref
(
true
)
const
loading
=
ref
(
true
)
//
初始筛选字段(用于重置)
//
默认筛选条件
const
initialFilterFields
=
ref
<
FilterField
[]
>
([]
)
const
defaultFilters
=
ref
<
Record
<
string
,
string
[]
>>
({}
)
// 监听 props.proposalInfo 变化
// 监听 props.proposalInfo 变化
watch
(()
=>
props
.
proposalInfo
,
(
newInfo
)
=>
{
watch
(()
=>
props
.
proposalInfo
,
(
newInfo
)
=>
{
if
(
newInfo
)
{
if
(
newInfo
)
{
currentProposalInfo
.
value
=
newInfo
currentProposalInfo
.
value
=
newInfo
// 根据提案信息生成默认筛选条件(仅用于 Step1 内部状态跟踪,不再传给 FilterSection)
defaultFilters
.
value
=
{
policyArea
:
newInfo
.
defaultDomains
?.
length
?
newInfo
.
defaultDomains
:
newInfo
.
areas
,
governmentType
:
newInfo
.
patternType
?
[
newInfo
.
patternType
]
:
[],
oppositionProposer
:
[],
proposalTime
:
[],
}
}
},
{
immediate
:
true
})
// 页面初始化时加载数据
onMounted
(
async
()
=>
{
try
{
// 如果没有从 props 获取到提案信息,则从 API 获取
if
(
!
props
.
proposalInfo
)
{
currentProposalInfo
.
value
=
await
fetchProposalInfo
()
}
// 获取筛选字段配置
const
fields
=
await
fetchFilterFields
()
// 如果有默认筛选条件,应用到筛选字段
if
(
props
.
defaultFilters
&&
Object
.
keys
(
props
.
defaultFilters
).
length
>
0
)
{
filterFields
.
value
=
fields
.
map
(
field
=>
({
...
field
,
selectedValues
:
props
.
defaultFilters
?.[
field
.
id
]
||
field
.
selectedValues
}))
}
else
{
filterFields
.
value
=
fields
}
}
// 保存初始状态用于重置
initialFilterFields
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
filterFields
.
value
))
}
finally
{
loading
.
value
=
false
loading
.
value
=
false
}
},
{
immediate
:
true
})
})
// 重置所有筛选条件
// 重置所有筛选条件
:清空所有已选项
function
handleReset
()
{
function
handleReset
()
{
filterFields
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
initialFilterFields
.
value
))
filterSectionRef
.
value
?.
reset
()
}
// 设置为当前提案
function
handleSetAsCurrent
()
{
// 根据当前提案信息重新设置筛选条件
if
(
currentProposalInfo
.
value
)
{
filterFields
.
value
=
filterFields
.
value
.
map
(
field
=>
{
// 根据提案信息设置默认值
const
defaultValues
=
getDefaultValuesForField
(
field
.
id
,
currentProposalInfo
.
value
!
)
return
{
...
field
,
selectedValues
:
defaultValues
.
length
>
0
?
defaultValues
:
field
.
selectedValues
}
})
}
}
// 根据字段 ID 和提案信息获取默认值
function
getDefaultValuesForField
(
fieldId
:
string
,
info
:
ProposalInfo
):
string
[]
{
const
areaMap
:
Record
<
string
,
string
>
=
{
'能源'
:
'energy'
,
'集成电路'
:
'ic'
,
'人工智能'
:
'ai'
,
'生物技术'
:
'biotech'
}
switch
(
fieldId
)
{
case
'policyArea'
:
return
info
.
areas
.
map
(
area
=>
areaMap
[
area
]
||
area
.
toLowerCase
())
case
'proposerPosition'
:
return
info
.
proposerPosition
===
'委员会主席'
?
[
'chairman'
]
:
[]
case
'governmentType'
:
return
info
.
governmentType
.
includes
(
'一致'
)
?
[
'unified'
]
:
[
'divided'
]
case
'electionPhase'
:
return
info
.
electionPhase
.
includes
(
'蜜月'
)
?
[
'honeymoon'
]
:
[]
default
:
return
[]
}
}
}
// 下一步
// 下一步
:获取已选的筛选条件并传给父组件
function
handleNext
()
{
function
handleNext
()
{
emit
(
'next'
)
const
selectedFilters
=
filterSectionRef
.
value
?.
getValues
()
||
{}
emit
(
'next'
,
selectedFilters
)
}
}
</
script
>
</
script
>
...
...
src/views/bill/influence/ProgressForecast/components/Step2FilterBills.vue
浏览文件 @
8e7d08ff
...
@@ -77,13 +77,12 @@
...
@@ -77,13 +77,12 @@
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
computed
,
onMounted
,
inject
,
watch
}
from
'vue'
import
{
ref
,
computed
,
onMounted
,
inject
,
watch
}
from
'vue'
import
type
{
FilterStats
,
BillInfo
}
from
'../api'
import
type
{
FilterStats
,
BillInfo
}
from
'../api'
import
{
fetchFilterStats
,
fetchBillList
}
from
'../api'
import
{
getSimiBills
,
transformSimiBillsData
}
from
'@/api/bill/billHome'
import
{
getSimiBills
,
transformSimiBillsData
}
from
'@/api/bill/billHome'
import
BillCard
from
'./BillCard.vue'
import
BillCard
from
'./BillCard.vue'
const
emit
=
defineEmits
<
{
const
emit
=
defineEmits
<
{
previous
:
[]
previous
:
[]
next
:
[]
next
:
[
selectedBills
:
any
[]
]
}
>
()
}
>
()
// 从父组件注入筛选参数
// 从父组件注入筛选参数
...
@@ -93,6 +92,8 @@ const filterParams = inject<any>('filterParams', null)
...
@@ -93,6 +92,8 @@ const filterParams = inject<any>('filterParams', null)
const
stats
=
ref
<
FilterStats
|
null
>
(
null
)
const
stats
=
ref
<
FilterStats
|
null
>
(
null
)
// 法案列表
// 法案列表
const
bills
=
ref
<
BillInfo
[]
>
([])
const
bills
=
ref
<
BillInfo
[]
>
([])
// 原始法案数据(用于传给第三页)
const
rawBillsData
=
ref
<
any
[]
>
([])
// 加载状态
// 加载状态
const
loading
=
ref
(
true
)
const
loading
=
ref
(
true
)
...
@@ -121,36 +122,30 @@ const selectedCount = computed(() => {
...
@@ -121,36 +122,30 @@ const selectedCount = computed(() => {
async
function
loadData
()
{
async
function
loadData
()
{
loading
.
value
=
true
loading
.
value
=
true
try
{
try
{
//
优先使用真实 API
//
使用真实 API,传入 billIds、domains、patternType、proposalType
const
params
=
{
const
params
=
{
patternType
:
filterParams
?.
governmentType
||
'统一政府'
,
billIds
:
filterParams
?.
value
.
billIds
,
proposalType
:
'两党共同提案'
domains
:
JSON
.
stringify
(
filterParams
?.
value
.
domains
)
||
[],
patternType
:
filterParams
?.
value
.
patternType
||
'统一政府'
,
proposalType
:
filterParams
?.
value
.
proposalType
||
'两党共同提案'
}
}
const
response
=
await
getSimiBills
(
params
)
const
response
=
await
getSimiBills
(
params
)
if
(
response
&&
response
.
success
&&
response
.
data
)
{
if
(
response
&&
response
.
data
)
{
// 保存原始数据
rawBillsData
.
value
=
response
.
data
const
{
stats
:
apiStats
,
bills
:
apiBills
}
=
transformSimiBillsData
(
response
)
const
{
stats
:
apiStats
,
bills
:
apiBills
}
=
transformSimiBillsData
(
response
)
stats
.
value
=
apiStats
stats
.
value
=
apiStats
bills
.
value
=
apiBills
bills
.
value
=
apiBills
}
else
{
}
else
{
// 如果 API 失败,使用模拟数据
stats
.
value
=
null
const
[
statsData
,
billsData
]
=
await
Promise
.
all
([
bills
.
value
=
[]
fetchFilterStats
(),
fetchBillList
()
])
stats
.
value
=
statsData
bills
.
value
=
billsData
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
'获取相似法案失败:'
,
error
)
console
.
error
(
'获取相似法案失败:'
,
error
)
// 使用模拟数据作为 fallback
stats
.
value
=
null
const
[
statsData
,
billsData
]
=
await
Promise
.
all
([
bills
.
value
=
[]
fetchFilterStats
(),
fetchBillList
()
])
stats
.
value
=
statsData
bills
.
value
=
billsData
}
finally
{
}
finally
{
loading
.
value
=
false
loading
.
value
=
false
}
}
...
@@ -189,7 +184,11 @@ function handleBack() {
...
@@ -189,7 +184,11 @@ function handleBack() {
// 开始预测分析
// 开始预测分析
function
handleStartAnalysis
()
{
function
handleStartAnalysis
()
{
emit
(
'next'
)
// 获取用户勾选的法案ID列表
const
selectedIds
=
bills
.
value
.
filter
(
b
=>
b
.
selected
).
map
(
b
=>
b
.
id
)
// 从原始数据中筛选出用户勾选的法案
const
selectedBills
=
rawBillsData
.
value
.
filter
(
b
=>
selectedIds
.
includes
(
b
.
bill_id
))
emit
(
'next'
,
selectedBills
)
}
}
</
script
>
</
script
>
...
...
src/views/bill/influence/ProgressForecast/components/Step3PredictionAnalysis.vue
浏览文件 @
8e7d08ff
<
template
>
<
template
>
<div
class=
"step-container"
>
<div
class=
"step-container"
>
<div
v-if=
"predictionData"
class=
"content-wrapper"
>
<div
v-if=
"props.loading"
class=
"loading-wrapper flex-display-center"
>
<span
class=
"text-tip-2 text-primary-50-clor"
>
预测分析中...
</span>
</div>
<div
v-else-if=
"predictionData"
class=
"content-wrapper"
>
<div
class=
"header-section flex-display-start"
>
<div
class=
"header-section flex-display-start"
>
<div
class=
"header-left flex-display-start"
>
<div
class=
"header-left flex-display-start"
>
...
@@ -27,8 +30,8 @@
...
@@ -27,8 +30,8 @@
<div
class=
"highlight-box text-regular"
>
<div
class=
"highlight-box text-regular"
>
<div
class=
"highlight-wave text-regular"
></div>
<div
class=
"highlight-wave text-regular"
></div>
<div
class=
"highlight-content text-regular"
>
<div
class=
"highlight-content text-regular"
>
<p
class=
"highlight-title text-regular"
>
《大而美法案》的通过概率非常高
。
</p>
<p
class=
"highlight-title text-regular"
>
该法案的通过概率为
{{
predictionData
?.
overallProbability
||
'—'
}}
。
</p>
<p
class=
"highlight-text text-regular"
>
该法案由众议院共和党领导层在5月正式提出,作为特朗普第二任期核心经济议程,旨在通过一揽子税收、贸易和预算改革提振经济。到6月初,法案已快速通过关键的筹款委员会和预算委员会审议,进入众议院全院辩论阶段。共和党当时控制众议院,且党内团结支持;白宫已明确表示强烈支持。虽然民主党普遍反对,但共和党凭借席位优势足以在众议院通过。主要不确定性在于参议院,但预计部分温和民主党议员可能支持,或通过预算和解程序(只需简单多数)规避阻挠议事。因此,该法案在6月初已势在必行,最终成法几无悬念。
</p>
<p
class=
"highlight-text text-regular"
>
{{
predictionData
?.
highlightText
}}
</p>
</div>
</div>
</div>
</div>
<div
v-if=
"predictionData?.phases?.length"
class=
"phases-list"
>
<div
v-if=
"predictionData?.phases?.length"
class=
"phases-list"
>
...
@@ -59,23 +62,22 @@
...
@@ -59,23 +62,22 @@
</
template
>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
onMounted
,
computed
}
from
'vue'
import
{
ref
,
computed
}
from
'vue'
import
{
fetchPredictionAnalysis
,
type
PredictionAnalysis
}
from
'../api'
import
type
{
PredictionAnalysis
}
from
'../api'
import
PredictionPhaseCard
from
'./PredictionPhaseCard.vue'
import
PredictionPhaseCard
from
'./PredictionPhaseCard.vue'
const
props
=
defineProps
<
{
data
?:
PredictionAnalysis
|
null
loading
?:
boolean
}
>
()
const
emit
=
defineEmits
<
{
const
emit
=
defineEmits
<
{
(
e
:
'prev'
):
void
(
e
:
'prev'
):
void
(
e
:
'repredict'
):
void
(
e
:
'repredict'
):
void
}
>
()
}
>
()
// 预测分析数据
// 预测分析数据 - 从 props 获取,暂无真实接口
const
predictionData
=
ref
<
PredictionAnalysis
|
null
>
(
null
)
const
predictionData
=
computed
(()
=>
props
.
data
||
null
)
// 获取预测分析数据
onMounted
(
async
()
=>
{
const
data
=
await
fetchPredictionAnalysis
()
predictionData
.
value
=
data
})
// 根据索引和progressLevel返回进度条格子的类名
// 根据索引和progressLevel返回进度条格子的类名
function
getOverallSegmentClass
(
index
:
number
)
{
function
getOverallSegmentClass
(
index
:
number
)
{
...
@@ -140,15 +142,16 @@ function handleRepredict() {
...
@@ -140,15 +142,16 @@ function handleRepredict() {
</
script
>
</
script
>
<
style
scoped
>
<
style
scoped
>
/* .text-title-2-bold{
color: #3b414b;
} */
.step-container
{
.step-container
{
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
height
:
100%
;
height
:
100%
;
}
}
.loading-wrapper
{
flex
:
1
;
}
.content-wrapper
{
.content-wrapper
{
flex
:
1
;
flex
:
1
;
overflow
:
auto
;
overflow
:
auto
;
...
@@ -157,7 +160,6 @@ function handleRepredict() {
...
@@ -157,7 +160,6 @@ function handleRepredict() {
.header-section
{
.header-section
{
justify-content
:
space-between
;
justify-content
:
space-between
;
align-items
:
flex-start
;
align-items
:
flex-start
;
/* margin-bottom: 24px; */
}
}
.header-left
{
.header-left
{
...
...
src/views/bill/influence/ProgressForecast/index.vue
浏览文件 @
8e7d08ff
差异被折叠。
点击展开。
src/views/characterPage/components/memberOfCongress/components/characterRelationships/symbol.png
0 → 100644
浏览文件 @
8e7d08ff
3.5 KB
src/views/characterPage/components/memberOfCongress/components/historicalProposal/components/BillCard.vue
浏览文件 @
8e7d08ff
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
<div
class=
"meta-row"
>
<div
class=
"meta-row"
>
<span
class=
"meta-label"
>
相关领域:
</span>
<span
class=
"meta-label"
>
相关领域:
</span>
<div
class=
"meta-tags"
>
<div
class=
"meta-tags"
>
<TagBadge
v-for=
"item in bill.industryList"
:key=
"item.industryName"
:label=
"item.industryName"
tag-class=
"tag3
"
/>
<AreaTag
v-for=
"item in bill.industryList"
:key=
"item.industryName"
:tagName=
"item.industryName
"
/>
</div>
</div>
</div>
</div>
<div
class=
"meta-row"
>
<div
class=
"meta-row"
>
...
@@ -45,7 +45,6 @@
...
@@ -45,7 +45,6 @@
<
script
setup
>
<
script
setup
>
import
{
computed
}
from
'vue'
import
{
computed
}
from
'vue'
import
DocumentPreview
from
'./DocumentPreview.vue'
import
DocumentPreview
from
'./DocumentPreview.vue'
import
TagBadge
from
'./TagBadge.vue'
import
ProgressBar
from
'./ProgressBar.vue'
import
ProgressBar
from
'./ProgressBar.vue'
const
props
=
defineProps
({
const
props
=
defineProps
({
...
@@ -179,23 +178,25 @@ const currentStageIndex = computed(() => {
...
@@ -179,23 +178,25 @@ const currentStageIndex = computed(() => {
.bill-card-meta
{
.bill-card-meta
{
width
:
100%
;
width
:
100%
;
flex
:
1
;
flex
:
1
;
position
:
relative
;
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
min-height
:
0
;
min-height
:
0
;
overflow
:
hidden
;
}
}
.meta-row
{
.meta-row
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
flex-start
;
position
:
absolute
;
left
:
0
;
width
:
100%
;
width
:
100%
;
gap
:
12px
;
}
}
.meta-row
:nth-child
(
1
)
{
top
:
0
;
}
.meta-row
:nth-child
(
1
)
{
}
.meta-row
:nth-child
(
2
)
{
top
:
36px
;
}
.meta-row
:nth-child
(
2
)
{
}
.meta-row
:nth-child
(
3
)
{
top
:
72px
;
}
.meta-row
:nth-child
(
3
)
{
}
.meta-row
:nth-child
(
4
)
{
top
:
108px
;
}
.meta-row
:nth-child
(
4
)
{
}
.meta-row
:nth-child
(
5
)
{
top
:
144px
;
}
.meta-row
:nth-child
(
5
)
{
}
.meta-label
{
.meta-label
{
font-size
:
16px
;
font-size
:
16px
;
...
@@ -206,6 +207,7 @@ const currentStageIndex = computed(() => {
...
@@ -206,6 +207,7 @@ const currentStageIndex = computed(() => {
white-space
:
nowrap
;
white-space
:
nowrap
;
flex-shrink
:
0
;
flex-shrink
:
0
;
width
:
100px
;
width
:
100px
;
padding-top
:
2px
;
}
}
.meta-value
{
.meta-value
{
...
@@ -213,6 +215,8 @@ const currentStageIndex = computed(() => {
...
@@ -213,6 +215,8 @@ const currentStageIndex = computed(() => {
font-weight
:
400
;
font-weight
:
400
;
color
:
rgba
(
95
,
101
,
108
,
1
);
color
:
rgba
(
95
,
101
,
108
,
1
);
line-height
:
24px
;
line-height
:
24px
;
flex
:
1
;
min-width
:
0
;
}
}
.sponsor-name
{
.sponsor-name
{
...
@@ -225,11 +229,11 @@ const currentStageIndex = computed(() => {
...
@@ -225,11 +229,11 @@ const currentStageIndex = computed(() => {
gap
:
8px
;
gap
:
8px
;
flex-wrap
:
wrap
;
flex-wrap
:
wrap
;
align-items
:
center
;
align-items
:
center
;
flex
:
1
;
min-width
:
0
;
}
}
.meta-row-progress
{
.meta-row-progress
{
left
:
0
;
right
:
0
;
width
:
100%
;
width
:
100%
;
}
}
.meta-row-progress
:deep
(
.progress-bar
)
{
.meta-row-progress
:deep
(
.progress-bar
)
{
...
...
src/views/characterPage/components/techLeader/index.vue
浏览文件 @
8e7d08ff
...
@@ -84,7 +84,7 @@
...
@@ -84,7 +84,7 @@
</div>
</div>
</div>
</div>
</div>
</div>
<
div
class=
"line-test"
></div
>
<
!-- <div class="line-test"></div> --
>
</div>
</div>
<div
class=
"pagination"
>
<div
class=
"pagination"
>
<div
class=
"total"
>
{{ `共 ${total} 项` }}
</div>
<div
class=
"total"
>
{{ `共 ${total} 项` }}
</div>
...
@@ -854,9 +854,11 @@ onMounted(() => {
...
@@ -854,9 +854,11 @@ onMounted(() => {
margin-top
:
10px
;
margin-top
:
10px
;
.main-item
{
.main-item
{
width
:
1014px
;
width
:
1014px
;
margin-bottom
:
40px
;
display
:
flex
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
flex-start
;
margin-bottom
:
20px
;
position
:
relative
;
.time
{
.time
{
width
:
77px
;
width
:
77px
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
...
@@ -995,7 +997,16 @@ onMounted(() => {
...
@@ -995,7 +997,16 @@ onMounted(() => {
}
}
}
}
}
}
.
main-item
:
:
after
{
content
:
''
;
position
:
absolute
;
left
:
109px
;
top
:
24px
;
bottom
:
-20px
;
width
:
1px
;
background-color
:
rgb
(
230
,
231
,
232
);
z-index
:
-1
;
}
.line-test
{
.line-test
{
position
:
absolute
;
position
:
absolute
;
top
:
10px
;
top
:
10px
;
...
...
src/views/characterPage/components/thinkTankPerson/index.vue
浏览文件 @
8e7d08ff
...
@@ -69,7 +69,7 @@
...
@@ -69,7 +69,7 @@
</div>
</div>
</div>
</div>
</div>
</div>
<
div
class=
"line-test"
></div
>
<
!-- <div class="line-test"></div> --
>
</div>
</div>
<div
class=
"pagination"
>
<div
class=
"pagination"
>
<div
class=
"total"
>
{{ `共 ${total} 项` }}
</div>
<div
class=
"total"
>
{{ `共 ${total} 项` }}
</div>
...
@@ -606,9 +606,12 @@ const companyList = ref([
...
@@ -606,9 +606,12 @@ const companyList = ref([
.main-item
{
.main-item
{
width
:
100%
;
width
:
100%
;
margin-bottom
:
40px
;
display
:
flex
;
display
:
flex
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
flex-start
;
margin-bottom
:
20px
;
position
:
relative
;
.time
{
.time
{
width
:
77px
;
width
:
77px
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
...
@@ -717,7 +720,16 @@ const companyList = ref([
...
@@ -717,7 +720,16 @@ const companyList = ref([
}
}
}
}
}
}
.
main-item
:
:
after
{
content
:
''
;
position
:
absolute
;
left
:
109px
;
top
:
24px
;
bottom
:
-20px
;
width
:
1px
;
background-color
:
rgb
(
230
,
231
,
232
);
z-index
:
-1
;
}
.line-test
{
.line-test
{
position
:
absolute
;
position
:
absolute
;
top
:
10px
;
top
:
10px
;
...
...
src/views/decree/allOrganization/assets/icons/tips-icon.png
0 → 100644
浏览文件 @
8e7d08ff
1.0 KB
src/views/decree/allOrganization/index.vue
0 → 100644
浏览文件 @
8e7d08ff
<
template
>
<div
class=
"view-box"
>
<div
class=
"container-box"
>
<div
class=
"hard-box"
>
<div
class=
"hard-name text-title-0-show"
>
美国政府机构
</div>
<div
class=
"hard-num text-title-2-show"
>
{{
organizationInfo
.
total
}}
家
</div>
<div
style=
"width: 0px; flex: auto;"
></div>
<div
class=
"hard-input"
>
<el-input
v-model=
"organizationInfo.keyWord"
@
keyup
.
enter=
"onAllOrganization()"
style=
"width:100%; height:100%;"
:suffix-icon=
"Search"
placeholder=
"搜索机构"
/>
</div>
<div
class=
"hard-time"
>
<el-select
v-model=
"organizationInfo.isSort"
@
change=
"onAllOrganization()"
placeholder=
"发布时间"
style=
"width:160px; margin-left:8px;"
>
<template
#
prefix
>
<div
class=
"icon1"
>
<img
v-if=
"isSort"
src=
"@/assets/icons/shengxu1.png"
alt=
""
/>
<img
v-else
src=
"@/assets/icons/jiangxu1.png"
alt=
""
/>
</div>
</
template
>
<el-option
label=
"政令数量"
:value=
"1"
/>
</el-select>
</div>
</div>
<div
class=
"date-box"
>
<div
class=
"date-icon"
>
<img
:src=
"tipsTcon"
alt=
""
>
</div>
<div
class=
"date-text"
>
近期美国各联邦政府机构发布涉华政令数量汇总
</div>
<TimeTabPane
@
time-click=
"handleDateChange"
/>
</div>
<div
class=
"organization-list"
ref=
"refOrganization"
v-loading=
"organizationInfo.loading"
>
<div
class=
"organization-item"
v-for=
"(item, index) in organizationInfo.list"
:key=
"index"
@
click=
"handleToInstitution(item)"
>
<div
class=
"item-left"
>
<img
:src=
"item.imgUrl || DefaultIcon2"
alt=
""
/>
</div>
<div
class=
"item-right one-line-ellipsis"
>
{{ item.orgName }}
</div>
<div
class=
"item-total"
>
{{ item.totalOrderNum }}项
</div>
<el-icon
color=
"var(--color-primary-100)"
><ArrowRightBold
/></el-icon>
<div
class=
"item-dot"
v-if=
"item.recentOrderNum"
>
+{{item.recentOrderNum}}
</div>
</div>
</div>
<div
class=
"pagination-box"
>
<el-pagination
@
current-change=
"onAllOrganization"
:pageSize=
"organizationInfo.pageSize"
:current-page=
"organizationInfo.pageNum"
background
layout=
"prev, pager, next"
:total=
"organizationInfo.total"
/>
</div>
</div>
<div
class=
"back-bnt"
@
click=
"router.back()"
>
<el-icon><Back
/></el-icon>
<div
style=
"margin-left: 6px;"
>
返回
</div>
</div>
</div>
</template>
<
script
setup
name=
"index"
>
import
{
onMounted
,
reactive
,
ref
}
from
"vue"
import
{
Search
}
from
'@element-plus/icons-vue'
import
router
from
"@/router"
;
import
TimeTabPane
from
'@/components/base/TimeTabPane/index.vue'
;
import
{
getAllOrganization
}
from
"@/api/decree/home"
;
import
tipsTcon
from
"./assets/icons/tips-icon.png"
;
import
DefaultIcon2
from
"@/assets/icons/default-icon2.png"
;
const
organizationInfo
=
reactive
({
loading
:
false
,
pageNum
:
1
,
pageSize
:
8
,
total
:
0
,
isSort
:
1
,
keyWord
:
""
,
day
:
7
,
list
:
[]
})
const
onAllOrganization
=
async
(
num
)
=>
{
organizationInfo
.
pageNum
=
num
||
1
organizationInfo
.
loading
=
true
try
{
let
{
keyWord
,
pageNum
,
pageSize
,
day
}
=
organizationInfo
const
res
=
await
getAllOrganization
({
day
,
pageNum
:
pageNum
-
1
,
pageSize
,
keyWord
:
keyWord
||
undefined
});
console
.
log
(
"机构列表"
,
res
);
if
(
res
.
code
===
200
)
{
organizationInfo
.
list
=
res
.
data
.
orgList
||
[];
organizationInfo
.
total
=
res
.
data
.
total
||
0
;
}
}
catch
(
error
)
{
console
.
error
(
"获取机构列表数据失败"
,
error
);
organizationInfo
.
list
=
[];
organizationInfo
.
total
=
0
;
}
organizationInfo
.
loading
=
false
}
const
handleDateChange
=
(
event
)
=>
{
if
(
event
?.
time
===
'近一周'
)
organizationInfo
.
day
=
7
if
(
event
?.
time
===
'近一月'
)
organizationInfo
.
day
=
30
if
(
event
?.
time
===
'近一年'
)
organizationInfo
.
day
=
365
onAllOrganization
()
}
// 跳转行政机构主页
const
handleToInstitution
=
item
=>
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
orgName
);
const
curRoute
=
router
.
resolve
({
path
:
"/institution"
,
query
:
{
id
:
item
.
orgId
}
});
window
.
open
(
curRoute
.
href
,
"_blank"
);
};
const
refOrganization
=
ref
()
onMounted
(()
=>
{
// 根据元素的高度决定分页显示的机构数量
let
height
=
2
;
if
(
refOrganization
.
value
)
{
height
=
Math
.
floor
(
refOrganization
.
value
?.
clientHeight
/
120
)
}
organizationInfo
.
pageSize
=
height
*
4
onAllOrganization
()
})
</
script
>
<
style
scoped
lang=
"scss"
>
.view-box
{
width
:
100%
;
height
:
100%
;
background
:
url("./assets/images/background.png")
,
linear-gradient
(
180deg
,
rgba
(
229
,
241
,
254
,
1
)
0%
,
rgba
(
246
,
251
,
255
,
0
)
30%
);
background-size
:
100%
100%
;
display
:
flex
;
justify-content
:
center
;
position
:
relative
;
.back-bnt
{
position
:
absolute
;
top
:
16px
;
left
:
30px
;
width
:
86px
;
height
:
38px
;
background-color
:
white
;
border-radius
:
19px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
color
:
var
(
--
text-primary-65-color
);
font-family
:
Source
Han
Sans
CN
;
font-size
:
16px
;
cursor
:
pointer
;
}
.container-box
{
width
:
1600px
;
padding
:
50px
0
20px
;
display
:
flex
;
flex-direction
:
column
;
.hard-box
{
display
:
flex
;
align-items
:
center
;
width
:
100%
;
.hard-name
{
color
:
var
(
--
text-primary-90-color
);
height
:
62px
;
line-height
:
62px
!
important
;
}
.hard-num
{
height
:
36px
;
background-color
:
var
(
--
color-primary-100
);
color
:
var
(
--
bg-white-100
);
border-radius
:
18px
;
line-height
:
36px
!
important
;
padding
:
0
16px
;
margin-left
:
16px
;
}
.hard-input
{
background-color
:
var
(
--
el-fill-color-blank
);
border-radius
:
var
(
--
el-border-radius-base
);
box-shadow
:
0
0
0
1px
var
(
--
el-border-color
)
inset
;
box-sizing
:
border-box
;
margin-left
:
20px
;
width
:
160px
;
height
:
32px
;
}
.hard-time
{
height
:
42px
;
padding
:
5px
0
;
.icon1
{
width
:
11px
;
height
:
14px
;
font-size
:
0px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
.date-box
{
margin-top
:
6px
;
display
:
flex
;
align-items
:
center
;
width
:
100%
;
.date-icon
{
width
:
16px
;
height
:
16px
;
font-size
:
0px
;
margin-right
:
6px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.date-text
{
width
:
20px
;
flex
:
auto
;
font-size
:
18px
;
line-height
:
18px
;
font-family
:
Source
Han
Sans
CN
;
color
:
var
(
--
text-primary-80-color
);
}
}
.organization-list
{
width
:
100%
;
height
:
20px
;
padding
:
16px
0
;
margin-top
:
10px
;
flex
:
auto
;
display
:
grid
;
grid-template-columns
:
repeat
(
4
,
1fr
);
grid-auto-rows
:
104px
;
gap
:
16px
;
font-family
:
Microsoft
YaHei
;
.organization-item
{
padding
:
0
16px
;
display
:
flex
;
box-sizing
:
border-box
;
background
:
rgba
(
255
,
255
,
255
,
0
.65
);
border
:
1px
solid
rgba
(
255
,
255
,
255
,
1
);
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
transition
:
transform
0
.3s
ease
,
box-shadow
0
.3s
ease
;
position
:
relative
;
&
:hover
{
transform
:
translateY
(
-3px
);
box-shadow
:
0
4px
16px
rgba
(
0
,
0
,
0
,
0
.15
);
}
.item-left
{
width
:
48px
;
height
:
48px
;
font-size
:
0px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.item-right
{
width
:
20px
;
flex
:
auto
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-size
:
20px
;
font-weight
:
700
;
line-height
:
20px
;
margin
:
0
16px
;
}
.item-total
{
font-size
:
20px
;
margin-right
:
2px
;
white-space
:
nowrap
;
font-weight
:
700
;
line-height
:
20px
;
color
:
var
(
--
color-primary-100
);
}
.item-more
{
font-size
:
16px
;
margin-right
:
12px
;
white-space
:
nowrap
;
font-weight
:
700
;
line-height
:
16px
;
color
:
var
(
--
color-primary-100
);
}
.item-dot
{
position
:
absolute
;
right
:
-13px
;
top
:
-10px
;
padding
:
0
8px
;
height
:
26px
;
background-color
:
#FF4D4F
;
color
:
white
;
font-size
:
16px
;
line-height
:
26px
;
font-family
:
Source
Han
Sans
CN
;
border-radius
:
14px
;
letter-spacing
:
1px
;
}
}
}
.pagination-box
{
display
:
flex
;
justify-content
:
center
;
}
}
}
</
style
>
\ No newline at end of file
src/views/decree/com/MindGraph.vue
0 → 100644
浏览文件 @
8e7d08ff
<
template
>
<div
class=
"view-box"
>
<div
ref=
"graphContainer"
style=
"height: 100%; width: 100%;"
></div>
</div>
</
template
>
<
script
setup
name=
"MindGraph"
>
import
{
ref
,
onBeforeUnmount
}
from
"vue"
import
*
as
G6
from
'@antv/g6'
;
// 初始化画布
const
graphContainer
=
ref
(
null
);
let
graph
=
null
;
const
onInitGraph
=
()
=>
{
const
container
=
graphContainer
.
value
;
const
width
=
container
.
clientWidth
;
const
height
=
container
.
clientHeight
;
graph
=
new
G6
.
Graph
({
container
:
container
,
width
,
height
,
// fitView: true,
// fitViewPadding: 50,
defaultNode
:
{
type
:
"rect"
,
size
:
[
250
,
45
],
style
:
{
fill
:
"#F6FAFF"
,
stroke
:
"#B9DCFF"
,
lineWidth
:
1
},
labelCfg
:
{
style
:
{
fill
:
"#055FC2"
,
fontSize
:
18
,
lineHeight
:
25
,
fontWeight
:
"bold"
,
fontFamily
:
"Source Han Sans CN"
,
}
}
},
defaultEdge
:
{
type
:
"cubic-horizontal"
,
style
:
{
stroke
:
"#B9DCFF"
,
lineWidth
:
2
,
endArrow
:
true
,
}
},
layout
:
{
type
:
'dagre'
,
// 层次布局
rankdir
:
'LR'
,
// 布局从左向右
controlPoints
:
true
,
// 节点间连线的控制点
nodesep
:
10
,
// 同一层节点之间的距离
ranksep
:
50
,
// 不同层节点之间的距离
},
modes
:
{
default
:
[
'drag-canvas'
,
// 鼠标拖拽移动画布
'zoom-canvas'
,
// 鼠标滚轮缩放
// 'drag-node' // 可选:允许拖拽节点
]
},
});
}
// 加载思维导图数据
const
onMindGraphData
=
(
nodes
=
[],
edges
=
[])
=>
{
let
data
=
{
nodes
:[],
edges
}
nodes
.
forEach
(
node
=>
{
if
(
node
.
maxWidth
)
onFormatLineFeed
(
node
);
data
.
nodes
.
push
(
node
);
})
if
(
!
graph
)
onInitGraph
();
graph
.
data
(
data
);
graph
.
render
();
}
// 获取文本宽度
const
canvas
=
document
.
createElement
(
'canvas'
);
const
ctx
=
canvas
.
getContext
(
'2d'
);
const
getLabelWidth
=
(
label
,
size
,
family
)
=>
{
ctx
.
font
=
`
${
size
}
px
${
family
}
`
;
return
ctx
.
measureText
(
label
).
width
;
}
// 文本插入换行符
const
onFormatLineFeed
=
(
node
)
=>
{
let
size
=
node
?.
labelCfg
?.
style
?.
fontSize
||
'16'
let
family
=
node
?.
labelCfg
?.
style
?.
fontFamily
||
'Source Han Sans CN'
const
lines
=
[];
let
line
=
''
;
for
(
let
char
of
node
.
label
)
{
const
testLine
=
line
+
char
;
const
width
=
getLabelWidth
(
testLine
,
size
,
family
);
if
(
width
>
node
.
maxWidth
-
40
)
{
lines
.
push
(
line
);
line
=
char
;
}
else
{
line
=
testLine
;
}
}
if
(
line
)
lines
.
push
(
line
);
node
.
label
=
lines
.
join
(
"
\
n"
)
node
.
size
=
[
node
.
maxWidth
,
25
*
lines
.
length
+
20
]
}
defineExpose
({
onMindGraphData
})
onBeforeUnmount
(()
=>
{
graph
?.
destroy
()
})
</
script
>
<
style
scoped
lang=
"scss"
>
.view-box
{
width
:
100%
;
height
:
100%
;
}
</
style
>
\ No newline at end of file
src/views/decree/decreeHome/index.vue
浏览文件 @
8e7d08ff
...
@@ -29,24 +29,24 @@
...
@@ -29,24 +29,24 @@
<div
class=
"item-footer"
>
分析报告
</div>
<div
class=
"item-footer"
>
分析报告
</div>
</div>
</div>
</div>
-->
</div>
-->
<div
class=
"date-box"
v-if=
"
govIns
List.length"
>
<div
class=
"date-box"
v-if=
"
keyOrganization
List.length"
>
<div
class=
"date-icon"
>
<div
class=
"date-icon"
>
<img
:src=
"tipsTcon"
alt=
""
>
<img
:src=
"tipsTcon"
alt=
""
>
</div>
</div>
<div
class=
"date-text"
>
近期美国各联邦政府机构发布涉华政令数量汇总
</div>
<div
class=
"date-text"
>
近期美国各联邦政府机构发布涉华政令数量汇总
</div>
<TimeTabPane
@
time-click=
"
handleGetDepartmentList
"
/>
<TimeTabPane
@
time-click=
"
onKeyOrganization
"
/>
</div>
</div>
<div
class=
"home-main-header-item-box"
v-if=
"
govIns
List.length"
>
<div
class=
"home-main-header-item-box"
v-if=
"
keyOrganization
List.length"
>
<div
class=
"organization-item"
v-for=
"(item, index) in
govInsList.slice(0, 7)
"
:key=
"index"
@
click=
"handleToInstitution(item)"
>
<div
class=
"organization-item"
v-for=
"(item, index) in
keyOrganizationList
"
:key=
"index"
@
click=
"handleToInstitution(item)"
>
<div
class=
"item-left"
>
<div
class=
"item-left"
>
<img
:src=
"item.
orgImage
|| DefaultIcon2"
alt=
""
/>
<img
:src=
"item.
imgUrl
|| DefaultIcon2"
alt=
""
/>
</div>
</div>
<div
class=
"item-right one-line-ellipsis"
>
{{
item
.
orgName
}}
</div>
<div
class=
"item-right one-line-ellipsis"
>
{{
item
.
orgName
}}
</div>
<div
class=
"item-total"
>
{{
item
.
total
}}
项
</div>
<div
class=
"item-total"
>
{{
item
.
total
OrderNum
}}
项
</div>
<el-icon
color=
"var(--color-primary-100)"
><ArrowRightBold
/></el-icon>
<el-icon
color=
"var(--color-primary-100)"
><ArrowRightBold
/></el-icon>
<div
class=
"item-dot"
v-if=
"item.
totalRecent"
>
+
{{
item
.
totalRecent
}}
</div>
<div
class=
"item-dot"
v-if=
"item.
recentOrderNum"
>
+
{{
item
.
recentOrderNum
}}
</div>
</div>
</div>
<div
class=
"organization-item"
>
<div
class=
"organization-item"
@
click=
"onNavigateTo()"
>
<div
class=
"item-more"
>
查看全部机构 (
{{
govInsList
.
length
+
1
}}
家)
</div>
<div
class=
"item-more"
>
查看全部机构 (
{{
govInsList
.
length
+
1
}}
家)
</div>
<el-icon
color=
"var(--color-primary-100)"
><ArrowRightBold
/></el-icon>
<el-icon
color=
"var(--color-primary-100)"
><ArrowRightBold
/></el-icon>
</div>
</div>
...
@@ -164,7 +164,6 @@
...
@@ -164,7 +164,6 @@
<DivideHeader
id=
"position2"
class=
"divide2"
:titleText=
"'资讯要闻'"
></DivideHeader>
<DivideHeader
id=
"position2"
class=
"divide2"
:titleText=
"'资讯要闻'"
></DivideHeader>
<div
class=
"center-center"
>
<div
class=
"center-center"
>
<NewsList
:newsList=
"newsList"
@
item-click=
"handleToNewsAnalysis"
@
more-click=
"handleToMoreNews"
/>
<NewsList
:newsList=
"newsList"
@
item-click=
"handleToNewsAnalysis"
@
more-click=
"handleToMoreNews"
/>
<!--
<NewsList
:newsList=
"newsList"
/>
-->
<MessageBubble
:messageList=
"messageList"
@
person-click=
"handleClickPerson"
@
info-click=
"handleGetMessage"
<MessageBubble
:messageList=
"messageList"
@
person-click=
"handleClickPerson"
@
info-click=
"handleGetMessage"
imageUrl=
"img"
@
more-click=
"handleToSocialDetail"
/>
imageUrl=
"img"
@
more-click=
"handleToSocialDetail"
/>
</div>
</div>
...
@@ -194,7 +193,7 @@
...
@@ -194,7 +193,7 @@
</el-select>
</el-select>
</div>
</div>
</div>
</div>
<div
class=
"box5-main"
>
<div
class=
"box5-main"
v-loading=
"box5Params.loading"
>
<div
class=
"box5-chart"
id=
"chart1"
></div>
<div
class=
"box5-chart"
id=
"chart1"
></div>
</div>
</div>
<div
class=
"data-origin-box"
>
<div
class=
"data-origin-box"
>
...
@@ -227,7 +226,7 @@
...
@@ -227,7 +226,7 @@
</el-select>
</el-select>
</div>
</div>
</div>
</div>
<div
class=
"box5-main"
>
<div
class=
"box5-main"
v-loading=
"box6Params.loading"
>
<div
class=
"box5-chart"
id=
"chart2"
></div>
<div
class=
"box5-chart"
id=
"chart2"
></div>
</div>
</div>
<div
class=
"data-origin-box"
>
<div
class=
"data-origin-box"
>
...
@@ -267,7 +266,7 @@
...
@@ -267,7 +266,7 @@
</el-select>
</el-select>
</div>
</div>
</div>
</div>
<div
class=
"box7-main"
>
<div
class=
"box7-main"
v-loading=
"box7Params.loading"
>
<div
class=
"box7-list"
>
<div
class=
"box7-list"
>
<div
class=
"box7-item"
v-for=
"(item, index) in keyDecreeList"
:key=
"index"
@
click=
"handleKeyDecree(item)"
>
<div
class=
"box7-item"
v-for=
"(item, index) in keyDecreeList"
:key=
"index"
@
click=
"handleKeyDecree(item)"
>
<div
class=
"icon"
>
<div
class=
"icon"
>
...
@@ -315,7 +314,7 @@
...
@@ -315,7 +314,7 @@
</el-select>
</el-select>
</div>
</div>
</div>
</div>
<div
class=
"box8-content"
>
<div
class=
"box8-content"
v-loading=
"box8Params.loading"
>
<WordCloudChart
v-if=
"wordCloudData?.length"
:data=
"wordCloudData"
width=
"100%"
height=
"100%"
/>
<WordCloudChart
v-if=
"wordCloudData?.length"
:data=
"wordCloudData"
width=
"100%"
height=
"100%"
/>
</div>
</div>
<div
class=
"data-origin-box"
>
<div
class=
"data-origin-box"
>
...
@@ -485,6 +484,8 @@ import DefaultIcon2 from "@/assets/icons/default-icon2.png";
...
@@ -485,6 +484,8 @@ import DefaultIcon2 from "@/assets/icons/default-icon2.png";
import
tipsTcon
from
"./assets/images/tips-icon.png"
;
import
tipsTcon
from
"./assets/images/tips-icon.png"
;
import
{
ElMessage
}
from
"element-plus"
;
import
{
ElMessage
}
from
"element-plus"
;
import
{
useGotoNewsDetail
}
from
'@/router/modules/news'
;
const
containerRef
=
ref
(
null
);
const
containerRef
=
ref
(
null
);
const
{
isShow
}
=
useContainerScroll
(
containerRef
);
const
{
isShow
}
=
useContainerScroll
(
containerRef
);
const
currentPage
=
ref
(
1
);
const
currentPage
=
ref
(
1
);
...
@@ -499,14 +500,9 @@ const handleCurrentChange = page => {
...
@@ -499,14 +500,9 @@ const handleCurrentChange = page => {
// 机构列表
// 机构列表
const
govInsList
=
ref
([]);
const
govInsList
=
ref
([]);
const
checkedGovIns
=
ref
([]);
const
checkedGovIns
=
ref
([]);
const
handleGetDepartmentList
=
async
(
event
)
=>
{
const
handleGetDepartmentList
=
async
()
=>
{
let
day
=
7
if
(
event
?.
time
===
'近一周'
)
day
=
7
if
(
event
?.
time
===
'近一月'
)
day
=
30
if
(
event
?.
time
===
'近一年'
)
day
=
365
try
{
try
{
const
res
=
await
getDepartmentList
({
day
});
const
res
=
await
getDepartmentList
({
day
:
7
});
console
.
log
(
"机构列表"
,
res
);
console
.
log
(
"机构列表"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
govInsList
.
value
=
res
.
data
;
govInsList
.
value
=
res
.
data
;
...
@@ -526,6 +522,10 @@ const handleToInstitution = item => {
...
@@ -526,6 +522,10 @@ const handleToInstitution = item => {
});
});
window
.
open
(
curRoute
.
href
,
"_blank"
);
window
.
open
(
curRoute
.
href
,
"_blank"
);
};
};
// 跳转全部机构页面
const
onNavigateTo
=
()
=>
{
router
.
push
({
name
:
"allOrganization"
});
}
// 查看更多风险信号
// 查看更多风险信号
const
handleToMoreRiskSignal
=
()
=>
{
const
handleToMoreRiskSignal
=
()
=>
{
...
@@ -657,7 +657,6 @@ const handleGetNews = async () => {
...
@@ -657,7 +657,6 @@ const handleGetNews = async () => {
const
res
=
await
getNews
({
moduleId
:
"0101"
});
const
res
=
await
getNews
({
moduleId
:
"0101"
});
console
.
log
(
"新闻资讯"
,
res
);
console
.
log
(
"新闻资讯"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
// newsList.value = res.data || []
newsList
.
value
=
(
res
.
data
??
[]).
map
(
item
=>
{
newsList
.
value
=
(
res
.
data
??
[]).
map
(
item
=>
{
return
{
return
{
newsId
:
item
.
newsId
,
newsId
:
item
.
newsId
,
...
@@ -673,14 +672,9 @@ const handleGetNews = async () => {
...
@@ -673,14 +672,9 @@ const handleGetNews = async () => {
}
}
};
};
// 点击新闻条目,跳转到新闻分析页
// 点击新闻条目,跳转到新闻分析页
const
gotoNewsDetail
=
useGotoNewsDetail
()
const
handleToNewsAnalysis
=
news
=>
{
const
handleToNewsAnalysis
=
news
=>
{
const
route
=
router
.
resolve
({
gotoNewsDetail
(
news
.
newsId
)
path
:
"/newsAnalysis"
,
query
:
{
newsId
:
news
.
newsId
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
};
// 社交媒体
// 社交媒体
...
@@ -799,9 +793,11 @@ const box5Params = reactive({
...
@@ -799,9 +793,11 @@ const box5Params = reactive({
year
:
yearList
[
0
].
value
,
year
:
yearList
[
0
].
value
,
domainId
:
''
,
domainId
:
''
,
proposeName
:
''
,
proposeName
:
''
,
loading
:
false
,
})
})
const
summarize1
=
ref
()
const
summarize1
=
ref
()
const
handleGetDecreeYearOrder
=
async
()
=>
{
const
handleGetDecreeYearOrder
=
async
()
=>
{
box5Params
.
loading
=
true
try
{
try
{
let
{
year
,
domainId
,
proposeName
}
=
box5Params
;
let
{
year
,
domainId
,
proposeName
}
=
box5Params
;
const
res
=
await
getDecreeYearOrder
({
const
res
=
await
getDecreeYearOrder
({
...
@@ -822,6 +818,7 @@ const handleGetDecreeYearOrder = async () => {
...
@@ -822,6 +818,7 @@ const handleGetDecreeYearOrder = async () => {
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"行政令发布频度error"
,
error
);
console
.
error
(
"行政令发布频度error"
,
error
);
}
}
box5Params
.
loading
=
false
};
};
// AI智能总结
// AI智能总结
const
onChartInterpretation
=
async
(
text
)
=>
{
const
onChartInterpretation
=
async
(
text
)
=>
{
...
@@ -882,9 +879,11 @@ const chart2Data = ref([
...
@@ -882,9 +879,11 @@ const chart2Data = ref([
const
box6Params
=
reactive
({
const
box6Params
=
reactive
({
year
:
yearList
[
0
].
value
,
year
:
yearList
[
0
].
value
,
proposeName
:
''
,
proposeName
:
''
,
loading
:
false
,
});
});
const
summarize2
=
ref
()
const
summarize2
=
ref
()
const
handleGetDecreeArea
=
async
()
=>
{
const
handleGetDecreeArea
=
async
()
=>
{
box6Params
.
loading
=
true
try
{
try
{
let
{
year
,
proposeName
}
=
box6Params
;
let
{
year
,
proposeName
}
=
box6Params
;
const
res
=
await
getDecreeArea
({
const
res
=
await
getDecreeArea
({
...
@@ -904,6 +903,7 @@ const handleGetDecreeArea = async () => {
...
@@ -904,6 +903,7 @@ const handleGetDecreeArea = async () => {
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"政令科技领域error"
,
error
);
console
.
error
(
"政令科技领域error"
,
error
);
}
}
box6Params
.
loading
=
false
};
};
const
handleBox6
=
async
()
=>
{
const
handleBox6
=
async
()
=>
{
await
handleGetDecreeArea
();
await
handleGetDecreeArea
();
...
@@ -926,8 +926,10 @@ const box7Params = reactive({
...
@@ -926,8 +926,10 @@ const box7Params = reactive({
year
:
yearList
[
0
].
value
,
year
:
yearList
[
0
].
value
,
domainId
:
''
,
domainId
:
''
,
proposeName
:
''
,
proposeName
:
''
,
loading
:
false
,
})
})
const
handleGetKeyDecree
=
async
()
=>
{
const
handleGetKeyDecree
=
async
()
=>
{
box7Params
.
loading
=
true
try
{
try
{
let
{
year
,
domainId
,
proposeName
}
=
box7Params
;
let
{
year
,
domainId
,
proposeName
}
=
box7Params
;
const
res
=
await
getKeyDecree
({
const
res
=
await
getKeyDecree
({
...
@@ -950,6 +952,7 @@ const handleGetKeyDecree = async () => {
...
@@ -950,6 +952,7 @@ const handleGetKeyDecree = async () => {
});
});
}
}
}
catch
(
error
)
{
}
}
catch
(
error
)
{
}
box7Params
.
loading
=
false
};
};
// 政令重点条款
// 政令重点条款
...
@@ -958,8 +961,10 @@ const box8Params = reactive({
...
@@ -958,8 +961,10 @@ const box8Params = reactive({
year
:
yearList
[
0
].
value
,
year
:
yearList
[
0
].
value
,
domainId
:
''
,
domainId
:
''
,
proposeName
:
''
,
proposeName
:
''
,
loading
:
false
,
})
})
const
handleGetDecreeKeyInstruction
=
async
()
=>
{
const
handleGetDecreeKeyInstruction
=
async
()
=>
{
box8Params
.
loading
=
true
try
{
try
{
let
{
year
,
domainId
,
proposeName
}
=
box8Params
;
let
{
year
,
domainId
,
proposeName
}
=
box8Params
;
const
res
=
await
getDecreeKeyInstruction
({
const
res
=
await
getDecreeKeyInstruction
({
...
@@ -972,6 +977,7 @@ const handleGetDecreeKeyInstruction = async () => {
...
@@ -972,6 +977,7 @@ const handleGetDecreeKeyInstruction = async () => {
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"政令重点条款error"
,
error
);
console
.
error
(
"政令重点条款error"
,
error
);
}
}
box8Params
.
loading
=
false
};
};
// 资源库
// 资源库
...
@@ -1197,12 +1203,16 @@ const handleSearch = () => {
...
@@ -1197,12 +1203,16 @@ const handleSearch = () => {
// 关键机构
// 关键机构
const
keyOrganizationList
=
ref
([]);
const
keyOrganizationList
=
ref
([]);
const
onKeyOrganization
=
async
()
=>
{
const
onKeyOrganization
=
async
(
event
)
=>
{
let
day
=
7
if
(
event
?.
time
===
'近一周'
)
day
=
7
if
(
event
?.
time
===
'近一月'
)
day
=
30
if
(
event
?.
time
===
'近一年'
)
day
=
365
try
{
try
{
const
res
=
await
getKeyOrganization
();
const
res
=
await
getKeyOrganization
(
{
day
}
);
console
.
log
(
"关键机构"
,
res
);
console
.
log
(
"关键机构"
,
res
);
if
(
res
.
code
===
200
)
{
if
(
res
.
code
===
200
)
{
keyOrganizationList
.
value
=
res
.
data
.
map
(
item
=>
({
orgName
:
item
.
orgName
,
orgId
:
item
.
id
}))
;
keyOrganizationList
.
value
=
res
.
data
;
}
}
}
catch
(
error
)
{
}
}
catch
(
error
)
{
}
}
}
...
@@ -1423,15 +1433,13 @@ onMounted(async () => {
...
@@ -1423,15 +1433,13 @@ onMounted(async () => {
.home-main-header-item-box
{
.home-main-header-item-box
{
margin
:
20px
0
64px
;
margin
:
20px
0
64px
;
width
:
1600px
;
width
:
1600px
;
display
:
flex
;
display
:
grid
;
flex-wrap
:
wrap
;
grid-template-columns
:
repeat
(
4
,
1fr
);
grid-auto-rows
:
80px
;
gap
:
16px
;
gap
:
16px
;
font-family
:
Microsoft
YaHei
;
font-family
:
Microsoft
YaHei
;
.organization-item
{
.organization-item
{
width
:
20%
;
flex
:
auto
;
height
:
80px
;
padding
:
0
16px
;
padding
:
0
16px
;
display
:
flex
;
display
:
flex
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
...
@@ -2194,6 +2202,7 @@ onMounted(async () => {
...
@@ -2194,6 +2202,7 @@ onMounted(async () => {
.box5-main
{
.box5-main
{
flex
:
auto
;
flex
:
auto
;
height
:
20px
;
height
:
20px
;
padding-top
:
16px
;
.box5-chart
{
.box5-chart
{
height
:
100%
;
height
:
100%
;
}
}
...
...
src/views/decree/decreeLayout/deepdig/index.vue
浏览文件 @
8e7d08ff
...
@@ -170,7 +170,6 @@ const onWordWrap = (word, num) => {
...
@@ -170,7 +170,6 @@ const onWordWrap = (word, num) => {
}
}
const
handleClickDecree
=
decree
=>
{
const
handleClickDecree
=
decree
=>
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
decree
.
name
);
const
route
=
router
.
resolve
({
const
route
=
router
.
resolve
({
path
:
"/decreeLayout"
,
path
:
"/decreeLayout"
,
query
:
{
query
:
{
...
...
src/views/decree/decreeLayout/influence/index.vue
浏览文件 @
8e7d08ff
...
@@ -75,7 +75,7 @@
...
@@ -75,7 +75,7 @@
<
/div
>
<
/div
>
<
/template
>
<
/template
>
<
div
class
=
"box2-main"
>
<
div
class
=
"box2-main"
>
<
AiTips
:
tips
=
"tips"
/
>
<
!--
<
AiTips
:
tips
=
"tips"
/>
--
>
<
div
class
=
"graph-box"
v
-
if
=
"contentType==1"
>
<
div
class
=
"graph-box"
v
-
if
=
"contentType==1"
>
<
ChartChain
:
listData
=
"fishbone.list"
:
baseData
=
"fishbone.base"
/>
<
ChartChain
:
listData
=
"fishbone.list"
:
baseData
=
"fishbone.base"
/>
<
/div
>
<
/div
>
...
...
src/views/decree/decreeLayout/overview/background/index.vue
浏览文件 @
8e7d08ff
...
@@ -46,7 +46,7 @@
...
@@ -46,7 +46,7 @@
<div
class=
"custom-collapse-title"
>
<div
class=
"custom-collapse-title"
>
<div
class=
"custom-collapse-index"
>
{{
index
+
1
}}
</div>
<div
class=
"custom-collapse-index"
>
{{
index
+
1
}}
</div>
<div
class=
"custom-collapse-name one-line-ellipsis"
>
<div
class=
"custom-collapse-name one-line-ellipsis"
>
<span
class=
"text-click-hover"
@
click
.
stop=
"handleClick
Decree
(item)"
>
{{
item
.
title
}}
</span>
<span
class=
"text-click-hover"
@
click
.
stop=
"handleClick
Bull
(item)"
>
{{
item
.
title
}}
</span>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
...
@@ -73,9 +73,9 @@
...
@@ -73,9 +73,9 @@
<div
class=
"time-line-icon"
>
<div
class=
"time-line-icon"
>
<img
style=
"width: 100%; height: 100%;"
:src=
"item.orgImage || DefaultIcon1"
alt=
""
>
<img
style=
"width: 100%; height: 100%;"
:src=
"item.orgImage || DefaultIcon1"
alt=
""
>
</div>
</div>
<div
class=
"time-line-name"
@
click=
"handleToInstitution(item)"
>
{{ item.proposeOrgName }}
</div>
<div
class=
"time-line-name
text-click-hover
"
@
click=
"handleToInstitution(item)"
>
{{ item.proposeOrgName }}
</div>
</div>
</div>
<div
class=
"timeline-content"
>
{{ item.describe }}
</div>
<div
class=
"timeline-content"
@
click=
"handleClickDecree(item)"
>
{{ item.describe }}
</div>
</div>
</div>
</el-timeline-item>
</el-timeline-item>
</el-timeline>
</el-timeline>
...
@@ -167,15 +167,24 @@ const handleGetPrev = async () => {
...
@@ -167,15 +167,24 @@ const handleGetPrev = async () => {
};
};
// 跳转行政机构主页
// 跳转行政机构主页
const
handleToInstitution
=
item
=>
{
const
handleToInstitution
=
item
=>
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
proposeOrgName
);
const
curRoute
=
router
.
resolve
({
const
curRoute
=
router
.
resolve
({
path
:
"/institution"
,
path
:
"/institution"
,
query
:
{
query
:
{
id
:
item
.
i
d
id
:
item
.
orgI
d
}
}
});
});
window
.
open
(
curRoute
.
href
,
"_blank"
);
window
.
open
(
curRoute
.
href
,
"_blank"
);
};
};
// 跳转科技政令详情页
const
handleClickDecree
=
item
=>
{
const
route
=
router
.
resolve
({
path
:
"/decreeLayout"
,
query
:
{
id
:
item
.
id
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 法律依据
// 法律依据
const
dependList
=
ref
([]);
const
dependList
=
ref
([]);
...
@@ -186,7 +195,7 @@ const handleGetLaws = async () => {
...
@@ -186,7 +195,7 @@ const handleGetLaws = async () => {
console
.
log
(
"法律依据"
,
res
);
console
.
log
(
"法律依据"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
dependList
.
value
=
res
.
data
;
dependList
.
value
=
res
.
data
;
dependActive
.
value
=
res
.
data
.
map
(
item
=>
item
.
billId
);
//
dependActive.value = res.data.map(item => item.billId);
}
else
{
}
else
{
dependList
.
value
=
[];
dependList
.
value
=
[];
}
}
...
@@ -196,7 +205,7 @@ const handleGetLaws = async () => {
...
@@ -196,7 +205,7 @@ const handleGetLaws = async () => {
}
}
};
};
// 跳转科技法案详情页
// 跳转科技法案详情页
const
handleClick
Decree
=
decree
=>
{
const
handleClick
Bull
=
decree
=>
{
window
.
sessionStorage
.
setItem
(
"billId"
,
decree
.
billId
);
window
.
sessionStorage
.
setItem
(
"billId"
,
decree
.
billId
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
decree
.
title
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
decree
.
title
);
const
route
=
router
.
resolve
({
const
route
=
router
.
resolve
({
...
@@ -414,7 +423,6 @@ onMounted(() => {
...
@@ -414,7 +423,6 @@ onMounted(() => {
.time-line-name
{
.time-line-name
{
color
:
rgba
(
59
,
65
,
75
,
1
);
color
:
rgba
(
59
,
65
,
75
,
1
);
font-size
:
15px
;
font-size
:
15px
;
cursor
:
pointer
;
}
}
}
}
...
@@ -445,6 +453,7 @@ onMounted(() => {
...
@@ -445,6 +453,7 @@ onMounted(() => {
font-size
:
16px
;
font-size
:
16px
;
font-weight
:
400
;
font-weight
:
400
;
line-height
:
26px
;
line-height
:
26px
;
cursor
:
pointer
;
}
}
}
}
}
}
...
...
src/views/decree/decreeLayout/overview/introduction/index.vue
浏览文件 @
8e7d08ff
...
@@ -83,7 +83,7 @@
...
@@ -83,7 +83,7 @@
<img
:src=
"item.imageUrl || DefaultIconNews"
alt=
""
/>
<img
:src=
"item.imageUrl || DefaultIconNews"
alt=
""
/>
</div>
</div>
<div
class=
"item-center"
>
<div
class=
"item-center"
>
<div
class=
"bubble-header"
@
click=
"
handleClickToNewsDetail(item
)"
>
<div
class=
"bubble-header"
@
click=
"
gotoNewsDetail(item.id
)"
>
<span
class=
"name"
>
{{ item.sjbt }}
</span>
<span
class=
"name"
>
{{ item.sjbt }}
</span>
<span
class=
"meta"
>
{{ item.sjsj }} · {{ item.source }}
</span>
<span
class=
"meta"
>
{{ item.sjsj }} · {{ item.source }}
</span>
</div>
</div>
...
@@ -177,6 +177,9 @@ import DefaultIcon1 from "@/assets/icons/default-icon1.png";
...
@@ -177,6 +177,9 @@ import DefaultIcon1 from "@/assets/icons/default-icon1.png";
import
DefaultIcon2
from
"@/assets/icons/default-icon2.png"
;
import
DefaultIcon2
from
"@/assets/icons/default-icon2.png"
;
import
DefaultIconNews
from
"@/assets/icons/default-icon-news.png"
;
import
DefaultIconNews
from
"@/assets/icons/default-icon-news.png"
;
import
{
useGotoNewsDetail
}
from
'@/router/modules/news'
;
const
gotoNewsDetail
=
useGotoNewsDetail
()
const
route
=
useRoute
();
const
route
=
useRoute
();
const
decreeId
=
ref
(
route
.
query
.
id
);
const
decreeId
=
ref
(
route
.
query
.
id
);
...
@@ -235,7 +238,7 @@ handleGetBasicInfo();
...
@@ -235,7 +238,7 @@ handleGetBasicInfo();
const
wordCloudData
=
ref
([])
const
wordCloudData
=
ref
([])
const
onKeyWordUp
=
async
()
=>
{
const
onKeyWordUp
=
async
()
=>
{
try
{
try
{
const
res
=
await
getKeyWordUp
();
const
res
=
await
getKeyWordUp
(
{
id
:
decreeId
.
value
}
);
console
.
log
(
"政令关键词云"
,
res
);
console
.
log
(
"政令关键词云"
,
res
);
wordCloudData
.
value
=
res
.
data
.
slice
(
0
,
10
).
map
(
item
=>
({
name
:
item
.
name
,
value
:
item
.
count
}));
wordCloudData
.
value
=
res
.
data
.
slice
(
0
,
10
).
map
(
item
=>
({
name
:
item
.
name
,
value
:
item
.
count
}));
}
catch
(
error
)
{
}
catch
(
error
)
{
...
@@ -271,15 +274,6 @@ const handleGetRelateEvents = async () => {
...
@@ -271,15 +274,6 @@ const handleGetRelateEvents = async () => {
console
.
error
(
"获取相关事件数据失败"
,
error
);
console
.
error
(
"获取相关事件数据失败"
,
error
);
}
}
};
};
const
handleClickToNewsDetail
=
news
=>
{
const
route
=
router
.
resolve
({
path
:
"/newsAnalysis"
,
query
:
{
newsId
:
news
.
id
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 发布机构
// 发布机构
const
box3TopTopData
=
ref
({
const
box3TopTopData
=
ref
({
...
@@ -476,7 +470,6 @@ onMounted(() => {
...
@@ -476,7 +470,6 @@ onMounted(() => {
font-weight
:
400
;
font-weight
:
400
;
font-size
:
16px
;
font-size
:
16px
;
line-height
:
30px
;
line-height
:
30px
;
min-height
:
300px
;
}
}
}
}
...
...
src/views/decree/decreeLayout/overview/measures/assets/images/edit-line.png
0 → 100644
浏览文件 @
8e7d08ff
270 Bytes
src/views/decree/decreeLayout/overview/measures/index.vue
浏览文件 @
8e7d08ff
...
@@ -3,6 +3,14 @@
...
@@ -3,6 +3,14 @@
<div
class=
"page-left"
>
<div
class=
"page-left"
>
<div
class=
"box1"
>
<div
class=
"box1"
>
<AnalysisBox
title=
"主要指令"
:showAllBtn=
"false"
>
<AnalysisBox
title=
"主要指令"
:showAllBtn=
"false"
>
<template
#
header-btn
>
<div
class=
"mind-bnt"
@
click=
"onDecreeMindMap()"
>
<div
class=
"mind-icon"
>
<img
src=
"./assets/images/edit-line.png"
alt=
""
>
</div>
<div
class=
"mind-text"
>
思维导图
</div>
</div>
</
template
>
<div
class=
"analysis-box"
>
<div
class=
"analysis-box"
>
<div
class=
"analysis-top"
>
<div
class=
"analysis-top"
>
<el-select
v-model=
"areaType"
:empty-values=
"[null, undefined]"
@
change=
"onMainContentData()"
style=
"width: 200px;"
>
<el-select
v-model=
"areaType"
:empty-values=
"[null, undefined]"
@
change=
"onMainContentData()"
style=
"width: 200px;"
>
...
@@ -92,7 +100,7 @@
...
@@ -92,7 +100,7 @@
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"organization-button"
>
<div
class=
"organization-button"
@
click=
"handleClickToolBox()"
>
<div
class=
"button-text"
>
查看政令执行情况
</div>
<div
class=
"button-text"
>
查看政令执行情况
</div>
<el-icon
size=
"16"
><Right
/></el-icon>
<el-icon
size=
"16"
><Right
/></el-icon>
</div>
</div>
...
@@ -114,16 +122,29 @@
...
@@ -114,16 +122,29 @@
</AnalysisBox>
</AnalysisBox>
</div>
</div>
</div>
</div>
<el-dialog
v-model=
"isTreeDialog"
width=
"1540px"
top=
"8vh"
class=
"viewpoint-dialog"
destroy-on-close
>
<
template
#
header
>
<div
class=
"viewpoint-header"
>
<div
class=
"viewpoint-title"
>
政令举措思维导图
</div>
</div>
</
template
>
<div
class=
"viewpoint-body"
>
<MindGraph
ref=
"refMindGraph"
></MindGraph>
</div>
</el-dialog>
</div>
</div>
</template>
</template>
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
,
reactive
}
from
"vue"
;
import
{
ref
,
onMounted
,
reactive
}
from
"vue"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
ElMessage
}
from
"element-plus"
;
import
router
from
"@/router"
;
import
router
from
"@/router"
;
import
{
Search
}
from
'@element-plus/icons-vue'
import
{
Search
}
from
'@element-plus/icons-vue'
import
MindGraph
from
"@/views/decree/com/MindGraph.vue"
import
{
getDecreeOrganization
}
from
"@/api/decree/introduction"
;
import
{
getDecreeOrganization
}
from
"@/api/decree/introduction"
;
import
{
getDecreeRelatedEntity
,
getDecreeMainContent
}
from
"@/api/decree/background"
;
import
{
getDecreeRelatedEntity
,
getDecreeMainContent
,
getDecreeMindMap
}
from
"@/api/decree/background"
;
import
{
getDecreehylyList
}
from
"@/api/decree/home"
;
import
{
getDecreehylyList
}
from
"@/api/decree/home"
;
import
ActionButton
from
'@/components/base/ActionButton/index.vue'
import
ActionButton
from
'@/components/base/ActionButton/index.vue'
import
DefaultIcon1
from
"@/assets/icons/default-icon1.png"
;
import
DefaultIcon1
from
"@/assets/icons/default-icon1.png"
;
...
@@ -132,6 +153,10 @@ import defaultCom from "@/views/coopRestriction/assets/images/default-icon2.png"
...
@@ -132,6 +153,10 @@ import defaultCom from "@/views/coopRestriction/assets/images/default-icon2.png"
const
route
=
useRoute
();
const
route
=
useRoute
();
const
handleClickToolBox
=
()
=>
{
ElMessage
.
warning
(
"当前功能正在开发中,敬请期待!"
);
};
// 科技领域
// 科技领域
const
areaType
=
ref
(
""
);
const
areaType
=
ref
(
""
);
const
areaList
=
ref
([]);
const
areaList
=
ref
([]);
...
@@ -272,6 +297,50 @@ const simpleNumToChinese = (num) => {
...
@@ -272,6 +297,50 @@ const simpleNumToChinese = (num) => {
}
}
}
}
// 思维导图
const
isTreeDialog
=
ref
(
false
);
const
refMindGraph
=
ref
(
null
);
const
onDecreeMindMap
=
async
()
=>
{
let
labelCfg
=
{
position
:
'left'
,
offset
:
-
20
,
style
:
{
fontWeight
:
"normal"
,
fontSize
:
16
,
textAlign
:
'left'
,
autoWrap
:
true
}
}
isTreeDialog
.
value
=
true
;
try
{
let
res
=
await
getDecreeMindMap
({
id
:
route
.
query
.
id
});
console
.
log
(
"思维导图"
,
res
);
if
(
res
.
code
===
200
)
{
let
nodes
=
[]
let
edges
=
[]
Object
.
keys
(
res
.
data
||
{}).
forEach
((
label
,
count
)
=>
{
nodes
.
push
({
id
:
`node-
${
count
}
`
,
label
})
})
Object
.
values
(
res
.
data
||
{}).
forEach
((
list
,
count
)
=>
{
list
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
execAgent
?.
length
)
{
nodes
.
push
({
id
:
`node-
${
count
}
-
${
index
}
`
,
label
:
item
.
textZh
,
maxWidth
:
600
,
labelCfg
})
item
.
execAgent
.
forEach
((
label
,
num
)
=>
{
nodes
.
push
({
id
:
`node-
${
count
}
-
${
index
}
-
${
num
}
`
,
label
})
edges
.
push
({
id
:
`edge1-
${
count
}
-
${
index
}
-
${
num
}
`
,
source
:
`node-
${
count
}
-
${
index
}
-
${
num
}
`
,
target
:
`node-
${
count
}
-
${
index
}
`
})
edges
.
push
({
id
:
`edge2-
${
count
}
-
${
index
}
-
${
num
}
`
,
source
:
`node-
${
count
}
`
,
target
:
`node-
${
count
}
-
${
index
}
-
${
num
}
`
})
})
}
})
})
setTimeout
(()
=>
{
refMindGraph
.
value
.
onMindGraphData
(
nodes
,
edges
)
},
100
)
}
}
catch
(
error
)
{
console
.
error
(
"获取思维导图数据失败:"
,
error
);
}
}
// 相关实体
// 相关实体
const
entityList
=
ref
([]);
const
entityList
=
ref
([]);
const
onRelatedEntityData
=
async
()
=>
{
const
onRelatedEntityData
=
async
()
=>
{
...
@@ -359,6 +428,31 @@ onMounted(() => {
...
@@ -359,6 +428,31 @@ onMounted(() => {
flex
:
auto
;
flex
:
auto
;
.box1
{
.box1
{
.mind-bnt
{
background-color
:
var
(
--
color-primary-10
);
height
:
28px
;
border-radius
:
14px
;
display
:
flex
;
align-items
:
center
;
padding
:
0
16px
;
cursor
:
pointer
;
.mind-icon
{
width
:
16px
;
height
:
13px
;
font-size
:
0px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.mind-text
{
color
:
var
(
--
color-primary-100
);
font-family
:
Source
Han
Sans
CN
;
font-size
:
16px
;
line-height
:
16px
;
margin-left
:
6px
;
}
}
.analysis-box
{
.analysis-box
{
display
:
flex
;
display
:
flex
;
...
@@ -776,5 +870,42 @@ onMounted(() => {
...
@@ -776,5 +870,42 @@ onMounted(() => {
}
}
}
}
}
}
// 修改element-plus弹出框样式
:deep
(
.viewpoint-dialog
)
{
padding
:
0
;
border-radius
:
4px
;
.el-dialog__body
{
padding
:
0
;
}
.el-dialog__header
{
padding
:
0
;
margin
:
0
;
position
:
relative
;
height
:
48px
;
}
.el-dialog__headerbtn
{
top
:
50%
;
transform
:
translateY
(
-50%
);
right
:
12px
;
}
.viewpoint-header
{
height
:
48px
;
display
:
flex
;
align-items
:
center
;
padding
:
0
24px
;
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
}
.viewpoint-title
{
font-size
:
16px
;
font-weight
:
700
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
}
.viewpoint-body
{
padding
:
16px
;
height
:
77vh
;
}
}
}
}
</
style
>
</
style
>
\ No newline at end of file
src/views/exportControl/v2.0SingleSanction/components/deepMining/index.vue
浏览文件 @
8e7d08ff
...
@@ -187,11 +187,11 @@ const handleMouseLeave = () => {
...
@@ -187,11 +187,11 @@ const handleMouseLeave = () => {
isInChart
.
value
=
false
;
isInChart
.
value
=
false
;
};
};
const
handleNodeClick
=
(
node
)
=>
{
const
handleNodeClick
=
node
=>
{
selectedNode
.
value
=
node
;
selectedNode
.
value
=
node
;
};
};
const
handleLayoutChange
=
(
type
)
=>
{
const
handleLayoutChange
=
type
=>
{
controlActive
.
value
=
type
;
controlActive
.
value
=
type
;
if
(
type
!==
2
)
{
if
(
type
!==
2
)
{
isInChart
.
value
=
true
;
isInChart
.
value
=
true
;
...
@@ -201,9 +201,8 @@ const handleLayoutChange = (type) => {
...
@@ -201,9 +201,8 @@ const handleLayoutChange = (type) => {
};
};
const
updateGraphData
=
()
=>
{
const
updateGraphData
=
()
=>
{
const
data
=
rightActiveTab
.
value
===
'supplyChain'
const
data
=
?
singleSanctionEntitySupplyChainData
.
value
rightActiveTab
.
value
===
"supplyChain"
?
singleSanctionEntitySupplyChainData
.
value
:
singleSanctionEntityEquityData
.
value
;
:
singleSanctionEntityEquityData
.
value
;
if
(
!
data
)
return
;
if
(
!
data
)
return
;
...
@@ -231,7 +230,7 @@ const updateGraphData = () => {
...
@@ -231,7 +230,7 @@ const updateGraphData = () => {
links
.
push
({
links
.
push
({
source
:
`p-
${
item
.
id
||
index
}
`
,
source
:
`p-
${
item
.
id
||
index
}
`
,
target
:
"0"
,
target
:
"0"
,
name
:
rightActiveTab
.
value
===
'supplyChain'
?
"供应商"
:
(
item
.
type
||
"持股"
)
name
:
rightActiveTab
.
value
===
"supplyChain"
?
"供应商"
:
item
.
type
||
"持股"
});
});
});
});
...
@@ -248,14 +247,14 @@ const updateGraphData = () => {
...
@@ -248,14 +247,14 @@ const updateGraphData = () => {
links
.
push
({
links
.
push
({
source
:
"0"
,
source
:
"0"
,
target
:
`c-
${
item
.
id
||
index
}
`
,
target
:
`c-
${
item
.
id
||
index
}
`
,
name
:
rightActiveTab
.
value
===
'supplyChain'
?
"客户"
:
(
item
.
type
||
"投资"
)
name
:
rightActiveTab
.
value
===
"supplyChain"
?
"客户"
:
item
.
description
||
"投资"
});
});
});
});
graphData
.
value
=
{
nodes
,
links
};
graphData
.
value
=
{
nodes
,
links
};
};
};
const
updateTreeData
=
(
data
)
=>
{
const
updateTreeData
=
data
=>
{
if
(
!
data
)
return
;
if
(
!
data
)
return
;
treeData
.
value
=
{
treeData
.
value
=
{
...
@@ -336,17 +335,17 @@ const getSingleSanctionEntityListRequest = async () => {
...
@@ -336,17 +335,17 @@ const getSingleSanctionEntityListRequest = async () => {
}
}
};
};
watch
(
rightActiveTab
,
async
(
newTab
)
=>
{
watch
(
rightActiveTab
,
async
newTab
=>
{
if
(
newTab
===
'supplyChain'
)
{
if
(
newTab
===
"supplyChain"
)
{
await
getSingleSanctionEntitySupplyChainRequest
();
await
getSingleSanctionEntitySupplyChainRequest
();
}
else
{
}
else
{
await
getSingleSanctionEntityEquityRequest
();
await
getSingleSanctionEntityEquityRequest
();
}
}
});
});
watch
(
activeEntityId
,
async
(
newId
)
=>
{
watch
(
activeEntityId
,
async
newId
=>
{
if
(
newId
)
{
if
(
newId
)
{
if
(
rightActiveTab
.
value
===
'supplyChain'
)
{
if
(
rightActiveTab
.
value
===
"supplyChain"
)
{
await
getSingleSanctionEntitySupplyChainRequest
();
await
getSingleSanctionEntitySupplyChainRequest
();
}
else
{
}
else
{
await
getSingleSanctionEntityEquityRequest
();
await
getSingleSanctionEntityEquityRequest
();
...
@@ -355,7 +354,7 @@ watch(activeEntityId, async (newId) => {
...
@@ -355,7 +354,7 @@ watch(activeEntityId, async (newId) => {
});
});
watch
(
is50PercentRule
,
async
()
=>
{
watch
(
is50PercentRule
,
async
()
=>
{
if
(
rightActiveTab
.
value
===
'equity'
)
{
if
(
rightActiveTab
.
value
===
"equity"
)
{
await
getSingleSanctionEntityEquityRequest
();
await
getSingleSanctionEntityEquityRequest
();
}
}
});
});
...
...
src/views/innovationSubject/ResourceLibrary/ResourceLibrary.vue
浏览文件 @
8e7d08ff
...
@@ -71,21 +71,19 @@
...
@@ -71,21 +71,19 @@
v-for=
"item in listData"
v-for=
"item in listData"
:key=
"item.id"
:key=
"item.id"
class=
"resource-card"
class=
"resource-card"
@
click=
"goToInstitution(item.id)"
>
>
<div
class=
"card-logo"
>
<div
class=
"card-logo"
>
<img
:src=
"item.logo
Url
|| defaultLogo"
:alt=
"item.name"
/>
<img
:src=
"item.logo || defaultLogo"
:alt=
"item.name"
/>
</div>
</div>
<div
class=
"card-name"
>
{{
item
.
name
}}
</div>
<div
class=
"card-name"
>
{{
item
.
name
}}
</div>
<div
class=
"card-location"
>
{{
item
.
address
}}
</div>
<div
class=
"card-location"
>
{{
item
.
location
}}
</div>
<div
class=
"card-majors"
>
{{
item
.
majors
}}
</div>
<div
class=
"card-majors"
>
{{
item
.
majors
}}
</div>
<div
class=
"card-tags"
>
<div
class=
"card-tags"
>
<span
v-for=
"tag in item.tags"
<AreaTag
v-for=
"tag in item.tags"
:key=
"tag"
:key=
"tag"
:tagName=
"tag"
/>
class=
"tag"
>
{{
tag
}}
</span>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
...
@@ -134,7 +132,10 @@
...
@@ -134,7 +132,10 @@
import
{
ref
,
computed
,
onMounted
,
watch
}
from
'vue'
import
{
ref
,
computed
,
onMounted
,
watch
}
from
'vue'
import
{
getIndustryKeyList
}
from
'@/api/bill/billHome.js'
import
{
getIndustryKeyList
}
from
'@/api/bill/billHome.js'
import
{
getSubjectList
}
from
'@/api/characterPage/characterPage.js'
import
{
getSubjectList
}
from
'@/api/characterPage/characterPage.js'
import
AreaTag
from
'@/components/base/AreaTag/index.vue'
import
{
useRouter
}
from
'vue-router'
const
router
=
useRouter
()
// Props
// Props
const
props
=
defineProps
<
{
const
props
=
defineProps
<
{
initialTab
?:
string
initialTab
?:
string
...
@@ -142,7 +143,9 @@ const props = defineProps<{
...
@@ -142,7 +143,9 @@ const props = defineProps<{
// 默认logo
// 默认logo
const
defaultLogo
=
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9IiNhMzE4MWIiIHJ4PSI0Ii8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTggOGgxNnYxNkg4eiIvPjwvc3ZnPg=='
const
defaultLogo
=
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9IiNhMzE4MWIiIHJ4PSI0Ii8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTggOGgxNnYxNkg4eiIvPjwvc3ZnPg=='
const
goOrigin
=
(
id
)
=>
{
router
.
push
(
`/InnovativeInstitutions/
${
id
}
`
)
}
// 标签配置 - 添加 subjectTypeId
// 标签配置 - 添加 subjectTypeId
const
tabs
=
ref
([
const
tabs
=
ref
([
{
label
:
'大学'
,
value
:
'university'
,
subjectTypeId
:
1
},
{
label
:
'大学'
,
value
:
'university'
,
subjectTypeId
:
1
},
...
@@ -165,7 +168,17 @@ const fields = ref<{ label: string; value: string }[]>([
...
@@ -165,7 +168,17 @@ const fields = ref<{ label: string; value: string }[]>([
{
label
:
'全部领域'
,
value
:
'all'
}
{
label
:
'全部领域'
,
value
:
'all'
}
])
])
const
fieldsLoading
=
ref
(
false
)
const
fieldsLoading
=
ref
(
false
)
const
goToInstitution
=
(
id
)
=>
{
router
.
push
({
name
:
'InnovativeInstitutions'
,
params
:
{
id
:
id
,
type
:
1
}
})
}
// 获取科技领域选项
// 获取科技领域选项
async
function
fetchFieldOptions
()
{
async
function
fetchFieldOptions
()
{
fieldsLoading
.
value
=
true
fieldsLoading
.
value
=
true
...
@@ -274,7 +287,6 @@ function goToPage(page: number | string) {
...
@@ -274,7 +287,6 @@ function goToPage(page: number | string) {
}
}
}
}
// 模拟API获取数据
async
function
fetchData
()
{
async
function
fetchData
()
{
loading
.
value
=
true
loading
.
value
=
true
try
{
try
{
...
@@ -299,12 +311,12 @@ async function fetchData() {
...
@@ -299,12 +311,12 @@ async function fetchData() {
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 映射 API 返回的数据到卡片显示格式
// 映射 API 返回的数据到卡片显示格式
const
mappedData
=
(
res
.
data
.
content
||
[]).
map
((
item
:
any
)
=>
({
const
mappedData
=
(
res
.
data
.
content
||
[]).
map
((
item
:
any
)
=>
({
id
:
item
.
i
d
,
id
:
item
.
orgI
d
,
name
:
item
.
orgName
,
name
:
item
.
orgName
,
location
:
item
.
countryName
?
`
${
item
.
countryName
}
·
${
item
.
provinceName
}
`
:
item
.
provinceName
||
'--'
,
location
:
item
.
address
||
'--'
,
majors
:
item
.
fieldList
?.
join
(
'、'
)
||
'--'
,
majors
:
item
.
fieldList
?.
join
(
'、'
)
||
'--'
,
tags
:
item
.
areaList
?.
map
((
a
:
any
)
=>
a
.
areaName
)
||
[],
tags
:
item
.
taglist
||
[],
logo
:
defaultLogo
logo
:
item
.
logoUrl
}))
}))
listData
.
value
=
mappedData
listData
.
value
=
mappedData
...
...
src/views/innovationSubject/innovativeInstitutions/index.vue
浏览文件 @
8e7d08ff
...
@@ -70,13 +70,21 @@
...
@@ -70,13 +70,21 @@
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
import
{
ref
}
from
'vue'
import
{
ref
,
computed
,
provide
}
from
'vue'
import
{
useRoute
}
from
'vue-router'
import
AreaTag
from
'@/components/base/AreaTag/index.vue'
import
AreaTag
from
'@/components/base/AreaTag/index.vue'
import
SchoolDetail
from
'./tabs/SchoolDetail.vue'
import
SchoolDetail
from
'./tabs/SchoolDetail.vue'
import
ResearchStrength
from
'./tabs/ResearchStrength.vue'
import
ResearchStrength
from
'./tabs/ResearchStrength.vue'
import
Cooperation
from
'./tabs/Cooperation.vue'
import
Cooperation
from
'./tabs/Cooperation.vue'
import
OtherInfo
from
'./tabs/OtherInfo.vue'
import
OtherInfo
from
'./tabs/OtherInfo.vue'
// 从路由获取 orgId
const
route
=
useRoute
()
const
orgId
=
computed
(()
=>
route
.
params
.
id
||
''
)
// 提供给子组件使用
provide
(
'orgId'
,
orgId
)
// 大学基本信息
// 大学基本信息
const
universityInfo
=
ref
({
const
universityInfo
=
ref
({
name
:
'哈佛大学'
,
name
:
'哈佛大学'
,
...
...
src/views/innovationSubject/innovativeInstitutions/tabs/OtherInfo.vue
浏览文件 @
8e7d08ff
...
@@ -42,100 +42,127 @@
...
@@ -42,100 +42,127 @@
</
template
>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
computed
}
from
'vue'
import
{
ref
,
computed
,
onMounted
,
watch
}
from
'vue'
import
AnalysisBox
from
'@/components/base/boxBackground/analysisBox.vue'
import
AnalysisBox
from
'@/components/base/boxBackground/analysisBox.vue'
import
LeftBtn
from
'@/components/base/pageBtn/leftBtn.vue'
import
LeftBtn
from
'@/components/base/pageBtn/leftBtn.vue'
import
RightBtn
from
'@/components/base/pageBtn/rightBtn.vue'
import
RightBtn
from
'@/components/base/pageBtn/rightBtn.vue'
import
AreaTag
from
'@/components/base/AreaTag/index.vue'
import
AreaTag
from
'@/components/base/AreaTag/index.vue'
import
{
getLabList
,
getPolicyList
}
from
'@/api/innovationSubject/overview.js'
const
props
=
defineProps
<
{
orgId
?:
string
}
>
()
const
areaTypeMap
:
Record
<
string
,
string
>
=
{
'人工智能'
:
'tag1'
,
'生物科技'
:
'tag2'
,
'太空'
:
'tag3'
,
'航空航天'
:
'tag4'
,
'先进制造'
:
'tag5'
,
'物理学'
:
'tag6'
,
'海洋'
:
'tag7'
,
'新能源'
:
'tag8'
,
'医学'
:
'tag9'
,
'化学'
:
'tag10'
,
'新一代通信网络'
:
'tag11'
,
'其他'
:
'tag12'
}
// 重点实验室数据
const
labsData
=
ref
<
Array
<
{
const
labsData
=
ref
([
logo
:
string
{
name
:
string
logo
:
'/images/lab-wyss.png'
,
description
:
string
name
:
'怀斯生物启发工程研究所'
,
tags
:
Array
<
{
name
:
string
;
type
:
string
}
>
description
:
'成立于2009年,由汉斯约尔格·怀斯(Hansjörg Wyss)捐赠建立,聚焦仿生学与跨学科工程,推动医疗、机器人、材料等领域的突破。'
,
}
>>
([])
tags
:
[{
name
:
'生物科技'
,
type
:
'tag2'
}]
},
const
policyData
=
ref
<
Array
<
{
{
title
:
string
logo
:
'/images/lab-rowland.png'
,
description
:
string
name
:
'罗兰研究所'
,
}
>>
([])
description
:
'原为独立研究机构,2002年并入哈佛,支持高风险、高回报的基础科学研究,尤其鼓励青年科学家。'
,
tags
:
[{
name
:
'物理学'
,
type
:
'tag6'
},
{
name
:
'化学'
,
type
:
'tag10'
}]
const
currentPage
=
ref
(
1
)
},
const
pageSize
=
ref
(
6
)
{
const
totalCount
=
ref
(
0
)
logo
:
'/images/lab-quantum.png'
,
const
totalPages
=
ref
(
0
)
name
:
'哈佛量子计划'
,
const
loading
=
ref
(
false
)
description
:
'跨学院合作平台,整合物理、工程、计算机科学等资源,推动量子科学与技术发展。'
,
tags
:
[{
name
:
'物理'
,
type
:
'tag6'
}]
const
fetchLabList
=
async
()
=>
{
},
const
orgId
=
props
.
orgId
||
'6789'
{
try
{
logo
:
'/images/lab-broad.png'
,
const
result
=
await
getLabList
(
orgId
)
name
:
'博德研究所'
,
if
(
result
.
success
&&
result
.
data
)
{
description
:
'全球顶尖基因组学与生物医学研究中心,推动精准医学与疾病机制研究。'
,
labsData
.
value
=
result
.
data
.
map
((
item
:
any
)
=>
({
tags
:
[{
name
:
'医学'
,
type
:
'tag9'
}]
logo
:
item
.
logoUrl
||
'/images/lab-default.png'
,
},
name
:
item
.
labName
,
{
description
:
item
.
introduction
,
logo
:
'/images/lab-stem.png'
,
tags
:
(
item
.
arealist
||
[]).
map
((
area
:
string
)
=>
({
name
:
'哈佛干细胞研究所'
,
name
:
area
,
description
:
'成立于2004年,联合哈佛医学院、牙医学院、文理学院等,推动干细胞基础研究与临床转化。'
,
type
:
areaTypeMap
[
area
]
||
'tag12'
tags
:
[{
name
:
'医学'
,
type
:
'tag9'
}]
}))
},
}))
{
}
logo
:
'/images/lab-cfa.png'
,
}
catch
(
error
)
{
name
:
'哈佛大学天体物理中心'
,
console
.
error
(
'获取实验室列表失败:'
,
error
)
description
:
'由哈佛大学与史密森尼学会于1973年联合成立,是全球规模最大、最活跃的天体物理研究机构之一。'
,
tags
:
[{
name
:
'天体物理'
,
type
:
'tag3'
}]
}
}
])
}
// 政策文件数据
const
fetchPolicyList
=
async
()
=>
{
const
policyData
=
ref
([
const
orgId
=
props
.
orgId
||
'6789'
{
title
:
'《哈佛大学权利与责任声明》'
,
description
:
'阐明学生在言论自由、学术自由、正当程序、尊重他人等方面的权利与义务。'
},
loading
.
value
=
true
{
title
:
'《哈佛大学学术诚信政策》'
,
description
:
'定义抄袭、作弊、伪造等学术不端行为,并规定处理流程。'
},
try
{
{
title
:
'《哈佛大学反歧视与反骚扰政策》'
,
description
:
'禁止基于种族、性别、性取向、宗教、残疾等的歧视与骚扰,明确举报与调查机制。'
},
const
result
=
await
getPolicyList
(
orgId
,
currentPage
.
value
,
pageSize
.
value
)
{
title
:
'《研究合规与人类受试者保护政策》'
,
description
:
'规范涉及人类受试者的研究(如医学、心理学、社会学实验),确保符合联邦法规(如Common Rule)。'
},
if
(
result
.
success
&&
result
.
data
)
{
{
title
:
'《哈佛法学院学术政策手册》'
,
description
:
'详述J.D./LL.M./S.J.D.学位要求、课程规则、成绩制度、书面作业要求、出勤规定、荣誉毕业标准等。'
},
policyData
.
value
=
result
.
data
.
content
.
map
((
item
:
any
)
=>
({
{
title
:
'《哈佛文理研究生院学生手册》'
,
description
:
'涵盖博士生资格考试、论文提交、助教职责、奖学金续期、学术进展评估等。'
}
title
:
`《
${
item
.
name
}
》`
,
])
description
:
item
.
introduction
}))
// 分页相关
totalCount
.
value
=
result
.
data
.
totalElements
const
currentPage
=
ref
(
5
)
totalPages
.
value
=
result
.
data
.
totalPages
const
totalCount
=
ref
(
105
)
}
const
totalPages
=
computed
(()
=>
Math
.
ceil
(
totalCount
.
value
/
10
))
}
catch
(
error
)
{
console
.
error
(
'获取政策文件列表失败:'
,
error
)
}
finally
{
loading
.
value
=
false
}
}
watch
(
currentPage
,
()
=>
{
fetchPolicyList
()
})
onMounted
(()
=>
{
fetchLabList
()
fetchPolicyList
()
})
const
displayPages
=
computed
(()
=>
{
const
displayPages
=
computed
(()
=>
{
const
pages
:
(
number
|
string
)[]
=
[]
const
pages
:
(
number
|
string
)[]
=
[]
if
(
totalPages
.
value
<=
7
)
{
const
total
=
totalPages
.
value
for
(
let
i
=
1
;
i
<=
totalPages
.
value
;
i
++
)
pages
.
push
(
i
)
if
(
total
<=
7
)
{
for
(
let
i
=
1
;
i
<=
total
;
i
++
)
pages
.
push
(
i
)
}
else
{
}
else
{
pages
.
push
(
1
)
pages
.
push
(
1
)
if
(
currentPage
.
value
>
3
)
pages
.
push
(
'...'
)
if
(
currentPage
.
value
>
3
)
pages
.
push
(
'...'
)
const
start
=
Math
.
max
(
2
,
currentPage
.
value
-
1
)
const
start
=
Math
.
max
(
2
,
currentPage
.
value
-
1
)
const
end
=
Math
.
min
(
total
Pages
.
value
-
1
,
currentPage
.
value
+
1
)
const
end
=
Math
.
min
(
total
-
1
,
currentPage
.
value
+
1
)
for
(
let
i
=
start
;
i
<=
end
;
i
++
)
pages
.
push
(
i
)
for
(
let
i
=
start
;
i
<=
end
;
i
++
)
pages
.
push
(
i
)
if
(
currentPage
.
value
<
total
Pages
.
value
-
2
)
pages
.
push
(
'...'
)
if
(
currentPage
.
value
<
total
-
2
)
pages
.
push
(
'...'
)
pages
.
push
(
total
Pages
.
value
)
pages
.
push
(
total
)
}
}
return
pages
return
pages
})
})
// 上一页
const
prevPage
=
()
=>
{
const
prevPage
=
()
=>
{
if
(
currentPage
.
value
>
1
)
currentPage
.
value
--
if
(
currentPage
.
value
>
1
)
currentPage
.
value
--
}
}
// 下一页
const
nextPage
=
()
=>
{
const
nextPage
=
()
=>
{
if
(
currentPage
.
value
<
totalPages
.
value
)
currentPage
.
value
++
if
(
currentPage
.
value
<
totalPages
.
value
)
currentPage
.
value
++
}
}
// 跳转到指定页
const
goToPage
=
(
page
:
number
|
string
)
=>
{
const
goToPage
=
(
page
:
number
|
string
)
=>
{
if
(
typeof
page
===
'number'
)
currentPage
.
value
=
page
if
(
typeof
page
===
'number'
)
currentPage
.
value
=
page
}
}
// 获取标签样式
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
...
...
src/views/innovationSubject/innovativeInstitutions/tabs/ResearchStrength.vue
浏览文件 @
8e7d08ff
差异被折叠。
点击展开。
vite.config.js
浏览文件 @
8e7d08ff
...
@@ -55,6 +55,7 @@ export default defineConfig({
...
@@ -55,6 +55,7 @@ export default defineConfig({
'/api'
:
{
'/api'
:
{
target
:
'http://8.140.26.4:9085/'
,
target
:
'http://8.140.26.4:9085/'
,
// target: 'http://192.168.0.4:28080/',
changeOrigin
:
true
,
changeOrigin
:
true
,
rewrite
:
(
path
)
=>
path
.
replace
(
/^
\/
api/
,
''
)
rewrite
:
(
path
)
=>
path
.
replace
(
/^
\/
api/
,
''
)
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论