Skip to content
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

feat:preview multi page structured data transfer and nested display #978

Merged
merged 3 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 40 additions & 12 deletions packages/design-core/src/preview/src/preview/Preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export default {
const debugSwitch = injectDebugSwitch()
const editorComponent = computed(() => (debugSwitch?.value ? Monaco : EmptyEditor))
const store = new ReplStore()
const { getAllNestedBlocksSchema, generatePageCode } = getMetaApi('engine.service.generateCode')
const ROOT_ID = '0'

const sfcOptions = {
script: {
Expand Down Expand Up @@ -84,6 +86,43 @@ export default {
return getInitImportMap()
}

const getFamilyPages = (appData) => {
const familyPages = []
const ancestors = queryParams.ancestors

for (let i = 0; i < ancestors.length; i++) {
const nextPage = i < ancestors.length - 1 ? ancestors[i + 1].name : null
const panelValueAndType = {
panelValue:
generatePageCode(
ancestors[i].page_content,
appData?.componentsMap || [],
{
blockRelativePath: './'
},
nextPage
) || '',
panelType: 'vue'
}

if (ancestors[i]?.parentId === ROOT_ID) {
familyPages.push({
...panelValueAndType,
panelName: 'Main.vue',
index: true
})
} else {
familyPages.push({
...panelValueAndType,
panelName: `${ancestors[i].name}.vue`,
index: false
})
}
}

return familyPages
}

const promiseList = [
fetchAppSchema(queryParams?.app),
fetchMetaData(queryParams),
Expand All @@ -93,22 +132,12 @@ export default {
Promise.all(promiseList).then(async ([appData, metaData, _void, importMapData]) => {
addUtilsImportMap(importMapData, metaData.utils || [])

const { getAllNestedBlocksSchema, generatePageCode } = getMetaApi('engine.service.generateCode')

const blocks = await getAllNestedBlocksSchema(queryParams.pageInfo?.schema, fetchBlockSchema)

// TODO: 需要验证级联生成 block schema
// TODO: 物料内置 block 需要如何处理?
const pageCode = [
{
panelName: 'Main.vue',
panelValue:
generatePageCode(queryParams.pageInfo?.schema, appData?.componentsMap || [], {
blockRelativePath: './'
}) || '',
panelType: 'vue',
index: true
},
...getFamilyPages(appData),
...(blocks || []).map((blockSchema) => {
return {
panelName: `${blockSchema.fileName}.vue`,
Expand Down Expand Up @@ -171,7 +200,6 @@ export default {
Object.assign(newFiles, metaFiles)

setFiles(newFiles)

return PreviewTips.READY_FOR_PREVIEW
})

Expand Down
43 changes: 28 additions & 15 deletions packages/plugins/page/src/composable/usePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,21 @@ const getPageList = async (appId) => {
return pageSettingState.pages
}

/**
* @param {string | number} id
* @param {(string | number)[]} ancestors
* @returns {(string | number)[]}
*/
const getAncestorsRecursively = (id) => {
const pageNode = pageSettingState.treeDataMapping[id]

if (pageNode.id === pageSettingState.ROOT_ID) {
return []
}

return [pageNode].concat(getAncestorsRecursively(pageNode.parentId))
}

/**
* @param {string | number} id page Id
* @param {boolean} withFolders default `false`
Expand All @@ -222,30 +237,27 @@ const getAncestors = async (id, withFolders) => {
await getPageList(appId)
}

/**
* @param {string | number} id
* @param {(string | number)[]} ancestors
* @returns {(string | number)[]}
*/
const getAncestorsRecursively = (id) => {
const pageNode = pageSettingState.treeDataMapping[id]

if (pageNode.id === pageSettingState.ROOT_ID) {
return []
}

return [pageNode].concat(getAncestorsRecursively(pageNode.parentId))
}

const ancestorsWithSelf = getAncestorsRecursively(id)
const ancestors = ancestorsWithSelf.slice(1).reverse()

if (withFolders) {
return ancestors.map((item) => item.id)
}

return ancestors.filter((item) => item.isPage).map((item) => item.id)
}

const getFamily = async (id) => {
if (pageSettingState.pages.length === 0) {
const appId = getMetaApi(META_SERVICE.GlobalService).getBaseInfo().id
await getPageList(appId)
}

return getAncestorsRecursively(id)
.filter((item) => item.isPage)
.reverse()
}

export default () => {
return {
DEFAULT_PAGE,
Expand All @@ -261,6 +273,7 @@ export default () => {
isChangePageData,
getPageList,
getAncestors,
getFamily,
STATIC_PAGE_GROUP_ID,
COMMON_PAGE_GROUP_ID
}
Expand Down
4 changes: 3 additions & 1 deletion packages/toolbars/preview/src/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<script>
import { previewPage, previewBlock } from '@opentiny/tiny-engine-common/js/preview'
import { useBlock, useCanvas, useLayout, useNotify } from '@opentiny/tiny-engine-meta-register'
import { useBlock, useCanvas, useLayout, useNotify, usePage } from '@opentiny/tiny-engine-meta-register'
import { getMergeMeta, getOptions } from '@opentiny/tiny-engine-meta-register'
import meta from '../meta'
import { ToolbarBase } from '@opentiny/tiny-engine-common'
Expand All @@ -30,6 +30,7 @@ export default {
setup() {
const { isBlock, getCurrentPage, canvasApi } = useCanvas()
const { getCurrentBlock } = useBlock()
const { getFamily } = usePage()

const preview = async () => {
const { beforePreview, previewMethod, afterPreview } = getOptions(meta.id)
Expand Down Expand Up @@ -79,6 +80,7 @@ export default {
const page = getCurrentPage()
params.id = page?.id
params.pageInfo.name = page?.name
params.ancestors = await getFamily(params.id)
previewPage(params)
}

Expand Down
15 changes: 10 additions & 5 deletions packages/vue-generator/src/generator/vue/sfc/genSetupSFC.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const defaultStyleConfig = {
lang: ''
}

const generateSFCFile = (schema, componentsMap, config = {}) => {
const generateSFCFile = (schema, componentsMap, config = {}, nextPage) => {
const parsedConfig = parseConfig(config)
const { blockRelativePath, blockSuffix, scriptConfig: initScriptConfig, styleConfig: initStyleConfig } = parsedConfig
// 前置动作,对 Schema 进行解析初始化相关配置与变量
Expand Down Expand Up @@ -197,18 +197,23 @@ const generateSFCFile = (schema, componentsMap, config = {}) => {
}

// 解析 template
const templateStr = genTemplateByHook(schema, globalHooks, { ...parsedConfig, componentsMap: componentsMap })
const templateStr = genTemplateByHook(
schema,
globalHooks,
{ ...parsedConfig, componentsMap: componentsMap },
nextPage
)

// 生成 script
const scriptStr = genScriptByHook(schema, globalHooks, { ...parsedConfig, componentsMap: componentsMap })
const scriptStr = genScriptByHook(schema, globalHooks, { ...parsedConfig, componentsMap: componentsMap }, nextPage)

// 生成 style
const styleStr = generateStyleTag(schema, styleConfig)

return `${templateStr}\n${scriptStr}\n${styleStr}`
}

export const genSFCWithDefaultPlugin = (schema, componentsMap, config = {}) => {
export const genSFCWithDefaultPlugin = (schema, componentsMap, config = {}, nextPage) => {
const { templateItemValidate = [], genTemplate = [], parseScript = [], genScript = {} } = config.hooks || {}
const defaultComponentHooks = [handleComponentNameHook, handleTinyIcon]

Expand Down Expand Up @@ -265,7 +270,7 @@ export const genSFCWithDefaultPlugin = (schema, componentsMap, config = {}) => {
// 兼容单独调用的场景,单独调用时,这里会默认加上 builtInComponents
const compsMapWithBuiltIn = [...componentsMap, ...BUILTIN_COMPONENTS_MAP]

return generateSFCFile(schema, compsMapWithBuiltIn, newConfig)
return generateSFCFile(schema, compsMapWithBuiltIn, newConfig, nextPage)
}

export default generateSFCFile
19 changes: 11 additions & 8 deletions packages/vue-generator/src/generator/vue/sfc/generateScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import { INSERT_POSITION } from '@/constant'
import { transformObjType } from './generateAttribute'
import { hasJsx } from '@/utils/hasJsx'

export const defaultGenImportHook = (schema, globalHooks) => {
export const defaultGenImportHook = (schema, globalHooks, config, nextPage) => {
const dependenciesMap = globalHooks.getImport() || {}
const importContent = Object.entries(dependenciesMap).map(([key, value]) => {
return generateImportByPkgName({ pkgName: key, imports: value }) || ''
})

return Object.entries(dependenciesMap)
.map(([key, value]) => {
return generateImportByPkgName({ pkgName: key, imports: value }) || ''
})
.join('\n')
if (nextPage) {
importContent.push(`import ${nextPage} from "./${nextPage}.vue"`)
}

return importContent.join('\n')
}

export const defaultGenPropsHook = (schema) => {
Expand Down Expand Up @@ -162,7 +165,7 @@ export const GEN_SCRIPT_HOOKS = {
GEN_LIFECYCLE: 'GEN_LIFECYCLE'
}

export const genScriptByHook = (schema, globalHooks, config) => {
export const genScriptByHook = (schema, globalHooks, config, nextPage) => {
const hooks = config.hooks || {}
const { parseScript = [], genScript = {} } = hooks

Expand Down Expand Up @@ -206,7 +209,7 @@ export const genScriptByHook = (schema, globalHooks, config) => {
statementGroupByPosition[AFTER_METHODS].push(statement?.value)
})

const importStr = genScript[GEN_SCRIPT_HOOKS.GEN_IMPORT]?.(schema, globalHooks, config) || ''
const importStr = genScript[GEN_SCRIPT_HOOKS.GEN_IMPORT]?.(schema, globalHooks, config, nextPage) || ''
const propsStr = genScript[GEN_SCRIPT_HOOKS.GEN_PROPS]?.(schema, globalHooks, config) || ''
const emitStr = genScript[GEN_SCRIPT_HOOKS.GEN_EMIT]?.(schema, globalHooks, config) || ''
const stateStr = genScript[GEN_SCRIPT_HOOKS.GEN_STATE]?.(schema, globalHooks, config) || ''
Expand Down
15 changes: 9 additions & 6 deletions packages/vue-generator/src/generator/vue/sfc/generateTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,14 @@ export const validEmptyTemplateHook = (schema = {}) => {

// TODO: 支持物料中自定义出码关联片段

export const recursiveGenTemplateByHook = (schemaWithRes, globalHooks, config = {}) => {
export const recursiveGenTemplateByHook = (schemaWithRes, globalHooks, config = {}, nextPage) => {
const schemaChildren = schemaWithRes?.schema?.children || []
const { hooks = {}, isJSX } = config
// 自定义 hooks
const { genTemplate: genTemplateHooks, templateItemValidate } = hooks

if (!Array.isArray(schemaChildren)) {
schemaWithRes.children.push(schemaChildren || '')

return
}

Expand All @@ -195,7 +194,11 @@ export const recursiveGenTemplateByHook = (schemaWithRes, globalHooks, config =
return schemaItem || ''
}

const { componentName, component } = schemaItem
let { componentName, component } = schemaItem

if (nextPage) {
componentName = componentName === 'RouterView' ? nextPage : componentName
}

const optionData = {
schema: schemaItem,
Expand All @@ -208,7 +211,7 @@ export const recursiveGenTemplateByHook = (schemaWithRes, globalHooks, config =
}

for (const hookItem of [...genTemplateHooks, recursiveGenTemplateByHook]) {
hookItem(optionData, globalHooks, config)
hookItem(optionData, globalHooks, config, nextPage)
}

const startTag = generateTag(optionData.componentName, {
Expand All @@ -230,13 +233,13 @@ ${optionData.prefix.join('')}${startTag}${optionData.children.join('')}${endTag}
schemaWithRes.children = schemaWithRes.children.concat(resArr)
}

export const genTemplateByHook = (schema, globalHooks, config) => {
export const genTemplateByHook = (schema, globalHooks, config, nextPage) => {
const parsedSchema = {
children: [],
schema: structuredClone({ children: [{ ...schema, componentName: 'div' }] })
}

recursiveGenTemplateByHook(parsedSchema, globalHooks, config)
recursiveGenTemplateByHook(parsedSchema, globalHooks, config, nextPage)

return `<template>${parsedSchema.children.join('')}</template>`
}