Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
2bc44aa0
提交
2bc44aa0
authored
3月 12, 2026
作者:
刘宇琪
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
刘宇琪 创新主题页面
上级
de9b61c0
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
881 行增加
和
101 行删除
+881
-101
AnalysisText.vue
...ews/innovationSubject/InnovationAnalysis/AnalysisText.vue
+79
-0
CustomSelect.vue
...ews/innovationSubject/InnovationAnalysis/CustomSelect.vue
+155
-0
DonutChart.vue
...views/innovationSubject/InnovationAnalysis/DonutChart.vue
+101
-0
InnovationAnalysis.vue
...novationSubject/InnovationAnalysis/InnovationAnalysis.vue
+0
-0
RadarChart.vue
...views/innovationSubject/InnovationAnalysis/RadarChart.vue
+104
-0
RankingTable.vue
...ews/innovationSubject/InnovationAnalysis/RankingTable.vue
+211
-0
api.ts
src/views/innovationSubject/InnovationAnalysis/api.ts
+139
-0
bindEcharts.js
...views/innovationSubject/InnovationAnalysis/bindEcharts.js
+0
-0
index.ts
src/views/innovationSubject/InnovationAnalysis/index.ts
+4
-0
types.ts
src/views/innovationSubject/InnovationAnalysis/types.ts
+63
-0
ResourceLibrary.vue
...ews/innovationSubject/ResourceLibrary/ResourceLibrary.vue
+0
-0
index.ts
src/views/innovationSubject/ResourceLibrary/index.ts
+3
-0
index.vue
src/views/innovationSubject/index.vue
+22
-101
没有找到文件。
src/views/innovationSubject/InnovationAnalysis/AnalysisText.vue
0 → 100644
浏览文件 @
2bc44aa0
<
template
>
<div
class=
"analysis-box"
>
<div
class=
"analysis-icon"
>
<svg
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
>
<circle
cx=
"12"
cy=
"12"
r=
"10"
/>
<path
d=
"M12 6v6l4 2"
/>
</svg>
</div>
<div
class=
"analysis-content"
>
<p
class=
"analysis-text"
>
{{
text
}}
</p>
</div>
<div
v-if=
"showArrow"
class=
"analysis-arrow"
>
<svg
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
>
<path
d=
"M5 12h14M12 5l7 7-7 7"
/>
</svg>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
defineProps
<
{
text
:
string
showArrow
?:
boolean
}
>
()
</
script
>
<
style
scoped
>
.analysis-box
{
display
:
flex
;
align-items
:
flex-start
;
gap
:
12px
;
padding
:
16px
20px
;
background
:
linear-gradient
(
135deg
,
#F0F7FF
0%
,
#E8F4FD
100%
);
border-radius
:
8px
;
border
:
1px
solid
#D4E8FC
;
}
.analysis-icon
{
flex-shrink
:
0
;
width
:
24px
;
height
:
24px
;
color
:
#2D8CF0
;
}
.analysis-icon
svg
{
width
:
100%
;
height
:
100%
;
}
.analysis-content
{
flex
:
1
;
min-width
:
0
;
}
.analysis-text
{
margin
:
0
;
font-size
:
14px
;
line-height
:
1.8
;
color
:
#2D8CF0
;
}
.analysis-arrow
{
flex-shrink
:
0
;
width
:
20px
;
height
:
20px
;
color
:
#2D8CF0
;
cursor
:
pointer
;
transition
:
transform
0.2s
;
}
.analysis-arrow
:hover
{
transform
:
translateX
(
4px
);
}
.analysis-arrow
svg
{
width
:
100%
;
height
:
100%
;
}
</
style
>
src/views/innovationSubject/InnovationAnalysis/CustomSelect.vue
0 → 100644
浏览文件 @
2bc44aa0
<
template
>
<div
ref=
"selectRef"
class=
"custom-select"
:class=
"
{ 'is-open': isOpen }">
<div
class=
"select-trigger"
@
click=
"toggleDropdown"
>
<span
class=
"select-value"
>
{{
selectedLabel
}}
</span>
<svg
class=
"select-arrow"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
>
<path
d=
"M6 9l6 6 6-6"
/>
</svg>
</div>
<Transition
name=
"dropdown"
>
<div
v-if=
"isOpen"
class=
"select-dropdown"
>
<div
v-for=
"option in options"
:key=
"option.value"
class=
"select-option"
:class=
"
{ 'is-selected': option.value === modelValue }"
@click="selectOption(option)"
>
{{
option
.
label
}}
</div>
</div>
</Transition>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
computed
,
onMounted
,
onUnmounted
}
from
'vue'
import
type
{
SelectOption
}
from
'./types'
const
props
=
defineProps
<
{
modelValue
:
string
options
:
SelectOption
[]
placeholder
?:
string
}
>
()
const
emit
=
defineEmits
<
{
'update:modelValue'
:
[
value
:
string
]
}
>
()
const
isOpen
=
ref
(
false
)
const
selectRef
=
ref
<
HTMLDivElement
>
()
const
selectedLabel
=
computed
(()
=>
{
const
option
=
props
.
options
.
find
(
opt
=>
opt
.
value
===
props
.
modelValue
)
return
option
?.
label
||
props
.
placeholder
||
'请选择'
})
function
toggleDropdown
()
{
isOpen
.
value
=
!
isOpen
.
value
}
function
selectOption
(
option
:
SelectOption
)
{
emit
(
'update:modelValue'
,
option
.
value
)
isOpen
.
value
=
false
}
function
handleClickOutside
(
event
:
MouseEvent
)
{
if
(
selectRef
.
value
&&
!
selectRef
.
value
.
contains
(
event
.
target
as
Node
))
{
isOpen
.
value
=
false
}
}
onMounted
(()
=>
{
document
.
addEventListener
(
'click'
,
handleClickOutside
)
})
onUnmounted
(()
=>
{
document
.
removeEventListener
(
'click'
,
handleClickOutside
)
})
</
script
>
<
style
scoped
>
.custom-select
{
position
:
relative
;
min-width
:
120px
;
font-family
:
'Source Han Sans CN'
,
'Microsoft YaHei'
,
sans-serif
;
}
.select-trigger
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
gap
:
8px
;
padding
:
8px
12px
;
background-color
:
#fff
;
border
:
1px
solid
#E0E0E0
;
border-radius
:
4px
;
cursor
:
pointer
;
transition
:
border-color
0.2s
;
}
.select-trigger
:hover
{
border-color
:
#2D8CF0
;
}
.is-open
.select-trigger
{
border-color
:
#2D8CF0
;
}
.select-value
{
font-size
:
14px
;
color
:
#333
;
}
.select-arrow
{
width
:
16px
;
height
:
16px
;
color
:
#999
;
transition
:
transform
0.2s
;
}
.is-open
.select-arrow
{
transform
:
rotate
(
180deg
);
}
.select-dropdown
{
position
:
absolute
;
top
:
calc
(
100%
+
4px
);
left
:
0
;
right
:
0
;
background-color
:
#fff
;
border
:
1px
solid
#E0E0E0
;
border-radius
:
4px
;
box-shadow
:
0
4px
12px
rgba
(
0
,
0
,
0
,
0.1
);
z-index
:
100
;
overflow
:
hidden
;
}
.select-option
{
padding
:
10px
12px
;
font-size
:
14px
;
color
:
#333
;
cursor
:
pointer
;
transition
:
background-color
0.2s
;
}
.select-option
:hover
{
background-color
:
#F5F7FA
;
}
.select-option.is-selected
{
color
:
#2D8CF0
;
background-color
:
#E8F4FD
;
}
.dropdown-enter-active
,
.dropdown-leave-active
{
transition
:
opacity
0.2s
,
transform
0.2s
;
}
.dropdown-enter-from
,
.dropdown-leave-to
{
opacity
:
0
;
transform
:
translateY
(
-8px
);
}
</
style
>
src/views/innovationSubject/InnovationAnalysis/DonutChart.vue
0 → 100644
浏览文件 @
2bc44aa0
<
template
>
<div
class=
"donut-chart-container"
>
<div
v-if=
"loading"
class=
"chart-loading"
>
<div
class=
"loading-spinner"
></div>
</div>
<div
ref=
"chartRef"
class=
"chart"
></div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
onMounted
,
onUnmounted
,
watch
,
shallowRef
}
from
'vue'
import
*
as
echarts
from
'echarts'
import
{
pieOption
}
from
'./bindEcharts'
// 接收 barOptionData: { names: string[], values: number[], total: number }
const
props
=
defineProps
<
{
data
:
{
names
:
string
[]
values
:
number
[]
total
:
number
}
loading
?:
boolean
}
>
()
const
chartRef
=
ref
<
HTMLDivElement
>
()
const
chartInstance
=
shallowRef
<
echarts
.
ECharts
>
()
function
initChart
()
{
if
(
!
chartRef
.
value
)
return
chartInstance
.
value
=
echarts
.
init
(
chartRef
.
value
)
updateChart
()
}
function
updateChart
()
{
if
(
!
chartInstance
.
value
||
props
.
loading
)
return
if
(
!
props
.
data
?.
names
?.
length
)
return
const
option
=
pieOption
(
props
.
data
)
chartInstance
.
value
.
setOption
(
option
)
}
function
handleResize
()
{
chartInstance
.
value
?.
resize
()
}
onMounted
(()
=>
{
initChart
()
window
.
addEventListener
(
'resize'
,
handleResize
)
})
onUnmounted
(()
=>
{
window
.
removeEventListener
(
'resize'
,
handleResize
)
chartInstance
.
value
?.
dispose
()
})
watch
(()
=>
props
.
data
,
updateChart
,
{
deep
:
true
})
watch
(()
=>
props
.
loading
,
(
loading
)
=>
{
if
(
!
loading
)
{
updateChart
()
}
})
</
script
>
<
style
scoped
>
.donut-chart-container
{
position
:
relative
;
width
:
100%
;
height
:
300px
;
}
.chart
{
width
:
100%
;
height
:
100%
;
}
.chart-loading
{
position
:
absolute
;
inset
:
0
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
background-color
:
rgba
(
255
,
255
,
255
,
0.8
);
z-index
:
10
;
}
.loading-spinner
{
width
:
32px
;
height
:
32px
;
border
:
3px
solid
#E8E8E8
;
border-top-color
:
#2D8CF0
;
border-radius
:
50%
;
animation
:
spin
1s
linear
infinite
;
}
@keyframes
spin
{
to
{
transform
:
rotate
(
360deg
);
}
}
</
style
>
src/views/innovationSubject/InnovationAnalysis/InnovationAnalysis.vue
0 → 100644
浏览文件 @
2bc44aa0
差异被折叠。
点击展开。
src/views/innovationSubject/InnovationAnalysis/RadarChart.vue
0 → 100644
浏览文件 @
2bc44aa0
<
template
>
<div
class=
"radar-chart-container"
>
<div
v-if=
"loading"
class=
"chart-loading"
>
<div
class=
"loading-spinner"
></div>
</div>
<div
ref=
"chartRef"
class=
"chart"
></div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
onMounted
,
onUnmounted
,
watch
,
shallowRef
}
from
'vue'
import
*
as
echarts
from
'echarts'
import
{
raderOption
}
from
'./bindEcharts'
// 接收 raderOptionData: API 返回的原始数据
// 数据结构: [{ subjectTypeName: string, areaVoList: [{ areaName: string, amount: number }] }]
const
props
=
defineProps
<
{
data
:
Array
<
{
subjectTypeName
:
string
areaVoList
:
Array
<
{
areaName
:
string
amount
:
number
}
>
}
>
loading
?:
boolean
}
>
()
const
chartRef
=
ref
<
HTMLDivElement
>
()
const
chartInstance
=
shallowRef
<
echarts
.
ECharts
>
()
function
initChart
()
{
if
(
!
chartRef
.
value
)
return
chartInstance
.
value
=
echarts
.
init
(
chartRef
.
value
)
updateChart
()
}
function
updateChart
()
{
if
(
!
chartInstance
.
value
||
props
.
loading
)
return
if
(
!
props
.
data
?.
length
)
return
const
option
=
raderOption
(
props
.
data
)
chartInstance
.
value
.
setOption
(
option
)
}
function
handleResize
()
{
chartInstance
.
value
?.
resize
()
}
onMounted
(()
=>
{
initChart
()
window
.
addEventListener
(
'resize'
,
handleResize
)
})
onUnmounted
(()
=>
{
window
.
removeEventListener
(
'resize'
,
handleResize
)
chartInstance
.
value
?.
dispose
()
})
watch
(()
=>
props
.
data
,
updateChart
,
{
deep
:
true
})
watch
(()
=>
props
.
loading
,
(
loading
)
=>
{
if
(
!
loading
)
{
updateChart
()
}
})
</
script
>
<
style
scoped
>
.radar-chart-container
{
position
:
relative
;
width
:
100%
;
height
:
300px
;
}
.chart
{
width
:
100%
;
height
:
100%
;
}
.chart-loading
{
position
:
absolute
;
inset
:
0
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
background-color
:
rgba
(
255
,
255
,
255
,
0.8
);
z-index
:
10
;
}
.loading-spinner
{
width
:
32px
;
height
:
32px
;
border
:
3px
solid
#E8E8E8
;
border-top-color
:
#2D8CF0
;
border-radius
:
50%
;
animation
:
spin
1s
linear
infinite
;
}
@keyframes
spin
{
to
{
transform
:
rotate
(
360deg
);
}
}
</
style
>
src/views/innovationSubject/InnovationAnalysis/RankingTable.vue
0 → 100644
浏览文件 @
2bc44aa0
<
template
>
<div
class=
"ranking-table"
>
<!-- 动态表头 -->
<div
class=
"table-header"
>
<div
v-for=
"header in headerList"
:key=
"header.columnName"
class=
"col"
:class=
"getColumnClass(header.columnName)"
>
{{
header
.
columnLabel
}}
</div>
</div>
<!-- 加载状态 -->
<div
v-if=
"loading"
class=
"loading-state"
>
<div
class=
"loading-spinner"
></div>
<span>
加载中...
</span>
</div>
<!-- 动态表格内容 -->
<div
v-else
class=
"table-body"
>
<div
v-for=
"(item, index) in dataList"
:key=
"item.recordId || index"
class=
"table-row"
>
<div
v-for=
"header in headerList"
:key=
"header.columnName"
class=
"col"
:class=
"getColumnClass(header.columnName)"
>
{{
formatCellValue
(
item
.
columnValues
[
header
.
columnName
],
header
.
columnName
)
}}
</div>
</div>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
}
from
'vue'
const
props
=
defineProps
<
{
data
:
any
loading
:
boolean
}
>
()
// 表头列表(按 displayOrder 排序)
const
headerList
=
computed
(()
=>
{
if
(
!
props
.
data
?.
headerlist
)
return
[]
return
[...
props
.
data
.
headerlist
].
sort
((
a
,
b
)
=>
a
.
displayOrder
-
b
.
displayOrder
)
})
// 数据列表
const
dataList
=
computed
(()
=>
{
if
(
!
props
.
data
?.
datalist
)
return
[]
return
props
.
data
.
datalist
})
// 根据列名返回对应的 class
function
getColumnClass
(
columnName
:
string
):
string
{
const
classMap
:
Record
<
string
,
string
>
=
{
'ranking'
:
'col-rank'
,
'orgName'
:
'col-name'
,
'count'
:
'col-index'
,
'share'
:
'col-index'
}
return
classMap
[
columnName
]
||
'col-index'
}
// 格式化单元格值
function
formatCellValue
(
value
:
any
,
columnName
:
string
):
string
{
if
(
value
===
undefined
||
value
===
null
)
return
'--'
// 份额指数保留2位小数
if
(
columnName
===
'share'
)
{
return
parseFloat
(
value
).
toFixed
(
2
)
}
return
value
.
toString
()
}
</
script
>
<
style
scoped
>
.ranking-table
{
width
:
100%
;
box-sizing
:
border-box
;
padding
:
0
24px
;
font-family
:
var
(
--font-family-base
,
'Source Han Sans CN'
,
'Microsoft YaHei'
,
sans-serif
);
}
.table-header
{
display
:
flex
;
align-items
:
center
;
padding
:
0
;
border-bottom
:
1px
solid
#D9D9D9
;
color
:
#666666
;
font-size
:
14px
;
font-weight
:
500
;
background-color
:
transparent
;
height
:
60px
;
box-sizing
:
border-box
;
overflow
:
visible
;
}
.table-body
{
min-height
:
200px
;
}
.table-row
{
display
:
flex
;
align-items
:
center
;
padding
:
0
;
border-bottom
:
1px
solid
#F0F0F0
;
transition
:
background-color
0.2s
ease
;
height
:
60px
;
box-sizing
:
border-box
;
}
.table-row
:hover
{
background-color
:
#FAFAFA
;
}
.col
{
flex-shrink
:
0
;
font-size
:
14px
;
color
:
#333333
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
height
:
100%
;
}
.col-rank
{
width
:
60px
;
}
.col-name
{
width
:
210px
;
justify-content
:
flex-start
;
padding-left
:
29px
;
}
.col-type
{
width
:
260px
;
}
.col-index
{
width
:
150px
;
}
.col-score
{
width
:
150px
;
font-weight
:
600
;
color
:
#000
;
}
.col-trend
{
width
:
122px
;
flex
:
1
;
}
.trend-icon
{
display
:
inline-flex
;
align-items
:
center
;
justify-content
:
center
;
width
:
28px
;
height
:
28px
;
border-radius
:
4px
;
flex-shrink
:
0
;
}
.trend-icon
svg
{
width
:
14px
;
height
:
14px
;
}
.trend-up
{
background-color
:
rgba
(
82
,
196
,
26
,
0.15
);
color
:
#52C41A
;
}
.trend-down
{
background-color
:
rgba
(
245
,
34
,
45
,
0.15
);
color
:
#F5222D
;
}
.loading-state
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
padding
:
60px
0
;
color
:
#999999
;
}
.loading-spinner
{
width
:
32px
;
height
:
32px
;
border
:
3px
solid
#E8E8E8
;
border-top-color
:
#2D8CF0
;
border-radius
:
50%
;
animation
:
spin
1s
linear
infinite
;
margin-bottom
:
12px
;
}
@keyframes
spin
{
to
{
transform
:
rotate
(
360deg
);
}
}
</
style
>
src/views/innovationSubject/InnovationAnalysis/api.ts
0 → 100644
浏览文件 @
2bc44aa0
// // 模拟 API 服务
// import type { RankingApiResponse, LayoutApiResponse } from './types'
// // 模拟延迟
// const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
// // 获取创新主体排名数据
// export async function fetchRankingData(year: string): Promise<RankingApiResponse> {
// await delay(500)
// return {
// list: [
// {
// rank: 1,
// name: '麻省理工学院(MIT)',
// type: '研究型大学',
// rdInvestIndex: 64,
// personnelIndex: 72,
// patentIndex: 87,
// paperIndex: 22,
// totalScore: 92,
// trend: 'up'
// },
// {
// rank: 2,
// name: '麻省理工学院',
// type: '国家实验室',
// rdInvestIndex: 66,
// personnelIndex: 60,
// patentIndex: 68,
// paperIndex: 69,
// totalScore: 85,
// trend: 'up'
// },
// {
// rank: 3,
// name: '斯坦福大学',
// type: '科技企业',
// rdInvestIndex: 76,
// personnelIndex: 11,
// patentIndex: 93,
// paperIndex: 51,
// totalScore: 81,
// trend: 'up'
// },
// {
// rank: 4,
// name: '谷歌(Alphabet)',
// type: '科技企业',
// rdInvestIndex: 7,
// personnelIndex: 2,
// patentIndex: 21,
// paperIndex: 4,
// totalScore: 76,
// trend: 'down'
// },
// {
// rank: 5,
// name: '耶鲁大学',
// type: '国防承包商',
// rdInvestIndex: 12,
// personnelIndex: 4,
// patentIndex: 63,
// paperIndex: 38,
// totalScore: 71,
// trend: 'down'
// }
// ],
// analysis: '研究型大学在综合排名中占据主导地位,特别是在论文和影响力指标上表现突出;科技企业在专利指数上领先,但在论文产出方面相对较弱;国家实验室和国防承包商在特定领域(如国家安全、能源)有显著优势,但在综合排名中相对靠后。'
// }
// }
// // 获取研究布局数据
// export async function fetchLayoutData(category: string, year: string): Promise<LayoutApiResponse> {
// await delay(500)
// return {
// fields: [
// { name: '人工智能与信息技术', value: 27, color: '#4A90D9' },
// { name: '生物医学与健康', value: 22, color: '#F5A623' },
// { name: '能源与环境技术', value: 18, color: '#7ED4BC' },
// { name: '先进制造与材料', value: 15, color: '#5BC0DE' },
// { name: '国家安全与国防', value: 12, color: '#F17C67' },
// { name: '航空航天', value: 8, color: '#B8D4E8' }
// ],
// radarIndicators: [
// { name: '集成电路', max: 100 },
// { name: '生物科技', max: 100 },
// { name: '人工智能', max: 100 },
// { name: '通信网络', max: 100 },
// { name: '量子科技', max: 100 },
// { name: '能源领域', max: 100 }
// ],
// radarData: [
// {
// name: '研究型大学',
// color: '#4A7DC9',
// values: [85, 90, 75, 60, 70, 65]
// },
// {
// name: '国家实验室',
// color: '#F5A623',
// values: [70, 65, 80, 75, 85, 80]
// },
// {
// name: '科技企业',
// color: '#B8A9C9',
// values: [90, 55, 95, 85, 50, 45]
// },
// {
// name: '国防承包商',
// color: '#4CAF50',
// values: [60, 40, 70, 65, 90, 85]
// }
// ],
// fieldAnalysis: '人工智能与信息技术占据最大份额,反映了数字经济的核心地位;生物医学与健康是第二大研发领域,特别是在疫情后投入显著增加;能源与环境技术和先进制造与材料作为基础支撑领域保持稳定投入;国家安全与国防和航空航天作为战略领域保持专项投入。',
// radarAnalysis: '研究型大学在基础科学领域(生物医学、材料科学)占据主导地位;科技企业高度集中于人工智能和信息技术领域;国家实验室在能源技术和国家安全相关领域有显著优势;国防承包商的研究高度集中于航空航天和国家安全领域。'
// }
// }
// // 获取年份选项
// export function getYearOptions(): { label: string; value: string }[] {
// return [
// { label: '2023', value: '2023' },
// { label: '2022', value: '2022' },
// { label: '2021', value: '2021' },
// { label: '2020', value: '2020' }
// ]
// }
// // 获取类别选项
// export function getCategoryOptions(): { label: string; value: string }[] {
// return [
// { label: '研发产出投入', value: 'rd_output' },
// { label: '人员投入', value: 'personnel' },
// { label: '专利产出', value: 'patent' },
// { label: '论文产出', value: 'paper' }
// ]
// }
src/views/innovationSubject/InnovationAnalysis/bindEcharts.js
0 → 100644
浏览文件 @
2bc44aa0
差异被折叠。
点击展开。
src/views/innovationSubject/InnovationAnalysis/index.ts
0 → 100644
浏览文件 @
2bc44aa0
// 导出主组件和类型
export
{
default
as
InnovationAnalysis
}
from
'./InnovationAnalysis.vue'
export
*
from
'./types'
export
*
from
'./api'
src/views/innovationSubject/InnovationAnalysis/types.ts
0 → 100644
浏览文件 @
2bc44aa0
// 类型定义
// 机构类型枚举
export
type
OrganizationType
=
'研究型大学'
|
'国家实验室'
|
'科技企业'
|
'国防承包商'
// 创新主体排名数据
export
interface
RankingItem
{
rank
:
number
name
:
string
type
:
OrganizationType
rdInvestIndex
:
number
personnelIndex
:
number
patentIndex
:
number
paperIndex
:
number
totalScore
:
number
trend
:
'up'
|
'down'
}
// 环形图数据项
export
interface
DonutDataItem
{
name
:
string
value
:
number
color
:
string
}
// 雷达图数据项
export
interface
RadarDataItem
{
name
:
string
color
:
string
values
:
number
[]
}
// 雷达图维度指标
export
interface
RadarIndicator
{
name
:
string
max
:
number
color
?:
string
}
// 创新主体排名 API 响应
export
interface
RankingApiResponse
{
data
:
RankingItem
[]
analysisText
:
string
}
// 研究布局 API 响应
export
interface
ResearchLayoutApiResponse
{
donutData
:
DonutDataItem
[]
radarData
:
RadarDataItem
[]
radarIndicators
:
RadarIndicator
[]
donutAnalysisText
:
string
radarAnalysisText
:
string
}
// 请求参数
export
interface
RankingParams
{
year
:
string
}
export
interface
ResearchLayoutParams
{
year
:
string
type
:
string
}
src/views/innovationSubject/ResourceLibrary/ResourceLibrary.vue
0 → 100644
浏览文件 @
2bc44aa0
差异被折叠。
点击展开。
src/views/innovationSubject/ResourceLibrary/index.ts
0 → 100644
浏览文件 @
2bc44aa0
// 资源库组件导出
export
{
default
as
ResourceLibrary
}
from
'./ResourceLibrary.vue'
export
*
from
'./api'
src/views/innovationSubject/index.vue
浏览文件 @
2bc44aa0
...
...
@@ -203,7 +203,8 @@
</div>
-->
</div>
<DivideHeader
id=
"position3"
class=
"divide3"
:titleText=
"'数据总览'"
></DivideHeader>
<div
v-if=
"activeCate === '创新主体排名'"
>
<InnovationAnalysis
:active-cate1=
"activeCate1"
/>
<!--
<div
v-if=
"activeCate === '创新主体排名'"
>
<div
class=
"center-footer"
>
<div
class=
"home-main-footer-header"
>
<div
class=
"btn-box"
>
...
...
@@ -236,31 +237,7 @@
{{
scope
.
row
.
columnValues
[
item
.
columnName
]
}}
</
template
>
</el-table-column>
<!-- <el-table-column prop="name" label="机构名称" width="200"> </el-table-column>
<el-table-column label="类型" width="200">
<template #default="scope">
<div style="display: flex; align-items: center; gap: 5px">
<div v-for="tag in scopetype" :key="tag" :class="{
tag1: tag === '研究型大学',
tag2: tag === '国家实验室',
tag3: tag === '科技企业',
tag4: tag === '国防承包商'
}">
{{ tag }}
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="research" label="研发投入指数" width="200"> </el-table-column>
<el-table-column prop="people" label="人员投入指数" width="200"> </el-table-column>
<el-table-column prop="patent" label="专利产出指数" width="200"> </el-table-column>
<el-table-column prop="paper" label="论文产出指数" width="200"> </el-table-column>
<el-table-column prop="score" label="综合得分" width="150"> </el-table-column>
<el-table-column prop="trend" label="趋势" width="100">
<template #default="scope">
<div :class="{ up: scope.row.trend === 'up', down: scope.row.trend === 'down' }"></div>
</template>
</el-table-column> -->
</el-table>
<div
class=
"center-footer-elx-footer"
>
<img
src=
"./assets/images/ai.png"
alt=
""
/>
...
...
@@ -321,52 +298,12 @@
</div>
</div>
</div>
</div>
</div>
-->
</div>
<div
class=
"home-main-footer"
>
<DivideHeader
id=
"position4"
class=
"divide4"
:titleText=
"'资源库'"
></DivideHeader>
<div
class=
"home-main-footer-header"
>
<div
class=
"btn-box"
>
<div
class=
"btn"
:class=
"{ btnActive: activeCate1 === cate.id }"
v-for=
"(cate, index) in categoryList1"
:key=
"index"
@
click=
"handleClickCate1(cate.id)"
>
{{ cate.typeName }}
</div>
</div>
<div
class=
"select-box"
>
<el-select
v-model=
"areaSelect"
placeholder=
"全部领域"
style=
"width: 120px"
@
change=
"handleFindListBySubjectTypeId"
>
<el-option
v-for=
"item in areaList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</div>
</div>
<div
class=
"home-main-footer-main"
>
<div
style=
"width: 1600px"
>
<div
class=
"footer-main-item"
v-for=
"item in universityList"
:key=
"item.name"
@
click=
"handleClickToDetail(item.orgId)"
>
<img
:src=
"item.logoUrl"
style=
"height: 32px; width: 32px"
/>
<div
class=
"item-text"
>
{{ item.orgName }}
</div>
<div
class=
"item-text2"
>
{{ item.address }}
</div>
<div
class=
"item-text2"
>
{{ item.businessScope }}
</div>
<div
class=
"taglist"
>
<div
class=
"tag1"
v-for=
"(val, idx) in item.taglist"
:key=
"idx"
:class=
"{
tag2: val === '人工智能',
tag3: val === '新一代通信技术',
tag4: val === '生物科技',
tag5: val === '量子科技'
}"
>
{{ val }}
</div>
</div>
</div>
</div>
<div
class=
"footer-box"
>
<div
class=
"footer-right"
>
<el-pagination
@
current-change=
"handleCurrentChange"
:pageSize=
"12"
:current-page=
"currentPage"
background
layout=
"prev, pager, next"
:total=
"total"
/>
</div>
</div>
</div>
<ResourceLibrary
:initial-tab=
"'university'"
/>
</div>
</div>
</div>
...
...
@@ -375,11 +312,10 @@
<
script
setup
>
import
RiskSignal
from
"@/components/RiskSignal/RiskSignal.vue"
;
import
NewsList
from
"@/components/
NewsList/NewsList
.vue"
;
import
NewsList
from
"@/components/
base/newsList/index
.vue"
;
import
{
onMounted
,
ref
,
computed
}
from
"vue"
;
import
*
as
echarts
from
"echarts"
;
import
router
from
"@/router"
;
import
router
from
"@/router"
;
import
DivideHeader
from
"@/components/DivideHeader.vue"
;
import
scrollToTop
from
"@/utils/scrollToTop"
;
import
{
useContainerScroll
}
from
"@/hooks/useScrollShow"
;
...
...
@@ -402,13 +338,13 @@ import {
getResearchFieldSubjectType
}
from
"@/api/innovationSubject/overview.js"
;
import
setChart
from
"@/utils/setChart"
;
import
InnovationAnalysis
from
'./InnovationAnalysis/InnovationAnalysis.vue'
import
News1
from
"./assets/images/news1.png"
;
import
News2
from
"./assets/images/news2.png"
;
import
News3
from
"./assets/images/news3.png"
;
import
News4
from
"./assets/images/news4.png"
;
import
News5
from
"./assets/images/news5.png"
;
import
ResourceLibrary
from
'./ResourceLibrary/ResourceLibrary.vue'
import
Message1
from
"./assets/images/iconp9.png"
;
import
Message2
from
"./assets/images/iconp8.png"
;
import
Message3
from
"./assets/images/iconp5.png"
;
...
...
@@ -430,25 +366,29 @@ const distributionList = ref([
name
:
"研究型大学"
,
num
:
142
,
color
:
"rgba(231, 243, 255, 1)"
,
textcolor
:
"rgba(22, 119, 255, 1)"
textcolor
:
"rgba(22, 119, 255, 1)"
,
id
:
1
},
{
name
:
"国家实验室"
,
num
:
28
,
color
:
"rgba(255, 247, 230, 1)"
,
textcolor
:
"rgba(255, 169, 64, 1)"
textcolor
:
"rgba(255, 169, 64, 1)"
,
id
:
2
},
{
name
:
"科技企业"
,
num
:
326
,
color
:
"rgba(230, 255, 251, 1)"
,
textcolor
:
"rgba(19, 168, 168, 1)"
textcolor
:
"rgba(19, 168, 168, 1)"
,
id
:
3
},
{
name
:
"国防承包商"
,
num
:
38
,
color
:
"rgba(249, 240, 255, 1)"
,
textcolor
:
"rgba(114, 46, 209, 1)"
textcolor
:
"rgba(114, 46, 209, 1)"
,
id
:
4
}
]);
const
distributionColorList
=
ref
([
...
...
@@ -497,26 +437,7 @@ const zhouList = ref([
// name: "马萨诸塞州",
// num: "85"
// },
// {
// index: 2,
// name: "加利福尼亚州",
// num: "67"
// },
// {
// index: 3,
// name: "佐治亚州",
// num: "49"
// },
// {
// index: 4,
// name: "华盛顿州",
// num: "31"
// },
// {
// index: 5,
// name: "伊利诺伊州",
// num: "29"
// }
]);
//统计不同地理对应的主体数量
...
...
@@ -541,7 +462,7 @@ const handleClickToDetail = university => {
// 查看更多风险信号
const
handleToMoreRiskSignal
=
()
=>
{
const
route
=
router
.
resolve
(
"/
viewR
iskSignal"
);
const
route
=
router
.
resolve
(
"/
r
iskSignal"
);
window
.
open
(
route
.
href
,
"_blank"
);
};
...
...
@@ -2196,8 +2117,8 @@ onMounted(async () => {
.home-main-footer
{
margin-top
:
34px
;
height
:
91
0px
;
background
:
rgb
a
(
248
,
249
,
250
,
1
);
height
:
135
0px
;
background
:
rgb
(
255
255
255
);
overflow
:
hidden
;
.divide4
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论