提交 db0abf0c authored 作者: huhuiqing's avatar huhuiqing

Merge branch 'master' of http://8.140.26.4:10003/caijian/risk-monitor into dev_hhq

# Conflicts: # src/views/thinkTank/index.vue
...@@ -140,3 +140,16 @@ export function getBillHyly(params) { ...@@ -140,3 +140,16 @@ export function getBillHyly(params) {
params, params,
}) })
} }
// 根据法案ID获取法案全局信息
/**
* @param {id}
* @header token
*/
export function getBillInfoGlobal(params) {
return request({
method: 'GET',
url: `/api/billInfoBean/summary/${params.id}`,
params,
})
}
\ No newline at end of file
...@@ -328,6 +328,49 @@ export function getSelectEntitiesList(startTime) { ...@@ -328,6 +328,49 @@ export function getSelectEntitiesList(startTime) {
); );
} }
/**
* 涉及50%规则的实体数
*/
export function getEntitiesCountBy50PercentRules(
typeName = "实体清单",
pageNum = 1,
pageSize = 10,
sanctionDate = "",
isCn = false
) {
return request200(
request({
method: "POST",
url: "/api/sanctionList/getRuleCount",
data: {
typeName,
pageNum,
pageSize,
sanctionDate,
isCn
}
})
);
}
/**
* 获取前序事件
*/
// /entitiesDataInfo/precedingEvents
export function getPrecedingEvents(startTime = "2025-11-11", pageNum = 1, pageSize = 10) {
return request200(
request({
method: "POST",
url: "/api/entitiesDataInfo/precedingEvents",
data: {
sanctionDate: startTime,
pageNum,
pageSize
}
})
);
}
/** /**
* 领域分布查询 * 领域分布查询
*/ */
...@@ -352,7 +395,7 @@ export function getDomainDistribution(sanctionDate = "2025-11-11") { ...@@ -352,7 +395,7 @@ export function getDomainDistribution(sanctionDate = "2025-11-11") {
* startTime: string * startTime: string
* }[]>} * }[]>}
*/ */
export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize = 10, sanctionDate = "", rule = false) { export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize = 10, sanctionDate = "", isCn = false) {
return request200( return request200(
request({ request({
method: "POST", method: "POST",
...@@ -362,7 +405,7 @@ export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize ...@@ -362,7 +405,7 @@ export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize
pageNum, pageNum,
pageSize, pageSize,
sanctionDate, sanctionDate,
rule isCn
} }
}) })
); );
...@@ -584,7 +627,8 @@ export function getCountThisType(param) { ...@@ -584,7 +627,8 @@ export function getCountThisType(param) {
return request200( return request200(
request({ request({
method: "GET", method: "GET",
url: "/api/entitiesDataCount/countThisType", // url: "/api/entitiesDataCount/countThisType",
url: "/api/entitiesDataInfo/annual/researchInstitute",
params: { params: {
param param
} }
...@@ -592,6 +636,48 @@ export function getCountThisType(param) { ...@@ -592,6 +636,48 @@ export function getCountThisType(param) {
); );
} }
/**
* 企业类实体历史制裁情况
*/
export function getEnterpriseSanCount() {
return request200(
request({
method: "GET",
url: "/api/entitiesDataInfo/annual/enterprise"
})
);
}
/**
* 根据领域获取产业链信息
*/
export function getChainInfoByDomainId(domainId) {
return request200(
request({
method: "GET",
url: "/api/chain/getChainInfo",
params: {
domainId
}
})
);
}
/**
* 产业链中国企业实体信息查询
*/
export function getCnEntityOnChain(chainId) {
return request200(
request({
method: "GET",
url: "/api/chain/getChainEntityStat",
params: {
chainId
}
})
);
}
/** /**
* 产业链信息查询 * 产业链信息查询
*/ */
...@@ -677,3 +763,76 @@ export function getKeyListedEntityList(date, keyword = "") { ...@@ -677,3 +763,76 @@ export function getKeyListedEntityList(date, keyword = "") {
}) })
); );
} }
/**
* 获取科学仪器对美依赖数量
*/
export function getScientificInstrumentDependencyCount(orgIds = "12100000400012916R,121000004013595328,12100000435230200R") {
return request200(
request({
method: "GET",
url: "/api/instrument/getDependencyUS",
params: {
orgIds
}
})
);
}
/**
* 科学仪器近十年对美依赖度升高风险分析
* url: /instrument/getDependencyUSRisk
*/
export function getScientificInstrumentDependencyRisk() {
return request200(
request({
method: "GET",
url: "/api/instrument/getDependencyUSRisk"
})
);
}
/**
* 科学仪器近十年国产化数量统计
* url:/instrument/getLocalizationRisk
*/
export function getScientificInstrumentLocalizationRisk() {
return request200(
request({
method: "GET",
url: "/api/instrument/getLocalizationRisk"
})
);
}
/**
* 科学仪器进口国统计
* url: /instrument/getOriginCount
*/
export function getScientificInstrumentOriginCount(orgIds = "12100000400012916R,121000004013595328,12100000435230200R") {
return request200(
request({
method: "GET",
url: "/api/instrument/getOriginCount",
params: {
orgIds
}
})
);
}
/**
* 新增科研机构列表
* url: /entitiesDataInfo/scientificImpact/entityList
*/
export function getScientificImpactEntityList(startTime) {
return request200(
request({
method: "GET",
url: "/api/entitiesDataInfo/scientificImpact/entityList",
params: {
sanctionDate: startTime || "2025-11-11"
}
})
);
}
...@@ -141,6 +141,7 @@ export function getThinkPolicy(params) { ...@@ -141,6 +141,7 @@ export function getThinkPolicy(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/api/thinkTankInfo/policy/${params.id}/${params.startDate}`, url: `/api/thinkTankInfo/policy/${params.id}/${params.startDate}`,
params
}) })
} }
......
...@@ -49,3 +49,27 @@ ...@@ -49,3 +49,27 @@
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: #c1c1c1 #f1f1f1; scrollbar-color: #c1c1c1 #f1f1f1;
} }
/* 只针对水平滚动条 */
::-webkit-scrollbar:horizontal {
height: 5px;
}
/* 水平滚动条轨道 */
::-webkit-scrollbar-track:horizontal {
background: linear-gradient(90deg, #f0f0f0, #e0e0e0);
}
/* 水平滚动条滑块 */
::-webkit-scrollbar-thumb:horizontal {
background: #bcbcbc;
min-width: 40px; /* 最小宽度 */
}
::-webkit-scrollbar-thumb:horizontal:hover {
background: #505357;
}
::-webkit-scrollbar-thumb:horizontal:active {
background: #505357;
}
\ No newline at end of file
...@@ -84,7 +84,6 @@ ...@@ -84,7 +84,6 @@
<div class="btn-icon"> <div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" /> <img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div> </div>
</div> </div>
<div class="btn" @click="handleToPosi('position2')"> <div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">{{ "资讯要闻" }}</div> <div class="btn-text">{{ "资讯要闻" }}</div>
...@@ -127,15 +126,26 @@ ...@@ -127,15 +126,26 @@
</div> </div>
<div class="title">{{ "热门法案" }}</div> <div class="title">{{ "热门法案" }}</div>
</div> </div>
<div class="box1-header-right" @click="handleClickToDetail"> <div class="box1-header-right" @click="handleClickToDetail()">
{{ "查看详情 >" }} {{ "查看详情 >" }}
</div> </div>
</div> </div>
<div class="box1-main"> <div class="box1-main" style="display: block">
<el-carousel
ref="carouselRef"
height="354px"
:autoplay="true"
:interval="3000"
arrow="never"
indicator-position="none"
@change="handleCarouselChange"
>
<el-carousel-item v-for="(bill, billIndex) in hotBillList" :key="billIndex">
<div class="carousel-content" style="display: flex; height: 100%">
<div class="box1-main-left"> <div class="box1-main-left">
<div class="box1-main-left-title"> <div class="box1-main-left-title">
<!-- "H.R.1(119th)-大而美法案" --> <!-- "H.R.1(119th)-大而美法案" -->
{{ curBill.billName }} {{ bill.billName }}
</div> </div>
<div class="box1-main-left-info"> <div class="box1-main-left-info">
<div <div
...@@ -146,7 +156,7 @@ ...@@ -146,7 +156,7 @@
info3: index === 2, info3: index === 2,
info4: index === 3 info4: index === 3
}" }"
v-for="(item, index) in curBill.hylyList" v-for="(item, index) in bill.hylyList"
:key="index" :key="index"
> >
{{ item.industryName }} {{ item.industryName }}
...@@ -156,19 +166,19 @@ ...@@ -156,19 +166,19 @@
<div class="info1-box"> <div class="info1-box">
<div class="icon"></div> <div class="icon"></div>
<div class="info1-box-left">{{ "提案人:" }}</div> <div class="info1-box-left">{{ "提案人:" }}</div>
<div class="info1-box-right">{{ curBill.tarName }}</div> <div class="info1-box-right">{{ bill.tarName }}</div>
</div> </div>
<div class="info1-box"> <div class="info1-box">
<div class="icon"></div> <div class="icon"></div>
<div class="info1-box-left">{{ "提出时间:" }}</div> <div class="info1-box-left">{{ "提出时间:" }}</div>
<div class="info1-box-right"> <div class="info1-box-right">
{{ curBill.introductionDate }} {{ bill.introductionDate }}
</div> </div>
</div> </div>
</div> </div>
<div class="box1-main-left-info2"> <div class="box1-main-left-info2">
<div class="info2-item" v-for="(item, index) in curBill.dyqkList" :key="index"> <div class="info2-item" v-for="(item, index) in bill.dyqkList" :key="index">
<div class="time-line" v-if="index !== curBill.dyqkList.length - 1"></div> <div class="time-line" v-if="index !== bill.dyqkList.length - 1"></div>
<div class="item-icon"> <div class="item-icon">
<img src="./assets/images/info2-icon.png" alt="" /> <img src="./assets/images/info2-icon.png" alt="" />
</div> </div>
...@@ -198,6 +208,9 @@ ...@@ -198,6 +208,9 @@
</div> </div>
</div> </div>
</div> </div>
</el-carousel-item>
</el-carousel>
</div>
</div> </div>
<div class="box2"> <div class="box2">
<div class="box2-header"> <div class="box2-header">
...@@ -210,11 +223,7 @@ ...@@ -210,11 +223,7 @@
</div> </div>
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div <div class="box2-main-item" v-for="(item, index) in warningList" :key="index">
class="box2-main-item"
v-for="(item, index) in warningList"
:key="index"
>
<div <div
class="item-left" class="item-left"
:class="{ :class="{
...@@ -253,14 +262,21 @@ ...@@ -253,14 +262,21 @@
</div> </div>
</div> </div>
<div class="box3-main"> <div class="box3-main">
<div class="box3-item" v-for="(news, index) in newsList" :key="index" @click="handleClickToNewsDetail()"> <div
class="box3-item"
v-for="(news, index) in newsList"
:key="index"
@click="handleClickToNewsDetail()"
>
<div class="left"> <div class="left">
<img :src="news.newsImage || News1" alt="" /> <img :src="news.newsImage || News1" alt="" />
</div> </div>
<div class="right"> <div class="right">
<div class="right-top"> <div class="right-top">
<div class="title">{{ news.newsTitle }}</div> <div class="title">{{ news.newsTitle }}</div>
<div class="time">{{ news.newsDate ? news.newsDate.slice(5) : '' }} - {{ news.newsOrg }}</div> <div class="time">
{{ news.newsDate ? news.newsDate.slice(5) : "" }} - {{ news.newsOrg }}
</div>
</div> </div>
<div class="right-footer">{{ news.newsContent }}</div> <div class="right-footer">{{ news.newsContent }}</div>
</div> </div>
...@@ -276,7 +292,7 @@ ...@@ -276,7 +292,7 @@
</div> </div>
<div class="box4-main"> <div class="box4-main">
<div class="box4-main-item" v-for="(item, index) in messageList" :key="index"> <div class="box4-main-item" v-for="(item, index) in messageList" :key="index">
<div class="left" @click="handleClcikToCharacter(index)"> <div class="left" @click="handleClcikToCharacter(item, index)">
<img :src="item.personImage" alt="" /> <img :src="item.personImage" alt="" />
</div> </div>
<div class="right"> <div class="right">
...@@ -308,14 +324,26 @@ ...@@ -308,14 +324,26 @@
</div> </div>
</div> </div>
<div class="box5-select"> <div class="box5-select">
<el-select v-model="box5Select" placeholder="选择领域" @change="handleBox5Change" style="width: 150px"> <el-select
v-model="box5Select"
placeholder="选择领域"
@change="handleBox5Change"
style="width: 150px"
>
<el-option label="全部领域" value="全部领域" /> <el-option label="全部领域" value="全部领域" />
<el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</div> </div>
<div class="box5-main" :style="{ display: !box5HasData ? 'flex' : 'block', justifyContent: 'center', alignItems: 'center' }"> <div
class="box5-main"
:style="{
display: !box5HasData ? 'flex' : 'block',
justifyContent: 'center',
alignItems: 'center'
}"
>
<el-empty v-if="!box5HasData" description="暂无数据" :image-size="100" /> <el-empty v-if="!box5HasData" description="暂无数据" :image-size="100" />
<div v-else id="box5Chart" style="width: 100%; height: 100%;"></div> <div v-else id="box5Chart" style="width: 100%; height: 100%"></div>
</div> </div>
</div> </div>
<div class="box6"> <div class="box6">
...@@ -344,10 +372,10 @@ ...@@ -344,10 +372,10 @@
<div class="box7-header-title">{{ "法案提出部门" }}</div> <div class="box7-header-title">{{ "法案提出部门" }}</div>
</div> </div>
<div class="box7-header-right"> <div class="box7-header-right">
<div class="header-right-icon"> <!-- <div class="header-right-icon">
<img src="./assets/images/tips-icon.png" alt="" /> <img src="./assets/images/tips-icon.png" alt="" />
</div> </div> -->
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div> <!-- <div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div> -->
</div> </div>
</div> </div>
<div class="box-center"> <div class="box-center">
...@@ -360,9 +388,16 @@ ...@@ -360,9 +388,16 @@
/> />
</el-select> </el-select>
</div> </div>
<div class="box7-main" :style="{ display: !box7HasData ? 'flex' : 'block', justifyContent: 'center', alignItems: 'center' }"> <div
class="box7-main"
:style="{
display: !box7HasData ? 'flex' : 'block',
justifyContent: 'center',
alignItems: 'center'
}"
>
<el-empty v-if="!box7HasData" description="暂无数据" :image-size="100" /> <el-empty v-if="!box7HasData" description="暂无数据" :image-size="100" />
<div v-else id="box7Chart" style="width: 100%; height: 100%;"></div> <div v-else id="box7Chart" style="width: 100%; height: 100%"></div>
</div> </div>
</div> </div>
<div class="box8"> <div class="box8">
...@@ -374,10 +409,10 @@ ...@@ -374,10 +409,10 @@
<div class="box8-header-title">{{ "关键议员提案" }}</div> <div class="box8-header-title">{{ "关键议员提案" }}</div>
</div> </div>
<div class="box8-header-right"> <div class="box8-header-right">
<div class="header-right-icon"> <!-- <div class="header-right-icon">
<img src="./assets/images/tips-icon.png" alt="" /> <img src="./assets/images/tips-icon.png" alt="" />
</div> </div> -->
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div> <!-- <div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div> -->
</div> </div>
</div> </div>
<div class="box-center"> <div class="box-center">
...@@ -390,14 +425,21 @@ ...@@ -390,14 +425,21 @@
/> />
</el-select> </el-select>
</div> </div>
<div class="box8-main" :style="{ display: box8Data.length === 0 ? 'flex' : 'block', justifyContent: 'center', alignItems: 'center' }"> <div
class="box8-main"
:style="{
display: box8Data.length === 0 ? 'flex' : 'block',
justifyContent: 'center',
alignItems: 'center'
}"
>
<el-empty v-if="box8Data.length === 0" description="暂无数据" :image-size="100" /> <el-empty v-if="box8Data.length === 0" description="暂无数据" :image-size="100" />
<div <div
v-else v-else
class="box8-main-item" class="box8-main-item"
v-for="(item, index) in box8Data" v-for="(item, index) in box8Data"
:key="index" :key="index"
@click="handleClcikToCharacter(index)" @click="handleClcikToCharacter(item, index)"
> >
<div class="box8-main-item-left"> <div class="box8-main-item-left">
<img :src="item.img" alt="" referrerpolicy="no-referrer" class="left-img" /> <img :src="item.img" alt="" referrerpolicy="no-referrer" class="left-img" />
...@@ -427,10 +469,10 @@ ...@@ -427,10 +469,10 @@
<div class="box9-header-title">{{ "涉华法案领域分布" }}</div> <div class="box9-header-title">{{ "涉华法案领域分布" }}</div>
</div> </div>
<div class="box9-header-right"> <div class="box9-header-right">
<div class="header-right-icon"> <!-- <div class="header-right-icon">
<img src="./assets/images/tips-icon.png" alt="" /> <img src="./assets/images/tips-icon.png" alt="" />
</div> </div> -->
<div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div> <!-- <div class="header-right-text">{{ "数据来源:美国国会官方网站" }}</div> -->
</div> </div>
</div> </div>
<div class="box-center"> <div class="box-center">
...@@ -443,9 +485,16 @@ ...@@ -443,9 +485,16 @@
/> />
</el-select> </el-select>
</div> </div>
<div class="box9-main" :style="{ display: !box9HasData ? 'flex' : 'block', justifyContent: 'center', alignItems: 'center' }"> <div
class="box9-main"
:style="{
display: !box9HasData ? 'flex' : 'block',
justifyContent: 'center',
alignItems: 'center'
}"
>
<el-empty v-if="!box9HasData" description="暂无数据" :image-size="100" /> <el-empty v-if="!box9HasData" description="暂无数据" :image-size="100" />
<div v-else id="box9Chart" style="width: 100%; height: 100%;"></div> <div v-else id="box9Chart" style="width: 100%; height: 100%"></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -465,7 +514,6 @@ ...@@ -465,7 +514,6 @@
{{ cate.name }} {{ cate.name }}
</div> </div>
</div> </div>
</div> </div>
<div class="home-main-footer-main"> <div class="home-main-footer-main">
<div class="left"> <div class="left">
...@@ -476,9 +524,7 @@ ...@@ -476,9 +524,7 @@
</div> </div>
<div class="select-main"> <div class="select-main">
<el-checkbox-group class="checkbox-group" v-model="activeAreaList" @change="handleAreaChange"> <el-checkbox-group class="checkbox-group" v-model="activeAreaList" @change="handleAreaChange">
<el-checkbox class="filter-checkbox" label="全部领域"> <el-checkbox class="filter-checkbox" label="全部领域"> 全部领域 </el-checkbox>
全部领域
</el-checkbox>
<el-checkbox <el-checkbox
v-for="(area, index) in cateKuList" v-for="(area, index) in cateKuList"
:key="area.id" :key="area.id"
...@@ -549,7 +595,12 @@ ...@@ -549,7 +595,12 @@
<div class="right"> <div class="right">
<div class="right-header"> <div class="right-header">
<div class="right-header-box"> <div class="right-header-box">
<el-select v-model="footerSelect1" placeholder="选择委员会" style="width: 240px" @change="handleFooterSelect1Change"> <el-select
v-model="footerSelect1"
placeholder="选择委员会"
style="width: 240px"
@change="handleFooterSelect1Change"
>
<el-option <el-option
v-for="item in postOrgList" v-for="item in postOrgList"
:key="item.departmentId" :key="item.departmentId"
...@@ -559,7 +610,12 @@ ...@@ -559,7 +610,12 @@
</el-select> </el-select>
</div> </div>
<div class="right-header-box"> <div class="right-header-box">
<el-select v-model="footerSelect2" placeholder="选择提出议员" style="width: 240px" @change="handleFooterSelect2Change"> <el-select
v-model="footerSelect2"
placeholder="选择提出议员"
style="width: 240px"
@change="handleFooterSelect2Change"
>
<el-option <el-option
v-for="item in postMemberList" v-for="item in postMemberList"
:key="item.memberId" :key="item.memberId"
...@@ -568,8 +624,13 @@ ...@@ -568,8 +624,13 @@
/> />
</el-select> </el-select>
</div> </div>
<div class="right-header-box" style="margin-left: auto;"> <div class="right-header-box" style="margin-left: auto">
<el-select v-model="releaseTime" placeholder="选择排序方式" style="width: 120px" @change="handlePxChange"> <el-select
v-model="releaseTime"
placeholder="选择排序方式"
style="width: 120px"
@change="handlePxChange"
>
<el-option <el-option
v-for="item in releaseTimeList" v-for="item in releaseTimeList"
:key="item.value" :key="item.value"
...@@ -580,7 +641,12 @@ ...@@ -580,7 +641,12 @@
</div> </div>
</div> </div>
<div class="right-main" v-loading="loading"> <div class="right-main" v-loading="loading">
<div class="right-main-box" v-for="(item, index) in bills" :key="index" @click="handleClickToDetail()"> <div
class="right-main-box"
v-for="(item, index) in bills"
:key="index"
@click="handleClickToDetailO(item)"
>
<div class="header"> <div class="header">
<div class="title">{{ item.name }}</div> <div class="title">{{ item.name }}</div>
<div class="en-title">{{ item.eName }}</div> <div class="en-title">{{ item.eName }}</div>
...@@ -610,7 +676,6 @@ ...@@ -610,7 +676,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="right-footer"> <div class="right-footer">
<div class="footer-left"> <div class="footer-left">
{{ `共${total}项调查` }} {{ `共${total}项调查` }}
...@@ -631,6 +696,7 @@ ...@@ -631,6 +696,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script setup> <script setup>
...@@ -707,20 +773,21 @@ import { iteratee } from "lodash"; ...@@ -707,20 +773,21 @@ import { iteratee } from "lodash";
const searchBillText = ref(""); const searchBillText = ref("");
const formatMessageTime = (timeStr) => { const formatMessageTime = timeStr => {
if (!timeStr) return ''; if (!timeStr) return "";
// 假设格式为 2025-11-02T12:09:45 // 假设格式为 2025-11-02T12:09:45
if (timeStr.includes('T')) { if (timeStr.includes("T")) {
const [date, time] = timeStr.split('T'); const [date, time] = timeStr.split("T");
const [year, month, day] = date.split('-'); const [year, month, day] = date.split("-");
const [hour, minute] = time.split(':'); const [hour, minute] = time.split(":");
return `${year}-${month}-${day} ${hour}:${minute}`; return `${year}-${month}-${day} ${hour}:${minute}`;
} }
return timeStr; return timeStr;
}; };
// 跳转人物主页 // 跳转人物主页
const handleClcikToCharacter = index => { const handleClcikToCharacter = (item, index) => {
window.sessionStorage.setItem("memberId", item.memberId);
let type; let type;
if (index === 0) { if (index === 0) {
type = 2; type = 2;
...@@ -757,23 +824,22 @@ const { isShow } = useContainerScroll(containerRef); ...@@ -757,23 +824,22 @@ const { isShow } = useContainerScroll(containerRef);
const hotBillList = ref([]); // 热门法案列表 const hotBillList = ref([]); // 热门法案列表
const curHotBillListIndex = ref(0); // 当前热门法案索引 const curHotBillListIndex = ref(0); // 当前热门法案索引
const carouselRef = ref(null);
const handleCarouselChange = index => {
curHotBillListIndex.value = index;
if (hotBillList.value && hotBillList.value.length > 0) {
curBill.value = hotBillList.value[index];
}
};
// 切换热门法案 // 切换热门法案
const handleSwithCurBill = name => { const handleSwithCurBill = name => {
if (name === "left") { if (name === "left") {
if (curHotBillListIndex.value === 0) { carouselRef.value.prev();
curHotBillListIndex.value = hotBillList.value.length - 1;
} else {
curHotBillListIndex.value--;
}
} else { } else {
if (curHotBillListIndex.value === hotBillList.value.length - 1) { carouselRef.value.next();
curHotBillListIndex.value = 0;
} else {
curHotBillListIndex.value++;
}
} }
curBill.value = hotBillList.value[curHotBillListIndex.value];
}; };
// 当前法案 // 当前法案
...@@ -788,9 +854,13 @@ const curBill = ref({ ...@@ -788,9 +854,13 @@ const curBill = ref({
// 查看详情 // 查看详情
const handleClickToDetail = () => { const handleClickToDetail = () => {
// window.sessionStorage.setItem("billId", curBill.value.billId); window.sessionStorage.setItem("billId", curBill.value.billId);
window.sessionStorage.setItem("billId", "119_HR_1"); const route = router.resolve("/billLayout");
// router.push("/billLayout"); window.open(route.href, "_blank");
};
// 查看详情 传递参数
const handleClickToDetailO = item => {
window.sessionStorage.setItem("billId", item.billId);
const route = router.resolve("/billLayout"); const route = router.resolve("/billLayout");
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
...@@ -1001,7 +1071,6 @@ const categoryList = ref([]); ...@@ -1001,7 +1071,6 @@ const categoryList = ref([]);
// 资源库使用的领域分类列表 // 资源库使用的领域分类列表
const cateKuList = ref([]); const cateKuList = ref([]);
// 获取领域分类 // 获取领域分类
const handleGetHylyList = async () => { const handleGetHylyList = async () => {
try { try {
...@@ -1078,10 +1147,7 @@ const handleGetPostOrgList = async () => { ...@@ -1078,10 +1147,7 @@ const handleGetPostOrgList = async () => {
console.log("提出部门列表", res); console.log("提出部门列表", res);
if (res.code === 200) { if (res.code === 200) {
const list = res.data.filter(item => item.departmentId); const list = res.data.filter(item => item.departmentId);
postOrgList.value = [ postOrgList.value = [{ departmentName: "全部委员会", departmentId: "全部委员会" }, ...list];
{ departmentName: "全部委员会", departmentId: "全部委员会" },
...list
];
} }
} catch (error) {} } catch (error) {}
}; };
...@@ -1094,10 +1160,7 @@ const handleGetPostMemberList = async () => { ...@@ -1094,10 +1160,7 @@ const handleGetPostMemberList = async () => {
console.log("提出议员列表", res); console.log("提出议员列表", res);
if (res.code === 200) { if (res.code === 200) {
const list = res.data.filter(item => item.memberId); const list = res.data.filter(item => item.memberId);
postMemberList.value = [ postMemberList.value = [{ memberName: "全部提出议员", memberId: "全部提出议员" }, ...list];
{ memberName: "全部提出议员", memberId: "全部提出议员" },
...list
];
} }
} catch (error) {} } catch (error) {}
}; };
...@@ -1124,25 +1187,25 @@ const handleGetBills = async () => { ...@@ -1124,25 +1187,25 @@ const handleGetBills = async () => {
}; };
if (!activeYyList.value.includes("全部议院")) { if (!activeYyList.value.includes("全部议院")) {
params.congressIds = activeYyList.value.join(','); params.congressIds = activeYyList.value.join(",");
} }
if (footerSelect1.value !== "全部委员会") { if (footerSelect1.value !== "全部委员会") {
params.departmentId = footerSelect1.value; params.departmentId = footerSelect1.value;
} }
if (!activeDpList.value.includes("全部党派")) { if (!activeDpList.value.includes("全部党派")) {
params.partyIds = activeDpList.value.join(','); params.partyIds = activeDpList.value.join(",");
} }
if (footerSelect2.value !== "全部提出议员") { if (footerSelect2.value !== "全部提出议员") {
params.personId = footerSelect2.value; params.personId = footerSelect2.value;
} }
if (!activeAreaList.value.includes("全部领域")) { if (!activeAreaList.value.includes("全部领域")) {
params.researchIds = activeAreaList.value.join(','); params.researchIds = activeAreaList.value.join(",");
} }
if (releaseTime.value !== true) { if (releaseTime.value !== true) {
params.sortFun = releaseTime.value; params.sortFun = releaseTime.value;
} }
if (!activePubTime.value.includes("全部时间")) { if (!activePubTime.value.includes("全部时间")) {
params.years = activePubTime.value.join(','); params.years = activePubTime.value.join(",");
} }
try { try {
...@@ -1151,7 +1214,7 @@ const handleGetBills = async () => { ...@@ -1151,7 +1214,7 @@ const handleGetBills = async () => {
if (res.code === 200) { if (res.code === 200) {
if (res.data && res.data.content) { if (res.data && res.data.content) {
bills.value = res.data.content.map(item => ({ bills.value = res.data.content.map(item => ({
// id: item.billId, billId: item.billId,
name: item.billName, name: item.billName,
eName: item.billNameEn, eName: item.billNameEn,
tcr: item.personName, tcr: item.personName,
...@@ -1165,13 +1228,13 @@ const handleGetBills = async () => { ...@@ -1165,13 +1228,13 @@ const handleGetBills = async () => {
bills.value = []; bills.value = [];
total.value = 0; total.value = 0;
} }
}else { } else {
bills.value = []; bills.value = [];
total.value = 0; total.value = 0;
} }
loading.value = false; loading.value = false;
} catch (error) { } catch (error) {
if (error.name !== 'AbortError') { if (error.name !== "AbortError") {
console.error(error); console.error(error);
loading.value = false; loading.value = false;
} }
...@@ -1179,19 +1242,19 @@ const handleGetBills = async () => { ...@@ -1179,19 +1242,19 @@ const handleGetBills = async () => {
}; };
// 处理选择委员会变化 // 处理选择委员会变化
const handleFooterSelect1Change = (val) => { const handleFooterSelect1Change = val => {
console.log("选择委员会变化", val); console.log("选择委员会变化", val);
// 等会再做处理 // 等会再做处理
handleGetBills(); handleGetBills();
}; };
// 处理选择议员变化 // 处理选择议员变化
const handleFooterSelect2Change = (val) => { const handleFooterSelect2Change = val => {
console.log("选择议员变化", val); console.log("选择议员变化", val);
// 等会再做处理 // 等会再做处理
handleGetBills(); handleGetBills();
}; };
// 处理选择排序方式变化 // 处理选择排序方式变化
const handlePxChange = (val) => { const handlePxChange = val => {
console.log("选择排序方式变化", val); console.log("选择排序方式变化", val);
// 等会再做处理 // 等会再做处理
handleGetBills(); handleGetBills();
...@@ -1303,7 +1366,9 @@ const handleBox5 = async () => { ...@@ -1303,7 +1366,9 @@ const handleBox5 = async () => {
await nextTick(); await nextTick();
const proposed = box5Data.value.data[0].value; const proposed = box5Data.value.data[0].value;
const passed = box5Data.value.data[1].value; const passed = box5Data.value.data[1].value;
const rate = box5Data.value.percent || proposed.map((p, i) => { const rate =
box5Data.value.percent ||
proposed.map((p, i) => {
const pass = passed[i] || 0; const pass = passed[i] || 0;
return p ? ((pass / p) * 100).toFixed(2) : 0; return p ? ((pass / p) * 100).toFixed(2) : 0;
}); });
...@@ -1459,6 +1524,7 @@ const handleBox8Data = async () => { ...@@ -1459,6 +1524,7 @@ const handleBox8Data = async () => {
console.log("关键议员提案", res); console.log("关键议员提案", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box8Data.value = res.data.map(item => ({ box8Data.value = res.data.map(item => ({
memberId: item.memberId,
name: item.memberName, name: item.memberName,
zhiwei: item.position, zhiwei: item.position,
img: item.imageUrl, img: item.imageUrl,
...@@ -1522,7 +1588,7 @@ const handleClickTab = tab => { ...@@ -1522,7 +1588,7 @@ const handleClickTab = tab => {
}; };
const activeAreaList = ref(["全部领域"]); const activeAreaList = ref(["全部领域"]);
const handleAreaChange = (val) => { const handleAreaChange = val => {
if (val.includes("全部领域") && val.length > 1) { if (val.includes("全部领域") && val.length > 1) {
if (val[val.length - 1] === "全部领域") { if (val[val.length - 1] === "全部领域") {
activeAreaList.value = ["全部领域"]; activeAreaList.value = ["全部领域"];
...@@ -1544,7 +1610,7 @@ const dpList = ref([ ...@@ -1544,7 +1610,7 @@ const dpList = ref([
]); ]);
const activeDpList = ref(["全部党派"]); const activeDpList = ref(["全部党派"]);
// 处理选择党派变化 // 处理选择党派变化
const handleDpChange = (val) => { const handleDpChange = val => {
if (val.includes("全部党派") && val.length > 1) { if (val.includes("全部党派") && val.length > 1) {
if (val[val.length - 1] === "全部党派") { if (val[val.length - 1] === "全部党派") {
activeDpList.value = ["全部党派"]; activeDpList.value = ["全部党派"];
...@@ -1565,7 +1631,7 @@ const yyList = ref([ ...@@ -1565,7 +1631,7 @@ const yyList = ref([
]); ]);
const activeYyList = ref(["全部议院"]); const activeYyList = ref(["全部议院"]);
// 处理选择议院变化 // 处理选择议院变化
const handleYyChange = (val) => { const handleYyChange = val => {
if (val.includes("全部议院") && val.length > 1) { if (val.includes("全部议院") && val.length > 1) {
if (val[val.length - 1] === "全部议院") { if (val[val.length - 1] === "全部议院") {
activeYyList.value = ["全部议院"]; activeYyList.value = ["全部议院"];
...@@ -1585,12 +1651,12 @@ const pubTime = ref([ ...@@ -1585,12 +1651,12 @@ const pubTime = ref([
{ id: "2024", name: "2024年" }, { id: "2024", name: "2024年" },
{ id: "2023", name: "2023年" }, { id: "2023", name: "2023年" },
{ id: "2022", name: "2022年" }, { id: "2022", name: "2022年" },
{ id: "2021", name: "2021年" }, { id: "2021", name: "2021年" }
// { id: "更早时间", name: "更早时间" } // { id: "更早时间", name: "更早时间" }
]); ]);
const activePubTime = ref(["全部时间"]); const activePubTime = ref(["全部时间"]);
// 处理选择时间变化 // 处理选择时间变化
const handlePubTimeChange = (val) => { const handlePubTimeChange = val => {
if (val.includes("全部时间") && val.length > 1) { if (val.includes("全部时间") && val.length > 1) {
if (val[val.length - 1] === "全部时间") { if (val[val.length - 1] === "全部时间") {
activePubTime.value = ["全部时间"]; activePubTime.value = ["全部时间"];
...@@ -1782,6 +1848,8 @@ onUnmounted(() => {}); ...@@ -1782,6 +1848,8 @@ onUnmounted(() => {});
.home-box { .home-box {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: url("./assets/images/background.png");
background-size: 100% 100%;
overflow-y: auto; overflow-y: auto;
.home-header { .home-header {
height: 64px; height: 64px;
...@@ -1809,8 +1877,6 @@ onUnmounted(() => {}); ...@@ -1809,8 +1877,6 @@ onUnmounted(() => {});
width: 1600px; width: 1600px;
margin: 0 auto; margin: 0 auto;
margin-top: 48px; margin-top: 48px;
background: url("./assets/images/background.png");
background-size: 100% 100%;
.home-main-header { .home-main-header {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -1959,6 +2025,7 @@ onUnmounted(() => {}); ...@@ -1959,6 +2025,7 @@ onUnmounted(() => {});
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
z-index: 10;
.icon { .icon {
width: 11px; width: 11px;
height: 18px; height: 18px;
...@@ -1979,6 +2046,7 @@ onUnmounted(() => {}); ...@@ -1979,6 +2046,7 @@ onUnmounted(() => {});
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
z-index: 10;
.icon { .icon {
width: 11px; width: 11px;
height: 18px; height: 18px;
...@@ -2722,7 +2790,7 @@ onUnmounted(() => {}); ...@@ -2722,7 +2790,7 @@ onUnmounted(() => {});
} }
.box5-select { .box5-select {
position: absolute; position: absolute;
top: 50px; top: 53px;
left: 100px; left: 100px;
z-index: 100; z-index: 100;
} }
......
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
<div class="layout-main-header-left-box"> <div class="layout-main-header-left-box">
<div class="left-box-top"> <div class="left-box-top">
<div class="icon"> <div class="icon">
<img src="./assets/images/USA-logo.png" alt="" /> <img :src="billInfoGlobal.imageUrl || USALogo" alt="" />
</div> </div>
<div class="info"> <div class="info">
<div class="info-box1">{{ "H.R.1(119th)-大而美法案" }}</div> <div class="info-box1">{{ billInfoGlobal.billName }}</div>
<div class="info-box2"> <div class="info-box2">
{{ "第119届美国国会众议院第1号法案 One Big Beautiful Bill Act" }} {{ billInfoGlobal.description }} {{ billInfoGlobal.billNameEn }}
</div> </div>
</div> </div>
</div> </div>
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
</div> </div>
<div class="layout-main-header-right-box"> <div class="layout-main-header-right-box">
<div class="right-box-top"> <div class="right-box-top">
<div class="time">{{ "2025年7月" }}</div> <div class="time">{{ billInfoGlobal.introductionDate }}</div>
<div class="name">{{ "乔迪·阿灵顿(Jodey Arrington)​​ " }}</div> <div class="name">{{ billInfoGlobal.tarName }}</div>
</div> </div>
<div class="right-box-bottom"> <div class="right-box-bottom">
<!-- <el-button type="plain" size="large" icon="Search" @click="handleSwitchActiveName('法案原文')" <!-- <el-button type="plain" size="large" icon="Search" @click="handleSwitchActiveName('法案原文')"
...@@ -135,6 +135,7 @@ ...@@ -135,6 +135,7 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import router from "@/router"; import router from "@/router";
import { getBillInfoGlobal } from "@/api/bill";
import icon1 from "./assets/icons/icon1.png"; import icon1 from "./assets/icons/icon1.png";
import icon1Active from "./assets/icons/icon1_active.png"; import icon1Active from "./assets/icons/icon1_active.png";
...@@ -144,9 +145,24 @@ import icon3 from "./assets/icons/icon3.png"; ...@@ -144,9 +145,24 @@ import icon3 from "./assets/icons/icon3.png";
import icon3Active from "./assets/icons/icon3_active.png"; import icon3Active from "./assets/icons/icon3_active.png";
import icon4 from "./assets/icons/icon4.png"; import icon4 from "./assets/icons/icon4.png";
import icon4Active from "./assets/icons/icon4_active.png"; import icon4Active from "./assets/icons/icon4_active.png";
import USALogo from "./assets/images/USA-logo.png";
const activeName = ref("分析报告"); const activeName = ref("分析报告");
// 获取法案全局信息
const billInfoGlobal = ref({});
const getBillInfoGlobalFn = async () => {
const res = await getBillInfoGlobal({
id: window.sessionStorage.getItem("billId")
});
if (res.code === 200) {
console.log("法案全局信息", res);
if (res.data) {
billInfoGlobal.value = res.data;
}
}
};
const handleSwitchActiveName = name => { const handleSwitchActiveName = name => {
activeName.value = name; activeName.value = name;
}; };
...@@ -200,6 +216,7 @@ const handleClickMainHeaderBtn = item => { ...@@ -200,6 +216,7 @@ const handleClickMainHeaderBtn = item => {
}; };
onMounted(() => { onMounted(() => {
getBillInfoGlobalFn();
if (window.sessionStorage.getItem("activeTitle")) { if (window.sessionStorage.getItem("activeTitle")) {
activeTitle.value = window.sessionStorage.getItem("activeTitle"); activeTitle.value = window.sessionStorage.getItem("activeTitle");
} }
...@@ -377,7 +394,7 @@ onMounted(() => { ...@@ -377,7 +394,7 @@ onMounted(() => {
margin-left: 9px; margin-left: 9px;
.info-box1 { .info-box1 {
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: "Microsoft YaHei";
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
line-height: 22px; line-height: 22px;
...@@ -387,16 +404,20 @@ onMounted(() => { ...@@ -387,16 +404,20 @@ onMounted(() => {
} }
.info-box2 { .info-box2 {
margin-top: 5px; margin-top: 5px;
height: 22px; // height: 22px;
line-height: 22px; line-height: 22px;
color: rgba(132, 136, 142, 1); color: rgba(132, 136, 142, 1);
font-family: "Microsoft YaHei";
font-family: Microsoft YaHei;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 22px; line-height: 22px;
letter-spacing: 0px; letter-spacing: 0px;
text-align: left; text-align: left;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
} }
} }
} }
......
...@@ -1092,6 +1092,19 @@ onMounted(async () => { ...@@ -1092,6 +1092,19 @@ onMounted(async () => {
.dialog-box1-main { .dialog-box1-main {
margin-top: 4px; margin-top: 4px;
margin-left: 18px; margin-left: 18px;
max-height: 120px;
overflow-y: auto;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(0, 0, 0, 0.2);
}
&::-webkit-scrollbar-track {
border-radius: 0;
background: rgba(0, 0, 0, 0.1);
}
.item { .item {
display: flex; display: flex;
.item-left { .item-left {
...@@ -1107,13 +1120,16 @@ onMounted(async () => { ...@@ -1107,13 +1120,16 @@ onMounted(async () => {
.item-right { .item-right {
margin-top: 8px; margin-top: 8px;
margin-left: 9px; margin-left: 9px;
width: 420px; width: 400px;
height: 22px; height: 22px;
color: rgba(132, 136, 142, 1); color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 22px; line-height: 22px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
} }
} }
......
...@@ -106,7 +106,7 @@ ...@@ -106,7 +106,7 @@
<div class="home-main-header-item-box"> <div class="home-main-header-item-box">
<div class="item" v-for="(item, index) in govInsList" :key="index" @click="handleToInstitution(item)"> <div class="item" v-for="(item, index) in govInsList" :key="index" @click="handleToInstitution(item)">
<div class="item-left"> <div class="item-left">
<img :src="item.img?item.img: DefaultIcon2" alt="" /> <img :src="item.img ? item.img : DefaultIcon2" alt="" />
</div> </div>
<div class="item-right">{{ item.name }}</div> <div class="item-right">{{ item.name }}</div>
</div> </div>
...@@ -116,16 +116,16 @@ ...@@ -116,16 +116,16 @@
<div class="home-main-center"> <div class="home-main-center">
<div class="center-top"> <div class="center-top">
<div class="box1"> <div class="box1">
<!-- <div class="box1-left"> <div class="box1-left" @click="handleSwithCurDecree('left')">
<div class="icon"> <div class="icon">
<img src="./assets/images/box1-left.png" alt="" /> <img src="./assets/images/box1-left.png" alt="" />
</div> </div>
</div> </div>
<div class="box1-right"> <div class="box1-right" @click="handleSwithCurDecree('right')">
<div class="icon"> <div class="icon">
<img src="./assets/images/box1-right.png" alt="" /> <img src="./assets/images/box1-right.png" alt="" />
</div> </div>
</div> --> </div>
<div class="box1-header"> <div class="box1-header">
<div class="box1-header-left"> <div class="box1-header-left">
<div class="icon"> <div class="icon">
...@@ -137,7 +137,14 @@ ...@@ -137,7 +137,14 @@
{{ "查看详情 >" }} {{ "查看详情 >" }}
</div> </div>
</div> </div>
<el-carousel ref="carouselRef" trigger="click" height="395px" :autoplay="true"> <el-carousel
ref="carouselRef"
height="395px"
:autoplay="true"
:interval="3000"
arrow="never"
indicator-position="none"
>
<el-carousel-item v-for="(item, index) in box1DataList" :key="index"> <el-carousel-item v-for="(item, index) in box1DataList" :key="index">
<div class="box1-main"> <div class="box1-main">
<div class="box1-main-left"> <div class="box1-main-left">
...@@ -335,7 +342,6 @@ ...@@ -335,7 +342,6 @@
<DivideHeader id="position4" class="divide4" :titleText="'资源库'"></DivideHeader> <DivideHeader id="position4" class="divide4" :titleText="'资源库'"></DivideHeader>
<div class="home-main-footer-header"> <div class="home-main-footer-header">
<div class="btn-box"> <div class="btn-box">
<div <div
class="btn" class="btn"
:class="{ btnActive: activeCate === cate.id }" :class="{ btnActive: activeCate === cate.id }"
...@@ -345,7 +351,6 @@ ...@@ -345,7 +351,6 @@
> >
{{ cate.name }} {{ cate.name }}
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
<div class="paixu-btn" @click="handleSwithSort"> <div class="paixu-btn" @click="handleSwithSort">
...@@ -375,6 +380,7 @@ ...@@ -375,6 +380,7 @@
:key="time.id" :key="time.id"
v-model="activePubTime" v-model="activePubTime"
:label="time.id" :label="time.id"
style="width: 100px"
class="filter-checkbox" class="filter-checkbox"
> >
{{ time.name }} {{ time.name }}
...@@ -414,13 +420,13 @@ ...@@ -414,13 +420,13 @@
class="main-item" class="main-item"
v-for="(item, index) in curDecreeList" v-for="(item, index) in curDecreeList"
:key="index" :key="index"
@click="handleClickToDetail" @click="handleClickDecree(item)"
> >
<div class="main-item-left"> <div class="main-item-left">
<div class="left-left">{{ item.time }}</div> <div class="left-left">{{ item.time }}</div>
<div class="left-right"> <div class="left-right">
<div class="icon"> <div class="icon">
<img :src="item.orgImage?item.orgImage:DefaultIcon2" alt=""> <img :src="item.orgImage ? item.orgImage : DefaultIcon2" alt="" />
</div> </div>
<div class="line" v-if="index !== 9 && index !== totalDecreesNum - 1"></div> <div class="line" v-if="index !== 9 && index !== totalDecreesNum - 1"></div>
</div> </div>
...@@ -497,8 +503,8 @@ import getCalendarHeatChart from "./utils/cleandarHeat"; ...@@ -497,8 +503,8 @@ import getCalendarHeatChart from "./utils/cleandarHeat";
import setChart from "@/utils/setChart"; import setChart from "@/utils/setChart";
import DefaultIcon1 from '@/assets/icons/default-icon1.png' 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 p1 from "./assets/images/iconp1.png"; import p1 from "./assets/images/iconp1.png";
import p2 from "./assets/images/iconp2.png"; import p2 from "./assets/images/iconp2.png";
...@@ -534,10 +540,8 @@ import Message3 from "./assets/images/message-icon3.png"; ...@@ -534,10 +540,8 @@ import Message3 from "./assets/images/message-icon3.png";
// 跳转行政机构主页 // 跳转行政机构主页
const handleToInstitution = item => { const handleToInstitution = item => {
if (item.name === "美国商务部") {
const curRoute = router.resolve("/institution"); const curRoute = router.resolve("/institution");
window.open(curRoute.href, "_blank"); window.open(curRoute.href, "_blank");
}
}; };
// 返回首页 // 返回首页
...@@ -689,6 +693,17 @@ const handleClickToDetail = () => { ...@@ -689,6 +693,17 @@ const handleClickToDetail = () => {
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
// 点击政令库政令
const handleClickDecree = decree => {
const route = router.resolve({
path: "/decreeLayout",
query: {
id: decree.id
}
});
window.open(route.href, "_blank");
};
// 风险信号 // 风险信号
const warningList = ref([ const warningList = ref([
{ {
...@@ -780,7 +795,6 @@ const messageList = ref([ ...@@ -780,7 +795,6 @@ const messageList = ref([
// time: "14:49 · 发布于X", // time: "14:49 · 发布于X",
// content: `如果这个疯狂的支出法案获得通过,‘美国党’将在第二天成立。` // content: `如果这个疯狂的支出法案获得通过,‘美国党’将在第二天成立。`
// } // }
]); ]);
const handleGetMessage = async () => { const handleGetMessage = async () => {
const params = { const params = {
...@@ -854,7 +868,6 @@ const chart2Data = ref([ ...@@ -854,7 +868,6 @@ const chart2Data = ref([
// name: "人工智能", // name: "人工智能",
// value: 46 // value: 46
// }, // },
]); ]);
// const colorList = ["#69B1FF", "#FFC069", "#87E8DE", "#85A5FF", "#FF7875", "#B37FEB", "#4096FF"]; // const colorList = ["#69B1FF", "#FFC069", "#87E8DE", "#85A5FF", "#FF7875", "#B37FEB", "#4096FF"];
...@@ -892,7 +905,6 @@ const keyDecreeList = ref([ ...@@ -892,7 +905,6 @@ const keyDecreeList = ref([
// time: "2025年2月", // time: "2025年2月",
// content: `将中国列为“外国对手”,系统性收紧中美在半导体、人工智能、量子技术等前沿科技领域的双向投资,构建对华科技封锁体系。` // content: `将中国列为“外国对手”,系统性收紧中美在半导体、人工智能、量子技术等前沿科技领域的双向投资,构建对华科技封锁体系。`
// }, // },
]); ]);
const handleGetKeyDecree = async () => { const handleGetKeyDecree = async () => {
...@@ -1111,6 +1123,15 @@ watch( ...@@ -1111,6 +1123,15 @@ watch(
} }
); );
// 切换当前政令
const handleSwithCurDecree = name => {
if (name === "left") {
carouselRef.value.prev();
} else {
carouselRef.value.next();
}
};
onMounted(async () => { onMounted(async () => {
handleGetAreaList(); handleGetAreaList();
handleGetDecreeOrderList(); handleGetDecreeOrderList();
...@@ -1447,6 +1468,7 @@ onMounted(async () => { ...@@ -1447,6 +1468,7 @@ onMounted(async () => {
position: relative; position: relative;
.box1-left { .box1-left {
position: absolute; position: absolute;
z-index: 9999;
left: 0; left: 0;
top: 200px; top: 200px;
width: 24px; width: 24px;
...@@ -1467,6 +1489,7 @@ onMounted(async () => { ...@@ -1467,6 +1489,7 @@ onMounted(async () => {
} }
.box1-right { .box1-right {
position: absolute; position: absolute;
z-index: 9999;
right: 0; right: 0;
top: 200px; top: 200px;
width: 24px; width: 24px;
...@@ -1857,7 +1880,7 @@ onMounted(async () => { ...@@ -1857,7 +1880,7 @@ onMounted(async () => {
height: 402px; height: 402px;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
padding-top: 6px; padding: 6px 0;
.box3-item { .box3-item {
display: flex; display: flex;
height: 77px; height: 77px;
...@@ -1967,7 +1990,7 @@ onMounted(async () => { ...@@ -1967,7 +1990,7 @@ onMounted(async () => {
height: 402px; height: 402px;
overflow-y: auto; overflow-y: auto;
box-sizing: border-box; box-sizing: border-box;
padding-top: 8px; padding-bottom: 8px;
.box4-main-item { .box4-main-item {
margin-top: 16px; margin-top: 16px;
display: flex; display: flex;
...@@ -2601,7 +2624,8 @@ onMounted(async () => { ...@@ -2601,7 +2624,8 @@ onMounted(async () => {
} }
} }
.box7-main { .box7-main {
height: 400px; margin-top: 10px;
height: 380px;
box-sizing: border-box; box-sizing: border-box;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
...@@ -2720,7 +2744,6 @@ onMounted(async () => { ...@@ -2720,7 +2744,6 @@ onMounted(async () => {
width: 1600px; width: 1600px;
height: 70px; height: 70px;
margin: 36px auto 16px; margin: 36px auto 16px;
// background: orange;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.btn-box { .btn-box {
...@@ -2731,6 +2754,7 @@ onMounted(async () => { ...@@ -2731,6 +2754,7 @@ onMounted(async () => {
display: flex; display: flex;
gap: 8px; gap: 8px;
white-space: nowrap; white-space: nowrap;
.btn { .btn {
min-width: min-content; min-width: min-content;
height: 42px; height: 42px;
...@@ -2756,7 +2780,6 @@ onMounted(async () => { ...@@ -2756,7 +2780,6 @@ onMounted(async () => {
background: rgba(20, 89, 187, 1); background: rgba(20, 89, 187, 1);
} }
} }
} }
.select-box { .select-box {
margin-top: 5px; margin-top: 5px;
...@@ -2903,7 +2926,8 @@ onMounted(async () => { ...@@ -2903,7 +2926,8 @@ onMounted(async () => {
gap: 18px; gap: 18px;
justify-content: flex-end; justify-content: flex-end;
.left-left { .left-left {
width: 84px; margin-left: 30px;
width: 54px;
height: 48px; height: 48px;
color: var(--color-main-active); color: var(--color-main-active);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
...@@ -2919,7 +2943,7 @@ onMounted(async () => { ...@@ -2919,7 +2943,7 @@ onMounted(async () => {
height: 24px; height: 24px;
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
img{ img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
......
[ [
{ {
"personImage": "https://www.congress.gov/img/member/y000064_200.jpg", "name": "美国",
"personName": "扬(Young, Todd)", "count": 0.37960339943342775
"remarks": "拜登打心底里厌恶美国的石油和天然气产业,他的一系列政策,正在摧毁这个能为美国创造大量就业岗位的重要领域。",
"time": "2025-04-12T03:27:07",
"orgName": "推特"
}, },
{ {
"personImage": "https://www.congress.gov/img/member/k000306_200.jpg", "name": "德国",
"personName": "科尔贝 (Kolbe), 吉姆 (Jim)", "count": 0.20113314447592068
"remarks": "美国将控制加沙地带,我们会把这片被战火摧毁的区域改造成 “中东的里维埃拉”,这一计划会为当地带来全新未来。", },
"time": "2025-01-12T00:55:53", {
"orgName": "推特" "name": "日本",
"count": 0.1558073654390935
} }
] ]
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="fishbone-wrapper"> <div class="fishbone-wrapper">
<div class="fishbone-scroll-container" ref="scrollContainerRef"> <div class="fishbone-scroll-container" ref="scrollContainerRef">
<div class="fishbone" ref="fishboneRef" v-if="fishboneData.length > 0"> <div class="fishbone" ref="fishboneRef" v-if="fishboneData.length > 0">
<div class="main-line" :style="{ width: (fishboneData.length / 2) * 340 - 275 + 'px' }"></div> <div class="main-line" :style="{ width: (fishboneData.length / 2) * 340 - 200 + 'px' }"></div>
<!-- 奇数索引的数据组放在上方 --> <!-- 奇数索引的数据组放在上方 -->
<div <div
v-for="(causeGroup, groupIndex) in getOddGroups(fishboneData)" v-for="(causeGroup, groupIndex) in getOddGroups(fishboneData)"
......
...@@ -99,6 +99,13 @@ import college9 from "../../assets/images/college9.png"; ...@@ -99,6 +99,13 @@ import college9 from "../../assets/images/college9.png";
import college10 from "../../assets/images/college10.png"; import college10 from "../../assets/images/college10.png";
import college11 from "../../assets/images/college11.png"; import college11 from "../../assets/images/college11.png";
import { getHorizontalBarChart1, getPieOption2, getMultipleLineChart } from "../../utils/charts"; import { getHorizontalBarChart1, getPieOption2, getMultipleLineChart } from "../../utils/charts";
import {
getScientificImpactEntityList,
getScientificInstrumentDependencyCount,
getScientificInstrumentDependencyRisk,
getScientificInstrumentLocalizationRisk,
getScientificInstrumentOriginCount
} from "@/api/exportControl";
const selectOptions = [ const selectOptions = [
{ {
value: 1, value: 1,
...@@ -170,39 +177,153 @@ const horizontalBarOptions = shallowRef({}); ...@@ -170,39 +177,153 @@ const horizontalBarOptions = shallowRef({});
const pieOptions2 = shallowRef({}); const pieOptions2 = shallowRef({});
const multipleLineOptions1 = shallowRef({}); const multipleLineOptions1 = shallowRef({});
const multipleLineOptions2 = shallowRef({}); const multipleLineOptions2 = shallowRef({});
onMounted(() => { // 获取仪器对美依赖度升高风险分析数据
horizontalBarOptions.value = getHorizontalBarChart1( const fetchDependencyRiskData = async () => {
["地球探测仪器", "计算机及其配套设备", "天文仪器", "分析仪器", "核仪器", "物理性能测试仪器", "医学科研仪器"], try {
[10, 10, 21, 25, 79, 95, 109], const data = await getScientificInstrumentDependencyRisk();
false if (data && data.instrumentCountList && Array.isArray(data.instrumentCountList)) {
); // 提取年份数据(去重并排序)
pieOptions2.value = getPieOption2([ const allYears = [...new Set(data.instrumentCountList.flatMap(item => item.countList.map(c => c.year)))].sort();
{ name: "美国", value: 27 },
{ name: "日本", value: 22 }, // 转换数据格式以适应 getMultipleLineChart
{ name: "德国", value: 18 }, const chartData = data.instrumentCountList.map(item => {
{ name: "英国", value: 15 }, // 为每个仪器类型创建完整的年份数据序列
{ name: "韩国", value: 12 }, const values = allYears.map(year => {
{ name: "荷兰", value: 8 }, const yearData = item.countList.find(c => c.year === year);
{ name: "其他", value: 7 } return yearData ? yearData.count : 0;
]); });
return {
name: item.name,
value: values
};
});
// 使用 getMultipleLineChart 生成图表配置
multipleLineOptions1.value = getMultipleLineChart({ multipleLineOptions1.value = getMultipleLineChart({
dates: ["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"], dates: allYears.map(String), // 转换为字符串以匹配原数据格式
data: [ data: chartData
{ name: "电子测量仪器", value: [45, 35, 25, 20, 20, 14, 15, 15, 23, 21] },
{ name: "分析仪器", value: [35, 33, 24, 21, 22, 18, 13, 19, 21, 31] },
{ name: "工艺试验仪器", value: [32, 22, 12, 11, 14, 15, 17, 13, 12, 26] },
{ name: "核仪器", value: [48, 38, 28, 28, 28, 18, 18, 18, 28, 28] }
]
}); });
}
} catch (error) {
console.error("获取仪器对美依赖度升高风险分析数据失败:", error);
}
};
// 获取仪器国产化降低风险分析数据
const fetchLocalizationRiskData = async () => {
try {
const data = await getScientificInstrumentLocalizationRisk();
if (data && data.instrumentCountList && Array.isArray(data.instrumentCountList)) {
// 提取年份数据(去重并排序)
const allYears = [...new Set(data.instrumentCountList.flatMap(item => item.countList.map(c => c.year)))].sort();
// 转换数据格式以适应 getMultipleLineChart
const chartData = data.instrumentCountList.map(item => {
// 为每个仪器类型创建完整的年份数据序列
const values = allYears.map(year => {
const yearData = item.countList.find(c => c.year === year);
return yearData ? yearData.count : 0;
});
return {
name: item.name,
value: values
};
});
// 使用 getMultipleLineChart 生成图表配置
multipleLineOptions2.value = getMultipleLineChart({ multipleLineOptions2.value = getMultipleLineChart({
dates: ["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"], dates: allYears.map(String), // 转换为字符串以匹配原数据格式
data: [ data: chartData
{ name: "电子测量仪器", value: [45, 35, 25, 20, 20, 14, 15, 15, 23, 21] },
{ name: "分析仪器", value: [35, 33, 24, 21, 22, 18, 13, 19, 21, 31] },
{ name: "工艺试验仪器", value: [32, 22, 12, 11, 14, 15, 17, 13, 12, 26] },
{ name: "核仪器", value: [48, 38, 28, 28, 28, 18, 18, 18, 28, 28] }
]
}); });
}
} catch (error) {
console.error("获取仪器国产化降低风险分析数据失败:", error);
}
};
// 获取各类别仪器对美依赖情况数据
const fetchDependencyCountData = async () => {
try {
const data = await getScientificInstrumentDependencyCount();
if (data && Array.isArray(data)) {
// 按照 count 降序排列
const sortedData = data.sort((a, b) => a.count - b.count);
// 提取仪器名称和对应的计数
const names = sortedData.map(item => item.name);
const counts = sortedData.map(item => item.count);
// 使用 getHorizontalBarChart1 生成图表配置
horizontalBarOptions.value = getHorizontalBarChart1(names, counts, false);
}
} catch (error) {
console.error("获取各类别仪器对美依赖情况数据失败:", error);
}
};
// 获取仪器进口国可替代性分析数据
const fetchOriginCountData = async () => {
try {
const data = await getScientificInstrumentOriginCount();
if (data && Array.isArray(data)) {
// 转换数据格式以适应 getPieOption2
// 数据结构应该是 [{ name: "国家名", value: 数量 }]
const pieData = data.map(item => ({
name: item.name,
value: (item.count * 100).toFixed(1)
}));
// 使用 getPieOption2 生成图表配置
pieOptions2.value = getPieOption2(pieData);
}
} catch (error) {
console.error("获取仪器进口国可替代性分析数据失败:", error);
}
};
onMounted(async () => {
// horizontalBarOptions.value = getHorizontalBarChart1(
// ["地球探测仪器", "计算机及其配套设备", "天文仪器", "分析仪器", "核仪器", "物理性能测试仪器", "医学科研仪器"],
// [10, 10, 21, 25, 79, 95, 109],
// false
// );
// pieOptions2.value = getPieOption2([
// { name: "美国", value: 27 },
// { name: "日本", value: 22 },
// { name: "德国", value: 18 },
// { name: "英国", value: 15 },
// { name: "韩国", value: 12 },
// { name: "荷兰", value: 8 },
// { name: "其他", value: 7 }
// ]);
// multipleLineOptions1.value = getMultipleLineChart({
// dates: ["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
// data: [
// { name: "电子测量仪器", value: [45, 35, 25, 20, 20, 14, 15, 15, 23, 21] },
// { name: "分析仪器", value: [35, 33, 24, 21, 22, 18, 13, 19, 21, 31] },
// { name: "工艺试验仪器", value: [32, 22, 12, 11, 14, 15, 17, 13, 12, 26] },
// { name: "核仪器", value: [48, 38, 28, 28, 28, 18, 18, 18, 28, 28] }
// ]
// });
// multipleLineOptions2.value = getMultipleLineChart({
// dates: ["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
// data: [
// { name: "电子测量仪器", value: [45, 35, 25, 20, 20, 14, 15, 15, 23, 21] },
// { name: "分析仪器", value: [35, 33, 24, 21, 22, 18, 13, 19, 21, 31] },
// { name: "工艺试验仪器", value: [32, 22, 12, 11, 14, 15, 17, 13, 12, 26] },
// { name: "核仪器", value: [48, 38, 28, 28, 28, 18, 18, 18, 28, 28] }
// ]
// });
// 获取各类别仪器对美依赖情况数据
await fetchDependencyCountData();
// 获取仪器进口国可替代性分析数据
await fetchOriginCountData();
// 获取仪器对美依赖度升高风险分析数据
await fetchDependencyRiskData();
// 获取仪器国产化降低风险分析数据
await fetchLocalizationRiskData();
}); });
</script> </script>
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
<div class="listWrap"> <div class="listWrap">
<div class="item" v-for="(item, index) in listData" :key="index" @click="handleEttClick(item)"> <div class="item" v-for="(item, index) in listData" :key="index" @click="handleEttClick(item)">
<div class="index" :class="{ isTopTen: index < 10 }">{{ index + 1 }}</div> <div class="index" :class="{ isTopTen: index < 10 }">{{ index + 1 }}</div>
<div class="name">{{ item.name }}</div> <div class="name">{{ item.name || item.nameEn }}</div>
<div class="icon" :class="{ iconUp: item.isUp, iconDown: !item.isUp }"></div> <div class="icon" :class="{ iconUp: item.marketChange > 0, iconDown: item.marketChange < 0 }"></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -22,10 +22,13 @@ ...@@ -22,10 +22,13 @@
<Hint <Hint
text="法案核心意图在于通过税收优惠吸引制造业回流美国​,并在关键科技领域对中国进行遏制,限制中国获取先进技术、资本和市场渠道,从而延缓中国科技产业的发展速度。给半导体、新能源、人工智能等相关科技行业带来不小的短期压力。" text="法案核心意图在于通过税收优惠吸引制造业回流美国​,并在关键科技领域对中国进行遏制,限制中国获取先进技术、资本和市场渠道,从而延缓中国科技产业的发展速度。给半导体、新能源、人工智能等相关科技行业带来不小的短期压力。"
></Hint> ></Hint>
<div class="subPanel2-buttonlist" v-if="chainData.length > 0">
<ButtonList :list="chainData" :active-id="activeChainId" @click="setActiveChainId"></ButtonList>
</div>
<div class="chartsWrap"> <div class="chartsWrap">
<div class="right-main-content"> <div class="right-main-content">
<div class="right-main-content-main"> <div class="right-main-content-main">
<Fishbone :chainId="activeButtonId" /> <Fishbone :chainId="chainData.length > 0 ? activeChainId : activeButtonId" />
</div> </div>
<div class="right-main-content-footer"> <div class="right-main-content-footer">
<div class="footer-item1"> <div class="footer-item1">
...@@ -34,10 +37,13 @@ ...@@ -34,10 +37,13 @@
<img src="../../assets/images/warning.png" alt="" /> <img src="../../assets/images/warning.png" alt="" />
</div> </div>
<div class="text"> <div class="text">
{{ "中国企业45家(51.00%),受制裁3家(7.00%)" }} {{
`国内企业数据量${cnEntityOnChainData.upstreamInternalCount}家(${cnEntityOnChainData.upstreamInternalRate}%),受制裁${cnEntityOnChainData.upstreamEntityCount}家(${cnEntityOnChainData.upstreamEntityRate}%)`
}}
<!-- {{ "中国企业45家(51.00%),受制裁3家(7.00%)" }} -->
</div> </div>
</div> </div>
<div class="footer-item1-top">{{ "基础支撑" }}</div> <div class="footer-item1-top">{{ "上游" }}</div>
</div> </div>
<div class="footer-item2"> <div class="footer-item2">
<div class="footer-item2-bottom"> <div class="footer-item2-bottom">
...@@ -45,10 +51,13 @@ ...@@ -45,10 +51,13 @@
<img src="../../assets/images/warning.png" alt="" /> <img src="../../assets/images/warning.png" alt="" />
</div> </div>
<div class="text"> <div class="text">
{{ "中国企业45家(51.00%),受制裁3家(7.00%)" }} {{
`国内企业数据量${cnEntityOnChainData.midstreamInternalCount}家(${cnEntityOnChainData.midstreamInternalRate}%),受制裁${cnEntityOnChainData.midstreamEntityCount}家(${cnEntityOnChainData.midstreamEntityRate}%)`
}}
<!-- {{ "中国企业45家(51.00%),受制裁3家(7.00%)" }} -->
</div> </div>
</div> </div>
<div class="footer-item2-top">{{ "软件算法" }}</div> <div class="footer-item2-top">{{ "中游" }}</div>
</div> </div>
<div class="footer-item3"> <div class="footer-item3">
<div class="footer-item3-bottom"> <div class="footer-item3-bottom">
...@@ -56,10 +65,13 @@ ...@@ -56,10 +65,13 @@
<img src="../../assets/images/warning.png" alt="" /> <img src="../../assets/images/warning.png" alt="" />
</div> </div>
<div class="text"> <div class="text">
{{ "中国企业45家(51.00%),受制裁3家(7.00%)" }} {{
`国内企业数据量${cnEntityOnChainData.downstreamInternalCount}家(${cnEntityOnChainData.downstreamInternalRate}%),受制裁${cnEntityOnChainData.downstreamEntityCount}家(${cnEntityOnChainData.downstreamEntityRate}%)`
}}
<!-- {{ "中国企业45家(51.00%),受制裁3家(7.00%)" }} -->
</div> </div>
</div> </div>
<div class="footer-item3-top">{{ "行业应用" }}</div> <div class="footer-item3-top">{{ "下游" }}</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -77,7 +89,7 @@ import Hint from "./hint.vue"; ...@@ -77,7 +89,7 @@ import Hint from "./hint.vue";
import ButtonList from "@/components/buttonList/buttonList.vue"; import ButtonList from "@/components/buttonList/buttonList.vue";
import Fishbone from "./fishbone.vue"; import Fishbone from "./fishbone.vue";
import { getHorizontalBarChart2 } from "../../utils/charts"; import { getHorizontalBarChart2 } from "../../utils/charts";
import { getDomainDistribution, getChainEntities } from "@/api/exportControl"; import { getDomainDistribution, getChainEntities, getChainInfoByDomainId, getCnEntityOnChain } from "@/api/exportControl";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
...@@ -151,6 +163,78 @@ const handleEttClick = item => { ...@@ -151,6 +163,78 @@ const handleEttClick = item => {
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
// 处理点击事件
const handleChainClick = async chainId => {};
// 获取产业链信息数据
const chainData = ref([]);
const activeChainId = ref(chainData.value[0]?.id);
const setActiveChainId = id => {
activeChainId.value = id;
};
const fetchChainInfo = async () => {
try {
const data = await getChainInfoByDomainId(activeButtonId.value);
console.log("getChainInfoByDomainId", data);
if (data && Array.isArray(data)) {
// 将获取到的数据赋值给 chainData
chainData.value = data.map(item => ({
...item,
text: item.name
}));
console.log("chainData.value", chainData.value);
setActiveChainId(chainData.value[0].id);
} else {
setActiveChainId(null);
chainData.value = [];
}
} catch (error) {
console.error("获取产业链信息数据失败:", error);
}
};
const cnEntityOnChainData = ref({
upstreamInternalCount: 0,
upstreamInternalRate: 0,
upstreamEntityCount: 0,
upstreamEntityRate: 0,
midstreamInternalCount: 0,
midstreamInternalRate: 0,
midstreamEntityCount: 0,
midstreamEntityRate: 0,
downstreamInternalCount: 0,
downstreamInternalRate: 0,
downstreamEntityCount: 0,
downstreamEntityRate: 0
});
const fetchCnEntityOnChain = async () => {
try {
console.log("getCnEntityOnChain 111111", chainData.value);
const data = await getCnEntityOnChain(chainData.value.length > 0 ? activeChainId.value : activeButtonId.value);
console.log("getCnEntityOnChain", data);
if (!!data && Object.keys(data).length > 0) {
// 将获取到的数据赋值给 cnEntityOnChainData
cnEntityOnChainData.value = {
upstreamInternalCount: data.upstreamInternalCount || 0,
upstreamInternalRate: Math.floor(data.upstreamInternalRate * 100) || 0,
upstreamEntityCount: data.upstreamEntityCount || 0,
upstreamEntityRate: Math.floor(data.upstreamEntityRate * 100) || 0,
midstreamInternalCount: data.midstreamInternalCount || 0,
midstreamInternalRate: Math.floor(data.midstreamInternalRate * 100) || 0,
midstreamEntityCount: data.midstreamEntityCount || 0,
midstreamEntityRate: Math.floor(data.midstreamEntityRate * 100) || 0,
downstreamInternalCount: data.downstreamInternalCount || 0,
downstreamInternalRate: Math.floor(data.downstreamInternalRate * 100) || 0,
downstreamEntityCount: data.downstreamEntityCount || 0,
downstreamEntityRate: Math.floor(data.downstreamEntityRate * 100) || 0
};
console.log("getCnEntityOnChain 222222", chainData.value);
}
} catch (error) {
console.error("获取产业链信息数据失败:", error);
}
};
// 获取领域分布数据并更新图表 // 获取领域分布数据并更新图表
const fetchDomainDistribution = async () => { const fetchDomainDistribution = async () => {
try { try {
...@@ -193,6 +277,7 @@ const fetchChainEntities = async () => { ...@@ -193,6 +277,7 @@ const fetchChainEntities = async () => {
listData.value = data.map(item => ({ listData.value = data.map(item => ({
...item, ...item,
name: item.orgNameZh, name: item.orgNameZh,
nameEn: item.orgName,
isUp: item.isUp isUp: item.isUp
})); }));
} }
...@@ -203,16 +288,31 @@ const fetchChainEntities = async () => { ...@@ -203,16 +288,31 @@ const fetchChainEntities = async () => {
onMounted(async () => { onMounted(async () => {
fetchDomainDistribution(); fetchDomainDistribution();
// horizontalBarOptions.value = getHorizontalBarChart2(
// ["贸易", "军工", "金融业", "跨境电商", "半导体", "新能源"],
// [10, 21, 25, 79, 95, 109],
// false
// );
fetchChainEntities(); fetchChainEntities();
// 获取产业链信息数据
fetchChainInfo();
// 获取产业链中国企业实体信息查询
fetchCnEntityOnChain();
}); });
watch(() => activeButtonId.value, fetchChainEntities); watch(
() => activeButtonId.value,
async () => {
await fetchChainEntities();
// 获取产业链信息数据
await fetchChainInfo();
// 获取产业链中国企业实体信息查询
await fetchCnEntityOnChain();
}
);
watch(
() => activeChainId.value,
async () => {
await fetchCnEntityOnChain();
}
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -225,6 +325,9 @@ watch(() => activeButtonId.value, fetchChainEntities); ...@@ -225,6 +325,9 @@ watch(() => activeButtonId.value, fetchChainEntities);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 17px 18px 12px 18px; padding: 17px 18px 12px 18px;
&-buttonlist {
padding: 10px;
}
.chartsWrap { .chartsWrap {
flex: 1; flex: 1;
.right-main-content { .right-main-content {
......
...@@ -124,9 +124,6 @@ const fetchKeyEntityList = async (date = "2025-11-11", keyword = "") => { ...@@ -124,9 +124,6 @@ const fetchKeyEntityList = async (date = "2025-11-11", keyword = "") => {
}; };
onMounted(async () => { onMounted(async () => {
// 确保默认值正确设置
domainValue.value = domainOptions[0].value;
typeValue.value = typeOptions[0].value;
try { try {
const [entitiesGrowthTrendData, entitiesUpdateCountData] = await Promise.all([ const [entitiesGrowthTrendData, entitiesUpdateCountData] = await Promise.all([
getEntitiesGrowthTrend(), getEntitiesGrowthTrend(),
...@@ -167,7 +164,7 @@ onMounted(async () => { ...@@ -167,7 +164,7 @@ onMounted(async () => {
}); });
const domainOptions = [ const domainOptions = [
{ {
value: "", value: "all",
label: "全部" label: "全部"
}, },
{ {
...@@ -257,7 +254,7 @@ const domainOptions = [ ...@@ -257,7 +254,7 @@ const domainOptions = [
]; ];
const typeOptions = [ const typeOptions = [
{ {
value: "", value: "all",
label: "全部" label: "全部"
}, },
{ {
...@@ -273,14 +270,14 @@ const typeOptions = [ ...@@ -273,14 +270,14 @@ const typeOptions = [
label: "地址" label: "地址"
} }
]; ];
const domainValue = ref(""); const domainValue = ref("all");
const typeValue = ref(""); const typeValue = ref("all");
const bar1Option = shallowRef({}); const bar1Option = shallowRef({});
const bar1DataIsEmpty = ref(false); const bar1DataIsEmpty = ref(false);
watch( watch(
[domainValue, typeValue], [domainValue, typeValue],
async ([domain, type]) => { async ([domain, type]) => {
let EntitiesChangeCount = await getEntitiesChangeCount(domain, type); let EntitiesChangeCount = await getEntitiesChangeCount(domain == "all" ? "" : domain, type == "all" ? "" : type);
EntitiesChangeCount = _.reverse(EntitiesChangeCount); EntitiesChangeCount = _.reverse(EntitiesChangeCount);
bar1DataIsEmpty.value = EntitiesChangeCount.length === 0; bar1DataIsEmpty.value = EntitiesChangeCount.length === 0;
bar1Option.value = getBarChart( bar1Option.value = getBarChart(
...@@ -292,16 +289,6 @@ watch( ...@@ -292,16 +289,6 @@ watch(
}, },
{ immediate: true } { immediate: true }
); );
// const options = [
// {
// value: "1",
// label: "人工智能"
// },
// {
// value: "2",
// label: "航空航天"
// }
// ];
const subPanel4 = ref([ const subPanel4 = ref([
{ {
name: "中国科学技术大学", name: "中国科学技术大学",
......
...@@ -76,18 +76,6 @@ import { getEntityFinancing, getEntityMarketValue, getKeyListedEntityList, getSa ...@@ -76,18 +76,6 @@ import { getEntityFinancing, getEntityMarketValue, getKeyListedEntityList, getSa
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const options = [
{
value: "1",
label: "人工智能"
},
{
value: "2",
label: "航空航天"
}
];
const value1 = ref("");
const value2 = ref("");
const value3 = ref(""); const value3 = ref("");
const bar1Option = shallowRef({}); const bar1Option = shallowRef({});
const bar2Option = shallowRef({}); const bar2Option = shallowRef({});
...@@ -119,6 +107,7 @@ const subPanel4 = ref([ ...@@ -119,6 +107,7 @@ const subPanel4 = ref([
// 获取重点上市企业列表数据 // 获取重点上市企业列表数据
const fetchKeyListedEntityList = async (keyword = "") => { const fetchKeyListedEntityList = async (keyword = "") => {
try { try {
console.log("获取重点上市企业列表数据", route.query.startTime);
const data = await getKeyListedEntityList(route.query.startTime, keyword); const data = await getKeyListedEntityList(route.query.startTime, keyword);
if (data && Array.isArray(data)) { if (data && Array.isArray(data)) {
// 根据 fishbone-mock.json 的数据结构处理数据 // 根据 fishbone-mock.json 的数据结构处理数据
...@@ -197,12 +186,12 @@ const fetchEntityFinancing = async () => { ...@@ -197,12 +186,12 @@ const fetchEntityFinancing = async () => {
// 按日期排序 // 按日期排序
const sortedData = data const sortedData = data
.sort((a, b) => { .sort((a, b) => {
return new Date(a.name) - new Date(b.name); return new Date(a.year) - new Date(b.year);
}) })
.filter((item, idx) => idx % 3 === 0); .filter((item, idx) => idx % 3 === 0);
// 提取 x 轴数据(日期) // 提取 x 轴数据(日期)
const xAxisData = sortedData.map(item => item.name); const xAxisData = sortedData.map(item => item.year);
// 提取 y 轴数据(融资数量) // 提取 y 轴数据(融资数量)
const seriesData = sortedData.map(item => item.count); const seriesData = sortedData.map(item => item.count);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
</CardCustom> </CardCustom>
</div> </div>
<div class="row"> <div class="row">
<CardCustom title="历次制裁涉及实体数" :style="{ width: '798px', height: '422px' }"> <CardCustom title="历次制裁涉及实体类型数" :style="{ width: '798px', height: '422px' }">
<div class="subPanel3"> <div class="subPanel3">
<div class="chartsWrap" :style="{ paddingBottom: '10px' }"> <div class="chartsWrap" :style="{ paddingBottom: '10px' }">
<Echarts :option="bar2Option" height="100%"></Echarts> <Echarts :option="bar2Option" height="100%"></Echarts>
...@@ -46,7 +46,7 @@ import { Search } from "@element-plus/icons-vue"; ...@@ -46,7 +46,7 @@ import { Search } from "@element-plus/icons-vue";
import Echarts from "@/components/Chart/index.vue"; import Echarts from "@/components/Chart/index.vue";
import { getBarChart, getLineChart, getPieOption1 } from "../../utils/charts"; import { getBarChart, getLineChart, getPieOption1 } from "../../utils/charts";
import Hint from "./hint.vue"; import Hint from "./hint.vue";
import { getCountSanTypeByTime, getCountTypeByYear, getCountThisType } from "@/api/exportControl"; import { getCountSanTypeByTime, getCountTypeByYear, getCountThisType, getEnterpriseSanCount } from "@/api/exportControl";
import _ from "lodash"; import _ from "lodash";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const route = useRoute(); const route = useRoute();
...@@ -60,7 +60,7 @@ onMounted(async () => { ...@@ -60,7 +60,7 @@ onMounted(async () => {
getCountSanTypeByTime(route.query.startTime), getCountSanTypeByTime(route.query.startTime),
getCountThisType("1"), getCountThisType("1"),
getCountTypeByYear(), getCountTypeByYear(),
getCountThisType("2") getEnterpriseSanCount()
]); ]);
pie1Option.value = getPieOption1( pie1Option.value = getPieOption1(
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
import Echarts from "@/components/Chart/index.vue"; import Echarts from "@/components/Chart/index.vue";
import { getPieOption } from "../../utils/charts"; import { getPieOption } from "../../utils/charts";
import { ref, onMounted, shallowRef } from "vue"; import { ref, onMounted, shallowRef } from "vue";
import { getCountByDomain, getCountByType } from "@/api/exportControl"; import { getCountByDomain, getCountByType, getDomainDistribution } from "@/api/exportControl";
import _ from "lodash"; import _ from "lodash";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const route = useRoute(); const route = useRoute();
...@@ -22,7 +22,7 @@ const pie2Option = shallowRef({}); ...@@ -22,7 +22,7 @@ const pie2Option = shallowRef({});
onMounted(async () => { onMounted(async () => {
try { try {
const [countByDomainData, countByTypeData] = await Promise.all([ const [countByDomainData, countByTypeData] = await Promise.all([
getCountByDomain(route.query.startTime), getDomainDistribution(route.query.startTime),
getCountByType(route.query.startTime) getCountByType(route.query.startTime)
]); ]);
pie1Option.value = getPieOption( pie1Option.value = getPieOption(
...@@ -30,7 +30,7 @@ onMounted(async () => { ...@@ -30,7 +30,7 @@ onMounted(async () => {
.filter(item => item.count > 0) .filter(item => item.count > 0)
.map(item => { .map(item => {
return { return {
name: item?.domain, name: item?.name,
value: item?.count value: item?.count
}; };
}) })
......
...@@ -88,9 +88,13 @@ ...@@ -88,9 +88,13 @@
<div class="hintWrap"> <div class="hintWrap">
<div class="title"> <div class="title">
共计 共计
<span class="text1">112</span> <span class="text1">{{ entityTotal }}</span>
家,其中50%规则涉及 家,其中50%规则涉及
<span class="text2">604</span> <span class="text2">{{
panel5IsChecked
? entitiesCountBy50PercentRules?.ruleCount
: entitiesCountBy50PercentRules?.totalCount
}}</span>
</div> </div>
</div> </div>
...@@ -156,6 +160,7 @@ ...@@ -156,6 +160,7 @@
</CardCustom> </CardCustom>
<CardCustom title="美国前序相关制裁、前序相关事件列表" :style="{ width: '600px', height: '678px' }"> <CardCustom title="美国前序相关制裁、前序相关事件列表" :style="{ width: '600px', height: '678px' }">
<div class="panel6"> <div class="panel6">
<div class="panel6-list">
<div class="item" v-for="(item, idx) in panel6" :key="item.title"> <div class="item" v-for="(item, idx) in panel6" :key="item.title">
<div class="left"> <div class="left">
<div class="icon"></div> <div class="icon"></div>
...@@ -167,7 +172,8 @@ ...@@ -167,7 +172,8 @@
<div class="desc">{{ item.desc }}</div> <div class="desc">{{ item.desc }}</div>
</div> </div>
</div> </div>
<div class="more"> </div>
<div class="more" @click="handleMoreClick">
查看更多 查看更多
<span class="moreIcon"></span> <span class="moreIcon"></span>
</div> </div>
...@@ -185,24 +191,14 @@ import ButtonList from "@/components/buttonList/buttonList.vue"; ...@@ -185,24 +191,14 @@ import ButtonList from "@/components/buttonList/buttonList.vue";
import Hint from "../components/hint.vue"; import Hint from "../components/hint.vue";
import { onMounted, reactive, ref, shallowRef, watch } from "vue"; import { onMounted, reactive, ref, shallowRef, watch } from "vue";
import panel1_1 from "../../assets/images/panel1_1.png"; import panel1_1 from "../../assets/images/panel1_1.png";
import panel2_1 from "../../assets/images/panel2_1.png";
import panel2_2 from "../../assets/images/panel2_2.png";
import panel2_3 from "../../assets/images/panel2_3.png";
import panel2_4 from "../../assets/images/panel2_4.png";
import panel5_1 from "../../assets/images/panel5_1.png";
import panel5_2 from "../../assets/images/panel5_2.png";
import panel5_3 from "../../assets/images/panel5_3.png";
import panel5_4 from "../../assets/images/panel5_4.png";
import panel5_5 from "../../assets/images/panel5_5.png";
import panel5_6 from "../../assets/images/panel5_6.png";
import panel5_7 from "../../assets/images/panel5_7.png";
import panel5_8 from "../../assets/images/panel5_8.png";
import { import {
getOrganizationInfo, getOrganizationInfo,
getPersonList, getPersonList,
getSanReasonSelect, getSanReasonSelect,
getSelectEntitiesList, getSelectEntitiesList,
getEntitiesList getEntitiesList,
getEntitiesCountBy50PercentRules,
getPrecedingEvents
} from "@/api/exportControl"; } from "@/api/exportControl";
import _ from "lodash"; import _ from "lodash";
...@@ -211,32 +207,7 @@ import { formatAnyDateToChinese } from "../../utils"; ...@@ -211,32 +207,7 @@ import { formatAnyDateToChinese } from "../../utils";
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const organizationInfo = shallowRef({}); const organizationInfo = shallowRef({});
const personLis = shallowRef([ const personLis = shallowRef([]);
// {
// name: "吉娜·雷蒙多",
// enName: "Gina Raimondo",
// party: "美国民主党",
// img: panel2_1
// },
// {
// name: "迈克・约翰逊",
// enName: "Mike Johnson",
// party: "美国共和党",
// img: panel2_2
// },
// {
// name: "艾伦·埃斯特韦斯",
// enName: "Alan Estevez",
// party: "美国民主党",
// img: panel2_3
// },
// {
// name: "凯・格兰杰",
// enName: "Kay Granger",
// party: "美国共和党",
// img: panel2_4
// }
]);
const sanReasonSelect = shallowRef([ const sanReasonSelect = shallowRef([
{ {
text: "获取美国产物项,以支持中国量子技术;" text: "获取美国产物项,以支持中国量子技术;"
...@@ -275,16 +246,33 @@ const total = ref(0); ...@@ -275,16 +246,33 @@ const total = ref(0);
const loading = ref(false); const loading = ref(false);
const tableWrapRef = ref(null); const tableWrapRef = ref(null);
const noMoreData = ref(false); const noMoreData = ref(false);
const entitiesCountBy50PercentRules = ref({
ruleCount: 0,
totalCount: 0
});
const precedingEvents = shallowRef([]);
const panel6 = ref([]);
const panel6CurrentPage = ref(1);
const panel6PageSize = ref(10);
const panel6Loading = ref(false);
const panel6NoMoreData = ref(false);
onMounted(async () => { onMounted(async () => {
try { try {
const [organizationInfoData, sanReasonSelectData] = await Promise.all([ const [organizationInfoData, sanReasonSelectData, entitiesCountBy50PercentRulesData, precedingEventsData] =
await Promise.all([
getOrganizationInfo(), getOrganizationInfo(),
// getPersonList(), // getPersonList(),
getSanReasonSelect(route.query.startTime) getSanReasonSelect(route.query.startTime),
// getSelectEntitiesList(route.query.startTime) getEntitiesCountBy50PercentRules("实体清单", currentPage.value, pageSize.value),
// getSelectEntitiesList(route.query.startTime),
getPrecedingEvents(route.query.startTime)
]); ]);
console.log("organizationInfoData", organizationInfoData); console.log("entitiesCountBy50PercentRulesData", entitiesCountBy50PercentRulesData);
entitiesCountBy50PercentRules.value = {
ruleCount: entitiesCountBy50PercentRulesData?.ruleCount || 0,
totalCount: entitiesCountBy50PercentRulesData?.totalCount || 0
};
organizationInfo.value = { organizationInfo.value = {
img: panel1_1, img: panel1_1,
mingcheng: organizationInfoData?.orgNameZh, mingcheng: organizationInfoData?.orgNameZh,
...@@ -304,18 +292,12 @@ onMounted(async () => { ...@@ -304,18 +292,12 @@ onMounted(async () => {
return { text: item }; return { text: item };
}); });
// selectEntitiesList.value = _.map(selectEntitiesListData, item => { precedingEvents.value = precedingEventsData.content || [];
// return { panel6.value = precedingEventsData.content.map(item => ({
// name: item?.entityNameZh, ...item,
// domains: item.techDomainList, time: formatAnyDateToChinese(item.eventTime),
// address: "--", desc: item.summary || "--"
// time: formatAnyDateToChinese(item?.startTime), }));
// isUp: true,
// revenue: "--",
// subCompany: "--",
// img: ""
// };
// });
// 初始化加载第一页数据 // 初始化加载第一页数据
await fetchEntitiesList(currentPage.value, pageSize.value); await fetchEntitiesList(currentPage.value, pageSize.value);
...@@ -325,6 +307,7 @@ onMounted(async () => { ...@@ -325,6 +307,7 @@ onMounted(async () => {
}); });
// 获取实体清单数据 // 获取实体清单数据
const entityTotal = ref(0);
const fetchEntitiesList = async (page = 1, size = 10) => { const fetchEntitiesList = async (page = 1, size = 10) => {
if (loading.value || noMoreData.value) return; if (loading.value || noMoreData.value) return;
...@@ -332,6 +315,7 @@ const fetchEntitiesList = async (page = 1, size = 10) => { ...@@ -332,6 +315,7 @@ const fetchEntitiesList = async (page = 1, size = 10) => {
try { try {
const res = await getEntitiesList("实体清单", page, size, route.query.startTime, panel5IsChecked.value); const res = await getEntitiesList("实体清单", page, size, route.query.startTime, panel5IsChecked.value);
if (res) { if (res) {
entityTotal.value = res.totalElements;
const newData = res.content.map(item => ({ const newData = res.content.map(item => ({
...item, ...item,
name: item.entityNameZh, name: item.entityNameZh,
...@@ -372,6 +356,7 @@ watch( ...@@ -372,6 +356,7 @@ watch(
() => panel5IsChecked.value, () => panel5IsChecked.value,
newVal => { newVal => {
fetchEntitiesList(1, 10); fetchEntitiesList(1, 10);
// getEntitiesCountBy50PercentRules("实体清单", 1, pageSize.value)
} }
); );
...@@ -421,108 +406,10 @@ const panel5TypeMap = { ...@@ -421,108 +406,10 @@ const panel5TypeMap = {
通信网络: "warning", 通信网络: "warning",
航空航天: "success" 航空航天: "success"
}; };
const panel5MockData = [
{
name: "科大讯飞股份有限公司",
domains: ["人工智能"],
address: "深圳",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "讯飞智元信息科技...等15家>",
img: panel5_1
},
{
name: "华为技术有限公司",
domains: ["通信网络"],
address: "--",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "海思半导体有限公...等15家>",
img: panel5_2
},
{
name: "中国航空工业集团",
domains: ["航空航天"],
address: "--",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "中航科技控股有限...等15家>",
img: panel5_3
},
{
name: "杭州海康威视有限公司",
domains: ["航空航天"],
address: "深圳",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "海云智能科技有限...等15家>",
img: panel5_4
},
{
name: "浪潮集团有限公司",
domains: ["人工智能"],
address: "--",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "浪潮商用机器有限...等15家>",
img: panel5_5
},
{
name: "中兴通讯股份有限公司",
domains: ["航空航天"],
address: "深圳",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "中融讯合通信设备...等15家>",
img: panel5_6
},
{
name: "大疆创新科技有限公司",
domains: ["人工智能"],
address: "--",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "大疆智能计算服务...等15家>",
img: panel5_7
},
{
name: "艾睿中国电子贸易有限公司",
domains: ["航空航天"],
address: "上海",
time: "2025年9月",
isUp: true,
revenue: "325",
subCompany: "讯飞智元信息科技...等15家>",
img: panel5_8
}
];
// 历次制裁过程
const panel6 = ref([
{
time: "2025-09-02",
title: "传感器和仪器仪表技术咨询委员会将于2024年5月9日召开部分闭门会议",
desc: "传感器与仪器仪表技术咨询委员会(以下简称“委员会”)将于美国东部夏令时间2024年5月9日星期四下午1:00至2:30召开会议。本次会议将通过微软团队(MS Teams)以线上形式举行。根据美国商务部第10-16号《部门组织》文件。"
},
{
time: "2025-04-17",
title: "美国对华加征关税至20%并扩大科技制裁",
desc: '美国以"芬太尼问题"为由提高对华关税至20%,恢复钢铁铝关税;同时推动《恢复贸易公平法案》,计划对中国商品征收100%关税。系统性打压中国高科技产业,关税措施实质为经济勒索。'
},
{
time: "2025-04-17",
title: "中美关税战升级至125%与反制措施",
desc: '美国将对华关税从34%提升至84%(总税率104%),中方同步对美商品加征同等税率,并暂停进口美国影片、限制留学合作。特朗普政府通过"基准关税+对等关税+额外加征"策略施压,引发全球供应链震荡。'
}
]);
const handleOrgClick = item => { const handleOrgClick = item => {
console.log(item); console.log(item);
if (item.entityType != 2) return;
const route = router.resolve({ const route = router.resolve({
path: "/companyPages", path: "/companyPages",
query: { query: {
...@@ -531,6 +418,47 @@ const handleOrgClick = item => { ...@@ -531,6 +418,47 @@ const handleOrgClick = item => {
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
// 处理"查看更多"点击事件
const handleMoreClick = async () => {
if (panel6Loading.value || panel6NoMoreData.value) return;
panel6Loading.value = true;
try {
// 增加页码
panel6CurrentPage.value++;
// 获取更多数据
const moreEvents = await getPrecedingEvents(route.query.startTime, panel6CurrentPage.value, panel6PageSize.value);
if (moreEvents && Array.isArray(moreEvents.content) && moreEvents.content.length > 0) {
// 处理新数据
const newEvents = moreEvents.content.map(item => ({
...item,
time: formatAnyDateToChinese(item.eventTime),
desc: item.summary || "--"
}));
// 追加到现有数据
panel6.value = [...panel6.value, ...newEvents];
// 检查是否还有更多数据(简单的检查方式)
// 如果返回的数据少于请求的数量,则认为没有更多数据
if (newEvents.length < panel6PageSize.value) {
panel6NoMoreData.value = true;
}
} else {
// 没有更多数据
panel6NoMoreData.value = true;
}
} catch (error) {
console.error("获取更多前序事件失败:", error);
// 出错时回退页码
panel6CurrentPage.value--;
} finally {
panel6Loading.value = false;
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -820,10 +748,16 @@ const handleOrgClick = item => { ...@@ -820,10 +748,16 @@ const handleOrgClick = item => {
} }
.panel6 { .panel6 {
height: 100%; height: 100%;
padding: 6px 45px 0 28px; padding: 6px 45px 20px 28px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
.panel6-list {
height: 90%;
overflow-y: auto;
margin-bottom: auto;
padding-left: 5px;
}
.item { .item {
display: flex; display: flex;
.left { .left {
......
<template> <template>
<div class="message-bubble"> <div class="message-bubble">
<div class="avatar-container" @click="handleClick"> <div class="avatar-container" @click="handleClick">
<img :src="avatar" :alt="name" class="avatar" /> <img :src="avatar || avatarUser" :alt="name" class="avatar" />
</div> </div>
<div class="bubble-container"> <div class="bubble-container">
<div class="bubble"> <div class="bubble">
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
</template> </template>
<script setup> <script setup>
import avatarUser from "@/assets/images/avatar_user.png";
const emit = defineEmits(["click", "info-click"]); const emit = defineEmits(["click", "info-click"]);
defineProps({ defineProps({
avatar: { avatar: {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="news-list"> <div class="news-list">
<div v-for="(item, index) in listData" :key="index" class="news-item" @click="handleItemClick(item)"> <div v-for="(item, index) in listData" :key="index" class="news-item" @click="handleItemClick(item)">
<div class="news-image"> <div class="news-image">
<img :src="item.image || newsImg" :alt="item.title" /> <img :src="item.avatar || newsImg" :alt="item.title" />
</div> </div>
<div class="news-content"> <div class="news-content">
<div class="news-header"> <div class="news-header">
......
...@@ -91,7 +91,24 @@ ...@@ -91,7 +91,24 @@
<template #default> <template #default>
<div class="box1"> <div class="box1">
<el-carousel ref="carouselRef" trigger="click" height="350px" :autoplay="true"> <div class="box1-left-arrow" @click="handleSwithCurPolicy('left')">
<div class="icon">
<img src="./assets/images/box1-left.png" alt="" />
</div>
</div>
<div class="box1-right-arrow" @click="handleSwithCurPolicy('right')">
<div class="icon">
<img src="./assets/images/box1-right.png" alt="" />
</div>
</div>
<el-carousel
ref="carouselRef"
height="350px"
:autoplay="true"
:interval="3000"
arrow="never"
indicator-position="none"
>
<el-carousel-item v-for="(item, index) in entitiesDataInfoList" :key="item.id + index"> <el-carousel-item v-for="(item, index) in entitiesDataInfoList" :key="item.id + index">
<div> <div>
<div class="box1-top"> <div class="box1-top">
...@@ -220,7 +237,7 @@ ...@@ -220,7 +237,7 @@
<template #default> <template #default>
<div class="news-list"> <div class="news-list">
<NewsList :list-data="newsList" @click="handleNewsInfoClick" /> <NewsList :list-data="newsList" @item-click="item => handleNewsInfoClick(item)" />
</div> </div>
</template> </template>
</custom-container> </custom-container>
...@@ -321,7 +338,7 @@ ...@@ -321,7 +338,7 @@
</div> </div>
<div class="box3-content"> <div class="box3-content">
<div class="box3-content-title">商业管制清单(CCL)更新频度</div> <div class="box3-content-title">商业管制清单(CCL)更新频度</div>
<el-table :data="tableData1" stripe style="width: 100%"> <el-table :data="tableData2" stripe style="width: 100%">
<el-table-column prop="year" label="年份" width="150" /> <el-table-column prop="year" label="年份" width="150" />
<el-table-column label="发布次数" width="200"> <el-table-column label="发布次数" width="200">
<template #default="scope"> <template #default="scope">
...@@ -694,6 +711,7 @@ import _ from "lodash"; ...@@ -694,6 +711,7 @@ import _ from "lodash";
const handleCompClick = item => { const handleCompClick = item => {
console.log("item", item); console.log("item", item);
if (item.entityType != 2) return;
const route = router.resolve({ const route = router.resolve({
path: "/companyPages", path: "/companyPages",
query: { query: {
...@@ -712,6 +730,8 @@ const trendOption = ref({}); ...@@ -712,6 +730,8 @@ const trendOption = ref({});
const trendChecked = ref(false); const trendChecked = ref(false);
// 发布频度 // 发布频度
const tableData1 = ref([]); const tableData1 = ref([]);
// CCL发布频度
const tableData2 = ref([]);
// 历次制裁过程 // 历次制裁过程
const sanctionProcessList = ref([]); const sanctionProcessList = ref([]);
const sanctionPage = ref(1); const sanctionPage = ref(1);
...@@ -727,10 +747,11 @@ const newsList = ref([]); ...@@ -727,10 +747,11 @@ const newsList = ref([]);
onMounted(async () => { onMounted(async () => {
try { try {
const [dataCount, entitiesDataInfo, industryCountByYear, countDomainByYear] = await Promise.all([ const [dataCount, entitiesDataInfo, industryCountByYear, cclList, countDomainByYear] = await Promise.all([
getEntitiesDataCount(), getEntitiesDataCount(),
getEntitiesDataInfo(), getEntitiesDataInfo(),
getIndustryCountByYear(1), getIndustryCountByYear(1),
getIndustryCountByYear(13),
getCountDomainByYear(trendChecked.value) getCountDomainByYear(trendChecked.value)
]); ]);
// 交换第二个和第三个元素 // 交换第二个和第三个元素
...@@ -742,6 +763,7 @@ onMounted(async () => { ...@@ -742,6 +763,7 @@ onMounted(async () => {
}); });
entitiesDataInfoList.value = entitiesDataInfo || []; entitiesDataInfoList.value = entitiesDataInfo || [];
const list = _.chain(industryCountByYear).filter("year").orderBy("year", "desc").value(); const list = _.chain(industryCountByYear).filter("year").orderBy("year", "desc").value();
const cclList1 = _.chain(cclList).filter("year").orderBy("year", "desc").value();
const total = _.sumBy(list, "count"); const total = _.sumBy(list, "count");
tableData1.value = _.map(list, item => { tableData1.value = _.map(list, item => {
return { return {
...@@ -751,6 +773,14 @@ onMounted(async () => { ...@@ -751,6 +773,14 @@ onMounted(async () => {
tags: item.domain tags: item.domain
}; };
}).slice(0, 5); }).slice(0, 5);
tableData2.value = _.map(cclList1, item => {
return {
year: item.year,
num: item.count,
percent: item.count / total,
tags: item.domain
};
}).slice(0, 5);
console.log("countDomainByYear", countDomainByYear); console.log("countDomainByYear", countDomainByYear);
// 整理柱状图数据并应用到趋势图 // 整理柱状图数据并应用到趋势图
if (countDomainByYear && countDomainByYear[0].yearDomainCount) { if (countDomainByYear && countDomainByYear[0].yearDomainCount) {
...@@ -1194,6 +1224,7 @@ const fetchNewsInfo = async () => { ...@@ -1194,6 +1224,7 @@ const fetchNewsInfo = async () => {
const data = await getNewsInfo(); const data = await getNewsInfo();
if (data && Array.isArray(data)) { if (data && Array.isArray(data)) {
newsList.value = data.map(item => ({ newsList.value = data.map(item => ({
...item,
avatar: item.newsImage, avatar: item.newsImage,
name: item.newsTitle, name: item.newsTitle,
time: formatTime(item.newsDate), time: formatTime(item.newsDate),
...@@ -1439,12 +1470,21 @@ const handleNewsInfoClick = item => { ...@@ -1439,12 +1470,21 @@ const handleNewsInfoClick = item => {
const route = router.resolve({ const route = router.resolve({
path: "/newsAnalysis", path: "/newsAnalysis",
query: { query: {
newsId: item.id newsId: item.newsId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
// 切换当前出口管制政策
const handleSwithCurPolicy = name => {
if (name === "left") {
carouselRef.value.prev();
} else {
carouselRef.value.next();
}
};
onMounted(async () => { onMounted(async () => {
handleGetHylyList(); handleGetHylyList();
let chart1 = getMultiLineChart(chart1Data.value.title, chart1Data.value.data[0].value, chart1Data.value.data[1].value); let chart1 = getMultiLineChart(chart1Data.value.title, chart1Data.value.data[0].value, chart1Data.value.data[1].value);
...@@ -1507,6 +1547,48 @@ const handleMediaClick = item => { ...@@ -1507,6 +1547,48 @@ const handleMediaClick = item => {
flex-direction: column; flex-direction: column;
gap: 20px; gap: 20px;
position: relative; position: relative;
.box1-left-arrow {
position: absolute;
z-index: 9999;
left: -20px;
top: 135px;
width: 24px !important;
height: 48px;
background: #e7f1ff;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.icon {
width: 11px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
}
.box1-right-arrow {
position: absolute;
z-index: 9999;
right: -20px;
top:135px;
width: 24px;
height: 48px;
background: #e7f1ff;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.icon {
width: 11px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
}
.box1-absolute { .box1-absolute {
position: absolute; position: absolute;
width: 240px; width: 240px;
...@@ -1887,10 +1969,14 @@ const handleMediaClick = item => { ...@@ -1887,10 +1969,14 @@ const handleMediaClick = item => {
} }
.home-wrapper { .home-wrapper {
width: 100%;
height: calc(100vh - 96px);
position: relative;
overflow-y: hidden;
.home-main { .home-main {
// width: 1400px; width: 100%;
padding: 0 5%; height: 100%;
margin: 0 auto; overflow-y: auto;
background: url("./assets/images/background.png"); background: url("./assets/images/background.png");
background-size: 100% 100%; background-size: 100% 100%;
.home-main-header { .home-main-header {
...@@ -2044,44 +2130,9 @@ const handleMediaClick = item => { ...@@ -2044,44 +2130,9 @@ const handleMediaClick = item => {
gap: 20px; gap: 20px;
.box1 { .box1 {
display: flex; display: flex;
gap: 10px; gap: 10px;
position: relative; position: relative;
// .box1-left {
// position: absolute;
// left: 0;
// top: 200px;
// width: 24px;
// height: 48px;
// background: #e7f1ff;
// display: flex;
// justify-content: center;
// align-items: center;
// cursor: pointer;
// .icon {
// width: 11px;
// height: 18px;
// img {
// width: 100%;
// height: 100%;
// }
// }
// }
.box1-right {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
cursor: pointer;
.icon {
width: 11px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
}
.box1-header { .box1-header {
height: 53px; height: 53px;
border-bottom: 1px solid rgba(240, 242, 244, 1); border-bottom: 1px solid rgba(240, 242, 244, 1);
......
...@@ -139,6 +139,7 @@ export function getPieOption2(data, title) { ...@@ -139,6 +139,7 @@ export function getPieOption2(data, title) {
} }
}, },
legend: { legend: {
type: "scroll",
icon: "rect", icon: "rect",
top: "center", top: "center",
right: "40", right: "40",
...@@ -825,6 +826,7 @@ export const getMultipleLineChart = obj => { ...@@ -825,6 +826,7 @@ export const getMultipleLineChart = obj => {
containLabel: true containLabel: true
}, },
legend: { legend: {
type: "scroll",
right: "5%", right: "5%",
icon: "circle", icon: "circle",
itemWidth: 15, itemWidth: 15,
...@@ -835,7 +837,7 @@ export const getMultipleLineChart = obj => { ...@@ -835,7 +837,7 @@ export const getMultipleLineChart = obj => {
}, },
itemGap: 17, itemGap: 17,
data: obj.data.map((item, index) => { data: obj.data.map((item, index) => {
return { name: item.name, itemStyle: { color: color[index] } }; return { name: item.name, itemStyle: { color: color[index % 4] } };
}) })
}, },
xAxis: { xAxis: {
......
...@@ -1698,10 +1698,14 @@ onMounted(async () => { ...@@ -1698,10 +1698,14 @@ onMounted(async () => {
} }
.home-wrapper { .home-wrapper {
width: 100%;
height: calc(100vh - 96px);
position: relative;
overflow-y: hidden;
.home-main { .home-main {
// width: 1400px; width: 100%;
padding: 0 5%; height: 100%;
margin: 0 auto; overflow-y: auto;
background: url("./assets/images/background.png"); background: url("./assets/images/background.png");
background-size: 100% 100%; background-size: 100% 100%;
.home-main-header { .home-main-header {
......
...@@ -352,7 +352,6 @@ ...@@ -352,7 +352,6 @@
/> />
</el-select> </el-select>
</div> </div>
</div> </div>
</div> </div>
<div class="center-footer-layout"> <div class="center-footer-layout">
...@@ -405,6 +404,7 @@ ...@@ -405,6 +404,7 @@
</div> </div>
</div> </div>
<div class="home-main-footer-main"> <div class="home-main-footer-main">
<div class="footer-main-item" v-for="item in universityList" :key="item.name" @click="handleClickToDetail"> <div class="footer-main-item" v-for="item in universityList" :key="item.name" @click="handleClickToDetail">
<img :src="item.pic" style="height: 32px; width: 32px;" /> <img :src="item.pic" style="height: 32px; width: 32px;" />
<div class="item-text">{{ item.name }}</div> <div class="item-text">{{ item.name }}</div>
...@@ -894,7 +894,6 @@ onMounted(async () => { ...@@ -894,7 +894,6 @@ onMounted(async () => {
let chart1 = getPieChart(chart1Data.value, colorList); let chart1 = getPieChart(chart1Data.value, colorList);
setChart(chart1, "chart1"); setChart(chart1, "chart1");
}); });
</script> </script>
......
...@@ -1070,10 +1070,14 @@ onMounted(async () => { ...@@ -1070,10 +1070,14 @@ onMounted(async () => {
box-shadow: none; box-shadow: none;
} }
.home-wrapper { .home-wrapper {
width: 100%;
height: calc(100vh - 96px);
position: relative;
overflow-y: hidden;
.home-main { .home-main {
// width: 1400px;
width: 100%; width: 100%;
margin: 0 auto; height: 100%;
overflow-y: auto;
background: url("./assets/images/background.png"); background: url("./assets/images/background.png");
background-size: 100% 100%; background-size: 100% 100%;
.home-main-header { .home-main-header {
...@@ -1217,7 +1221,7 @@ onMounted(async () => { ...@@ -1217,7 +1221,7 @@ onMounted(async () => {
right: 19px; right: 19px;
width: 6px; width: 6px;
height: 12px; height: 12px;
img{ img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
......
...@@ -100,10 +100,13 @@ ...@@ -100,10 +100,13 @@
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div class="box2-main-item" v-for="(item, index) in warningList" :key="index"> <div class="box2-main-item" v-for="(item, index) in warningList" :key="index">
<div class="item-left" :class="{ <div
class="item-left"
:class="{
itemLeftStatus1: item.status === '一般风险', itemLeftStatus1: item.status === '一般风险',
itemLeftStatus2: item.status === '重大风险' itemLeftStatus2: item.status === '重大风险'
}"> }"
>
{{ item.status }} {{ item.status }}
</div> </div>
<div class="item-right"> <div class="item-right">
...@@ -131,14 +134,18 @@ ...@@ -131,14 +134,18 @@
<img src="./assets/images/TechnologyFigures-icon3.png" alt="" /> <img src="./assets/images/TechnologyFigures-icon3.png" alt="" />
</div> </div>
<!-- <div class="box3-header-title">{{ "人物动向" }}</div> --> <!-- <div class="box3-header-title">{{ "人物动向" }}</div> -->
<div class="header-title" <div
style="width: 1560px; display: flex; justify-content: space-between; margin-top: 10px"> class="header-title"
style="width: 1560px; display: flex; justify-content: space-between; margin-top: 10px"
>
<div class="box3-header-title"> <div class="box3-header-title">
{{ "人物动向" }} {{ "人物动向" }}
</div> </div>
<div style="display: flex; gap: 8px; margin-right: 12px"> <div style="display: flex; gap: 8px; margin-right: 12px">
<div v-for="value in peoDateList" <div
:class="peoDate !== value ? 'btn-box-samll' : 'btn-box-select-samll'"> v-for="value in peoDateList"
:class="peoDate !== value ? 'btn-box-samll' : 'btn-box-select-samll'"
>
{{ value }} {{ value }}
</div> </div>
</div> </div>
...@@ -154,14 +161,18 @@ ...@@ -154,14 +161,18 @@
<div class="header-icon"> <div class="header-icon">
<img src="./assets/images/header-message.png" alt="" /> <img src="./assets/images/header-message.png" alt="" />
</div> </div>
<div class="header-title" <div
style="width: 1595px; display: flex; justify-content: space-between; margin-top: 10px"> class="header-title"
style="width: 1595px; display: flex; justify-content: space-between; margin-top: 10px"
>
<div> <div>
{{ "重要人物言论及立场" }} {{ "重要人物言论及立场" }}
</div> </div>
<div style="display: flex; gap: 8px; margin-right: 12px"> <div style="display: flex; gap: 8px; margin-right: 12px">
<div v-for="value in fields" <div
:class="fieldSelect !== value ? 'btn-box-samll' : 'btn-box-select-samll'"> v-for="value in fields"
:class="fieldSelect !== value ? 'btn-box-samll' : 'btn-box-select-samll'"
>
{{ value }} {{ value }}
</div> </div>
</div> </div>
...@@ -178,18 +189,33 @@ ...@@ -178,18 +189,33 @@
<div class="box5-header"> <div class="box5-header">
<div class="box5-header-left"> <div class="box5-header-left">
<div class="box5-header-icon"> <div class="box5-header-icon">
<img src="./assets/images/TechnologyFigures-icon1.png" alt="" <img
style="margin: 13px 21px 13px 21px; height: 22px" /> src="./assets/images/TechnologyFigures-icon1.png"
alt=""
style="margin: 13px 21px 13px 21px; height: 22px"
/>
<div class="box5-header-title">{{ "科技人物观点词云" }}</div> <div class="box5-header-title">{{ "科技人物观点词云" }}</div>
</div> </div>
<div> <div>
<div style="height: 45px; display: flex; align-items: center"> <div style="height: 45px; display: flex; align-items: center">
<el-select v-model="wordCloudvalue" style="width: 120px; height: 28px"> <el-select v-model="wordCloudvalue" style="width: 120px; height: 28px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" /> <el-option
v-for="item in yearList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<el-select v-model="wordCloudfield" style="width: 120px; height: 28px; margin: 10px 24px 10px 5px"> <el-select
<el-option v-for="item in fieldSelect" :key="item.value" :label="item.label" v-model="wordCloudfield"
:value="item.value" /> style="width: 120px; height: 28px; margin: 10px 24px 10px 5px"
>
<el-option
v-for="item in fieldSelect"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
</div> </div>
...@@ -202,17 +228,22 @@ ...@@ -202,17 +228,22 @@
<div class="header-icon"> <div class="header-icon">
<img src="./assets/images/box3-header-icon.png" alt="" /> <img src="./assets/images/box3-header-icon.png" alt="" />
</div> </div>
<div class="header-title" <div
style="display: flex; width: 740px; justify-content: space-between; align-items: center"> class="header-title"
style="display: flex; width: 740px; justify-content: space-between; align-items: center"
>
<div> <div>
{{ "科技人物观点涉及领域变化趋势" }} {{ "科技人物观点涉及领域变化趋势" }}
</div> </div>
<el-select v-model="areaSelect" style="width: 120px; height: 28px"> <el-select v-model="areaSelect" style="width: 120px; height: 28px">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> <el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
</div> </div>
<div class="box6-main" id="box6Chart"></div> <div class="box6-main" id="box6Chart"></div>
...@@ -238,16 +269,22 @@ ...@@ -238,16 +269,22 @@
</div> </div>
<div style="display: flex; width: 730px; justify-content: space-between; align-items: center"> <div style="display: flex; width: 730px; justify-content: space-between; align-items: center">
<div class="box8-header-title">{{ "主要人物涉华观点统计" }}</div> <div class="box8-header-title">{{ "主要人物涉华观点统计" }}</div>
<div style="gap: 8px;display: flex;"> <div style="gap: 8px; display: flex">
<div v-for="value in viewOption" <div
:class="viewSelect !== value ? 'btn-box-samll' : 'btn-box-select-samll'"> v-for="value in viewOption"
:class="viewSelect !== value ? 'btn-box-samll' : 'btn-box-select-samll'"
>
{{ value }} {{ value }}
</div> </div>
<el-select v-model="wordCloudvalue" style="width: 120px; height: 28px; margin-top: -5px;"> <el-select v-model="wordCloudvalue" style="width: 120px; height: 28px; margin-top: -5px">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" /> <el-option
v-for="item in yearList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
...@@ -262,8 +299,13 @@ ...@@ -262,8 +299,13 @@
<DivideHeader id="position4" class="divide-header" :titleText="'资源库'"></DivideHeader> <DivideHeader id="position4" class="divide-header" :titleText="'资源库'"></DivideHeader>
<div class="home-main-footer-header"> <div class="home-main-footer-header">
<div class="btn-box"> <div class="btn-box">
<div class="btn" :class="{ btnActive: activeCate === cate }" v-for="(cate, index) in categoryList" <div
:key="index" @click="handleClickCate(cate)"> class="btn"
:class="{ btnActive: activeCate === cate }"
v-for="(cate, index) in categoryList"
:key="index"
@click="handleClickCate(cate)"
>
{{ cate }} {{ cate }}
</div> </div>
</div> </div>
...@@ -438,13 +480,22 @@ onMounted(() => { ...@@ -438,13 +480,22 @@ onMounted(() => {
} }
.home-wrapper { .home-wrapper {
width: 100%;
height: calc(100vh - 96px);
position: relative;
overflow-y: hidden;
.home-main { .home-main {
width: 1920px; // width: 1920px;
margin: 0 auto; // margin: 0 auto;
// background: url("./assets/images/background.png");
// background-repeat: no-repeat;
// background-color: #fff;
// background-size: contain;
width: 100%;
height: 100%;
overflow-y: auto;
background: url("./assets/images/background.png"); background: url("./assets/images/background.png");
background-repeat: no-repeat; background-size: 100% 100%;
background-color: #fff;
background-size: contain;
.home-main-header { .home-main-header {
display: flex; display: flex;
......
...@@ -431,7 +431,8 @@ onMounted(async () => { ...@@ -431,7 +431,8 @@ onMounted(async () => {
width: 1056px; width: 1056px;
height: 1280px; height: 1280px;
margin: 0 auto; margin: 0 auto;
overflow: auto; overflow: hidden;
overflow-y: auto;
.box1-item { .box1-item {
height: 128px; height: 128px;
...@@ -456,6 +457,7 @@ onMounted(async () => { ...@@ -456,6 +457,7 @@ onMounted(async () => {
} }
.center { .center {
width: 850px;
margin-left: 18px; margin-left: 18px;
.title { .title {
......
...@@ -39,8 +39,13 @@ ...@@ -39,8 +39,13 @@
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div class="box2-main-tag-box"> <div class="box2-main-tag-box">
<div class="tag" :class="{ tagActive: activeArea === item }" v-for="(item, index) in areaList" :key="index" <div
@click="handleClickArea(item.status)"> class="tag"
:class="{ tagActive: activeArea === item }"
v-for="(item, index) in areaList"
:key="index"
@click="handleClickArea(item.status)"
>
{{ item.industryName }} {{ item.industryName }}
</div> </div>
</div> </div>
...@@ -94,13 +99,16 @@ ...@@ -94,13 +99,16 @@
</div> </div>
</div> </div>
<div class="box3-main-footer"> <div class="box3-main-footer">
<div class="info"> <div class="info">{{ total }}项调查</div>
{{ total }}项调查
</div>
<div class="page-box"> <div class="page-box">
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total" <el-pagination
@current-change="handleCurrentChange" :current-page="currentPage" /> :page-size="12"
background
layout="prev, pager, next"
:total="total"
@current-change="handleCurrentChange"
:current-page="currentPage"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -131,7 +139,6 @@ import { ...@@ -131,7 +139,6 @@ import {
getThinkTankReportContent, getThinkTankReportContent,
getThinkTankReportIndustry, getThinkTankReportIndustry,
getThinkTankReportIndustryCloud getThinkTankReportIndustryCloud
} from "@/api/thinkTank/overview"; } from "@/api/thinkTank/overview";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
const router = useRouter(); const router = useRouter();
...@@ -141,27 +148,25 @@ const box1Data = ...@@ -141,27 +148,25 @@ const box1Data =
ref(`包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。 ref(`包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。
为了应对这一挑战,兰德大学的研究人员对美中竞争进行了经济和制度分析,进行了参与式的远见练习,以了解确保美国经济健康的长期路径,并创建了两个经济竞争游戏,探索多个国家在相互交流的同时确保经济健康的动态...`); 为了应对这一挑战,兰德大学的研究人员对美中竞争进行了经济和制度分析,进行了参与式的远见练习,以了解确保美国经济健康的长期路径,并创建了两个经济竞争游戏,探索多个国家在相互交流的同时确保经济健康的动态...`);
//获取内容摘要 //获取内容摘要
const handleGetThinkTankReportAbstract = async () => { const handleGetThinkTankReportAbstract = async () => {
try { try {
const res = await getThinkTankReportAbstract(router.currentRoute._value.params.id); const res = await getThinkTankReportAbstract(router.currentRoute._value.params.id);
console.log("内容摘要", res); console.log("内容摘要", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box1Data.value = res.data box1Data.value = res.data;
} }
} catch (error) { } catch (error) {
console.error("获取内容摘要error", error); console.error("获取内容摘要error", error);
} }
}; };
// 涉及科技领域 // 涉及科技领域
const areaList = ref([]); const areaList = ref([]);
const activeArea = ref(6); const activeArea = ref(6);
const handleClickArea = area => { const handleClickArea = area => {
activeArea.value = area; activeArea.value = area;
handleGetThinkTankReportIndustryCloud() handleGetThinkTankReportIndustryCloud();
}; };
const box2Data = ref([ const box2Data = ref([
// { // {
...@@ -204,21 +209,20 @@ const handleGetThinkTankReportIndustryCloud = async () => { ...@@ -204,21 +209,20 @@ const handleGetThinkTankReportIndustryCloud = async () => {
const params = { const params = {
id: router.currentRoute._value.params.id, id: router.currentRoute._value.params.id,
industryId: activeArea.value industryId: activeArea.value
} };
const res = await getThinkTankReportIndustryCloud(params); const res = await getThinkTankReportIndustryCloud(params);
console.log("科技领域词云", res); console.log("科技领域词云", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
const data = [] const data = [];
res.data.map(item => { res.data.map(item => {
data.push( data.push({
{
name: item.clause, name: item.clause,
value: item.count value: item.count
}) });
box2Data.value = data box2Data.value = data;
const box2Chart = getWordCloudChart(box2Data.value); const box2Chart = getWordCloudChart(box2Data.value);
setChart(box2Chart, "box2Chart"); setChart(box2Chart, "box2Chart");
}) });
} }
} catch (error) { } catch (error) {
console.error("获取科技领域词云error", error); console.error("获取科技领域词云error", error);
...@@ -230,7 +234,7 @@ const handleGetThinkTankReportIndustry = async () => { ...@@ -230,7 +234,7 @@ const handleGetThinkTankReportIndustry = async () => {
const res = await getThinkTankReportIndustry(router.currentRoute._value.params.id); const res = await getThinkTankReportIndustry(router.currentRoute._value.params.id);
console.log("涉及科技领域", res); console.log("涉及科技领域", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
areaList.value = res.data areaList.value = res.data;
} }
} catch (error) { } catch (error) {
console.error("获取涉及科技领域error", error); console.error("获取涉及科技领域error", error);
...@@ -378,10 +382,10 @@ const majorOpinions = ref([ ...@@ -378,10 +382,10 @@ const majorOpinions = ref([
} }
]); ]);
// 处理页码改变事件 // 处理页码改变事件
const currentPage = ref(1) const currentPage = ref(1);
const handleCurrentChange = page => { const handleCurrentChange = page => {
currentPage.value = page; currentPage.value = page;
handleGetThinkDynamicsReport() handleGetThinkDynamicsReport();
}; };
//获取报告主要观点 //获取报告主要观点
const handleGetThinkTankReportContent = async () => { const handleGetThinkTankReportContent = async () => {
...@@ -389,19 +393,18 @@ const handleGetThinkTankReportContent = async () => { ...@@ -389,19 +393,18 @@ const handleGetThinkTankReportContent = async () => {
const res = await getThinkTankReportContent(router.currentRoute._value.params.id); const res = await getThinkTankReportContent(router.currentRoute._value.params.id);
console.log("主要观点", res); console.log("主要观点", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
majorOpinions.value = res.data.content majorOpinions.value = res.data.content;
} }
} catch (error) { } catch (error) {
console.error("获取主要观点error", error); console.error("获取主要观点error", error);
} }
}; };
onMounted(() => { onMounted(() => {
handleGetThinkTankReportAbstract() handleGetThinkTankReportAbstract();
handleGetThinkTankReportContent() handleGetThinkTankReportContent();
handleGetThinkTankReportIndustry() handleGetThinkTankReportIndustry();
handleGetThinkTankReportIndustryCloud()
handleGetThinkTankReportIndustryCloud();
}); });
</script> </script>
...@@ -506,14 +509,15 @@ onMounted(() => { ...@@ -506,14 +509,15 @@ onMounted(() => {
line-height: 30px; line-height: 30px;
letter-spacing: 0px; letter-spacing: 0px;
text-align: justify; text-align: justify;
display: -webkit-box; overflow-y: auto;
/* 使用Webkit的弹性盒模型 */ // display: -webkit-box;
-webkit-box-orient: vertical; // /* 使用Webkit的弹性盒模型 */
/* 垂直排列 */ // -webkit-box-orient: vertical;
-webkit-line-clamp: 9; // /* 垂直排列 */
/* 限制显示9行 */ // -webkit-line-clamp: 9;
overflow: hidden; // /* 限制显示9行 */
/* 隐藏超出部分 */ // overflow: hidden;
// /* 隐藏超出部分 */
} }
.box1-footer { .box1-footer {
...@@ -667,6 +671,9 @@ onMounted(() => { ...@@ -667,6 +671,9 @@ onMounted(() => {
line-height: 26px; line-height: 26px;
letter-spacing: 0px; letter-spacing: 0px;
text-align: left; text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.desc { .desc {
...@@ -678,6 +685,9 @@ onMounted(() => { ...@@ -678,6 +685,9 @@ onMounted(() => {
line-height: 22px; line-height: 22px;
letter-spacing: 0px; letter-spacing: 0px;
text-align: left; text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
} }
......
...@@ -12,8 +12,13 @@ ...@@ -12,8 +12,13 @@
<div class="box-main"> <div class="box-main">
<div class="select-box"> <div class="select-box">
<el-select v-model="box1SelectYear" placeholder="选择时间" style="width: 100px"> <el-select v-model="box1SelectYear" placeholder="选择时间" style="width: 100px">
<el-option v-for="(item, index) in box1YearList" :key="index" :label="item.label" :value="item.value" <el-option
@click="handleGetThinkPolicyIndustry()" /> v-for="(item, index) in box1YearList"
:key="index"
:label="item.label"
:value="item.value"
@click="handleGetThinkPolicyIndustry()"
/>
</el-select> </el-select>
</div> </div>
<div id="box1Chart"></div> <div id="box1Chart"></div>
...@@ -30,22 +35,32 @@ ...@@ -30,22 +35,32 @@
<div class="box-main"> <div class="box-main">
<div class="select-box"> <div class="select-box">
<el-select v-model="box2SelectYear" placeholder="选择时间" style="width: 100px"> <el-select v-model="box2SelectYear" placeholder="选择时间" style="width: 100px">
<el-option v-for="item in box2YearList" :key="item.value" :label="item.label" :value="item.value" <el-option
@click="handleGetThinkPolicyIndustryTotal()" /> v-for="item in box2YearList"
:key="item.value"
:label="item.label"
:value="item.value"
@click="handleGetThinkPolicyIndustryTotal()"
/>
</el-select> </el-select>
</div> </div>
<div id="box2Chart"> <div id="box2Chart">
<div class="box2-item" v-for="(item, index) in box2Data" :key="index"> <div class="box2-item" v-for="(item, index) in box2Data" :key="index">
<div class="icon" :style="{ background: item.color }"></div> <div class="icon" :style="{ background: item.color }"></div>
<div class="name">{{ item.industry }}</div> <div class="name">{{ item.industry }}</div>
<el-progress :show-text="false" :color="box2ColorList[index]" style="width: 220px" stroke-width="8" <el-progress
:percentage="item.percent" /> :show-text="false"
:color="box2ColorList[index]"
style="width: 170px"
stroke-width="8"
:percentage="item.percent"
/>
<div class="num">{{ item.amount + "项" }} / {{ item.totalAmount + "项" }}</div> <div class="num">{{ item.amount + "项" }} / {{ item.totalAmount + "项" }}</div>
<div class="per">{{ item.percent + "%" }}</div> <div class="per">{{ item.percent + "%" }}</div>
</div> </div>
<div class="box2-item"> <!-- <div class="box2-item">
<el-progress :percentage="50" /> <el-progress :percentage="50" />
</div> </div> -->
</div> </div>
</div> </div>
</div> </div>
...@@ -60,8 +75,13 @@ ...@@ -60,8 +75,13 @@
<div class="box-main"> <div class="box-main">
<div class="select-box"> <div class="select-box">
<el-select v-model="box3SelectYear" placeholder="选择时间" style="width: 100px"> <el-select v-model="box3SelectYear" placeholder="选择时间" style="width: 100px">
<el-option v-for="item in box3YearList" :key="item.value" :label="item.label" :value="item.value" <el-option
@click="handleGetThinkPolicyIndustryChange()" /> v-for="item in box3YearList"
:key="item.value"
:label="item.label"
:value="item.value"
@click="handleGetThinkPolicyIndustryChange()"
/>
</el-select> </el-select>
</div> </div>
<div id="box3Chart"></div> <div id="box3Chart"></div>
...@@ -80,7 +100,7 @@ ...@@ -80,7 +100,7 @@
<el-select v-model="selectedYear" placeholder="选择时间" style="width: 120px" @click="handleGetThinkPolicy()"> <el-select v-model="selectedYear" placeholder="选择时间" style="width: 120px" @click="handleGetThinkPolicy()">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
<el-select v-model="sort" placeholder="发布时间" style="width: 120px"> <el-select v-model="sort" placeholder="发布时间" style="width: 120px; margin-left: 8px">
<el-option @click="handleGetThinkPolicy()" :key="true" label="正序" :value="true" /> <el-option @click="handleGetThinkPolicy()" :key="true" label="正序" :value="true" />
<el-option @click="handleGetThinkPolicy()" :key="false" label="倒序" :value="false" /> <el-option @click="handleGetThinkPolicy()" :key="false" label="倒序" :value="false" />
</el-select> </el-select>
...@@ -99,8 +119,14 @@ ...@@ -99,8 +119,14 @@
class="filter-checkbox"> class="filter-checkbox">
{{ item }} {{ item }}
</el-checkbox> --> </el-checkbox> -->
<el-checkbox v-for="research in areaList" :key="research.id" v-model="selectedAreaList" <el-checkbox
:label="research.id" @change="handleGetThinkPolicy()" class="filter-checkbox"> style="width: 180px"
v-for="research in areaList"
:key="research.id"
v-model="selectedAreaList"
:label="research.id"
class="filter-checkbox"
>
{{ research.name }} {{ research.name }}
</el-checkbox> </el-checkbox>
</div> </div>
...@@ -141,13 +167,16 @@ ...@@ -141,13 +167,16 @@
</div> </div>
</div> </div>
<div class="right-footer"> <div class="right-footer">
<div class="info"> <div class="info">{{ total }}项调查</div>
{{ total }}项调查
</div>
<div class="page-box"> <div class="page-box">
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total" <el-pagination
@current-change="handleCurrentChange" :current-page="currentPage" /> :page-size="12"
background
layout="prev, pager, next"
:total="total"
@current-change="handleCurrentChange"
:current-page="currentPage"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -157,7 +186,7 @@ ...@@ -157,7 +186,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, watch, onMounted } from "vue";
import setChart from "@/utils/setChart"; import setChart from "@/utils/setChart";
import getPieChart from "./utils/piechart"; import getPieChart from "./utils/piechart";
import getMultiLineChart from "./utils/multiLineChart"; import getMultiLineChart from "./utils/multiLineChart";
...@@ -237,19 +266,19 @@ const handleGetThinkPolicyIndustry = async () => { ...@@ -237,19 +266,19 @@ const handleGetThinkPolicyIndustry = async () => {
const parmas = { const parmas = {
id: router.currentRoute._value.params.id, id: router.currentRoute._value.params.id,
year: box1SelectYear.value year: box1SelectYear.value
} };
const res = await getThinkPolicyIndustry(parmas); const res = await getThinkPolicyIndustry(parmas);
console.log("提出建议领域分布", res); console.log("提出建议领域分布", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
let data = [] let data = [];
res.data.map(item => { res.data.map(item => {
data.push({ data.push({
name: item.industry, name: item.industry,
value: item.amount, value: item.amount,
percent: item.percent percent: item.percent
}) });
}) });
box1Data.value = data box1Data.value = data;
const box1Chart = getPieChart(box1Data.value); const box1Chart = getPieChart(box1Data.value);
setChart(box1Chart, "box1Chart"); setChart(box1Chart, "box1Chart");
} }
...@@ -303,7 +332,7 @@ const box2Data = ref([ ...@@ -303,7 +332,7 @@ const box2Data = ref([
// color: "#69B1FF" // color: "#69B1FF"
// } // }
]); ]);
const box2ColorList = ref(["#CE4F51", "#055FC2", "#13A8A8", "#722ED1", "#FA8C16", "#69B1FF"]) const box2ColorList = ref(["#CE4F51", "#055FC2", "#13A8A8", "#722ED1", "#FA8C16", "#69B1FF"]);
const box2SelectYear = ref("2025"); const box2SelectYear = ref("2025");
const box2YearList = ref([ const box2YearList = ref([
{ {
...@@ -325,11 +354,11 @@ const handleGetThinkPolicyIndustryTotal = async () => { ...@@ -325,11 +354,11 @@ const handleGetThinkPolicyIndustryTotal = async () => {
const parmas = { const parmas = {
id: router.currentRoute._value.params.id, id: router.currentRoute._value.params.id,
year: box2SelectYear.value year: box2SelectYear.value
} };
const res = await getThinkPolicyIndustryTotal(parmas); const res = await getThinkPolicyIndustryTotal(parmas);
console.log("相关政策领域分布", res); console.log("相关政策领域分布", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
box2Data.value = res.data box2Data.value = res.data;
} }
} catch (error) { } catch (error) {
console.error("获取相关政策领域分布error", error); console.error("获取相关政策领域分布error", error);
...@@ -372,7 +401,7 @@ const handleGetThinkPolicyIndustryChange = async () => { ...@@ -372,7 +401,7 @@ const handleGetThinkPolicyIndustryChange = async () => {
const parmas = { const parmas = {
id: router.currentRoute._value.params.id, id: router.currentRoute._value.params.id,
year: box3SelectYear.value year: box3SelectYear.value
} };
const res = await getThinkPolicyIndustryChange(parmas); const res = await getThinkPolicyIndustryChange(parmas);
console.log("热门研究方向变化趋势", res); console.log("热门研究方向变化趋势", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
...@@ -404,7 +433,7 @@ const handleGetThinkPolicyIndustryChange = async () => { ...@@ -404,7 +433,7 @@ const handleGetThinkPolicyIndustryChange = async () => {
}; };
frontendData.data.push(industryData); frontendData.data.push(industryData);
}); });
box3Data.value = frontendData box3Data.value = frontendData;
let box3Chart = getMultiLineChart( let box3Chart = getMultiLineChart(
box3Data.value.title, box3Data.value.title,
box3Data.value.data[0].value, box3Data.value.data[0].value,
...@@ -439,8 +468,7 @@ const selectedYear = ref(1); ...@@ -439,8 +468,7 @@ const selectedYear = ref(1);
// 科技领域 // 科技领域
const areaList = ref([]); const areaList = ref([]);
const selectedAreaList = ref(null); const selectedAreaList = ref([]);
//获取科技领域 //获取科技领域
const handleGetHylyList = async () => { const handleGetHylyList = async () => {
...@@ -448,7 +476,7 @@ const handleGetHylyList = async () => { ...@@ -448,7 +476,7 @@ const handleGetHylyList = async () => {
const res = await getHylyList(); const res = await getHylyList();
console.log("智库研究类型信息", res); console.log("智库研究类型信息", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
areaList.value = res.data areaList.value = res.data;
} }
} catch (error) { } catch (error) {
console.error("获取研究类型error", error); console.error("获取研究类型error", error);
...@@ -506,115 +534,8 @@ const policyList = ref([ ...@@ -506,115 +534,8 @@ const policyList = ref([
// } // }
// ] // ]
// }, // },
// {
// img: Img2,
// title: "考虑采取更全面的方法来打击全球供应链中强迫劳动使用的选项。",
// time: "2025年3月15日",
// desc: " 美国贸易执法是否发挥了作用,能否做得更多?",
// tagList: ["人工智能", "集成电路"],
// fileList: [
// {
// type: "法案",
// title: "2024《维吾尔强迫劳动预防法》"
// }
// ]
// },
// {
// img: Img2,
// title: "与利益相关者共同收集证据,为关于贸易执法的公共讨论提供信息。",
// time: "2025年3月15日",
// desc: "美国贸易执法是否发挥了作用,能否做得更多?",
// tagList: ["人工智能", "集成电路"],
// fileList: [
// {
// type: "法案",
// title: "2024《维吾尔强迫劳动预防法》"
// }
// ]
// },
// {
// img: Img2,
// title: "推动清洁能源生产供内用,化石燃料重新配置出口。",
// time: "2025年6月26日",
// desc: "美国贸易执法是否发挥了作用,能否做得更多?",
// tagList: ["人工智能", "集成电路"],
// fileList: [
// {
// type: "法案",
// title: "2024《重塑美国人口结构法案》"
// },
// {
// type: "法案",
// title: "2024《重塑美国人口结构法案》"
// }
// ]
// },
// {
// img: Img2,
// title: "允许OPT的国际学生出国旅行并持多次入境签证重新进入美国。",
// time: "2025年6月26日",
// desc: "中美经济竞争:复杂经济和地缘政治关系中的收益与风险",
// tagList: ["人工智能", "集成电路"],
// fileList: [
// {
// type: "法案",
// title: "2024《重塑美国人口结构法案》"
// },
// {
// type: "法案",
// title: "2025《开放人才法案》"
// }
// ]
// },
// {
// img: Img3,
// title: "增加中国公民可获得的 H-1B 签证数量。",
// time: "2025年6月26日",
// desc: "中美经济竞争:复杂经济和地缘政治关系中的收益与风险",
// tagList: ["人工智能", "集成电路"],
// fileList: [
// {
// type: "法案",
// title: "2024《重塑美国人口结构法案》"
// },
// {
// type: "法案",
// title: "2025《GENIUS法案》"
// }
// ]
// },
// {
// img: Img3,
// title: "通过就业偏好类别增加绿卡的数量。",
// time: "2025年6月26日",
// desc: "中美经济竞争:复杂经济和地缘政治关系中的收益与风险",
// tagList: ["人工智能", "集成电路"],
// fileList: [
// {
// type: "法案",
// title: "2024《重塑美国人口结构法案》"
// },
// {
// type: "法案",
// title: "2025《开放人才法案》"
// }
// ]
// },
// {
// img: Img4,
// title: "推动清洁能源生产供内用,化石燃料重新配置出口。",
// time: "2025年6月26日",
// desc: "美国传统能源产业的未来:是走向终结还是持续发展?",
// tagList: ["人工智能", "集成电路"],
// fileList: [
// {
// type: "法案",
// title: "2024《能源法案》"
// }
// ]
// }
]);
]);
//获取当前时间x年前的日期 //获取当前时间x年前的日期
function getDateYearsAgo(years) { function getDateYearsAgo(years) {
...@@ -629,12 +550,13 @@ function getDateYearsAgo(years) { ...@@ -629,12 +550,13 @@ function getDateYearsAgo(years) {
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
} }
const sort = ref(true) const total = ref(0);
const currentPage = ref(1) const sort = ref(true);
const currentPage = ref(1);
// 处理页码改变事件 // 处理页码改变事件
const handleCurrentChange = page => { const handleCurrentChange = page => {
currentPage.value = page; currentPage.value = page;
handleGetThinkDynamicsReport() handleGetThinkPolicy();
}; };
const handleGetThinkPolicy = async () => { const handleGetThinkPolicy = async () => {
...@@ -642,31 +564,35 @@ const handleGetThinkPolicy = async () => { ...@@ -642,31 +564,35 @@ const handleGetThinkPolicy = async () => {
const parmas = { const parmas = {
id: router.currentRoute._value.params.id, id: router.currentRoute._value.params.id,
startDate: getDateYearsAgo(selectedYear.value), startDate: getDateYearsAgo(selectedYear.value),
parmas: {
sortFun: sort.value, sortFun: sort.value,
currentPage: currentPage.value, currentPage: currentPage.value,
pageSize: 12, pageSize: 10,
researchTypeIds: selectedAreaList.value ? selectedAreaList.value : null, researchTypeIds: selectedAreaList.value.join(',')
} };
}
const res = await getThinkPolicy(parmas); const res = await getThinkPolicy(parmas);
console.log("智库政策", res); console.log("智库政策", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
policyList.value = res.data.content policyList.value = res.data.content;
total.value = res.data.totalElements total.value = res.data.totalElements;
} }
} catch (error) { } catch (error) {
console.error("获取智库政策error", error); console.error("获取智库政策error", error);
} }
}; };
onMounted(() => { watch(
handleGetThinkPolicyIndustry() () => selectedAreaList.value,
handleGetThinkPolicyIndustryTotal() val => {
handleGetThinkPolicyIndustryChange() handleGetThinkPolicy();
handleGetHylyList() }
handleGetThinkPolicy() );
onMounted(() => {
handleGetThinkPolicyIndustry();
handleGetThinkPolicyIndustryTotal();
handleGetThinkPolicyIndustryChange();
handleGetHylyList();
handleGetThinkPolicy();
}); });
</script> </script>
...@@ -752,6 +678,8 @@ onMounted(() => { ...@@ -752,6 +678,8 @@ onMounted(() => {
margin: 0 auto; margin: 0 auto;
margin-top: 50px; margin-top: 50px;
height: 300px; height: 300px;
overflow: hidden;
overflow-y: auto;
.box2-item { .box2-item {
height: 30px; height: 30px;
...@@ -766,7 +694,7 @@ onMounted(() => { ...@@ -766,7 +694,7 @@ onMounted(() => {
} }
.name { .name {
width: 80px; width: 120px;
margin-left: 7px; margin-left: 7px;
margin-right: 23px; margin-right: 23px;
height: 24px; height: 24px;
...@@ -780,7 +708,7 @@ onMounted(() => { ...@@ -780,7 +708,7 @@ onMounted(() => {
} }
.num { .num {
width: 80px; width: 100px;
margin-left: 10px; margin-left: 10px;
height: 22px; height: 22px;
color: rgba(95, 101, 108, 1); color: rgba(95, 101, 108, 1);
...@@ -860,7 +788,7 @@ onMounted(() => { ...@@ -860,7 +788,7 @@ onMounted(() => {
.left { .left {
width: 300px; width: 300px;
height: 483px; height: 800px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1); border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px; border-radius: 10px;
...@@ -869,7 +797,6 @@ onMounted(() => { ...@@ -869,7 +797,6 @@ onMounted(() => {
.select-box { .select-box {
margin-top: 21px; margin-top: 21px;
.select-box-header { .select-box-header {
display: flex; display: flex;
gap: 17px; gap: 17px;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
{{ thinkTank.describe }} {{ thinkTank.describe }}
</div> </div>
<div class="center-footer"> <div class="center-footer">
<div class="tag" v-for="tag in thinkTank.tags">{{ tag.industryName }}</div> <div class="tag" v-for="tag,index in thinkTank.tags" :key="index">{{ tag.industryName }}</div>
</div> </div>
</div> </div>
...@@ -114,7 +114,10 @@ onMounted(async () => { ...@@ -114,7 +114,10 @@ onMounted(async () => {
.header-top-left { .header-top-left {
width: 88px; width: 88px;
height: 88px; height: 88px;
background: purple; img{
width: 100%;
height: 100%;
}
} }
.header-top-center { .header-top-center {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<el-option @click="handleGetThinkDynamicsReport()" v-for="item in yearList" :key="item.value" <el-option @click="handleGetThinkDynamicsReport()" v-for="item in yearList" :key="item.value"
:label="item.label" :value="item.value" /> :label="item.label" :value="item.value" />
</el-select> </el-select>
<el-select v-model="sort" placeholder="发布时间" style="width: 120px"> <el-select v-model="sort" placeholder="发布时间" style="width: 120px; margin-left: 8px;">
<el-option @click="handleGetThinkDynamicsReport()" :key="true" label="正序" :value="true" /> <el-option @click="handleGetThinkDynamicsReport()" :key="true" label="正序" :value="true" />
<el-option @click="handleGetThinkDynamicsReport()" :key="false" label="倒序" :value="false" /> <el-option @click="handleGetThinkDynamicsReport()" :key="false" label="倒序" :value="false" />
</el-select> </el-select>
...@@ -503,6 +503,9 @@ onMounted(async () => { ...@@ -503,6 +503,9 @@ onMounted(async () => {
font-size: 18px; font-size: 18px;
font-weight: 700; font-weight: 700;
line-height: 24px; line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.footer-card-footer { .footer-card-footer {
......
...@@ -335,12 +335,10 @@ ...@@ -335,12 +335,10 @@
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange"> <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">
全部领域 全部领域
</el-checkbox> </el-checkbox>
<el-checkbox-group v-model="selectedAreaList"> <el-checkbox v-for="research in areaList" :key="research.id" v-model="selectedAreaList"
<el-checkbox v-for="(research, index) in areaList" :key="index" :label="research.id" :label="research.id" @change="handleCheckedAreaChange()" class="filter-checkbox">
@change="handleCheckedAreaChange()" class="filter-checkbox">
{{ research.name }} {{ research.name }}
</el-checkbox> </el-checkbox>
</el-checkbox-group>
</div> </div>
</div> </div>
</div> </div>
...@@ -1302,9 +1300,15 @@ onMounted(async () => { ...@@ -1302,9 +1300,15 @@ onMounted(async () => {
} }
.home-wrapper { .home-wrapper {
width: 100%;
height: calc(100vh - 96px);
position: relative;
overflow-y: hidden;
.home-main { .home-main {
width: 1920px; width: 100%;
margin: 0 auto; height: 100%;
overflow-y: auto;
background: url("./assets/images/background.png"); background: url("./assets/images/background.png");
background-size: 100% 100%; background-size: 100% 100%;
...@@ -1528,6 +1532,9 @@ onMounted(async () => { ...@@ -1528,6 +1532,9 @@ onMounted(async () => {
font-weight: 400; font-weight: 400;
line-height: 32px; line-height: 32px;
letter-spacing: 0px; letter-spacing: 0px;
overflow: hidden;
// text-overflow: ellipsis;
// white-space: nowrap;
} }
.rank1 { .rank1 {
......
# 交互消息类
## ApiResult
```java
public class ApiResult<T> {
@ApiModelProperty("响应码")
private int code;
@ApiModelProperty("响应消息")
private String message;
@ApiModelProperty("是否成功")
private boolean success;
@ApiModelProperty("响应数据")
private T data;
}
```
## LatestExportControlInfo
```java
public class LatestExportControlInfo {
// 出口管制事件ID
private String id;
// 管制信息标题
private String name;
// 管制内容简述
private String summary;
// 发布机构名称
private String postOrgName;
// 发布时间
private Date postDate;
// 涉及领域
private List<String> domains;
// 涉及中国实体数
private Integer cnEntityCount;
// 涉及主要实体
private List<SanctionListBean> sanEntities;
}
```
## AnnualCount
```java
public class AnnualCount {
// 年份
private Integer year;
// 数量
private Integer count;
// 领域列表
private List<String> domain;
}
```
## DomainCount
```java
public class DomainCount {
// 制裁类型名称
private String sanTypeName;
// 领域统计信息
private List<BaseCount> domainCountInfo;
}
```
## BaseCount
```java
public class BaseCount {
// 统计名称
private String name;
// 数量
private Integer count;
}
```
## ExportPageQuery
```java
public class ExportPageQuery extends BasePageQuery {
// 类型名称(实体清单)
private String typeName;
// 制裁时间
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date sanctionDate;
// 是否只看中国实体
private Boolean isCn;
}
```
## BasePageQuery
```java
public class BasePageQuery {
// 查询页
private Integer pageNum = 1;
// 每页数量
private Integer pageSize = 10;
// 排序字段
private String sortField;
// 排序方式
private String sortOrder;
}
```
## SanctionProcess
```java
public class SanctionProcess {
// 制裁事件ID
private String id;
// 制裁时间
private Date postDate;
// 制裁标题
private String name;
// 制裁内容简述
private String summary;
// 涉及中国实体数
private Integer cnEntityCount;
}
```
## SanctionListBean
```java
public class SanctionListBean extends BaseBean {
@Id
@Column(name = "ID", nullable = false)
private String id;
@Column(name = "ENTITY_NAME")
private String entityName;
@Column(name = "SAN_TYPE_ID")
private Integer sanTypeId;
@Column(name = "ENTITY_TYPE")
private Integer entityType;
@Column(name = "ENTITY_ID")
private String entityId;
@Column(name = "ENTITY_NAME_ZH")
private String entityNameZh;
@Column(name = "COUNTRY_ID")
private String countryId;
@Column(name = "SAN_REASON")
private String sanReason;
@Column(name = "SAN_INTENSITY")
private char sanIntensity;
@Column(name = "START_TIME")
private Date startTime;
@Column(name = "END_TIME")
private Date endTime;
@Column(name = "IS_KEY")
private char isKey;
@Transient
private List<TechDomainBean> techDomainList;
/**
* 领域列表
*/
@Transient
private List<String> techDomains;
/**
* 50%规则子企业数
*/
@Transient
private Integer ruleOrgCount;
// 50%规则子企业列表
@Transient
private List<Organization> ruleOrgList;
}
```
## OrgInfo
```java
public class OrgInfo {
// 机构id
private String id;
// 机构名称
private String orgName;
// 机构中文名称
private String orgNameZh;
// 相关制裁措施列表
private List<String> sanTypeList;
// 机构职责
private String orgDuty;
// 机构图片
private String imageUrl;
// 人员列表
private List<PersonInfo> personList;
// 领域列表
private List<String> domainList;
// 市值
private Double marketValue;
// 市值变化(-1:降低;0:持平:1:上升)
private Integer marketChange;
// 地址
private String address;
// 类型
private String orgType;
// 行业
private List<String> industryList;
// 科研仪器数
private Integer instrumentNum;
}
```
## PersonInfo
```java
public class PersonInfo {
// id
private String id;
// 人物类别
private Integer type;
// 姓名
private String name;
// 党派
private String party;
// 职位
private String position;
// 头像链接
private String imageUrl;
}
```
## SanCountInfo
```java
public class SanCountInfo {
// 实体数
private Integer entityNum;
// 实体变动数
private Integer entityChange;
// 上市公司数
private Integer listedCompanyNum;
// 上市公司变动数
private Integer listedCompanyChange;
// 涉及领域名数
private Integer domainNum;
// 涉及领域变动数
private Integer domainChange;
// 实体类型数
private Integer typeNum;
// 实体类型变动数
private Integer typeChange;
}
```
## Chain
```java
public class Chain {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// 名称
@Column(name = "name")
private String name;
// 中文名称
@Column(name = "name_zh")
private String nameZh;
// 值
@Column(name = "description")
private String description;
// 父级id
@Column(name = "parent_id")
private Integer parentId;
// 是否为产业链主分支
@Column(name = "is_main_branch")
private String isMainBranch;
// 下属产业链分支
@Transient
private List<Chain> children;
}
```
## FishboneResp
```java
public class FishboneResp<T> {
private String text;
private List<T> causes;
}
```
## AreasStreamResp
```java
public class AreasStreamResp {
// 上游国内企业数量
private int upstreamInternalCount;
// 上游国内占比
private double upstreamInternalRate;
// 上游受制裁企业数量
private int upstreamEntityCount;
// 上游受制裁占比
private double upstreamEntityRate;
// 中游国内企业数量
private int midstreamInternalCount;
// 中游国内占比
private double midstreamInternalRate;
// 中游受制裁企业数量
private int midstreamEntityCount;
// 中游受制裁占比
private double midstreamEntityRate;
// 下游国内企业数量
private int downstreamInternalCount;
// 下游国内占比
private double downstreamInternalRate;
// 下游受制裁企业数量
private int downstreamEntityCount;
// 下游受制裁占比
private double downstreamEntityRate;
}
```
## AnnualDomainQuery
```java
public class AnnualDomainQuery {
// 开始年份
private Integer startYear;
// 结束年份
private Integer endYear;
// 是否考虑50%规则
private Boolean isRule;
}
```
## AnnualDomainCount
```java
public class AnnualDomainCount {
// 年度领域统计
private List<DomainCount> yearDomainCount;
// 所有领域
private List<BaseCount> domians;
}
```
## SanctionTypeBean
```java
public class SanctionTypeBean extends BaseBean {
@Id
@Column(name = "ID", nullable = false)
private Integer id;
@Column(name = "NAME")
private String name;
@Column(name = "NAME_ZH")
private String nameZh;
@Column(name = "NAME_ABBR")
private String nameAbbr;
@Column(name = "DESCRIPTION")
private String description;
// 发布国家
@Column(name = "POST_COUNTRY_ID")
private String postCountryId;
// 发布机构
@Column(name = "POST_ORG_ID")
private String postOrgId;
// 是否出口管制 1:是 0:否
@Column(name = "IS_EXPORT_CONTROL")
private String isExportControl;
// 总发布次数
@Transient
private Integer postCount;
}
```
## Organization
```java
public class Organization extends BaseBean {
// 机构id
@Id
@Column(name = "id", nullable = false)
private String id;
// 机构名称
@Column(name = "org_name", nullable = false)
private String orgName;
// 组织机构代码
@Column(name = "uscc")
private String uscc;
// 机构简称
@Column(name = "org_abb")
private String orgAbb;
// 机构英文名称
@Column(name = "org_name_en")
private String orgNameEn;
// 机构英文简称
@Column(name = "org_abb_en")
private String orgAbbEn;
// 机构别名
@Column(name = "org_alias")
private String orgAlias;
// 机构曾用名
@Column(name = "org_former_name")
private String orgFormerName;
// 机构类型id
@Column(name = "org_type_id")
private Long orgTypeId;
// 机构简介
@Column(name = "org_introduction")
private String orgIntroduction;
// 营业范围
@Column(name = "business_scope")
private String businessScope;
// 行业id
@Column(name = "domain_ids")
private String domainIds;
// 行业代码
@Column(name = "economic_industry_code")
private String economicIndustryCode;
// 经济行业名称
@Column(name = "economic_industry_name")
private String economicIndustryName;
// 国家id
@Column(name = "country_id")
private String countryId;
// 省份
@Column(name = "province")
private String province;
// 城市
@Column(name = "city")
private String city;
// 区县
@Column(name = "county")
private String county;
// 详细地址
@Column(name = "address")
private String address;
// 成立时间
@Column(name = "establishment_date")
private LocalDate establishmentDate;
// 变更时间
@Column(name = "issuing_date")
private String issuingDate;
// 营业期限自
@Column(name = "operation_period_from")
private String operationPeriodFrom;
// 营业期限至
@Column(name = "operation_period_until")
private String operationPeriodUntil;
// 营业状态
@Column(name = "business_status")
private String businessStatus;
// 法人id
@Column(name = "legal_representative_id")
private String legalRepresentativeId;
/// 法人
@Column(name = "legal_representative")
private String legalRepresentative;
// 联系电话
@Column(name = "telephone")
private String telephone;
// 邮箱
@Column(name = "email")
private String email;
// 邮政编码
@Column(name = "postcode")
private String postcode;
// 网址
@Column(name = "url")
private String url;
// 员工人数
@Column(name = "number_of_employees")
private String numberOfEmployees;
// 注册资金
@Column(name = "registered_capital")
private String registeredCapital;
// LOGO链接
@Column(name = "logo_url")
private String logoUrl;
@Column(name = "create_by")
private String createBy;
@Column(name = "update_by")
private String updateBy;
@Column(name = "p_org_id")
private String pOrgId;
}
```
## EventInfo
```java
public class EventInfo extends BaseBean {
@Id
@Column(name = "id")
@ApiModelProperty(value = "唯一标识")
private String id;
@Column(name = "title")
@ApiModelProperty(value = "标题")
private String title;
@Column(name = "event_time")
@ApiModelProperty(value = "事件时间")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date eventTime;
@Column(name = "summary")
@ApiModelProperty(value = "摘要")
private String summary;
@Column(name = "summary_zh")
@ApiModelProperty(value = "摘要译文")
private String summaryZh;
@Column(name = "event_type")
@ApiModelProperty(value = "事件类别")
private String eventType;
@Column(name = "CONTENT")
@ApiModelProperty(value = "主要内容")
private String content;
@Column(name = "title_zh")
@ApiModelProperty(value = "标题译文")
private String titleZh;
@Column(name = "content_zh")
@ApiModelProperty(value = "主要内容译文")
private String contentZh;
@Column(name = "type")
@ApiModelProperty(value = "事件类别")
private String type;
@Column(name = "LOCATION")
@ApiModelProperty(value = "事件地点")
private String location;
@Column(name = "country")
@ApiModelProperty(value = "国家")
private String country;
}
```
## RegionCount
```java
public class RegionCount {
// 名称
private String name;
// 数量
private Integer count;
// 经度
private Double lon;
// 纬度
private Double lat;
}
```
## EventQuery
```java
public class EventQuery extends BasePageQuery {
// 制裁记录ID (暂时无作用,后续根据ID查)
private Integer sanctionId;
// 制裁时间
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date sanctionDate;
}
```
## RuleEntityCount
```JAVA
public class RuleEntityCount {
// 总数
private Integer totalCount;
// 50%规则关联数
private Integer ruleCount;
}
```
## RiskSignalVO
```java
public class RiskSignalVO {
@ApiModelProperty("风险信号id")
private Long signalId;
@ApiModelProperty("风险信号标题")
private String signalTitle;
@ApiModelProperty("风险信号时间")
private LocalDate signalTime;
@ApiModelProperty("风险信号等级")
private String signalLevel;
@ApiModelProperty("风险信号关联法案id")
private String billId;
@ApiModelProperty("风险信号关联政令id")
private Long orderId;
@ApiModelProperty("风险信号关联报告id")
private String reportId;
@ApiModelProperty("风险信号关联制裁id")
private Integer sanId;
}
```
## NewsVO
```java
public class NewsVO {
@ApiModelProperty(value = "新闻id")
private String newsId;
@ApiModelProperty(value = "新闻时间")
private LocalDate newsDate;
@ApiModelProperty(value = "新闻内容")
private String newsContent;
@ApiModelProperty(value = "新闻标题")
private String newsTitle;
@ApiModelProperty(value = "新闻机构")
private String newsOrg;
@ApiModelProperty(value = "新闻图片")
private String newsImage;
}
```
## RemarksVO
```java
public class RemarksVO {
@ApiModelProperty(value = "人物id")
private String personId;
@ApiModelProperty(value = "人物图像")
private String personImage;
@ApiModelProperty(value = "人物名称")
private String personName;
@ApiModelProperty(value = "言论ID")
private Long remarksId;
@ApiModelProperty(value = "人物言论")
private String remarks;
@ApiModelProperty(value = "时间")
private LocalDateTime time;
@ApiModelProperty(value = "言论平台名称")
private String orgName;
}
```
# 字典
## 领域类别(id:name)
1:人工智能、2:生物科技、3:新一代信息技术、4:量子科技、5:新能源、6:集成电路、7:海洋、8:先进制造、9:新材料、10:航空航天、11:深海、12:极地、13:太空、14:核
## 实体类别(id:name)
1:人物、2:机构、7:地址
## 人物类别(待定)
1:政府官员、2:科技领袖、3:顶级科学家、4:国会议员
# 出口管制
## **获取出口管制类清单统计信息**
请求地址:/sanctionList/export/getTotalInfo
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<List<SanctionTypeBean>>
## 最新出口管制政策(4条)
请求地址:/entitiesDataInfo/getLatestInfo
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<LatestExportControlInfo>
## 发布(更新)频度
请求地址:/entitiesDataCount/getAnnualCount
请求类型:GET
输入参数:
​ 参数:Integer sanTypeId(制裁类别)
​ 实体清单发布频度:1;CCL发布频度:13
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<List<AnnualCount>>
## **制裁领域分析**(20251215)
请求地址:/entitiesDataCount/getSanDomainCount
请求类型:GET
输入参数:
​ 参数:Boolean rule(是否勾选50%规则)
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<List<DomainCount>>
## **历次制裁过程**
请求地址:/entitiesDataCount/getSanctionProcess
请求类型:POST
输入参数:
​ 参数:ExportPageQuery exportPageQuery
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<Page<SanctionProcess>>
## **制裁实体清单**列表(20251215)
请求地址:/sanctionList/pageQuery
请求类型:POST
输入参数:
​ 参数:ExportPageQuery exportPageQuery
​ 出口管制-概览页请求时:typeName=实体清单
​ 实体清单-制裁概览页请求时:typeName=实体清单,sanctionDate=该次制裁的具体时间
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<Page<SanctionListBean>>
## **发布机构与重点人物**
请求地址:/sanctionList/getPublishedOrg
请求类型:GET
输入参数:
​ 参数:Integer sanTypeId
​ 暂时固定输入:1;对应实体清单发布机构
​ 请求头:携带token
输出结果:ApiResult<OrgInfo>
## **领域分布查询**
请求地址:/entitiesDataInfo/getDomianDistribution
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **类型分布查询**
请求地址:/entitiesDataInfo/getTypeDistribution
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **区域分布查询**
请求地址:/entitiesDataInfo/getRegionDistribution
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<RegionCount>>
## **制裁理由查询**
请求地址:/entitiesDataInfo/getSanReason
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<String>>
## **深度挖掘-制裁信息变化统计**
请求地址:/entitiesDataInfo/getSanCountInfo
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<SanCountInfo>
## **年度实体数统计**
请求地址:/entitiesDataInfo/getCountByDomianAndType
请求类型:GET
输入参数:
​ 参数:String domianId (非必需,领域类别ID),Integer typeId (非必需,实体类别ID)
​ 参考字典
​ 请求头:携带token
输出结果:ApiResult<SanCountInfo>
## **重点实体列表查询**
请求地址:/entitiesDataInfo/getKeyEntities
请求类型:GET
输入参数:
​ 参数:String sanctionDate(必需),String searchText(非必需,检索文本)
​ 请求头:携带token
输出结果:ApiResult<List<OrgInfo>>
## **上市企业制裁强度**
请求地址:/entitiesDataInfo/listedEntity/sanInfo
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **上市企业融资变化情况**
请求地址:/entitiesDataInfo/listedEntity/financing
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **上市企业市值变化情况**
请求地址:/entitiesDataInfo/listedEntity/market
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **重点上市企业列表**
请求地址:/entitiesDataInfo/listedEntity/keyEntity
请求类型:GET
输入参数:
​ 参数:String sanctionDate(必需),String searchText(非必需,检索文本)
​ 请求头:携带token
输出结果:ApiResult<List<OrgInfo>>
## **历次制裁涉及领域数查询**
请求地址:/entitiesDataInfo/getPreviousDomian
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **具体领域的制裁实体数统计**
请求地址:/entitiesDataInfo/getDomianAnnual
请求类型:GET
输入参数:
​ 参数:String domainId
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **具体实体类型的制裁实体数统计**
请求地址:/entitiesDataInfo/getEntityTypeAnnual
请求类型:GET
输入参数:
​ 参数:Integer entityTypeId
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **产业链结构查询**
请求地址:/chain/getChainTree
请求类型:GET
输入参数:
​ 参数:Integer chainId,非必需
​ 请求头:携带token
输出结果:ApiResult<List<Chain>>
## **根据领域获取产业链信息**
请求地址:/chain/getChainInfo
请求类型:GET
输入参数:
​ 参数:Integer domainId,领域ID
​ 请求头:携带token
输出结果:ApiResult<List<Chain>>
## **产业链鱼骨图信息查询**
请求地址:/chain/getChainFishbone
请求类型:GET
输入参数:
​ 参数:Integer chainId
​ 请求头:携带token
输出结果:ApiResult<FishboneResp>
## **产业链中国企业实体信息查询**
请求地址:/chain/getChainEntityStat
请求类型:GET
输入参数:
​ 参数:Integer chainId
​ 请求头:携带token
输出结果:ApiResult<AreasStreamResp>
## **实体列表查询**
请求地址:/entitiesDataInfo/getEntityList
请求类型:GET
输入参数:
​ 参数:String sanctionDate(制裁时间),String domainId(领域ID)
​ 请求头:携带token
输出结果:ApiResult<List<OrgInfo>>
## **历年制裁领域统计**
请求地址:/entitiesDataCount/getAnnualSanDomain
请求类型:POST
输入参数:
​ 参数:AnnualDomainQuery annualDomainQuery
​ 请求头:携带token
输出结果:ApiResult<List<AnnualDomainCount>>
## **新增实体数量增长趋势**
请求地址:/entitiesDataInfo/yoyComparison
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **获取机构的详情信息**
请求地址:/organization/getDetail/{id}
请求类型:GET
输入参数:
​ 参数:机构ID
​ 请求头:携带token
输出结果:ApiResult<Organization>
## **获取美国前序事件**
请求地址:/entitiesDataInfo/precedingEvents
请求类型:POST
输入参数:
​ 参数:EventQuery eventQuery
​ 请求头:携带token
输出结果:ApiResult<Page<EventInfo>>
## **新增科研机构列表**
请求地址:/entitiesDataInfo/scientificImpact/entityList
请求类型:GET
输入参数:
​ 参数:String sanctionDate
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **各类别仪器对美依赖情况**
请求地址:/instrument/getDependencyUS
请求类型:GET
输入参数:
​ 参数:List<String> orgIds 机构公司ID列表
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **仪器对美依赖度升高风险分析**
请求地址:/instrument/getDependencyUSRisk
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **仪器进口国可替代性分析**
请求地址:/instrument/getOriginCount
请求类型:GET
输入参数:
​ 参数:List<String> orgIds 机构公司ID列表
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **仪器国产化降低风险分析**
请求地址:/instrument/getLocalizationRisk
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **制裁实体清单50%规则实体数**
请求地址:/sanctionList/getRuleCount
请求类型:POST
输入参数:
​ 参数:ExportPageQuery exportPageQuery
​ 请求头:携带token
输出结果:ApiResult<RuleEntityCount>
## **科研院所类实体历史制裁情况**
请求地址:/entitiesDataInfo/annual/researchInstitute
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **企业类实体历史制裁情况**
请求地址:/entitiesDataInfo/annual/enterprise
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **风险信号**
请求地址:/commonFeature/riskSignal/{moduleId}
请求类型:GET
输入参数:
​ 参数:moduleId
​ 请求头:携带token
输出结果:ApiResult<List<RiskSignalVO>>
## **新闻资讯**
请求地址:/commonFeature/news/{moduleId}
请求类型:GET
输入参数:
​ 参数:moduleId
​ 请求头:携带token
输出结果:ApiResult<List<NewsVO>>
## **社交媒体**
请求地址:/commonFeature/remarks/{moduleId}
请求类型:GET
输入参数:
​ 参数:moduleId
​ 请求头:携带token
输出结果:ApiResult<List<RemarksVO>>
\ No newline at end of file
# 交互消息类
## ApiResult
```java
public class ApiResult<T> {
@ApiModelProperty("响应码")
private int code;
@ApiModelProperty("响应消息")
private String message;
@ApiModelProperty("是否成功")
private boolean success;
@ApiModelProperty("响应数据")
private T data;
}
```
## LatestExportControlInfo
```java
public class LatestExportControlInfo {
// 出口管制事件ID
private String id;
// 管制信息标题
private String name;
// 管制内容简述
private String summary;
// 发布机构名称
private String postOrgName;
// 发布时间
private Date postDate;
// 涉及领域
private List<String> domains;
// 涉及中国实体数
private Integer cnEntityCount;
// 涉及主要实体
private List<SanctionListBean> sanEntities;
}
```
## AnnualCount
```java
public class AnnualCount {
// 年份
private Integer year;
// 数量
private Integer count;
// 领域列表
private List<String> domain;
}
```
## DomainCount
```java
public class DomainCount {
// 制裁类型名称
private String sanTypeName;
// 领域统计信息
private List<BaseCount> domainCountInfo;
}
```
## BaseCount
```java
public class BaseCount {
// 统计名称
private String name;
// 数量
private Integer count;
}
```
## ExportPageQuery
```java
public class ExportPageQuery extends BasePageQuery {
// 类型名称(实体清单)
private String typeName;
// 制裁时间
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date sanctionDate;
// 是否只看中国实体
private Boolean isCn;
}
```
## BasePageQuery
```java
public class BasePageQuery {
// 查询页
private Integer pageNum = 1;
// 每页数量
private Integer pageSize = 10;
// 排序字段
private String sortField;
// 排序方式
private String sortOrder;
}
```
## SanctionProcess
```java
public class SanctionProcess {
// 制裁事件ID
private String id;
// 制裁时间
private Date postDate;
// 制裁标题
private String name;
// 制裁内容简述
private String summary;
// 涉及中国实体数
private Integer cnEntityCount;
}
```
## SanctionListBean
```java
public class SanctionListBean extends BaseBean {
@Id
@Column(name = "ID", nullable = false)
private String id;
@Column(name = "ENTITY_NAME")
private String entityName;
@Column(name = "SAN_TYPE_ID")
private Integer sanTypeId;
@Column(name = "ENTITY_TYPE")
private Integer entityType;
@Column(name = "ENTITY_ID")
private String entityId;
@Column(name = "ENTITY_NAME_ZH")
private String entityNameZh;
@Column(name = "COUNTRY_ID")
private String countryId;
@Column(name = "SAN_REASON")
private String sanReason;
@Column(name = "SAN_INTENSITY")
private char sanIntensity;
@Column(name = "START_TIME")
private Date startTime;
@Column(name = "END_TIME")
private Date endTime;
@Column(name = "IS_KEY")
private char isKey;
@Transient
private List<TechDomainBean> techDomainList;
/**
* 领域列表
*/
@Transient
private List<String> techDomains;
/**
* 50%规则子企业数
*/
@Transient
private Integer ruleOrgCount;
// 50%规则子企业列表
@Transient
private List<Organization> ruleOrgList;
}
```
## OrgInfo
```java
public class OrgInfo {
// 机构id
private String id;
// 机构名称
private String orgName;
// 相关制裁措施列表
private List<String> sanTypeList;
// 机构职责
private String orgDuty;
// 机构图片
private String imageUrl;
// 人员列表
private List<PersonInfo> personList;
}
```
## PersonInfo
```java
public class PersonInfo {
// id
private String id;
// 人物类别
private Integer type;
// 姓名
private String name;
// 党派
private String party;
// 职位
private String position;
// 头像链接
private String imageUrl;
}
```
## SanCountInfo
```java
public class SanCountInfo {
// 实体数
private Integer entityNum;
// 实体变动数
private Integer entityChange;
// 上市公司数
private Integer listedCompanyNum;
// 上市公司变动数
private Integer listedCompanyChange;
// 涉及领域名数
private Integer domainNum;
// 涉及领域变动数
private Integer domainChange;
// 实体类型数
private Integer typeNum;
// 实体类型变动数
private Integer typeChange;
}
```
## Chain
```java
public class Chain {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// 名称
@Column(name = "name")
private String name;
// 中文名称
@Column(name = "name_zh")
private String nameZh;
// 值
@Column(name = "description")
private String description;
// 父级id
@Column(name = "parent_id")
private Integer parentId;
// 是否为产业链主分支
@Column(name = "is_main_branch")
private String isMainBranch;
// 下属产业链分支
@Transient
private List<Chain> children;
}
```
## FishboneResp
```java
public class FishboneResp<T> {
private String text;
private List<T> causes;
}
```
## AreasStreamResp
```java
public class AreasStreamResp {
// 上游国内企业数量
private int upstreamInternalCount;
// 上游国内占比
private double upstreamInternalRate;
// 上游受制裁企业数量
private int upstreamEntityCount;
// 上游受制裁占比
private double upstreamEntityRate;
// 中游国内企业数量
private int midstreamInternalCount;
// 中游国内占比
private double midstreamInternalRate;
// 中游受制裁企业数量
private int midstreamEntityCount;
// 中游受制裁占比
private double midstreamEntityRate;
// 下游国内企业数量
private int downstreamInternalCount;
// 下游国内占比
private double downstreamInternalRate;
// 下游受制裁企业数量
private int downstreamEntityCount;
// 下游受制裁占比
private double downstreamEntityRate;
}
```
## AnnualDomainQuery
```java
public class AnnualDomainQuery {
// 开始年份
private Integer startYear;
// 结束年份
private Integer endYear;
// 是否考虑50%规则
private Boolean isRule;
}
```
## AnnualDomainCount
```java
public class AnnualDomainCount {
// 年度领域统计
private List<DomainCount> yearDomainCount;
// 所有领域
private List<BaseCount> domians;
}
```
## SanctionTypeBean
```java
public class SanctionTypeBean extends BaseBean {
@Id
@Column(name = "ID", nullable = false)
private Integer id;
@Column(name = "NAME")
private String name;
@Column(name = "NAME_ZH")
private String nameZh;
@Column(name = "NAME_ABBR")
private String nameAbbr;
@Column(name = "DESCRIPTION")
private String description;
// 发布国家
@Column(name = "POST_COUNTRY_ID")
private String postCountryId;
// 发布机构
@Column(name = "POST_ORG_ID")
private String postOrgId;
// 是否出口管制 1:是 0:否
@Column(name = "IS_EXPORT_CONTROL")
private String isExportControl;
// 总发布次数
@Transient
private Integer postCount;
}
```
## Organization
```java
public class Organization extends BaseBean {
// 机构id
@Id
@Column(name = "id", nullable = false)
private String id;
// 机构名称
@Column(name = "org_name", nullable = false)
private String orgName;
// 组织机构代码
@Column(name = "uscc")
private String uscc;
// 机构简称
@Column(name = "org_abb")
private String orgAbb;
// 机构英文名称
@Column(name = "org_name_en")
private String orgNameEn;
// 机构英文简称
@Column(name = "org_abb_en")
private String orgAbbEn;
// 机构别名
@Column(name = "org_alias")
private String orgAlias;
// 机构曾用名
@Column(name = "org_former_name")
private String orgFormerName;
// 机构类型id
@Column(name = "org_type_id")
private Long orgTypeId;
// 机构简介
@Column(name = "org_introduction")
private String orgIntroduction;
// 营业范围
@Column(name = "business_scope")
private String businessScope;
// 行业id
@Column(name = "domain_ids")
private String domainIds;
// 行业代码
@Column(name = "economic_industry_code")
private String economicIndustryCode;
// 经济行业名称
@Column(name = "economic_industry_name")
private String economicIndustryName;
// 国家id
@Column(name = "country_id")
private String countryId;
// 省份
@Column(name = "province")
private String province;
// 城市
@Column(name = "city")
private String city;
// 区县
@Column(name = "county")
private String county;
// 详细地址
@Column(name = "address")
private String address;
// 成立时间
@Column(name = "establishment_date")
private LocalDate establishmentDate;
// 变更时间
@Column(name = "issuing_date")
private String issuingDate;
// 营业期限自
@Column(name = "operation_period_from")
private String operationPeriodFrom;
// 营业期限至
@Column(name = "operation_period_until")
private String operationPeriodUntil;
// 营业状态
@Column(name = "business_status")
private String businessStatus;
// 法人id
@Column(name = "legal_representative_id")
private String legalRepresentativeId;
/// 法人
@Column(name = "legal_representative")
private String legalRepresentative;
// 联系电话
@Column(name = "telephone")
private String telephone;
// 邮箱
@Column(name = "email")
private String email;
// 邮政编码
@Column(name = "postcode")
private String postcode;
// 网址
@Column(name = "url")
private String url;
// 员工人数
@Column(name = "number_of_employees")
private String numberOfEmployees;
// 注册资金
@Column(name = "registered_capital")
private String registeredCapital;
// LOGO链接
@Column(name = "logo_url")
private String logoUrl;
@Column(name = "create_by")
private String createBy;
@Column(name = "update_by")
private String updateBy;
@Column(name = "p_org_id")
private String pOrgId;
}
```
## EventInfo
```java
public class EventInfo extends BaseBean {
@Id
@Column(name = "id")
@ApiModelProperty(value = "唯一标识")
private String id;
@Column(name = "title")
@ApiModelProperty(value = "标题")
private String title;
@Column(name = "event_time")
@ApiModelProperty(value = "事件时间")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date eventTime;
@Column(name = "summary")
@ApiModelProperty(value = "摘要")
private String summary;
@Column(name = "summary_zh")
@ApiModelProperty(value = "摘要译文")
private String summaryZh;
@Column(name = "event_type")
@ApiModelProperty(value = "事件类别")
private String eventType;
@Column(name = "CONTENT")
@ApiModelProperty(value = "主要内容")
private String content;
@Column(name = "title_zh")
@ApiModelProperty(value = "标题译文")
private String titleZh;
@Column(name = "content_zh")
@ApiModelProperty(value = "主要内容译文")
private String contentZh;
@Column(name = "type")
@ApiModelProperty(value = "事件类别")
private String type;
@Column(name = "LOCATION")
@ApiModelProperty(value = "事件地点")
private String location;
@Column(name = "country")
@ApiModelProperty(value = "国家")
private String country;
}
```
# 字典
## 领域类别(id:name)
1:人工智能、2:生物科技、3:新一代信息技术、4:量子科技、5:新能源、6:集成电路、7:海洋、8:先进制造、9:新材料、10:航空航天、11:深海、12:极地、13:太空、14:核
## 实体类别(id:name)
1:人物、2:机构、7:地址
## 人物类别(待定)
1:政府官员、2:科技领袖、3:顶级科学家、4:国会议员
# 出口管制
## **获取出口管制类清单统计信息**
请求地址:/sanctionList/export/getTotalInfo
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<List<SanctionTypeBean>>
## 最新出口管制政策(4条)
请求地址:http://8.140.26.4:9085/entitiesDataInfo/getLatestInfo
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<LatestExportControlInfo>
## 发布(更新)频度
请求地址:http://8.140.26.4:9085/entitiesDataCount/getAnnualCount
请求类型:GET
输入参数:
​ 参数:Integer sanTypeId(制裁类别)
​ 实体清单发布频度:1;CCL发布频度:X(待定,暂无数据)
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<List<AnnualCount>>
## **制裁领域分析**(20251215)
请求地址:http://8.140.26.4:9085/entitiesDataCount/getSanDomainCount
请求类型:GET
输入参数:
​ 参数:Boolean rule(是否勾选50%规则)
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<List<DomainCount>>
## **历次制裁过程**
请求地址:http://8.140.26.4:9085/entitiesDataCount/getSanctionProcess
请求类型:POST
输入参数:
​ 参数:ExportPageQuery exportPageQuery
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<Page<SanctionProcess>>
## **制裁实体清单**列表(20251215)
请求地址:/sanctionList/pageQuery
请求类型:POST
输入参数:
​ 参数:ExportPageQuery exportPageQuery
​ 出口管制-概览页请求时:typeName=实体清单
​ 实体清单-制裁概览页请求时:typeName=实体清单,sanctionDate=该次制裁的具体时间
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<Page<SanctionListBean>>
## **发布机构与重点人物**
请求地址:/sanctionList/getPublishedOrg
请求类型:GET
输入参数:
​ 参数:Integer sanTypeId
​ 暂时固定输入:1;对应实体清单发布机构
​ 请求头:携带token
输出结果:ApiResult<OrgInfo>
## **领域分布查询**
请求地址:/entitiesDataInfo/getDomianDistribution
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **类型分布查询**
请求地址:/entitiesDataInfo/getTypeDistribution
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **区域分布查询**
请求地址:/entitiesDataInfo/getRegionDistribution
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **制裁理由查询**
请求地址:/entitiesDataInfo/getSanReason
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<List<String>>
## **深度挖掘-制裁信息变化统计**
请求地址:/entitiesDataInfo/getSanCountInfo
请求类型:GET
输入参数:
​ 参数:String sanctionDate (制裁时间)
​ 请求头:携带token
输出结果:ApiResult<SanCountInfo>
## **年度实体数统计**
请求地址:/entitiesDataInfo/getCountByDomianAndType
请求类型:GET
输入参数:
​ 参数:String domianId (非必需,领域类别ID),Integer typeId (非必需,实体类别ID)
​ 参考字典
​ 请求头:携带token
输出结果:ApiResult<SanCountInfo>
## **重点实体列表查询**
请求地址:/entitiesDataInfo/getKeyEntities
请求类型:GET
输入参数:
​ 参数:String sanctionDate(必需),String searchText(非必需,检索文本)
​ 请求头:携带token
输出结果:ApiResult<List<OrgInfo>>
## **上市企业制裁强度**
请求地址:/entitiesDataInfo/listedEntity/sanInfo
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **上市企业融资变化情况**
请求地址:/entitiesDataInfo/listedEntity/financing
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **上市企业市值变化情况**
请求地址:/entitiesDataInfo/listedEntity/market
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **重点上市企业列表**
请求地址:/entitiesDataInfo/listedEntity/keyEntity
请求类型:GET
输入参数:
​ 参数:String sanctionDate(必需),String searchText(非必需,检索文本)
​ 请求头:携带token
输出结果:ApiResult<List<OrgInfo>>
## **历次制裁涉及领域数查询**
请求地址:/entitiesDataInfo/getPreviousDomian
请求类型:GET
输入参数:
​ 参数:无
​ 请求头:携带token
输出结果:ApiResult<List<BaseCount>>
## **具体领域的制裁实体数统计**
请求地址:/entitiesDataInfo/getDomianAnnual
请求类型:GET
输入参数:
​ 参数:String domainId
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **具体实体类型的制裁实体数统计**
请求地址:/entitiesDataInfo/getEntityTypeAnnual
请求类型:GET
输入参数:
​ 参数:Integer entityTypeId
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **产业链结构查询**
请求地址:/chain/getChainTree
请求类型:GET
输入参数:
​ 参数:Integer chainId,非必需
​ 请求头:携带token
输出结果:ApiResult<List<Chain>>
## **产业链鱼骨图信息查询**
请求地址:/chain/getChainFishbone
请求类型:GET
输入参数:
​ 参数:Integer chainId
​ 请求头:携带token
输出结果:ApiResult<FishboneResp>
## **产业链中国企业实体信息查询**
请求地址:/chain/getChainEntityStat
请求类型:GET
输入参数:
​ 参数:Integer chainId
​ 请求头:携带token
输出结果:ApiResult<AreasStreamResp>
## **实体列表查询**
请求地址:/entitiesDataInfo/getEntityList
请求类型:GET
输入参数:
​ 参数:String sanctionDate(制裁时间),String domainId(领域ID)
​ 请求头:携带token
输出结果:ApiResult<List<OrgInfo>>
## **历年制裁领域统计**
请求地址:/entitiesDataCount/getAnnualSanDomain
请求类型:POST
输入参数:
​ 参数:AnnualDomainQuery annualDomainQuery
​ 请求头:携带token
输出结果:ApiResult<List<AnnualDomainCount>>
## **新增实体数量增长趋势**
请求地址:/entitiesDataInfo/yoyComparison
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token
输出结果:ApiResult<List<AnnualCount>>
## **获取机构的详情信息**
请求地址:/organization/getDetail/{id}
请求类型:GET
输入参数:
​ 参数:机构ID
​ 请求头:携带token
输出结果:ApiResult<Organization>
## **获取5条美国前序事件**
请求地址:/entitiesDataInfo/precedingEvents
请求类型:GET
输入参数:
​ 参数:String sanctionDate 制裁时间
​ 请求头:携带token
输出结果:ApiResult<List<EventInfo>>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论