cadeditfronttest/参考(仅表格).HTML
puzzlesion 1bd8f25cdb feat: 图纸工作台核心功能重构与交互增强
本次提交对图纸工作台进行了全面的功能重构和交互体验升级,主要涵盖了数据结构优化、核心逻辑增强、以及全新的可视化交互功能。

### 主要更新内容:

#### 1. **核心应用逻辑 (app.js)**

-   **数据结构优化**:
    -   重构了初始化逻辑,现在每个图片被视为一个独立的 \drawing\ 对象,包含自身的坐标边界和关联图片,使数据模型更清晰。
-   **状态管理**:
    -   引入 \currentDrawingId\ 状态,用于精确追踪和控制当前显示的图纸。
-   **核心功能增强**:
    -   **自动图纸切换**: 实现了 \getDrawingForItem\ 映射逻辑,当用户在结构树中选择不同层级的件号时,系统能自动切换到其关联的图纸。
    -   **件号重命名 (handleItemRename)**: 彻底重写了重命名逻辑,现在支持递归更新所有子孙件号的ID和层级关系,保证了复杂结构下数据的一致性。
    -   **件号更新 (handleItemUpdate)**: 增强了件号创建和更新的鲁棒性,在添加深层级子件号时,会自动创建不存在的父级装配件,简化了操作流程。
    -   **图片拖拽**: 新增 \updateImagePosition\ 处理器,允许用户在画布上直接拖动图片并更新其世界坐标。

#### 2. **数据编辑器 (components/DataEditor.js)**

-   **UI/UX 改进**:
    -   大幅扩展了可编辑字段,增加了中文名、英文名、规格、材料、比例和备注等详细属性。
    -   界面现在能够智能区分零件和装配件,并对装配件的重量输入框进行只读处理,因为其重量由子件自动汇总计算。
    -   为只读字段添加了明确的提示信息,优化了用户体验。

#### 3. **图纸查看器 (components/DrawingViewer.js)**

-   **全新交互功能**:
    -   **画布平移与缩放**: 实现了完整的画布拖拽平移和鼠标滚轮缩放功能,操作更流畅。
    -   **表格与图片拖拽**: 用户现在可以直接在画布上拖动明细表 (\GraphicalTable\) 和图纸中的图片,实现自由布局。
    -   **点击创建件号**: 在画布空白处单击,会弹出输入框,允许用户在指定位置快速创建新的件号,并记录其在图纸上的标记位置 (\markerPosition\)。
-   **UI 浮层与控件**:
    -   在画布上增加了多个交互浮层,包括左上角的图纸-件号绑定工具、右上角的缩放按钮、以及两侧用于切换图纸的箭头按钮。
    -   新增了动态输入框 (\inputBox\),用于响应画布点击事件,提升了操作的直观性。
-   **渲染与状态**:
    -   \GraphicalTable\ 和 \<image>\ 元素现在具备了拖拽所需的所有属性和事件处理。
    -   内部状态管理重构,以支持新的视图变换 (\iewTransform\) 和交互状态。

#### 4. **主页面 (index.html)**

-   **项目依赖**:
    -   将 React 的 CDN 依赖切换为本地 \endor\ 目录下的文件,提高了应用的稳定性和加载速度。
    -   移除了 Babel 依赖,因为项目已统一使用 \React.createElement\ API,无需 JSX 编译。
-   **样式系统**:
    -   全面拥抱 Tailwind CSS 的 \@layer\ 规则,对样式进行了分层(theme, base, components, utilities),使 CSS 结构更清晰、更易于维护。
    -   定义了全局 CSS 变量,统一了颜色、尺寸等设计规范。
2025-09-13 13:52:07 +08:00

419 lines
24 KiB
HTML
Raw 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>SVG Drawing Table Generator Workbench</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', 'Helvetica Neue', 'Arial', sans-serif;
background-color: #f1f5f9;
}
svg text {
font-family: 'KaiTi', 'SimSun', sans-serif;
}
.form-input {
@apply w-full p-2 border border-slate-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm;
}
.sidebar-item {
@apply block w-full text-left px-4 py-2.5 text-sm font-medium text-slate-700 rounded-md hover:bg-slate-200 transition-colors;
}
.sidebar-item.active {
@apply bg-indigo-600 text-white hover:bg-indigo-700;
}
.data-table th, .data-table td {
@apply px-3 py-2 text-left text-sm whitespace-nowrap;
}
.data-table thead {
@apply bg-slate-100;
}
</style>
</head>
<body class="h-screen w-screen overflow-hidden flex flex-col">
<header class="bg-white border-b border-slate-200 shadow-sm z-10">
<div class="max-w-full mx-auto px-6 py-3">
<h1 class="text-xl font-bold text-slate-800">图纸物料清单工作台</h1>
</div>
</header>
<div class="flex flex-grow overflow-hidden">
<!-- Left Sidebar: Table List -->
<aside class="w-64 bg-white border-r border-slate-200 p-4 flex flex-col">
<h2 class="text-sm font-semibold text-slate-500 uppercase tracking-wider mb-3">我的表格</h2>
<div id="table-list" class="flex-grow space-y-1 overflow-y-auto">
<!-- Table list items will be injected here -->
</div>
<button id="add-table-btn" class="mt-4 w-full flex items-center justify-center px-4 py-2 border border-dashed border-slate-300 text-sm font-medium rounded-md text-slate-700 hover:bg-slate-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
+ 新建表格
</button>
</aside>
<!-- Center: SVG Preview -->
<main class="flex-grow bg-slate-50 p-6 overflow-auto">
<div id="svg-container" class="bg-white w-full h-full rounded-lg shadow-inner border border-slate-200 p-4">
<svg id="drawing-svg" width="100%" height="100%"></svg>
</div>
</main>
<!-- Right Sidebar: Editor -->
<aside id="editor-sidebar" class="w-96 bg-white border-l border-slate-200 p-6 flex flex-col overflow-y-auto">
<!-- Form for adding/editing a row -->
<div id="editor-form-container">
<h2 id="editor-title" class="text-lg font-semibold text-slate-800 mb-4">添加新物料行</h2>
<form id="entry-form" class="grid grid-cols-2 gap-4 text-sm">
<div>
<label for="input-jianhao" class="block text-xs font-medium text-slate-600">件号</label>
<input type="text" id="input-jianhao" class="form-input mt-1">
</div>
<div class="col-span-2">
<label for="input-tuhao" class="block text-xs font-medium text-slate-600">图号或标准号</label>
<input type="text" id="input-tuhao" class="form-input mt-1">
</div>
<div>
<label for="input-chinese-name" class="block text-xs font-medium text-slate-600">中文名称</label>
<input type="text" id="input-chinese-name" class="form-input mt-1">
</div>
<div>
<label for="input-english-name" class="block text-xs font-medium text-slate-600">英文名称</label>
<input type="text" id="input-english-name" class="form-input mt-1">
</div>
<div>
<label for="input-shuliang" class="block text-xs font-medium text-slate-600">数量</label>
<input type="text" id="input-shuliang" class="form-input mt-1">
</div>
<div>
<label for="input-cailiao" class="block text-xs font-medium text-slate-600">材料</label>
<input type="text" id="input-cailiao" class="form-input mt-1">
</div>
<div>
<label for="input-dan" class="block text-xs font-medium text-slate-600">单重 (kg)</label>
<input type="text" id="input-dan" class="form-input mt-1">
</div>
<div>
<label for="input-zong" class="block text-xs font-medium text-slate-600">总重 (kg)</label>
<input type="text" id="input-zong" class="form-input mt-1">
</div>
<div class="col-span-2">
<label for="input-beizhu" class="block text-xs font-medium text-slate-600">备注</label>
<input type="text" id="input-beizhu" class="form-input mt-1">
</div>
<div class="col-span-2">
<button type="submit" id="form-submit-btn" class="mt-2 w-full inline-flex justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
添加行
</button>
<button type="button" id="form-cancel-btn" class="mt-2 w-full hidden inline-flex justify-center px-4 py-2 border border-slate-300 text-sm font-medium rounded-md shadow-sm text-slate-700 bg-white hover:bg-slate-50">
取消编辑
</button>
</div>
</form>
</div>
<!-- Data Management Table -->
<div class="mt-8 flex-grow flex flex-col overflow-hidden">
<h2 class="text-lg font-semibold text-slate-800 mb-4">当前数据</h2>
<div class="overflow-y-auto border border-slate-200 rounded-lg">
<table class="w-full data-table">
<thead class="sticky top-0">
<tr>
<th>件号</th>
<th>名称</th>
<th>数量</th>
<th>操作</th>
</tr>
</thead>
<tbody id="data-table-body" class="divide-y divide-slate-200">
</tbody>
</table>
</div>
</div>
</aside>
</div>
<script>
const headerTemplate = { "template_name": "标准物料清单-底部表头", "row_height": 8.0, "header_height": 14.0, "column_boundaries": [0.0, 15.0, 45.0, 100.0, 110.0, 140.0, 150.0, 160.0, 185.0], "header_definition": { "lines": [ {"start": [0.0, 14.0], "end": [185.0, 14.0]}, {"start": [160.0, 6.5], "end": [140.0, 6.5]}, {"start": [110.0, 0.0], "end": [110.0, 14.0]}, {"start": [15.0, 14.0], "end": [15.0, 0.0]}, {"start": [45.0, 0.0], "end": [45.0, 14.0]}, {"start": [100.0, 0.0], "end": [100.0, 14.0]}, {"start": [140.0, 0.0], "end": [140.0, 14.0]}, {"start": [160.0, 0.0], "end": [160.0, 14.0]}, {"start": [150.0, 6.5], "end": [150.0, 14.0]}, {"start": [0.0, 0.0], "end": [185.0, 0.0]}, {"start": [185.0, 0.0], "end": [185.0, 14.0]}], "texts": [ {"content": "总", "relative_pos": [153.62, 10.23], "height": 3.5}, {"content": "单", "relative_pos": [143.79, 10.02], "height": 3.5}, {"content": "TOTAL", "relative_pos": [152.64, 7.45], "height": 2.0}, {"content": "SINGLE", "relative_pos": [141.89, 7.45], "height": 2.0}, {"content": "备 注", "relative_pos": [169.33, 6.8], "height": 3.5, "alignment": "BOTTOM_CENTER"}, {"content": "材 料", "relative_pos": [121.56, 6.56], "height": 3.5}, {"content": "数量", "relative_pos": [102.5, 6.56], "height": 3.5}, {"content": "名 称", "relative_pos": [67.3, 6.56], "height": 3.5}, {"content": "件 号", "relative_pos": [4.43, 6.56], "height": 3.5}, {"content": "图号或标准号", "relative_pos": [22.43, 6.53], "height": 3.5}, {"content": "MAT'L", "relative_pos": [122.94, 2.33], "height": 2.0}, {"content": "QTY.", "relative_pos": [102.89, 2.33], "height": 2.0}, {"content": "REMARKS", "relative_pos": [165.48, 2.3], "height": 2.0}, {"content": "PARTS. NAME.", "relative_pos": [65.06, 1.76], "height": 2.0}, {"content": "DWG NO. OR STD. NO.", "relative_pos": [19.43, 1.76], "height": 2.0}, {"content": "PARTS .NO.", "relative_pos": [7.77, 1.76], "height": 2.0, "alignment": "BOTTOM_CENTER"}, {"content": "MASSkg", "relative_pos": [148.32, 1.7], "height": 2.0}, {"content": "质量", "relative_pos": [142.49, 0.87], "height": 3.5}] } };
const columnsTemplate = { "row_height": 8.0, "column_definitions": [ {"name": "件号", "relative_x_start": 0.0, "text_definitions": [{"data_key": "main", "relative_pos": [5.82, 1.46], "height": 3.5, "alignment": "BOTTOM_LEFT"}]}, {"name": "图号或标准号", "relative_x_start": 15.0, "text_definitions": [{"data_key": "main", "relative_pos": [14.77, 1.15], "height": 3.0, "alignment": "BOTTOM_CENTER"}]}, {"name": "名称", "relative_x_start": 45.0, "text_definitions": [{"data_key": "chinese_name", "relative_pos": [1.76, 3.88], "height": 3.5}, {"data_key": "english_name", "relative_pos": [1.79, 1.0], "height": 2.0}, {"data_key": "specification", "relative_pos": [18.68, 3.9], "height": 3.0}]}, {"name": "数量", "relative_x_start": 100.0, "text_definitions": [{"data_key": "main", "relative_pos": [4.97, 1.37], "height": 3.0, "alignment": "BOTTOM_CENTER"}]}, {"name": "材料", "relative_x_start": 110.0, "text_definitions": [{"data_key": "main", "relative_pos": [15.16, 1.12], "height": 3.5, "alignment": "BOTTOM_CENTER"}]}, {"name": "单", "relative_x_start": 140.0, "text_definitions": [{"data_key": "main", "relative_pos": [5.06, 1.42], "height": 3.0, "alignment": "BOTTOM_CENTER"}]}, {"name": "总", "relative_x_start": 150.0, "text_definitions": [{"data_key": "main", "relative_pos": [5.06, 1.42], "height": 3.0, "alignment": "BOTTOM_CENTER"}]}, {"name": "备注", "relative_x_start": 160.0, "text_definitions": [{"data_key": "main", "relative_pos": [12.06, 1.42], "height": 3.0, "alignment": "BOTTOM_CENTER"}]}] };
// --- Application State ---
let state = {
tables: [
{
id: Date.now(),
name: "主装配图物料清单",
data: [
{"件号": {"main": "1"}, "图号或标准号": {"main": "JB/T 1001"}, "名称": {"chinese_name": "轴承座", "english_name": "Bearing Seat"}, "数量": {"main": "2"}, "材料": {"main": "HT200"}, "单": {"main": "15.5"}, "总": {"main": "31.0"}, "备注": {"main": "外购"}},
{"件号": {"main": "2"}, "图号或标准号": {"main": "GB/T 5783"}, "名称": {"chinese_name": "六角螺栓", "english_name": "Hex Bolt"}, "数量": {"main": "8"}, "材料": {"main": "Q235"}, "单": {"main": "0.5"}, "总": {"main": "4.0"}, "备注": {"main": "M8x20"}}
]
}
],
activeTableId: null,
editingRowIndex: null
};
state.activeTableId = state.tables[0].id;
// --- DOM Elements ---
const tableList = document.getElementById('table-list');
const addTableBtn = document.getElementById('add-table-btn');
const entryForm = document.getElementById('entry-form');
const editorSidebar = document.getElementById('editor-sidebar');
const dataTableBody = document.getElementById('data-table-body');
const editorTitle = document.getElementById('editor-title');
const formSubmitBtn = document.getElementById('form-submit-btn');
const formCancelBtn = document.getElementById('form-cancel-btn');
// --- Main App Logic ---
document.addEventListener('DOMContentLoaded', () => {
addTableBtn.addEventListener('click', addNewTable);
entryForm.addEventListener('submit', handleFormSubmit);
formCancelBtn.addEventListener('click', cancelEdit);
renderApp();
});
function getActiveTable() {
return state.tables.find(t => t.id === state.activeTableId);
}
function renderApp() {
if (!getActiveTable() && state.tables.length > 0) {
state.activeTableId = state.tables[0].id;
}
renderTableList();
const activeTable = getActiveTable();
if (activeTable) {
editorSidebar.classList.remove('hidden');
renderEditor(activeTable.data);
renderSVG(activeTable.data);
} else {
editorSidebar.classList.add('hidden');
document.getElementById('drawing-svg').innerHTML = '';
}
}
// --- Left Sidebar Logic ---
function renderTableList() {
tableList.innerHTML = '';
state.tables.forEach(table => {
const button = document.createElement('button');
button.className = `sidebar-item ${table.id === state.activeTableId ? 'active' : ''}`;
button.textContent = table.name;
button.dataset.id = table.id;
button.addEventListener('click', () => {
state.activeTableId = table.id;
state.editingRowIndex = null; // Reset editing state when switching tables
renderApp();
});
tableList.appendChild(button);
});
}
function addNewTable() {
const newName = prompt("请输入新表格的名称:", `新物料清单 ${state.tables.length + 1}`);
if (newName) {
const newTable = {
id: Date.now(),
name: newName,
data: []
};
state.tables.push(newTable);
state.activeTableId = newTable.id;
renderApp();
}
}
// --- Right Sidebar Logic ---
function renderEditor(data) {
renderManagementTable(data);
if (state.editingRowIndex !== null) {
const rowData = data[state.editingRowIndex];
populateForm(rowData);
editorTitle.textContent = `编辑行: ${rowData['件号'].main}`;
formSubmitBtn.textContent = '更新行';
formCancelBtn.classList.remove('hidden');
} else {
entryForm.reset();
editorTitle.textContent = '添加新物料行';
formSubmitBtn.textContent = '添加行';
formCancelBtn.classList.add('hidden');
}
}
function handleFormSubmit(e) {
e.preventDefault();
const activeTable = getActiveTable();
if (!activeTable) return;
const newRow = {
"件号": { "main": document.getElementById('input-jianhao').value },
"图号或标准号": { "main": document.getElementById('input-tuhao').value },
"名称": { "chinese_name": document.getElementById('input-chinese-name').value, "english_name": document.getElementById('input-english-name').value },
"数量": { "main": document.getElementById('input-shuliang').value },
"材料": { "main": document.getElementById('input-cailiao').value },
"单": { "main": document.getElementById('input-dan').value },
"总": { "main": document.getElementById('input-zong').value },
"备注": { "main": document.getElementById('input-beizhu').value },
};
if (state.editingRowIndex !== null) {
activeTable.data[state.editingRowIndex] = newRow;
state.editingRowIndex = null;
} else {
activeTable.data.push(newRow);
}
renderApp();
}
function populateForm(rowData) {
document.getElementById('input-jianhao').value = rowData['件号'].main || '';
document.getElementById('input-tuhao').value = rowData['图号或标准号'].main || '';
document.getElementById('input-chinese-name').value = rowData['名称'].chinese_name || '';
document.getElementById('input-english-name').value = rowData['名称'].english_name || '';
document.getElementById('input-shuliang').value = rowData['数量'].main || '';
document.getElementById('input-cailiao').value = rowData['材料'].main || '';
document.getElementById('input-dan').value = rowData['单'].main || '';
document.getElementById('input-zong').value = rowData['总'].main || '';
document.getElementById('input-beizhu').value = rowData['备注'].main || '';
}
function cancelEdit() {
state.editingRowIndex = null;
renderApp();
}
function renderManagementTable(data) {
dataTableBody.innerHTML = '';
if(!data) return;
data.forEach((rowData, index) => {
const tr = document.createElement('tr');
tr.className = "hover:bg-slate-50";
tr.innerHTML = `
<td class="font-medium text-slate-800">${rowData['件号'].main}</td>
<td>${rowData['名称'].chinese_name || ''}</td>
<td>${rowData['数量'].main}</td>
<td class="flex items-center space-x-2">
<button class="text-indigo-600 hover:text-indigo-800 text-xs" data-index="${index}">编辑</button>
<button class="text-red-600 hover:text-red-800 text-xs" data-index="${index}">删除</button>
</td>
`;
dataTableBody.appendChild(tr);
});
dataTableBody.querySelectorAll('button').forEach(button => {
button.addEventListener('click', (e) => {
const index = parseInt(e.target.dataset.index, 10);
if (e.target.textContent === '删除') {
if(confirm(`确定要删除 件号 ${data[index]['件号'].main} 吗?`)) {
getActiveTable().data.splice(index, 1);
renderApp();
}
} else if (e.target.textContent === '编辑') {
state.editingRowIndex = index;
renderApp();
editorSidebar.scrollTop = 0; // scroll to top
}
});
});
}
// --- Center SVG Logic ---
function renderSVG(drawingData) {
const svgNS = "http://www.w3.org/2000/svg";
const svg = document.getElementById('drawing-svg');
svg.innerHTML = '';
if (!drawingData) return;
const strokeColor = "#334155", strokeWidth = 0.3, textColor = "#0f172a", margin = 10;
const { header_height, row_height } = headerTemplate;
const totalRows = drawingData.length;
const tableWidth = Math.max(...headerTemplate.column_boundaries);
const tableHeight = header_height + (totalRows * row_height);
svg.setAttribute('viewBox', `0 0 ${tableWidth + 2 * margin} ${tableHeight + 2 * margin}`);
const mainGroup = document.createElementNS(svgNS, 'g');
mainGroup.setAttribute('transform', `translate(${margin}, ${tableHeight + margin}) scale(1, -1)`);
svg.appendChild(mainGroup);
const bodyGroup = document.createElementNS(svgNS, 'g');
mainGroup.appendChild(bodyGroup);
drawingData.forEach((rowData, rowIndex) => {
const rowY = header_height + ((totalRows - 1 - rowIndex) * row_height);
const rowGroup = document.createElementNS(svgNS, 'g');
rowGroup.setAttribute('transform', `translate(0, ${rowY})`);
bodyGroup.appendChild(rowGroup);
const lineEl = document.createElementNS(svgNS, 'line');
lineEl.setAttribute('x1', headerTemplate.column_boundaries[0]);
lineEl.setAttribute('y1', 0);
lineEl.setAttribute('x2', tableWidth);
lineEl.setAttribute('y2', 0);
lineEl.setAttribute('stroke', strokeColor);
lineEl.setAttribute('stroke-width', strokeWidth);
rowGroup.appendChild(lineEl);
columnsTemplate.column_definitions.forEach(colDef => {
colDef.text_definitions.forEach(textDef => {
const dataItem = rowData[colDef.name];
if (dataItem && dataItem[textDef.data_key] != null) {
const content = dataItem[textDef.data_key];
const x = colDef.relative_x_start + textDef.relative_pos[0];
const y = textDef.relative_pos[1];
const textEl = createSvgText(content, x, y, textDef.height, textColor, textDef.alignment);
rowGroup.appendChild(textEl);
}
});
});
});
headerTemplate.column_boundaries.forEach(xPos => {
if (xPos <= tableWidth) {
const lineEl = document.createElementNS(svgNS, 'line');
lineEl.setAttribute('x1', xPos);
lineEl.setAttribute('y1', header_height);
lineEl.setAttribute('x2', xPos);
lineEl.setAttribute('y2', tableHeight);
lineEl.setAttribute('stroke', strokeColor);
lineEl.setAttribute('stroke-width', strokeWidth);
bodyGroup.appendChild(lineEl);
}
});
const headerGroup = document.createElementNS(svgNS, 'g');
headerGroup.setAttribute('transform', 'translate(0, 0)');
mainGroup.appendChild(headerGroup);
headerTemplate.header_definition.lines.forEach(line => {
const lineEl = document.createElementNS(svgNS, 'line');
lineEl.setAttribute('x1', line.start[0]);
lineEl.setAttribute('y1', line.start[1]);
lineEl.setAttribute('x2', line.end[0]);
lineEl.setAttribute('y2', line.end[1]);
lineEl.setAttribute('stroke', strokeColor);
lineEl.setAttribute('stroke-width', strokeWidth);
headerGroup.appendChild(lineEl);
});
headerTemplate.header_definition.texts.forEach(text => {
const textEl = createSvgText(text.content, text.relative_pos[0], text.relative_pos[1], text.height, textColor, text.alignment);
headerGroup.appendChild(textEl);
});
}
function createSvgText(content, x, y, height, color, alignment = 'BOTTOM_LEFT') {
const svgNS = "http://www.w3.org/2000/svg";
const textEl = document.createElementNS(svgNS, 'text');
textEl.setAttribute('x', x);
textEl.setAttribute('y', y);
textEl.setAttribute('font-size', height);
textEl.setAttribute('fill', color);
textEl.setAttribute('transform', 'scale(1, -1)');
textEl.setAttribute('y', -y);
textEl.setAttribute('text-anchor', (alignment === 'BOTTOM_CENTER') ? 'middle' : (alignment === 'BOTTOM_RIGHT' ? 'end' : 'start'));
textEl.textContent = content;
return textEl;
}
</script>
</body>
</html>