1. 数据产品详情页
2. 数据资产化树状图
3. 数据运营页
This commit is contained in:
sichan 2025-02-03 14:51:07 +08:00
parent 125f97abb5
commit 987bef5737
10 changed files with 2373 additions and 1425 deletions

View File

@ -1,261 +0,0 @@
/* 基础变量定义 */
:root {
--bg-dark: #0F172A;
--card-bg: #1E293B;
--primary-blue: #3B82F6;
--primary-glow: rgba(59, 130, 246, 0.15);
--success-green: #10B981;
--warning-yellow: #F59E0B;
--danger-red: #EF4444;
--text-primary: #E2E8F0;
--text-secondary: #94A3B8;
--border-color: rgba(59, 130, 246, 0.2);
--grid-line: rgba(148, 163, 184, 0.1);
}
/* 全局样式 */
body {
background-color: var(--bg-dark);
color: var(--text-primary);
min-height: 100vh;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
/* 网格背景 */
.grid-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
linear-gradient(var(--grid-line) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
background-size: 50px 50px;
z-index: -1;
}
/* BI看板头部 */
.bi-header {
background: var(--bg-dark);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 1rem 1.5rem;
margin-bottom: 1.5rem;
}
.header-content {
max-width: 100%;
}
.bi-title {
font-size: 1.5rem;
font-weight: 600;
margin: 0;
background: linear-gradient(90deg, var(--primary-blue), #60A5FA);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.bi-meta {
margin-top: 0.5rem;
font-size: 0.85rem;
color: var(--text-secondary);
}
.bi-meta span {
margin-right: 1.5rem;
display: inline-flex;
align-items: center;
}
.bi-meta i {
margin-right: 0.5rem;
color: var(--primary-blue);
}
/* 时间选择器样式 */
.time-selector .btn-group {
background: rgba(59, 130, 246, 0.1);
border-radius: 6px;
padding: 2px;
}
.time-selector .btn {
font-size: 0.85rem;
padding: 0.375rem 0.75rem;
border: none;
background: transparent;
color: var(--text-secondary);
}
.time-selector .btn.active {
background: var(--primary-blue);
color: white;
border-radius: 4px;
}
.time-selector .btn:hover:not(.active) {
background: rgba(59, 130, 246, 0.2);
color: var(--primary-blue);
}
/* 数据流转视图 */
.data-flow-container {
background: var(--card-bg);
border-radius: 16px;
border: 1px solid var(--border-color);
padding: 2rem;
position: relative;
backdrop-filter: blur(10px);
}
/* 数据节点 */
.data-node {
background: rgba(30, 41, 59, 0.8);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 1.5rem;
transition: all 0.3s ease;
position: relative;
}
.data-node::after {
content: '';
position: absolute;
inset: 0;
border-radius: 12px;
padding: 1px;
background: linear-gradient(45deg, var(--primary-blue), transparent);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
.data-node:hover {
transform: translateY(-3px);
box-shadow: 0 0 20px var(--primary-glow);
}
/* 数据流线条 */
.data-flow-line {
height: 2px;
background: linear-gradient(90deg,
transparent,
var(--primary-blue),
transparent
);
position: relative;
overflow: hidden;
}
.data-flow-line::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(90deg,
transparent,
var(--primary-blue),
transparent
);
animation: flowAnimation 2s infinite linear;
}
@keyframes flowAnimation {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* 数据指标卡片 */
.metric-card {
background: rgba(30, 41, 59, 0.8);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 1.5rem;
position: relative;
overflow: hidden;
}
.metric-value {
font-size: 2rem;
font-weight: 700;
color: var(--primary-blue);
text-shadow: 0 0 10px var(--primary-glow);
}
.metric-label {
color: var(--text-secondary);
font-size: 0.9rem;
}
/* 图表容器 */
.chart-container {
background: rgba(30, 41, 59, 0.8);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 1.5rem;
height: 300px;
position: relative;
}
/* 数据表格 */
.data-table {
background: rgba(30, 41, 59, 0.8);
border-radius: 12px;
border: 1px solid var(--border-color);
}
.data-table th {
background: rgba(59, 130, 246, 0.1);
color: var(--text-primary);
font-weight: 500;
border-bottom: 1px solid var(--border-color);
}
.data-table td {
color: var(--text-secondary);
border-bottom: 1px solid var(--border-color);
}
/* 状态标签 */
.status-badge {
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.85rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.status-active {
background: rgba(16, 185, 129, 0.1);
color: var(--success-green);
}
.status-warning {
background: rgba(245, 158, 11, 0.1);
color: var(--warning-yellow);
}
/* 动画效果 */
@keyframes pulse {
0% { box-shadow: 0 0 0 0 var(--primary-glow); }
70% { box-shadow: 0 0 0 10px transparent; }
100% { box-shadow: 0 0 0 0 transparent; }
}
/* 响应式调整 */
@media (max-width: 768px) {
.bi-title {
font-size: 2rem;
}
.data-flow-container {
padding: 1rem;
}
.chart-container {
height: 250px;
}
}

View File

@ -0,0 +1,472 @@
/* 基础重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 页面基础样式 */
body {
background-color: #f8fafc;
color: #1e293b;
line-height: 1.5;
}
/* 产品容器 */
.product-container {
max-width: 1200px;
margin: 0 auto;
padding: 0;
position: relative;
z-index: 1;
}
/* 产品头部 */
.product-header {
background: linear-gradient(135deg, #7c3aed 0%, #4f46e5 100%);
color: white;
padding: 3rem 0;
position: relative;
margin-bottom: 2rem;
}
.product-header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('../../../images/pattern.png') repeat;
opacity: 0.1;
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
position: relative;
}
.product-badges {
margin-bottom: 1rem;
}
.badge {
display: inline-block;
padding: 0.35rem 0.75rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 500;
margin-right: 0.5rem;
}
.badge.primary {
background-color: rgba(255, 255, 255, 0.2);
}
.badge.warning {
background-color: rgba(251, 191, 36, 0.2);
color: #fbbf24;
}
.product-header h1 {
font-size: 2.5rem;
margin-bottom: 1.5rem;
line-height: 1.2;
font-weight: 600;
}
.product-meta {
display: flex;
gap: 2rem;
flex-wrap: wrap;
}
.meta-item {
display: flex;
align-items: center;
gap: 0.75rem;
}
.meta-item i {
font-size: 1.5rem;
opacity: 0.8;
}
/* 主要内容区域 */
.product-content {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 2rem;
padding: 0 2rem;
margin-bottom: 3rem;
}
/* 左侧内容 */
.content-main {
display: flex;
flex-direction: column;
gap: 2rem;
}
.product-section {
background: white;
border-radius: 12px;
padding: 2rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.product-section h2 {
font-size: 1.5rem;
color: #1e293b;
margin-bottom: 1.5rem;
font-weight: 600;
}
.section-content {
color: #475569;
}
/* 特性网格 */
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-top: 1.5rem;
}
.feature-item {
display: flex;
align-items: center;
gap: 1rem;
background: #f8fafc;
padding: 1rem;
border-radius: 8px;
}
.feature-item i {
color: #7c3aed;
font-size: 1.25rem;
flex-shrink: 0;
}
/* 数据特征 */
.data-specs {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
}
.spec-group h3 {
font-size: 1.1rem;
color: #1e293b;
margin-bottom: 1rem;
font-weight: 600;
}
.spec-group ul {
list-style: none;
padding: 0;
}
.spec-group li {
margin-bottom: 0.75rem;
padding-left: 1.5rem;
position: relative;
}
.spec-group li:before {
content: "•";
color: #7c3aed;
position: absolute;
left: 0;
font-weight: bold;
}
/* 应用场景卡片 */
.scenario-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.scenario-card {
background: #f8fafc;
border-radius: 12px;
padding: 1.5rem;
text-align: center;
transition: transform 0.2s;
}
.scenario-card:hover {
transform: translateY(-2px);
}
.scenario-icon {
width: 48px;
height: 48px;
background: #7c3aed;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 1rem auto;
}
.scenario-icon i {
color: white;
font-size: 1.5rem;
}
.scenario-card h4 {
color: #1e293b;
margin-bottom: 0.75rem;
font-weight: 600;
}
.scenario-card p {
color: #64748b;
line-height: 1.6;
}
/* 代码示例 */
.code-sample {
background: #1e293b;
border-radius: 8px;
overflow: hidden;
}
.code-header {
background: #334155;
padding: 0.75rem 1rem;
display: flex;
justify-content: space-between;
align-items: center;
color: white;
}
.copy-btn {
background: none;
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 0.5rem 1rem;
border-radius: 4px;
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
transition: all 0.2s;
}
.copy-btn:hover {
background: rgba(255, 255, 255, 0.1);
}
.code-sample pre {
margin: 0;
padding: 1.5rem;
overflow-x: auto;
}
.code-sample code {
color: #e2e8f0;
font-family: 'Courier New', Courier, monospace;
line-height: 1.6;
}
/* 右侧购买信息 */
.content-sidebar {
position: sticky;
top: 2rem;
display: flex;
flex-direction: column;
gap: 2rem;
}
.purchase-card {
background: white;
border-radius: 12px;
padding: 2rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.price-header {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 1.5rem;
}
.price-header h3 {
font-size: 1.25rem;
color: #1e293b;
font-weight: 600;
}
.price-tag {
font-size: 2rem;
font-weight: 600;
color: #7c3aed;
}
.price-tag small {
font-size: 1rem;
color: #64748b;
}
.price-features {
margin-bottom: 2rem;
}
.price-features .feature-item {
margin-bottom: 1rem;
background: none;
padding: 0;
}
.price-features .feature-item i {
color: #34d399;
}
.purchase-btn {
width: 100%;
background: #7c3aed;
color: white;
border: none;
padding: 1rem;
border-radius: 8px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
margin-bottom: 1rem;
}
.purchase-btn:hover {
background: #6d28d9;
}
.contact-btn {
width: 100%;
background: none;
border: 1px solid #e2e8f0;
padding: 1rem;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
color: #64748b;
cursor: pointer;
transition: all 0.2s;
font-size: 1rem;
}
.contact-btn:hover {
background: #f8fafc;
border-color: #7c3aed;
color: #7c3aed;
}
/* 服务保障 */
.service-guarantees {
background: white;
border-radius: 12px;
padding: 2rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.guarantee-item {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem 0;
border-bottom: 1px solid #e2e8f0;
}
.guarantee-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.guarantee-item i {
font-size: 1.5rem;
color: #7c3aed;
flex-shrink: 0;
}
.guarantee-info h4 {
color: #1e293b;
margin-bottom: 0.25rem;
font-weight: 600;
}
.guarantee-info p {
color: #64748b;
font-size: 0.875rem;
margin: 0;
}
/* 响应式调整 */
@media (max-width: 1024px) {
.product-content {
grid-template-columns: 1fr;
gap: 2rem;
}
.content-sidebar {
position: static;
}
}
@media (max-width: 768px) {
.product-header {
padding: 2rem 0;
}
.product-header h1 {
font-size: 2rem;
}
.header-content,
.product-content {
padding: 0 1rem;
}
.product-meta {
gap: 1rem;
}
.product-section,
.purchase-card,
.service-guarantees {
padding: 1.5rem;
}
.feature-grid,
.data-specs,
.scenario-cards {
grid-template-columns: 1fr;
}
}
/* 滚动条美化 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}

View File

@ -0,0 +1,354 @@
.tech-tree-layout {
display: flex;
gap: 30px;
min-height: calc(100vh - 180px);
padding: 0 20px;
background: linear-gradient(135deg, #1a1f2c 0%, #2c3e50 100%);
}
.tech-tree-container {
flex: 1;
background: rgba(26, 32, 44, 0.9);
color: #fff;
padding: 30px;
margin: 20px 0;
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
min-width: 0;
}
/* 标题和控制按钮区域 */
.tech-tree-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.tech-tree-header h1 {
font-size: 24px;
font-weight: 600;
color: #fff;
margin: 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.tech-tree-controls {
display: flex;
gap: 12px;
}
.tech-tree-controls button {
background: rgba(52, 152, 219, 0.1);
color: #3498db;
border: 1px solid rgba(52, 152, 219, 0.3);
padding: 8px 16px;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
display: flex;
align-items: center;
gap: 6px;
}
.tech-tree-controls button:hover {
background: rgba(52, 152, 219, 0.2);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.2);
}
/* 树形图容器 */
.tech-tree {
width: 100%;
height: calc(100vh - 300px);
position: relative;
overflow: hidden;
}
.tech-tree svg {
width: 100%;
height: 100%;
}
/* 节点样式 */
.node {
cursor: pointer;
transition: all 0.3s ease;
}
.node rect {
fill: rgba(44, 62, 80, 0.9);
stroke: #3498db;
stroke-width: 2px;
rx: 8px;
ry: 8px;
transition: all 0.3s ease;
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.1));
}
.node:hover rect {
fill: rgba(52, 152, 219, 0.2);
stroke: #2ecc71;
transform: scale(1.05);
filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.2));
}
.node text {
fill: #fff;
font-size: 14px;
font-weight: 500;
pointer-events: none;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
/* 连接线样式 */
.link {
fill: none;
stroke: rgba(52, 152, 219, 0.4);
stroke-width: 2px;
transition: all 0.3s ease;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}
.node:hover + .link,
.link:hover {
stroke: rgba(46, 204, 113, 0.8);
stroke-width: 3px;
filter: drop-shadow(0 4px 8px rgba(46, 204, 113, 0.2));
}
/* 右侧详情面板 */
.detail-panel {
width: 400px;
margin: 20px 0;
background: rgba(26, 32, 44, 0.9);
border-radius: 16px;
color: #fff;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
flex-shrink: 0;
transition: all 0.3s ease;
}
.detail-content {
position: sticky;
top: 20px;
padding: 30px;
}
.detail-header {
padding-bottom: 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
margin-bottom: 20px;
}
.detail-header h2 {
margin: 0;
color: #3498db;
font-size: 1.5em;
font-weight: 600;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.detail-body {
overflow-y: auto;
max-height: calc(100vh - 300px);
padding-right: 10px;
}
.detail-body::-webkit-scrollbar {
width: 6px;
}
.detail-body::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.detail-body::-webkit-scrollbar-thumb {
background: rgba(52, 152, 219, 0.5);
border-radius: 3px;
}
.info-section {
margin-bottom: 25px;
animation: fadeIn 0.3s ease;
}
.info-section h3 {
color: #3498db;
margin-bottom: 15px;
font-size: 1.2em;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.info-section h3::before {
content: '';
display: inline-block;
width: 4px;
height: 16px;
background: #3498db;
border-radius: 2px;
}
.info-section p {
line-height: 1.6;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 15px;
}
.info-section ul {
list-style-type: none;
padding: 0;
}
.info-section li {
margin-bottom: 12px;
padding-left: 24px;
position: relative;
color: rgba(255, 255, 255, 0.9);
transition: all 0.3s ease;
}
.info-section li:before {
content: "•";
color: #3498db;
position: absolute;
left: 8px;
font-size: 1.2em;
}
.info-section li:hover {
transform: translateX(5px);
color: #fff;
}
/* 动画效果 */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 节点状态样式 */
.node.active rect {
fill: rgba(46, 204, 113, 0.2);
stroke: #2ecc71;
stroke-width: 3px;
filter: drop-shadow(0 8px 16px rgba(46, 204, 113, 0.3));
}
.node.completed rect {
stroke: #2ecc71;
}
.node.locked rect {
stroke: #e74c3c;
fill: rgba(231, 76, 60, 0.1);
}
/* 响应式布局 */
@media (max-width: 1200px) {
.tech-tree-layout {
flex-direction: column;
}
.detail-panel {
width: 100%;
}
}
/* 主内容区域 */
.main-content {
min-height: calc(100vh - 140px); /* 减去header和footer的高度 */
padding: 20px 0;
background: linear-gradient(135deg, #1a1f2c 0%, #2c3e50 100%);
}
/* 确保container样式正确 */
.container {
max-width: 1600px;
margin: 0 auto;
padding: 0 20px;
}
/* 提示框样式 */
.tooltip {
position: absolute;
background-color: rgba(44, 62, 80, 0.9);
color: #fff;
padding: 10px;
border-radius: 4px;
font-size: 14px;
pointer-events: none;
z-index: 1000;
}
/* 模态框样式 */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
z-index: 1000;
}
.modal-content {
position: relative;
background-color: #2c3e50;
margin: 5% auto;
padding: 0;
width: 70%;
max-width: 800px;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
color: #fff;
}
.modal-header {
padding: 20px;
border-bottom: 1px solid #34495e;
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-header h2 {
margin: 0;
color: #3498db;
}
.close {
color: #aaa;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
}
.close:hover {
color: #fff;
}
.modal-body {
padding: 20px;
max-height: 70vh;
overflow-y: auto;
}

View File

@ -137,4 +137,477 @@
.data-market .card .btn-outline-primary:hover {
color: #fff;
background-color: #0d6efd;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
.page-title {
font-size: 2.5rem;
color: #333;
margin-bottom: 2rem;
text-align: center;
border-bottom: 3px solid #007bff;
padding-bottom: 1rem;
}
section {
margin-bottom: 3rem;
}
section h2 {
color: #007bff;
font-size: 1.8rem;
margin-bottom: 1.5rem;
}
.content-box {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 2rem;
margin-bottom: 2rem;
}
.content-box h3 {
color: #2c3e50;
font-size: 1.4rem;
margin-bottom: 1rem;
border-bottom: 2px solid #eee;
padding-bottom: 0.5rem;
}
.content-box ul {
list-style-type: none;
padding-left: 0;
}
.content-box ul li {
margin-bottom: 0.5rem;
padding-left: 1.5rem;
position: relative;
}
.content-box ul li:before {
content: "•";
color: #007bff;
position: absolute;
left: 0;
}
.table-responsive {
overflow-x: auto;
margin: 1rem 0;
}
table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0;
}
table th,
table td {
padding: 0.75rem;
border: 1px solid #dee2e6;
text-align: left;
}
table th {
background-color: #f8f9fa;
font-weight: 600;
}
.profile-group,
.risk-group {
margin-bottom: 2rem;
}
.profile-group:last-child,
.risk-group:last-child {
margin-bottom: 0;
}
@media (max-width: 768px) {
.container {
padding: 1rem;
}
.page-title {
font-size: 2rem;
}
section h2 {
font-size: 1.5rem;
}
.content-box {
padding: 1rem;
}
}
/* 仪表盘容器 */
.dashboard-container {
padding: 2rem;
background-color: #f8fafc;
min-height: 100vh;
}
/* 顶部统计卡片 */
.stats-cards {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
margin-bottom: 2rem;
}
.stat-card {
background: white;
border-radius: 12px;
padding: 1.5rem;
display: flex;
align-items: center;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.stat-icon {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
}
.stat-icon i {
font-size: 1.5rem;
color: white;
}
.customer-icon {
background-color: #7c3aed;
}
.revenue-icon {
background-color: #60a5fa;
}
.conversion-icon {
background-color: #fbbf24;
}
.deals-icon {
background-color: #34d399;
}
.stat-info h3 {
font-size: 0.875rem;
color: #64748b;
margin-bottom: 0.5rem;
}
.stat-number {
font-size: 1.5rem;
font-weight: 600;
color: #1e293b;
margin-bottom: 0.25rem;
}
.stat-trend {
font-size: 0.875rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.stat-trend.positive {
color: #34d399;
}
.stat-trend.negative {
color: #ef4444;
}
.stat-trend small {
color: #64748b;
}
/* 主要内容区域 */
.dashboard-content {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 1.5rem;
height: calc(100vh - 200px);
overflow: auto;
}
.content-left, .content-right {
display: flex;
flex-direction: column;
gap: 1.5rem;
overflow-y: auto;
max-height: 100%;
}
/* 面板通用样式 */
.panel {
background: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
flex-shrink: 0;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.panel-header h2 {
font-size: 1.25rem;
color: #1e293b;
font-weight: 600;
}
/* 热门交易列表 */
.deals-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.deal-item {
display: flex;
align-items: center;
padding: 0.75rem;
border-radius: 8px;
background-color: #f8fafc;
}
.deal-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 1rem;
}
.deal-info {
flex: 1;
}
.deal-name {
font-weight: 500;
color: #1e293b;
}
.deal-email {
font-size: 0.875rem;
color: #64748b;
}
.deal-amount {
font-weight: 600;
color: #1e293b;
}
/* 图表控制按钮 */
.chart-controls {
display: flex;
gap: 0.5rem;
}
.control-btn {
padding: 0.5rem 1rem;
border: 1px solid #e2e8f0;
border-radius: 6px;
background: none;
color: #64748b;
cursor: pointer;
transition: all 0.2s;
}
.control-btn.active {
background-color: #7c3aed;
color: white;
border-color: #7c3aed;
}
/* 数据来源统计 */
.source-stats {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
margin-top: 1.5rem;
}
.stat-item {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.stat-label {
font-size: 0.875rem;
color: #64748b;
}
.stat-value {
font-size: 1.25rem;
font-weight: 600;
color: #1e293b;
}
/* 交易状态 */
.status-total {
font-size: 1.5rem;
font-weight: 600;
color: #1e293b;
display: flex;
align-items: baseline;
gap: 0.5rem;
}
.status-trend {
font-size: 0.875rem;
color: #34d399;
}
.status-list {
display: flex;
flex-direction: column;
gap: 1rem;
margin-top: 1.5rem;
}
.status-item {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.status-info {
display: flex;
align-items: center;
gap: 0.75rem;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.status-dot.success {
background-color: #34d399;
}
.status-dot.pending {
background-color: #fbbf24;
}
.status-dot.rejected {
background-color: #ef4444;
}
.status-dot.upcoming {
background-color: #60a5fa;
}
.status-name {
flex: 1;
color: #1e293b;
}
.status-count {
color: #64748b;
font-size: 0.875rem;
}
.status-bar {
height: 6px;
background-color: #f1f5f9;
border-radius: 3px;
overflow: hidden;
}
.bar-fill {
height: 100%;
border-radius: 3px;
transition: width 0.3s ease;
}
.bar-fill.success {
background-color: #34d399;
}
.bar-fill.pending {
background-color: #fbbf24;
}
.bar-fill.rejected {
background-color: #ef4444;
}
.bar-fill.upcoming {
background-color: #60a5fa;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.stats-cards {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.dashboard-container {
padding: 1rem;
}
.dashboard-content {
height: auto;
overflow: visible;
}
.content-left, .content-right {
overflow-y: visible;
max-height: none;
}
.revenue-chart, .source-distribution {
height: 300px;
}
.revenue-chart canvas {
height: 200px !important;
}
.source-distribution canvas {
height: 150px !important;
}
}
.revenue-chart {
height: 400px;
position: relative;
}
.revenue-chart canvas {
height: 300px !important;
}
.source-distribution {
height: 400px;
position: relative;
}
.source-distribution canvas {
height: 200px !important;
margin-bottom: 1rem;
}

View File

@ -0,0 +1,136 @@
{
"id": "credit-score-001",
"type": "financial",
"sensitivity": "level-2",
"badges": [
{
"text": "金融数据",
"type": "primary"
},
{
"text": "二级敏感",
"type": "warning"
}
],
"title": "企业信用评分数据包",
"meta": [
{
"icon": "bi-clock",
"text": "每日更新"
},
{
"icon": "bi-database",
"text": "100TB+"
},
{
"icon": "bi-building",
"text": "覆盖100万+企业"
},
{
"icon": "bi-star-fill",
"text": "4.8分 (2,389条评价)"
}
],
"overview": {
"description": "本数据包提供全面的企业信用评分数据,包含企业基础信息、经营状况、信用记录等多维度数据。适用于金融风控、企业征信、商业决策等场景。",
"features": [
"实时更新的企业信用评分",
"多维度风险指标",
"历史变更记录",
"关联企业图谱"
]
},
"specifications": [
{
"title": "数据维度",
"items": [
"企业基础信息",
"经营指标评分",
"信用历史记录",
"风险预警指标",
"行业对标分析"
]
},
{
"title": "更新频率",
"items": [
"基础数据:每日更新",
"评分数据:实时更新",
"关联数据:每周更新",
"行业数据:每月更新"
]
},
{
"title": "数据格式",
"items": [
"JSON/XML格式",
"REST API接口",
"批量数据文件",
"实时推送服务"
]
}
],
"scenarios": [
{
"icon": "bi-shield-check",
"title": "信贷风控",
"description": "用于银行、金融机构的企业贷款风险评估,提供全面的信用风险分析。"
},
{
"icon": "bi-graph-up",
"title": "商业决策",
"description": "帮助企业评估合作伙伴的信用状况,优化商业决策流程。"
},
{
"icon": "bi-search",
"title": "市场调研",
"description": "为市场研究提供数据支持,分析行业趋势和企业发展状况。"
}
],
"sample": {
"enterprise_id": "E100000123",
"basic_info": {
"name": "示例科技有限公司",
"registration_date": "2015-06-15",
"registered_capital": 10000000
},
"credit_score": {
"overall_score": 85,
"financial_score": 88,
"operation_score": 82,
"risk_level": "低风险"
},
"risk_indicators": {
"payment_delay_rate": 0.02,
"legal_risk_count": 0,
"market_risk_level": "A"
}
},
"pricing": {
"amount": 2000,
"unit": "月",
"features": [
"不限API调用次数",
"7*24小时技术支持",
"数据更新实时推送",
"专属数据分析报告"
]
},
"guarantees": [
{
"icon": "bi-shield-check",
"title": "数据安全",
"description": "数据加密传输与存储"
},
{
"icon": "bi-patch-check",
"title": "准确性保证",
"description": "数据准确率99.9%"
},
{
"icon": "bi-clock-history",
"title": "更新及时",
"description": "每日更新数据"
}
]
}

View File

@ -0,0 +1,313 @@
// 定义数据资产路径树的数据结构
const treeData = {
name: "数据资产入表",
children: [
{
name: "数据采集",
description: "从各种来源收集原始数据",
children: [
{
name: "结构化数据",
description: "数据库、Excel等格式化数据",
children: [
{
name: "数据库抽取",
description: "使用ETL工具从数据库中抽取数据"
},
{
name: "文件导入",
description: "导入Excel、CSV等文件数据"
}
]
},
{
name: "非结构化数据",
description: "文档、图片、视频等非结构化数据",
children: [
{
name: "文本解析",
description: "解析文档、日志等文本数据"
},
{
name: "媒体处理",
description: "处理图片、视频等媒体数据"
}
]
}
]
},
{
name: "数据处理",
description: "对采集的数据进行清洗和转换",
children: [
{
name: "数据清洗",
description: "去除异常值和重复数据",
children: [
{
name: "质量检查",
description: "检查数据完整性和准确性"
},
{
name: "数据修复",
description: "修复和补充缺失数据"
}
]
},
{
name: "数据转换",
description: "转换数据格式和结构",
children: [
{
name: "格式标准化",
description: "统一数据格式和编码"
},
{
name: "结构转换",
description: "调整数据结构以适应目标系统"
}
]
}
]
},
{
name: "数据入表",
description: "将处理后的数据导入目标系统",
children: [
{
name: "数据映射",
description: "建立源数据和目标表的字段映射",
children: [
{
name: "字段匹配",
description: "确定源字段和目标字段的对应关系"
},
{
name: "转换规则",
description: "定义数据转换和计算规则"
}
]
},
{
name: "数据加载",
description: "将数据加载到目标表中",
children: [
{
name: "增量更新",
description: "只更新变化的数据"
},
{
name: "全量替换",
description: "完全替换目标表数据"
}
]
}
]
}
]
};
// 定义节点详细信息数据
const nodeDetails = {
"数据资产入表": {
description: "数据资产入表是将各类数据规范化并导入系统的完整流程",
steps: [
"制定数据采集计划",
"确定数据处理规则",
"设计数据存储结构",
"实施数据导入流程"
],
notes: [
"确保数据质量和完整性",
"注意数据安全和隐私保护",
"建立数据版本控制机制"
],
docs: [
"《数据资产管理规范》",
"《数据质量控制指南》",
"《数据安全管理制度》"
]
},
"数据采集": {
description: "从各种来源收集原始数据的过程",
steps: [
"识别数据源",
"建立采集通道",
"制定采集策略",
"执行数据采集"
],
notes: [
"确保数据源的可靠性",
"建立数据采集的监控机制",
"注意采集频率的控制"
],
docs: [
"《数据采集规范》",
"《数据源接入指南》"
]
},
"结构化数据": {
description: "处理来自数据库、Excel等格式化数据源的数据",
steps: [
"连接数据源",
"提取目标数据",
"验证数据格式",
"临时存储数据"
],
notes: [
"检查数据完整性",
"处理特殊字符",
"注意数据量大小"
],
docs: [
"《结构化数据处理指南》",
"《数据库连接配置手册》"
]
},
// ... 为每个节点添加详细信息
};
// 初始化D3树形图
document.addEventListener('DOMContentLoaded', () => {
// 设置SVG尺寸和边距
const margin = {top: 60, right: 120, bottom: 60, left: 120};
const width = 1200 - margin.left - margin.right;
const height = 800 - margin.top - margin.bottom;
// 创建SVG容器
const svg = d3.select('#techTree')
.append('svg')
.attr('width', '100%')
.attr('height', '100%')
.attr('viewBox', `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
// 创建树形布局
const tree = d3.tree()
.size([width, height])
.separation((a, b) => (a.parent == b.parent ? 2 : 3));
// 创建层级数据
const root = d3.hierarchy(treeData);
// 计算节点位置
tree(root);
// 创建连接线 - 使用贝塞尔曲线
const link = svg.selectAll('.link')
.data(root.links())
.enter()
.append('path')
.attr('class', 'link')
.attr('d', d3.linkHorizontal()
.x(d => d.y)
.y(d => d.x));
// 创建节点组
const node = svg.selectAll('.node')
.data(root.descendants())
.enter()
.append('g')
.attr('class', d => `node${d.children ? ' node--internal' : ' node--leaf'}`)
.attr('transform', d => `translate(${d.y},${d.x})`);
// 添加节点矩形
node.append('rect')
.attr('width', 160)
.attr('height', 60)
.attr('x', -80)
.attr('y', -30)
.attr('rx', 8)
.attr('ry', 8);
// 添加节点文本
node.append('text')
.attr('dy', '0.35em')
.attr('text-anchor', 'middle')
.each(function(d) {
const text = d3.select(this);
const words = d.data.name.split('');
const lineHeight = 1.1;
const maxLength = 8;
let line = [];
let tspans = [];
words.forEach((word, i) => {
line.push(word);
if (line.length === maxLength || i === words.length - 1) {
tspans.push(line.join(''));
line = [];
}
});
tspans.forEach((tspan, i) => {
text.append('tspan')
.attr('x', 0)
.attr('dy', i === 0 ? -0.5 * (tspans.length - 1) * lineHeight + 'em' : lineHeight + 'em')
.text(tspan);
});
});
// 获取详情面板元素
const detailTitle = document.getElementById('detailTitle');
const detailDescription = document.getElementById('detailDescription');
const detailSteps = document.getElementById('detailSteps');
const detailNotes = document.getElementById('detailNotes');
const detailDocs = document.getElementById('detailDocs');
// 修改节点点击事件
node.on('click', (event, d) => {
const details = nodeDetails[d.data.name] || {
description: d.data.description || "暂无详细描述",
steps: [],
notes: [],
docs: []
};
// 更新详情面板内容
detailTitle.textContent = d.data.name;
detailDescription.textContent = details.description;
// 更新步骤列表
detailSteps.innerHTML = details.steps.map(step => `<li>${step}</li>`).join('');
// 更新注意事项
detailNotes.innerHTML = details.notes.map(note => `<li>${note}</li>`).join('');
// 更新相关文档
detailDocs.innerHTML = details.docs.map(doc => `<li>${doc}</li>`).join('');
// 添加active类到当前节点
svg.selectAll('.node').classed('active', false);
d3.select(event.currentTarget).classed('active', true);
});
// 添加缩放功能
const zoom = d3.zoom()
.scaleExtent([0.5, 2])
.on('zoom', (event) => {
svg.attr('transform', event.transform);
});
// 初始化缩放
d3.select('#techTree svg')
.call(zoom)
.call(zoom.transform, d3.zoomIdentity.translate(margin.left, margin.top));
// 绑定按钮事件
document.getElementById('zoomIn').addEventListener('click', () => {
d3.select('#techTree svg').transition()
.call(zoom.scaleBy, 1.2);
});
document.getElementById('zoomOut').addEventListener('click', () => {
d3.select('#techTree svg').transition()
.call(zoom.scaleBy, 0.8);
});
document.getElementById('resetView').addEventListener('click', () => {
d3.select('#techTree svg').transition()
.call(zoom.transform, d3.zoomIdentity.translate(margin.left, margin.top));
});
});

View File

@ -0,0 +1,248 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>数据产品详情 - 可信数据空间</title>
<link rel="stylesheet" href="../../../assets/css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<link href="../../../vendor/bootstrap/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link href="../../../assets/css/pages/mods/mod4-ops/data-detail.css" rel="stylesheet">
</head>
<body class="d-flex flex-column min-vh-100">
<!-- 使用组件加载器加载header -->
<header></header>
<!-- 主要内容区域 -->
<div class="flex-grow-1">
<div class="product-container">
<!-- 产品头部信息 -->
<div class="product-header">
<div class="header-content">
<div class="product-badges" id="productBadges">
<!-- 徽章将通过JavaScript动态加载 -->
</div>
<h1 id="productTitle"><!-- 标题将通过JavaScript动态加载 --></h1>
<div class="product-meta" id="productMeta">
<!-- 元数据将通过JavaScript动态加载 -->
</div>
</div>
</div>
<!-- 主要内容区域 -->
<div class="product-content">
<!-- 左侧主要内容 -->
<div class="content-main">
<!-- 产品概述 -->
<section class="product-section">
<h2>产品概述</h2>
<div class="section-content">
<p id="productDescription"><!-- 描述将通过JavaScript动态加载 --></p>
<div class="feature-grid" id="featureGrid">
<!-- 特性将通过JavaScript动态加载 -->
</div>
</div>
</section>
<!-- 数据特征 -->
<section class="product-section">
<h2>数据特征</h2>
<div class="section-content">
<div class="data-specs" id="dataSpecs">
<!-- 数据特征将通过JavaScript动态加载 -->
</div>
</div>
</section>
<!-- 应用场景 -->
<section class="product-section">
<h2>应用场景</h2>
<div class="section-content">
<div class="scenario-cards" id="scenarioCards">
<!-- 应用场景将通过JavaScript动态加载 -->
</div>
</div>
</section>
<!-- 数据样例 -->
<section class="product-section">
<h2>数据样例</h2>
<div class="section-content">
<div class="code-sample">
<div class="code-header">
<span>JSON示例</span>
<button class="copy-btn">
<i class="bi bi-clipboard"></i>
复制代码
</button>
</div>
<pre><code id="sampleCode"><!-- 示例代码将通过JavaScript动态加载 --></code></pre>
</div>
</div>
</section>
</div>
<!-- 右侧购买信息 -->
<div class="content-sidebar">
<div class="purchase-card">
<div class="price-section">
<div class="price-header">
<h3>定价方案</h3>
<span class="price-tag" id="priceTag"><!-- 价格将通过JavaScript动态加载 --></span>
</div>
<div class="price-features" id="priceFeatures">
<!-- 价格特性将通过JavaScript动态加载 -->
</div>
</div>
<button class="purchase-btn">立即购买</button>
<button class="contact-btn">
<i class="bi bi-headset"></i>
联系客服
</button>
</div>
<!-- 服务保障 -->
<div class="service-guarantees" id="serviceGuarantees">
<!-- 服务保障将通过JavaScript动态加载 -->
</div>
</div>
</div>
</div>
</div>
<!-- 使用组件加载器加载footer -->
<footer></footer>
<script src="../../../vendor/bootstrap/bootstrap.bundle.min.js"></script>
<script src="../../../assets/js/main.js"></script>
<script>
document.addEventListener('DOMContentLoaded', async () => {
// 初始化组件
ComponentLoader.init();
// 获取产品ID从URL参数中获取
const urlParams = new URLSearchParams(window.location.search);
const productId = urlParams.get('id') || 'credit-score'; // 修改默认ID
try {
// 加载产品数据
const response = await fetch(`../../../assets/data/data-products/${productId}.json`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// 更新页面标题
document.title = `${data.title} - 可信数据空间`;
// 加载徽章
const badgesHtml = data.badges.map(badge => `
<span class="badge ${badge.type}">${badge.text}</span>
`).join('');
document.getElementById('productBadges').innerHTML = badgesHtml;
// 加载标题
document.getElementById('productTitle').textContent = data.title;
// 加载元数据
const metaHtml = data.meta.map(item => `
<div class="meta-item">
<i class="bi ${item.icon}"></i>
<span>${item.text}</span>
</div>
`).join('');
document.getElementById('productMeta').innerHTML = metaHtml;
// 加载产品描述
document.getElementById('productDescription').textContent = data.overview.description;
// 加载特性
const featuresHtml = data.overview.features.map(feature => `
<div class="feature-item">
<i class="bi bi-check-circle"></i>
<span>${feature}</span>
</div>
`).join('');
document.getElementById('featureGrid').innerHTML = featuresHtml;
// 加载数据特征
const specsHtml = data.specifications.map(spec => `
<div class="spec-group">
<h3>${spec.title}</h3>
<ul>
${spec.items.map(item => `<li>${item}</li>`).join('')}
</ul>
</div>
`).join('');
document.getElementById('dataSpecs').innerHTML = specsHtml;
// 加载应用场景
const scenariosHtml = data.scenarios.map(scenario => `
<div class="scenario-card">
<div class="scenario-icon">
<i class="bi ${scenario.icon}"></i>
</div>
<h4>${scenario.title}</h4>
<p>${scenario.description}</p>
</div>
`).join('');
document.getElementById('scenarioCards').innerHTML = scenariosHtml;
// 加载示例代码
document.getElementById('sampleCode').textContent = JSON.stringify(data.sample, null, 4);
// 加载价格
document.getElementById('priceTag').innerHTML = `¥${data.pricing.amount}<small>/${data.pricing.unit}</small>`;
// 加载价格特性
const priceFeaturesHtml = data.pricing.features.map(feature => `
<div class="feature-item">
<i class="bi bi-check2"></i>
<span>${feature}</span>
</div>
`).join('');
document.getElementById('priceFeatures').innerHTML = priceFeaturesHtml;
// 加载服务保障
const guaranteesHtml = data.guarantees.map(guarantee => `
<div class="guarantee-item">
<i class="bi ${guarantee.icon}"></i>
<div class="guarantee-info">
<h4>${guarantee.title}</h4>
<p>${guarantee.description}</p>
</div>
</div>
`).join('');
document.getElementById('serviceGuarantees').innerHTML = guaranteesHtml;
// 初始化代码复制功能
const copyBtn = document.querySelector('.copy-btn');
const codeElement = document.querySelector('.code-sample code');
copyBtn.addEventListener('click', () => {
const code = codeElement.textContent;
navigator.clipboard.writeText(code).then(() => {
copyBtn.innerHTML = '<i class="bi bi-check"></i> 已复制';
setTimeout(() => {
copyBtn.innerHTML = '<i class="bi bi-clipboard"></i> 复制代码';
}, 2000);
});
});
} catch (error) {
console.error('加载产品数据失败:', error);
// 显示错误提示
document.querySelector('.product-container').innerHTML = `
<div style="text-align: center; padding: 2rem; color: #ef4444;">
<i class="bi bi-exclamation-triangle" style="font-size: 3rem; margin-bottom: 1rem;"></i>
<h2>数据加载失败</h2>
<p>抱歉,无法加载产品数据。请稍后再试。</p>
<p style="color: #64748b; font-size: 0.875rem;">错误信息:${error.message}</p>
</div>
`;
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据资产入表路径图</title>
<!-- 基础样式 -->
<link rel="stylesheet" href="../../../assets/css/style.css">
<!-- 组件样式 -->
<link rel="stylesheet" href="../../../assets/css/components/header.css">
<link rel="stylesheet" href="../../../assets/css/components/footer.css">
<!-- 页面特定样式 -->
<link rel="stylesheet" href="../../../assets/css/pages/mods/mod4-ops/data-path-tree.css">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<!-- D3.js -->
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<!-- 引入header组件 -->
<div id="header"></div>
<!-- 主要内容 -->
<div class="main-content">
<div class="container">
<div class="tech-tree-layout">
<div class="tech-tree-container">
<div class="tech-tree-header">
<h1>数据资产入表路径图</h1>
<div class="tech-tree-controls">
<button id="zoomIn">放大</button>
<button id="zoomOut">缩小</button>
<button id="resetView">重置视图</button>
</div>
</div>
<div id="techTree" class="tech-tree"></div>
</div>
<!-- 右侧详情面板 -->
<div class="detail-panel">
<div class="detail-content">
<div class="detail-header">
<h2 id="detailTitle">选择一个节点查看详情</h2>
</div>
<div class="detail-body">
<div class="info-section">
<h3>描述</h3>
<p id="detailDescription">点击左侧科技树的节点,查看详细信息。</p>
</div>
<div class="info-section">
<h3>关键步骤</h3>
<ul id="detailSteps"></ul>
</div>
<div class="info-section">
<h3>注意事项</h3>
<ul id="detailNotes"></ul>
</div>
<div class="info-section">
<h3>相关文档</h3>
<ul id="detailDocs"></ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 引入footer组件 -->
<div id="footer"></div>
<!-- 组件加载脚本 -->
<script>
// 加载header组件
fetch('/components/header/header.html')
.then(response => response.text())
.then(data => {
document.getElementById('header').innerHTML = data;
})
.catch(error => console.error('Error loading header:', error));
// 加载footer组件
fetch('/components/footer/footer.html')
.then(response => response.text())
.then(data => {
document.getElementById('footer').innerHTML = data;
})
.catch(error => console.error('Error loading footer:', error));
</script>
<!-- 页面特定脚本 -->
<script src="../../../assets/js/pages/mods/mod4-ops/data-path-tree.js"></script>
</body>
</html>

View File

@ -0,0 +1,283 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据交易平台运营分析</title>
<link rel="stylesheet" href="../../../assets/css/style.css">
<link rel="stylesheet" href="../../../assets/css/pages/mods/mod4-ops/doc-menu.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div class="dashboard-container">
<!-- 顶部卡片区域 -->
<div class="stats-cards">
<div class="stat-card">
<div class="stat-icon customer-icon">
<i class="bi bi-people"></i>
</div>
<div class="stat-info">
<h3>总用户数</h3>
<div class="stat-number">102,890</div>
<div class="stat-trend positive">
<span>+40%</span>
<small>本月</small>
</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon revenue-icon">
<i class="bi bi-currency-dollar"></i>
</div>
<div class="stat-info">
<h3>总收入</h3>
<div class="stat-number">¥56,562</div>
<div class="stat-trend positive">
<span>+25%</span>
<small>本月</small>
</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon conversion-icon">
<i class="bi bi-graph-up"></i>
</div>
<div class="stat-info">
<h3>转化率</h3>
<div class="stat-number">12.08%</div>
<div class="stat-trend negative">
<span>-12%</span>
<small>本月</small>
</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon deals-icon">
<i class="bi bi-bag-check"></i>
</div>
<div class="stat-info">
<h3>总交易数</h3>
<div class="stat-number">2,543</div>
<div class="stat-trend positive">
<span>+19%</span>
<small>本月</small>
</div>
</div>
</div>
</div>
<!-- 主要内容区域 -->
<div class="dashboard-content">
<!-- 左侧内容 -->
<div class="content-left">
<!-- 热门交易 -->
<div class="panel top-deals">
<div class="panel-header">
<h2>热门交易</h2>
<button class="more-btn">查看全部</button>
</div>
<div class="deals-list">
<div class="deal-item">
<img src="../../../assets/images/avatar/1.jpg" alt="用户头像" class="deal-avatar">
<div class="deal-info">
<div class="deal-name">张三科技</div>
<div class="deal-email">zhangsan@example.com</div>
</div>
<div class="deal-amount">¥2,893</div>
</div>
<div class="deal-item">
<img src="../../../assets/images/avatar/2.jpg" alt="用户头像" class="deal-avatar">
<div class="deal-info">
<div class="deal-name">李四数据</div>
<div class="deal-email">lisi@example.com</div>
</div>
<div class="deal-amount">¥4,289</div>
</div>
<div class="deal-item">
<img src="../../../assets/images/avatar/3.jpg" alt="用户头像" class="deal-avatar">
<div class="deal-info">
<div class="deal-name">王五科技</div>
<div class="deal-email">wangwu@example.com</div>
</div>
<div class="deal-amount">¥6,347</div>
</div>
</div>
</div>
<!-- 收益分析图表 -->
<div class="panel revenue-chart">
<div class="panel-header">
<h2>收益分析</h2>
<div class="chart-controls">
<button class="control-btn active"></button>
<button class="control-btn"></button>
<button class="control-btn"></button>
<button class="control-btn"></button>
</div>
</div>
<canvas id="revenueChart"></canvas>
</div>
</div>
<!-- 右侧内容 -->
<div class="content-right">
<!-- 数据来源分布 -->
<div class="panel source-distribution">
<div class="panel-header">
<h2>数据来源分布</h2>
</div>
<canvas id="sourceChart"></canvas>
<div class="source-stats">
<div class="stat-item">
<span class="stat-label">金融机构</span>
<span class="stat-value">1,624</span>
</div>
<div class="stat-item">
<span class="stat-label">电商平台</span>
<span class="stat-value">1,267</span>
</div>
<div class="stat-item">
<span class="stat-label">政务部门</span>
<span class="stat-value">1,153</span>
</div>
<div class="stat-item">
<span class="stat-label">其他来源</span>
<span class="stat-value">679</span>
</div>
</div>
</div>
<!-- 交易状态 -->
<div class="panel deals-status">
<div class="panel-header">
<h2>交易状态</h2>
<div class="status-total">
4,289
<span class="status-trend">+102 较上周</span>
</div>
</div>
<div class="status-list">
<div class="status-item">
<div class="status-info">
<span class="status-dot success"></span>
<span class="status-name">成功交易</span>
<span class="status-count">987笔</span>
</div>
<div class="status-bar">
<div class="bar-fill success" style="width: 35%"></div>
</div>
</div>
<div class="status-item">
<div class="status-info">
<span class="status-dot pending"></span>
<span class="status-name">待处理</span>
<span class="status-count">1,073笔</span>
</div>
<div class="status-bar">
<div class="bar-fill pending" style="width: 28%"></div>
</div>
</div>
<div class="status-item">
<div class="status-info">
<span class="status-dot rejected"></span>
<span class="status-name">已拒绝</span>
<span class="status-count">1,674笔</span>
</div>
<div class="status-bar">
<div class="bar-fill rejected" style="width: 22%"></div>
</div>
</div>
<div class="status-item">
<div class="status-info">
<span class="status-dot upcoming"></span>
<span class="status-name">即将到期</span>
<span class="status-count">921笔</span>
</div>
<div class="status-bar">
<div class="bar-fill upcoming" style="width: 15%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// 收益分析图表
const revenueCtx = document.getElementById('revenueChart').getContext('2d');
new Chart(revenueCtx, {
type: 'line',
data: {
labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
datasets: [{
label: '收入',
data: [300, 450, 320, 480, 650, 580, 420, 380, 430, 550, 480, 520],
borderColor: '#7c3aed',
tension: 0.4,
fill: false
}, {
label: '支出',
data: [200, 350, 280, 400, 520, 450, 380, 320, 390, 450, 400, 440],
borderColor: '#60a5fa',
tension: 0.4,
fill: false
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
align: 'end'
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: '#f1f5f9'
}
},
x: {
grid: {
display: false
}
}
}
}
});
// 数据来源分布图表
const sourceCtx = document.getElementById('sourceChart').getContext('2d');
new Chart(sourceCtx, {
type: 'doughnut',
data: {
labels: ['金融机构', '电商平台', '政务部门', '其他来源'],
datasets: [{
data: [1624, 1267, 1153, 679],
backgroundColor: ['#7c3aed', '#60a5fa', '#fbbf24', '#34d399']
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
boxWidth: 12,
padding: 15
}
}
},
cutout: '70%'
}
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff