Files

855 lines
18 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>x-data-spreadsheet</title>
<style>
body { margin:0; padding:20px; font-family:Arial,sans-serif; background-color:#f5f5f5; }
.layout { display:flex; gap:20px; align-items:flex-start; }
.main { flex:1 1 auto; min-width:0; }
#xspreadsheet { width:100%; height:calc(100vh - 140px); min-height:600px; box-shadow:0 2px 10px rgba(0,0,0,0.1); background-color:white; }
.toc-sidebar {
flex: 0 0 200px;
position: sticky;
top: 20px;
max-height: calc(100vh - 40px);
overflow-y: auto;
background: #ffffff;
border-radius: 6px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
padding: 12px 0;
box-sizing: border-box;
}
.toc-sidebar h3 {
margin: 0 14px 8px 0;
font-size: 12px;
font-weight: 600;
color: #333;
border-bottom: 1px solid #eee;
padding: 0 14px 8px;
letter-spacing: 0.5px;
text-transform: uppercase;
}
.toc-sheet-group { margin-bottom: 10px; }
.toc-sheet-name {
font-size: 11px;
color: #999;
margin: 4px 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.toc-list { list-style: none; padding: 0; margin: 0; }
.toc-list li { margin: 0; }
.toc-link {
display: block;
padding: 5px 14px;
color: #555;
text-decoration: none;
font-size: 12.5px;
line-height: 1.5;
cursor: pointer;
border-left: 2px solid transparent;
transition: background 0.12s, color 0.12s, border-color 0.12s;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.toc-link:hover { background: #f0f7ff; color: #1677ff; }
.toc-link.active {
background: #e6f4ff;
color: #1677ff;
border-left-color: #1677ff;
font-weight: 600;
}
.toc-empty { font-size: 12px; color: #999; padding: 8px 14px; }
</style>
<link rel="stylesheet" href="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.css">
</head>
<body>
<h1>x-data-spreadsheet</h1>
<div class="layout">
<div class="main">
<div id="xspreadsheet"></div>
</div>
<aside class="toc-sidebar">
<h3>目录</h3>
<div id="toc-container"></div>
</aside>
</div>
<script src="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.js"></script>
<script>
const rawData = {
"name": "Table_0",
"rows": {
"0": {
"cells": {
"19": {
"text": "PD4.2.2",
"merge": [
0,
2
]
}
}
},
"1": {
"cells": {
"0": {
"text": "基本要求",
"merge": [
0,
1
]
},
"2": {
"text": "01.在路基用地和取土坑范国内,己清除地表植被、杂物、积水、淤泥和表土,处理坑塘,并按施工技术规范和设计要求对基底进行压实.表土己充分利用.口2.坝方路基分层坝筑压实,每层表面平整,路拱合适,排水良好,无明显碾压轮迹,无亏坡.口3.己设置施工临时排水系统,避免冲刷边坡,路床顶面无积水.4.在设定取土区内合理取土,无溢开滥挖.完工后己按要求对取土坑和奔土场进行依整.",
"merge": [
0,
19
]
}
}
},
"2": {
"cells": {
"1": {
"text": "项次",
"merge": [
1,
0
]
},
"2": {
"text": "检查项目",
"merge": [
1,
3
]
},
"6": {
"text": "规定值或允许偏差",
"merge": [
0,
2
]
},
"9": {
"text": "实测值或实测差值",
"merge": [
0,
9
]
},
"19": {
"text": "质量评定",
"merge": [
0,
2
]
}
}
},
"3": {
"cells": {
"6": {
"text": "商速公路一级公路"
},
"7": {
"text": "二级公路"
},
"8": {
"text": "三、四级公路"
},
"9": {
"text": "1"
},
"10": {
"text": "2"
},
"11": {
"text": "3"
},
"12": {
"text": "4"
},
"13": {
"text": "5"
},
"14": {
"text": "6"
},
"15": {
"text": "7"
},
"16": {
"text": "8"
},
"17": {
"text": "9"
},
"18": {
"text": "10"
},
"19": {
"text": "平均值、代表值"
},
"20": {
"text": "合格率(%)"
},
"21": {
"text": "合格判定"
}
}
},
"4": {
"cells": {
"1": {
"text": "1A",
"merge": [
6,
0
]
},
"2": {
"text": "医卖医卖",
"merge": [
6,
0
]
},
"3": {
"text": "上路床",
"merge": [
0,
1
]
},
"5": {
"text": "0~0.3m"
},
"6": {
"text": "≥96"
},
"7": {
"text": "≥95"
},
"8": {
"text": "≥94"
}
}
},
"5": {
"cells": {
"3": {
"text": "下路床",
"merge": [
1,
0
]
},
"4": {
"text": "经、中及交通荷载等级"
},
"5": {
"text": "0.3m~0.8m"
},
"6": {
"text": "96"
},
"7": {
"text": "≥95"
},
"8": {
"text": "≥94"
},
"9": {
"merge": [
0,
9
]
}
}
},
"6": {
"cells": {
"4": {
"text": "特重、极重交通荷载等级"
},
"5": {
"text": "0.3m~1.2m"
},
"6": {
"text": "296"
},
"7": {
"text": "≥95"
},
"8": {
"text": "-"
}
}
},
"7": {
"cells": {
"3": {
"text": "上路提",
"merge": [
1,
0
]
},
"4": {
"text": "轻、中及重交通荷载等级"
},
"5": {
"text": "0.8m~1.5m"
},
"6": {
"text": "≥94"
},
"7": {
"text": "≥94"
},
"8": {
"text": "≥93"
}
}
},
"8": {
"cells": {
"4": {
"text": "特薰、极薰交通荷载等级"
},
"5": {
"text": "1.2m~1.9m"
},
"6": {
"text": "≥94"
},
"7": {
"text": "≥94"
},
"8": {
"text": "-"
}
}
},
"9": {
"cells": {
"3": {
"text": "下路提",
"merge": [
1,
0
]
},
"4": {
"text": "轻、中及交通荷载等级"
},
"5": {
"text": "≥1.5m"
},
"6": {
"text": "≥93",
"merge": [
1,
0
]
},
"7": {
"text": "≥92",
"merge": [
1,
0
]
},
"8": {
"text": "≥90",
"merge": [
1,
0
]
}
}
},
"10": {
"cells": {
"4": {
"text": "特、极薰交通荷载等级"
},
"5": {
"text": "≥1.9m"
}
}
},
"11": {
"cells": {
"1": {
"text": "2A"
},
"2": {
"text": "弯沉(0.01mm)",
"merge": [
0,
3
]
},
"6": {
"text": "≤设计验收弯沉值",
"merge": [
0,
2
]
},
"9": {
"merge": [
0,
9
]
}
}
},
"12": {
"cells": {
"1": {
"text": "3"
},
"2": {
"text": "纵断商程(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "+10-15"
},
"7": {
"text": "+10.-20",
"merge": [
0,
1
]
}
}
},
"13": {
"cells": {
"1": {
"text": "4"
},
"2": {
"text": "中线偏位(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "50"
},
"7": {
"text": "100",
"merge": [
0,
1
]
}
}
},
"14": {
"cells": {
"1": {
"text": "5"
},
"2": {
"text": "宽度(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "满足设计要求",
"merge": [
0,
2
]
}
}
},
"15": {
"cells": {
"1": {
"text": "6"
},
"2": {
"text": "平整度(mm)",
"merge": [
0,
3
]
},
"6": {
"text": "415"
},
"7": {
"text": "520",
"merge": [
0,
1
]
}
}
},
"16": {
"cells": {
"1": {
"text": "7"
},
"2": {
"text": "横坡(%)",
"merge": [
0,
3
]
},
"6": {
"text": "±0.3"
},
"7": {
"text": "±0.5",
"merge": [
0,
1
]
}
}
},
"17": {
"cells": {
"1": {
"text": "8"
},
"2": {
"text": "边坡",
"merge": [
0,
3
]
},
"6": {
"text": "满足设计要求",
"merge": [
0,
2
]
}
}
},
"18": {
"cells": {
"0": {
"text": "外观质量",
"merge": [
0,
5
]
},
"6": {
"text": "01.路基边线与边坡未出现单向累计长度超过50m的弯折.口2.路基边坡、护坡道、碎离台无滑坡、爆方或深度超过100mm的冲沟.",
"merge": [
0,
8
]
},
"15": {
"text": "质量保证资料",
"merge": [
0,
3
]
}
}
},
"19": {
"cells": {
"0": {
"text": "工程质量等级评定",
"merge": [
0,
5
]
},
"6": {
"text": "口合格口不合格",
"merge": [
0,
13
]
}
}
},
"len": 20
},
"merges": [
"P19:S19",
"C17:F17",
"G19:O19",
"B3:B4",
"J12:S12",
"G18:I18",
"G3:I3",
"J3:S3",
"G10:G11",
"G15:I15",
"C13:F13",
"B5:B11",
"C18:F18",
"T1:V1",
"C15:F15",
"A20:F20",
"C14:F14",
"H17:I17",
"A2:B2",
"H16:I16",
"A19:F19",
"D8:D9",
"C16:F16",
"T3:V3",
"G12:I12",
"C2:V2",
"H13:I13",
"I10:I11",
"J6:S6",
"C5:C11",
"D10:D11",
"C3:F4",
"G20:T20",
"C12:F12",
"D5:E5",
"H14:I14",
"D6:D7",
"H10:H11"
],
"cols": {
"0": {
"width": 120
},
"1": {
"width": 120
},
"2": {
"width": 120
},
"3": {
"width": 120
},
"4": {
"width": 120
},
"5": {
"width": 120
},
"6": {
"width": 120
},
"7": {
"width": 120
},
"8": {
"width": 120
},
"9": {
"width": 120
},
"10": {
"width": 120
},
"11": {
"width": 120
},
"12": {
"width": 120
},
"13": {
"width": 120
},
"14": {
"width": 120
},
"15": {
"width": 120
},
"16": {
"width": 120
},
"17": {
"width": 120
},
"18": {
"width": 120
},
"19": {
"width": 120
},
"20": {
"width": 120
},
"21": {
"width": 120
}
}
};
// Normalize: x_spreadsheet.loadData accepts an array of sheets or a single sheet
const sheets = Array.isArray(rawData) ? rawData : [rawData];
// ---- TOC builder ----
function cellText(row, col) {
if (!row || !row.cells) return null;
const c = row.cells[col];
if (!c) return null;
return (c.text || '').trim() || null;
}
function extractToc(sheet) {
const items = [];
const rows = sheet.rows || {};
const len = rows.len || 0;
const seen = new Set();
for (let i = 0; i < len; i++) {
const r = rows[i];
if (!r || !r.cells) continue;
const c0 = cellText(r, 0);
const c1 = cellText(r, 1);
const c2 = cellText(r, 2);
// 1) Top-level labels in column 0 (基本要求 / 外观质量 / 工程质量等级评定 / ...)
if (c0 && !seen.has('c0:' + c0)) {
items.push({ label: c0, row: i });
seen.add('c0:' + c0);
continue;
}
// 2) Numbered items in column 1 (项次: 1A, 2A, 3, 4, 5, 6, 7, 8, ...)
if (c1 && /^[0-9]+[A-Za-z]?$/.test(c1)) {
const label = c1 + (c2 ? ' ' + c2 : '');
if (!seen.has('c1:' + c1)) {
items.push({ label, row: i });
seen.add('c1:' + c1);
}
continue;
}
}
return items;
}
function renderToc(sheets) {
const container = document.getElementById('toc-container');
container.innerHTML = '';
let hasAny = false;
sheets.forEach((sheet, sheetIdx) => {
const items = extractToc(sheet);
if (!items.length && sheets.length === 1) return;
hasAny = true;
const group = document.createElement('div');
group.className = 'toc-sheet-group';
if (sheets.length > 1) {
const name = document.createElement('div');
name.className = 'toc-sheet-name';
name.textContent = sheet.name || ('Sheet ' + (sheetIdx + 1));
group.appendChild(name);
}
const ul = document.createElement('ul');
ul.className = 'toc-list';
items.forEach(item => {
const li = document.createElement('li');
const a = document.createElement('a');
a.className = 'toc-link';
a.href = 'javascript:void(0)';
a.dataset.sheet = sheetIdx;
a.dataset.row = item.row;
a.title = item.label + ' (row ' + item.row + ')';
a.innerHTML = item.label + '<span class="row-tag" style="color:#bbb;font-size:10.5px;margin-left:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;">·' + item.row + '</span>';
a.addEventListener('click', () => scrollToRow(sheetIdx, item.row, a));
li.appendChild(a);
ul.appendChild(li);
});
group.appendChild(ul);
container.appendChild(group);
});
if (!hasAny) {
const empty = document.createElement('div');
empty.className = 'toc-empty';
empty.textContent = '(未识别到目录项)';
container.appendChild(empty);
}
}
// ---- Scroll handling ----
// x-data-spreadsheet renders the grid on a canvas; rows are NOT in the DOM.
// We scroll by setting the vertical scrollbar's scrollTop, which fires
// the library's internal moveFn -> scrolly() -> re-render.
let __ssRef = null; // populated after load
function getSheetData(sheetIdx) {
if (!__ssRef) return null;
// spreadsheet.datas[] holds the pt instances; .data is shorthand for datas[0]
if (Array.isArray(__ssRef.datas) && __ssRef.datas[sheetIdx]) return __ssRef.datas[sheetIdx];
if (sheetIdx === 0 && __ssRef.data) return __ssRef.data;
return null;
}
function scrollToRow(sheetIdx, rowIndex, linkEl) {
if (!__ssRef) return;
// Mark active
document.querySelectorAll('.toc-link.active').forEach(el => el.classList.remove('active'));
if (linkEl) linkEl.classList.add('active');
try {
const liveData = getSheetData(sheetIdx);
if (!liveData || !liveData.rows || typeof liveData.rows.sumHeight !== 'function') {
console.warn('No live sheet data for index', sheetIdx);
return;
}
const y = liveData.rows.sumHeight(0, rowIndex);
const vbar = __ssRef.sheet && __ssRef.sheet.verticalScrollbar;
if (vbar && vbar.el && vbar.el[0]) {
vbar.el[0].scrollTop = y;
}
} catch (e) {
console.warn('scrollToRow failed:', e);
}
}
// ---- Init ----
document.addEventListener('DOMContentLoaded', function () {
if (typeof x_spreadsheet === 'undefined') {
document.body.innerHTML += '<p style="color:red;margin-top:10px;">Error: x-spreadsheet library failed to load. Check internet connection.</p>';
return;
}
try {
const spreadsheet = x_spreadsheet('#xspreadsheet');
spreadsheet.loadData(sheets);
__ssRef = spreadsheet;
renderToc(sheets);
} catch (e) {
console.error('Error:', e);
document.body.innerHTML += '<p style="color:red;margin-top:10px;">Error: ' + e.message + '</p>';
}
});
</script>
</body>
</html>