提交 466aabb3 authored 作者: yanpeng's avatar yanpeng

api-4

上级 34ad808f
......@@ -328,6 +328,31 @@ 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
}
})
);
}
/**
* 领域分布查询
*/
......@@ -352,7 +377,7 @@ export function getDomainDistribution(sanctionDate = "2025-11-11") {
* 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(
request({
method: "POST",
......@@ -362,7 +387,7 @@ export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize
pageNum,
pageSize,
sanctionDate,
rule
isCn
}
})
);
......@@ -584,7 +609,8 @@ export function getCountThisType(param) {
return request200(
request({
method: "GET",
url: "/api/entitiesDataCount/countThisType",
// url: "/api/entitiesDataCount/countThisType",
url: "/api/entitiesDataInfo/annual/researchInstitute",
params: {
param
}
......@@ -592,6 +618,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
}
})
);
}
/**
* 产业链信息查询
*/
......
[
{
"personImage": "https://www.congress.gov/img/member/y000064_200.jpg",
"personName": "扬(Young, Todd)",
"remarks": "拜登打心底里厌恶美国的石油和天然气产业,他的一系列政策,正在摧毁这个能为美国创造大量就业岗位的重要领域。",
"time": "2025-04-12T03:27:07",
"orgName": "推特"
},
{
"personImage": "https://www.congress.gov/img/member/k000306_200.jpg",
"personName": "科尔贝 (Kolbe), 吉姆 (Jim)",
"remarks": "美国将控制加沙地带,我们会把这片被战火摧毁的区域改造成 “中东的里维埃拉”,这一计划会为当地带来全新未来。",
"time": "2025-01-12T00:55:53",
"orgName": "推特"
"id": 86,
"name": "人工智能",
"nameZh": "人工智能",
"description": null,
"parentId": null,
"isMainBranch": "Y",
"children": null
}
]
\ No newline at end of file
......@@ -2,7 +2,7 @@
<div class="fishbone-wrapper">
<div class="fishbone-scroll-container" ref="scrollContainerRef">
<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
v-for="(causeGroup, groupIndex) in getOddGroups(fishboneData)"
......
......@@ -11,7 +11,7 @@
<div class="listWrap">
<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="name">{{ item.name }}</div>
<div class="name">{{ item.name || item.nameEn }}</div>
<div class="icon" :class="{ iconUp: item.isUp, iconDown: !item.isUp }"></div>
</div>
</div>
......@@ -22,10 +22,13 @@
<Hint
text="法案核心意图在于通过税收优惠吸引制造业回流美国​,并在关键科技领域对中国进行遏制,限制中国获取先进技术、资本和市场渠道,从而延缓中国科技产业的发展速度。给半导体、新能源、人工智能等相关科技行业带来不小的短期压力。"
></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="right-main-content">
<div class="right-main-content-main">
<Fishbone :chainId="activeButtonId" />
<Fishbone :chainId="chainData.length > 0 ? activeChainId : activeButtonId" />
</div>
<div class="right-main-content-footer">
<div class="footer-item1">
......@@ -34,10 +37,13 @@
<img src="../../assets/images/warning.png" alt="" />
</div>
<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 class="footer-item1-top">{{ "基础支撑" }}</div>
<div class="footer-item1-top">{{ "上游" }}</div>
</div>
<div class="footer-item2">
<div class="footer-item2-bottom">
......@@ -45,10 +51,13 @@
<img src="../../assets/images/warning.png" alt="" />
</div>
<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 class="footer-item2-top">{{ "软件算法" }}</div>
<div class="footer-item2-top">{{ "中游" }}</div>
</div>
<div class="footer-item3">
<div class="footer-item3-bottom">
......@@ -56,10 +65,13 @@
<img src="../../assets/images/warning.png" alt="" />
</div>
<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 class="footer-item3-top">{{ "行业应用" }}</div>
<div class="footer-item3-top">{{ "下游" }}</div>
</div>
</div>
</div>
......@@ -77,7 +89,7 @@ import Hint from "./hint.vue";
import ButtonList from "@/components/buttonList/buttonList.vue";
import Fishbone from "./fishbone.vue";
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";
const route = useRoute();
const router = useRouter();
......@@ -151,6 +163,78 @@ const handleEttClick = item => {
});
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 () => {
try {
......@@ -193,6 +277,7 @@ const fetchChainEntities = async () => {
listData.value = data.map(item => ({
...item,
name: item.orgNameZh,
nameEn: item.orgName,
isUp: item.isUp
}));
}
......@@ -203,16 +288,31 @@ const fetchChainEntities = async () => {
onMounted(async () => {
fetchDomainDistribution();
// horizontalBarOptions.value = getHorizontalBarChart2(
// ["贸易", "军工", "金融业", "跨境电商", "半导体", "新能源"],
// [10, 21, 25, 79, 95, 109],
// false
// );
fetchChainEntities();
// 获取产业链信息数据
fetchChainInfo();
// 获取产业链中国企业实体信息查询
fetchCnEntityOnChain();
});
watch(() => activeButtonId.value, fetchChainEntities);
watch(
() => activeButtonId.value,
async () => {
await fetchChainEntities();
// 获取产业链信息数据
await fetchChainInfo();
// 获取产业链中国企业实体信息查询
await fetchCnEntityOnChain();
}
);
watch(
() => activeChainId.value,
async () => {
await fetchCnEntityOnChain();
}
);
</script>
<style lang="scss" scoped>
......@@ -225,6 +325,9 @@ watch(() => activeButtonId.value, fetchChainEntities);
display: flex;
flex-direction: column;
padding: 17px 18px 12px 18px;
&-buttonlist {
padding: 10px;
}
.chartsWrap {
flex: 1;
.right-main-content {
......
......@@ -124,9 +124,6 @@ const fetchKeyEntityList = async (date = "2025-11-11", keyword = "") => {
};
onMounted(async () => {
// 确保默认值正确设置
domainValue.value = domainOptions[0].value;
typeValue.value = typeOptions[0].value;
try {
const [entitiesGrowthTrendData, entitiesUpdateCountData] = await Promise.all([
getEntitiesGrowthTrend(),
......@@ -167,7 +164,7 @@ onMounted(async () => {
});
const domainOptions = [
{
value: "",
value: "all",
label: "全部"
},
{
......@@ -257,7 +254,7 @@ const domainOptions = [
];
const typeOptions = [
{
value: "",
value: "all",
label: "全部"
},
{
......@@ -273,14 +270,14 @@ const typeOptions = [
label: "地址"
}
];
const domainValue = ref("");
const typeValue = ref("");
const domainValue = ref("all");
const typeValue = ref("all");
const bar1Option = shallowRef({});
const bar1DataIsEmpty = ref(false);
watch(
[domainValue, typeValue],
async ([domain, type]) => {
let EntitiesChangeCount = await getEntitiesChangeCount(domain, type);
let EntitiesChangeCount = await getEntitiesChangeCount(domain == "all" ? "" : domain, type == "all" ? "" : type);
EntitiesChangeCount = _.reverse(EntitiesChangeCount);
bar1DataIsEmpty.value = EntitiesChangeCount.length === 0;
bar1Option.value = getBarChart(
......@@ -292,16 +289,6 @@ watch(
},
{ immediate: true }
);
// const options = [
// {
// value: "1",
// label: "人工智能"
// },
// {
// value: "2",
// label: "航空航天"
// }
// ];
const subPanel4 = ref([
{
name: "中国科学技术大学",
......
......@@ -76,18 +76,6 @@ import { getEntityFinancing, getEntityMarketValue, getKeyListedEntityList, getSa
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const router = useRouter();
const options = [
{
value: "1",
label: "人工智能"
},
{
value: "2",
label: "航空航天"
}
];
const value1 = ref("");
const value2 = ref("");
const value3 = ref("");
const bar1Option = shallowRef({});
const bar2Option = shallowRef({});
......@@ -119,6 +107,7 @@ const subPanel4 = ref([
// 获取重点上市企业列表数据
const fetchKeyListedEntityList = async (keyword = "") => {
try {
console.log("获取重点上市企业列表数据", route.query.startTime);
const data = await getKeyListedEntityList(route.query.startTime, keyword);
if (data && Array.isArray(data)) {
// 根据 fishbone-mock.json 的数据结构处理数据
......
......@@ -19,7 +19,7 @@
</CardCustom>
</div>
<div class="row">
<CardCustom title="历次制裁涉及实体数" :style="{ width: '798px', height: '422px' }">
<CardCustom title="历次制裁涉及实体类型数" :style="{ width: '798px', height: '422px' }">
<div class="subPanel3">
<div class="chartsWrap" :style="{ paddingBottom: '10px' }">
<Echarts :option="bar2Option" height="100%"></Echarts>
......@@ -46,7 +46,7 @@ import { Search } from "@element-plus/icons-vue";
import Echarts from "@/components/Chart/index.vue";
import { getBarChart, getLineChart, getPieOption1 } from "../../utils/charts";
import Hint from "./hint.vue";
import { getCountSanTypeByTime, getCountTypeByYear, getCountThisType } from "@/api/exportControl";
import { getCountSanTypeByTime, getCountTypeByYear, getCountThisType, getEnterpriseSanCount } from "@/api/exportControl";
import _ from "lodash";
import { useRoute } from "vue-router";
const route = useRoute();
......@@ -60,7 +60,7 @@ onMounted(async () => {
getCountSanTypeByTime(route.query.startTime),
getCountThisType("1"),
getCountTypeByYear(),
getCountThisType("2")
getEnterpriseSanCount()
]);
pie1Option.value = getPieOption1(
......
......@@ -13,7 +13,7 @@
import Echarts from "@/components/Chart/index.vue";
import { getPieOption } from "../../utils/charts";
import { ref, onMounted, shallowRef } from "vue";
import { getCountByDomain, getCountByType } from "@/api/exportControl";
import { getCountByDomain, getCountByType, getDomainDistribution } from "@/api/exportControl";
import _ from "lodash";
import { useRoute } from "vue-router";
const route = useRoute();
......@@ -22,7 +22,7 @@ const pie2Option = shallowRef({});
onMounted(async () => {
try {
const [countByDomainData, countByTypeData] = await Promise.all([
getCountByDomain(route.query.startTime),
getDomainDistribution(route.query.startTime),
getCountByType(route.query.startTime)
]);
pie1Option.value = getPieOption(
......
......@@ -88,9 +88,13 @@
<div class="hintWrap">
<div class="title">
共计
<span class="text1">112</span>
<span class="text1">{{ entityTotal }}</span>
家,其中50%规则涉及
<span class="text2">604</span>
<span class="text2">{{
panel5IsChecked
? entitiesCountBy50PercentRulesData?.ruleCount
: entitiesCountBy50PercentRulesData?.totalCount
}}</span>
</div>
</div>
......@@ -185,10 +189,6 @@ import ButtonList from "@/components/buttonList/buttonList.vue";
import Hint from "../components/hint.vue";
import { onMounted, reactive, ref, shallowRef, watch } from "vue";
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";
......@@ -202,7 +202,8 @@ import {
getPersonList,
getSanReasonSelect,
getSelectEntitiesList,
getEntitiesList
getEntitiesList,
getEntitiesCountBy50PercentRules
} from "@/api/exportControl";
import _ from "lodash";
......@@ -275,16 +276,18 @@ const total = ref(0);
const loading = ref(false);
const tableWrapRef = ref(null);
const noMoreData = ref(false);
const entitiesCountBy50PercentRules = ref(0);
onMounted(async () => {
try {
const [organizationInfoData, sanReasonSelectData] = await Promise.all([
const [organizationInfoData, sanReasonSelectData, entitiesCountBy50PercentRulesData] = await Promise.all([
getOrganizationInfo(),
// getPersonList(),
getSanReasonSelect(route.query.startTime)
getSanReasonSelect(route.query.startTime),
getEntitiesCountBy50PercentRules("实体清单", currentPage.value, pageSize.value)
// getSelectEntitiesList(route.query.startTime)
]);
console.log("organizationInfoData", organizationInfoData);
console.log("entitiesCountBy50PercentRulesData", entitiesCountBy50PercentRulesData);
organizationInfo.value = {
img: panel1_1,
mingcheng: organizationInfoData?.orgNameZh,
......@@ -325,6 +328,7 @@ onMounted(async () => {
});
// 获取实体清单数据
const entityTotal = ref(0);
const fetchEntitiesList = async (page = 1, size = 10) => {
if (loading.value || noMoreData.value) return;
......@@ -332,6 +336,7 @@ const fetchEntitiesList = async (page = 1, size = 10) => {
try {
const res = await getEntitiesList("实体清单", page, size, route.query.startTime, panel5IsChecked.value);
if (res) {
entityTotal.value = res.totalElements;
const newData = res.content.map(item => ({
...item,
name: item.entityNameZh,
......@@ -372,6 +377,7 @@ watch(
() => panel5IsChecked.value,
newVal => {
fetchEntitiesList(1, 10);
// getEntitiesCountBy50PercentRules("实体清单", 1, pageSize.value)
}
);
......
......@@ -2,7 +2,7 @@
<div class="news-list">
<div v-for="(item, index) in listData" :key="index" class="news-item" @click="handleItemClick(item)">
<div class="news-image">
<img :src="item.image || newsImg" :alt="item.title" />
<img :src="item.avatar || newsImg" :alt="item.title" />
</div>
<div class="news-content">
<div class="news-header">
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论