提交 84abdc2b authored 作者: Vicky's avatar Vicky

人物页面接口

上级 a6dd260f
......@@ -21,6 +21,7 @@
<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from "echarts";
import {getCharacterGlobalInfo, getCharacterRelation } from "@/api/characterPage/characterPage.js";
import Center from "./assets/img1.png";
import P1 from "./assets/img2.png";
import P2 from "./assets/img3.png";
......@@ -35,8 +36,10 @@ import P10 from "./assets/img11.png";
import P11 from "./assets/img12.png";
import PS from "./assets/img13.png";
const list = ref(["圆形布局", "力导向布局", "树形布局"]);
const activeIndex = ref("圆形布局");
// 人物全局信息
const characterInfo = ref({});
// 人物关系
const CharacterRelation = ref({});
const nodes = [
{
......@@ -75,6 +78,98 @@ const nodes = [
{ id: "n3", name: "格温・肖特韦尔", category: 1, symbolSize: 80, symbol: `image://${P3}`, r: 80 }
];
const getCharacterGlobalInfoFn = async () => {
const params = {
personId: window.sessionStorage.getItem("personId") || "Y000064"
};
try{
const res = await getCharacterGlobalInfo(params);
if (res.code === 200) {
console.log("人物全局信息", res);
if (res.data) {
characterInfo.value = res.data;
}
}
const res1 = await getCharacterRelation(params);
if (res1.code === 200) {
console.log("人物关系", res1);
if (res1.data) {
CharacterRelation.value = res1.data;
}
}
nodes = [
{
id: "c",
name: characterInfo.value.name,
category: 0,
symbolSize: 80,
symbol: `image://${characterInfo.value.imageUrl}`,
label: {
show: true,
position: "bottom",
formatter: "{n|埃隆·马斯克}",
rich: {
n: {
color: "rgba(5,95,194,1)",
fontSize: 24,
fontWeight: 700,
fontFamily: "Microsoft YaHei",
lineHeight: 36
}
}
}
},
// 从三点钟方向顺时针排序
{ id: "n11", name: "贾斯汀・马斯克", category: 1, symbolSize: 80, symbol: `image://${P11}` },
{ id: "n7", name: "杰弗里·凯斯勒", category: 1, symbolSize: 80, symbol: `image://${P7}`, r: 80 },
{ id: "n6", name: "斯科特·贝森特", category: 1, symbolSize: 80, symbol: `image://${P6}` },
{ id: "n9", name: "道格·伯格姆", category: 1, symbolSize: 80, symbol: `image://${P9}` },
{ id: "n12", name: "史蒂夫・尤尔韦松", category: 1, symbolSize: 80, symbol: `image://${PS}` },
{ id: "n5", name: "拉里・埃里森", category: 1, symbolSize: 80, symbol: `image://${P5}`, r: 80 },
{ id: "n8", name: "马尔科·卢比奥", category: 1, symbolSize: 80, symbol: `image://${P8}` },
{ id: "n10", name: "艾拉・埃伦普里斯", category: 1, symbolSize: 80, symbol: `image://${P10}`, r: 80 },
{ id: "n2", name: "詹姆斯・默多克", category: 1, symbolSize: 80, symbol: `image://${P2}` },
{ id: "n1", name: "唐纳德・特朗普", category: 1, symbolSize: 80, symbol: `image://${P1}` },
{ id: "n4", name: "金博尔・马斯克", category: 1, symbolSize: 80, symbol: `image://${P4}` },
{ id: "n3", name: "格温・肖特韦尔", category: 1, symbolSize: 80, symbol: `image://${P3}`, r: 80 }
];
}catch(error){
}
};
const getCharacterRelationFn = async () => {
const params = {
personId: window.sessionStorage.getItem("personId") || "Y000064"
};
try{
const res = await getCharacterRelation(params);
if (res.code === 200) {
console.log("人物关系", res);
if (res.data) {
CharacterRelation.value = res.data;
}
}
}catch(error){
}
};
onMounted(() => {
getCharacterRelationFn();
getCharacterGlobalInfoFn();
});
const list = ref(["圆形布局", "力导向布局", "树形布局"]);
const activeIndex = ref("圆形布局");
const links = [
{ source: "n11", target: "c", label: { show: true, formatter: "第一任妻子" } },
{ source: "n7", target: "c", label: { show: true, formatter: "风险投资家" } },
......
......@@ -3,30 +3,32 @@
<!-- 科技领袖人物基础 -->
<div class="header">
<div class="avatar">
<img :src="musk.avatar" alt="" />
<!-- <img :src="characterInfo.imageUrl" alt="" /> -->
<el-avatar :size="160" shape="circle" :src="characterInfo.imageUrl" />
</div>
<div class="info">
<!-- <div class="name"> -->
<p class="name-cn">{{ musk.nameCn }}</p>
<p class="name-en">{{ musk.nameEn }}</p>
<p class="name-cn">{{ characterInfo.name }}</p>
<p class="name-en">{{ characterInfo.ename }}</p>
<!-- </div> -->
<div class="introduction">
<p>{{ musk.introduction }}</p>
<p>{{ characterInfo.description }}</p>
</div>
<div class="domain">
<p
v-for="item in musk.domain"
v-for="item in characterInfo.industryList"
:key="item"
class="cl1"
:class="{
cl1: item === '电动汽车',
cl2: item === '太空探索',
cl3: item === '可再生资源',
cl4: item === '人工智能',
cl5: item === '脑机接口',
cl6: item === '超级高铁'
cl1: item.status === '1',
cl2: item.status === '2',
cl3: item.status === '3',
cl4: item.status === '4',
cl5: item.status === '5',
cl6: item.status === '6'
}"
>
{{ item }}
{{ item.industryName }}
</p>
</div>
</div>
......@@ -76,7 +78,7 @@
<div class="title">
<div class="box"></div>
<div class="text">最新动态</div>
<div class="input"><input type="checkbox" checked />只看涉华动态</div>
<div class="input"><input type="checkbox" v-model="isChecked" @change="handleChange"/>只看涉华动态</div>
<div class="btn">
<img src="./assets/下载按钮.png" alt="" />
<img src="./assets/收藏按钮.png" alt="" />
......@@ -84,30 +86,34 @@
</div>
<!-- 主要内容 -->
<div class="main">
<div v-for="item in newList" :key="item" class="main-item">
<div v-for="item in CharacterLatestDynamic" :key="item" class="main-item">
<div class="time">
<div class="year">{{ item.time.split("")[0] }}</div>
<div class="date">{{ item.time.split("年")[1] }}</div>
<div class="year">{{ item.time.split("-")[0] }}</div>
<div class="date">{{ item.time.split("-")[1] + "月" + item.time.split("-")[2] + "日"}}</div>
</div>
<div class="image">
<img src="./assets/type1.png" alt="" v-if="item.type === 1" /><img
<img src="./assets/type1.png" alt="" v-if="item.remarks === true" /><img
src="./assets/type2.png"
alt=""
v-else
/>
</div>
<div class="content">
<div :class="{ 'content-type1': item.type === 1, 'content-type2': item.type === 2 }">
<p :class="{ 'content-title1': item.type === 1, 'content-title2': item.type === 2 }">
<div :class="{ 'content-type1': item.remarks === true, 'content-type2': item.remarks === false }">
<p v-if="item.remarks === true" class="content-title1">
{{ item.content }}
</p>
<p v-else class="content-title2">
{{ item.title }}
</p>
<p class="content-title-en">{{ item.titleEn }}</p>
<p v-if="item.remarks === true" class="content-title-en">{{ item.econtent }}</p>
</div>
<p class="content-contentcontent">{{ item.content }}</p>
<p v-if="item.remarks === false" class="content-contentcontent">{{ item.content }}</p>
<div class="content-tag">
<div>
<span
v-for="tag in item.pie"
v-for="tag in item.industryList"
:key="tag"
class="tag"
:class="{
......@@ -120,20 +126,21 @@
>{{ tag }}</span
>
</div>
<div class="origin">来源:{{ item.origin }}</div>
<div class="origin">来源:{{ item.orgName }}</div>
</div>
</div>
</div>
<div class="line-test"></div>
</div>
<div class="pagination">
<div class="total">共153项动态</div>
<div class="total">{{`共${total}项动态`}}</div>
<el-pagination
@current-change="handleCurrentChange"
:page-size="pageSize"
:current-page="currentPage"
background
layout="prev, pager, next"
:page-count="10"
:pager-count="5"
v-model:current-page="currentPage"
:total="total"
class="custom-pagination"
/>
</div>
......@@ -153,41 +160,41 @@
<div class="baseInfo">
<div class="baseInfo-item">
<div class="baseInfo-item-title">出生日期:</div>
<div class="baseInfo-item-content">1971年6月28日</div>
<div class="baseInfo-item-content">{{characterBasicInfo.birthday}}</div>
</div>
<div class="baseInfo-item">
<div class="baseInfo-item-title">国籍:</div>
<div class="baseInfo-item-content">南非、加拿大、美国</div>
<div class="baseInfo-item-content">{{characterBasicInfo.country}}</div>
</div>
<div class="baseInfo-item">
<div class="baseInfo-item-title">教育背景:</div>
<div class="baseInfo-item-content">宾夕法尼亚大学(经济学、物理学)</div>
<div class="baseInfo-item-content" v-for="value in characterBasicInfo.educationList">{{ value.school +"("+ value.major+")"}}</div>
</div>
<div class="baseInfo-item">
<div class="baseInfo-item-title">净资产:</div>
<div class="baseInfo-item-content">约2000亿美元(2023年)</div>
<div class="baseInfo-item-content">{{characterBasicInfo.assets}}</div>
</div>
<div class="baseInfo-item">
<div class="baseInfo-item-title">职业:</div>
<div class="baseInfo-item-content">企业家、工程师、发明家</div>
<div class="baseInfo-item-content">{{characterBasicInfo.positionTitle}}</div>
</div>
<div class="baseInfo-item">
<div class="baseInfo-item-title">婚姻状况:</div>
<div class="baseInfo-item-content">曾多次结婚,有多个子女</div>
<div class="baseInfo-item-content">{{characterBasicInfo.marital}}</div>
</div>
<div class="baseInfo-item">
<div class="baseInfo-item-title">出生地:</div>
<div class="baseInfo-item-content">南非比勒陀利亚</div>
<div class="baseInfo-item-content">{{characterBasicInfo.birthPlace}}</div>
</div>
</div>
<div class="company">
<div class="company-title">知名企业</div>
<div class="company-content">
<div v-for="item in companyList" :key="item" class="company-item">
<img :src="item.logo" alt="" />
<div v-for="item in characterBasicInfo.organizationList" :key="item" class="company-item">
<img :src="item.imageUrl?item.imageUrl:DefaultIcon2" alt="" />
<div>
<div class="company-cn">{{ item.cn }}</div>
<div class="company-name">{{ item.name }}</div>
<div class="company-cn">{{ item.name }}</div>
<div class="company-name">{{ item.ename }}</div>
</div>
</div>
</div>
......@@ -204,10 +211,10 @@
</div>
</div>
<div class="content-main">
<div v-for="item in resumeList" :key="item.id" class="content-item">
<div v-for="item in CharacterResume" class="content-item">
<img src="./assets/icon01.png" alt="" class="image01" />
<div class="content-item-time">{{ item.time }}</div>
<div class="content-item-title">{{ item.title }}</div>
<div class="content-item-time">{{ item.startTime +'-' + item.endTime}}</div>
<div class="content-item-title">{{ item.orgName +'|' + item.jobName}}</div>
<div class="content-item-content">{{ item.content }}</div>
<div class="content-item-door" v-if="item.door">
<img src="./assets/icon02.png" alt="" />
......@@ -238,12 +245,13 @@
</template>
<div class="viewpoint-body">
<div class="viewpoint-body-title">#人工智能</div>
<div v-for="item in dialogData" :key="item.id" class="viewpoint-item">
<img :src="item.img" alt="" />
<div v-for="item in CharacterFieldView" class="viewpoint-item">
<!-- <img :src="item.imageUrl ? getProxyUrl(item.imageUrl) : DefaultIcon1" alt="" /> -->
<el-avatar :size="42" shape="circle" :src="item.imageUrl ? getProxyUrl(item.imageUrl) : DefaultIcon1" class="viewpoint-item-img" />
<div class="viewpoint-item-content">
<div class="viewpoint-item-name">{{ item.name }}</div>
<div class="viewpoint-item-desc">{{ item.content }}</div>
<div class="viewpoint-item-job">{{ item.job }}</div>
<div class="viewpoint-item-desc">{{ item.remarks }}</div>
<div class="viewpoint-item-job">{{ item.jobName }}</div>
</div>
</div>
</div>
......@@ -252,9 +260,15 @@
</template>
<script setup>
import { ref } from "vue";
import { ref, onMounted } from "vue";
import CharacterRelationships from "./components/characterRelationships/index.vue";
import RelevantSituation from "./components/relevantSituation/index.vue";
import { getCharacterGlobalInfo,
getCharacterBasicInfo,
getCharacterView,
getCharacterLatestDynamic,
getCharacterResume,
getCharacterFieldView } from "@/api/characterPage/characterPage.js";
import Musk from "./assets/Musk.png";
import spaceX from "./assets/spaceX.png";
......@@ -267,6 +281,22 @@ import img3 from "./assets/img3.png";
import img4 from "./assets/img4.png";
import img5 from "./assets/img5.png";
import DefaultIcon1 from '@/assets/icons/default-icon1.png'
import DefaultIcon2 from '@/assets/icons/default-icon2.png'
// 处理图片代理
const getProxyUrl = (url) => {
if (!url) return "";
const urlStr = String(url);
// 排除非 http 开头(相对路径)、已经是代理链接、或者是本地链接
if (!urlStr.startsWith('http') || urlStr.includes('images.weserv.nl') || urlStr.includes('localhost') || urlStr.includes('127.0.0.1')) {
return url;
}
// 移除协议头 http:// 或 https://
const cleanUrl = urlStr.replace(/^https?:\/\//i, '');
return `https://images.weserv.nl/?url=${encodeURIComponent(cleanUrl)}`;
};
const wordCloudData = ref([
[
......@@ -316,13 +346,193 @@ const musk = ref({
nameEn: "Elon Reeve Musk",
introduction: "南非裔美籍企业家与工程师,SpaceX 与 X(原推特)创始人,特斯拉 CEO,推动商业航天、电动汽车与卫星互联网变革。",
domain: ["电动汽车", "太空探索", "可再生资源", "人工智能", "脑机接口", "超级高铁"],
avatar: Musk
imageUrl: Musk
});
// 获取人物全局信息
const characterInfo = ref({});
const getCharacterGlobalInfoFn = async () => {
const params = {
personId: window.sessionStorage.getItem("personId") || "Y000064"
};
try{
const res = await getCharacterGlobalInfo(params);
if (res.code === 200) {
console.log("人物全局信息", res);
if (res.data) {
characterInfo.value = res.data;
}
}
}catch(error){
}
};
// 获取人物基本信息
const characterBasicInfo = ref({});
const getCharacterBasicInfoFn = async () => {
const params = {
personId: window.sessionStorage.getItem("personId") || "Y000064"
};
try{
const res = await getCharacterBasicInfo(params);
if (res.code === 200) {
console.log("人物基本信息", res);
if (res.data) {
characterBasicInfo.value = res.data;
}
}
}catch (error) {
console.error(error);
}
};
// 获取人物观点
const characterView = ref({});
const getCharacterViewFn = async () => {
const params = {
personId: window.sessionStorage.getItem("personId") || "Y000064",
year: numActive.value || 2025
};
try{
const res = await getCharacterView(params);
if (res.code === 200) {
console.log("人物观点", res);
if (res.data) {
characterView.value = res.data;
}
}
}catch(error){
}
};
// 获取领域观点
const CharacterFieldView = ref({});
const getCharacterFieldViewFn = async () => {
const params = {
areaId: window.sessionStorage.getItem("areaId") || "20",
};
try{
const res = await getCharacterFieldView(params);
if (res.code === 200) {
console.log("领域观点", res);
if (res.data) {
CharacterFieldView.value = res.data;
}
}
}catch(error){
}
};
//是否涉华
const isChecked = ref(false);
const related = ref('N');
const handleChange = event => {
if(isChecked.value){
related.value = 'Y';
}else{
related.value = 'N';
}
getCharacterLatestDynamicFn();
console.log(related.value);
};
const currentPage = ref(1);
// 处理页码改变事件
const handleCurrentChange = page => {
currentPage.value = page;
getCharacterLatestDynamicFn();
};
// 获取最新动态
const CharacterLatestDynamic = ref({});
const total = ref(0);
const pageSize = ref(7);
const loading = ref(false);
const abortController = ref(null);
const getCharacterLatestDynamicFn = async () => {
// 取消上一次未完成的请求
if (abortController.value) {
abortController.value.abort();
}
// 创建新的 AbortController
abortController.value = new AbortController();
loading.value = true;
const params = {
personId: window.sessionStorage.getItem("personId") || "Y000064",
cRelated: related.value,
currentPage: currentPage.value - 1,
pageSize: pageSize.value
};
try{
const res = await getCharacterLatestDynamic(params, abortController.value.signal);
console.log("最新动态", res);
if (res.code === 200) {
if (res.data&& res.data.content) {
CharacterLatestDynamic.value = res.data.content.map(item => ({
title: item.title,
content: item.content,
econtent: item.econtent,
time: item.time,
industryList: item.industryList || ["人工智能"],
orgName: item.orgName,
remarks: item.remarks
}));
total.value = res.data.totalElements;
}else {
CharacterLatestDynamic.value = [];
total.value = 0;
}
}else {
CharacterLatestDynamic.value = [];
total.value = 0;
}
loading.value = false;
}catch (error) {
if (error.name !== "AbortError") {
console.error(error);
loading.value = false;
}
}
};
//获取职业履历
const CharacterResume = ref({});
const getCharacterResumeFn = async () => {
const params = {
personId: window.sessionStorage.getItem("personId") || "Y000064"
};
try{
const res = await getCharacterResume(params);
if (res.code === 200) {
console.log("人物职业履历", res);
if (res.data) {
CharacterResume.value = res.data;
}
}
}catch(error){
}
};
const info = ref(["人物详情", "人物关系", "相关情况"]);
const infoActive = ref("人物详情");
const num = ref(["2025", "2024", "2023", "2022", "2021", "2020"]);
const numActive = ref("2025");
const currentPage = ref(5);
const dialogVisible = ref(false);
const handleClickTag = tag => {
dialogVisible.value = true;
......@@ -501,6 +711,17 @@ const dialogData = ref([
job: "斯坦福大学教授"
}
]);
onMounted(() => {
getCharacterGlobalInfoFn();
getCharacterBasicInfoFn();
getCharacterViewFn();
getCharacterLatestDynamicFn();
getCharacterResumeFn();
getCharacterFieldViewFn();
});
</script>
<style lang="scss" scoped>
......@@ -875,6 +1096,11 @@ const dialogData = ref([
}
}
.content-contentcontent {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
......@@ -1101,8 +1327,9 @@ const dialogData = ref([
height: 114px;
display: flex;
flex-wrap: wrap;
overflow-y: scroll;
.company-item {
width: 185px;
width: 180px;
height: 49px;
margin-bottom: 16px;
display: flex;
......@@ -1114,18 +1341,26 @@ const dialogData = ref([
margin-right: 8px;
}
.company-cn {
width: 130px;
font-size: 16px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(59, 65, 75);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.company-name {
width: 130px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.company-item:nth-child(2n-1) {
......@@ -1198,6 +1433,7 @@ const dialogData = ref([
left: -26px;
}
.content-item-time {
font-size: 16px;
font-weight: 700;
font-family: "Microsoft YaHei";
......@@ -1305,10 +1541,12 @@ const dialogData = ref([
margin-bottom: 12px;
position: relative;
padding-left: 48px;
img {
.viewpoint-item-img {
position: absolute;
top: -20px;
left: -20px;
top: 0;
left: -10px;
width: 42px;
height: 42px;
}
.viewpoint-item-content {
width: 665px;
......
......@@ -4,7 +4,7 @@
<!-- 主要内容 -->
<div class="main">
<!-- 科技领袖 -->
<tech-leader v-if="type == 1" />
<tech-leader v-if="type == 1"/>
<!-- 国会议员 -->
<member-of-congress v-if="type == 2" />
<!-- 智库研究人员 -->
......@@ -23,6 +23,8 @@ import ThinkTankPerson from './components/thinkTankPerson/index.vue';
// 获取路由参数,1为科技领袖,2为国会议员,3为智库研究人员
const route = useRoute();
const type = ref(route.query.type || 1);
</script>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论