@@ -0,0 +1,302 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
<title>四等水准测量记录表</title>
|
||||||
|
<style>
|
||||||
|
:root{--border:#222;--thin:#555;--bg:#f6f7fb;--blue:#1f6feb;--red:#d1242f}
|
||||||
|
*{box-sizing:border-box}
|
||||||
|
body{margin:0;padding:18px;background:var(--bg);font-family:"Microsoft YaHei",SimSun,Arial,sans-serif;color:#111}
|
||||||
|
.toolbar{position:sticky;top:0;z-index:10;background:#fff;border:1px solid #ddd;border-radius:10px;padding:10px;margin-bottom:12px;box-shadow:0 2px 10px #0001;display:flex;gap:8px;flex-wrap:wrap;align-items:center}
|
||||||
|
button,.file-label{border:1px solid #bbb;background:#fff;border-radius:7px;padding:7px 10px;cursor:pointer;font-size:14px}
|
||||||
|
button.primary{background:var(--blue);border-color:var(--blue);color:#fff}
|
||||||
|
button.danger{color:var(--red);border-color:#e6b8bd}
|
||||||
|
button:hover,.file-label:hover{filter:brightness(.97)}
|
||||||
|
input[type=file]{display:none}
|
||||||
|
.tip{font-size:13px;color:#555;margin-left:auto}
|
||||||
|
.page{width:1120px;max-width:100%;margin:auto;background:#fff;padding:18px 18px 28px;border:1px solid #ddd;box-shadow:0 2px 16px #0001}
|
||||||
|
.meta{display:grid;grid-template-columns:1fr 1fr 2fr;gap:16px;margin:0 0 8px;font-size:15px;align-items:end}
|
||||||
|
.meta input{border:none;border-bottom:1px solid #777;outline:none;padding:3px 6px;font-size:15px;width:190px}
|
||||||
|
h1{text-align:center;font-size:22px;letter-spacing:2px;margin:0 0 10px}
|
||||||
|
table{width:100%;border-collapse:collapse;table-layout:fixed;background:#fff}
|
||||||
|
th,td{border:1px solid var(--border);text-align:center;vertical-align:middle;padding:0;height:30px;font-size:13px;line-height:1.15}
|
||||||
|
th{font-weight:600;background:#fafafa}
|
||||||
|
.thin td,.thin th{border-color:var(--thin)}
|
||||||
|
input,select{width:100%;height:100%;border:none;outline:none;text-align:center;font:inherit;background:transparent;padding:3px}
|
||||||
|
input.calc{background:#f8fbff;color:#0b5cab;font-weight:600}
|
||||||
|
input.warn{background:#fff3cd;color:#8a5a00}
|
||||||
|
.v{writing-mode:vertical-rl;text-orientation:upright;letter-spacing:2px}
|
||||||
|
.narrow{font-size:12px}
|
||||||
|
.station-start td{border-top-width:2px}
|
||||||
|
.group-end td{border-bottom-width:2px}
|
||||||
|
.dircell{display:flex;align-items:center;height:100%}
|
||||||
|
.dir-fixed{min-width:34px;border-right:1px solid #ccc;height:100%;display:flex;align-items:center;justify-content:center;background:#fbfbfb;font-weight:600}
|
||||||
|
.dircell input{text-align:left;padding-left:6px}
|
||||||
|
.right-note{width:84px}
|
||||||
|
.summary{margin-top:10px;display:grid;grid-template-columns:repeat(5,1fr);gap:8px;font-size:14px}
|
||||||
|
.box{border:1px solid #ccc;border-radius:8px;padding:8px;background:#fafafa}
|
||||||
|
.box b{display:block;margin-bottom:4px}
|
||||||
|
@media print{body{background:#fff;padding:0}.toolbar{display:none}.page{box-shadow:none;border:none;width:100%;padding:10mm}button{display:none}th,td{height:25px;font-size:11px}.summary{page-break-inside:avoid}}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="toolbar">
|
||||||
|
<button class="primary" onclick="addStation()">+新增一个测站</button>
|
||||||
|
<button onclick="addStations(5)">+新增5个测站</button>
|
||||||
|
<button onclick="exportJSON()">导出JSON</button>
|
||||||
|
<button onclick="exportCSV()">导出CSV</button>
|
||||||
|
<label class="file-label" for="importFile">导入JSON/CSV</label><input id="importFile" type="file" accept=".json,.csv,text/csv,application/json" onchange="importFile(event)">
|
||||||
|
<button onclick="window.print()">打印/另存PDF</button>
|
||||||
|
<button class="danger" onclick="clearAll()">清空</button>
|
||||||
|
<span class="tip">输入上下丝、黑面、红面、K值后自动计算;“后/前/后-前”后面的文字可直接填写。</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page">
|
||||||
|
<div class="meta">
|
||||||
|
<div>观测员:<input id="observer" /></div>
|
||||||
|
<div>记录员:<input id="recorder" /></div>
|
||||||
|
<h1>四等水准测量记录表</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table id="recordTable">
|
||||||
|
<colgroup>
|
||||||
|
<col style="width:42px"><col style="width:46px">
|
||||||
|
<col style="width:88px"><col style="width:88px"><col style="width:82px">
|
||||||
|
<col style="width:88px"><col style="width:88px"><col style="width:82px">
|
||||||
|
<col style="width:98px"><col style="width:84px"><col style="width:84px"><col style="width:86px"><col style="width:96px"><col style="width:82px">
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th rowspan="3" class="v">测站编号</th>
|
||||||
|
<th rowspan="3" class="v">转点</th>
|
||||||
|
<th colspan="3">后尺</th>
|
||||||
|
<th colspan="3">前尺</th>
|
||||||
|
<th rowspan="3">方向及<br>尺号</th>
|
||||||
|
<th colspan="2">标尺读数<br>(m)</th>
|
||||||
|
<th rowspan="3">黑+K-红<br>(mm)</th>
|
||||||
|
<th rowspan="3">高差中数<br>h(m)</th>
|
||||||
|
<th rowspan="3">备注</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>上丝</th><th>下丝</th><th>视距d(m)</th>
|
||||||
|
<th>上丝</th><th>下丝</th><th>视距d(m)</th>
|
||||||
|
<th>黑面</th><th>红面</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th colspan="3" class="narrow">自动:d =(上丝-下丝)×100</th>
|
||||||
|
<th colspan="3" class="narrow">后-前视距差自动计算</th>
|
||||||
|
<th colspan="2" class="narrow">可输入至 0.001 m</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody"></tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="summary">
|
||||||
|
<div class="box"><b>测站数</b><span id="sumStations">0</span></div>
|
||||||
|
<div class="box"><b>Σ后视距(m)</b><span id="sumBackD">0.00</span></div>
|
||||||
|
<div class="box"><b>Σ前视距(m)</b><span id="sumFrontD">0.00</span></div>
|
||||||
|
<div class="box"><b>Σ视距差(m)</b><span id="sumDiffD">0.00</span></div>
|
||||||
|
<div class="box"><b>Σ高差中数(m)</b><span id="sumH">0.0000</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const tbody = document.getElementById('tbody');
|
||||||
|
let stationCount = 0;
|
||||||
|
|
||||||
|
function n(v){ const x = parseFloat(String(v).trim()); return Number.isFinite(x) ? x : null; }
|
||||||
|
function fmt(v, d=3){ return Number.isFinite(v) ? v.toFixed(d) : ''; }
|
||||||
|
function mm(v){ return Number.isFinite(v) ? Math.round(v).toString() : ''; }
|
||||||
|
function q(root, sel){ return root.querySelector(sel); }
|
||||||
|
|
||||||
|
function input(cls='', extra=''){
|
||||||
|
return `<input class="${cls}" ${extra} oninput="recalc()">`;
|
||||||
|
}
|
||||||
|
function calcInput(cls=''){
|
||||||
|
return `<input class="calc ${cls}" readonly>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addStation(data={}){
|
||||||
|
stationCount++;
|
||||||
|
const sid = 'S' + Date.now() + '_' + Math.random().toString(16).slice(2);
|
||||||
|
const tr1 = document.createElement('tr');
|
||||||
|
const tr2 = document.createElement('tr');
|
||||||
|
const tr3 = document.createElement('tr');
|
||||||
|
tr1.className = 'station station-start'; tr2.className = 'station'; tr3.className = 'station group-end';
|
||||||
|
[tr1,tr2,tr3].forEach(tr => tr.dataset.sid = sid);
|
||||||
|
|
||||||
|
tr1.innerHTML = `
|
||||||
|
<td rowspan="3"><input class="stationNo" value="${data.stationNo ?? stationCount}" oninput="recalc()"></td>
|
||||||
|
<td rowspan="3"><input class="turnPoint" value="${data.turnPoint ?? ''}" oninput="recalc()"></td>
|
||||||
|
<td>${input('backUpper', `value="${data.backUpper ?? ''}"`)}</td>
|
||||||
|
<td>${input('backLower', `value="${data.backLower ?? ''}"`)}</td>
|
||||||
|
<td>${calcInput('backD')}</td>
|
||||||
|
<td>${input('frontUpper', `value="${data.frontUpper ?? ''}"`)}</td>
|
||||||
|
<td>${input('frontLower', `value="${data.frontLower ?? ''}"`)}</td>
|
||||||
|
<td>${calcInput('frontD')}</td>
|
||||||
|
<td><div class="dircell"><span class="dir-fixed">后</span><input class="dirBack" value="${data.dirBack ?? ''}" placeholder="尺号/说明"></div></td>
|
||||||
|
<td>${input('backBlack', `value="${data.backBlack ?? ''}"`)}</td>
|
||||||
|
<td>${input('backRed', `value="${data.backRed ?? ''}"`)}</td>
|
||||||
|
<td>${input('kBack', `value="${data.kBack ?? ''}" placeholder="K")}</td>
|
||||||
|
<td rowspan="3">${calcInput('hAvg')}</td>
|
||||||
|
<td rowspan="3"><input class="note" value="${data.note ?? ''}" oninput="recalc()"></td>`;
|
||||||
|
|
||||||
|
tr2.innerHTML = `
|
||||||
|
<td colspan="3" class="narrow">后视距自动</td>
|
||||||
|
<td colspan="3" class="narrow">前视距自动</td>
|
||||||
|
<td><div class="dircell"><span class="dir-fixed">前</span><input class="dirFront" value="${data.dirFront ?? ''}" placeholder="尺号/说明"></div></td>
|
||||||
|
<td>${input('frontBlack', `value="${data.frontBlack ?? ''}"`)}</td>
|
||||||
|
<td>${input('frontRed', `value="${data.frontRed ?? ''}"`)}</td>
|
||||||
|
<td>${input('kFront', `value="${data.kFront ?? ''}" placeholder="K")}</td>`;
|
||||||
|
|
||||||
|
tr3.innerHTML = `
|
||||||
|
<td colspan="2" class="narrow">视距差</td>
|
||||||
|
<td>${calcInput('diffD')}</td>
|
||||||
|
<td colspan="2" class="narrow">累计视距差</td>
|
||||||
|
<td>${calcInput('cumDiffD')}</td>
|
||||||
|
<td><div class="dircell"><span class="dir-fixed">后-前</span><input class="dirDiff" value="${data.dirDiff ?? ''}" placeholder="可写说明"></div></td>
|
||||||
|
<td>${calcInput('hBlack')}</td>
|
||||||
|
<td>${calcInput('hRed')}</td>
|
||||||
|
<td>${calcInput('checkDiff')}</td>`;
|
||||||
|
|
||||||
|
tbody.append(tr1,tr2,tr3);
|
||||||
|
recalc();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addStations(k){ for(let i=0;i<k;i++) addStation(); }
|
||||||
|
function stationGroups(){
|
||||||
|
const rows = [...tbody.querySelectorAll('tr.station-start')];
|
||||||
|
return rows.map(start => {
|
||||||
|
const sid = start.dataset.sid;
|
||||||
|
const all = [...tbody.querySelectorAll(`tr[data-sid="${sid}"]`)];
|
||||||
|
return {sid, rows: all, r1: all[0], r2: all[1], r3: all[2]};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function recalc(){
|
||||||
|
let cumDiff = 0, sumBackD=0, sumFrontD=0, sumH=0, validH=0;
|
||||||
|
for (const g of stationGroups()){
|
||||||
|
const bu=n(q(g.r1,'.backUpper')?.value), bl=n(q(g.r1,'.backLower')?.value);
|
||||||
|
const fu=n(q(g.r1,'.frontUpper')?.value), fl=n(q(g.r1,'.frontLower')?.value);
|
||||||
|
const backD = (bu!==null && bl!==null) ? (bu-bl)*100 : null;
|
||||||
|
const frontD = (fu!==null && fl!==null) ? (fu-fl)*100 : null;
|
||||||
|
q(g.r1,'.backD').value = fmt(backD,2);
|
||||||
|
q(g.r1,'.frontD').value = fmt(frontD,2);
|
||||||
|
if(backD!==null) sumBackD += backD;
|
||||||
|
if(frontD!==null) sumFrontD += frontD;
|
||||||
|
|
||||||
|
const diffD = (backD!==null && frontD!==null) ? backD-frontD : null;
|
||||||
|
if(diffD!==null) cumDiff += diffD;
|
||||||
|
q(g.r3,'.diffD').value = fmt(diffD,2);
|
||||||
|
q(g.r3,'.cumDiffD').value = fmt(cumDiff,2);
|
||||||
|
|
||||||
|
const bb=n(q(g.r1,'.backBlack')?.value), br=n(q(g.r1,'.backRed')?.value), kb=n(q(g.r1,'.kBack')?.value);
|
||||||
|
const fb=n(q(g.r2,'.frontBlack')?.value), fr=n(q(g.r2,'.frontRed')?.value), kf=n(q(g.r2,'.kFront')?.value);
|
||||||
|
|
||||||
|
// 单尺校核:黑面读数 + K - 红面读数,K通常填mm;黑/红读数填m。
|
||||||
|
const backCheck = (bb!==null && br!==null && kb!==null) ? (bb*1000 + kb - br*1000) : null;
|
||||||
|
const frontCheck = (fb!==null && fr!==null && kf!==null) ? (fb*1000 + kf - fr*1000) : null;
|
||||||
|
q(g.r1,'.kBack').classList.toggle('warn', backCheck!==null && Math.abs(backCheck)>3);
|
||||||
|
q(g.r2,'.kFront').classList.toggle('warn', frontCheck!==null && Math.abs(frontCheck)>3);
|
||||||
|
// 为节省版面,K列输入框仍保留K值;后-前行显示两尺校核差。
|
||||||
|
|
||||||
|
const hBlack = (bb!==null && fb!==null) ? bb - fb : null;
|
||||||
|
const hRed = (br!==null && fr!==null && kb!==null && kf!==null) ? (br - fr + (kf-kb)/1000) : null;
|
||||||
|
const hAvg = (hBlack!==null && hRed!==null) ? (hBlack + hRed)/2 : (hBlack!==null ? hBlack : null);
|
||||||
|
const checkDiff = (hBlack!==null && hRed!==null) ? (hBlack-hRed)*1000 : null;
|
||||||
|
q(g.r3,'.hBlack').value = fmt(hBlack,4);
|
||||||
|
q(g.r3,'.hRed').value = fmt(hRed,4);
|
||||||
|
q(g.r3,'.checkDiff').value = mm(checkDiff);
|
||||||
|
q(g.r1,'.hAvg').value = fmt(hAvg,4);
|
||||||
|
if(hAvg!==null){ sumH += hAvg; validH++; }
|
||||||
|
}
|
||||||
|
document.getElementById('sumStations').textContent = stationGroups().length;
|
||||||
|
document.getElementById('sumBackD').textContent = sumBackD.toFixed(2);
|
||||||
|
document.getElementById('sumFrontD').textContent = sumFrontD.toFixed(2);
|
||||||
|
document.getElementById('sumDiffD').textContent = (sumBackD-sumFrontD).toFixed(2);
|
||||||
|
document.getElementById('sumH').textContent = sumH.toFixed(4);
|
||||||
|
saveLocal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function collect(){
|
||||||
|
return {
|
||||||
|
observer: document.getElementById('observer').value,
|
||||||
|
recorder: document.getElementById('recorder').value,
|
||||||
|
stations: stationGroups().map(g => ({
|
||||||
|
stationNo:q(g.r1,'.stationNo').value, turnPoint:q(g.r1,'.turnPoint').value,
|
||||||
|
backUpper:q(g.r1,'.backUpper').value, backLower:q(g.r1,'.backLower').value,
|
||||||
|
frontUpper:q(g.r1,'.frontUpper').value, frontLower:q(g.r1,'.frontLower').value,
|
||||||
|
dirBack:q(g.r1,'.dirBack').value, dirFront:q(g.r2,'.dirFront').value, dirDiff:q(g.r3,'.dirDiff').value,
|
||||||
|
backBlack:q(g.r1,'.backBlack').value, backRed:q(g.r1,'.backRed').value, kBack:q(g.r1,'.kBack').value,
|
||||||
|
frontBlack:q(g.r2,'.frontBlack').value, frontRed:q(g.r2,'.frontRed').value, kFront:q(g.r2,'.kFront').value,
|
||||||
|
note:q(g.r1,'.note').value
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function load(data){
|
||||||
|
tbody.innerHTML=''; stationCount=0;
|
||||||
|
document.getElementById('observer').value = data.observer ?? '';
|
||||||
|
document.getElementById('recorder').value = data.recorder ?? '';
|
||||||
|
(data.stations && data.stations.length ? data.stations : Array.from({length:8},()=>({}))).forEach(addStation);
|
||||||
|
recalc();
|
||||||
|
}
|
||||||
|
function download(name, text, type){
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = URL.createObjectURL(new Blob([text],{type})); a.download = name; a.click(); URL.revokeObjectURL(a.href);
|
||||||
|
}
|
||||||
|
function exportJSON(){ download('四等水准测量记录表.json', JSON.stringify(collect(),null,2), 'application/json;charset=utf-8'); }
|
||||||
|
function exportCSV(){
|
||||||
|
const rows = [['测站编号','转点','后上丝','后下丝','后视距','前上丝','前下丝','前视距','后尺号说明','前尺号说明','后-前说明','后黑','后红','后K','前黑','前红','前K','黑面高差','红面高差','高差中数','备注']];
|
||||||
|
for(const g of stationGroups()) rows.push([
|
||||||
|
q(g.r1,'.stationNo').value,q(g.r1,'.turnPoint').value,q(g.r1,'.backUpper').value,q(g.r1,'.backLower').value,q(g.r1,'.backD').value,
|
||||||
|
q(g.r1,'.frontUpper').value,q(g.r1,'.frontLower').value,q(g.r1,'.frontD').value,q(g.r1,'.dirBack').value,q(g.r2,'.dirFront').value,q(g.r3,'.dirDiff').value,
|
||||||
|
q(g.r1,'.backBlack').value,q(g.r1,'.backRed').value,q(g.r1,'.kBack').value,q(g.r2,'.frontBlack').value,q(g.r2,'.frontRed').value,q(g.r2,'.kFront').value,
|
||||||
|
q(g.r3,'.hBlack').value,q(g.r3,'.hRed').value,q(g.r1,'.hAvg').value,q(g.r1,'.note').value
|
||||||
|
]);
|
||||||
|
const csv = rows.map(r => r.map(v => '"'+String(v??'').replaceAll('"','""')+'"').join(',')).join('\n');
|
||||||
|
download('四等水准测量记录表.csv', '\ufeff'+csv, 'text/csv;charset=utf-8');
|
||||||
|
}
|
||||||
|
async function importFile(e){
|
||||||
|
const file = e.target.files[0]; if(!file) return;
|
||||||
|
const text = await file.text();
|
||||||
|
try{
|
||||||
|
if(file.name.toLowerCase().endsWith('.json')) load(JSON.parse(text));
|
||||||
|
else importCSV(text);
|
||||||
|
}catch(err){ alert('导入失败:' + err.message); }
|
||||||
|
e.target.value='';
|
||||||
|
}
|
||||||
|
function parseCSVLine(line){
|
||||||
|
const out=[]; let cur='', inQ=false;
|
||||||
|
for(let i=0;i<line.length;i++){
|
||||||
|
const c=line[i];
|
||||||
|
if(c==='"' && line[i+1]==='"'){cur+='"'; i++;}
|
||||||
|
else if(c==='"') inQ=!inQ;
|
||||||
|
else if(c===',' && !inQ){out.push(cur); cur='';}
|
||||||
|
else cur+=c;
|
||||||
|
}
|
||||||
|
out.push(cur); return out;
|
||||||
|
}
|
||||||
|
function importCSV(text){
|
||||||
|
const lines = text.replace(/^\ufeff/,'').split(/\r?\n/).filter(Boolean);
|
||||||
|
const data={observer:'',recorder:'',stations:[]};
|
||||||
|
for(const line of lines.slice(1)){
|
||||||
|
const r=parseCSVLine(line);
|
||||||
|
data.stations.push({stationNo:r[0],turnPoint:r[1],backUpper:r[2],backLower:r[3],frontUpper:r[5],frontLower:r[6],dirBack:r[8],dirFront:r[9],dirDiff:r[10],backBlack:r[11],backRed:r[12],kBack:r[13],frontBlack:r[14],frontRed:r[15],kFront:r[16],note:r[20]});
|
||||||
|
}
|
||||||
|
load(data);
|
||||||
|
}
|
||||||
|
function saveLocal(){ localStorage.setItem('fourth_leveling_record', JSON.stringify(collect())); }
|
||||||
|
function loadLocal(){
|
||||||
|
const raw = localStorage.getItem('fourth_leveling_record');
|
||||||
|
if(raw){ try{ load(JSON.parse(raw)); return; }catch{} }
|
||||||
|
load({stations:Array.from({length:8},()=>({}))});
|
||||||
|
}
|
||||||
|
function clearAll(){ if(confirm('确定清空当前表格吗?')){ localStorage.removeItem('fourth_leveling_record'); load({stations:Array.from({length:8},()=>({}))}); } }
|
||||||
|
|
||||||
|
document.getElementById('observer').addEventListener('input', saveLocal);
|
||||||
|
document.getElementById('recorder').addEventListener('input', saveLocal);
|
||||||
|
loadLocal();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+90
-29
@@ -3,36 +3,97 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>多彩场景信函样例</title>
|
<title>信函已加密</title>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Zhi+Mang+Xing&display=swap" rel="stylesheet">
|
<style>
|
||||||
<link rel="stylesheet" href="../css/style.css">
|
:root {
|
||||||
<link rel="stylesheet" href="../css/notice-banner.css">
|
color-scheme: light;
|
||||||
|
font-family: "Noto Sans SC", "Microsoft YaHei", Arial, sans-serif;
|
||||||
|
background: #f5f7fb;
|
||||||
|
color: #182235;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
padding: 24px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unlock-panel {
|
||||||
|
width: min(420px, 100%);
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #d9e2ef;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 18px 45px rgba(36, 54, 84, 0.12);
|
||||||
|
padding: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
color: #52627a;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid #b8c6d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 12px 13px;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 14px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
background: #174ea6;
|
||||||
|
color: #ffffff;
|
||||||
|
font: inherit;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
cursor: wait;
|
||||||
|
opacity: 0.65;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
min-height: 22px;
|
||||||
|
margin-top: 12px;
|
||||||
|
color: #b42318;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<main class="unlock-panel">
|
||||||
<div class="letter-container theme-campus">
|
<h1>信函已加密</h1>
|
||||||
|
<p>请输入密码后在本机解锁查看内容。</p>
|
||||||
<h2 class="salutation">亲爱的赵家祺:</h2>
|
<form id="unlockForm">
|
||||||
|
<label for="letterPassword">访问密码</label>
|
||||||
<div class="content">
|
<input id="letterPassword" type="password" autocomplete="current-password" autofocus>
|
||||||
<p>好久不见!最近过得怎么样?</p>
|
<button type="submit">解锁</button>
|
||||||
<p>感觉太敷衍也不太好,但又感觉没什么可写的。今天是2026年6月21日,距离高中毕业已经2年有余,不知道你还活着吗,活得怎么样。其实到这里就已经写不下去,就像那个信封里的一样,我记得好像只写了两行。如果你还没有看那就别看了,上次你还让我用AI写,那是付费内容,ChatGPT一个月$20呢。其实只是感觉用AI不好。平时一直在用AI做各种各样事,感觉再用AI写这个有点不好。</p>
|
<div id="unlockStatus" class="status" role="status" aria-live="polite"></div>
|
||||||
<p>(又水了几行)</p>
|
</form>
|
||||||
<p>希望你最近能过得好吧。最近我才刚刚结束了为期一个月的期末大预习,甚至有一周考四科外加实习的地狱时刻。其实还有考试要延续到七月中旬,七月底才要放假。不知道你最近如何?</p>
|
</main>
|
||||||
<p>好,就这样了,剩下的你自行想象吧!</p>
|
<script id="encryptedPayload" type="application/json">{"v":1,"alg":"AES-256-GCM","kdf":"PBKDF2-SHA256","iterations":310000,"salt":"ws1u7yJ0EytWVyBfFQMRSA==","iv":"Q5PFApqjMtJbcoM6","ciphertext":"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"}</script>
|
||||||
|
<script defer src="../js/page-unlock.js"></script>
|
||||||
<div class="closing">
|
|
||||||
<p class="wish-prefix">此致</p>
|
|
||||||
<p class="wish-suffix">敬礼!</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="footer">
|
|
||||||
<p class="signature">bi</p>
|
|
||||||
<p class="date">2026年6月21日</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script defer src="../js/notice-banner.js?v=20260614"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user