暴露OCDIframeAPI接口,包含getFirstVisiblePageNo和gotoPage方法 移除demo.html中重复实现的页面跳转逻辑,改用新API
216 lines
8.8 KiB
HTML
216 lines
8.8 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Canvas Editor Iframe Demo</title>
|
||
<style>
|
||
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial; margin: 0; padding: 16px; }
|
||
.panel { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
|
||
.panel input[type="text"] { width: 420px; padding: 6px 8px; font-size: 12px; }
|
||
.panel button { padding: 6px 12px; font-size: 12px; cursor: pointer; }
|
||
.layout { display: flex; gap: 12px; align-items: flex-start; }
|
||
.sidebar { width: 280px; border: 1px solid #e2e6ed; border-radius: 8px; padding: 12px; background: #fafafa; }
|
||
.sidebar h4 { margin: 0 0 8px; font-weight: 600; font-size: 14px; }
|
||
.bookmark-form { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
|
||
.bookmark-form input { flex: 1; min-width: 0; padding: 6px 8px; font-size: 12px; }
|
||
.bookmark-form input[type="number"] { width: 80px; }
|
||
.bookmark-form button { padding: 6px 12px; font-size: 12px; cursor: pointer; }
|
||
.bookmark-list { list-style: none; padding: 0; margin: 0; }
|
||
.bookmark-item { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px; border-bottom: 1px solid #eee; }
|
||
.bookmark-item span { font-size: 12px; color: #111827; }
|
||
.bookmark-actions { display: flex; gap: 6px; }
|
||
.bookmark-actions button { padding: 4px 8px; font-size: 12px; cursor: pointer; }
|
||
.editorWrap { flex: 1; }
|
||
iframe { width: 100%; height: 80vh; border: 1px solid #e2e6ed; }
|
||
small { color: #6b7280; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h3>父页面通过地址拼接加载子页面(filePath + mode=edit)</h3>
|
||
<div class="panel">
|
||
<input id="urlInput" type="text" placeholder="输入同源文件URL" />
|
||
<label style="display:flex;align-items:center;gap:6px;">
|
||
<input id="editModeToggle" type="checkbox" />
|
||
<span>编辑模式(勾选则拼接 mode=edit,不勾选为只读)</span>
|
||
</label>
|
||
<button id="loadBtn">设置 iframe 地址</button>
|
||
<small>示例:vocd.html?filePath=URL&mode=edit 或 vocd.html?filePath=URL</small>
|
||
</div>
|
||
<div class="layout">
|
||
<aside class="sidebar">
|
||
<h4>书签</h4>
|
||
<div class="bookmark-form">
|
||
<button id="addBookmarkBtn">添加书签</button>
|
||
<small>自动命名为书签N+1,页码取当前可见页</small>
|
||
</div>
|
||
<ul id="bookmarkList" class="bookmark-list"></ul>
|
||
</aside>
|
||
<div class="editorWrap">
|
||
<iframe id="editorFrame" src="./vocd.html" referrerpolicy="no-referrer"></iframe>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const editorFrame = document.getElementById('editorFrame')
|
||
const loadBtn = document.getElementById('loadBtn')
|
||
const urlInput = document.getElementById('urlInput')
|
||
const editModeToggle = document.getElementById('editModeToggle')
|
||
const addBookmarkBtn = document.getElementById('addBookmarkBtn')
|
||
const bookmarkList = document.getElementById('bookmarkList')
|
||
|
||
function buildSrc(filePath, isEdit) {
|
||
const base = './vocd.html'
|
||
return `${base}?filePath=${encodeURIComponent(filePath)}` + (isEdit ? '&mode=edit' : '')
|
||
}
|
||
|
||
// 页面加载后,自动将 iframe 指向 vocd.html 并使用同源 /test.ocd
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const defaultUrl = '/test.ocd' // 来自 public,同源可直接访问
|
||
urlInput.value = defaultUrl
|
||
const base = './vocd.html'
|
||
// 默认不勾选:只读模式(不拼接 mode)
|
||
editModeToggle.checked = false
|
||
const src = buildSrc(defaultUrl, editModeToggle.checked)
|
||
editorFrame.src = src
|
||
console.log('[demo] 自动设置 iframe src:', src)
|
||
renderBookmarks()
|
||
})
|
||
|
||
// 切换编辑模式时,刷新 iframe 地址,保留当前 filePath
|
||
editModeToggle.addEventListener('change', () => {
|
||
const typedUrl = urlInput.value.trim()
|
||
const currentAbs = editorFrame.src || './vocd.html'
|
||
const currentUrl = new URL(currentAbs, window.location.href)
|
||
const currentFilePath = currentUrl.searchParams.get('filePath') || (typedUrl || '/test.ocd')
|
||
const src = buildSrc(currentFilePath, editModeToggle.checked)
|
||
editorFrame.src = src
|
||
console.log('[demo] 编辑模式切换,刷新 iframe src:', src)
|
||
renderBookmarks()
|
||
})
|
||
|
||
loadBtn.onclick = () => {
|
||
const typedUrl = urlInput.value.trim()
|
||
const base = './vocd.html'
|
||
const targetUrl = typedUrl || '/test.ocd'
|
||
const src = buildSrc(targetUrl, editModeToggle.checked)
|
||
editorFrame.src = src
|
||
console.log('[demo] 设置 iframe src:', src)
|
||
renderBookmarks()
|
||
}
|
||
|
||
function getCurrentFilePath() {
|
||
const currentAbs = editorFrame.src || './vocd.html'
|
||
const currentUrl = new URL(currentAbs, window.location.href)
|
||
return currentUrl.searchParams.get('filePath') || '/test.ocd'
|
||
}
|
||
|
||
function getBookmarkKey() {
|
||
const fp = getCurrentFilePath()
|
||
return `bookmarks:${fp}`
|
||
}
|
||
|
||
function readBookmarks() {
|
||
try {
|
||
const raw = localStorage.getItem(getBookmarkKey())
|
||
return raw ? JSON.parse(raw) : []
|
||
} catch {
|
||
return []
|
||
}
|
||
}
|
||
|
||
function writeBookmarks(list) {
|
||
localStorage.setItem(getBookmarkKey(), JSON.stringify(list))
|
||
}
|
||
|
||
function getNextBookmarkName() {
|
||
const list = readBookmarks()
|
||
let maxN = 0
|
||
list.forEach(b => {
|
||
const m = /^书签(\d+)$/.exec(String(b.name || ''))
|
||
if (m) {
|
||
const n = parseInt(m[1], 10)
|
||
if (Number.isFinite(n)) maxN = Math.max(maxN, n)
|
||
}
|
||
})
|
||
return `书签${maxN + 1}`
|
||
}
|
||
|
||
function renderBookmarks() {
|
||
const list = readBookmarks()
|
||
bookmarkList.innerHTML = ''
|
||
list.forEach(item => {
|
||
const li = document.createElement('li')
|
||
li.className = 'bookmark-item'
|
||
const label = document.createElement('span')
|
||
label.textContent = `${item.name}(第${item.page}页)`
|
||
const actions = document.createElement('div')
|
||
actions.className = 'bookmark-actions'
|
||
const jumpBtn = document.createElement('button')
|
||
jumpBtn.textContent = '跳转'
|
||
jumpBtn.onclick = () => {
|
||
const api = editorFrame.contentWindow && editorFrame.contentWindow.OCDIframeAPI
|
||
if (api && typeof api.gotoPage === 'function') {
|
||
api.gotoPage(item.page)
|
||
} else {
|
||
alert('子页面未提供跳转 API')
|
||
}
|
||
}
|
||
const editBtn = document.createElement('button')
|
||
editBtn.textContent = '编辑'
|
||
editBtn.onclick = () => {
|
||
const newName = window.prompt('书签名称', item.name) || item.name
|
||
const newPageStr = window.prompt('页码(正整数)', String(item.page)) || String(item.page)
|
||
const newPage = Math.max(1, parseInt(newPageStr, 10) || item.page)
|
||
const list2 = readBookmarks().map(b => (b.id === item.id ? { ...b, name: newName, page: newPage } : b))
|
||
writeBookmarks(list2)
|
||
renderBookmarks()
|
||
}
|
||
const delBtn = document.createElement('button')
|
||
delBtn.textContent = '删除'
|
||
delBtn.onclick = () => {
|
||
const list2 = readBookmarks().filter(b => b.id !== item.id)
|
||
writeBookmarks(list2)
|
||
renderBookmarks()
|
||
}
|
||
actions.appendChild(jumpBtn)
|
||
actions.appendChild(editBtn)
|
||
actions.appendChild(delBtn)
|
||
li.appendChild(label)
|
||
li.appendChild(actions)
|
||
bookmarkList.appendChild(li)
|
||
})
|
||
}
|
||
|
||
function addBookmark(name, page) {
|
||
const list = readBookmarks()
|
||
const id = Date.now().toString(36) + Math.random().toString(36).slice(2)
|
||
const item = { id, name, page }
|
||
writeBookmarks([...list, item])
|
||
renderBookmarks()
|
||
}
|
||
|
||
addBookmarkBtn.onclick = () => {
|
||
const name = getNextBookmarkName()
|
||
let page = 1
|
||
try {
|
||
const api = editorFrame.contentWindow && editorFrame.contentWindow.OCDIframeAPI
|
||
if (api && typeof api.getFirstVisiblePageNo === 'function') {
|
||
page = api.getFirstVisiblePageNo()
|
||
} else {
|
||
console.warn('[demo] 子页面未暴露 getFirstVisiblePageNo,默认使用第1页')
|
||
}
|
||
} catch (e) {
|
||
console.warn('[demo] 获取当前可见页失败,默认第1页', e)
|
||
}
|
||
addBookmark(name, page)
|
||
}
|
||
|
||
|
||
editorFrame.addEventListener('load', () => {
|
||
renderBookmarks()
|
||
})
|
||
</script>
|
||
</body>
|
||
</html>
|