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

refactor(materials): useResource spilt & Message notification for material loading life cycle #716

Open
wants to merge 3 commits into
base: refactor/develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion packages/design-core/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default {
useCanvas().isCanvasApiReady,
(ready) => {
if (ready) {
useResource().fetchResource()
useResource().initResource()
}
},
{
Expand Down
74 changes: 40 additions & 34 deletions packages/plugins/materials/src/composable/useMaterial.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { reactive } from 'vue'
import { useHttp } from '@opentiny/tiny-engine-http'
import { utils, constants } from '@opentiny/tiny-engine-utils'
import { meta as BuiltinComponentMaterials } from '@opentiny/tiny-engine-builtin-component'
import { getMergeMeta, useNotify, useCanvas, useBlock } from '@opentiny/tiny-engine-meta-register'
import { getMergeMeta, useNotify, useCanvas, useBlock, useMessage } from '@opentiny/tiny-engine-meta-register'

const { camelize, capitalize } = utils
const { MATERIAL_TYPE } = constants
Expand All @@ -36,6 +36,13 @@ const materialState = reactive({
const componentState = reactive({
componentsMap: {}
})

const publishMessage = (topicContent) => {
const topic = `lowcode.materials.${topicContent}`
const { publish } = useMessage()
publish({ topic })
}

const getSnippet = (component) => {
let schema = {}
materialState.components.some(({ children }) => {
Expand All @@ -50,7 +57,11 @@ const getSnippet = (component) => {
return schema
}

const generateNode = ({ type, component }) => {
/**
* 生成组件的schema节点
* @returns schema
*/
const generateSchemaNode = ({ type, component }) => {
const snippet = getSnippet(component) || {}
const schema = {
componentName: component,
Expand Down Expand Up @@ -153,12 +164,6 @@ const registerBlock = async (data, notFetchResouce) => {
return block
}

const clearMaterials = () => {
materialState.components = []
materialState.blocks = []
resource.clear()
}

const clearBlockResources = () => blockResource.clear()

/**
Expand Down Expand Up @@ -218,7 +223,6 @@ const addMaterials = (materials = {}) => {
materials.components.forEach(registerComponentToResource)

const promises = materials?.blocks?.map((item) => registerBlock(item, true))

Promise.allSettled(promises).then((blocks) => {
if (!blocks?.length) {
return
Expand Down Expand Up @@ -252,25 +256,23 @@ const getMaterial = (name) => {
}
}

const setMaterial = (name, data) => {
resource.set(name, data)
}

/**
* 获取物料,并返回符合物料协议的bundle.json内容
* @returns getMaterialsRes: () => Promise<Materials>
* @returns fetchUserMaterialData: () => Promise<Materials>
*/
export const getMaterialsRes = async () => {
export const fetchUserMaterialData = async () => {
const bundleUrls = getMergeMeta('engine.config')?.material || []
const materials = await Promise.allSettled(bundleUrls.map((url) => http.get(url)))
return materials
}

const fetchMaterial = async () => {
const materials = await getMaterialsRes()
const initUserMaterial = async () => {
publishMessage('beginFetchMaterialData')
const materials = await fetchUserMaterialData()

materials.forEach((response) => {
if (response.status === 'fulfilled' && response.value.materials) {
publishMessage('endFetchMaterialData')
addMaterials(response.value.materials)
}
})
Expand Down Expand Up @@ -314,6 +316,9 @@ const updateCanvasDependencies = (blocks) => {
useCanvas().canvasApi.value?.canvasDispatch('updateDependencies', { detail: materialState.thirdPartyDeps })
}

/**
* 初始化内置组件
*/
const initBuiltinMaterial = () => {
const { Builtin } = useCanvas().canvasApi.value
Builtin.data.materials.components[0].children.forEach(registerComponentToResource)
Expand All @@ -327,31 +332,32 @@ const initBuiltinMaterial = () => {
materialState.components.push(builtinSnippets)
}

const initMaterial = ({ isInit = true, appData = {} } = {}) => {
/**
*
* @param {*} param
* isInit 是否
*/
const initMaterialModule = async (appData) => {
initBuiltinMaterial()
if (isInit) {
componentState.componentsMap = {}
appData.componentsMap?.forEach((component) => {
if (component.dependencies) {
getBlockDeps(component.dependencies)
}
componentState.componentsMap[component.componentName] = component
})
}
componentState.componentsMap = {}
appData.componentsMap?.forEach((component) => {
if (component.dependencies) {
getBlockDeps(component.dependencies)
}
componentState.componentsMap[component.componentName] = component
})
await initUserMaterial()
}

export default function () {
return {
materialState, // 存放着组件、物料侧区块、第三方依赖信息
initMaterial, // 物料模块初始化
fetchMaterial, // 请求物料并进行处理
getMaterialsRes, // 获取物料,并返回符合物料协议的bundle.json内容,getMaterialsRes: () => Promise<Materials>
generateNode, // 根据 包含{ type, componentName }的组件信息生成组件schema节点,结构:
clearMaterials, // 清空物料
clearBlockResources, // 清空区块缓存,以便更新最新版区块
initMaterialModule, // 物料模块初始化
fetchUserMaterialData, // 获取物料,并返回符合物料协议的bundle.json内容,getMaterialsRes: () => Promise<Materials>
generateSchemaNode, // 根据 包含{ type, componentName }的组件信息生成组件schema节点
getMaterial, // 获取单个物料,(property) getMaterial: (name: string) => Material
setMaterial, // 设置单个物料 (property) setMaterial: (name: string, data: Material) => void
registerBlock, // 注册新的区块
clearBlockResources, // 清空区块缓存,以便更新最新版区块
updateCanvasDependencies, //传入新的区块,获取新增区块的依赖,更新画布中的组件依赖
getConfigureMap // 获取物料组件的配置信息
}
Expand Down
26 changes: 14 additions & 12 deletions packages/plugins/materials/src/composable/useResource.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const handlePopStateEvent = async () => {
await useTranslate().initI18n({ host: id, hostType: type })
}

const fetchResource = async ({ isInit = true } = {}) => {
const fetchResource = async () => {
const { id, type } = useEditorInfo().useInfo()
useApp().appInfoState.selectedId = id
const appData = await useHttp().get(`/app-center/v1/api/apps/schema/${id}`)
Expand All @@ -137,8 +137,6 @@ const fetchResource = async ({ isInit = true } = {}) => {
resState.isDemo = appData.meta?.is_demo
resState.globalState = appData?.meta.global_state

useMaterial().initMaterial({ isInit, appData })

// 词条语言为空时使用默认的语言
const defaultLocales = [
{ lang: 'zh_CN', label: 'zh_CN' },
Expand All @@ -151,25 +149,29 @@ const fetchResource = async ({ isInit = true } = {}) => {
locales,
messages: appData.i18n
}

try {
await useMaterial().fetchMaterial()

if (isInit) {
await initPageOrBlock()
}

await useTranslate().initI18n({ host: id, hostType: type, init: true })
} catch (error) {
console.log(error) // eslint-disable-line
}
return appData
}

const initResource = async () => {
const appData = await fetchResource()
try {
await useMaterial().initMaterialModule(appData)
await initPageOrBlock()
} catch (error) {
console.log(error) // eslint-disable-line
}
}

export default function () {
return {
resState,
fetchResource,
initPageOrBlock,
initResource, // 初始化资源
fetchResource, // 请求资源
handlePopStateEvent
}
}
41 changes: 41 additions & 0 deletions packages/plugins/materials/src/composable/useResource拆解.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# useResource
## state
```js
const resState = reactive({
dataSource: [], // 数据源
pageTree: [], // 大纲数
langs: {}, // i18n
utils: {}, // 工具类
globalState: [] // 全局信息
})

```

## api

### fetchResource

#### 作用
1. 获取appData
2. 用appData初始化或者刷新state
3. 调用useMaterial.initMaterialModule初始化物料模块
4. 初始化当前画布显示的页面或者区块 initPageorBlock
5. 刷新i18n
#### 在哪里被调用
1. app.vue 在canvas ready后,作为资源初始化
2. BlockGroupPanel 在新增消费的区块时调用,用作刷新相关数据
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use fenced code blocks for better readability.

Indented code blocks are not the recommended style for markdown. Use fenced code blocks instead.

-    1. 获取appData
-    2. 用appData初始化或者刷新state
-    3. 调用useMaterial.initMaterialModule初始化物料模块
-    4. 初始化当前画布显示的页面或者区块 initPageorBlock
-    5. 刷新i18n
+```
+1. 获取appData
+2. 用appData初始化或者刷新state
+3. 调用useMaterial.initMaterialModule初始化物料模块
+4. 初始化当前画布显示的页面或者区块 initPageorBlock
+5. 刷新i18n
+```
Tools
Markdownlint

19-19: Expected: fenced; Actual: indented
Code block style

(MD046, code-block-style)


25-25: Expected: fenced; Actual: indented
Code block style

(MD046, code-block-style)


### handlePopStateEvent
#### 作用
1. 能够在路由发生改变时init当前的页面和block
2. 刷新i18n
#### 在哪里被调用
1. app.vue 绑定pop state的事件监听
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use fenced code blocks for better readability.

Indented code blocks are not the recommended style for markdown. Use fenced code blocks instead.

-    1. 能够在路由发生改变时init当前的页面和block
-    2. 刷新i18n
+```
+1. 能够在路由发生改变时init当前的页面和block
+2. 刷新i18n
+```
Tools
Markdownlint

30-30: Expected: fenced; Actual: indented
Code block style

(MD046, code-block-style)


33-33: Expected: fenced; Actual: indented
Code block style

(MD046, code-block-style)


## 可改造的点(数据流解决后)
1. 利用数据流的通信,将appData获取后发送事件通知
2. 将fetchResource调用useMaterial.initMaterialModule初始化物料模块提出,解耦useMaterial。
3. 将 fetchResource调用 initPageorBlock 抽取出来,同2一样,使用事件通信
4. 将 handlePopStateEvent 抽取出来
5. 看一下APP.vue是一个什么样的角色,如果app.vue里可以调用上面的几个元服务,那么2,3,4都可以直接写在app.vue中。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use fenced code blocks for better readability.

Indented code blocks are not the recommended style for markdown. Use fenced code blocks instead.

-    1. 利用数据流的通信,将appData获取后发送事件通知
-    2. 将fetchResource调用useMaterial.initMaterialModule初始化物料模块提出,解耦useMaterial。
-    3. 将 fetchResource调用 initPageorBlock 抽取出来,同2一样,使用事件通信
-    4. 将 handlePopStateEvent 抽取出来
-    5. 看一下APP.vue是一个什么样的角色,如果app.vue里可以调用上面的几个元服务,那么2,3,4都可以直接写在app.vue中。
+```
+1. 利用数据流的通信,将appData获取后发送事件通知
+2. 将fetchResource调用useMaterial.initMaterialModule初始化物料模块提出,解耦useMaterial。
+3. 将 fetchResource调用 initPageorBlock 抽取出来,同2一样,使用事件通信
+4. 将 handlePopStateEvent 抽取出来
+5. 看一下APP.vue是一个什么样的角色,如果app.vue里可以调用上面的几个元服务,那么2,3,4都可以直接写在app.vue中。
+```
Tools
Markdownlint

36-36: Expected: fenced; Actual: indented
Code block style

(MD046, code-block-style)


4 changes: 2 additions & 2 deletions packages/plugins/materials/src/meta/block/src/BlockList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default {
},
emits: ['check', 'close'],
setup(props, { emit }) {
const { generateNode, registerBlock } = useMaterial()
const { generateSchemaNode, registerBlock } = useMaterial()
const { isDefaultGroupId, isAllGroupId, selectedBlock, selectedGroup, isRefresh, getBlockAssetsByVersion } =
useBlock()
const blockRef = ref(null)
Expand Down Expand Up @@ -91,7 +91,7 @@ export default {

registerBlock(block).then(() => {
const blockName = block.component || block.blockName
const node = generateNode({ type: 'block', component: blockName })
const node = generateSchemaNode({ type: 'block', component: blockName })
const { addComponent, dragStart } = useCanvas().canvasApi.value
if (isShortcutPanel) {
emitEvent('close')
Expand Down
6 changes: 3 additions & 3 deletions packages/plugins/materials/src/meta/component/src/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<template v-for="child in item.children" :key="child.component">
<canvas-drag-item
v-if="!child.hidden && (child.name?.zh_CN || child.name)"
:data="generateNode({ component: child.snippetName || child.component })"
:data="generateSchemaNode({ component: child.snippetName || child.component })"
@click="componentClick"
>
<li class="component-item">
Expand Down Expand Up @@ -48,7 +48,7 @@ export default {
setup() {
const COMPONENT_PANEL_COLUMNS = '1fr 1fr 1fr'
const SHORTCUT_PANEL_COLUMNS = '1fr 1fr 1fr 1fr 1fr 1fr'
const { generateNode, materialState } = useMaterial()
const { generateSchemaNode, materialState } = useMaterial()
const gridTemplateColumns = ref(COMPONENT_PANEL_COLUMNS)
const panelState = inject('panelState', {})
const { components } = materialState
Expand Down Expand Up @@ -111,7 +111,7 @@ export default {
gridTemplateColumns,
state,
change,
generateNode,
generateSchemaNode,
componentClick
}
}
Expand Down