Skip to content

Commit

Permalink
feat: materials new protocol (opentiny#940)
Browse files Browse the repository at this point in the history
  • Loading branch information
yy-wow authored Jan 15, 2025
1 parent bf30f72 commit a7477a8
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 325 deletions.
233 changes: 49 additions & 184 deletions designer-demo/public/mock/bundle.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion mockServer/src/mock/get/app-center/v1/apps/schema/918.json
Original file line number Diff line number Diff line change
Expand Up @@ -2092,7 +2092,8 @@
"value": "",
"package": "axios",
"destructuring": false,
"exportName": "axios"
"exportName": "axios",
"cdnLink": "https://unpkg.com/browse/[email protected]/dist/esm/axios.min.js"
}
},
{
Expand Down
24 changes: 19 additions & 5 deletions packages/canvas/DesignCanvas/src/DesignCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,21 @@ export default {
const canvasRef = ref(null)
let showModal = false // 弹窗标识
const { canvasSrc = '' } = getOptions(meta.id) || {}
let canvasSrcDoc = ''
const canvasSrcDoc = ref('')
if (!canvasSrc) {
const { importMap, importStyles } = getImportMapData(getMergeMeta('engine.config')?.importMapVersion)
canvasSrcDoc = initCanvas(importMap, importStyles).html
}
useMessage().subscribe({
topic: 'init_canvas_deps',
subscriber: 'canvas_design_canvas',
callback: (deps) => {
if (canvasSrc) {
return
}
const { importMap, importStyles } = getImportMapData(getMergeMeta('engine.config')?.importMapVersion, deps)
canvasSrcDoc.value = initCanvas(importMap, importStyles).html
}
})
const removeNode = (node) => {
const { pageState } = useCanvas()
Expand Down Expand Up @@ -231,6 +240,11 @@ export default {
})
onUnmounted(() => {
window.removeEventListener('popstate', postUrlChanged)
useMessage().unsubscribe({
topic: 'init_canvas_deps',
subscriber: 'canvas_design_canvas'
})
})
return {
Expand Down
15 changes: 12 additions & 3 deletions packages/canvas/DesignCanvas/src/importMap.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VITE_CDN_DOMAIN } from '@opentiny/tiny-engine-common/js/environments'

export function getImportMapData(overrideVersions = {}) {
export function getImportMapData(overrideVersions = {}, canvasDeps = { scripts: [], styles: [] }) {
const importMapVersions = Object.assign(
{
vue: '3.4.23',
Expand Down Expand Up @@ -32,16 +32,25 @@ export function getImportMapData(overrideVersions = {}) {
}
}

const materialsAndUtilsRequire = canvasDeps.scripts.reduce((imports, { package: pkg, script }) => {
if (pkg && script) {
imports[pkg] = script
}

return imports
}, {})

const importMap = {
imports: {
vue: `${VITE_CDN_DOMAIN}/vue@${importMapVersions.vue}/dist/vue.runtime.esm-browser.prod.js`,
'vue-i18n': `${VITE_CDN_DOMAIN}/vue-i18n@${importMapVersions.vueI18n}/dist/vue-i18n.esm-browser.js`,
...blockRequire.imports,
...tinyVueRequire.imports
...tinyVueRequire.imports,
...materialsAndUtilsRequire
}
}

const importStyles = [...blockRequire.importStyles]
const importStyles = [...blockRequire.importStyles, ...canvasDeps.styles]

return {
importMap,
Expand Down
45 changes: 24 additions & 21 deletions packages/canvas/common/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,20 @@ export const copyObject = (node) => {
}

/**
* 动态导入组件,缓存组件对象
* @param {object} param0 组件的依赖: { package: 包名,script:js文件cdn, components:组件id和导出组件名的映射关系}
* 动态导入获取组件库模块
* @param {*} pkg 模块名称
* @param {*} script 模块的cdn地址
* @returns
*/
export const dynamicImportComponents = async ({ package: pkg, script, components }) => {
if (!script) return
const dynamicImportComponentLib = async ({ pkg, script }) => {
if (window.TinyComponentLibs[pkg]) {
return window.TinyComponentLibs[pkg]
}

if (!script) {
return {}
}

const href = window.parent.location.href || location.href // 这里要取父窗口的地址,因为在iframe中href是about:srcdoc
const scriptUrl = script.startsWith('.') ? new URL(script, href).href : script

Expand All @@ -71,27 +79,22 @@ export const dynamicImportComponents = async ({ package: pkg, script, components
window.TinyComponentLibs[pkg] = modules
}

Object.entries(components).forEach(([componentId, exportName]) => {
const modules = window.TinyComponentLibs[pkg]

if (!window.TinyLowcodeComponent[componentId]) {
window.TinyLowcodeComponent[componentId] = modules[exportName]
}
})
return window.TinyComponentLibs[pkg]
}

/**
* 更新区块/组件依赖
* @param {object} param0 依赖的CDN信息
* 获取组件对象并缓存,组件渲染时使用
* @param {object} param0 组件的依赖: { package: 包名,script:js文件cdn, components:组件id和导出组件名的映射关系}
* @returns
*/
export const updateDependencies = ({ detail }) => {
const { scripts = [], styles = [] } = detail || {}
const { styles: canvasStyles } = window.thirdPartyDeps
const newStyles = [...styles].filter((item) => !canvasStyles.has(item))
export const getComponents = async ({ package: pkg, script, components }) => {
if (!pkg) return

newStyles.forEach((item) => canvasStyles.add(item))
const modules = await dynamicImportComponentLib({ pkg, script })

const promises = [...newStyles].map((src) => addStyle(src)).concat(scripts.map(dynamicImportComponents))

Promise.allSettled(promises)
Object.entries(components).forEach(([componentId, exportName]) => {
if (!window.TinyLowcodeComponent[componentId]) {
window.TinyLowcodeComponent[componentId] = modules[exportName]
}
})
}
5 changes: 3 additions & 2 deletions packages/canvas/container/src/CanvasContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<script>
import { onMounted, ref, computed, onUnmounted, watch, watchEffect } from 'vue'
import { iframeMonitoring } from '@opentiny/tiny-engine-common/js/monitor'
import { useTranslate, useCanvas, useMaterial, useMessage, useResource } from '@opentiny/tiny-engine-meta-register'
import { useTranslate, useCanvas, useMessage, useResource } from '@opentiny/tiny-engine-meta-register'
import { NODE_UID, NODE_LOOP, DESIGN_MODE } from '../../common'
import { registerHostkeyEvent, removeHostkeyEvent } from './keyboard'
import CanvasMenu, { closeMenu, openMenu } from './components/CanvasMenu.vue'
Expand Down Expand Up @@ -117,7 +117,8 @@ export default {
const beforeCanvasReady = () => {
if (iframe.value) {
const win = iframe.value.contentWindow
win.thirdPartyDeps = useMaterial().materialState.thirdPartyDeps
// 用于画布初始化组件依赖
win.componentsDeps = useResource().appSchemaState.materialsDeps.scripts.filter((item) => item.components)
const { subscribe, unsubscribe } = useMessage()
const { getSchemaDiff, patchLatestSchema, getSchema, getNode } = useCanvas()
Expand Down
1 change: 0 additions & 1 deletion packages/canvas/container/src/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,5 @@ export const initCanvas = ({ renderer, iframe, emit, controller }) => {
}

setConfigure(useMaterial().getConfigureMap())
canvasDispatch('updateDependencies', { detail: useMaterial().materialState.thirdPartyDeps })
canvasState.loading = false
}
26 changes: 25 additions & 1 deletion packages/canvas/render/src/application-function/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ref } from 'vue'
import TinyVue from '@opentiny/vue'
import * as TinyVueIcon from '@opentiny/vue-icon'
import { generateFunction } from '../data-utils'
import { globalNotify } from '../canvas-function'

export interface IUtil {
name: string
Expand All @@ -18,7 +19,7 @@ export function useUtils(context: Record<string, any>) {
const utils: Record<string, Function | any> = {}
const getUtils = () => utils

const setUtils = (data: Array<IUtil>) => {
const setUtils = async (data: Array<IUtil>) => {
if (!Array.isArray(data)) {
return
}
Expand Down Expand Up @@ -52,6 +53,29 @@ export function useUtils(context: Record<string, any>) {
utilsCollection[item.name] = generateFunction(item.content.value, context) || defaultFn
}
})

const npmUtilsImports = data
.filter((item) => item.type === 'npm' && item.content.cdnLink)
.map((item) => import(/* @vite-ignore */ item.content.cdnLink))
const npmUtils = await Promise.allSettled(npmUtilsImports)

npmUtils.forEach((res, index) => {
const { name, content } = data[index]
const { exportName, destructuring, cdnLink } = content

if (res.status !== 'fulfilled') {
globalNotify({
type: 'error',
message: `加载工具类“${name}”失败,请检查cdn链接是否正确,${cdnLink}`
})

return
}

const module = res.value
utilsCollection[name] = destructuring ? module[exportName] : module.default
})

Object.assign(utils, utilsCollection)

refreshKey.value++
Expand Down
10 changes: 4 additions & 6 deletions packages/canvas/render/src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/

import { createApp } from 'vue'
import { addScript, addStyle, dynamicImportComponents, updateDependencies } from '../../common/index.js'
import { addScript, addStyle, getComponents } from '../../common'
import TinyI18nHost, { I18nInjectionKey } from '@opentiny/tiny-engine-common/js/i18n'
import Main, { api } from './RenderMain'
import lowcode from './lowcode'
Expand All @@ -31,8 +31,6 @@ const initRenderContext = () => {

window.TinyLowcodeComponent = {}
window.TinyComponentLibs = {}

document.addEventListener('updateDependencies', updateDependencies)
}

let App = null
Expand Down Expand Up @@ -83,10 +81,10 @@ export const createRender = (config) => {
initRenderContext()

const { styles = [], scripts = [] } = config.canvasDependencies
const { styles: thirdStyles = [], scripts: thirdScripts = [] } = window.thirdPartyDeps || {}
const componentsDeps = window.componentsDeps || []

Promise.all([
...thirdScripts.map(dynamicImportComponents),
...scripts.map((src) => addScript(src)).concat([...thirdStyles, ...styles].map((src) => addStyle(src)))
...componentsDeps.map(getComponents),
...scripts.map((src) => addScript(src)).concat(styles.map((src) => addStyle(src)))
]).finally(() => create(config))
}
5 changes: 5 additions & 0 deletions packages/canvas/render/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ export declare global {
TinyGlobalConfig: Record<string, any>
loadBlockComponent: (blockName: string) => Promise<any>
host: any
componentsDeps: Array<{
script: string
package: string
components: Record<string, string>
}>
}
}
17 changes: 9 additions & 8 deletions packages/common/js/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import { constants } from '@opentiny/tiny-engine-utils'
import { isDevelopEnv } from './environments'
import { useMaterial } from '@opentiny/tiny-engine-meta-register'
import { useMaterial, useResource } from '@opentiny/tiny-engine-meta-register'
// prefer old unicode hacks for backward compatibility

const { COMPONENT_NAME } = constants
Expand All @@ -26,13 +26,14 @@ const open = (params = {}) => {
params.app = paramsMap.get('id')
params.tenant = paramsMap.get('tenant')

const { scripts, styles } = useMaterial().materialState.thirdPartyDeps
params.scripts = {}
scripts
.filter((item) => item.script)
.forEach((item) => {
params.scripts[item.package] = item.script
})
const { scripts, styles } = useMaterial().getCanvasDeps()
const utilsDeps = useResource().getUtilsDeps()

params.scripts = [...scripts, ...utilsDeps].reduce((res, item) => {
res[item.package] = item.script

return res
}, {})
params.styles = [...styles]

const href = window.location.href.split('?')[0] || './'
Expand Down
13 changes: 1 addition & 12 deletions packages/design-core/src/preview/src/preview/Preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,6 @@ export default {
store['initTsConfig']() // 触发获取组件d.ts方便调试
}
const addUtilsImportMap = (importMap, utils = []) => {
const utilsImportMaps = {}
utils.forEach(({ type, content: { package: packageName, cdnLink } }) => {
if (type === 'npm' && cdnLink) {
utilsImportMaps[packageName] = cdnLink
}
})
const newImportMap = { imports: { ...importMap.imports, ...utilsImportMaps } }
store.setImportMap(newImportMap)
}
const queryParams = getSearchParams()
const getImportMap = async () => {
if (import.meta.env.VITE_LOCAL_BUNDLE_DEPS === 'true') {
Expand Down Expand Up @@ -134,7 +123,7 @@ export default {
getImportMap()
]
Promise.all(promiseList).then(async ([appData, metaData, _void, importMapData]) => {
addUtilsImportMap(importMapData, metaData.utils || [])
store.setImportMap(importMapData)
const blocks = await getAllNestedBlocksSchema(queryParams.pageInfo?.schema, fetchBlockSchema)
Expand Down
56 changes: 26 additions & 30 deletions packages/plugins/bridge/src/js/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,14 @@ const generateBridgeUtil = (...args) => {
}
}

export const saveResource = (data, callback, emit) => {
if (getActionType() === ACTION_TYPE.Edit) {
data.id = state.resource.id
requestUpdateReSource(data).then((result) => {
export const saveResource = async (data, callback, emit) => {
const isEdit = getActionType() === ACTION_TYPE.Edit

try {
if (isEdit) {
data.id = state.resource.id
const result = await requestUpdateReSource(data)

if (result) {
const index = useResource().appSchemaState[data.category].findIndex((item) => item.name === result.name)

Expand All @@ -192,36 +196,28 @@ export const saveResource = (data, callback, emit) => {
}

useResource().appSchemaState[data.category][index] = result

// 更新画布工具函数环境,保证渲染最新工具类返回值, 并触发画布的强制刷新

generateBridgeUtil(getAppId())

useNotify({
type: 'success',
message: '修改成功'
})

emit('refresh', state.type)
state.refresh = true
callback()
}
})
} else {
requestAddReSource(data).then((result) => {
} else {
const result = await requestAddReSource(data)

if (result) {
useResource().appSchemaState[data.category].push(result)

// 更新画布工具函数环境,保证渲染最新工具类返回值, 并触发画布的强制刷新
generateBridgeUtil(getAppId())
useNotify({
type: 'success',
message: '创建成功'
})
emit('refresh', state.type)
state.refresh = true
callback()
}
}

// 更新画布工具函数环境,保证渲染最新工具类返回值, 并触发画布的强制刷新
generateBridgeUtil(getAppId())
useNotify({
type: 'success',
message: `${isEdit ? '修改' : '创建'}成功`
})
emit('refresh', state.type)
state.refresh = true
callback()
} catch (error) {
useNotify({
type: 'error',
message: `工具类${isEdit ? '修改' : '创建'}失败:${error.message}`
})
}
}
Expand Down
Loading

0 comments on commit a7477a8

Please sign in to comment.