-
Notifications
You must be signed in to change notification settings - Fork 468
feat: preview support auto update #1327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7b0e48c
17a9903
35f25a3
22b180c
12a25c8
105e511
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,53 +10,294 @@ | |||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| import { constants } from '@opentiny/tiny-engine-utils' | ||||||||||||||||||||||||||||||||||||||||||||
| import { useThrottleFn } from '@vueuse/core' | ||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||
| useMaterial, | ||||||||||||||||||||||||||||||||||||||||||||
| useResource, | ||||||||||||||||||||||||||||||||||||||||||||
| useMessage, | ||||||||||||||||||||||||||||||||||||||||||||
| useCanvas, | ||||||||||||||||||||||||||||||||||||||||||||
| usePage, | ||||||||||||||||||||||||||||||||||||||||||||
| useBlock, | ||||||||||||||||||||||||||||||||||||||||||||
| getMetaApi, | ||||||||||||||||||||||||||||||||||||||||||||
| META_SERVICE, | ||||||||||||||||||||||||||||||||||||||||||||
| getMergeMeta | ||||||||||||||||||||||||||||||||||||||||||||
| } from '@opentiny/tiny-engine-meta-register' | ||||||||||||||||||||||||||||||||||||||||||||
| import { utils } from '@opentiny/tiny-engine-utils' | ||||||||||||||||||||||||||||||||||||||||||||
| import { isDevelopEnv } from './environments' | ||||||||||||||||||||||||||||||||||||||||||||
| import { useMaterial, useResource } from '@opentiny/tiny-engine-meta-register' | ||||||||||||||||||||||||||||||||||||||||||||
| // prefer old unicode hacks for backward compatibility | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const { COMPONENT_NAME } = constants | ||||||||||||||||||||||||||||||||||||||||||||
| const { deepClone } = utils | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| export const utoa = (string) => btoa(unescape(encodeURIComponent(string))) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| export const atou = (base64) => decodeURIComponent(escape(atob(base64))) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const open = (params = {}) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const paramsMap = new URLSearchParams(location.search) | ||||||||||||||||||||||||||||||||||||||||||||
| params.app = paramsMap.get('id') | ||||||||||||||||||||||||||||||||||||||||||||
| params.tenant = paramsMap.get('tenant') | ||||||||||||||||||||||||||||||||||||||||||||
| // 保存预览窗口引用 | ||||||||||||||||||||||||||||||||||||||||||||
| let previewWindow = null | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const getScriptAndStyleDeps = () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const { scripts, styles } = useMaterial().getCanvasDeps() | ||||||||||||||||||||||||||||||||||||||||||||
| const utilsDeps = useResource().getUtilsDeps() | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| params.scripts = [...scripts, ...utilsDeps].reduce((res, item) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const scriptsDeps = [...scripts, ...utilsDeps].reduce((res, item) => { | ||||||||||||||||||||||||||||||||||||||||||||
| res[item.package] = item.script | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return res | ||||||||||||||||||||||||||||||||||||||||||||
| }, {}) | ||||||||||||||||||||||||||||||||||||||||||||
| params.styles = [...styles] | ||||||||||||||||||||||||||||||||||||||||||||
| const stylesDeps = [...styles] | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||
| scripts: scriptsDeps, | ||||||||||||||||||||||||||||||||||||||||||||
| styles: stylesDeps | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const getSchemaParams = async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const { isBlock, getPageSchema, getCurrentPage, getSchema } = useCanvas() | ||||||||||||||||||||||||||||||||||||||||||||
| const isBlockPreview = isBlock() | ||||||||||||||||||||||||||||||||||||||||||||
| const { scripts, styles } = getScriptAndStyleDeps() | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (isBlockPreview) { | ||||||||||||||||||||||||||||||||||||||||||||
| const { getCurrentBlock } = useBlock() | ||||||||||||||||||||||||||||||||||||||||||||
| const block = getCurrentBlock() | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const latestPage = { | ||||||||||||||||||||||||||||||||||||||||||||
| ...block, | ||||||||||||||||||||||||||||||||||||||||||||
| page_content: getSchema() | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return deepClone({ | ||||||||||||||||||||||||||||||||||||||||||||
| currentPage: latestPage, | ||||||||||||||||||||||||||||||||||||||||||||
| ancestors: [], | ||||||||||||||||||||||||||||||||||||||||||||
| scripts, | ||||||||||||||||||||||||||||||||||||||||||||
| styles | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const pageSchema = getPageSchema() | ||||||||||||||||||||||||||||||||||||||||||||
| const currentPage = getCurrentPage() | ||||||||||||||||||||||||||||||||||||||||||||
| const { getFamily } = usePage() | ||||||||||||||||||||||||||||||||||||||||||||
| const latestPage = { | ||||||||||||||||||||||||||||||||||||||||||||
| ...currentPage, | ||||||||||||||||||||||||||||||||||||||||||||
| page_content: pageSchema | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const ancestors = await getFamily(latestPage) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return deepClone({ | ||||||||||||||||||||||||||||||||||||||||||||
| currentPage: latestPage, | ||||||||||||||||||||||||||||||||||||||||||||
| ancestors, | ||||||||||||||||||||||||||||||||||||||||||||
| scripts, | ||||||||||||||||||||||||||||||||||||||||||||
| styles | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 当 schema 变化时发送更新 | ||||||||||||||||||||||||||||||||||||||||||||
| const sendSchemaUpdate = (data) => { | ||||||||||||||||||||||||||||||||||||||||||||
| previewWindow.postMessage( | ||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||
| source: 'designer', | ||||||||||||||||||||||||||||||||||||||||||||
| type: 'schema', | ||||||||||||||||||||||||||||||||||||||||||||
| data | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| previewWindow.origin || window.location.origin | ||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| let hasSchemaChangeListener = false | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const cleanupSchemaChangeListener = () => { | ||||||||||||||||||||||||||||||||||||||||||||
| const { unsubscribe } = useMessage() | ||||||||||||||||||||||||||||||||||||||||||||
| unsubscribe({ | ||||||||||||||||||||||||||||||||||||||||||||
| topic: 'schemaChange', | ||||||||||||||||||||||||||||||||||||||||||||
| subscriber: 'preview-communication' | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
| unsubscribe({ | ||||||||||||||||||||||||||||||||||||||||||||
| topic: 'schemaImport', | ||||||||||||||||||||||||||||||||||||||||||||
| subscriber: 'preview-communication' | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
| unsubscribe({ | ||||||||||||||||||||||||||||||||||||||||||||
| topic: 'pageOrBlockInit', | ||||||||||||||||||||||||||||||||||||||||||||
| subscriber: 'preview-communication' | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
| hasSchemaChangeListener = false | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const handleSchemaChange = async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| // 如果预览窗口不存在或已关闭,则取消订阅 | ||||||||||||||||||||||||||||||||||||||||||||
| if (!previewWindow || previewWindow.closed) { | ||||||||||||||||||||||||||||||||||||||||||||
| cleanupSchemaChangeListener() | ||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const params = await getSchemaParams() | ||||||||||||||||||||||||||||||||||||||||||||
| sendSchemaUpdate(params) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 设置监听 schemaChange 事件,自动发送更新到预览页面 | ||||||||||||||||||||||||||||||||||||||||||||
| export const setupSchemaChangeListener = () => { | ||||||||||||||||||||||||||||||||||||||||||||
| // 如果已经存在监听,则取消之前的监听 | ||||||||||||||||||||||||||||||||||||||||||||
| if (hasSchemaChangeListener) { | ||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const { subscribe } = useMessage() | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| subscribe({ | ||||||||||||||||||||||||||||||||||||||||||||
| topic: 'schemaChange', | ||||||||||||||||||||||||||||||||||||||||||||
| subscriber: 'preview-communication', | ||||||||||||||||||||||||||||||||||||||||||||
| // 防抖更新,防止因为属性变化频繁触发 | ||||||||||||||||||||||||||||||||||||||||||||
| callback: useThrottleFn(handleSchemaChange, 1000, true) | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| subscribe({ | ||||||||||||||||||||||||||||||||||||||||||||
| topic: 'schemaImport', | ||||||||||||||||||||||||||||||||||||||||||||
| subscriber: 'preview-communication', | ||||||||||||||||||||||||||||||||||||||||||||
| callback: useThrottleFn(handleSchemaChange, 1000, true) | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| subscribe({ | ||||||||||||||||||||||||||||||||||||||||||||
| topic: 'pageOrBlockInit', | ||||||||||||||||||||||||||||||||||||||||||||
| subscriber: 'preview-communication', | ||||||||||||||||||||||||||||||||||||||||||||
| callback: handleSchemaChange | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| hasSchemaChangeListener = true | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 监听来自预览页面的消息 | ||||||||||||||||||||||||||||||||||||||||||||
| const setupMessageListener = () => { | ||||||||||||||||||||||||||||||||||||||||||||
| window.addEventListener('message', async (event) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const parsedOrigin = new URL(event.origin) | ||||||||||||||||||||||||||||||||||||||||||||
| const parsedHost = new URL(window.location.href) | ||||||||||||||||||||||||||||||||||||||||||||
| // 确保消息来源安全 | ||||||||||||||||||||||||||||||||||||||||||||
| if (parsedOrigin.origin === parsedHost.origin || parsedOrigin.host === parsedHost.host) { | ||||||||||||||||||||||||||||||||||||||||||||
| const { event: eventType, source } = event.data || {} | ||||||||||||||||||||||||||||||||||||||||||||
| // 通过 heartbeat 消息来重新建立连接,避免刷新页面后 previewWindow 为 null | ||||||||||||||||||||||||||||||||||||||||||||
| if (source === 'preview' && eventType === 'connect' && !previewWindow) { | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+165
to
+172
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Same issue described for - const parsedOrigin = new URL(event.origin)
- const parsedHost = new URL(window.location.href)
+ if (event.origin === 'null') return
+ const parsedOrigin = new URL(event.origin)
+ const parsedHost = new URL(window.location.href)Prevents silent failures when the designer is served from 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
| previewWindow = event.source | ||||||||||||||||||||||||||||||||||||||||||||
| setupSchemaChangeListener() | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (source === 'preview' && eventType === 'onMounted' && previewWindow) { | ||||||||||||||||||||||||||||||||||||||||||||
| const params = await getSchemaParams() | ||||||||||||||||||||||||||||||||||||||||||||
| sendSchemaUpdate(params) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 创建 BroadcastChannel 实例用于通信 | ||||||||||||||||||||||||||||||||||||||||||||
| const previewChannel = new BroadcastChannel('tiny-engine-preview-channel') | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 可能是刷新,需要重新建立连接 | ||||||||||||||||||||||||||||||||||||||||||||
| previewChannel.postMessage({ | ||||||||||||||||||||||||||||||||||||||||||||
| event: 'connect', | ||||||||||||||||||||||||||||||||||||||||||||
| source: 'designer' | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| previewChannel.close() | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 初始化消息监听 | ||||||||||||||||||||||||||||||||||||||||||||
| setupMessageListener() | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const handleHistoryPreview = (params, url) => { | ||||||||||||||||||||||||||||||||||||||||||||
| let historyPreviewWindow = null | ||||||||||||||||||||||||||||||||||||||||||||
| const handlePreviewReady = (event) => { | ||||||||||||||||||||||||||||||||||||||||||||
| if (event.origin === window.location.origin || event.origin.includes(window.location.hostname)) { | ||||||||||||||||||||||||||||||||||||||||||||
| const { event: eventType, source } = event.data || {} | ||||||||||||||||||||||||||||||||||||||||||||
| if (source === 'preview' && eventType === 'onMounted' && historyPreviewWindow) { | ||||||||||||||||||||||||||||||||||||||||||||
| const { scripts, styles, ancestors = [], ...rest } = params | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| historyPreviewWindow.postMessage( | ||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||
| source: 'designer', | ||||||||||||||||||||||||||||||||||||||||||||
| type: 'schema', | ||||||||||||||||||||||||||||||||||||||||||||
| data: deepClone({ | ||||||||||||||||||||||||||||||||||||||||||||
| currentPage: rest, | ||||||||||||||||||||||||||||||||||||||||||||
| ancestors, | ||||||||||||||||||||||||||||||||||||||||||||
| scripts, | ||||||||||||||||||||||||||||||||||||||||||||
| styles | ||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||
| previewWindow.origin || window.location.origin | ||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 历史页面不需要实时更新预览,发送完消息后移除监听 | ||||||||||||||||||||||||||||||||||||||||||||
| window.removeEventListener('message', handlePreviewReady) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| window.addEventListener('message', handlePreviewReady) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| historyPreviewWindow = window.open(url, '_blank') | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const getQueryParams = (params = {}, isHistory = false) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const paramsMap = new URLSearchParams(location.search) | ||||||||||||||||||||||||||||||||||||||||||||
| const tenant = paramsMap.get('tenant') || '' | ||||||||||||||||||||||||||||||||||||||||||||
| const pageId = paramsMap.get('pageid') | ||||||||||||||||||||||||||||||||||||||||||||
| const blockId = paramsMap.get('blockid') | ||||||||||||||||||||||||||||||||||||||||||||
| const theme = getMetaApi(META_SERVICE.ThemeSwitch)?.getThemeState()?.theme | ||||||||||||||||||||||||||||||||||||||||||||
| const framework = getMergeMeta('engine.config')?.dslMode | ||||||||||||||||||||||||||||||||||||||||||||
| const platform = getMergeMeta('engine.config')?.platformId | ||||||||||||||||||||||||||||||||||||||||||||
| const { scripts, styles } = getScriptAndStyleDeps() | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| let query = `tenant=${tenant}&id=${paramsMap.get('id')}&theme=${theme}&framework=${framework}` | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| query += `&platform=${platform}&scripts=${JSON.stringify(scripts)}&styles=${JSON.stringify(styles)}` | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (pageId) { | ||||||||||||||||||||||||||||||||||||||||||||
| query += `&pageid=${pageId}` | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (blockId) { | ||||||||||||||||||||||||||||||||||||||||||||
| query += `&blockid=${blockId}` | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (isHistory) { | ||||||||||||||||||||||||||||||||||||||||||||
| query += `&history=${params.history}` | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return query | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const open = (params = {}, isHistory = false) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const href = window.location.href.split('?')[0] || './' | ||||||||||||||||||||||||||||||||||||||||||||
| const tenant = new URLSearchParams(location.search).get('tenant') || '' | ||||||||||||||||||||||||||||||||||||||||||||
| const { scripts, styles } = getScriptAndStyleDeps() | ||||||||||||||||||||||||||||||||||||||||||||
| const query = getQueryParams(params, isHistory) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| let openUrl = '' | ||||||||||||||||||||||||||||||||||||||||||||
| const hashString = utoa(JSON.stringify(params)) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| openUrl = isDevelopEnv | ||||||||||||||||||||||||||||||||||||||||||||
| ? `./preview.html?tenant=${tenant}#${hashString}` | ||||||||||||||||||||||||||||||||||||||||||||
| : `${href.endsWith('/') ? href : `${href}/`}preview?tenant=${tenant}#${hashString}` | ||||||||||||||||||||||||||||||||||||||||||||
| // 从预览组件配置获取自定义URL | ||||||||||||||||||||||||||||||||||||||||||||
| const customPreviewUrl = getMergeMeta('engine.toolbars.preview')?.options?.previewUrl | ||||||||||||||||||||||||||||||||||||||||||||
| const defaultPreviewUrl = isDevelopEnv ? `./preview.html` : `${href.endsWith('/') ? href : `${href}/`}preview` | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const aTag = document.createElement('a') | ||||||||||||||||||||||||||||||||||||||||||||
| aTag.href = openUrl | ||||||||||||||||||||||||||||||||||||||||||||
| aTag.target = '_blank' | ||||||||||||||||||||||||||||||||||||||||||||
| aTag.click() | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| if (customPreviewUrl) { | ||||||||||||||||||||||||||||||||||||||||||||
| // 如果配置了自定义预览URL,则使用自定义URL | ||||||||||||||||||||||||||||||||||||||||||||
| openUrl = | ||||||||||||||||||||||||||||||||||||||||||||
| typeof customPreviewUrl === 'function' | ||||||||||||||||||||||||||||||||||||||||||||
| ? customPreviewUrl(defaultPreviewUrl, query) | ||||||||||||||||||||||||||||||||||||||||||||
| : `${customPreviewUrl}?${query}` | ||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||
| // 否则使用默认生成的URL | ||||||||||||||||||||||||||||||||||||||||||||
| openUrl = `${defaultPreviewUrl}?${query}` | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (isHistory) { | ||||||||||||||||||||||||||||||||||||||||||||
| handleHistoryPreview({ ...params, scripts, styles }, openUrl) | ||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (previewWindow && !previewWindow.closed) { | ||||||||||||||||||||||||||||||||||||||||||||
| // 如果预览窗口存在,则聚焦预览窗口 | ||||||||||||||||||||||||||||||||||||||||||||
| previewWindow.focus() | ||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // 打开新窗口并保存引用 | ||||||||||||||||||||||||||||||||||||||||||||
| previewWindow = window.open(openUrl, '_blank') | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+288
to
296
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Existing preview window is focused but not refreshed When the preview window already exists, Minimal fix – trigger an immediate sync before early-return: - if (previewWindow && !previewWindow.closed) {
- // 如果预览窗口存在,则聚焦预览窗口
- previewWindow.focus()
- return
- }
+ if (previewWindow && !previewWindow.closed) {
+ previewWindow.focus()
+ // force immediate schema push so that deps / params stay in sync
+ getSchemaParams().then(sendSchemaUpdate).catch(console.error)
+ return
+ }Ensures the user sees the latest state without needing an extra schema-changing action. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
| export const previewPage = (params = {}) => { | ||||||||||||||||||||||||||||||||||||||||||||
| params.type = COMPONENT_NAME.Page | ||||||||||||||||||||||||||||||||||||||||||||
| open(params) | ||||||||||||||||||||||||||||||||||||||||||||
| // 设置 schemaChange 事件监听 | ||||||||||||||||||||||||||||||||||||||||||||
| setupSchemaChangeListener() | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| export const previewBlock = (params = {}) => { | ||||||||||||||||||||||||||||||||||||||||||||
| params.type = COMPONENT_NAME.Block | ||||||||||||||||||||||||||||||||||||||||||||
| open(params) | ||||||||||||||||||||||||||||||||||||||||||||
| export const previewPage = (params = {}, isHistory = false) => { | ||||||||||||||||||||||||||||||||||||||||||||
| open(params, isHistory) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,11 +14,13 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </template> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <script lang="jsx"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { watch } from 'vue' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useBreadcrumb, getMergeRegistry, getMergeMeta } from '@opentiny/tiny-engine-meta-register' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Switch as TinySwitch } from '@opentiny/vue' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { getSearchParams } from './preview/http' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { constants } from '@opentiny/tiny-engine-utils' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { BROADCAST_CHANNEL } from '../src/preview/srcFiles/constant' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { injectDebugSwitch } from './preview/debugSwitch' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { previewState } from './preview/usePreviewData' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| components: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -30,10 +32,18 @@ export default { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ChangeLang = getMergeRegistry('toolbars', 'engine.toolbars.lang')?.entry | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const langOptions = getMergeMeta('engine.toolbars.lang').options | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ToolbarMedia = null // TODO: Media plugin rely on layout/canvas. Further processing is required. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { setBreadcrumbPage, setBreadcrumbBlock } = useBreadcrumb() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { setBreadcrumbPage } = useBreadcrumb() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { pageInfo } = getSearchParams() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setBreadcrumbPage([pageInfo?.name]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| watch( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| () => previewState.currentPage, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (newVal) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (newVal?.page_content?.componentName === constants.COMPONENT_NAME.Block) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setBreadcrumbBlock([newVal?.name_cn || newVal?.page_content?.fileName]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setBreadcrumbPage([newVal?.name]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+35
to
47
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainEnsure breadcrumb is initialized on first render
- watch(
- () => previewState.currentPage,
- (newVal) => {
+ watch(
+ () => previewState.currentPage,
+ (newVal) => {
if (newVal?.page_content?.componentName === constants.COMPONENT_NAME.Block) {
setBreadcrumbBlock([newVal?.name_cn || newVal?.page_content?.fileName])
} else {
setBreadcrumbPage([newVal?.name])
}
- }
+ },
+ { immediate: true }
)🏁 Script executed: #!/bin/bash
# Locate Toolbar.vue to confirm import and signature of watch
fd --extension vue Toolbar.vue
# Inspect the top of the file to see how watch is imported
sed -n '1,20p' packages/design-core/src/preview/src/Toolbar.vueLength of output: 959 Add immediate option to breadcrumb watcher File: watch(
() => previewState.currentPage,
(newVal) => {
if (newVal?.page_content?.componentName === constants.COMPONENT_NAME.Block) {
setBreadcrumbBlock([newVal?.name_cn || newVal?.page_content?.fileName])
} else {
setBreadcrumbPage([newVal?.name])
}
- }
+ },
+ { immediate: true }
)📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const setViewPort = (item) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const iframe = document.getElementsByClassName('iframe-container')[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify if hot reload should be disabled by default
Adding
previewHotReload: falseexplicitly disables hot reload for the preview in the demo environment. Consider whether this is the desired default behavior for demonstration purposes.🏁 Script executed:
Length of output: 180
Let’s search without restricting file types to see if this setting appears elsewhere:
🏁 Script executed:
Length of output: 3124
Clarify previewHotReload default behavior
The
previewHotReloadoption defaults to live‐update (true) when not specified. In the demo you’ve explicitly turned it off:Please decide which you intend for the demo:
previewHotReload: falseoverride so the preview hot‐reload remains enabled by default.