提交 be66e5bb authored 作者: 张伊明's avatar 张伊明

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

......@@ -10,6 +10,7 @@ lerna-debug.log*
*.rar
*.zip
*.7z
*.rest
# Dependencies
node_modules
......
......@@ -321,6 +321,13 @@ body {
.el-popper[data-popper-placement^="top"] > .el-popper__arrow:before {
display: none;
}
/* 单行文本溢出隐藏显示省略号 */
.one-line-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
<style lang="scss" scoped>
......
......@@ -7,32 +7,41 @@ import request from "@/api/request.js";
* @param {String} params.date - 日期
*/
export function getAllUnionList(params) {
return request({
method: 'GET',
url: `/api/union/union/unionList/${params.date}`
})
return request({
method: "GET",
url: `/api/union/union/unionList/${params.date}`,
params: {
domainId: params.domainId ? params.domainId : null
}
});
}
// 全联盟-获取排华数量
/**
* @header token
*/
export function getUnionCount() {
return request({
method: 'GET',
url: `/api/union/union/unionCount`
})
export function getUnionCount(params) {
return request({
method: "GET",
url: `/api/union/union/unionCount`,
params: {
currentPage: params.page ? params.page : 1,
pageSize: params.pageSize ? params.pageSize : 10,
domainId: params.domainId ? params.domainId : null
}
});
}
// 全联盟-获取排华联盟动态
/**
* @header token
*/
export function getDynamic() {
return request({
method: 'GET',
url: `/api/union/union/dynamic`
})
export function getDynamic(params) {
return request({
method: "GET",
url: `/api/union/union/dynamic`,
params
});
}
// 全联盟-获取排华联盟预警
......@@ -42,10 +51,10 @@ export function getDynamic() {
* @header token
*/
export function getPrediction() {
return request({
method: 'GET',
url: `/api/union/union/prediction`
})
return request({
method: "GET",
url: `/api/union/union/prediction`
});
}
// 全联盟-获取排华联盟领域分布
......@@ -55,10 +64,10 @@ export function getPrediction() {
* @header token
*/
export function getIndustry() {
return request({
method: 'GET',
url: `/api/union/union/industry`
})
return request({
method: "GET",
url: `/api/union/union/industry`
});
}
// 全联盟-获取排华联盟国家紧密度
......@@ -68,8 +77,8 @@ export function getIndustry() {
* @header token
*/
export function getCountryRelation() {
return request({
method: 'GET',
url: `/api/union/union/countryRelation`
})
}
\ No newline at end of file
return request({
method: "GET",
url: `/api/union/union/countryRelation`
});
}
......@@ -12,6 +12,18 @@ export function getDecreeBackground(params) {
})
}
// 前序政令
/**
* @param {id}
*/
export function getDecreePrev(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/prev/${params.id}`,
params
})
}
// 相关事件
/**
* @param { id }
......@@ -34,4 +46,28 @@ export function getDecreeDepend(params) {
url: `/api/administrativeOrderInfo/depend/${params.id}`,
params
})
}
// 主要指令
/**
* @param { id }
*/
export function getDecreeMainContent(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/mainContent/${params.id}`,
params
})
}
// 相关实体
/**
* @param { id }
*/
export function getDecreeRelatedEntity(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/relatedEntity/${params.id}`,
params
})
}
\ No newline at end of file
import request from "@/api/request.js";
// 获取相关政令
/**
* @param { id }
*/
export function getDecreeRelatedOrder(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/relatedOrder/${params.id}`,
params
})
}
// 根据政令ID获取领域公司信息
/**
* @param {cRelated, id}
......
......@@ -60,16 +60,17 @@ export function getDecreeSummary(params) {
})
}
// 获取报告原文
// 获取风险信号
/**
* @param {id}
*/
// export function getDecreeReport(params) {
// return request({
// method: 'GET',
// url: `/api/administrativeOrderInfo/contentUrl/${params.id}`,
// })
// }
export function getDecreeRiskSignal(params) {
return request({
method: 'GET',
url: `/api/administrativeOrderInfo/riskSignal/${params.id}`,
params
})
}
export function getDecreeReport(params) {
return request({
......
import request from "@/api/request.js";
const INTELLECTUAL_API = "/intelligent-api";
export class IntelligentResultWrapper<T> {
result: T;
status: string;
}
export class TextEntity {
text_span: string;
type: string;
}
// 智能化:提取文本实体
export function extractTextEntity(text: string): Promise<IntelligentResultWrapper<TextEntity[]>> {
return request({
url: `${INTELLECTUAL_API}/extract-entity`,
method: "POST",
data: {
text
}
});
}
......@@ -35,7 +35,7 @@ export function getHotNews() {
export function getHotNewsByArea(params) {
return request({
method: 'GET',
url: `/api/news/hotNews`,
url: `/api/news/hotAreaNews/${params.moduleId}`,
params
})
}
......
......@@ -83,6 +83,15 @@ export function getThinkTankReport(params) {
})
}
// 智库概览:政策建议(资源库-政策建议)
export function getThinkTankOverviewPolicy(params) {
return request({
method: 'GET',
url: `/api/thinkTankOverview/policy`,
params
})
}
/********* 智库信息 */
//智库百科:获取全局信息
export function getThinkTankSummary(params) {
......@@ -119,6 +128,13 @@ export function getThinkPolicyIndustry(params) {
url: `/api/thinkTankInfo/policyIndustry/${params.id}/${params.year}`,
})
}
//提出政策建议涉及部门分布
export function getPolicyAdviceDeptDistribution(params){
return request({
method: 'GET',
url: `/api/thinkTankInfo/policyDepartment/${params.id}/${params.year}`,
})
}
//获取相关政策领域分布
export function getThinkPolicyIndustryTotal(params) {
......@@ -201,6 +217,15 @@ export const getThinkTankReportSummary = (params) => {
}
);
}
//智库报告:获取相关报告
export const getThinkTankReportRelated = (params) => {
return request(
{
method: 'GET',
url: `/api/thinkTankReport/related/${params}`,
}
);
}
//获取报告原文
export const getThinkTankReportcontentUrl = (params) => {
......
......@@ -2,74 +2,99 @@ import request from "@/api/request.js";
// 全要素统计
export function getElementCount(params) {
return request({
method: 'GET',
url: `/api/element/elementCount/${params.date}`,
})
return request({
method: "GET",
url: `/api/element/elementCount/${params.date}`
});
}
// 美对华科技要素打压遏制数量趋势
export function getElementSuppressTrend(params) {
return request({
method: "GET",
url: `/api/element/DomainContainmentTrend/${params.date}`,
params: {
domainId: params.domainId ? params.domainId : null
}
});
}
// 最新动态
export function getNewDynamics() {
return request({
method: 'GET',
url: `/api/element/newDynamics`,
})
return request({
method: "GET",
url: `/api/element/newDynamics`
});
}
// 美对我要素打压情况
/**
* @param {currentPage, pageSize}
* @param {currentPage, pageSize}
*/
export function getElementSuppress(params) {
return request({
method: 'GET',
url: `/api/element/elementSuppress/${params.date}`,
params
})
return request({
method: "GET",
url: `/api/element/elementSuppress/${params.date}`,
params: {
elementId: params.elementId ? params.elementId : null,
page: params.currentPage,
pageSize: params.pageSize
}
});
}
// 关键词云-上
/**
* @param {date}
* @param {date}
*/
export function getKeyWordUp(params) {
return request({
method: 'GET',
url: `/api/element/getKeyWordUp/${params.date}`,
})
return request({
method: "GET",
url: `/api/element/getKeyWordUp/${params.date}`,
params: {
elementId: params.elementId ? params.elementId : null
}
});
}
// 美自身要素发展情况
/**
* @param {currentPage, pageSize}
* @param {currentPage, pageSize}
*/
export function getElementDevelop(params) {
return request({
method: 'GET',
url: `/api/element/elementDevelop/${params.date}`,
params
})
return request({
method: "GET",
url: `/api/element/elementDevelop/${params.date}`,
params: {
elementId: params.elementId ? params.elementId : null,
page: params.currentPage,
pageSize: params.pageSize
}
});
}
// 关键词云-下
/**
* @param {currentPage, pageSize}
* @param {currentPage, pageSize}
*/
export function getKeyWordDown(params) {
return request({
method: 'GET',
url: `/api/element/getKeyWordDown/${params.date}`,
})
return request({
method: "GET",
url: `/api/element/getKeyWordDown/${params.date}`,
params: {
elementId: params.elementId ? params.elementId : null
}
});
}
// 通过id获取政令详细信息
/**
* @param {id}
* @param {id}
*/
export function getOrderInfo(params) {
return request({
method: 'GET',
url: `/api/element/getOrderInfo/${params.id}`,
params
})
}
\ No newline at end of file
return request({
method: "GET",
url: `/api/element/getOrderInfo/${params.id}`,
params
});
}
差异被折叠。
export const TAGTYPE = ["primary", "success", "warning", "danger", "info"];
// 双色图表
export const DOUBLECHARTCOLORS = [
'#055FC2',
'#CE4F51'
]
// 多色图表预设颜色列表 20种
export const MUTICHARTCOLORS = [
"#69B1FF",
"#FF7875",
"#B37FEB",
"#FFC069",
"#1677FF",
"#87E8DE",
"#ADC6FF",
"#FFBB96",
"#BAE0FF",
"#FFD591",
"#6691FF",
"#FFB2AF",
"#81D0FF",
"#D8E5FB",
"#7981F1",
"#FF9696",
"#6678A1",
"#273C57",
"#E8B8FF",
"#DF812E"
];
......@@ -103,6 +103,7 @@ const headerTitleClasses = computed(() => [
border-bottom: 1px solid #ebeef5;
/* background-color: #f8fafc; */
padding-left: 0;
// background: linear-gradient(180deg, rgb(231, 243, 255) 0%, rgba(231, 243, 255, 0) 100%);
}
.header-left {
......@@ -132,10 +133,10 @@ const headerTitleClasses = computed(() => [
}
.header-icon {
width: 20px;
height: 20px;
width: 22px;
height: 18px;
margin-left: 5px;
margin-right: 19px;
margin-right: 14px;
}
.blue-title-block {
......@@ -148,14 +149,13 @@ const headerTitleClasses = computed(() => [
.header-title {
font-family: $base-font-family;
font-size: $base-font-size;
font-size: 20px;
font-weight: 700;
/* color: var(--color-main-active); */
/* color: var(--base-color); */
color: $base-color;
line-height: 48px;
padding: 0 12px;
font-size: 20px;
// padding: 0 12px;
}
.header-title-primary {
......
......@@ -41,6 +41,7 @@ const classObject = computed(() => ({
height: 24px;
padding: 0 8px;
line-height: 24px;
width: fit-content;
text-align: center;
font-family: Microsoft YaHei;
font-style: Regular;
......
<template>
<div class="wordcloud-wrapper" :style="{ width: width ? width : '520px', height: height ? height : '400px' }">
<div class="chart-box" id="wordcloud-chart">
</div>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
import setChart from '@/utils/setChart';
import getWordCloudChart from './wordCloudChart';
const props = defineProps(({
width: {
type: String,
default: ''
},
height: {
type: String,
default: ''
},
data: {
type: Array,
default: [
// { name: "与马斯克公开冲突", value: 100 },
// { name: "传统能源", value: 5 },
// { name: "共和党财政鹰派", value: 77 },
// { name: "未实现赤字控制目标", value: 35 },
// { name: "得克萨斯州", value: 88 },
// { name: "选举压力", value: 57 },
// { name: "主张财政紧缩", value: 72 },
// { name: "财政保守", value: 18 },
]
}
}))
onMounted(() => {
let chart = getWordCloudChart(props.data);
setChart(chart, "wordcloud-chart");
})
</script>
<style lang="scss">
.chart-box {
width: 100%;
height: 100%;
}
</style>
\ No newline at end of file
import 'echarts-wordcloud';
const getWordCloudChart = (data) => {
const option = {
grid: {
left: 5,
top: 5,
right: 5,
bottom: 5,
},
series: [
{
type: "wordCloud",
shape: 'circle',
width: '100%',
height: '100%',
// 其他形状你可以使用形状路径
// shape: 'circle', // 示例
// 或者自定义路径
gridSize: 35, // 网格大小,影响词间距。
sizeRange: [16, 36], // 定义词云中文字大小的范围
rotationRange: [0, 0],
rotationStep: 0,
drawOutOfBound: false, // 是否超出画布
shrinkToFit: true, // 是否自动缩小以适应容器
// 字体
textStyle: {
// normal: {
// color: function () {
// return 'rgb(' + [
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160)
// ].join(',') + ')';
// }
// },
color: function () {
let colors = [
"rgba(189, 33, 33, 1)",
"rgba(232, 151, 21, 1)",
"rgba(220, 190, 68, 1)",
"rgba(96, 58, 186, 1)",
"rgba(32, 121, 69, 1)",
"rgba(22, 119, 255, 1)",
];
return colors[parseInt(Math.random() * colors.length)];
},
emphasis: {
shadowBlur: 5,
shadowColor: "#333",
},
},
// 设置词云数据
data: data,
},
],
};
return option
}
export default getWordCloudChart
\ No newline at end of file
......@@ -2,7 +2,10 @@
<div class="analysis-box-wrapper" :style="{ width: width ? width : '100%', height: height ? height : '100%' }">
<div class="wrapper-header">
<div class="header-icon"></div>
<div class="header-title">{{ title }}</div>
<div class="header-title">
<div v-if="title">{{ title }}</div>
<slot v-else name="custom-title"></slot>
</div>
<div class="header-btn" v-if="!showAllBtn">
<slot name="header-btn"></slot>
</div>
......@@ -98,54 +101,51 @@ const emit = defineEmits(['save', 'download', 'collect'])
.wrapper-header {
height: 45px;
display: flex;
padding-right: 14px;
align-items: center;
box-sizing: border-box;
position: relative;
.header-icon {
margin-top: 18px;
width: 8px;
height: 20px;
background: var(--color-main-active);
border-radius: 0 4px 4px 0;
margin-right: 14px;
}
.header-title {
margin-left: 14px;
margin-top: 14px;
height: 26px;
flex: auto;
width: 20px;
// color: var(--color-main-active);
// font-family: Source Han Sans CN;
// font-size: 20px;
// font-weight: 700;
// line-height: 26px;
// letter-spacing: 0px;
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
height: 100%;
&>div {
height: 100%;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
line-height: 45px;
font-weight: 700;
}
}
.header-btn {
position: absolute;
top: 14px;
right: 84px;
// display: flex;
// justify-content: flex-end;
// gap: 8px;
}
// .header-btn {
// display: flex;
// justify-content: flex-end;
// gap: 8px;
// }
.header-btn1 {
position: absolute;
top: 14px;
right: 116px;
}
// .header-btn1 {
// position: absolute;
// top: 14px;
// right: 116px;
// }
.header-right {
position: absolute;
top: 14px;
right: 14px;
height: 28px;
display: flex;
justify-content: flex-end;
......
......@@ -8,7 +8,6 @@
</template>
<script setup lang="ts">
import { size } from 'lodash';
import { ref, computed, watch, onMounted } from 'vue';
// 组件属性
......@@ -83,7 +82,7 @@ const processedSvgContent = computed(() => {
});
}
console.log(processed)
// console.log(processed)
return processed;
});
......
......@@ -323,10 +323,12 @@ onMounted(() => {
.nav-right {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 21px;
.info-box {
height: 40px;
display: flex;
justify-content: flex-end;
align-items: center;
......
<template>
<div class="box3-item" @click="handleToNewsAnalysis(news)">
<div class="left">
<img :src="news[props.img] ? news[props.img] : DefaultIconNews" alt="" />
</div>
<div class="right">
<div class="right-top">
<div class="title"><span class="text-inner">{{ news[props.title] }}</span></div>
<div class="time">{{ news[props.from] }}</div>
<el-space alignment="flex-start" :size="10">
<img :width="97" :height="72" :src="news ?? DefaultIconNews" alt="" />
<el-space direction="vertical" alignment="flex-start" :size="0" fill>
<div class="full-width flex-display">
<common-text :line-limit="1" class="text-title-3-bold text-hover flex-fill"
color="var(--text-primary-80-color)">
{{ title }}
</common-text>
<common-text class="text-tip-2" color="var(--text-primary-65-color)">
{{ from }}
</common-text>
</div>
<div class="right-footer">{{ news[props.content] }}</div>
</div>
</div>
<common-text :line-limit="contentLineLimit" class="text-compact" color="var(--text-primary-65-color)">
{{ content }}
</common-text>
</el-space>
</el-space>
</template>
<script setup>
import DefaultIconNews from "@/assets/icons/default-icon-news.png";
const props = defineProps({
// 新闻列表数据
news: {
type: Object,
default: () => { }
},
import { ElSpace } from "element-plus";
import CommonText from "../texts/CommonText.vue";
const props = defineProps({
img: {
type: String,
default: 'img'
default: ''
},
title: {
type: String,
default: "title"
default: ""
},
from: {
type: String,
default: "from"
default: ""
},
content: {
type: String,
default: "content"
default: ""
},
contentLineLimit: {
type: Number,
default: 2
}
});
const emit = defineEmits(['item-click', 'more-click']);
const handleToNewsAnalysis = (item, index) => {
emit('item-click', item, index)
};
</script>
<style lang="scss" scoped>
@use '@/styles/common.scss';
.box3-item {
display: flex;
align-items: center;
height: 78px;
margin: 0px 21px;
cursor: pointer;
&:hover {
.right-top .title {
color: rgb(5, 95, 194) !important;
font-weight: 700;
}
.right-top .text-inner {
border-bottom-color: rgb(5, 95, 194) !important;
}
}
}
.left {
width: 97px;
// flex-shrink: 0;
height: 72px;
img {
width: 100%;
height: 100%;
border-radius: 4px;
}
}
.right {
flex: 1;
min-width: 0;
margin-left: 20px;
.right-top {
display: flex;
justify-content: space-between;
.title {
// width: 500px;
@extend .text-title-3-bold;
color: var(--text-primary-80-color);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.text-inner {
border-bottom: 1px solid transparent;
}
}
.time {
text-align: right;
@extend .text-tip-2;
color: var(--text-primary-65-color);
}
}
.right-footer {
@extend .text-compact;
color: var(--text-primary-65-color);
@include common.text-ellipsis(2);
}
}
@use '@/styles/container.scss';
</style>
\ No newline at end of file
<template>
<el-space alignment="flex-start" :size="10">
<img :width="64" :height="52" :src="news ?? DefaultIconNews" alt="" />
<el-space direction="vertical" alignment="flex-start" :size="0">
<common-text :line-limit="1" class="text-regular text-hover" color="var(--text-primary-80-color)">
{{ title }}
</common-text>
<common-text :line-limit="1" class="text-tip-1" color="var(--text-primary-65-color)">
{{ from }}
</common-text>
</el-space>
</el-space>
</template>
<script setup>
import DefaultIconNews from "@/assets/icons/default-icon-news.png";
import { ElSpace } from "element-plus";
import CommonText from "../texts/CommonText.vue";
const props = defineProps({
img: {
type: String,
default: ''
},
title: {
type: String,
default: ""
},
from: {
type: String,
default: ""
}
});
</script>
<style lang="scss" scoped>
@use '@/styles/common.scss';
</style>
\ No newline at end of file
<template>
<div class="news-item">
<el-space direction="vertical" class="flex-fill" alignment='flex-start'>
<common-text :lineLimit="1" class="text-bold" color="var(--text-primary-80-color)">{{
<common-text :lineLimit="1" class="text-bold text-hover" color="var(--text-primary-80-color)">{{
props.title
}}</common-text>
<common-text class="text-tip-2" color="var(--text-primary-65-color)">
......@@ -12,7 +12,6 @@
</el-space>
</el-space>
<img style="width: 122px; height: 82px" :src="props.img">
<!-- <img v-else style="width: 122px; height: 82px" :src="DefaultIconNews"> -->
</div>
</template>
......
......@@ -80,6 +80,7 @@ const handleToNewsAnalysis = (item, index) => {
flex-direction: column;
gap: 0 !important;
overflow: hidden;
border: 1px solid rgba(234, 236, 238, 1) !important;
.news-header {
height: 48px !important;
......@@ -149,6 +150,7 @@ const handleToNewsAnalysis = (item, index) => {
&:hover {
background: var(--color-bg-hover);
.right-top .title {
text-decoration: underline;
color: rgb(5, 95, 194) !important;
......
......@@ -12,6 +12,7 @@
.left-btn-wrapper {
width: 24px;
height: 48px;
cursor: pointer
img {
width: 100%;
......
......@@ -12,7 +12,7 @@
.right-btn-wrapper {
width: 24px;
height: 48px;
cursor: pointer
img {
width: 100%;
height: 100%;
......
<template>
<div class="common-text">
<div class="common-text-box-hudf">
<slot></slot>
</div>
</template>
......@@ -18,8 +18,8 @@ const props = defineProps({
<style lang="scss" scoped>
@use '@/styles/common.scss';
.common-text {
color: v-bind(color);
.common-text-box-hudf {
color: v-bind(color) !important;
@if('v-bind(lineLimit) !==null') {
@include common.text-ellipsis(v-bind(lineLimit));
......
<template>
<p class="p-regular-rereg">
<span class="text-regular" v-for="(segment, index) in processedText" :key="index">
<a v-if="segment.isEntity" :href="`https://cn.bing.com/search?q=${segment.entity?.text_span}`"
class="entity-link" target="_blank" rel="noopener noreferrer">
{{ segment.entity?.text_span }}
<img :src="SearchIcon" :width="10" :height="10" alt="search" />
</a>
<span v-else>
{{ segment.text }}
</span>
</span>
</p>
</template>
<script lang="ts" setup>
import { TextEntity } from '@/api/intelligent';
import { ref, watch, onMounted } from 'vue';
import SearchIcon from './images/search.png'
export interface ProcessedTextSegment {
text: string
isEntity: boolean
entity?: TextEntity
}
const props = defineProps({
text: {
type: String,
default: ''
},
entities: {
type: Array<TextEntity>,
default: () => []
}
})
// 处理后的文本段
const processedText = ref<ProcessedTextSegment[]>([])
// 处理文本,识别并替换实体
const processText = () => {
console.log('props.entities.length', props.entities.length)
if (!props.text || !props.entities) {
// console.log('props.text', props.entities.length)
processedText.value = [{ text: '', isEntity: false }]
return
}
const result = []
let currentPosition = 0
// 按实体文本长度排序,优先匹配长文本
const sortedEntities = [...props.entities].sort((a, b) =>
b.text_span.length - a.text_span.length
)
while (currentPosition < props.text.length) {
let matched = false
for (const entity of sortedEntities) {
const entityText = entity.text_span
const endPosition = currentPosition + entityText.length
if (props.text.substring(currentPosition, endPosition) === entityText) {
// 如果当前位置是实体,添加到结果
result.push({
isEntity: true,
entity: { ...entity }
})
currentPosition = endPosition
matched = true
break
}
}
if (!matched) {
// 如果不是实体,收集普通文本
let nextEntityStart = props.text.length
for (const entity of sortedEntities) {
const pos = props.text.indexOf(entity.text_span, currentPosition)
if (pos !== -1 && pos < nextEntityStart) {
nextEntityStart = pos
}
}
if (nextEntityStart > currentPosition) {
const plainText = props.text.substring(currentPosition, nextEntityStart)
result.push({
text: plainText,
isEntity: false
})
currentPosition = nextEntityStart
} else {
// 没有更多实体,添加剩余文本
const remainingText = props.text.substring(currentPosition)
if (remainingText) {
result.push({
text: remainingText,
isEntity: false
})
}
currentPosition = props.text.length
}
}
}
processedText.value = result
}
// 监听文本和实体变化
watch(() => props.text, processText)
watch(() => props.entities, processText, { deep: true })
// 初始化处理
onMounted(processText)
</script>
<style lang="scss" scoped>
@use '@/styles/common.scss';
.entity-link {
color: var(--color-primary-100);
}
.p-regular-rereg {
text-indent: 2em;
}
</style>
\ No newline at end of file
<template>
<div class="full-width">
<div class="flex-display" style="align-items: center;">
<common-text class="text-title-3-bold" color="var(--text-primary-80-color)">{{ isOpenTranslation
? '中文' : '原文' }}</common-text>
<div class="flex-fill" style="margin: 0 10px;">
<el-divider></el-divider>
</div>
<el-button v-if="showMoreVisible" @click="() => { showMore = !showMore; updateText() }">
{{ showMore ? '收起' : '展开' }}
<el-icon>
<arrow-down v-if="showMore" />
<arrow-up v-else />
</el-icon>
</el-button>
</div>
<el-row :gutter="32">
<el-col :span="textColSpan" v-for="(item, index) in allTexts" :key="index">
<!-- <p class="p-news-content"> {{ item }}</p> -->
<intelligent-entity-text :text="item"
:entities="isHighlightEntity ? textEntities : []"></intelligent-entity-text>
</el-col>
</el-row>
</div>
</template>
<script lang="ts" setup>
import '@/styles/container.scss';
import '@/styles/common.scss';
import { ref, watch, onMounted } from 'vue';
import { TextEntity } from '@/api/intelligent';
import IntelligentEntityText from '@/components/base/texts/IntelligentEntityText.vue';
import { ElIcon, ElButton, ElDivider, ElRow, ElCol } from 'element-plus';
import CommonText from './CommonText.vue';
const allTexts = ref([]);
const textColSpan = ref(12);
const hasTranslation = ref(false);
const showMore = ref(false);
const showMoreVisible = ref(false);
const props = defineProps({
//段落列表: 原始文本
textsRaw: {
type: Array<String>,
default: () => []
},
//段落列表: 翻译文本
textsTranslate: {
type: Array<String>,
default: () => []
},
//是否显示翻译
isOpenTranslation: {
type: Boolean,
default: true
},
//是否高亮实体
isHighlightEntity: {
type: Boolean,
default: true
},
//实体列表
textEntities: {
type: Array<TextEntity>,
default: () => []
}
})
function updateText() {
const tempTexts = []
const tempRaws = props.textsRaw ?? []
const tempTranslates = props.textsTranslate ?? []
hasTranslation.value = tempTranslates.length > 0
if (hasTranslation.value && props.isOpenTranslation) {
// 遍历原始文本和翻译文本,将它们交替添加到 tempTexts 中,并保持原始文本和翻译文本的的数量一致
const maxCount = Math.max(tempRaws.length, tempTranslates.length)
for (let i = 0; i < maxCount; i++) {
if (i < tempTranslates.length) {
tempTexts.push(tempTranslates[i]);
} else {
tempTexts.push('');
}
if (i < tempRaws.length) {
tempTexts.push(tempRaws[i]);
} else {
tempTexts.push('');
}
}
console.log(tempTexts.length)
textColSpan.value = 12;
showMoreVisible.value = tempTexts.length > 6;
allTexts.value = showMore.value ? tempTexts : tempTexts.slice(0, 6);
} else {
textColSpan.value = 24;
showMoreVisible.value = tempRaws.length > 3;
allTexts.value = showMore.value ? tempRaws : tempRaws.slice(0, 3);
}
}
watch(() => [props.textsRaw, props.textsTranslate, props.isOpenTranslation], () => {
updateText();
})
onMounted(() => {
updateText();
})
</script>
\ No newline at end of file
......@@ -33,4 +33,15 @@ const comprehensiveSearchRoutes = [
]
import { useGotoPage } from "../common.js";
export function useGotoComprehensiveSearch() {
const gotoPage = useGotoPage();
return (isNewTabs = true) => gotoPage("/comprehensiveSearch/", {}, isNewTabs)
}
export function useGotoSearchResults() {
const gotoPage = useGotoPage();
return (isNewTabs = true) => gotoPage("/searchResults/", {searchText, areaName}, isNewTabs)
}
export default comprehensiveSearchRoutes
\ No newline at end of file
......@@ -4,6 +4,7 @@ const DecreeLayoutContainer = () => import('@/views/decree/decreeLayout/index.vu
const DecreeOverviewLayout = () => import('@/views/decree/decreeLayout/overview/index.vue')
const DecreeIntroduction = () => import('@/views/decree/decreeLayout/overview/introduction/index.vue')
const DecreeBackground = () => import('@/views/decree/decreeLayout/overview/background/index.vue')
const DecreeMeasures = () => import('@/views/decree/decreeLayout/overview/measures/index.vue')
const DecreeDeepDig = () => import('@/views/decree/decreeLayout/deepdig/index.vue')
const DecreeInfluence = () => import('@/views/decree/decreeLayout/influence/index.vue')
const Institution = () => import('@/views/decree/institution/index.vue')
......@@ -50,7 +51,13 @@ const decreeRoutes = [
name: "DecreeBackground",
component: DecreeBackground,
// meta: { title: "政令背景" }
}
},
{
path: "measures",
name: "DecreeMeasures",
component: DecreeMeasures,
// meta: { title: "政令举措" }
},
]
},
// 深度挖掘路由
......
......@@ -71,6 +71,14 @@
color: var(--text-primary-80);
}
.text-hover {
&:hover {
color: rgb(5, 95, 194) !important;
font-weight: 700;
cursor: pointer;
}
}
//0级标题
.text-title-0 {
@extend .text-base;
......
<template>
<el-row class="wrapper layout-grid-line">
<el-col :span="span">
<pre>
{{
`
import ActionButton from '@/components/base/ActionButton/index.vue'
<ActionButton name="全部选项" type="active" />
<ActionButton name="选项A" type="normal" />
<ActionButton name="选项B" type="normal" />
<ActionButton name="选项C" type="normal" />
选项按钮
`
}}
</pre>
<div class="button-box">
<ActionButton name="全部选项" type="active" />
<ActionButton name="选项A" type="normal" />
<ActionButton name="选项B" type="normal" />
<ActionButton name="选项C" type="normal" />
</div>
</el-col>
<el-col :span="span">
<pre>
{{
`
import LeftBtn from '@/components/base/PageBtn/LeftBtn.vue'
import RightBtn from '@/components/base/PageBtn/RightBtn.vue'
<LeftBtn />
<RightBtn />
左右按钮
`
}}
</pre>
<div class="button-box1">
<LeftBtn />
<RightBtn />
</div>
</el-col>
</el-row>
</template>
<script setup>
import '@/styles/common.scss'
import LeftBtn from '@/components/base/PageBtn/LeftBtn.vue'
import RightBtn from '@/components/base/PageBtn/RightBtn.vue'
const span = 12
</script>
<style lang="scss" scoped>
.button-box {
margin-left: 40px;;
display: flex;
gap: 8px
}
.button-box1 {
width: 200px;
display: flex;
justify-content: space-between;
margin-left: 40px;
margin-bottom: 10px;
gap: 8px
}
</style>
\ No newline at end of file
<template>
<el-row class="wrapper layout-grid-line">
<el-col :span="span">
<pre>
{{
`
import AreaTag from '@/components/base/AreaTag/index.vue'
<AreaTag tagName="人工智能" />
<AreaTag tagName="生物科技" />
<AreaTag tagName="新一代通信网络" />
<AreaTag tagName="量子科技" />
<AreaTag tagName="新能源" />
`
}}
</pre>
<div class="tag-box">
<AreaTag tagName="人工智能" />
<AreaTag tagName="生物科技" />
<AreaTag tagName="新一代通信网络" />
<AreaTag tagName="量子科技" />
<AreaTag tagName="新能源" />
</div>
</el-col>
</el-row>
</template>
<script setup>
import '@/styles/common.scss'
import AreaTag from '@/components/base/AreaTag/index.vue'
const span = 12
</script>
<style lang="scss" scoped>
.tag-box{
display: flex;
gap: 8px
}
</style>
\ No newline at end of file
......@@ -38,6 +38,14 @@ const span = 12
</pre>
<div class="mouse-hover">鼠标悬停</div>
</el-col>
<el-col :span="span">
<pre>{{ `import '@/styles/common.scss';\n<template>
<div class="text-hover"></div>
</template>
`}}
</pre>
<div class="text-hover">文字悬停</div>
</el-col>
</el-row>
</template>
......
<template>
<el-space direction="vertical" class="common-padding" fill alignment="flex-start">
<el-space>
<el-switch v-model="isHightLightEntity" active-text="高亮实体" @change="console.log(isHightLightEntity)" />
<el-switch v-model="isOpenTranslation" active-text="译文" />
</el-space>
<text-translate-pane :texts-raw="textEns" :texts-translate="textZns" :text-entities="textEntities"
:is-open-translation="isOpenTranslation" :is-highlight-entity="isHightLightEntity">
</text-translate-pane>
</el-space>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import TextTranslatePane from '@/components/base/texts/TextTranslatePane.vue'
import { ElSwitch, ElButton, ElSpace } from 'element-plus'
const isOpenTranslation = ref(true);
const isHightLightEntity = ref(true);
const textEntities = ref([{
text_span: '美国',
type: '国家'
},
{
text_span: 'U.S.',
type: '国家'
}]);
const textZns = ref(['华盛顿当地时间2024年7月2日,美国商务部产业与安全局(BIS)',
'发布一项最终规则,宣布修订《出口管理条例》(EAR) ,',
'以违反美国国家安全或外交政策利益为由在实体清单中增列来自四个国家的6个实体,其中包括2家中国企业。[1]',
'多余段落-测试']);
const textEns = ref(['Washington local time on July 2, 2024, the U.S. Department of Commerce, Industry and Security (BIS) released a final rule, announcing the revision of the Export Administration Regulations (EAR) ,',
'Violating the U.S. national security or diplomatic policy interests, BIS increased the list of 6 entities from four countries, including 2 Chinese companies, on the entity list. [1]',
'Your company has a large amount of money in the U.S.',
]);
</script>
<style scoped>
:deep(.el-col) {
border: 0px !important;
}
</style>
......@@ -4,6 +4,9 @@ import '@/styles/tabs.scss'
import ColorPrefixTitle from '@/components/base/texts/ColorPrefixTitle.vue';
import AiTipPane from '@/components/base/panes/AiTipPane.vue';
import CommonText from '@/components/base/texts/CommonText.vue';
import IntelligentEntityText from '@/components/base/texts/IntelligentEntityText.vue';
import TranslateExample from './TranslateExample.vue';
const span = 12
</script>
......@@ -50,6 +53,40 @@ const span = 12
</pre>
<ai-tip-pane>huidadadadadasda</ai-tip-pane>
</el-col>
<el-col :span="span">
<pre>{{ `import IntelligentEntityText from '@/components/base/texts/IntelligentEntityText.vue';\n<template>
<intelligent-entity-text
text="华盛顿当地时间2024年7月2日,美国商务部产业与安全局(BIS) 发布一项最终规则,宣布修订《出口管理条例》(EAR) ,以违反美国国家安全或外交政策利益为由在实体清单 中增列来自四个国家的6个实体,其中包括2家中国企业。[1]"
:entities="[{
text_span: '华盛顿',
type: 'location'
}, {
text_span: '美国商务部产业与安全局',
type: 'organization'
}]">
</intelligent-entity-text>
</template>
`}}
</pre>
<intelligent-entity-text
text="华盛顿当地时间2024年7月2日,美国商务部产业与安全局(BIS) 发布一项最终规则,宣布修订《出口管理条例》(EAR) ,以违反美国国家安全或外交政策利益为由在实体清单 中增列来自四个国家的6个实体,其中包括2家中国企业。[1]"
:entities="[{
text_span: '华盛顿',
type: 'location'
}, {
text_span: '美国商务部产业与安全局',
type: 'organization'
}]">
</intelligent-entity-text>
</el-col>
<el-col :span="span">
<pre>{{ `参考src/styles/components/TextPage/TranslateExample.vue` }}
</pre>
<translate-example>
</translate-example>
</el-col>
</el-row>
</template>
......
<template>
<el-row class="wrapper layout-grid-line">
<el-col :span="span">
<pre>
{{
`
import WordCloudChart from "@/components/base/WordCloundChart/index.vue"
<div class="chart-box">
<WordCloudChart :data="data" />
</div>
`
}}
</pre>
<div class="chart-box">
<WordCloudChart :data="data" />
</div>
</el-col>
</el-row>
</template>
<script setup>
import {ref} from 'vue'
import '@/styles/common.scss'
import WordCloudChart from "@/components/base/WordCloundChart/index.vue"
const span = 12
const data = ref([
{ name: "与马斯克公开冲突", value: 100 },
{ name: "传统能源", value: 5 },
{ name: "共和党财政鹰派", value: 77 },
{ name: "未实现赤字控制目标", value: 35 },
{ name: "得克萨斯州", value: 88 },
{ name: "选举压力", value: 57 },
{ name: "主张财政紧缩", value: 72 },
{ name: "财政保守", value: 18 },
])
</script>
<style lang="scss" scoped>
.chart-box {
width: 520px;
height: 400px;
border: 1px solid var(--bg-black-5);
}
</style>
\ No newline at end of file
.layout-grid-line {
.el-col {
.el-col:not(disinheritance) {
border: 1px double var(--bg-black-5);
}
......
......@@ -8,7 +8,7 @@
<div class="text-title-1-show">文字样式</div>
<TextStyle />
<div class="text-title-1-show">通用样式/组件</div>
<div style="position: relative; min-height: 300px;">
<div style="position: relative; min-height: 700px;">
<el-tabs tabPosition="left" class="tabs-nav-no-wrap left-float-nav-tabs">
<el-tab-pane label="通用" lazy>
<common-page />
......@@ -31,12 +31,21 @@
<el-tab-pane label="预警面板" lazy>
<WarnningPane />
</el-tab-pane>
<el-tab-pane label="领域标签" lazy>
<AreaTag />
</el-tab-pane>
<el-tab-pane label="按钮" lazy>
<ActionButton />
</el-tab-pane>
<el-tab-pane label="层级关系图" lazy>
<GraphChart />
</el-tab-pane>
<el-tab-pane label="引力关系图" lazy>
<GraphTreeChart />
</el-tab-pane>
<el-tab-pane label="词云图" lazy>
<WordCloudChart />
</el-tab-pane>
</el-tabs>
</div>
</el-space>
......@@ -59,6 +68,9 @@ import PeoplePage from './People/index.vue';
import WarnningPane from './WarnningPane/index.vue'
import GraphChart from './GraphChart/index.vue'
import GraphTreeChart from './GraphTreeChart/index.vue'
import AreaTag from './AreaTag/index.vue'
import ActionButton from './ActionButton/index.vue'
import WordCloudChart from './WordCloudChart/index.vue'
</script>
<style lang="scss" scoped>
......
......@@ -141,12 +141,30 @@
@page-change="handleNewsPageChange"
/>
</div>
<!-- <custom-container title="美对华领域打压遏制排行" :titleIcon="icon3" height="700px">
<template #header-right>
<div class="title-right-select">
<el-select
v-model="selectedField"
@change="handleFieldChange"
placeholder="全部领域"
class="field-select"
:style="{ width: '160px' }"
>
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</template>
</custom-container> -->
<div class="empty-section">
<div class="bottom-item">
<div class="bottom-item-title">
<img :src="icon3" alt="" />
<span>美对华领域打压遏制排行</span>
</div>
<el-select v-model="selectedField" placeholder="全部领域" class="field-select">
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="select-box">
<div class="rank-btns">
......@@ -160,13 +178,18 @@
受打压院校
</div>
</div>
<el-select v-model="selectedField" placeholder="全部领域" class="field-select">
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="main-box" v-loading="rankLoading" element-loading-background="rgba(255, 255, 255, 0.5)">
<!-- 机构排行的原有样式 -->
<template v-if="rankType === 'institution'">
<div class="table-header">
<div class="col-rank col-rank-75"></div>
<div class="col-name" style="color: rgb(59, 65, 75); font-weight: 700">部门名称</div>
<div class="col-domain" style="color: rgb(59, 65, 75); font-weight: 700"></div>
<div class="col-date" style="color: rgb(59, 65, 75); font-weight: 700"></div>
<div class="col-member" v-if="rankType !== 'school'" style="color: rgb(59, 65, 75); font-weight: 700">
打压次数
</div>
</div>
<div v-for="(item, index) in rankList" :key="index" class="rank-item">
<div class="rank-num" :class="'rank-' + (index + 1)">{{ index + 1 }}</div>
<img :src="item.orgPicture ? item.orgPicture : defaultImg" alt="" class="rank-icon" />
......@@ -177,7 +200,6 @@
<div class="rank-count">{{ item.count }}</div>
</div>
</template>
<!-- 企业/院校排行的表格样式 -->
<template v-else>
<div class="table-header">
<div class="col-rank"></div>
......@@ -210,7 +232,6 @@
</div>
</div>
<div class="col-date">{{ item.date }}</div>
<!-- <div class="col-member" v-if="rankType !== 'school'">{{ item.member }}</div> -->
<div class="col-member" v-if="rankType !== 'school'">{{ item.province }}</div>
</div>
</div>
......@@ -315,10 +336,13 @@ import getMultiLineChart from "./multiLineChart";
import CommonPrompt from "../../../../commonPrompt/index.vue";
import leftBtn from "../../assets/left-btn.png";
import rightBtn from "../../assets/right-btn.png";
import icon1 from "./icon/icon-1.png";
import icon3 from "./icon/icon-3.png";
import icon4 from "./icon/icon-4.png";
import defaultImg from "../../../../assets/images/default-icon2.png";
import { fieldOptions } from "@/views/ZMOverView/public.js";
import {
getAllDomainCount,
getDomainContainmentTrend,
......@@ -330,6 +354,7 @@ import { getUSGovernmentLatestDynamic, getDepartmentList, getSanTypeList } from
import { ElMessage } from "element-plus";
import { ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
import SimplePagination from "@/components/SimplePagination.vue";
import CustomContainer from "@/components/Container/index.vue";
const router = useRouter();
......@@ -752,23 +777,23 @@ const svgHeight = computed(() => {
return startY + rows * rowHeight + 50;
});
const fieldOptions = [
{ value: "", label: "全部领域" },
{ value: "1", label: "人工智能" },
{ value: "2", label: "生物科技" },
{ value: "3", label: "新一代信息技术" },
{ value: "4", label: "量子科技" },
{ value: "5", label: "新能源" },
{ value: "6", label: "集成电路" },
{ value: "7", label: "海洋" },
{ value: "8", label: "先进制造" },
{ value: "9", label: "新材料" },
{ value: "10", label: "航空航天" },
{ value: "11", label: "深海" },
{ value: "12", label: "极地" },
{ value: "13", label: "太空" },
{ value: "14", label: "核" }
];
// const fieldOptions = [
// { value: "", label: "全部领域" },
// { value: "1", label: "人工智能" },
// { value: "2", label: "生物科技" },
// { value: "3", label: "新一代信息技术" },
// { value: "4", label: "量子科技" },
// { value: "5", label: "新能源" },
// { value: "6", label: "集成电路" },
// { value: "7", label: "海洋" },
// { value: "8", label: "先进制造" },
// { value: "9", label: "新材料" },
// { value: "10", label: "航空航天" },
// { value: "11", label: "深海" },
// { value: "12", label: "极地" },
// { value: "13", label: "太空" },
// { value: "14", label: "核" }
// ];
// 全领域统计
const buttonsData = ref([]);
......@@ -1614,8 +1639,8 @@ watch(activeDate, () => {
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 17px;
padding-right: 35px;
padding-left: 16px;
padding-right: 16px;
box-sizing: border-box;
background: linear-gradient(180deg, rgba(231, 243, 255, 1) 0%, rgba(231, 243, 255, 0) 100%);
.bottom-item-title {
......@@ -1634,14 +1659,19 @@ watch(activeDate, () => {
color: rgb(5, 95, 194);
}
}
.field-select {
width: 160px;
}
}
.select-box {
width: 691px;
height: 32px;
height: 50px;
margin: 10px auto 5px auto;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
padding-bottom: 15px;
.rank-btns {
display: flex;
......@@ -1698,7 +1728,7 @@ watch(activeDate, () => {
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 28px;
gap: 21px;
overflow-y: auto;
.rank-item {
display: flex;
......@@ -1910,6 +1940,9 @@ watch(activeDate, () => {
text-align: center;
flex-shrink: 0;
}
.col-rank-75 {
width: 75px;
}
.col-name {
flex: 1.5;
min-width: 0;
......
{
"code": 200,
"message": "操作成功",
"success": true,
"data": [
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-01"
},
{
"elementName": "科研人才",
"elementNum": 1,
"elementDate": "2025-01"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-01"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-02"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-02"
},
{
"elementName": "科研仪器",
"elementNum": 1,
"elementDate": "2025-02"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-03"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-03"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-03"
},
{
"elementName": "科研机构",
"elementNum": 1,
"elementDate": "2025-04"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-04"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-04"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-05"
},
{
"elementName": "科研人才",
"elementNum": 1,
"elementDate": "2025-05"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-05"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-06"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-06"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-06"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-07"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-07"
},
{
"elementName": "科研仪器",
"elementNum": 3,
"elementDate": "2025-07"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-08"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-08"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-08"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-09"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-09"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-09"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-10"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-10"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-10"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-11"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-11"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-11"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2025-12"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2025-12"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2025-12"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2026-01"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2026-01"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2026-01"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2026-02"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2026-02"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2026-02"
},
{
"elementName": "科研机构",
"elementNum": 0,
"elementDate": "2026-03"
},
{
"elementName": "科研人才",
"elementNum": 0,
"elementDate": "2026-03"
},
{
"elementName": "科研仪器",
"elementNum": 0,
"elementDate": "2026-03"
}
]
}
\ No newline at end of file
No preview for this file type
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论