Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
efda93be
提交
efda93be
authored
12月 05, 2025
作者:
huhuiqing
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
研发投入+研究人员+专利情况(待完善)
上级
d28bc11c
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
624 行增加
和
809 行删除
+624
-809
Capability copy.vue
src/views/companyPages/component/Capability copy.vue
+0
-792
Capability.vue
src/views/companyPages/component/Capability.vue
+105
-17
researcher.vue
src/views/companyPages/component/researcher.vue
+375
-0
donutChart.js
src/views/companyPages/js/donutChart.js
+64
-0
radarChart.js
src/views/companyPages/js/radarChart.js
+80
-0
没有找到文件。
src/views/companyPages/component/Capability copy.vue
deleted
100644 → 0
浏览文件 @
d28bc11c
<
template
>
<div
class=
"page-content"
>
<!-- 公司导航栏 -->
<div
class=
"company-nav"
>
<div
class=
"company-logo-title"
>
<img
:src=
"data.company.logo"
alt=
"华为logo"
class=
"logo-img"
>
<div
class=
"title-group"
>
<h1
class=
"company-name"
>
{{
data
.
company
.
name
}}
</h1>
<p
class=
"company-english"
>
{{
data
.
company
.
englishName
}}
</p>
</div>
</div>
<div
class=
"main-tabs"
>
<div
v-for=
"(tab, index) in tabList"
:key=
"index"
:class=
"activeTab === tab ? 'tab-active' : 'tab'"
@
click=
"switchTab(tab)"
>
<img
:src=
"`src/assets/icons/company$
{index + 1}.svg`" alt="tab图标" class="icon mail-icon" />
{{
tab
}}
</div>
</div>
</div>
<!-- 主体内容区 -->
<div
class=
"main-content"
>
<!-- 左侧信息栏 -->
<div
class=
"left-sidebar"
>
<img
:src=
"data.company.logo"
alt=
"华为logo"
class=
"sidebar-logo"
>
<h2
class=
"sidebar-company-name"
>
{{
data
.
company
.
name
}}
</h2>
<div
class=
"contact-list"
>
<div
class=
"contact-item"
>
<img
src=
"../../assets/icons/shutter.svg"
alt=
"网址"
class=
"contact-icon"
>
<span>
{{
data
.
contactInfo
.
website
}}
</span>
</div>
<div
class=
"contact-item"
>
<img
src=
"../../assets/icons/location.svg"
alt=
"地址"
class=
"contact-icon"
>
<span>
{{
data
.
contactInfo
.
address
}}
</span>
</div>
<div
class=
"contact-item"
>
<img
src=
"../../assets/icons/call.svg"
alt=
"电话"
class=
"contact-icon"
>
<span>
{{
data
.
contactInfo
.
phone
}}
</span>
</div>
<div
class=
"contact-item"
>
<img
src=
"../../assets/icons/mail.svg"
alt=
"邮箱"
class=
"contact-icon"
>
<span>
{{
data
.
contactInfo
.
email
}}
</span>
</div>
</div>
<!-- 左侧数据根据标签切换 -->
<div
class=
"financial-list"
v-if=
"activeTab === '基础信息'"
>
<div
class=
"financial-item"
v-for=
"(item, idx) in data.financialData"
:key=
"idx"
>
<p
class=
"financial-value"
>
{{
item
.
value
}}
</p>
<p
class=
"financial-label"
>
{{
item
.
label
}}
</p>
</div>
</div>
<div
class=
"financial-list"
v-if=
"activeTab === '研发实力'"
>
<div
class=
"financial-item"
v-for=
"(value, key) in rndData.rndInfo"
:key=
"key"
>
<p
class=
"financial-value"
>
{{
value
}}
</p>
<p
class=
"financial-label"
>
{{
key
}}
</p>
</div>
</div>
</div>
<!-- 右侧内容区 -->
<div
class=
"right-content"
>
<!-- 基础信息标签内容 -->
<div
v-if=
"activeTab === '基础信息'"
>
<!-- 子标签栏 -->
<div
class=
"sub-tabs"
>
<span
v-for=
"(tab, idx) in data.company.subTabs"
:key=
"idx"
:class=
"['sub-tab', data.company.activeSubTab === tab ? 'active' : '']"
>
{{
tab
}}
</span>
<div
class=
"action-icons"
>
<img
src=
"../../assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"../../assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<!-- 企业概况内容 -->
<div
class=
"overview-content"
>
<div
class=
"info-grid"
>
<div
class=
"info-card"
>
<h3
class=
"section-title"
>
类别分布
</h3>
<ul
class=
"info-list"
>
<li
v-for=
"(value, key) in data.categoryDist"
:key=
"key"
style=
"display: flex;align-items: center;"
>
<div
class=
"li-icon"
></div>
<span
class=
"info-key"
>
{{
key
}}
</span>
<span
class=
"info-value"
>
{{
value
}}
</span>
</li>
</ul>
</div>
<div
class=
"info-card"
>
<h3
class=
"section-title"
>
经营信息
</h3>
<ul
class=
"info-list"
>
<li
v-for=
"(value, key) in data.businessInfo"
:key=
"key"
style=
"display: flex;align-items: center;"
>
<div
class=
"li-icon"
></div>
<span
class=
"info-key"
>
{{
key
}}
</span>
<span
class=
"info-value"
>
{{
value
}}
</span>
</li>
</ul>
</div>
</div>
</div>
<!-- 主要人员 -->
<div
class=
"section"
>
<div
class=
"section-header"
style=
"margin-top: 24px;"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
主要人员
</h3>
</div>
<div
class=
"personnel-grid"
>
<div
class=
"personnel-card"
v-for=
"(person, idx) in data.mainPersonnel"
:key=
"idx"
>
<div
class=
"personnel-card-header"
>
<img
:src=
"person.avatar"
alt=
"头像"
class=
"person-avatar"
>
<div
class=
"person-info"
>
<h4
class=
"person-name"
>
{{
person
.
name
}}
</h4>
<p
class=
"person-position"
>
{{
person
.
position
}}
</p>
</div>
</div>
<p
class=
"person-desc"
>
{{
person
.
desc
}}
</p>
</div>
</div>
</div>
<!-- 分支机构 -->
<div
class=
"section"
>
<div
class=
"section-header"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
分支机构
</h3>
</div>
<div
class=
"branches-grid"
>
<div
class=
"branch-item"
v-for=
"(branch, idx) in data.branches"
:key=
"idx"
>
<span>
{{
branch
}}
</span>
<img
src=
"../../assets/icons/open.png"
alt=
"箭头"
class=
"branch-arrow"
>
</div>
</div>
</div>
</div>
<!-- 研发实力标签内容 -->
<div
v-if=
"activeTab === '研发实力'"
>
<!-- 研发子标签栏 -->
<div
class=
"sub-tabs"
>
<span
class=
"sub-tab active"
>
研发投入
</span>
<span
class=
"sub-tab"
>
专利布局
</span>
<span
class=
"sub-tab"
>
技术突破
</span>
<div
class=
"action-icons"
>
<img
src=
"../../assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"../../assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<!-- 研发投入图表区域 -->
<div
class=
"rnd-charts"
>
<div
class=
"chart-card"
>
<div
class=
"section-header"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
年度研发投入(单位:亿美元)
</h3>
</div>
<div
id=
"rndInvestmentChart"
class=
"chart-container"
></div>
</div>
<div
class=
"chart-card"
>
<div
class=
"section-header"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
专利技术分布
</h3>
</div>
<div
id=
"patentDistChart"
class=
"chart-container"
></div>
</div>
</div>
<!-- 研发核心人员 -->
<div
class=
"section"
>
<div
class=
"section-header"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
研发核心人员
</h3>
</div>
<div
class=
"personnel-grid"
>
<div
class=
"personnel-card"
v-for=
"(person, idx) in rndData.rndPersonnel"
:key=
"idx"
>
<div
class=
"personnel-card-header"
>
<img
:src=
"person.avatar"
alt=
"头像"
class=
"person-avatar"
>
<div
class=
"person-info"
>
<h4
class=
"person-name"
>
{{
person
.
name
}}
</h4>
<p
class=
"person-position"
>
{{
person
.
position
}}
</p>
</div>
</div>
<p
class=
"person-desc"
>
{{
person
.
desc
}}
</p>
</div>
</div>
</div>
<!-- 核心技术突破 -->
<div
class=
"section"
>
<div
class=
"section-header"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
核心技术突破
</h3>
</div>
<div
class=
"branches-grid"
>
<div
class=
"branch-item"
v-for=
"(tech, idx) in rndData.techBreakthrough"
:key=
"idx"
>
<span>
{{
tech
}}
</span>
<img
src=
"../../assets/icons/open.png"
alt=
"箭头"
class=
"branch-arrow"
>
</div>
</div>
</div>
</div>
<!-- 被制裁情况标签内容 -->
<div
v-if=
"activeTab === '被制裁情况'"
>
<div
class=
"sub-tabs"
>
<span
class=
"sub-tab active"
>
制裁概况
</span>
<div
class=
"action-icons"
>
<img
src=
"../../assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"../../assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<div
class=
"section"
style=
"padding: 20px;text-align: center;color: #86909c;"
>
被制裁情况模块待开发...
</div>
</div>
<!-- 供应链情况标签内容 -->
<div
v-if=
"activeTab === '供应链情况'"
>
<div
class=
"sub-tabs"
>
<span
class=
"sub-tab active"
>
供应链概况
</span>
<div
class=
"action-icons"
>
<img
src=
"../../assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"../../assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<div
class=
"section"
style=
"padding: 20px;text-align: center;color: #86909c;"
>
供应链情况模块待开发...
</div>
</div>
</div>
</div>
</div>
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
,
watch
}
from
'vue'
// 引入数据文件
import
data
from
'./data/huaweiData.json'
import
rndData
from
'./data/huaweiRndData.json'
// 引入抽离的图表组件
import
getRndInvestmentChart
from
'./charts/rndInvestmentChart.js'
import
getPatentDistChart
from
'./charts/patentDistChart.js'
import
initEchart
from
'./charts/chartInit.js'
// 标签列表和激活状态
const
tabList
=
ref
([
'基础信息'
,
'研发实力'
,
'被制裁情况'
,
'供应链情况'
])
const
activeTab
=
ref
(
'基础信息'
)
// 切换标签方法
const
switchTab
=
(
tab
)
=>
{
activeTab
.
value
=
tab
// 切换到研发实力时初始化图表
if
(
tab
===
'研发实力'
)
{
// 确保DOM渲染完成后初始化图表
setTimeout
(
initRndCharts
,
100
)
}
}
// 初始化研发相关图表
const
initRndCharts
=
()
=>
{
// 1. 初始化研发投入折线图
const
investmentOption
=
getRndInvestmentChart
(
rndData
.
rndInvestment
)
initEchart
(
'rndInvestmentChart'
,
investmentOption
)
// 2. 初始化专利分布饼图
const
patentOption
=
getPatentDistChart
(
rndData
.
patentDist
)
initEchart
(
'patentDistChart'
,
patentOption
)
}
// 监听标签切换
watch
(
activeTab
,
(
newVal
)
=>
{
if
(
newVal
===
'研发实力'
)
{
setTimeout
(
initRndCharts
,
100
)
}
})
// 页面挂载时初始化
onMounted
(()
=>
{
if
(
activeTab
.
value
===
'研发实力'
)
{
initRndCharts
()
}
})
</
script
>
<
style
scoped
>
/* 基础样式 */
.page-content
{
font-family
:
"Microsoft Yahei"
,
"PingFang SC"
,
sans-serif
;
background-color
:
#f5f7fa
;
min-height
:
100vh
;
}
/* 公司导航栏 */
.company-nav
{
height
:
124px
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
flex-start
;
padding
:
0
160px
;
box-shadow
:
0px
4px
4px
0px
rgba
(
129
,
128
,
128
,
0.25
);
background
:
rgba
(
255
,
255
,
255
,
1
);
}
.company-logo-title
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
padding
:
5px
;
}
.logo-img
{
width
:
60px
;
height
:
60px
;
object-fit
:
contain
;
}
.title-group
{
display
:
flex
;
flex-direction
:
column
;
}
.company-name
{
font-size
:
18px
;
color
:
#1d2129
;
margin
:
0
;
}
.company-english
{
font-size
:
12px
;
color
:
#86909c
;
margin
:
0
;
}
.main-tabs
{
height
:
48px
;
display
:
flex
;
flex-direction
:
row
;
justify-content
:
flex-start
;
align-items
:
flex-start
;
gap
:
32px
;
padding
:
0px
16px
0px
0px
;
width
:
100%
;
}
.tab
{
color
:
rgba
(
59
,
65
,
75
,
1
);
height
:
48px
;
display
:
flex
;
flex-direction
:
row
;
justify-content
:
center
;
align-items
:
center
;
box-sizing
:
border-box
;
border-bottom
:
0px
solid
rgba
(
5
,
95
,
194
,
1
);
margin
:
6px
30px
0
0
;
cursor
:
pointer
;
gap
:
8px
;
}
.tab-active
{
color
:
rgba
(
5
,
95
,
194
,
1
);
height
:
48px
;
display
:
flex
;
flex-direction
:
row
;
justify-content
:
center
;
align-items
:
center
;
box-sizing
:
border-box
;
border-bottom
:
2px
solid
rgba
(
5
,
95
,
194
,
1
);
margin
:
6px
30px
0
0
;
cursor
:
pointer
;
gap
:
8px
;
}
/* 主体内容区 */
.main-content
{
margin
:
16px
160px
;
width
:
calc
(
100%
-
320px
);
display
:
flex
;
gap
:
16px
;
}
/* 左侧信息栏 */
.left-sidebar
{
width
:
360px
;
background-color
:
#fff
;
border-radius
:
6px
;
padding
:
30px
;
box-shadow
:
0
1px
2px
rgba
(
0
,
0
,
0
,
0.05
);
}
.sidebar-logo
{
width
:
132px
;
height
:
124px
;
object-fit
:
contain
;
margin
:
60px
auto
0
;
display
:
block
;
}
.sidebar-company-name
{
text-align
:
center
;
margin
:
48px
0
20px
;
padding-bottom
:
15px
;
color
:
rgba
(
10
,
18
,
30
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
24px
;
font-weight
:
700
;
line-height
:
32px
;
letter-spacing
:
0px
;
border-bottom
:
1px
solid
#ebebeb
;
}
.contact-list
{
margin-bottom
:
20px
;
padding-bottom
:
15px
;
border-bottom
:
1px
solid
#ebebeb
;
}
.contact-item
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
font-size
:
16px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
margin-bottom
:
12px
;
font-weight
:
400
;
line-height
:
30px
;
}
.contact-icon
{
width
:
14px
;
height
:
14px
;
flex-shrink
:
0
;
}
.financial-list
{
padding-top
:
15px
;
}
.financial-item
{
text-align
:
center
;
padding
:
12px
0
;
border-bottom
:
1px
solid
#ebebeb
;
}
.financial-item
:last-child
{
border-bottom
:
none
;
}
.financial-value
{
font-size
:
20px
;
color
:
#1890ff
;
font-weight
:
600
;
margin
:
0
0
5px
;
}
.financial-label
{
font-size
:
12px
;
color
:
#86909c
;
margin
:
0
;
}
/* 右侧内容区 */
.right-content
{
width
:
100%
;
flex
:
1
;
background-color
:
#fff
;
border-radius
:
6px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
}
/* 子标签栏 */
.sub-tabs
{
height
:
56px
;
padding
:
12px
24px
;
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
border-bottom
:
1px
solid
#ebebeb
;
}
.sub-tab
{
width
:
80px
;
height
:
28px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-size
:
16px
;
font-weight
:
400
;
line-height
:
30px
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
59
,
65
,
75
,
1
);
border-radius
:
4px
;
background
:
rgba
(
246
,
250
,
255
,
1
);
cursor
:
pointer
;
}
.sub-tab.active
{
color
:
rgba
(
5
,
95
,
194
,
1
);
border
:
1px
solid
rgba
(
5
,
95
,
194
,
1
);
background
:
rgba
(
246
,
250
,
255
,
1
);
}
.action-icons
{
display
:
flex
;
gap
:
15px
;
margin-left
:
auto
;
}
.action-icon
{
width
:
28px
;
height
:
28px
;
cursor
:
pointer
;
}
/* 信息网格 */
.info-grid
{
display
:
flex
;
gap
:
16px
;
padding
:
24px
;
}
.info-card
{
flex
:
1
;
background-color
:
#f9fafb
;
border-radius
:
6px
;
padding
:
12px
16px
;
}
.section-title
{
font-size
:
16px
;
color
:
rgba
(
5
,
95
,
194
,
1
);
font-family
:
Microsoft
YaHei
;
font-weight
:
700
;
line-height
:
24px
;
letter-spacing
:
1px
;
margin
:
0
0
16px
0
;
}
.info-list
{
list-style
:
none
;
padding
:
0
;
margin
:
0
;
}
.info-list
li
{
font-size
:
16px
;
margin-bottom
:
12px
;
line-height
:
24px
;
display
:
flex
;
align-items
:
center
;
}
.li-icon
{
width
:
4px
;
height
:
4px
;
background
:
rgba
(
59
,
65
,
75
,
1
);
border-radius
:
50%
;
flex-shrink
:
0
;
}
.info-key
{
width
:
100px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-size
:
16px
;
font-weight
:
700
;
line-height
:
24px
;
letter-spacing
:
1px
;
text-align
:
left
;
margin-left
:
22px
;
}
.info-value
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
justify
;
flex
:
1
;
}
/* 通用区块样式 */
.section
{
margin
:
0
24px
24px
;
}
.section-header
{
display
:
flex
;
align-items
:
center
;
margin-bottom
:
16px
;
}
.section-icon
{
width
:
7px
;
height
:
18px
;
border-radius
:
0
4px
4px
0
;
background
:
rgba
(
5
,
95
,
194
,
1
);
margin-right
:
17px
;
}
/* 人员网格 */
.personnel-grid
{
display
:
grid
;
grid-template-columns
:
repeat
(
3
,
1
fr
);
gap
:
15px
;
}
.personnel-card
{
height
:
150px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
223
,
232
,
239
,
1
);
border-radius
:
4px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
}
.personnel-card-header
{
display
:
flex
;
height
:
78px
;
background
:
rgba
(
246
,
249
,
250
,
1
);
padding
:
11px
15px
;
}
.person-avatar
{
width
:
50px
;
height
:
50px
;
border-radius
:
50%
;
object-fit
:
cover
;
flex-shrink
:
0
;
}
.person-info
{
flex
:
1
;
margin
:
0
16px
;
}
.person-name
{
margin
:
0
;
color
:
rgba
(
10
,
18
,
30
,
1
);
font-size
:
18px
;
font-weight
:
700
;
line-height
:
24px
;
}
.person-position
{
margin
:
0
;
color
:
rgba
(
10
,
18
,
30
,
1
);
font-size
:
14px
;
font-weight
:
400
;
line-height
:
24px
;
}
.person-desc
{
padding
:
16px
8px
;
margin
:
0
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
}
/* 分支机构/技术突破 */
.branches-grid
{
display
:
grid
;
grid-template-columns
:
repeat
(
3
,
1
fr
);
gap
:
0
10px
;
}
.branch-item
{
height
:
54px
;
display
:
flex
;
align-items
:
center
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-size
:
16px
;
font-weight
:
400
;
line-height
:
30px
;
cursor
:
pointer
;
padding
:
12px
16px
;
box-sizing
:
border-box
;
border-top
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
margin-bottom
:
-1px
;
border-radius
:
4px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
}
.branch-item
:hover
{
background-color
:
#f0f2f5
;
}
.branch-arrow
{
width
:
12px
;
height
:
12px
;
margin-left
:
auto
;
}
/* 研发图表样式 */
.rnd-charts
{
display
:
flex
;
gap
:
16px
;
padding
:
24px
;
flex-wrap
:
wrap
;
}
.chart-card
{
flex
:
1
;
min-width
:
400px
;
background
:
#f9fafb
;
border-radius
:
6px
;
padding
:
16px
;
}
.chart-container
{
width
:
100%
;
height
:
300px
;
margin-top
:
10px
;
}
/* 响应式适配 */
@media
(
max-width
:
1440px
)
{
.main-content
{
margin
:
16px
80px
;
width
:
calc
(
100%
-
160px
);
}
.company-nav
{
padding
:
0
80px
;
}
}
@media
(
max-width
:
1200px
)
{
.personnel-grid
{
grid-template-columns
:
repeat
(
2
,
1
fr
);
}
.branches-grid
{
grid-template-columns
:
repeat
(
2
,
1
fr
);
}
.chart-card
{
min-width
:
300px
;
}
}
@media
(
max-width
:
768px
)
{
.main-content
{
flex-direction
:
column
;
margin
:
16px
20px
;
width
:
calc
(
100%
-
40px
);
}
.left-sidebar
{
width
:
100%
;
}
.company-nav
{
padding
:
0
20px
;
height
:
auto
;
padding
:
16px
20px
;
}
.main-tabs
{
flex-wrap
:
wrap
;
height
:
auto
;
gap
:
16px
;
}
.info-grid
{
flex-direction
:
column
;
}
.personnel-grid
{
grid-template-columns
:
1
fr
;
}
.branches-grid
{
grid-template-columns
:
1
fr
;
}
.rnd-charts
{
flex-direction
:
column
;
}
.chart-card
{
min-width
:
100%
;
}
}
</
style
>
\ No newline at end of file
src/views/companyPages/component/Capability.vue
浏览文件 @
efda93be
...
...
@@ -2,7 +2,8 @@
<div
class=
"box-content"
>
<div
class=
"tab-box"
>
<div
v-for=
"(tab, index) in tabList"
:class=
"activeTab === tab ? 'tab-active' : 'tab'"
@
click=
"activeTab = tab"
>
<div
v-for=
"(tab, index) in tabList"
:class=
"activeTab === tab ? 'tab-active' : 'tab'"
@
click=
"changeTab(tab, index)"
>
{{
tab
}}
<div
class=
"arrow-active"
>
...
...
@@ -12,7 +13,7 @@
</div>
<!--/*头部总览 */-->
<div
class=
"total"
>
<div
v-for=
"(item) in totalData"
class=
"total-box"
>
<div
v-for=
"(item) in totalData
[activeIndex]
"
class=
"total-box"
>
<div
class=
"line"
>
</div>
...
...
@@ -36,15 +37,19 @@
<div
class=
"section-header"
style=
" margin-top: 24px;"
>
<div
style=
"display: flex;"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
年度研发投入对比
</h3>
<h3
class=
"section-title"
>
{{
activeTab
===
'研发投入'
?
'年度研发投入对比'
:
activeTab
===
'研究人员'
?
'研究人员数量增长趋势'
:
'专利地域分布'
}}
</h3>
</div>
<div
class=
"action-icons"
>
<img
src=
"@/assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"@/assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<div
id=
"chart1"
class=
"chart-box"
>
<div
id=
"chart1"
class=
"chart-box"
v-show=
"activeTab === '研发投入'"
>
</div>
<div
id=
"chart3"
class=
"chart-box"
v-show=
"activeTab === '研究人员'"
>
</div>
<div
id=
"chart5"
class=
"chart-box"
v-show=
"activeTab === '专利情况'"
>
</div>
<div
class=
"chart-text"
>
<img
src=
"@/assets/icons/model.png"
style=
"width: 19px;height: 20px;"
>
...
...
@@ -61,15 +66,19 @@
<div
class=
"section-header"
style=
" margin-top: 24px;"
>
<div
style=
"display: flex;"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
研发投入增长对比
</h3>
<h3
class=
"section-title"
>
{{
activeTab
===
'研发投入'
?
'研发投入增长对比'
:
activeTab
===
'研究人员'
?
'研究人员学历分布'
:
'专利技术领域分布'
}}
</h3>
</div>
<div
class=
"action-icons"
>
<img
src=
"@/assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"@/assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<div
id=
"chart2"
class=
"chart-box"
>
<div
id=
"chart2"
class=
"chart-box"
v-show=
"activeTab === '研发投入'"
>
</div>
<div
id=
"chart4"
class=
"chart-box"
v-show=
"activeTab === '研究人员'"
>
</div>
<div
id=
"chart6"
class=
"chart-box"
v-show=
"activeTab === '专利情况'"
>
</div>
<div
class=
"chart-text"
>
<img
src=
"@/assets/icons/model.png"
style=
"width: 19px;height: 20px;"
>
...
...
@@ -85,15 +94,17 @@
</div>
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
'vue'
import
{
ref
,
onMounted
,
nextTick
}
from
'vue'
import
getBarChart
from
"../js/barChart.js"
;
import
*
as
echarts
from
"echarts"
;
import
getDonutChart
from
'../js/donutChart.js'
;
import
getLineChart
from
"../js/lineChart.js"
;
import
getRadarChart
from
'../js/radarChart.js'
import
*
as
echarts
from
"echarts"
;
const
tabList
=
ref
([
'研发投入'
,
'研究人员'
,
'专利情况'
])
const
activeTab
=
ref
(
'研发投入'
)
const
totalData
=
ref
([
const
activeIndex
=
ref
(
0
)
const
totalData
=
ref
([
[
{
"label"
:
"累计研发投入"
,
"value"
:
9854
,
...
...
@@ -114,7 +125,17 @@ const totalData = ref([
"value"
:
"Top"
,
"unit"
:
""
}
])
],
[
{
label
:
'2025年拟招聘应届生'
,
value
:
11.4
,
unit
:
'万'
},
{
label
:
'研发人员占比'
,
value
:
55.4
,
unit
:
'%'
},
{
label
:
'全年计划培养实习生'
,
value
:
1
,
unit
:
'万+'
},
{
label
:
'研发人员总数'
,
value
:
5000
,
unit
:
'+'
}
],
[
{
label
:
'全球有效专利'
,
value
:
12
,
unit
:
'万+'
},
{
label
:
'PCT申请量排名'
,
value
:
'Top'
,
unit
:
'5'
},
{
label
:
'5G标准必要专利占比'
,
value
:
21.5
,
unit
:
'%'
},
{
label
:
'家族专利'
,
value
:
4500
,
unit
:
'+'
}
]])
//年度研发投入对比
const
chart1Data
=
ref
({
...
...
@@ -127,24 +148,91 @@ const chart2Data = {
dataY
:
[
1.2
,
1.5
,
1.4
,
1.8
,
1.3
,
1.5
,
1.6
,
1.4
]
};
const
chart3Data
=
ref
({
name
:
[
'2020'
,
'2021'
,
'2022'
,
'2023'
,
'2024'
,
'2025'
],
value
:
[
50
,
100
,
150
,
200
,
250
,
300
,
350
,
400
]
});
// 学历分布数据(对应图片)
const
chart4Data
=
ref
({
name
:
[
'博士'
,
'硕士'
,
'学士'
,
'其他'
],
value
:
[
28
,
36
,
22
,
8
],
})
// 学历分布数据(对应图片)
const
chart5Data
=
ref
({
name
:
[
'博士'
,
'硕士'
,
'学士'
,
'其他'
],
value
:
[
28
,
36
,
22
,
8
],
})
function
changeTab
(
tab
,
index
)
{
console
.
log
(
tab
,
activeTab
.
value
)
activeTab
.
value
=
tab
activeIndex
.
value
=
index
console
.
log
(
tab
,
activeTab
.
value
,
activeIndex
.
value
)
// 保证 DOM 更新完再画
nextTick
(()
=>
{
if
(
tab
===
'研发投入'
)
{
chart1
()
chart2
()
}
else
if
(
tab
===
'研究人员'
)
{
chart3
()
char4
()
}
if
(
tab
===
'专利情况'
)
{
char5
()
chart6
()
}
// 其它 tab 同理 …
})
}
// 绘制echarts图表
const
setChart
=
(
option
,
chartId
)
=>
{
let
chartDom
=
document
.
getElementById
(
chartId
);
console
.
log
(
chartDom
,
"chartDomchartDomchartDom"
);
chartDom
.
removeAttribute
(
"_echarts_instance_"
);
let
chart
=
echarts
.
init
(
chartDom
);
chart
.
setOption
(
option
);
return
chart
;
};
onMounted
(()
=>
{
function
chart1
()
{
let
char1
=
getBarChart
(
chart1Data
.
value
.
name
,
chart1Data
.
value
.
value
,
true
);
setChart
(
char1
,
"chart1"
);
}
function
chart2
()
{
let
chart2
=
getLineChart
(
chart2Data
.
dataX
,
chart2Data
.
dataY
);
setChart
(
chart2
,
"chart2"
);
// let char2 = radarChart();
// setChart(char2, "char2");
}
function
chart3
()
{
let
char3
=
getBarChart
(
chart3Data
.
value
.
name
,
chart3Data
.
value
.
value
,
true
);
setChart
(
char3
,
"chart3"
);
}
function
char4
()
{
console
.
log
(
chart4Data
.
value
)
let
char4
=
getDonutChart
(
chart4Data
.
value
.
name
,
chart4Data
.
value
.
value
,
true
);
setChart
(
char4
,
"chart4"
);
}
function
char5
()
{
console
.
log
(
chart5Data
.
value
)
let
char5
=
getDonutChart
(
chart5Data
.
value
.
name
,
chart5Data
.
value
.
value
,
true
);
setChart
(
char5
,
"chart5"
);
}
function
chart6
()
{
let
char6
=
getRadarChart
();
setChart
(
char6
,
"chart6"
);
}
onMounted
(()
=>
{
chart1
()
chart2
()
});
</
script
>
...
...
src/views/companyPages/component/researcher.vue
0 → 100644
浏览文件 @
efda93be
<
template
>
<div
class=
"box-content"
>
<div
class=
"tab-box"
>
<div
v-for=
"(tab, index) in tabList"
:class=
"activeTab === tab ? 'tab-active' : 'tab'"
@
click=
"activeTab = tab"
>
{{
tab
}}
<div
class=
"arrow-active"
>
</div>
</div>
</div>
<!--/*头部总览 */-->
<div
class=
"total"
>
<div
v-for=
"(item) in totalData"
class=
"total-box"
>
<div
class=
"line"
>
</div>
<div
class=
"total-label"
>
{{
item
.
label
}}
</div>
<div
class=
"total-content"
>
<div
class=
"total-value"
>
{{
item
.
value
}}
</div>
<div
class=
"total-unit"
>
{{
item
.
unit
}}
</div>
</div>
</div>
</div>
<!--/*图表 */-->
<div
class=
"chart"
>
<div
class=
"chart-content"
>
<div
class=
"section-header"
style=
" margin-top: 24px;"
>
<div
style=
"display: flex;"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
年度研发投入对比
</h3>
</div>
<div
class=
"action-icons"
>
<img
src=
"@/assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"@/assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<div
id=
"chart1"
class=
"chart-box"
>
</div>
<div
class=
"chart-text"
>
<img
src=
"@/assets/icons/model.png"
style=
"width: 19px;height: 20px;"
>
<div>
近五年来,华为的研发投入在绝对金额和投入强度上均持续攀升。尤其是在收入因外部制裁而经历波动时,研发投入依然保持强劲增长,使其投入强度达到了历史高位。
</div>
<div
class=
"arrow-2"
>
→
</div>
</div>
</div>
<div
class=
"chart-content"
>
<div
class=
"section-header"
style=
" margin-top: 24px;"
>
<div
style=
"display: flex;"
>
<div
class=
"section-icon"
></div>
<h3
class=
"section-title"
>
研发投入增长对比
</h3>
</div>
<div
class=
"action-icons"
>
<img
src=
"@/assets/icons/download.png"
alt=
"下载"
class=
"action-icon"
>
<img
src=
"@/assets/icons/shoucang.png"
alt=
"收藏"
class=
"action-icon"
>
</div>
</div>
<div
id=
"chart2"
class=
"chart-box"
>
</div>
<div
class=
"chart-text"
>
<img
src=
"@/assets/icons/model.png"
style=
"width: 19px;height: 20px;"
>
<div>
华为在巨大的外部压力下,研发投入不仅在绝对金额上持续增长,其占收入的比重更是大幅提升,特别是2021年后形成的“剪刀差”,体现了公司最高优先级的战略抉择。
</div>
<div
class=
"arrow-2"
>
→
</div>
</div>
</div>
</div>
</div>
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
'vue'
import
getBarChart
from
"../js/barChart.js"
;
import
*
as
echarts
from
"echarts"
;
import
getLineChart
from
"../js/lineChart.js"
;
const
tabList
=
ref
([
'研发投入'
,
'研究人员'
,
'专利情况'
])
const
activeTab
=
ref
(
'研发投入'
)
const
totalData
=
ref
([
{
"label"
:
"累计研发投入"
,
"value"
:
9854
,
"unit"
:
"亿元"
},
{
"label"
:
"年度研发投入"
,
"value"
:
2153.9
,
"unit"
:
"亿元"
},
{
"label"
:
"研发强度"
,
"value"
:
22.9
,
"unit"
:
"%"
},
{
"label"
:
"研发投入排名"
,
"value"
:
"Top"
,
"unit"
:
""
}
])
//年度研发投入对比
const
chart1Data
=
ref
({
name
:
[
'2020'
,
'2021'
,
'2022'
,
'2023'
,
'2024'
,
'2025'
],
value
:
[
50
,
100
,
150
,
200
,
250
,
300
,
350
,
400
]
});
//研发投入增长对比
const
chart2Data
=
{
dataX
:
[
"2025-01"
,
"2025-02"
,
"2025-03"
,
"2025-04"
,
"2025-05"
,
"2025-06"
,
"2025-07"
,
"2025-08"
],
dataY
:
[
1.2
,
1.5
,
1.4
,
1.8
,
1.3
,
1.5
,
1.6
,
1.4
]
};
// 绘制echarts图表
const
setChart
=
(
option
,
chartId
)
=>
{
let
chartDom
=
document
.
getElementById
(
chartId
);
console
.
log
(
chartDom
,
"chartDomchartDomchartDom"
);
chartDom
.
removeAttribute
(
"_echarts_instance_"
);
let
chart
=
echarts
.
init
(
chartDom
);
chart
.
setOption
(
option
);
return
chart
;
};
onMounted
(()
=>
{
let
char1
=
getBarChart
(
chart1Data
.
value
.
name
,
chart1Data
.
value
.
value
,
true
);
setChart
(
char1
,
"chart1"
);
let
chart2
=
getLineChart
(
chart2Data
.
dataX
,
chart2Data
.
dataY
);
setChart
(
chart2
,
"chart2"
);
// let char2 = radarChart();
// setChart(char2, "char2");
});
</
script
>
<
style
scoped
>
.box-content
{
width
:
100%
;
height
:
calc
(
100vh
-
220px
);
overflow
:
auto
;
}
.tab-box
{
/* 左侧导航 */
width
:
112px
;
height
:
128px
;
position
:
absolute
;
left
:
0
;
margin
:
20px
;
/* 自动布局 */
display
:
flex
;
flex-direction
:
column
;
justify-content
:
flex-start
;
align-items
:
center
;
gap
:
16
;
.tab
{
color
:
rgba
(
59
,
65
,
75
,
1
);
height
:
48px
;
display
:
flex
;
flex-direction
:
row
;
justify-content
:
center
;
align-items
:
center
;
box-sizing
:
border-box
;
border-bottom
:
0px
solid
rgba
(
5
,
95
,
194
,
1
);
margin
:
6px
30px
0
0
;
}
.tab-active
{
/* 容器 7 */
width
:
104px
;
height
:
32px
;
display
:
flex
;
align-items
:
center
;
box-sizing
:
border-box
;
border-bottom
:
2px
solid
rgba
(
5
,
95
,
194
,
1
);
margin
:
6px
30px
0
0
;
border-radius
:
16px
;
background
:
rgba
(
5
,
95
,
194
,
1
);
color
:
rgba
(
255
,
255
,
255
,
1
);
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
padding
:
4px
12px
;
}
.arrow-active
{
width
:
0
;
height
:
0
;
border-style
:
solid
;
border-width
:
4px
0
4px
6px
;
margin-left
:
5px
;
/* 上 右 下 左 */
border-color
:
transparent
transparent
transparent
#ffffff
;
/* 只给左边上色 */
/* background: rgba(255, 255, 255, 1); */
}
}
/*头部总览 */
.total
{
height
:
80px
;
display
:
flex
;
gap
:
16px
;
}
.total-box
{
border-radius
:
4px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
flex
:
1
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
.line
{
/* 矩形 214 */
width
:
4px
;
height
:
49px
;
background
:
rgba
(
5
,
95
,
194
,
1
);
}
.total-label
{
color
:
rgba
(
59
,
65
,
75
,
1
);
margin
:
0px
30px
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
24px
;
letter-spacing
:
1px
;
text-align
:
left
;
}
.total-content
{
display
:
flex
;
margin-right
:
35px
;
color
:
rgba
(
5
,
95
,
194
,
1
);
font-family
:
Microsoft
YaHei
;
letter-spacing
:
0px
;
text-align
:
right
;
.total-value
{
font-size
:
24px
;
font-weight
:
700
;
line-height
:
24px
;
}
.total-unit
{
font-size
:
16px
;
font-weight
:
500
;
line-height
:
16px
;
margin-top
:
8px
;
}
}
}
.chart
{
margin-top
:
16px
;
height
:
calc
(
100vh
-
320px
);
display
:
flex
;
gap
:
16px
;
.chart-content
{
border-radius
:
4px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
flex
:
1
;
justify-content
:
space-between
;
.section-header
{
display
:
flex
;
width
:
100%
;
justify-content
:
space-between
;
}
.section-icon
{
width
:
7px
;
height
:
18px
;
border-radius
:
0
4px
4px
0
;
background
:
rgba
(
5
,
95
,
194
,
1
);
margin-right
:
17px
;
}
.section-title
{
font-size
:
18px
;
color
:
#1d2129
;
margin
:
0
;
color
:
rgba
(
5
,
95
,
194
,
1
);
font-family
:
Microsoft
YaHei
;
font-weight
:
700
;
line-height
:
24px
;
letter-spacing
:
1px
;
text-align
:
left
;
}
}
.action-icons
{
display
:
flex
;
margin-left
:
auto
;
}
.action-icon
{
/* 收藏按钮 */
width
:
28px
;
height
:
28px
;
cursor
:
pointer
;
margin-right
:
12px
;
}
.chart-box
{
width
:
100%
;
height
:
calc
(
100%
-
130px
);
}
.chart-text
{
/* 大模型对话结果 */
height
:
52px
;
margin
:
12px
20px
;
/* 自动布局 */
display
:
flex
;
flex-direction
:
row
;
justify-content
:
center
;
align-items
:
center
;
gap
:
10
;
padding
:
0px
12px
0px
12px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
231
,
243
,
255
,
1
);
border-radius
:
4px
;
background
:
rgba
(
246
,
251
,
255
,
1
);
color
:
rgba
(
5
,
95
,
194
,
1
);
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
justify
;
gap
:
13px
;
}
.arrow-2
{
border-radius
:
50%
;
width
:
24px
;
height
:
24px
;
font-size
:
24px
;
background
:
rgba
(
231
,
243
,
255
,
1
);
}
}
</
style
>
\ No newline at end of file
src/views/companyPages/js/donutChart.js
0 → 100644
浏览文件 @
efda93be
// donutChart.js
import
*
as
echarts
from
'echarts'
;
/**
* 环形图( donut / pie )
* @param {Array<string>} nameList 名称数组
* @param {Array<number>} valueList 数值数组
* @param {boolean} isPercent 数值是否带 % 显示
* @returns {Object} echarts option
*/
const
getDonutChart
=
(
nameList
,
valueList
,
isPercent
=
false
)
=>
{
console
.
log
(
nameList
,
valueList
,
isPercent
=
false
)
// 渐变色可随主题扩展
const
colorList
=
[
'#87E8DE'
,
'#69B1FF'
,
'#FF7875'
,
'#B37FEB'
];
const
data
=
nameList
.
map
((
name
,
i
)
=>
({
name
,
value
:
valueList
[
i
]
}));
return
{
color
:
colorList
,
tooltip
:
{
trigger
:
'item'
,
formatter
:
'{a} <br/>{b} : {c}'
+
(
isPercent
?
'%'
:
''
)
+
' ({d}%)'
},
legend
:
{
orient
:
'vertical'
,
// left: 'center',
bottom
:
'bottom'
,
itemGap
:
16
,
textStyle
:
{
fontSize
:
14
,
color
:
'#666'
}
},
series
:
[
{
name
:
'统计'
,
type
:
'pie'
,
radius
:
[
'45%'
,
'70%'
],
// 内环 / 外环
center
:
[
'40%'
,
'50%'
],
avoidLabelOverlap
:
false
,
itemStyle
:
{
borderRadius
:
0
,
borderColor
:
'#fff'
,
borderWidth
:
2
},
label
:
{
show
:
false
,
position
:
'inside'
,
formatter
:
({
value
})
=>
value
+
(
isPercent
?
'%'
:
''
),
fontSize
:
14
,
color
:
'#fff'
},
emphasis
:
{
label
:
{
show
:
true
,
fontSize
:
16
,
fontWeight
:
'bold'
}
},
data
}
]
};
};
export
default
getDonutChart
;
\ No newline at end of file
src/views/companyPages/js/radarChart.js
0 → 100644
浏览文件 @
efda93be
import
*
as
echarts
from
"echarts"
;
const
getBarChart
=
(
nameList
,
valueList
,
isPer
)
=>
{
const
option
=
{
title
:
{
text
:
''
},
legend
:
{
icon
:
'circle'
,
orient
:
'horizontal'
,
// 横向
top
:
0
,
// 图上方
left
:
'center'
,
// 水平居中
textStyle
:
{
fontSize
:
14
// 字号,按需调整
},
grid
:
{
top
:
60
},
data
:
[
'美国'
,
'欧盟'
,
'英国'
,
'日本'
,
'韩国'
,
'加拿大'
]
},
radar
:
{
radius
:
'50%'
,
// 关键:缩小整个雷达
center
:
[
'50%'
,
'60%'
],
// 可选:再往下挪一点,避免图例挤在一起
indicator
:
[
{
name
:
'能源'
,
max
:
6500
},
{
name
:
'集成电路'
,
max
:
16000
},
{
name
:
'人工智能'
,
max
:
30000
},
{
name
:
'通信网络'
,
max
:
38000
},
{
name
:
'量子科技'
,
max
:
52000
},
{
name
:
'生物科技'
,
max
:
25000
}
],
axisName
:
{
formatter
:
'{value}'
,
color
:
'rgba(59, 65, 75, 1)'
,
fontSize
:
14
,
fontWeight
:
400
}
},
series
:
[
{
name
:
'Budget vs spending'
,
type
:
'radar'
,
symbol
:
'none'
,
data
:
[
{
value
:
[
4200
,
3000
,
20000
,
35000
,
50000
,
18000
],
name
:
'美国'
,
areaStyle
:
{
color
:
'rgba(10, 87, 166, 0.2)'
}
},
{
value
:
[
5000
,
14000
,
28000
,
26000
,
42000
,
21000
],
name
:
'欧盟'
,
areaStyle
:
{
color
:
'rgba(206, 79, 81, 0.2)'
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'英国'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'日本'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'韩国'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'加拿大'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
}
]
}
]
}
return
option
}
export
default
getBarChart
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论