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: materials new protocol #940

Merged
merged 27 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0e38294
feat: 物料资产包协议修改
yy-wow Dec 16, 2024
c0ee9b3
fix:容错处理packages不存在的情况
yy-wow Dec 16, 2024
7b910c5
fix:新建或修改npm类型工具类都要触发画布重新渲染
yy-wow Dec 16, 2024
6c49614
fix:动态导入组件库模块失败
yy-wow Dec 18, 2024
c971b2b
fix:动态导入组件库模块失败
yy-wow Dec 18, 2024
b277596
fix:画布物料依赖优化
yy-wow Dec 18, 2024
27cb75e
Merge branch 'refactor/develop' into feat/materials-new-protocol
yy-wow Jan 9, 2025
9ec89fb
fix: 新增或修改npm类型的utils更新画布
yy-wow Jan 9, 2025
50ef894
fix: 字段修改
yy-wow Jan 9, 2025
775f6c9
fix: 修复报错
yy-wow Jan 9, 2025
49caefe
fix: 修复工具类更新问题
yy-wow Jan 11, 2025
1942594
fix: 修复预览依赖字段问题
yy-wow Jan 11, 2025
8c36268
fix: 删除无用代码
yy-wow Jan 13, 2025
d8dd7eb
fix: 工具类依赖不添加到importmap,改为直接import cdn地址
yy-wow Jan 13, 2025
90917fa
fix: 预览页面工具类依赖处理
yy-wow Jan 13, 2025
b26bbf4
fix: 更新注释
yy-wow Jan 13, 2025
330c3a1
fix: review
yy-wow Jan 13, 2025
6de0c1f
fix: utils添加importmap字段修复
yy-wow Jan 13, 2025
861a6fc
fix: review
yy-wow Jan 13, 2025
12f43b0
Merge branch 'refactor/develop' into feat/materials-new-protocol
yy-wow Jan 14, 2025
58a3376
Merge branch 'refactor/develop' into feat/materials-new-protocol
yy-wow Jan 15, 2025
6d22724
fix: 动态加载npm类型工具类
yy-wow Jan 15, 2025
16e762a
fix: 卸载时停止订阅通知
yy-wow Jan 15, 2025
29fa9de
fix: 修复类型问题
yy-wow Jan 15, 2025
20d054c
fix: 卸载时停止订阅通知
yy-wow Jan 15, 2025
e2a5eb4
fix: 优化注释
yy-wow Jan 15, 2025
0df006e
fix: 兼容旧的物料协议
yy-wow Jan 15, 2025
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
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]
yy-wow marked this conversation as resolved.
Show resolved Hide resolved

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]
}
})
yy-wow marked this conversation as resolved.
Show resolved Hide resolved
}
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)
yy-wow marked this conversation as resolved.
Show resolved Hide resolved

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
Loading