2026-03-10 17:49:53 +08:00
|
|
|
|
<!doctype html>
|
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8" />
|
2026-03-21 19:10:50 +08:00
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
2026-03-10 17:49:53 +08:00
|
|
|
|
<title>企业全景报告</title>
|
2026-03-21 19:10:50 +08:00
|
|
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
|
|
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
|
|
|
|
<link
|
|
|
|
|
|
href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;600;700&family=Noto+Serif+SC:wght@600;700&display=swap"
|
|
|
|
|
|
rel="stylesheet"
|
|
|
|
|
|
/>
|
2026-03-10 17:49:53 +08:00
|
|
|
|
<style>
|
|
|
|
|
|
:root {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
--blue-950: #172554;
|
|
|
|
|
|
--blue-900: #1e3a8a;
|
|
|
|
|
|
--blue-800: #1e40af;
|
|
|
|
|
|
--blue-700: #1d4ed8;
|
|
|
|
|
|
--blue-600: #2563eb;
|
|
|
|
|
|
--blue-500: #3b82f6;
|
|
|
|
|
|
--blue-200: #bfdbfe;
|
|
|
|
|
|
--blue-100: #dbeafe;
|
|
|
|
|
|
--blue-50: #eff6ff;
|
|
|
|
|
|
--red-800: #991b1b;
|
|
|
|
|
|
--red-700: #b91c1c;
|
|
|
|
|
|
--red-600: #dc2626;
|
|
|
|
|
|
--red-100: #fee2e2;
|
|
|
|
|
|
--red-50: #fef2f2;
|
|
|
|
|
|
--ink: #1e293b;
|
|
|
|
|
|
--ink-secondary: #334155;
|
|
|
|
|
|
--muted: #64748b;
|
|
|
|
|
|
--line: #e2e8f0;
|
|
|
|
|
|
--line-soft: #f1f5f9;
|
|
|
|
|
|
--surface: #ffffff;
|
|
|
|
|
|
--surface-raised: #f8fafc;
|
|
|
|
|
|
--brand: var(--blue-800);
|
|
|
|
|
|
--brand-mid: var(--blue-700);
|
|
|
|
|
|
--accent-blue: var(--blue-600);
|
|
|
|
|
|
--accent-red: var(--red-600);
|
|
|
|
|
|
--success: #0d9488;
|
|
|
|
|
|
--success-soft: rgba(13, 148, 136, 0.1);
|
|
|
|
|
|
--warn: #ca8a04;
|
|
|
|
|
|
--warn-soft: rgba(202, 138, 4, 0.12);
|
|
|
|
|
|
--danger: var(--red-700);
|
|
|
|
|
|
--danger-soft: rgba(220, 38, 38, 0.1);
|
|
|
|
|
|
--radius: 12px;
|
|
|
|
|
|
--radius-sm: 8px;
|
|
|
|
|
|
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
|
|
|
|
|
|
--shadow-md: 0 4px 24px rgba(15, 23, 42, 0.06);
|
|
|
|
|
|
--shadow-header: 0 1px 3px rgba(15, 23, 42, 0.05);
|
|
|
|
|
|
--table-border: #d1d5db;
|
|
|
|
|
|
--table-line: #e5e7eb;
|
|
|
|
|
|
--table-head: #f9fafb;
|
|
|
|
|
|
--header-tint-from: #e8f0ff;
|
|
|
|
|
|
--header-tint-mid: #f0f6ff;
|
|
|
|
|
|
--header-tint-to: #ffffff;
|
|
|
|
|
|
--header-border: rgba(30, 64, 175, 0.22);
|
|
|
|
|
|
--header-strip-start: #172554;
|
|
|
|
|
|
--header-strip-mid: #1d4ed8;
|
|
|
|
|
|
--header-strip-end: #b91c1c;
|
|
|
|
|
|
--font-sans:
|
|
|
|
|
|
"Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
|
|
|
|
--font-serif: "Noto Serif SC", "Songti SC", "SimSun", serif;
|
|
|
|
|
|
--primary: var(--blue-700);
|
|
|
|
|
|
--primary-dark: var(--blue-900);
|
|
|
|
|
|
--text: var(--ink);
|
|
|
|
|
|
--text-muted: var(--muted);
|
|
|
|
|
|
--border: var(--line);
|
|
|
|
|
|
--bg-card: var(--surface);
|
|
|
|
|
|
--bg-page: #ffffff;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
*,
|
|
|
|
|
|
*::before,
|
|
|
|
|
|
*::after {
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
body {
|
|
|
|
|
|
margin: 0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-family: var(--font-sans);
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
line-height: 1.65;
|
|
|
|
|
|
color: var(--ink);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
background: var(--bg-page);
|
2026-03-21 19:10:50 +08:00
|
|
|
|
min-height: 100vh;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.page {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
position: relative;
|
|
|
|
|
|
max-width: 1040px;
|
|
|
|
|
|
margin: 40px auto 56px;
|
|
|
|
|
|
padding: 0 0 44px;
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border-radius: var(--radius);
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
box-shadow: var(--shadow-md);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
scroll-behavior: smooth;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.page::before {
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
height: 2px;
|
|
|
|
|
|
background: var(--blue-800);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.page-inner {
|
|
|
|
|
|
padding: 0 40px 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.page {
|
|
|
|
|
|
margin: 16px;
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
}
|
|
|
|
|
|
.page-inner {
|
|
|
|
|
|
padding: 0 20px 8px;
|
|
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.top-nav {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.top-nav-title {
|
|
|
|
|
|
font-weight: 600;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--ink);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
.top-nav-links {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.top-nav-links a {
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
border-radius: 0;
|
|
|
|
|
|
background: transparent;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--blue-700);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
cursor: default;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
pointer-events: none;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
position: relative;
|
|
|
|
|
|
margin: 28px 0 20px;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
border-radius: var(--radius);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
background: linear-gradient(
|
2026-03-21 19:10:50 +08:00
|
|
|
|
165deg,
|
|
|
|
|
|
var(--header-tint-from) 0%,
|
|
|
|
|
|
var(--header-tint-mid) 38%,
|
|
|
|
|
|
var(--header-tint-to) 72%
|
2026-03-10 17:49:53 +08:00
|
|
|
|
);
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border: 1px solid var(--header-border);
|
|
|
|
|
|
box-shadow:
|
|
|
|
|
|
inset 3px 0 0 var(--blue-800),
|
|
|
|
|
|
0 1px 2px rgba(30, 58, 138, 0.06),
|
|
|
|
|
|
0 18px 50px -14px rgba(30, 64, 175, 0.14);
|
|
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header::before {
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
height: 4px;
|
|
|
|
|
|
background: linear-gradient(
|
|
|
|
|
|
90deg,
|
|
|
|
|
|
var(--header-strip-start) 0%,
|
|
|
|
|
|
var(--header-strip-mid) 62%,
|
|
|
|
|
|
var(--header-strip-end) 100%
|
|
|
|
|
|
);
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-inner {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
|
|
|
|
gap: 32px 40px;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 30px 32px 32px;
|
|
|
|
|
|
padding-top: 28px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.header-main {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 0;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
min-width: 0;
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.header-score {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
align-self: stretch;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-score-inner {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-width: 200px;
|
|
|
|
|
|
padding: 22px 24px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.92);
|
|
|
|
|
|
border: 1px solid rgba(37, 99, 235, 0.2);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
box-shadow:
|
|
|
|
|
|
0 1px 0 rgba(255, 255, 255, 0.85) inset,
|
|
|
|
|
|
0 10px 28px -12px rgba(30, 64, 175, 0.2);
|
|
|
|
|
|
border-top: 3px solid var(--blue-700);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.header-inner {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
gap: 24px;
|
|
|
|
|
|
padding: 24px 20px 28px;
|
|
|
|
|
|
padding-top: 22px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-score {
|
|
|
|
|
|
justify-content: stretch;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-score-inner {
|
|
|
|
|
|
max-width: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-main h1.report-title {
|
|
|
|
|
|
margin: 0 0 14px;
|
|
|
|
|
|
font-family: var(--font-serif);
|
|
|
|
|
|
font-size: clamp(1.5rem, 4vw, 2rem);
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
letter-spacing: 0.02em;
|
|
|
|
|
|
color: var(--blue-950);
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.header-main .subtitle {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: var(--ink-secondary);
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
line-height: 1.55;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.header-main .subtitle + .subtitle {
|
2026-03-10 17:49:53 +08:00
|
|
|
|
margin-top: 8px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
color: var(--muted);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.header-meta-line {
|
|
|
|
|
|
margin-top: 16px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-size: 12px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
letter-spacing: 0.03em;
|
|
|
|
|
|
color: var(--muted);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.header-tags {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 8px;
|
2026-03-10 19:12:35 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.tag {
|
2026-03-10 19:12:35 +08:00
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 5px 10px;
|
|
|
|
|
|
border-radius: 6px;
|
2026-03-10 19:12:35 +08:00
|
|
|
|
font-size: 12px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
letter-spacing: 0.01em;
|
|
|
|
|
|
background: var(--surface-raised);
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
color: var(--ink-secondary);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header .tag {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.75);
|
|
|
|
|
|
border: 1px solid rgba(37, 99, 235, 0.22);
|
|
|
|
|
|
color: var(--blue-900);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-score .score {
|
|
|
|
|
|
font-family: var(--font-serif);
|
|
|
|
|
|
font-size: 2.35rem;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: var(--blue-900);
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
letter-spacing: 0.02em;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-score .label {
|
|
|
|
|
|
margin-top: 14px;
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
letter-spacing: 0.08em;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
2026-03-10 19:12:35 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.header-score .pill {
|
|
|
|
|
|
border-width: 1px;
|
|
|
|
|
|
margin-top: 0;
|
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
|
display: inline-flex;
|
2026-03-10 19:12:35 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.header-score .pill.low {
|
|
|
|
|
|
background: var(--success-soft);
|
|
|
|
|
|
color: var(--success);
|
|
|
|
|
|
border-color: rgba(13, 148, 136, 0.35);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-score .pill.mid {
|
|
|
|
|
|
background: var(--warn-soft);
|
|
|
|
|
|
color: var(--warn);
|
|
|
|
|
|
border-color: rgba(202, 138, 4, 0.35);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-score .pill.high {
|
|
|
|
|
|
background: var(--danger-soft);
|
|
|
|
|
|
color: var(--red-700);
|
|
|
|
|
|
border-color: rgba(220, 38, 38, 0.4);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.print-btn {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-actions-fixed {
|
|
|
|
|
|
position: fixed;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
top: 24px;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
right: 24px;
|
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-fixed-btn {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
gap: 8px;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
padding: 10px 18px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
color: var(--ink-secondary);
|
|
|
|
|
|
font-family: var(--font-sans);
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
letter-spacing: 0.04em;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
cursor: pointer;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
box-shadow: var(--shadow-sm);
|
2026-03-11 14:13:57 +08:00
|
|
|
|
transition:
|
2026-03-21 19:10:50 +08:00
|
|
|
|
transform 0.2s ease,
|
|
|
|
|
|
box-shadow 0.2s ease,
|
|
|
|
|
|
background 0.2s ease,
|
|
|
|
|
|
color 0.2s ease,
|
|
|
|
|
|
border-color 0.2s ease;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-fixed-btn:hover {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--blue-800);
|
2026-03-11 14:13:57 +08:00
|
|
|
|
color: #fff;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border-color: var(--blue-800);
|
|
|
|
|
|
box-shadow: var(--shadow-sm);
|
|
|
|
|
|
transform: none;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-fixed-btn:disabled {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
opacity: 0.55;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
cursor: not-allowed;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
transform: none;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-loading-overlay {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
inset: 0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: rgba(255, 255, 255, 0.72);
|
|
|
|
|
|
backdrop-filter: blur(6px);
|
2026-03-11 14:13:57 +08:00
|
|
|
|
z-index: 2000;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-loading-overlay[aria-hidden="true"] {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-loading-content {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
padding: 36px 44px;
|
|
|
|
|
|
border-radius: var(--radius);
|
2026-03-11 14:13:57 +08:00
|
|
|
|
text-align: center;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
box-shadow: var(--shadow-md);
|
2026-03-11 14:13:57 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-loading-spinner {
|
|
|
|
|
|
width: 44px;
|
|
|
|
|
|
height: 44px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border: 2px solid var(--line);
|
|
|
|
|
|
border-top-color: var(--blue-800);
|
2026-03-11 14:13:57 +08:00
|
|
|
|
border-radius: 50%;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
margin: 0 auto 18px;
|
|
|
|
|
|
animation: pdf-spin 0.8s linear infinite;
|
2026-03-11 14:13:57 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-loading-content p {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 15px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: var(--ink-secondary);
|
2026-03-11 14:13:57 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-11 14:13:57 +08:00
|
|
|
|
@keyframes pdf-spin {
|
|
|
|
|
|
to {
|
|
|
|
|
|
transform: rotate(360deg);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
|
|
|
|
|
|
.report-sections {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
margin-top: 36px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 22px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.section-card {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
scroll-margin-top: 24px;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
box-shadow: var(--shadow-sm);
|
|
|
|
|
|
overflow: hidden;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.section-card h2 {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 14px 24px 14px 20px;
|
|
|
|
|
|
font-size: 0.9375rem;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
letter-spacing: 0.04em;
|
|
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
background: var(--table-head);
|
|
|
|
|
|
border-bottom: 1px solid var(--table-border);
|
|
|
|
|
|
border-left: 3px solid var(--blue-800);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.section-card .section-body {
|
|
|
|
|
|
padding: 24px 28px 28px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.section-body h3,
|
|
|
|
|
|
.section-card .section-body h3 {
|
|
|
|
|
|
margin: 24px 0 12px;
|
|
|
|
|
|
font-size: 0.9375rem;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: var(--ink-secondary);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-body h3:first-child,
|
|
|
|
|
|
.section-card .section-body h3:first-of-type {
|
2026-03-10 17:49:53 +08:00
|
|
|
|
margin-top: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.report-subheading {
|
|
|
|
|
|
margin: 20px 0 10px !important;
|
|
|
|
|
|
font-size: 0.8125rem !important;
|
|
|
|
|
|
font-weight: 700 !important;
|
|
|
|
|
|
letter-spacing: 0.04em !important;
|
|
|
|
|
|
color: var(--ink-secondary) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.report-annual-card-title {
|
|
|
|
|
|
margin: 0 0 14px !important;
|
|
|
|
|
|
font-family: var(--font-sans);
|
|
|
|
|
|
font-size: 1.0625rem !important;
|
|
|
|
|
|
font-weight: 700 !important;
|
|
|
|
|
|
color: var(--ink) !important;
|
|
|
|
|
|
padding-bottom: 10px;
|
|
|
|
|
|
border-bottom: 1px solid var(--table-border);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.report-annual-shell {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
padding: 20px 22px 20px;
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
border-top: none;
|
|
|
|
|
|
border-left: 3px solid var(--blue-800);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.report-annual-shell:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
|
|
|
|
|
|
.kv-table {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
border-collapse: collapse;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border-spacing: 0;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-size: 13px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
line-height: 1.55;
|
|
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-table th,
|
|
|
|
|
|
.kv-table td {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 10px 14px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
vertical-align: top;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border-bottom: 1px solid var(--table-line);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
.kv-table tr:last-child th,
|
|
|
|
|
|
.kv-table tr:last-child td {
|
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.kv-table tbody tr:nth-child(even) {
|
|
|
|
|
|
background: #fafafa;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.kv-table tbody tr:nth-child(odd) {
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-table th {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
width: 148px;
|
|
|
|
|
|
max-width: 40%;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 12.5px;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
background: var(--table-head);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
text-align: left;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border-right: 1px solid var(--table-line);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-table td {
|
|
|
|
|
|
word-break: break-word;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
font-weight: 400;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.kv-grid {
|
|
|
|
|
|
--cols: 3;
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(var(--cols), 1fr);
|
2026-03-21 19:10:50 +08:00
|
|
|
|
gap: 0;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-size: 13px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
line-height: 1.55;
|
|
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
@media (max-width: 900px) {
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-grid {
|
|
|
|
|
|
--cols: 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.kv-grid {
|
|
|
|
|
|
--cols: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-grid .kv-pair {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
gap: 4px 8px;
|
|
|
|
|
|
padding: 10px 14px;
|
|
|
|
|
|
border-bottom: 1px solid var(--table-line);
|
|
|
|
|
|
border-right: 1px solid var(--table-line);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
align-items: baseline;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.kv-grid .kv-pair:nth-child(even) {
|
|
|
|
|
|
background: #fafafa;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-grid .kv-pair .k {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 12px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-grid .kv-pair .k::after {
|
|
|
|
|
|
content: ":";
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.kv-grid .kv-pair .v {
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
min-width: 0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
font-weight: 400;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-list {
|
|
|
|
|
|
list-style: none;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
margin: 0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
overflow: hidden;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.item-list li {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
|
border-bottom: 1px solid var(--table-line);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-size: 13px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
line-height: 1.55;
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-list li:nth-child(even) {
|
|
|
|
|
|
background: #fafafa;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.item-list li:last-child {
|
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.item-list li .item-title {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: var(--ink);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
margin-bottom: 4px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-size: 13px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.item-list li .item-meta {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
font-size: 12.5px;
|
|
|
|
|
|
line-height: 1.55;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.item-block {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--surface-raised);
|
|
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
border-left: 3px solid var(--blue-800);
|
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
|
margin-bottom: 10px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-size: 13px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
line-height: 1.55;
|
|
|
|
|
|
color: var(--ink-secondary);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.item-block .item-kv span.k {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
margin-right: 6px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 12px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-hint {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--muted);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-size: 13px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 18px 16px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
background: var(--surface-raised);
|
|
|
|
|
|
border: 1px dashed var(--line);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.count-hint {
|
|
|
|
|
|
font-size: 12px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
letter-spacing: 0.02em;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.cell-object .cell-kv-line {
|
|
|
|
|
|
margin: 6px 0;
|
|
|
|
|
|
line-height: 1.55;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cell-object .cell-kv-line:first-child {
|
|
|
|
|
|
margin-top: 0;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.cell-object .cell-k {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
min-width: 11em;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
font-size: 12.5px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
vertical-align: top;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cell-object .cell-k::after {
|
|
|
|
|
|
content: ":";
|
|
|
|
|
|
}
|
|
|
|
|
|
.cell-object .cell-v {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cell-object .cell-object {
|
|
|
|
|
|
margin-top: 6px;
|
|
|
|
|
|
margin-left: 4px;
|
|
|
|
|
|
padding-left: 10px;
|
|
|
|
|
|
border-left: 2px solid var(--table-line);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.pill {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 3px 8px;
|
|
|
|
|
|
border-radius: 4px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-size: 11px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
letter-spacing: 0.02em;
|
|
|
|
|
|
margin-left: 8px;
|
|
|
|
|
|
vertical-align: middle;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.pill.low {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--success-soft);
|
|
|
|
|
|
color: var(--success);
|
|
|
|
|
|
border: 1px solid rgba(13, 148, 136, 0.28);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.pill.mid {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--warn-soft);
|
|
|
|
|
|
color: var(--warn);
|
|
|
|
|
|
border: 1px solid rgba(202, 138, 4, 0.3);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.pill.high {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--danger-soft);
|
|
|
|
|
|
color: var(--red-700);
|
|
|
|
|
|
border: 1px solid rgba(220, 38, 38, 0.35);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.risk-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 11px 0;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
border-bottom: 1px solid var(--line-soft);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.risk-row .ok {
|
|
|
|
|
|
color: var(--success);
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 700;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.risk-row .bad {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--red-600);
|
|
|
|
|
|
font-weight: 700;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.risk-points-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
2026-03-21 19:10:50 +08:00
|
|
|
|
gap: 12px 16px;
|
|
|
|
|
|
margin-top: 10px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.risk-points-grid {
|
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.risk-point {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 10px 14px;
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
|
border-left: 3px solid var(--line);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.risk-point-name {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
font-weight: 500;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.risk-status-ok {
|
|
|
|
|
|
color: var(--success);
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
font-size: 12px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.risk-status-bad {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--red-600);
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
font-size: 12px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.raw-section summary {
|
|
|
|
|
|
cursor: pointer;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 12px 16px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
font-weight: 600;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: var(--ink-secondary);
|
|
|
|
|
|
background: var(--table-head);
|
|
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-radius: var(--radius-sm);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.raw-section pre {
|
|
|
|
|
|
font-size: 11px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
font-family:
|
|
|
|
|
|
ui-monospace, "Cascadia Code", "SF Mono", Consolas,
|
|
|
|
|
|
monospace;
|
|
|
|
|
|
background: #1e293b;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
color: #e2e8f0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 16px;
|
|
|
|
|
|
border-radius: 0 0 var(--radius-sm) var(--radius-sm);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
overflow: auto;
|
|
|
|
|
|
max-height: 320px;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
margin: 0;
|
|
|
|
|
|
border: 1px solid var(--table-border);
|
|
|
|
|
|
border-top: none;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
@media (max-width: 768px) {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.section-card .section-body {
|
|
|
|
|
|
padding: 18px 16px 20px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.section-card h2 {
|
|
|
|
|
|
padding: 12px 16px 12px 14px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
@media print {
|
|
|
|
|
|
body {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: #fff !important;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
margin: 0;
|
|
|
|
|
|
-webkit-print-color-adjust: exact;
|
|
|
|
|
|
print-color-adjust: exact;
|
|
|
|
|
|
}
|
|
|
|
|
|
.page {
|
|
|
|
|
|
max-width: none;
|
|
|
|
|
|
margin: 0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 0;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
border-radius: 0;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.page::before {
|
|
|
|
|
|
height: 2px;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.page-inner {
|
|
|
|
|
|
padding: 0 12mm;
|
|
|
|
|
|
}
|
|
|
|
|
|
.top-nav {
|
2026-03-10 19:12:35 +08:00
|
|
|
|
display: none !important;
|
|
|
|
|
|
}
|
2026-03-11 14:13:57 +08:00
|
|
|
|
.pdf-actions-fixed,
|
|
|
|
|
|
.pdf-loading-overlay {
|
|
|
|
|
|
display: none !important;
|
|
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.header {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: linear-gradient(
|
|
|
|
|
|
180deg,
|
|
|
|
|
|
#e8f0ff 0%,
|
|
|
|
|
|
#f8fafc 45%,
|
|
|
|
|
|
#ffffff 100%
|
|
|
|
|
|
) !important;
|
|
|
|
|
|
color: var(--ink) !important;
|
|
|
|
|
|
box-shadow: none !important;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-left: 3px solid var(--blue-800);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
border-radius: 0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-inner {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
padding: 20px 0 16px;
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header::before {
|
|
|
|
|
|
background: linear-gradient(
|
|
|
|
|
|
90deg,
|
|
|
|
|
|
var(--header-strip-start) 0%,
|
|
|
|
|
|
var(--header-strip-mid) 62%,
|
|
|
|
|
|
var(--header-strip-end) 100%
|
|
|
|
|
|
);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
2026-03-11 19:19:18 +08:00
|
|
|
|
.header-main {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-score-inner {
|
|
|
|
|
|
border-top-width: 3px;
|
|
|
|
|
|
border-top-color: var(--blue-700);
|
|
|
|
|
|
border-color: rgba(37, 99, 235, 0.2);
|
|
|
|
|
|
background: #fff !important;
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
max-width: 260px;
|
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
|
margin-right: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-main h1.report-title {
|
|
|
|
|
|
color: var(--blue-950) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-main .subtitle,
|
|
|
|
|
|
.header-main .subtitle + .subtitle {
|
|
|
|
|
|
color: var(--ink-secondary) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-meta-line {
|
|
|
|
|
|
color: var(--muted) !important;
|
2026-03-11 19:19:18 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.tag {
|
|
|
|
|
|
background: var(--surface-raised);
|
|
|
|
|
|
color: var(--ink-secondary);
|
|
|
|
|
|
border-color: var(--line);
|
2026-03-11 19:19:18 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.header .tag {
|
|
|
|
|
|
background: #fff !important;
|
|
|
|
|
|
color: var(--blue-900) !important;
|
|
|
|
|
|
border-color: rgba(37, 99, 235, 0.25) !important;
|
2026-03-11 19:19:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
.header-score {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: transparent !important;
|
|
|
|
|
|
border: none !important;
|
|
|
|
|
|
margin: 0 !important;
|
|
|
|
|
|
justify-content: center;
|
2026-03-11 19:10:55 +08:00
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
.header-score .score {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--blue-900) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-score .label {
|
|
|
|
|
|
color: var(--muted) !important;
|
2026-03-11 19:10:55 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
.header-main {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.header-score {
|
|
|
|
|
|
width: 100%;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
.section-card {
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
border-radius: 0;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
border: none;
|
|
|
|
|
|
border-bottom: 1px solid var(--line);
|
2026-03-11 17:23:09 +08:00
|
|
|
|
page-break-inside: auto;
|
|
|
|
|
|
break-inside: auto;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
padding: 0 !important;
|
2026-03-11 18:12:14 +08:00
|
|
|
|
margin-top: 6px !important;
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: #fff !important;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
.section-card h2 {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
background: var(--table-head) !important;
|
|
|
|
|
|
border-left-color: var(--blue-800);
|
|
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.section-card .section-body {
|
|
|
|
|
|
padding: 12px 0 16px !important;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
.item-list li {
|
2026-03-11 17:23:09 +08:00
|
|
|
|
page-break-inside: auto;
|
|
|
|
|
|
break-inside: auto;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
.raw-section pre {
|
|
|
|
|
|
max-height: none;
|
|
|
|
|
|
page-break-inside: avoid;
|
|
|
|
|
|
break-inside: avoid;
|
|
|
|
|
|
}
|
|
|
|
|
|
a {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
color: var(--ink);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<div class="page">
|
2026-03-21 19:10:50 +08:00
|
|
|
|
<div class="page-inner">
|
|
|
|
|
|
<!-- 隐藏的导航容器,仅用于脚本生成目录,页面不展示 -->
|
|
|
|
|
|
<nav class="top-nav">
|
|
|
|
|
|
<div id="navLinks"></div>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
<header class="header">
|
|
|
|
|
|
<div class="header-inner">
|
|
|
|
|
|
<div class="header-main">
|
|
|
|
|
|
<h1 class="report-title">企业全景报告</h1>
|
|
|
|
|
|
<div class="subtitle">
|
|
|
|
|
|
<span id="entName">企业名称</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="subtitle">
|
|
|
|
|
|
<span id="creditCodeLabel"
|
|
|
|
|
|
>统一社会信用代码:-</span
|
|
|
|
|
|
>
|
|
|
|
|
|
·
|
|
|
|
|
|
<span id="entStatusLabel">经营状态:-</span>
|
|
|
|
|
|
·
|
|
|
|
|
|
<span id="entTypeLabel">企业类型:-</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="header-tags" id="headerTags"></div>
|
|
|
|
|
|
<div class="header-meta-line" id="reportTimeLabel">
|
|
|
|
|
|
报告生成时间:-
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<aside class="header-score" aria-label="综合评分">
|
|
|
|
|
|
<div class="header-score-inner">
|
|
|
|
|
|
<div class="score" id="overallScore">--</div>
|
|
|
|
|
|
<div class="label">
|
|
|
|
|
|
综合评分
|
|
|
|
|
|
<span id="riskLevelPill" class="pill low"
|
|
|
|
|
|
>风险:-</span
|
|
|
|
|
|
>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</aside>
|
2026-03-10 17:49:53 +08:00
|
|
|
|
</div>
|
2026-03-21 19:10:50 +08:00
|
|
|
|
</header>
|
|
|
|
|
|
<main id="reportSections" class="report-sections"></main>
|
|
|
|
|
|
</div>
|
2026-03-10 17:49:53 +08:00
|
|
|
|
</div>
|
2026-03-11 14:13:57 +08:00
|
|
|
|
<!-- 固定悬浮的保存 PDF 按钮(在 .page 外,不会被截进 PDF) -->
|
|
|
|
|
|
<div class="pdf-actions-fixed">
|
2026-03-11 18:05:10 +08:00
|
|
|
|
<button id="btnSavePdf" class="pdf-fixed-btn" type="button">
|
|
|
|
|
|
保存为 PDF
|
|
|
|
|
|
</button>
|
2026-03-11 14:13:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 生成 PDF 时的加载浮层 -->
|
2026-03-11 18:05:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
id="pdfLoadingOverlay"
|
|
|
|
|
|
class="pdf-loading-overlay"
|
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
|
>
|
2026-03-11 14:13:57 +08:00
|
|
|
|
<div class="pdf-loading-content">
|
|
|
|
|
|
<div class="pdf-loading-spinner" aria-hidden="true"></div>
|
2026-03-21 19:10:50 +08:00
|
|
|
|
<p id="pdfLoadingMessage">正在准备 PDF,请稍候...</p>
|
2026-03-11 14:13:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-10 19:12:35 +08:00
|
|
|
|
<!-- 前端截图并生成 PDF 所需依赖 -->
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.1/dist/jspdf.umd.min.js"></script>
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
<script>
|
|
|
|
|
|
(function () {
|
|
|
|
|
|
// 后端通过模板引擎注入的企业报告数据(QYGLJ1U9 聚合结果)
|
|
|
|
|
|
// ReportJSON 为合法的 JSON 对象字面量
|
|
|
|
|
|
var reportData = {{ .ReportJSON }};
|
|
|
|
|
|
var sectionOrder = [
|
|
|
|
|
|
"riskOverview",
|
|
|
|
|
|
"basic",
|
|
|
|
|
|
"branches",
|
|
|
|
|
|
"shareholding",
|
|
|
|
|
|
"controller",
|
|
|
|
|
|
"beneficiaries",
|
|
|
|
|
|
"investments",
|
|
|
|
|
|
"guarantees",
|
|
|
|
|
|
"management",
|
|
|
|
|
|
"assets",
|
|
|
|
|
|
"licenses",
|
|
|
|
|
|
"activities",
|
|
|
|
|
|
"inspections",
|
|
|
|
|
|
"risks",
|
|
|
|
|
|
"timeline",
|
|
|
|
|
|
"listed",
|
2026-03-21 19:10:50 +08:00
|
|
|
|
"annualReports",
|
|
|
|
|
|
"taxViolations",
|
|
|
|
|
|
"ownTaxNotices",
|
2026-03-10 17:49:53 +08:00
|
|
|
|
];
|
|
|
|
|
|
var sectionTitles = {
|
|
|
|
|
|
riskOverview: "风险情况(综合分析)",
|
|
|
|
|
|
basic: "一、主体概览(企业基础信息)",
|
|
|
|
|
|
branches: "二、分支机构",
|
2026-03-21 19:10:50 +08:00
|
|
|
|
shareholding: "三、股权与控制(持股结构)",
|
2026-03-10 17:49:53 +08:00
|
|
|
|
controller: "四、实际控制人",
|
|
|
|
|
|
beneficiaries: "五、最终受益人",
|
|
|
|
|
|
investments: "六、对外投资",
|
2026-03-21 19:10:50 +08:00
|
|
|
|
guarantees: "七、对外担保(披露摘要)",
|
|
|
|
|
|
management: "八、人员与组织(高管与任职)",
|
|
|
|
|
|
assets: "九、资产与经营(财务摘要)",
|
2026-03-10 17:49:53 +08:00
|
|
|
|
licenses: "十、行政许可与资质",
|
2026-03-21 19:10:50 +08:00
|
|
|
|
activities: "十一、经营活动(招投标)",
|
2026-03-10 17:49:53 +08:00
|
|
|
|
inspections: "十二、抽查检查",
|
|
|
|
|
|
risks: "十三、风险与合规",
|
|
|
|
|
|
timeline: "十四、发展时间线",
|
|
|
|
|
|
listed: "十五、上市信息",
|
2026-03-21 19:10:50 +08:00
|
|
|
|
annualReports: "十六、企业年报(公示)",
|
|
|
|
|
|
taxViolations: "十七、税收违法",
|
|
|
|
|
|
ownTaxNotices: "十八、欠税公告",
|
2026-03-10 17:49:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
// 保持所有板块单列纵向排布
|
|
|
|
|
|
var keyLabels = {
|
|
|
|
|
|
entName: "企业名称",
|
|
|
|
|
|
creditCode: "统一社会信用代码",
|
|
|
|
|
|
regNo: "注册号",
|
|
|
|
|
|
orgCode: "组织机构代码",
|
|
|
|
|
|
entType: "企业类型",
|
|
|
|
|
|
entTypeCode: "企业类型编码",
|
|
|
|
|
|
entityTypeCode: "实体类型编码",
|
|
|
|
|
|
establishDate: "成立日期",
|
|
|
|
|
|
registeredCapital: "注册资本",
|
|
|
|
|
|
regCap: "注册资本",
|
|
|
|
|
|
regCapCurrency: "注册资本币种",
|
|
|
|
|
|
regCapCurrencyCode: "注册资本币种代码",
|
|
|
|
|
|
regOrg: "登记机关",
|
|
|
|
|
|
regOrgCode: "注册地址行政编号",
|
|
|
|
|
|
regProvince: "所在省份",
|
|
|
|
|
|
provinceCode: "所在省份编码",
|
|
|
|
|
|
regCity: "所在城市",
|
|
|
|
|
|
regCityCode: "所在城市编码",
|
|
|
|
|
|
regDistrict: "所在区/县",
|
|
|
|
|
|
districtCode: "所在区/县编码",
|
|
|
|
|
|
address: "住址",
|
|
|
|
|
|
postalCode: "邮编",
|
|
|
|
|
|
legalRepresentative: "法定代表人",
|
|
|
|
|
|
compositionForm: "组成形式",
|
|
|
|
|
|
approvedBusinessItem: "许可经营项目",
|
|
|
|
|
|
status: "经营状态",
|
|
|
|
|
|
statusCode: "经营状态编码",
|
|
|
|
|
|
operationPeriodFrom: "经营期限自",
|
|
|
|
|
|
operationPeriodTo: "经营期限至",
|
|
|
|
|
|
approveDate: "核准日期",
|
|
|
|
|
|
cancelDate: "注销日期",
|
|
|
|
|
|
revokeDate: "吊销日期",
|
|
|
|
|
|
cancelReason: "注销原因",
|
|
|
|
|
|
revokeReason: "吊销原因",
|
|
|
|
|
|
oldNames: "曾用名",
|
|
|
|
|
|
businessScope: "经营业务范围",
|
|
|
|
|
|
lastAnnuReportYear: "最后年检年度",
|
|
|
|
|
|
name: "名称",
|
|
|
|
|
|
type: "类型",
|
|
|
|
|
|
percent: "比例",
|
|
|
|
|
|
reason: "判定依据",
|
|
|
|
|
|
source: "来源",
|
|
|
|
|
|
id: "标识",
|
|
|
|
|
|
path: "控制路径",
|
|
|
|
|
|
topHolderName: "第一大股东",
|
|
|
|
|
|
topHolderPercent: "第一大股东持股",
|
|
|
|
|
|
top5TotalPercent: "前五大合计",
|
|
|
|
|
|
shareholderCount: "股东总数",
|
|
|
|
|
|
currency: "币种",
|
|
|
|
|
|
hasEquityPledges: "存在股权出质",
|
|
|
|
|
|
riskLevel: "风险等级",
|
|
|
|
|
|
riskScore: "风险得分",
|
|
|
|
|
|
totalCount: "对外投资数量",
|
|
|
|
|
|
totalAmount: "投资总额(万)",
|
|
|
|
|
|
employeeCount: "从业人数",
|
|
|
|
|
|
femaleEmployeeCount: "女性从业人数",
|
|
|
|
|
|
yearReportId: "年报标识",
|
|
|
|
|
|
investor: "股东/投资人",
|
|
|
|
|
|
changeDate: "变更日期",
|
|
|
|
|
|
detailBefore: "变更前",
|
|
|
|
|
|
detailAfter: "变更后",
|
|
|
|
|
|
changeType: "变更类型",
|
|
|
|
|
|
updateDate: "变更日期",
|
|
|
|
|
|
updateContent: "变更内容",
|
|
|
|
|
|
date: "日期",
|
|
|
|
|
|
title: "标题",
|
|
|
|
|
|
overallScore: "总体评分",
|
|
|
|
|
|
tags: "标签",
|
|
|
|
|
|
isListed: "是否上市",
|
|
|
|
|
|
company: "上市公司信息",
|
|
|
|
|
|
stock: "股票信息",
|
2026-03-11 17:23:09 +08:00
|
|
|
|
// 上市公司信息字段
|
|
|
|
|
|
bizScope: "经营范围",
|
|
|
|
|
|
regAddr: "注册地址",
|
|
|
|
|
|
regCapital: "注册资本",
|
|
|
|
|
|
cur: "币种",
|
|
|
|
|
|
curName: "币种名称",
|
2026-03-21 19:10:50 +08:00
|
|
|
|
// 欠税公告(QYGL7D9A)
|
|
|
|
|
|
taxIdNumber: "纳税人识别号",
|
|
|
|
|
|
taxpayerName: "纳税人名称",
|
|
|
|
|
|
taxCategory: "欠税税种",
|
|
|
|
|
|
ownTaxBalance: "欠税余额",
|
|
|
|
|
|
ownTaxAmount: "欠税金额",
|
|
|
|
|
|
newOwnTaxBalance: "当前新发生欠税余额",
|
|
|
|
|
|
taxType: "税务类型",
|
|
|
|
|
|
publishDate: "发布时间",
|
|
|
|
|
|
department: "税务机关",
|
|
|
|
|
|
legalPersonName: "法人或负责人名称",
|
|
|
|
|
|
personIdNumber: "证件号码",
|
|
|
|
|
|
personIdName: "法人证件名称",
|
|
|
|
|
|
taxpayerType: "纳税人类型",
|
|
|
|
|
|
regType: "注册类型",
|
|
|
|
|
|
// 税收违法(QYGL8848)
|
|
|
|
|
|
entityName: "企业名称",
|
|
|
|
|
|
entityCategory: "企业类别",
|
|
|
|
|
|
taxpayerCode: "纳税人识别号",
|
|
|
|
|
|
agencyPersonInfo: "直接责任中介机构信息",
|
|
|
|
|
|
illegalStartDate: "违法事实开始时间",
|
|
|
|
|
|
illegalEndDate: "违法事实结束时间",
|
|
|
|
|
|
illegalTime: "违法行为发生时间",
|
|
|
|
|
|
publishDepartment: "信息公示税务机关",
|
|
|
|
|
|
checkDepartment: "案件检查机关",
|
|
|
|
|
|
belongDepartment: "涉案企业所属税务机关",
|
|
|
|
|
|
punishBasis: "处罚法律依据及具体内容",
|
|
|
|
|
|
illegalFact: "具体违法事实描述",
|
|
|
|
|
|
caseType: "案件性质",
|
|
|
|
|
|
police: "案件移送公安机关情况",
|
|
|
|
|
|
// 企业年报(QYGLDJ12)
|
|
|
|
|
|
registerCode: "注册号",
|
|
|
|
|
|
organizationCode: "组织机构代码",
|
|
|
|
|
|
creditCode: "统一社会信用代码",
|
|
|
|
|
|
entityStatus: "企业经营状态",
|
|
|
|
|
|
telephone: "企业联系电话",
|
|
|
|
|
|
postCode: "邮政编码",
|
|
|
|
|
|
entityBusinessScope: "主营业务范围",
|
|
|
|
|
|
employeeCnt: "从业人数",
|
|
|
|
|
|
entityPractitionerFemaleAmount: "其中女性从业人数",
|
|
|
|
|
|
actualEmployeeCnt: "实际员工数量",
|
|
|
|
|
|
mainBusinessIncome: "主营业务收入",
|
|
|
|
|
|
netProfit: "净利润",
|
|
|
|
|
|
totalSalesAmount: "销售总额",
|
|
|
|
|
|
totalNetProfit: "利润总额",
|
|
|
|
|
|
totalAssets: "资产总额",
|
|
|
|
|
|
totalLiabilities: "负债总额",
|
|
|
|
|
|
totalOwnerEquity: "所有者权益合计",
|
|
|
|
|
|
totalTaxAmount: "纳税总额",
|
|
|
|
|
|
reportYear: "年报年份",
|
|
|
|
|
|
reportName: "年报名称",
|
|
|
|
|
|
reportDate: "年报提交日期",
|
|
|
|
|
|
isWebsite: "是否有网站或网店",
|
|
|
|
|
|
isInvest: "是否有对外投资信息或购买股权",
|
|
|
|
|
|
isExternalGuarantee: "是否提供对外担保",
|
|
|
|
|
|
isEquityTransfer: "是否发生股东股权转让",
|
|
|
|
|
|
entityHoldingInfo: "企业控股情况信息",
|
|
|
|
|
|
guaranteeInfo: "对外担保信息摘要",
|
|
|
|
|
|
investInfo: "对外投资信息摘要",
|
|
|
|
|
|
actualRegistCapitalInfo: "注册资本实缴情况",
|
|
|
|
|
|
reportChangeInfo: "年报变更记录",
|
|
|
|
|
|
reportBranch: "分支机构信息",
|
|
|
|
|
|
reportContributeInfo: "出资情况信息",
|
|
|
|
|
|
reportRecordInfo: "备案信息",
|
|
|
|
|
|
websiteType: "网址类型",
|
|
|
|
|
|
websiteName: "网址名称",
|
|
|
|
|
|
websiteUrl: "网址",
|
|
|
|
|
|
stockName: "股东名称",
|
|
|
|
|
|
identifyType: "证件类型",
|
|
|
|
|
|
stockPercent: "持股比例",
|
|
|
|
|
|
realCapiItems: "实缴出资详情",
|
|
|
|
|
|
shouldCapiItems: "应缴出资详情",
|
|
|
|
|
|
totalRealCapi: "实缴出资总额",
|
|
|
|
|
|
totalShouldCapi: "应缴出资总额",
|
|
|
|
|
|
investName: "被投资企业名称",
|
|
|
|
|
|
investCapi: "投资金额",
|
|
|
|
|
|
investPercent: "投资比例",
|
|
|
|
|
|
entityId: "主体标识",
|
|
|
|
|
|
investRegNo: "注册号/统一社会信用代码",
|
|
|
|
|
|
seqNo: "序号",
|
|
|
|
|
|
socialSecurity: "社会保险(分项参保人数)",
|
|
|
|
|
|
endowmentInsuranceEmployeeCnt: "城镇职工基本养老保险参保人数",
|
|
|
|
|
|
unemploymentInsuranceEmployeeCnt: "失业保险参保人数",
|
|
|
|
|
|
medicalInsuranceEmployeeCnt: "职工基本医疗保险参保人数",
|
|
|
|
|
|
injuryInsuranceEmployeeCnt: "工伤保险参保人数",
|
|
|
|
|
|
maternityInsuranceEmployeeCnt: "生育保险参保人数",
|
|
|
|
|
|
creditor: "债权人",
|
|
|
|
|
|
debtor: "债务人",
|
|
|
|
|
|
amount: "主债权数额",
|
|
|
|
|
|
period: "履行债务的期限",
|
|
|
|
|
|
guaranteeTime: "保证期间",
|
|
|
|
|
|
guaranteeType: "保证方式",
|
|
|
|
|
|
guaranteeScope: "保证范围",
|
|
|
|
|
|
beforePercent: "变更前股权比例",
|
|
|
|
|
|
afterPercent: "变更后股权比例",
|
|
|
|
|
|
changeDate: "变更日期",
|
|
|
|
|
|
updateItem: "修改事项",
|
|
|
|
|
|
beforeUpdate: "修改前内容",
|
|
|
|
|
|
afterUpdate: "修改后内容",
|
|
|
|
|
|
investType: "出资方式",
|
|
|
|
|
|
realCapi: "实缴额",
|
|
|
|
|
|
realCapiDate: "实缴日期",
|
|
|
|
|
|
shoudCapi: "应缴额",
|
|
|
|
|
|
shouldCapiDate: "应缴日期",
|
2026-03-10 17:49:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function label(key) {
|
|
|
|
|
|
return keyLabels[key] || key;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function esc(s) {
|
|
|
|
|
|
if (s == null || s === "") return "-";
|
|
|
|
|
|
return String(s);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 职务字段格式化:部分数据源为英文/代码,如 EXEC、EXEC&&LR、HEXEC
|
|
|
|
|
|
function formatPosition(position) {
|
|
|
|
|
|
if (!position) return "";
|
|
|
|
|
|
var p = String(position).trim();
|
|
|
|
|
|
if (!p) return "";
|
|
|
|
|
|
// 将可能存在的转义形式统一为普通字符
|
|
|
|
|
|
p = p.replace(/\\u0026/gi, "&");
|
|
|
|
|
|
// 已知常见职务代码映射
|
|
|
|
|
|
var dict = {
|
|
|
|
|
|
EXEC: "高管",
|
|
|
|
|
|
LR: "法定代表人",
|
|
|
|
|
|
HEXEC: "执行合伙人",
|
|
|
|
|
|
};
|
|
|
|
|
|
// 拆分出可能的代码片段(用非字母字符作为分隔)
|
|
|
|
|
|
var parts = p
|
|
|
|
|
|
.split(/[^A-Z]/i)
|
|
|
|
|
|
.map(function (s) {
|
|
|
|
|
|
return s.trim();
|
|
|
|
|
|
})
|
|
|
|
|
|
.filter(Boolean);
|
|
|
|
|
|
if (parts.length === 0) {
|
|
|
|
|
|
return p;
|
|
|
|
|
|
}
|
|
|
|
|
|
var mapped = parts.map(function (code) {
|
|
|
|
|
|
return dict[code] || code;
|
|
|
|
|
|
});
|
|
|
|
|
|
// 多个角色用顿号连接,例如 "高管、法定代表人"
|
|
|
|
|
|
return mapped.join("、");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-21 19:10:50 +08:00
|
|
|
|
function renderScalarForCell(x) {
|
|
|
|
|
|
if (x == null || x === "") return "-";
|
|
|
|
|
|
if (typeof x === "boolean") return x ? "是" : "否";
|
|
|
|
|
|
if (typeof x === "number") return String(x);
|
|
|
|
|
|
if (typeof x === "string") return esc(x);
|
|
|
|
|
|
return esc(String(x));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderObjectAsLines(obj, depth) {
|
|
|
|
|
|
depth = depth || 0;
|
|
|
|
|
|
if (depth > 5) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
return esc(JSON.stringify(obj));
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
return "-";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (obj == null) return "-";
|
|
|
|
|
|
if (typeof obj !== "object")
|
|
|
|
|
|
return renderScalarForCell(obj);
|
|
|
|
|
|
if (Array.isArray(obj)) {
|
|
|
|
|
|
if (!obj.length) return "-";
|
|
|
|
|
|
var allScalar = obj.every(function (x) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
x == null ||
|
|
|
|
|
|
typeof x === "string" ||
|
|
|
|
|
|
typeof x === "number" ||
|
|
|
|
|
|
typeof x === "boolean"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
if (allScalar) {
|
|
|
|
|
|
return obj.map(renderScalarForCell).join("、");
|
|
|
|
|
|
}
|
|
|
|
|
|
return obj.length ? "共 " + obj.length + " 条" : "-";
|
|
|
|
|
|
}
|
|
|
|
|
|
var keys = Object.keys(obj);
|
|
|
|
|
|
if (!keys.length) return "-";
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='cell-object'>" +
|
|
|
|
|
|
keys
|
|
|
|
|
|
.map(function (k) {
|
|
|
|
|
|
var val = obj[k];
|
|
|
|
|
|
var inner;
|
|
|
|
|
|
if (
|
|
|
|
|
|
val != null &&
|
|
|
|
|
|
typeof val === "object" &&
|
|
|
|
|
|
!Array.isArray(val) &&
|
|
|
|
|
|
Object.keys(val).length > 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
inner = renderObjectAsLines(val, depth + 1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
inner = renderCell(val);
|
|
|
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='cell-kv-line'><span class='cell-k'>" +
|
|
|
|
|
|
esc(label(k)) +
|
|
|
|
|
|
"</span><span class='cell-v'>" +
|
|
|
|
|
|
inner +
|
|
|
|
|
|
"</span></div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
})
|
|
|
|
|
|
.join("") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
function renderCell(v) {
|
|
|
|
|
|
if (v == null || v === "") return "-";
|
|
|
|
|
|
if (typeof v === "boolean") return v ? "是" : "否";
|
2026-03-21 19:10:50 +08:00
|
|
|
|
if (typeof v === "number") return String(v);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
if (typeof v === "object") {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
if (Array.isArray(v)) {
|
|
|
|
|
|
if (!v.length) return "-";
|
|
|
|
|
|
var allScalar = v.every(function (x) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
x == null ||
|
|
|
|
|
|
typeof x === "string" ||
|
|
|
|
|
|
typeof x === "number" ||
|
|
|
|
|
|
typeof x === "boolean"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
if (allScalar) {
|
|
|
|
|
|
return v.map(renderScalarForCell).join("、");
|
|
|
|
|
|
}
|
|
|
|
|
|
return "共 " + v.length + " 条";
|
|
|
|
|
|
}
|
|
|
|
|
|
return renderObjectAsLines(v, 0);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
return esc(v);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 传入 keys 时:渲染所有键,无值显示 -;未传 keys 时:按对象自身键渲染
|
|
|
|
|
|
function kvTable(obj, keys) {
|
|
|
|
|
|
if (!obj || typeof obj !== "object")
|
|
|
|
|
|
return "<p class='empty-hint'>暂无数据</p>";
|
|
|
|
|
|
var keyList = keys && keys.length ? keys : Object.keys(obj);
|
|
|
|
|
|
var rows = keyList.map(function (k) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<tr><th>" +
|
|
|
|
|
|
esc(label(k)) +
|
|
|
|
|
|
"</th><td>" +
|
|
|
|
|
|
renderCell(obj[k]) +
|
|
|
|
|
|
"</td></tr>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
return rows.length
|
|
|
|
|
|
? "<table class='kv-table'>" +
|
|
|
|
|
|
rows.join("") +
|
|
|
|
|
|
"</table>"
|
|
|
|
|
|
: "<p class='empty-hint'>暂无数据</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 多列网格展示 key-value,用于主体概览等需节省纵向空间的区块
|
|
|
|
|
|
function kvGrid(obj, keys, cols) {
|
|
|
|
|
|
if (!obj || typeof obj !== "object")
|
|
|
|
|
|
return "<p class='empty-hint'>暂无数据</p>";
|
|
|
|
|
|
var keyList = keys && keys.length ? keys : Object.keys(obj);
|
|
|
|
|
|
var parts = keyList.map(function (k) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='kv-pair'><span class='k'>" +
|
|
|
|
|
|
esc(label(k)) +
|
|
|
|
|
|
"</span><span class='v'>" +
|
|
|
|
|
|
renderCell(obj[k]) +
|
|
|
|
|
|
"</span></div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
var c = cols || 3;
|
|
|
|
|
|
return parts.length
|
|
|
|
|
|
? "<div class='kv-grid' style='--cols:" +
|
|
|
|
|
|
c +
|
|
|
|
|
|
"'>" +
|
|
|
|
|
|
parts.join("") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
: "<p class='empty-hint'>暂无数据</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function itemList(arr, fn) {
|
|
|
|
|
|
if (!Array.isArray(arr) || !arr.length)
|
|
|
|
|
|
return "<p class='empty-hint'>暂无数据</p>";
|
|
|
|
|
|
var html =
|
|
|
|
|
|
"<p class='count-hint'>共 " +
|
|
|
|
|
|
arr.length +
|
|
|
|
|
|
" 条</p><ul class='item-list'>";
|
|
|
|
|
|
arr.forEach(function (item, i) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<li>" +
|
|
|
|
|
|
(fn
|
|
|
|
|
|
? fn(item, i)
|
|
|
|
|
|
: typeof item === "object"
|
|
|
|
|
|
? JSON.stringify(item)
|
|
|
|
|
|
: esc(item)) +
|
|
|
|
|
|
"</li>";
|
|
|
|
|
|
});
|
|
|
|
|
|
return html + "</ul>";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderBasic(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无基础信息</p>";
|
|
|
|
|
|
// 与《企业全量信息核验V2_返回字段说明》BASIC 字段顺序对应
|
|
|
|
|
|
var keys = [
|
|
|
|
|
|
"entName",
|
|
|
|
|
|
"creditCode",
|
|
|
|
|
|
"regNo",
|
|
|
|
|
|
"orgCode",
|
|
|
|
|
|
"entType",
|
|
|
|
|
|
"entTypeCode",
|
|
|
|
|
|
"entityTypeCode",
|
|
|
|
|
|
"establishDate",
|
|
|
|
|
|
"registeredCapital",
|
|
|
|
|
|
"regCap",
|
|
|
|
|
|
"regCapCurrency",
|
|
|
|
|
|
"regCapCurrencyCode",
|
|
|
|
|
|
"regOrg",
|
|
|
|
|
|
"regOrgCode",
|
|
|
|
|
|
"regProvince",
|
|
|
|
|
|
"provinceCode",
|
|
|
|
|
|
"regCity",
|
|
|
|
|
|
"regCityCode",
|
|
|
|
|
|
"regDistrict",
|
|
|
|
|
|
"districtCode",
|
|
|
|
|
|
"address",
|
|
|
|
|
|
"postalCode",
|
|
|
|
|
|
"legalRepresentative",
|
|
|
|
|
|
"compositionForm",
|
|
|
|
|
|
"approvedBusinessItem",
|
|
|
|
|
|
"status",
|
|
|
|
|
|
"statusCode",
|
|
|
|
|
|
"operationPeriodFrom",
|
|
|
|
|
|
"operationPeriodTo",
|
|
|
|
|
|
"approveDate",
|
|
|
|
|
|
"cancelDate",
|
|
|
|
|
|
"revokeDate",
|
|
|
|
|
|
"cancelReason",
|
|
|
|
|
|
"revokeReason",
|
|
|
|
|
|
"oldNames",
|
|
|
|
|
|
"lastAnnuReportYear",
|
|
|
|
|
|
];
|
|
|
|
|
|
var o = {};
|
|
|
|
|
|
for (var k in v) o[k] = v[k];
|
|
|
|
|
|
// 曾用名:统一为字符串展示,无数据时显示 -(保证「曾用名」行始终出现)
|
|
|
|
|
|
o.oldNames =
|
|
|
|
|
|
v.oldNames &&
|
|
|
|
|
|
Array.isArray(v.oldNames) &&
|
|
|
|
|
|
v.oldNames.length
|
|
|
|
|
|
? v.oldNames.join(";")
|
|
|
|
|
|
: v.oldNames || "-";
|
2026-03-11 19:10:55 +08:00
|
|
|
|
var html = kvGrid(o, keys, 3);
|
2026-03-11 19:19:18 +08:00
|
|
|
|
// 经营业务范围:单独占一整行,避免挤在多列网格里
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>经营业务范围</h3>" +
|
|
|
|
|
|
"<div class='item-block'>" +
|
|
|
|
|
|
esc(v.businessScope || "-") +
|
|
|
|
|
|
"</div>";
|
2026-03-11 19:10:55 +08:00
|
|
|
|
return html;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderBranches(v) {
|
|
|
|
|
|
return itemList(v, function (b) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(b.name) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>注册号:" +
|
|
|
|
|
|
esc(b.regNo) +
|
|
|
|
|
|
";信用代码:" +
|
|
|
|
|
|
esc(b.creditCode) +
|
|
|
|
|
|
";登记机关:" +
|
|
|
|
|
|
esc(b.regOrg) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderShareholding(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无股权信息</p>";
|
2026-03-21 19:10:50 +08:00
|
|
|
|
var arDj12 =
|
|
|
|
|
|
reportData &&
|
|
|
|
|
|
Array.isArray(reportData.annualReports) &&
|
|
|
|
|
|
reportData.annualReports.length > 0;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
var html = "";
|
|
|
|
|
|
var summaryKeys = [
|
|
|
|
|
|
"shareholderCount",
|
|
|
|
|
|
"registeredCapital",
|
|
|
|
|
|
"currency",
|
|
|
|
|
|
"topHolderName",
|
|
|
|
|
|
"topHolderPercent",
|
|
|
|
|
|
"top5TotalPercent",
|
|
|
|
|
|
"hasEquityPledges",
|
|
|
|
|
|
];
|
|
|
|
|
|
var hasAny = summaryKeys.some(function (k) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
v[k] !== undefined && v[k] !== null && v[k] !== ""
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
if (hasAny) {
|
|
|
|
|
|
var rows = [];
|
|
|
|
|
|
// 股东总数
|
|
|
|
|
|
if (v.shareholderCount != null) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: "股东总数",
|
|
|
|
|
|
v: esc(v.shareholderCount),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// 注册资本(加单位元)
|
|
|
|
|
|
if (v.registeredCapital != null) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: "注册资本",
|
|
|
|
|
|
v: esc(v.registeredCapital) + " 元",
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// 币种
|
|
|
|
|
|
if (v.currency) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: "币种",
|
|
|
|
|
|
v: esc(v.currency),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// 第一大股东及持股
|
|
|
|
|
|
if (v.topHolderName || v.topHolderPercent != null) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: "第一大股东",
|
|
|
|
|
|
v: esc(v.topHolderName || "-"),
|
|
|
|
|
|
});
|
|
|
|
|
|
if (v.topHolderPercent != null) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: "第一大股东持股",
|
|
|
|
|
|
v:
|
|
|
|
|
|
(v.topHolderPercent * 100).toFixed(1) +
|
|
|
|
|
|
"%",
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 前五大合计
|
|
|
|
|
|
if (v.top5TotalPercent != null) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: "前五大合计",
|
|
|
|
|
|
v: (v.top5TotalPercent * 100).toFixed(1) + "%",
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// 是否存在股权出质
|
|
|
|
|
|
if (v.hasEquityPledges != null) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: "存在股权出质",
|
|
|
|
|
|
v: v.hasEquityPledges ? "是" : "否",
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (rows.length) {
|
|
|
|
|
|
var t =
|
|
|
|
|
|
"<table class='kv-table'><tbody>" +
|
|
|
|
|
|
rows
|
|
|
|
|
|
.map(function (r) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<tr><th>" +
|
|
|
|
|
|
esc(r.k) +
|
|
|
|
|
|
"</th><td>" +
|
|
|
|
|
|
esc(r.v) +
|
|
|
|
|
|
"</td></tr>"
|
|
|
|
|
|
);
|
|
|
|
|
|
})
|
|
|
|
|
|
.join("") +
|
|
|
|
|
|
"</tbody></table>";
|
|
|
|
|
|
html += "<h3>股权汇总</h3>" + t;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 股东明细:优先展示来自股权全景/全量信息的有效字段,避免大段空白
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>股东明细</h3>" +
|
|
|
|
|
|
itemList(v.shareholders, function (sh) {
|
|
|
|
|
|
var pct =
|
|
|
|
|
|
(sh.ownershipPercent != null
|
|
|
|
|
|
? sh.ownershipPercent
|
|
|
|
|
|
: sh.sharePercent) || 0;
|
|
|
|
|
|
var title =
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(sh.name) +
|
|
|
|
|
|
"(" +
|
|
|
|
|
|
(pct * 100).toFixed(1) +
|
|
|
|
|
|
"%)</div>";
|
|
|
|
|
|
var parts = [];
|
|
|
|
|
|
if (sh.type) {
|
|
|
|
|
|
parts.push("类型:" + esc(sh.type));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
sh.subscribedAmount != null &&
|
|
|
|
|
|
sh.subscribedAmount !== ""
|
|
|
|
|
|
) {
|
|
|
|
|
|
var sub = "认缴:" + esc(sh.subscribedAmount);
|
|
|
|
|
|
if (
|
|
|
|
|
|
sh.subscribedCurrency ||
|
|
|
|
|
|
sh.subscribedCurrencyCode
|
|
|
|
|
|
) {
|
|
|
|
|
|
sub +=
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(sh.subscribedCurrency || "") +
|
|
|
|
|
|
(sh.subscribedCurrencyCode
|
|
|
|
|
|
? "(" +
|
|
|
|
|
|
esc(sh.subscribedCurrencyCode) +
|
|
|
|
|
|
")"
|
|
|
|
|
|
: "");
|
|
|
|
|
|
}
|
|
|
|
|
|
parts.push(sub);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.subscribedDate) {
|
|
|
|
|
|
parts.push("认缴日:" + esc(sh.subscribedDate));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
sh.subscribedMethod ||
|
|
|
|
|
|
sh.subscribedMethodCode
|
|
|
|
|
|
) {
|
|
|
|
|
|
var subm =
|
|
|
|
|
|
"认缴方式:" +
|
|
|
|
|
|
esc(sh.subscribedMethod || "");
|
|
|
|
|
|
if (sh.subscribedMethodCode) {
|
|
|
|
|
|
subm +=
|
|
|
|
|
|
"(" +
|
|
|
|
|
|
esc(sh.subscribedMethodCode) +
|
|
|
|
|
|
")";
|
|
|
|
|
|
}
|
|
|
|
|
|
parts.push(subm);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.paidAmount != null && sh.paidAmount !== "") {
|
|
|
|
|
|
parts.push("实缴:" + esc(sh.paidAmount));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.paidDate) {
|
|
|
|
|
|
parts.push("实缴日:" + esc(sh.paidDate));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.paidMethod) {
|
|
|
|
|
|
parts.push("实缴方式:" + esc(sh.paidMethod));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.creditCode) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"股东信用代码:" + esc(sh.creditCode),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.regNo) {
|
|
|
|
|
|
parts.push("股东注册号:" + esc(sh.regNo));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.isHistory != null) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"是否历史:" + (sh.isHistory ? "是" : "否"),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
var meta =
|
|
|
|
|
|
parts.length > 0
|
|
|
|
|
|
? "<div class='item-meta'>" +
|
|
|
|
|
|
parts.join(";") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
: "";
|
|
|
|
|
|
return title + meta;
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>股权变更记录</h3>" +
|
|
|
|
|
|
itemList(v.equityChanges, function (e) {
|
|
|
|
|
|
var name = e.shareholderName;
|
|
|
|
|
|
// 如果是纯数字(可能是内部ID),在标题中不展示
|
|
|
|
|
|
var isId =
|
|
|
|
|
|
typeof name === "string" &&
|
|
|
|
|
|
/^[0-9]+$/.test(name);
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(e.changeDate) +
|
|
|
|
|
|
(isId || !name
|
|
|
|
|
|
? ""
|
|
|
|
|
|
: " " + esc(e.shareholderName)) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>变更前:" +
|
|
|
|
|
|
esc(e.percentBefore) +
|
|
|
|
|
|
" → 变更后:" +
|
|
|
|
|
|
esc(e.percentAfter) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>股权出质</h3>" +
|
|
|
|
|
|
itemList(v.equityPledges, function (e) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(e.regNo) +
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(e.pledgor) +
|
|
|
|
|
|
" → " +
|
|
|
|
|
|
esc(e.pledgee) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>出质数额:" +
|
|
|
|
|
|
esc(e.pledgedAmount) +
|
|
|
|
|
|
" 元" +
|
|
|
|
|
|
";登记日:" +
|
|
|
|
|
|
esc(e.regDate) +
|
|
|
|
|
|
";状态:" +
|
|
|
|
|
|
esc(e.status) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
2026-03-21 19:10:50 +08:00
|
|
|
|
html += "<h3>实缴出资明细</h3>";
|
|
|
|
|
|
if (
|
|
|
|
|
|
arDj12 &&
|
|
|
|
|
|
(!Array.isArray(v.paidInDetails) ||
|
|
|
|
|
|
!v.paidInDetails.length)
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<p class='empty-hint'>暂无实缴/应缴明细。</p>";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
html += itemList(v.paidInDetails, function (e) {
|
2026-03-10 17:49:53 +08:00
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(e.investor) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>日期:" +
|
|
|
|
|
|
esc(e.paidDate) +
|
|
|
|
|
|
";方式:" +
|
|
|
|
|
|
esc(e.paidMethod) +
|
|
|
|
|
|
";累计实缴:" +
|
|
|
|
|
|
esc(e.accumulatedPaid) +
|
|
|
|
|
|
" 万元" +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
2026-03-21 19:10:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
html += "<h3>认缴出资明细</h3>";
|
|
|
|
|
|
if (
|
|
|
|
|
|
arDj12 &&
|
|
|
|
|
|
(!Array.isArray(v.subscribedCapitalDetails) ||
|
|
|
|
|
|
!v.subscribedCapitalDetails.length)
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<p class='empty-hint'>暂无认缴出资明细。</p>";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
html += itemList(
|
|
|
|
|
|
v.subscribedCapitalDetails,
|
|
|
|
|
|
function (e) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(e.investor) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>认缴日:" +
|
|
|
|
|
|
esc(e.subscribedDate) +
|
|
|
|
|
|
";方式:" +
|
|
|
|
|
|
esc(e.subscribedMethod) +
|
|
|
|
|
|
";累计认缴:" +
|
|
|
|
|
|
esc(e.accumulatedSubscribed) +
|
|
|
|
|
|
" 元" +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderController(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无实控人信息</p>";
|
|
|
|
|
|
var html = kvTable(v, [
|
|
|
|
|
|
"id",
|
|
|
|
|
|
"name",
|
|
|
|
|
|
"type",
|
|
|
|
|
|
"percent",
|
|
|
|
|
|
"reason",
|
|
|
|
|
|
"source",
|
|
|
|
|
|
]);
|
|
|
|
|
|
if (v.path && typeof v.path === "object") {
|
|
|
|
|
|
html += "<h3>控制路径</h3>";
|
|
|
|
|
|
if (v.path.nodes && v.path.nodes.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<p class='count-hint'>节点 " +
|
|
|
|
|
|
v.path.nodes.length +
|
|
|
|
|
|
" 个</p>";
|
|
|
|
|
|
v.path.nodes.forEach(function (n) {
|
|
|
|
|
|
var id =
|
|
|
|
|
|
n.entityId != null ? n.entityId : n.uid;
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<div class='item-block'><span class='k'>" +
|
|
|
|
|
|
esc(n.label) +
|
|
|
|
|
|
"</span>" +
|
|
|
|
|
|
esc(n.name) +
|
|
|
|
|
|
(id != null
|
|
|
|
|
|
? "(id: " + esc(id) + ")"
|
|
|
|
|
|
: "") +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (v.path.links && v.path.links.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<p class='count-hint'>链接 " +
|
|
|
|
|
|
v.path.links.length +
|
|
|
|
|
|
" 条</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderBeneficiaries(v) {
|
|
|
|
|
|
return itemList(v, function (b) {
|
|
|
|
|
|
var pct = "-";
|
|
|
|
|
|
if (b.percent != null && b.percent !== 0) {
|
|
|
|
|
|
pct = (b.percent * 100).toFixed(1) + "%";
|
|
|
|
|
|
}
|
|
|
|
|
|
var title =
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(b.name) +
|
|
|
|
|
|
(pct !== "-" ? "(" + pct + ")" : "") +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
var parts = [];
|
|
|
|
|
|
if (b.type) {
|
|
|
|
|
|
parts.push("类型:" + esc(b.type));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (b.reason) {
|
|
|
|
|
|
parts.push("原因:" + esc(b.reason));
|
|
|
|
|
|
}
|
|
|
|
|
|
var meta =
|
|
|
|
|
|
parts.length > 0
|
|
|
|
|
|
? "<div class='item-meta'>" +
|
|
|
|
|
|
parts.join(";") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
: "";
|
|
|
|
|
|
return title + meta;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderInvestments(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无投资信息</p>";
|
|
|
|
|
|
var html =
|
|
|
|
|
|
"<h3>汇总</h3>" +
|
|
|
|
|
|
kvTable(v, ["totalCount", "totalAmount"]);
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>对外投资列表</h3>" +
|
|
|
|
|
|
itemList(v.list || v.entities, function (inv) {
|
|
|
|
|
|
var pct =
|
|
|
|
|
|
inv.investPercent != null
|
|
|
|
|
|
? (inv.investPercent * 100).toFixed(1)
|
|
|
|
|
|
: "-";
|
|
|
|
|
|
var title =
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(inv.entName) +
|
|
|
|
|
|
"(" +
|
|
|
|
|
|
pct +
|
|
|
|
|
|
"%)</div>";
|
|
|
|
|
|
var parts = [];
|
|
|
|
|
|
if (inv.creditCode) {
|
|
|
|
|
|
parts.push("信用代码:" + esc(inv.creditCode));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
inv.investAmount != null &&
|
|
|
|
|
|
inv.investAmount !== ""
|
|
|
|
|
|
) {
|
|
|
|
|
|
var amt =
|
|
|
|
|
|
"投资额:" + esc(inv.investAmount) + " 万";
|
|
|
|
|
|
if (inv.investCurrency) {
|
|
|
|
|
|
amt +=
|
|
|
|
|
|
"(单位:" +
|
|
|
|
|
|
esc(inv.investCurrency) +
|
|
|
|
|
|
")";
|
|
|
|
|
|
}
|
|
|
|
|
|
parts.push(amt);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (inv.entStatus) {
|
|
|
|
|
|
parts.push("状态:" + esc(inv.entStatus));
|
|
|
|
|
|
}
|
|
|
|
|
|
var meta =
|
|
|
|
|
|
parts.length > 0
|
|
|
|
|
|
? "<div class='item-meta'>" +
|
|
|
|
|
|
parts.join(";") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
: "";
|
|
|
|
|
|
return title + meta;
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>法定代表人个人对外投资</h3>" +
|
|
|
|
|
|
itemList(
|
|
|
|
|
|
v.legalRepresentativeInvestments ||
|
|
|
|
|
|
v.legalPersonInvestments,
|
|
|
|
|
|
function (inv) {
|
|
|
|
|
|
var pct = "-";
|
|
|
|
|
|
if (
|
|
|
|
|
|
inv.investPercent != null &&
|
|
|
|
|
|
Number(inv.investPercent) !== 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
pct =
|
|
|
|
|
|
(inv.investPercent * 100).toFixed(1) +
|
|
|
|
|
|
"%";
|
|
|
|
|
|
}
|
|
|
|
|
|
var title =
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(inv.entName) +
|
|
|
|
|
|
(pct !== "-" ? "(" + pct + ")" : "") +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
var parts = [];
|
|
|
|
|
|
if (inv.creditCode) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"信用代码:" + esc(inv.creditCode),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 优先展示投资额,其次在无投资额但有注册资本时展示注册资本
|
|
|
|
|
|
if (
|
|
|
|
|
|
inv.investAmount != null &&
|
|
|
|
|
|
inv.investAmount !== "" &&
|
|
|
|
|
|
Number(inv.investAmount) !== 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"投资额:" +
|
|
|
|
|
|
esc(inv.investAmount) +
|
|
|
|
|
|
" 万",
|
|
|
|
|
|
);
|
|
|
|
|
|
} else if (
|
|
|
|
|
|
inv.regCap != null &&
|
|
|
|
|
|
inv.regCap !== "" &&
|
|
|
|
|
|
Number(inv.regCap) !== 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"注册资本:" +
|
|
|
|
|
|
esc(inv.regCap) +
|
|
|
|
|
|
" 万(企业注册资本)",
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (inv.entStatus) {
|
|
|
|
|
|
parts.push("状态:" + esc(inv.entStatus));
|
|
|
|
|
|
}
|
|
|
|
|
|
var meta =
|
|
|
|
|
|
parts.length > 0
|
|
|
|
|
|
? "<div class='item-meta'>" +
|
|
|
|
|
|
parts.join(";") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
: "";
|
|
|
|
|
|
return title + meta;
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderGuarantees(v) {
|
|
|
|
|
|
if (!Array.isArray(v) || !v.length) {
|
|
|
|
|
|
return "<p class='empty-hint'>暂无对外担保信息</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
// 只展示有关键字段的记录,避免一堆空行
|
|
|
|
|
|
var coreKeys = [
|
|
|
|
|
|
"mortgagor",
|
|
|
|
|
|
"creditor",
|
|
|
|
|
|
"principalAmount",
|
|
|
|
|
|
"principalKind",
|
|
|
|
|
|
"guaranteeType",
|
|
|
|
|
|
"periodFrom",
|
|
|
|
|
|
"periodTo",
|
|
|
|
|
|
];
|
|
|
|
|
|
var list = v.filter(function (g) {
|
|
|
|
|
|
return coreKeys.some(function (k) {
|
|
|
|
|
|
return g[k] != null && g[k] !== "";
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!list.length) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<p class='empty-hint'>存在 " +
|
|
|
|
|
|
v.length +
|
2026-03-21 19:10:50 +08:00
|
|
|
|
" 条对外担保记录,但债务人、债权人等关键字段为空,暂无法展示详细明细。</p>"
|
2026-03-10 17:49:53 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<p class='count-hint'>共 " +
|
|
|
|
|
|
list.length +
|
2026-03-21 19:10:50 +08:00
|
|
|
|
" 条</p>" +
|
2026-03-10 17:49:53 +08:00
|
|
|
|
itemList(list, function (g) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(g.mortgagor || "-") +
|
|
|
|
|
|
" → " +
|
|
|
|
|
|
esc(g.creditor || "-") +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>主债权数额:" +
|
|
|
|
|
|
esc(g.principalAmount || "-") +
|
|
|
|
|
|
";种类:" +
|
|
|
|
|
|
esc(g.principalKind || "-") +
|
|
|
|
|
|
";保证方式:" +
|
|
|
|
|
|
esc(g.guaranteeType || "-") +
|
|
|
|
|
|
";期限:" +
|
|
|
|
|
|
esc(g.periodFrom || "-") +
|
|
|
|
|
|
" 至 " +
|
|
|
|
|
|
esc(g.periodTo || "-") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
})
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderManagement(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无人员信息</p>";
|
|
|
|
|
|
var html =
|
|
|
|
|
|
"<h3>高管列表</h3>" +
|
|
|
|
|
|
itemList(v.executives, function (e) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(e.name) +
|
|
|
|
|
|
"</div><div class='item-meta'>" +
|
|
|
|
|
|
esc(formatPosition(e.position)) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
2026-03-21 19:10:50 +08:00
|
|
|
|
html += "<h3>从业与社保</h3>";
|
|
|
|
|
|
html += kvTable(v, [
|
|
|
|
|
|
"employeeCount",
|
|
|
|
|
|
"femaleEmployeeCount",
|
|
|
|
|
|
"socialSecurity",
|
|
|
|
|
|
]);
|
2026-03-10 17:49:53 +08:00
|
|
|
|
html += "<h3>法定代表人其他任职</h3>";
|
|
|
|
|
|
var others =
|
|
|
|
|
|
v.legalRepresentativeOtherPositions ||
|
|
|
|
|
|
v.legalPersonOtherPositions;
|
|
|
|
|
|
html += itemList(others, function (f) {
|
|
|
|
|
|
var title =
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(f.entName) +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
var parts = [];
|
|
|
|
|
|
if (f.position) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"职务:" + esc(formatPosition(f.position)),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (f.name) {
|
|
|
|
|
|
parts.push("姓名:" + esc(f.name));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (f.entStatus) {
|
|
|
|
|
|
parts.push("企业状态:" + esc(f.entStatus));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (f.creditCode) {
|
|
|
|
|
|
parts.push("信用代码:" + esc(f.creditCode));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (f.regNo) {
|
|
|
|
|
|
parts.push("注册号:" + esc(f.regNo));
|
|
|
|
|
|
}
|
|
|
|
|
|
var meta =
|
|
|
|
|
|
parts.length > 0
|
|
|
|
|
|
? "<div class='item-meta'>" +
|
|
|
|
|
|
parts.join(";") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
: "";
|
|
|
|
|
|
return title + meta;
|
|
|
|
|
|
});
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderAssets(v) {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
if (!v) {
|
|
|
|
|
|
return "<p class='empty-hint'>暂无资产数据</p>";
|
|
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
var years = Array.isArray(v.years) ? v.years : [];
|
2026-03-21 19:10:50 +08:00
|
|
|
|
if (!years.length) {
|
2026-03-10 17:49:53 +08:00
|
|
|
|
return "<p class='empty-hint'>暂无资产数据</p>";
|
2026-03-21 19:10:50 +08:00
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
// 过滤掉所有核心字段都为空的年度记录,避免一堆空行
|
|
|
|
|
|
var coreKeys = [
|
|
|
|
|
|
"assetTotal",
|
|
|
|
|
|
"revenueTotal",
|
|
|
|
|
|
"netProfit",
|
|
|
|
|
|
"liabilityTotal",
|
|
|
|
|
|
"equityTotal",
|
|
|
|
|
|
"profitTotal",
|
|
|
|
|
|
];
|
|
|
|
|
|
var list = years.filter(function (y) {
|
|
|
|
|
|
return coreKeys.some(function (k) {
|
|
|
|
|
|
return y[k] != null && y[k] !== "";
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!list.length) {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
return "<p class='empty-hint'>存在资产经营记录,但资产总额、营收、净利润等核心字段为空,暂无法展示详细明细。</p>";
|
2026-03-10 17:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<h3>按年度资产经营数据</h3>" +
|
|
|
|
|
|
itemList(list, function (y) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(y.year) +
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(y.reportDate || "") +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>资产总额:" +
|
|
|
|
|
|
esc(y.assetTotal || "-") +
|
|
|
|
|
|
";营收:" +
|
|
|
|
|
|
esc(y.revenueTotal || "-") +
|
|
|
|
|
|
";净利润:" +
|
|
|
|
|
|
esc(y.netProfit || "-") +
|
|
|
|
|
|
";负债:" +
|
|
|
|
|
|
esc(y.liabilityTotal || "-") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
})
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderLicenses(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无许可信息</p>";
|
|
|
|
|
|
var html =
|
|
|
|
|
|
"<h3>行政许可列表</h3>" +
|
|
|
|
|
|
itemList(v.permits, function (p) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(p.name) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>有效期:" +
|
|
|
|
|
|
esc(p.valFrom) +
|
|
|
|
|
|
" ~ " +
|
|
|
|
|
|
esc(p.valTo) +
|
|
|
|
|
|
";许可机关:" +
|
|
|
|
|
|
esc(p.licAnth) +
|
|
|
|
|
|
";" +
|
|
|
|
|
|
esc(p.licItem) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>许可变更记录</h3>" +
|
|
|
|
|
|
itemList(v.permitChanges, function (p) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(p.changeDate) +
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(p.changeType) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>变更前:" +
|
|
|
|
|
|
(p.detailBefore || "-").substring(0, 80) +
|
|
|
|
|
|
"…;变更后:" +
|
|
|
|
|
|
(p.detailAfter || "-").substring(0, 80) +
|
|
|
|
|
|
"…</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>知识产权出质</h3>" +
|
|
|
|
|
|
itemList(v.ipPledges, function (i) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-block'>" +
|
|
|
|
|
|
(typeof i === "object"
|
|
|
|
|
|
? JSON.stringify(i)
|
|
|
|
|
|
: esc(i)) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderActivities(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无经营活动数据</p>";
|
2026-03-21 19:10:50 +08:00
|
|
|
|
var arDj12 =
|
|
|
|
|
|
reportData &&
|
|
|
|
|
|
Array.isArray(reportData.annualReports) &&
|
|
|
|
|
|
reportData.annualReports.length > 0;
|
2026-03-10 17:49:53 +08:00
|
|
|
|
// 招投标:对角色、类型做友好映射
|
|
|
|
|
|
var bidRoleMap = {
|
|
|
|
|
|
10: "招标人/采购人",
|
|
|
|
|
|
20: "中标人/供应商",
|
|
|
|
|
|
30: "代理机构",
|
|
|
|
|
|
};
|
|
|
|
|
|
var announceTypeMap = {
|
|
|
|
|
|
10: "招标公告",
|
|
|
|
|
|
20: "中标结果公告",
|
|
|
|
|
|
};
|
|
|
|
|
|
var html =
|
|
|
|
|
|
"<h3>招投标</h3>" +
|
|
|
|
|
|
itemList(v.bids, function (b) {
|
|
|
|
|
|
var t =
|
|
|
|
|
|
b.announcetitle ||
|
|
|
|
|
|
b.ANNOUNCETITLE ||
|
|
|
|
|
|
b.title ||
|
|
|
|
|
|
"-";
|
|
|
|
|
|
var roleCode = b.bidrole || b.BIDROLE;
|
|
|
|
|
|
var roleText =
|
|
|
|
|
|
bidRoleMap[Number(roleCode)] ||
|
|
|
|
|
|
(roleCode != null && roleCode !== ""
|
|
|
|
|
|
? "角色代码:" + roleCode
|
|
|
|
|
|
: "-");
|
|
|
|
|
|
var typeCode =
|
|
|
|
|
|
b.announceType ||
|
|
|
|
|
|
b.annoucetype ||
|
|
|
|
|
|
b.ANNOUNCETYPE;
|
|
|
|
|
|
var typeText =
|
|
|
|
|
|
announceTypeMap[Number(typeCode)] ||
|
|
|
|
|
|
(typeCode != null && typeCode !== ""
|
|
|
|
|
|
? "类型代码:" + typeCode
|
|
|
|
|
|
: "-");
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(t) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>角色:" +
|
|
|
|
|
|
esc(roleText) +
|
|
|
|
|
|
";类型:" +
|
|
|
|
|
|
esc(typeText) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
2026-03-21 19:10:50 +08:00
|
|
|
|
html += "<h3>网站/网店</h3>";
|
|
|
|
|
|
if (
|
|
|
|
|
|
arDj12 &&
|
|
|
|
|
|
(!Array.isArray(v.websites) || !v.websites.length)
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<p class='empty-hint'>暂无网站或网店信息。</p>";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
html += itemList(v.websites, function (w) {
|
2026-03-10 17:49:53 +08:00
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(w.websitname || w.WEBSITNAME || w.name) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>类型:" +
|
|
|
|
|
|
esc(w.webtype || w.WEBTYPE) +
|
|
|
|
|
|
";域名:" +
|
|
|
|
|
|
esc(w.domain || w.DOMAIN) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
2026-03-21 19:10:50 +08:00
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderInspections(v) {
|
|
|
|
|
|
return itemList(v, function (i) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(i.inspectDate) +
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(i.result) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>数据类型:" +
|
|
|
|
|
|
esc(i.dataType) +
|
|
|
|
|
|
";检查机关:" +
|
|
|
|
|
|
esc(i.regOrg) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderRisks(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无风险数据</p>";
|
|
|
|
|
|
var hasKeys = [
|
|
|
|
|
|
"hasCourtJudgments",
|
|
|
|
|
|
"hasJudicialAssists",
|
|
|
|
|
|
"hasDishonestDebtors",
|
|
|
|
|
|
"hasLimitHighDebtors",
|
|
|
|
|
|
"hasAdminPenalty",
|
|
|
|
|
|
"hasException",
|
|
|
|
|
|
"hasSeriousIllegal",
|
|
|
|
|
|
"hasTaxOwing",
|
|
|
|
|
|
"hasSeriousTaxIllegal",
|
|
|
|
|
|
"hasMortgage",
|
|
|
|
|
|
"hasEquityPledges",
|
|
|
|
|
|
"hasQuickCancel",
|
|
|
|
|
|
];
|
|
|
|
|
|
var hasLabels = [
|
|
|
|
|
|
"裁判文书",
|
|
|
|
|
|
"司法协助",
|
|
|
|
|
|
"失信被执行人",
|
|
|
|
|
|
"限高被执行人",
|
|
|
|
|
|
"行政处罚",
|
|
|
|
|
|
"经营异常",
|
|
|
|
|
|
"严重违法",
|
|
|
|
|
|
"欠税",
|
|
|
|
|
|
"重大税收违法",
|
|
|
|
|
|
"动产抵押",
|
|
|
|
|
|
"股权出质",
|
|
|
|
|
|
"简易注销",
|
|
|
|
|
|
];
|
|
|
|
|
|
var html = "<h3>风险项</h3><ul class='item-list'>";
|
|
|
|
|
|
hasKeys.forEach(function (k, idx) {
|
|
|
|
|
|
var val = v[k];
|
|
|
|
|
|
if (val === undefined)
|
|
|
|
|
|
val =
|
|
|
|
|
|
v[
|
|
|
|
|
|
k
|
|
|
|
|
|
.replace("Judgments", "JudicialCase")
|
|
|
|
|
|
.replace("Assists", "JudicialAid")
|
|
|
|
|
|
.replace("EquityPledges", "StockPawn")
|
|
|
|
|
|
];
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<li class='risk-row'><span>" +
|
|
|
|
|
|
hasLabels[idx] +
|
|
|
|
|
|
"</span><span class='" +
|
|
|
|
|
|
(val ? "bad" : "ok") +
|
|
|
|
|
|
"'>" +
|
|
|
|
|
|
(val ? "存在" : "未发现") +
|
|
|
|
|
|
"</span></li>";
|
|
|
|
|
|
});
|
|
|
|
|
|
html += "</ul>";
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>裁判文书</h3>" +
|
|
|
|
|
|
itemList(
|
|
|
|
|
|
v.courtJudgments || v.judicialCases,
|
|
|
|
|
|
function (c) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(
|
|
|
|
|
|
c.caseNumber ||
|
|
|
|
|
|
c.CASENUMBER ||
|
|
|
|
|
|
c.judicialDocumentId,
|
|
|
|
|
|
) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>案由:" +
|
|
|
|
|
|
esc(c.caseCause || c.CASECAUSE) +
|
|
|
|
|
|
";结果:" +
|
|
|
|
|
|
esc(c.judgeResult || c.JUDGERESULT) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>司法协助</h3>" +
|
|
|
|
|
|
itemList(
|
|
|
|
|
|
v.judicialAssists || v.judicialAids,
|
|
|
|
|
|
function (a) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(a.iname || a.INAME || a.marketName) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>法院:" +
|
|
|
|
|
|
esc(a.courtName || a.COURTNAME) +
|
|
|
|
|
|
";股权数额:" +
|
|
|
|
|
|
esc(a.shaream || a.SHAREAM) +
|
|
|
|
|
|
" 元</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>失信被执行人</h3>" +
|
|
|
|
|
|
itemList(v.dishonestDebtors, function (d) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>案号 " +
|
|
|
|
|
|
esc(d.caseNo) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>执行法院:" +
|
|
|
|
|
|
esc(d.execCourt) +
|
|
|
|
|
|
";履行情况:" +
|
|
|
|
|
|
esc(d.performanceStatus) +
|
|
|
|
|
|
";发布时间:" +
|
|
|
|
|
|
esc(d.publishDate) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>限高被执行人</h3>" +
|
|
|
|
|
|
itemList(v.limitHighDebtors, function (x) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(x.ah || x.caseNo) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>执行法院:" +
|
|
|
|
|
|
esc(x.zxfy || x.execCourt) +
|
|
|
|
|
|
";" +
|
|
|
|
|
|
esc(x.fbrq || x.publishDate) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
// 按案件类型展示涉诉信息(来自企业司法认证 entout)
|
|
|
|
|
|
if (v.litigation && v.litigation.totalCases) {
|
|
|
|
|
|
var lit = v.litigation;
|
|
|
|
|
|
var typeLabels = {
|
|
|
|
|
|
administrative: "行政案件",
|
|
|
|
|
|
implement: "执行案件",
|
|
|
|
|
|
preservation: "非诉保全审查",
|
|
|
|
|
|
civil: "民事案件",
|
|
|
|
|
|
criminal: "刑事案件",
|
|
|
|
|
|
bankrupt: "强制清算与破产案件",
|
|
|
|
|
|
jurisdict: "管辖案件",
|
|
|
|
|
|
compensate: "赔偿案件",
|
|
|
|
|
|
};
|
|
|
|
|
|
html += "<h3>涉诉案件汇总</h3>";
|
|
|
|
|
|
var rows = [];
|
|
|
|
|
|
Object.keys(typeLabels).forEach(function (k) {
|
|
|
|
|
|
var sec = lit[k];
|
|
|
|
|
|
if (sec && sec.count) {
|
|
|
|
|
|
rows.push({
|
|
|
|
|
|
k: typeLabels[k],
|
|
|
|
|
|
v: sec.count + " 件",
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (rows.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<table class='kv-table'><tbody>" +
|
|
|
|
|
|
rows
|
|
|
|
|
|
.map(function (r) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<tr><th>" +
|
|
|
|
|
|
esc(r.k) +
|
|
|
|
|
|
"</th><td>" +
|
|
|
|
|
|
esc(r.v) +
|
|
|
|
|
|
"</td></tr>"
|
|
|
|
|
|
);
|
|
|
|
|
|
})
|
|
|
|
|
|
.join("") +
|
|
|
|
|
|
"</tbody></table>";
|
|
|
|
|
|
}
|
|
|
|
|
|
Object.keys(typeLabels).forEach(function (k) {
|
|
|
|
|
|
var sec = lit[k];
|
|
|
|
|
|
if (!sec || !sec.cases || !sec.cases.length) return;
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>" +
|
|
|
|
|
|
typeLabels[k] +
|
|
|
|
|
|
"</h3>" +
|
|
|
|
|
|
itemList(sec.cases, function (c) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(c.caseNo) +
|
|
|
|
|
|
"(" +
|
|
|
|
|
|
esc(c.court) +
|
|
|
|
|
|
")</div>" +
|
|
|
|
|
|
"<div class='item-meta'>" +
|
|
|
|
|
|
"地区:" +
|
|
|
|
|
|
esc(c.region) +
|
|
|
|
|
|
";审级:" +
|
|
|
|
|
|
esc(c.trialLevel) +
|
|
|
|
|
|
";案件类型:" +
|
|
|
|
|
|
esc(c.caseType) +
|
|
|
|
|
|
";案由:" +
|
|
|
|
|
|
esc(c.cause) +
|
|
|
|
|
|
";标的金额:" +
|
|
|
|
|
|
esc(c.amount) +
|
|
|
|
|
|
";立案日期:" +
|
|
|
|
|
|
esc(c.filingDate) +
|
|
|
|
|
|
";裁判日期:" +
|
|
|
|
|
|
esc(c.judgmentDate) +
|
|
|
|
|
|
";胜败结果:" +
|
|
|
|
|
|
esc(c.victoryResult) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>行政处罚</h3>" +
|
|
|
|
|
|
itemList(v.adminPenalties, function (p) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(p.pendecno || p.PENDECNO) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>违法类型:" +
|
|
|
|
|
|
esc(p.illegacttype || p.ILLEGACTTYPE) +
|
|
|
|
|
|
";机关:" +
|
|
|
|
|
|
esc(p.penauth || p.PENAUTH) +
|
|
|
|
|
|
";日期:" +
|
|
|
|
|
|
esc(p.pendecissdate || p.PENDECISSDATE) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>行政处罚变更记录</h3>" +
|
|
|
|
|
|
itemList(v.adminPenaltyUpdates, function (p) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(p.updateDate) +
|
|
|
|
|
|
"</div><div class='item-meta'>" +
|
|
|
|
|
|
esc(p.updateContent) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>经营异常</h3>" +
|
|
|
|
|
|
itemList(v.exceptions, function (e) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(e.indate || e.INDATE) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>原因:" +
|
|
|
|
|
|
esc(e.inreason || e.INREASON) +
|
|
|
|
|
|
";移出:" +
|
|
|
|
|
|
esc(e.outdate || e.OUTDATE) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>严重违法</h3>" +
|
|
|
|
|
|
itemList(v.seriousIllegals, function (s) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-block'>" +
|
|
|
|
|
|
(typeof s === "object"
|
|
|
|
|
|
? JSON.stringify(s)
|
|
|
|
|
|
: esc(s)) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>动产抵押</h3>" +
|
|
|
|
|
|
itemList(v.mortgages, function (m) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(m.regNo) +
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(m.guaranteedAmount) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>登记日:" +
|
|
|
|
|
|
esc(m.regDate) +
|
|
|
|
|
|
";机关:" +
|
|
|
|
|
|
esc(m.regOrg) +
|
|
|
|
|
|
";状态:" +
|
|
|
|
|
|
esc(m.status) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html += "<h3>简易注销</h3>";
|
|
|
|
|
|
if (v.quickCancel) {
|
|
|
|
|
|
html += kvTable(v.quickCancel, [
|
|
|
|
|
|
"entName",
|
|
|
|
|
|
"creditCode",
|
|
|
|
|
|
"regNo",
|
|
|
|
|
|
"regOrg",
|
|
|
|
|
|
"noticeFromDate",
|
|
|
|
|
|
"noticeToDate",
|
|
|
|
|
|
"cancelResult",
|
|
|
|
|
|
]);
|
|
|
|
|
|
if (
|
|
|
|
|
|
v.quickCancel.dissents &&
|
|
|
|
|
|
v.quickCancel.dissents.length
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<p class='count-hint'>异议 " +
|
|
|
|
|
|
v.quickCancel.dissents.length +
|
|
|
|
|
|
" 条</p>";
|
|
|
|
|
|
v.quickCancel.dissents.forEach(function (d) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<div class='item-block'>" +
|
|
|
|
|
|
esc(d.dissentOrg) +
|
|
|
|
|
|
":" +
|
|
|
|
|
|
esc(d.dissentDes) +
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(d.dissentDate) +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
html += "<p class='empty-hint'>无</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
html += "<h3>清算信息</h3>";
|
|
|
|
|
|
if (v.liquidation) {
|
|
|
|
|
|
html += kvTable(v.liquidation, [
|
|
|
|
|
|
"principal",
|
|
|
|
|
|
"members",
|
|
|
|
|
|
]);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
html += "<p class='empty-hint'>无</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
html += "<h3>纳税与欠税</h3>";
|
|
|
|
|
|
var tax = v.taxRecords;
|
|
|
|
|
|
if (tax) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<p class='count-hint'>纳税A级年度:" +
|
|
|
|
|
|
(tax.taxLevelAYears && tax.taxLevelAYears.length
|
|
|
|
|
|
? tax.taxLevelAYears.length + " 条"
|
|
|
|
|
|
: "无") +
|
|
|
|
|
|
";欠税:" +
|
|
|
|
|
|
(tax.taxOwings && tax.taxOwings.length
|
|
|
|
|
|
? tax.taxOwings.length + " 条"
|
|
|
|
|
|
: "无") +
|
|
|
|
|
|
"</p>";
|
|
|
|
|
|
html += itemList(tax.taxOwings, function (t) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(t.taxOwedType || t.taxowedtype) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>合计:" +
|
|
|
|
|
|
esc(t.totalOwedAmount || t.totalowedamount) +
|
|
|
|
|
|
";公示日:" +
|
|
|
|
|
|
esc(t.publishDate || t.publishdate) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
html += "<p class='empty-hint'>无</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderRiskOverview(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无风险分析</p>";
|
|
|
|
|
|
var html = "";
|
|
|
|
|
|
// 风险点清单:命中 / 未命中,多列展示
|
|
|
|
|
|
if (Array.isArray(v.items) && v.items.length) {
|
|
|
|
|
|
html += "<h3>风险点一览</h3>";
|
|
|
|
|
|
html += "<div class='risk-points-grid'>";
|
|
|
|
|
|
v.items.forEach(function (it) {
|
|
|
|
|
|
var statusText = it.hit ? "命中" : "未命中";
|
|
|
|
|
|
var statusClass = it.hit
|
|
|
|
|
|
? "risk-status-bad"
|
|
|
|
|
|
: "risk-status-ok";
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<div class='risk-point'><span class='risk-point-name'>" +
|
|
|
|
|
|
esc(it.name) +
|
|
|
|
|
|
"</span><span class='" +
|
|
|
|
|
|
statusClass +
|
|
|
|
|
|
"'>" +
|
|
|
|
|
|
statusText +
|
|
|
|
|
|
"</span></div>";
|
|
|
|
|
|
});
|
|
|
|
|
|
html += "</div>";
|
|
|
|
|
|
}
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderTimeline(v) {
|
|
|
|
|
|
if (!v || !v.length)
|
|
|
|
|
|
return "<p class='empty-hint'>暂无发展时间线</p>";
|
|
|
|
|
|
return itemList(v, function (item) {
|
|
|
|
|
|
var title =
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(item.date) +
|
|
|
|
|
|
" " +
|
|
|
|
|
|
esc(item.type) +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
var body = "<div>" + esc(item.title || "") + "</div>";
|
|
|
|
|
|
var meta = "";
|
|
|
|
|
|
if (item.detailBefore || item.detailAfter) {
|
|
|
|
|
|
// 对长文本拆成更易读的多行段落
|
|
|
|
|
|
var before = (item.detailBefore || "")
|
|
|
|
|
|
.replace(/;/g, ";<br/>")
|
|
|
|
|
|
.replace(/;;+/g, ";");
|
|
|
|
|
|
var after = (item.detailAfter || "")
|
|
|
|
|
|
.replace(/;/g, ";<br/>")
|
|
|
|
|
|
.replace(/;;+/g, ";");
|
|
|
|
|
|
meta =
|
|
|
|
|
|
"<div class='item-meta'>" +
|
|
|
|
|
|
"<div><strong>变更前:</strong><br/>" +
|
|
|
|
|
|
before +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div style='margin-top:4px'><strong>变更后:</strong><br/>" +
|
|
|
|
|
|
after +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
}
|
|
|
|
|
|
return title + body + meta;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderListed(v) {
|
|
|
|
|
|
if (!v)
|
|
|
|
|
|
return "<p class='empty-hint'>非上市或暂无上市信息</p>";
|
|
|
|
|
|
var html =
|
|
|
|
|
|
"<h3>是否上市</h3><p>" +
|
|
|
|
|
|
(v.isListed ? "是" : "否") +
|
|
|
|
|
|
"</p>";
|
|
|
|
|
|
if (v.company) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>上市公司信息</h3>" +
|
|
|
|
|
|
kvTable(v.company, [
|
|
|
|
|
|
"bizScope",
|
|
|
|
|
|
"creditCode",
|
|
|
|
|
|
"regAddr",
|
|
|
|
|
|
"regCapital",
|
|
|
|
|
|
"orgCode",
|
|
|
|
|
|
"cur",
|
|
|
|
|
|
"curName",
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
html += "<h3>股票信息</h3>";
|
|
|
|
|
|
if (v.stock)
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<div class='item-block'>" +
|
|
|
|
|
|
(typeof v.stock === "object"
|
|
|
|
|
|
? JSON.stringify(v.stock)
|
|
|
|
|
|
: esc(v.stock)) +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
else html += "<p class='empty-hint'>无</p>";
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>十大股东</h3>" +
|
|
|
|
|
|
itemList(v.topShareholders, function (s) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(s.name || s.shaname) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>" +
|
|
|
|
|
|
esc(s.percent || s.fundedratio) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3>上市高管</h3>" +
|
|
|
|
|
|
itemList(v.listedManagers, function (m) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(m.name || m.perName) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>" +
|
|
|
|
|
|
esc(m.position) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderScores(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>暂无评分</p>";
|
|
|
|
|
|
var html = kvTable(v, [
|
|
|
|
|
|
"overallScore",
|
|
|
|
|
|
"stabilityScore",
|
|
|
|
|
|
"equityTransparencyScore",
|
|
|
|
|
|
"complianceScore",
|
|
|
|
|
|
"activityScore",
|
|
|
|
|
|
]);
|
|
|
|
|
|
if (v.tags && v.tags.length) {
|
|
|
|
|
|
html += "<h3>标签</h3><p>";
|
|
|
|
|
|
v.tags.forEach(function (t) {
|
|
|
|
|
|
html += "<span class='tag'>" + esc(t) + "</span> ";
|
|
|
|
|
|
});
|
|
|
|
|
|
html += "</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderBasicList(v) {
|
|
|
|
|
|
return itemList(v, function (b) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(b.entName || b.entname) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>信用代码:" +
|
|
|
|
|
|
esc(b.creditCode || b.creditNo || b.creditno) +
|
|
|
|
|
|
";注册号:" +
|
|
|
|
|
|
esc(b.regNo) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderRaw(v) {
|
|
|
|
|
|
if (!v) return "<p class='empty-hint'>无原始数据</p>";
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<details class='raw-section'><summary>展开 jiguangFull / judicialCertFull</summary>" +
|
|
|
|
|
|
"<pre>" +
|
|
|
|
|
|
esc(JSON.stringify(v, null, 2)).substring(0, 15000) +
|
|
|
|
|
|
(JSON.stringify(v).length > 15000
|
|
|
|
|
|
? "\n…(已截断)"
|
|
|
|
|
|
: "") +
|
|
|
|
|
|
"</pre></details>"
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-21 19:10:50 +08:00
|
|
|
|
function renderCapiItemList(arr) {
|
|
|
|
|
|
if (!Array.isArray(arr) || !arr.length) return "";
|
|
|
|
|
|
return itemList(arr, function (r) {
|
|
|
|
|
|
var parts = [];
|
|
|
|
|
|
if (r.investType) parts.push("方式:" + esc(r.investType));
|
|
|
|
|
|
if (r.realCapi != null && r.realCapi !== "")
|
|
|
|
|
|
parts.push("实缴:" + esc(r.realCapi));
|
|
|
|
|
|
if (r.shoudCapi != null && r.shoudCapi !== "")
|
|
|
|
|
|
parts.push("应缴:" + esc(r.shoudCapi));
|
|
|
|
|
|
if (r.shouldCapi != null && r.shouldCapi !== "")
|
|
|
|
|
|
parts.push("应缴:" + esc(r.shouldCapi));
|
|
|
|
|
|
if (r.realCapiDate)
|
|
|
|
|
|
parts.push("实缴日:" + esc(r.realCapiDate));
|
|
|
|
|
|
if (r.shouldCapiDate)
|
|
|
|
|
|
parts.push("应缴日:" + esc(r.shouldCapiDate));
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-meta'>" +
|
|
|
|
|
|
(parts.length
|
|
|
|
|
|
? parts.join(";")
|
|
|
|
|
|
: esc(JSON.stringify(r))) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderAnnualShareholders(list) {
|
|
|
|
|
|
if (!Array.isArray(list) || !list.length) return "";
|
|
|
|
|
|
var html = "";
|
|
|
|
|
|
list.forEach(function (sh) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<div class='item-block' style='margin-bottom:8px'>";
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(sh.stockName || "-") +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
var meta = [];
|
|
|
|
|
|
if (sh.identifyType)
|
|
|
|
|
|
meta.push("证件类型:" + esc(sh.identifyType));
|
|
|
|
|
|
if (sh.stockPercent)
|
|
|
|
|
|
meta.push("持股比例:" + esc(sh.stockPercent));
|
|
|
|
|
|
if (
|
|
|
|
|
|
sh.totalRealCapi != null &&
|
|
|
|
|
|
sh.totalRealCapi !== ""
|
|
|
|
|
|
)
|
|
|
|
|
|
meta.push("实缴总额:" + esc(sh.totalRealCapi));
|
|
|
|
|
|
if (
|
|
|
|
|
|
sh.totalShouldCapi != null &&
|
|
|
|
|
|
sh.totalShouldCapi !== ""
|
|
|
|
|
|
)
|
|
|
|
|
|
meta.push("应缴总额:" + esc(sh.totalShouldCapi));
|
|
|
|
|
|
if (meta.length)
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<div class='item-meta'>" +
|
|
|
|
|
|
meta.join(";") +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
if (sh.realCapiItems && sh.realCapiItems.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>实缴明细</h4>";
|
|
|
|
|
|
html += renderCapiItemList(sh.realCapiItems);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sh.shouldCapiItems && sh.shouldCapiItems.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>应缴明细</h4>";
|
|
|
|
|
|
html += renderCapiItemList(sh.shouldCapiItems);
|
|
|
|
|
|
}
|
|
|
|
|
|
html += "</div>";
|
|
|
|
|
|
});
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderAnnualReports(arr) {
|
|
|
|
|
|
if (!Array.isArray(arr) || !arr.length)
|
|
|
|
|
|
return "<p class='empty-hint'>暂无企业年报数据</p>";
|
|
|
|
|
|
var sorted = arr.slice().sort(function (a, b) {
|
|
|
|
|
|
var ya = parseInt(a.reportYear, 10) || 0;
|
|
|
|
|
|
var yb = parseInt(b.reportYear, 10) || 0;
|
|
|
|
|
|
return yb - ya;
|
|
|
|
|
|
});
|
|
|
|
|
|
var html =
|
|
|
|
|
|
"<p class='count-hint'>共 " + sorted.length + " 份</p>";
|
|
|
|
|
|
sorted.forEach(function (y) {
|
|
|
|
|
|
html += "<div class='report-annual-shell'>";
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h3 class='report-annual-card-title'>" +
|
|
|
|
|
|
esc(
|
|
|
|
|
|
y.reportName ||
|
|
|
|
|
|
(y.reportYear
|
|
|
|
|
|
? y.reportYear + " 年报"
|
|
|
|
|
|
: "年报"),
|
|
|
|
|
|
) +
|
|
|
|
|
|
"</h3>";
|
|
|
|
|
|
var sumKeys = [
|
|
|
|
|
|
"reportYear",
|
|
|
|
|
|
"reportDate",
|
|
|
|
|
|
"entityName",
|
|
|
|
|
|
"creditCode",
|
|
|
|
|
|
"registerCode",
|
|
|
|
|
|
"organizationCode",
|
|
|
|
|
|
"entityStatus",
|
|
|
|
|
|
"address",
|
|
|
|
|
|
"telephone",
|
|
|
|
|
|
"postCode",
|
|
|
|
|
|
"entityBusinessScope",
|
|
|
|
|
|
"employeeCnt",
|
|
|
|
|
|
"entityPractitionerFemaleAmount",
|
|
|
|
|
|
"actualEmployeeCnt",
|
|
|
|
|
|
"mainBusinessIncome",
|
|
|
|
|
|
"netProfit",
|
|
|
|
|
|
"totalSalesAmount",
|
|
|
|
|
|
"totalNetProfit",
|
|
|
|
|
|
"totalAssets",
|
|
|
|
|
|
"totalLiabilities",
|
|
|
|
|
|
"totalOwnerEquity",
|
|
|
|
|
|
"totalTaxAmount",
|
|
|
|
|
|
"isWebsite",
|
|
|
|
|
|
"isInvest",
|
|
|
|
|
|
"isExternalGuarantee",
|
|
|
|
|
|
"isEquityTransfer",
|
|
|
|
|
|
"entityHoldingInfo",
|
|
|
|
|
|
"guaranteeInfo",
|
|
|
|
|
|
"actualRegistCapitalInfo",
|
|
|
|
|
|
"reportBranch",
|
|
|
|
|
|
"reportContributeInfo",
|
|
|
|
|
|
"reportRecordInfo",
|
|
|
|
|
|
];
|
|
|
|
|
|
html += kvGrid(y, sumKeys, 3);
|
|
|
|
|
|
if (y.reportWebsiteInfo && y.reportWebsiteInfo.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>网站或网店</h4>";
|
|
|
|
|
|
html += itemList(y.reportWebsiteInfo, function (w) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-meta'>" +
|
|
|
|
|
|
esc(w.websiteName) +
|
|
|
|
|
|
"(" +
|
|
|
|
|
|
esc(w.websiteType) +
|
|
|
|
|
|
") " +
|
|
|
|
|
|
esc(w.websiteUrl) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
y.reportShareholderInfo &&
|
|
|
|
|
|
y.reportShareholderInfo.length
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>股东及出资</h4>";
|
|
|
|
|
|
html += renderAnnualShareholders(
|
|
|
|
|
|
y.reportShareholderInfo,
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (y.reportInvestInfo && y.reportInvestInfo.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>年报对外投资</h4>";
|
|
|
|
|
|
html += itemList(y.reportInvestInfo, function (inv) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(inv.investName) +
|
|
|
|
|
|
"</div><div class='item-meta'>投资金额:" +
|
|
|
|
|
|
esc(inv.investCapi) +
|
|
|
|
|
|
";比例:" +
|
|
|
|
|
|
esc(inv.investPercent) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
y.investInfo &&
|
|
|
|
|
|
Array.isArray(y.investInfo) &&
|
|
|
|
|
|
y.investInfo.length
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>对外投资</h4>";
|
|
|
|
|
|
html += itemList(y.investInfo, function (inv) {
|
|
|
|
|
|
var parts = [];
|
|
|
|
|
|
if (
|
|
|
|
|
|
inv.investCapi != null &&
|
|
|
|
|
|
inv.investCapi !== ""
|
|
|
|
|
|
) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"投资金额:" + esc(inv.investCapi),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
inv.investPercent != null &&
|
|
|
|
|
|
inv.investPercent !== ""
|
|
|
|
|
|
) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"投资比例:" + esc(inv.investPercent),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
inv.investRegNo != null &&
|
|
|
|
|
|
inv.investRegNo !== ""
|
|
|
|
|
|
) {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"注册号/统一码:" +
|
|
|
|
|
|
esc(inv.investRegNo),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (inv.entityId != null && inv.entityId !== "") {
|
|
|
|
|
|
parts.push(
|
|
|
|
|
|
"主体标识:" + esc(inv.entityId),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (inv.seqNo != null && inv.seqNo !== "") {
|
|
|
|
|
|
parts.push("序号:" + esc(inv.seqNo));
|
|
|
|
|
|
}
|
|
|
|
|
|
var meta =
|
|
|
|
|
|
parts.length > 0
|
|
|
|
|
|
? parts.join(";")
|
|
|
|
|
|
: "—";
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(inv.investName || "—") +
|
|
|
|
|
|
"</div><div class='item-meta'>" +
|
|
|
|
|
|
meta +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
y.reportSocialSecurityInfo &&
|
|
|
|
|
|
typeof y.reportSocialSecurityInfo === "object" &&
|
|
|
|
|
|
!Array.isArray(y.reportSocialSecurityInfo)
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>社会保险信息</h4>";
|
|
|
|
|
|
html += kvTable(
|
|
|
|
|
|
y.reportSocialSecurityInfo,
|
|
|
|
|
|
Object.keys(
|
|
|
|
|
|
y.reportSocialSecurityInfo,
|
|
|
|
|
|
).sort(),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
y.reportGuaranteeInfo &&
|
|
|
|
|
|
y.reportGuaranteeInfo.length
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>对外担保</h4>";
|
|
|
|
|
|
html += itemList(y.reportGuaranteeInfo, function (g) {
|
|
|
|
|
|
return kvTable(g, Object.keys(g));
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
y.reportEquityChangeInfo &&
|
|
|
|
|
|
y.reportEquityChangeInfo.length
|
|
|
|
|
|
) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>股权变更</h4>";
|
|
|
|
|
|
html += itemList(
|
|
|
|
|
|
y.reportEquityChangeInfo,
|
|
|
|
|
|
function (e) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(e.name) +
|
|
|
|
|
|
"</div><div class='item-meta'>" +
|
|
|
|
|
|
esc(e.beforePercent) +
|
|
|
|
|
|
" → " +
|
|
|
|
|
|
esc(e.afterPercent) +
|
|
|
|
|
|
";" +
|
|
|
|
|
|
esc(e.changeDate) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
var ch =
|
|
|
|
|
|
y.reportChangeInfo ||
|
|
|
|
|
|
y.rpportChangeInfo;
|
|
|
|
|
|
if (ch) {
|
|
|
|
|
|
if (typeof ch === "string" && ch.trim()) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>年报变更摘要</h4><div class='item-block'>" +
|
|
|
|
|
|
esc(ch) +
|
|
|
|
|
|
"</div>";
|
|
|
|
|
|
} else if (Array.isArray(ch) && ch.length) {
|
|
|
|
|
|
html +=
|
|
|
|
|
|
"<h4 class='report-subheading'>年报修改记录</h4>";
|
|
|
|
|
|
html += itemList(ch, function (c) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(c.updateItem) +
|
|
|
|
|
|
"</div><div class='item-meta'>" +
|
|
|
|
|
|
esc(c.updateDate) +
|
|
|
|
|
|
"</div><div class='item-block' style='margin-top:4px'><strong>修改前:</strong>" +
|
|
|
|
|
|
esc(c.beforeUpdate) +
|
|
|
|
|
|
"<br/><strong>修改后:</strong>" +
|
|
|
|
|
|
esc(c.afterUpdate) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
html += "</div>";
|
|
|
|
|
|
});
|
|
|
|
|
|
return html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderTaxViolationsSection(v) {
|
|
|
|
|
|
if (!v || !Array.isArray(v.items) || !v.items.length)
|
|
|
|
|
|
return "<p class='empty-hint'>暂无税收违法记录</p>";
|
|
|
|
|
|
return itemList(v.items, function (it) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(it.entityName) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>纳税人识别号:" +
|
|
|
|
|
|
esc(it.taxpayerCode) +
|
|
|
|
|
|
";案件性质:" +
|
|
|
|
|
|
esc(it.caseType) +
|
|
|
|
|
|
";企业类别:" +
|
|
|
|
|
|
esc(it.entityCategory) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-block' style='margin-top:6px'><div><strong>违法事实:</strong>" +
|
|
|
|
|
|
esc(it.illegalFact) +
|
|
|
|
|
|
"</div><div style='margin-top:4px'><strong>处罚依据:</strong>" +
|
|
|
|
|
|
esc(it.punishBasis) +
|
|
|
|
|
|
"</div></div>" +
|
|
|
|
|
|
"<div class='item-meta'>违法期间:" +
|
|
|
|
|
|
esc(it.illegalStartDate) +
|
|
|
|
|
|
" ~ " +
|
|
|
|
|
|
esc(it.illegalEndDate) +
|
|
|
|
|
|
";公示时间:" +
|
|
|
|
|
|
esc(it.illegalTime) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>公示机关:" +
|
|
|
|
|
|
esc(it.publishDepartment) +
|
|
|
|
|
|
";检查机关:" +
|
|
|
|
|
|
esc(it.checkDepartment) +
|
|
|
|
|
|
";所属税务机关:" +
|
|
|
|
|
|
esc(it.belongDepartment) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>移送公安:" +
|
|
|
|
|
|
esc(it.police || "—") +
|
|
|
|
|
|
";中介机构:" +
|
|
|
|
|
|
esc(it.agencyPersonInfo || "—") +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderOwnTaxNotices(v) {
|
|
|
|
|
|
if (!v || !Array.isArray(v.items) || !v.items.length)
|
|
|
|
|
|
return "<p class='empty-hint'>暂无欠税公告</p>";
|
|
|
|
|
|
return itemList(v.items, function (it) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
"<div class='item-title'>" +
|
|
|
|
|
|
esc(it.taxCategory || it.taxpayerName) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>纳税人:" +
|
|
|
|
|
|
esc(it.taxpayerName) +
|
|
|
|
|
|
";识别号:" +
|
|
|
|
|
|
esc(it.taxIdNumber) +
|
|
|
|
|
|
";税务类型:" +
|
|
|
|
|
|
esc(it.taxType) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>欠税余额:" +
|
|
|
|
|
|
esc(it.ownTaxBalance) +
|
|
|
|
|
|
";欠税金额:" +
|
|
|
|
|
|
esc(it.ownTaxAmount) +
|
|
|
|
|
|
";新发欠税余额:" +
|
|
|
|
|
|
esc(it.newOwnTaxBalance) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>发布日期:" +
|
|
|
|
|
|
esc(it.publishDate) +
|
|
|
|
|
|
";主管税务机关:" +
|
|
|
|
|
|
esc(it.department) +
|
|
|
|
|
|
"</div>" +
|
|
|
|
|
|
"<div class='item-meta'>法定代表人:" +
|
|
|
|
|
|
esc(it.legalPersonName) +
|
|
|
|
|
|
";" +
|
|
|
|
|
|
esc(it.personIdName) +
|
|
|
|
|
|
":" +
|
|
|
|
|
|
esc(it.personIdNumber) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 17:49:53 +08:00
|
|
|
|
var sectionRenderers = {
|
|
|
|
|
|
riskOverview: renderRiskOverview,
|
|
|
|
|
|
basic: renderBasic,
|
|
|
|
|
|
branches: renderBranches,
|
|
|
|
|
|
shareholding: renderShareholding,
|
|
|
|
|
|
controller: renderController,
|
|
|
|
|
|
beneficiaries: renderBeneficiaries,
|
|
|
|
|
|
investments: renderInvestments,
|
|
|
|
|
|
guarantees: renderGuarantees,
|
|
|
|
|
|
management: renderManagement,
|
|
|
|
|
|
assets: renderAssets,
|
|
|
|
|
|
licenses: renderLicenses,
|
|
|
|
|
|
activities: renderActivities,
|
|
|
|
|
|
inspections: renderInspections,
|
|
|
|
|
|
risks: renderRisks,
|
|
|
|
|
|
timeline: renderTimeline,
|
|
|
|
|
|
listed: renderListed,
|
2026-03-21 19:10:50 +08:00
|
|
|
|
annualReports: renderAnnualReports,
|
|
|
|
|
|
taxViolations: renderTaxViolationsSection,
|
|
|
|
|
|
ownTaxNotices: renderOwnTaxNotices,
|
2026-03-10 17:49:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function renderSectionContent(key, value) {
|
|
|
|
|
|
var fn = sectionRenderers[key];
|
|
|
|
|
|
if (fn) return fn(value);
|
|
|
|
|
|
if (value == null)
|
|
|
|
|
|
return "<p class='empty-hint'>暂无数据</p>";
|
|
|
|
|
|
if (Array.isArray(value))
|
|
|
|
|
|
return itemList(value, function (item) {
|
|
|
|
|
|
return typeof item === "object"
|
|
|
|
|
|
? "<div class='item-block'>" +
|
|
|
|
|
|
kvTable(item, Object.keys(item)) +
|
|
|
|
|
|
"</div>"
|
|
|
|
|
|
: esc(item);
|
|
|
|
|
|
});
|
|
|
|
|
|
if (typeof value === "object")
|
|
|
|
|
|
return kvTable(value, Object.keys(value));
|
|
|
|
|
|
return "<p>" + esc(value) + "</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function render() {
|
|
|
|
|
|
var d = reportData;
|
|
|
|
|
|
document.getElementById("entName").textContent =
|
|
|
|
|
|
d.entName || "企业名称";
|
|
|
|
|
|
document.getElementById("creditCodeLabel").textContent =
|
|
|
|
|
|
"统一社会信用代码:" + (d.creditCode || "-");
|
|
|
|
|
|
document.getElementById("entStatusLabel").textContent =
|
|
|
|
|
|
"经营状态:" +
|
|
|
|
|
|
((d.basic && (d.basic.status || d.basic.entStatus)) ||
|
|
|
|
|
|
"-");
|
|
|
|
|
|
document.getElementById("entTypeLabel").textContent =
|
|
|
|
|
|
"企业类型:" + ((d.basic && d.basic.entType) || "-");
|
|
|
|
|
|
document.getElementById("reportTimeLabel").textContent =
|
|
|
|
|
|
"报告生成时间:" + (d.reportTime || "-");
|
|
|
|
|
|
// 使用 riskOverview 中的风险得分和等级替换原综合评分
|
|
|
|
|
|
var ro = d.riskOverview || {};
|
|
|
|
|
|
document.getElementById("overallScore").textContent =
|
|
|
|
|
|
ro.riskScore != null ? ro.riskScore : "-";
|
|
|
|
|
|
var level = ro.riskLevel || "-";
|
|
|
|
|
|
var pill = document.getElementById("riskLevelPill");
|
|
|
|
|
|
pill.textContent = "风险:" + level;
|
|
|
|
|
|
pill.className = "pill low";
|
|
|
|
|
|
if (level === "中") pill.classList.add("mid");
|
|
|
|
|
|
else if (level === "高") pill.classList.add("high");
|
|
|
|
|
|
var tagsBox = document.getElementById("headerTags");
|
|
|
|
|
|
tagsBox.innerHTML = "";
|
|
|
|
|
|
(ro.tags || []).forEach(function (t) {
|
|
|
|
|
|
var span = document.createElement("span");
|
|
|
|
|
|
span.className = "tag";
|
|
|
|
|
|
span.textContent = t;
|
|
|
|
|
|
tagsBox.appendChild(span);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var nav = document.getElementById("navLinks");
|
|
|
|
|
|
nav.innerHTML = "";
|
|
|
|
|
|
sectionOrder.forEach(function (key) {
|
|
|
|
|
|
if (key === "raw") return;
|
|
|
|
|
|
var a = document.createElement("a");
|
|
|
|
|
|
a.href = "#section-" + key;
|
|
|
|
|
|
a.textContent = sectionTitles[key] || key;
|
|
|
|
|
|
nav.appendChild(a);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var container = document.getElementById("reportSections");
|
|
|
|
|
|
container.innerHTML = "";
|
|
|
|
|
|
sectionOrder.forEach(function (key) {
|
|
|
|
|
|
var value = d[key];
|
|
|
|
|
|
var card = document.createElement("div");
|
|
|
|
|
|
card.className = "section-card";
|
|
|
|
|
|
card.id = "section-" + key;
|
|
|
|
|
|
var title = document.createElement("h2");
|
|
|
|
|
|
title.textContent = sectionTitles[key] || key;
|
|
|
|
|
|
card.appendChild(title);
|
|
|
|
|
|
var body = document.createElement("div");
|
|
|
|
|
|
body.className = "section-body";
|
|
|
|
|
|
body.innerHTML = renderSectionContent(key, value);
|
|
|
|
|
|
card.appendChild(body);
|
|
|
|
|
|
container.appendChild(card);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function loadReport() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 使用后端注入的 reportData 直接渲染
|
|
|
|
|
|
if (!reportData || typeof reportData !== "object") {
|
|
|
|
|
|
reportData = {
|
|
|
|
|
|
entName: "未加载到数据",
|
|
|
|
|
|
basic: {},
|
|
|
|
|
|
risks: {},
|
|
|
|
|
|
riskOverview: {},
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
render();
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error("渲染企业报告失败", e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
loadReport();
|
2026-03-10 19:12:35 +08:00
|
|
|
|
|
2026-03-21 19:10:50 +08:00
|
|
|
|
// 绑定「保存为 PDF」:先轮询预生成状态,再 GET /pdf(服务端优先读缓存,必要时现场生成)
|
2026-03-10 19:12:35 +08:00
|
|
|
|
var saveBtn = document.getElementById("btnSavePdf");
|
2026-03-11 14:13:57 +08:00
|
|
|
|
var loadingOverlay = document.getElementById("pdfLoadingOverlay");
|
2026-03-21 19:10:50 +08:00
|
|
|
|
var pdfLoadingMessage = document.getElementById("pdfLoadingMessage");
|
|
|
|
|
|
function setPdfLoadingText(t) {
|
|
|
|
|
|
if (pdfLoadingMessage) pdfLoadingMessage.textContent = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
function pollPdfStatusUntilReady(reportId, maxMs, intervalMs) {
|
|
|
|
|
|
return new Promise(function (resolve) {
|
|
|
|
|
|
var start = Date.now();
|
|
|
|
|
|
function tick() {
|
|
|
|
|
|
fetch(
|
|
|
|
|
|
"/reports/qygl/" +
|
|
|
|
|
|
encodeURIComponent(reportId) +
|
|
|
|
|
|
"/pdf/status",
|
|
|
|
|
|
)
|
|
|
|
|
|
.then(function (r) {
|
|
|
|
|
|
if (!r.ok) return { status: "error" };
|
|
|
|
|
|
return r.json();
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(function (j) {
|
|
|
|
|
|
if (!j || !j.status) {
|
|
|
|
|
|
setPdfLoadingText("正在准备 PDF…");
|
|
|
|
|
|
if (Date.now() - start >= maxMs) {
|
|
|
|
|
|
resolve("timeout");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
setTimeout(tick, intervalMs);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (j.status === "ready") {
|
|
|
|
|
|
setPdfLoadingText("正在下载…");
|
|
|
|
|
|
resolve("ready");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (j.status === "none") {
|
|
|
|
|
|
setPdfLoadingText(
|
|
|
|
|
|
j.message ||
|
|
|
|
|
|
"正在生成 PDF,请稍候…",
|
|
|
|
|
|
);
|
|
|
|
|
|
resolve("none");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (j.status === "failed") {
|
|
|
|
|
|
setPdfLoadingText(
|
|
|
|
|
|
j.message ||
|
|
|
|
|
|
"预生成未完成,正在现场生成…",
|
|
|
|
|
|
);
|
|
|
|
|
|
resolve("failed");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (j.status === "pending") {
|
|
|
|
|
|
setPdfLoadingText(
|
|
|
|
|
|
j.message || "排队生成 PDF…",
|
|
|
|
|
|
);
|
|
|
|
|
|
} else if (j.status === "generating") {
|
|
|
|
|
|
setPdfLoadingText(
|
|
|
|
|
|
j.message || "正在生成 PDF…",
|
|
|
|
|
|
);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
setPdfLoadingText("正在准备 PDF…");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (Date.now() - start >= maxMs) {
|
|
|
|
|
|
resolve("timeout");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
setTimeout(tick, intervalMs);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(function () {
|
|
|
|
|
|
resolve("error");
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
tick();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-03-11 15:21:53 +08:00
|
|
|
|
if (saveBtn) {
|
2026-03-10 19:12:35 +08:00
|
|
|
|
saveBtn.addEventListener("click", function () {
|
2026-03-11 14:13:57 +08:00
|
|
|
|
var btnText = saveBtn.textContent;
|
|
|
|
|
|
saveBtn.disabled = true;
|
|
|
|
|
|
saveBtn.textContent = "生成中...";
|
|
|
|
|
|
if (loadingOverlay) {
|
|
|
|
|
|
loadingOverlay.setAttribute("aria-hidden", "false");
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
setPdfLoadingText("正在准备 PDF…");
|
2026-03-11 14:13:57 +08:00
|
|
|
|
function restoreBtn() {
|
|
|
|
|
|
saveBtn.disabled = false;
|
|
|
|
|
|
saveBtn.textContent = btnText;
|
|
|
|
|
|
if (loadingOverlay) {
|
|
|
|
|
|
loadingOverlay.setAttribute("aria-hidden", "true");
|
2026-03-10 19:12:35 +08:00
|
|
|
|
}
|
2026-03-11 14:13:57 +08:00
|
|
|
|
}
|
2026-03-11 15:00:25 +08:00
|
|
|
|
|
2026-03-11 15:21:53 +08:00
|
|
|
|
try {
|
|
|
|
|
|
var path = window.location.pathname || "";
|
2026-03-11 15:31:36 +08:00
|
|
|
|
var segments = path.split("/");
|
|
|
|
|
|
var reportId = null;
|
|
|
|
|
|
for (var i = 0; i < segments.length; i++) {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
if (
|
|
|
|
|
|
segments[i] === "qygl" &&
|
|
|
|
|
|
i + 1 < segments.length &&
|
|
|
|
|
|
segments[i + 1]
|
|
|
|
|
|
) {
|
2026-03-11 15:31:36 +08:00
|
|
|
|
reportId = segments[i + 1];
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-21 19:23:08 +08:00
|
|
|
|
if (
|
|
|
|
|
|
!reportId &&
|
|
|
|
|
|
reportData &&
|
|
|
|
|
|
reportData.reportId &&
|
|
|
|
|
|
typeof reportData.reportId === "string"
|
|
|
|
|
|
) {
|
|
|
|
|
|
reportId = reportData.reportId;
|
|
|
|
|
|
}
|
2026-03-11 15:31:36 +08:00
|
|
|
|
if (!reportId) {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
console.error(
|
|
|
|
|
|
"无法从当前 URL 解析报告编号,路径为",
|
|
|
|
|
|
path,
|
|
|
|
|
|
);
|
2026-03-11 15:21:53 +08:00
|
|
|
|
restoreBtn();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
var pdfUrl =
|
|
|
|
|
|
"/reports/qygl/" +
|
|
|
|
|
|
encodeURIComponent(reportId) +
|
|
|
|
|
|
"/pdf";
|
2026-03-11 15:00:25 +08:00
|
|
|
|
|
2026-03-21 19:10:50 +08:00
|
|
|
|
pollPdfStatusUntilReady(
|
|
|
|
|
|
reportId,
|
|
|
|
|
|
120000,
|
|
|
|
|
|
400,
|
|
|
|
|
|
).then(function () {
|
|
|
|
|
|
return fetch(pdfUrl, { method: "GET" });
|
2026-03-11 15:21:53 +08:00
|
|
|
|
})
|
|
|
|
|
|
.then(function (resp) {
|
|
|
|
|
|
if (!resp.ok) {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
throw new Error(
|
|
|
|
|
|
"生成 PDF 接口返回错误状态:" +
|
|
|
|
|
|
resp.status,
|
|
|
|
|
|
);
|
2026-03-10 19:12:35 +08:00
|
|
|
|
}
|
2026-03-21 19:10:50 +08:00
|
|
|
|
var contentType =
|
|
|
|
|
|
resp.headers.get("Content-Type") || "";
|
2026-03-11 15:21:53 +08:00
|
|
|
|
if (
|
2026-03-21 19:10:50 +08:00
|
|
|
|
contentType.indexOf(
|
|
|
|
|
|
"application/pdf",
|
|
|
|
|
|
) === -1 &&
|
|
|
|
|
|
contentType.indexOf(
|
|
|
|
|
|
"application/octet-stream",
|
|
|
|
|
|
) === -1
|
2026-03-11 15:21:53 +08:00
|
|
|
|
) {
|
|
|
|
|
|
return resp.text().then(function (txt) {
|
2026-03-21 19:10:50 +08:00
|
|
|
|
throw new Error(
|
|
|
|
|
|
"生成 PDF 失败:" + txt,
|
|
|
|
|
|
);
|
2026-03-11 15:21:53 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
return resp.blob();
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(function (blob) {
|
|
|
|
|
|
var fileName = "企业全景报告.pdf";
|
|
|
|
|
|
if (
|
|
|
|
|
|
reportData &&
|
|
|
|
|
|
reportData.entName &&
|
|
|
|
|
|
typeof reportData.entName === "string"
|
|
|
|
|
|
) {
|
|
|
|
|
|
fileName =
|
2026-03-21 19:10:50 +08:00
|
|
|
|
reportData.entName +
|
|
|
|
|
|
"_企业全景报告.pdf";
|
2026-03-11 15:21:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
var url = window.URL.createObjectURL(blob);
|
|
|
|
|
|
var a = document.createElement("a");
|
|
|
|
|
|
a.href = url;
|
|
|
|
|
|
a.download = fileName;
|
|
|
|
|
|
document.body.appendChild(a);
|
|
|
|
|
|
a.click();
|
|
|
|
|
|
document.body.removeChild(a);
|
|
|
|
|
|
window.URL.revokeObjectURL(url);
|
|
|
|
|
|
restoreBtn();
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(function (e) {
|
|
|
|
|
|
console.error("生成 PDF 失败(后端接口)", e);
|
|
|
|
|
|
restoreBtn();
|
|
|
|
|
|
alert("生成 PDF 失败,请稍后重试");
|
2026-03-10 19:12:35 +08:00
|
|
|
|
});
|
2026-03-11 15:21:53 +08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error("触发生成 PDF 失败", e);
|
|
|
|
|
|
restoreBtn();
|
2026-03-10 19:12:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-03-10 17:49:53 +08:00
|
|
|
|
})();
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|