当前位置: 首页 > news >正文

windows部署腾讯tmagic-editor02-Runtime

创建editor项目

将上一教程中的hello-world复制过来,改名hello-editor

创建runtime项目

和hello-editor同级

pnpm create vite

在这里插入图片描述
在这里插入图片描述
删除src/components/HelloWorld.vue

按钮需要用的ts types依赖

pnpm add @tmagic/schema @tmagic/stage

在这里插入图片描述

实现runtime

将hello-editor中的render函数实现移植到runtime项目中

<script setup lang="ts">
import {createApp,ref, computed} from 'vue';
import type StageCore from '@tmagic/stage';const value = ref({type: 'app',// 必须加上ID,这个id可能是数据库生成的key,也可以是生成的uuidid: 1,items: [],
});const render = async ({renderer}:StageCore) => {const root = window.document.createElement('div');const page = value.value.items[0];if (!page.value) return root;const {width = 375, height = 1700} = page.value.style || {};root.id = `${page.value.id}`;root.style.cssText = `width: ${width}px;height: ${height}px;`;createApp({template: '<div v-for="node in config.items" :key="node.id" :id="node.id">hello world</div>',props: ['config'],},{config: page.value,},).mount(root);renderer.on('onload', () => {const style = window.document.createElement('style');// 隐藏滚动条,重置默认样式style.innerHTML = `body {overflow: auto;}html,body {height: 100%; margin: 0;padding: 0;}html::-webkit-scrollbar {width: 0 !important;display: none;}`;renderer.iframe?.contentDocument?.head.appendChild(style);renderer.contentWindow?.magic?.onPageElUpdate(root);renderer.contentWindow?.magic?.onRuntimeReady({});});return root;
};
</script><template><div></div>
</template><style scoped>
</style>

新建ui-page.vue文件

<template><div v-if="config" :id="config.id" :style="style"><div v-for="node in config.items" :key="node.id" :id="node.id">hello world</div></div>
</template><script lang="ts" setup>
import { computed } from 'vue';const props = defineProps<{config: any;
}>();const style = computed(() => {const { width = 375, height = 1700 } = props.config.style || {};return {width: `${width}px`,height: `${height}px`,};
});
</script>

将以下代码覆盖到src/App.vue中

<template><uiPage :config="page"></uiPage>
</template><script lang="ts" setup>
import { ref } from 'vue';import uiPage from './ui-page.vue';const page = ref<any>();
</script>

修改vite.config.js
在这里插入图片描述

启动项目
在这里插入图片描述

修改hello-editor

删除render props,添加runtimeUrl,修改样式app.vue

<template><m-editorv-model="value":runtime-url="runtimeUrl":component-group-list="componentGroupList"></m-editor>
</template><script lang="ts" setup>
import {ref, createApp, computed} from 'vue';
import {editorService} from '@tmagic/editor';const page = computed(() => editorService.get('page'));const value = ref({type: 'app',// 必须加上ID,这个id可能是数据库生成的key,也可以是生成的uuidid: 1,items: [],
});const componentGroupList = ref([{title: '组件列表',items: [{icon: 'https://vfiles.gtimg.cn/vupload/20220614/9cc3091655207317835.png',text: 'HelloWorld',type: 'hello-world',},],},
]);const runtimeUrl = 'http://localhost:8078/';
</script><style>
#app {overflow: auto;
}html,body,#app {height: 100%; margin: 0;padding: 0;
}#app::-webkit-scrollbar {width: 0 !important;display: none;
}
</style>

在这里插入图片描述
启动hello-editor
在这里插入图片描述

跨域问题

修改editor-runtime下的vite.config.js

 server: {port: 8078, //指定端口号headers:{'Access-Control-Allow-Origin': '*',}},

runtime与editor通信

到这里项目就可以正常访问了,但是会发现添加组件没有反应。

这是因为在runtime中无法直接获取到editor中的dsl,所以需要通过editor注入到window的magic api来交互

如出现在runtime中出现magic为undefined, 可以尝试在App.vue中通过监听message,来准备获取magic注入时机,然后调用magic.onRuntimeReady,示例代码如下

window.addEventListener('message', ({ data }) => {if (!data.tmagicRuntimeReady) {return;}window.magic?.onRuntimeReady({// ...});
});

注意:这里可能会出现editor抛出message的时候,runtime还没有执行到监听message的情况 编辑器只在iframe onload事件中抛出message 如果出现runtime中接收不到message的情况,可以尝试在onMounted的时候调用magic.onRuntimeReady

修改main.js为main.ts

import { createApp } from 'vue'
import type { Magic } from '@tmagic/stage';
import './style.css';
import App from './App.vue';declare global {interface Window {magic?: Magic;}
}
createApp(App).mount('#app')

新增tsconfig.json

{"compilerOptions": {"target": "esnext","module": "esnext","strict": true,"jsx": "preserve","moduleResolution": "node","skipLibCheck": true,"esModuleInterop": true,"allowSyntheticDefaultImports": true,"forceConsistentCasingInFileNames": true,"useDefineForClassFields": true,"sourceMap": true,"baseUrl": ".","types": ["webpack-env"],"paths": {"@/*": ["src/*"]},"lib": ["esnext","dom","dom.iterable","scripthost"]},"include": ["src/**/*.ts","src/**/*.tsx","src/**/*.vue","tests/**/*.ts","tests/**/*.tsx"],"exclude": ["node_modules"]
}

src下新增shims-vue.d.ts

/* eslint-disable */
declare module '*.vue' {import type { DefineComponent } from 'vue'const component: DefineComponent<{}, {}, any>export default component
}

修改runtime下的app.vue

<template><uiPage :config="page"></uiPage>
</template><script lang="ts" setup>
import type { RemoveData, UpdateData } from '@tmagic/stage';
import type { Id, MApp, MNode } from '@tmagic/schema';
import { ref,reactive } from 'vue';
import uiPage from './ui-page.vue';
const root = ref<MApp>();const page = ref<any>();window.magic?.onRuntimeReady({/** 当编辑器的dsl对象变化时会调用 */updateRootConfig(config: MApp) {root.value = config;},/** 当编辑器的切换页面时会调用 */updatePageId(id: Id) {page.value = root.value?.items?.find((item) => item.id === id);},/** 新增组件时调用 */add({ config }: UpdateData) {const parent = config.type === 'page' ? root.value : page.value;parent.items?.push(config);},/** 更新组件时调用 */update({ config }: UpdateData) {const index = page.value.items?.findIndex((child: MNode) => child.id === config.id);page.value.items.splice(index, 1, reactive(config));},/** 删除组件时调用 */remove({ id }: RemoveData) {const index = page.value.items?.findIndex((child: MNode) => child.id === id);page.value.items.splice(index, 1);},
});
</script>

同步页面dom给编辑器

由于组件渲染在runtime中,对于编辑器来说是个黑盒,并不知道哪个dom节点才是页面(对于dsl的解析渲染可能是千奇百怪的),所以需要将页面的dom节点同步给编辑器
修改runtime下的app.vue

const pageComp = ref<InstanceType<typeof uiPage>>();watch(page, async () => {// page配置变化后,需要等dom更新await nextTick();window?.magic?.onPageElUpdate(pageComp.value?.$el);
});

以上就是一个简单runtime实现,以及与编辑的交互,这是一个不完善的实现(会发现组件再画布中无法自由拖动,是因为没有完整的解析style),但是其中已经几乎覆盖所有需要关心的内容

当前教程中实现了一个简单的page,tmagic提供了一个比较完善的实现,将在下一节介绍

在这里插入图片描述

相关文章:

windows部署腾讯tmagic-editor02-Runtime

创建editor项目 将上一教程中的hello-world复制过来&#xff0c;改名hello-editor 创建runtime项目 和hello-editor同级 pnpm create vite删除src/components/HelloWorld.vue 按钮需要用的ts types依赖 pnpm add tmagic/schema tmagic/stage实现runtime 将hello-editor中…...

“分块”算法的基本要素及 build() 函数的构建细节

【“分块”算法知识点】 ● 分块是用线段树的分区思想改良的暴力法。代码比线段树简单。效率比普通暴力法高。分块适合求解 m=n=10^5 规模的问题,或 m*sqrt(n)≈10^7 的问题。其中,n 为元素个数,m 为操作次数。 ● “分块”算法的基本要素 (1)块的大小用 block 表示。通常…...

畅捷通TPlus keyEdit.aspx、KeyInfoList.aspx SQL注入漏洞复现

前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 一、产…...

Ubuntu22 下配置 Qt5 环境

1. Qt 简介 Qt5 中的新功能&#xff0c;可以看到各个版本的情况Whats New in Qt 5 | Qt 5.15 Qt 源文件网址Index of /archive/qt 2. 安装 Qt Creator cd 到安装包所在目录&#xff0c;进行软件安装。赋予可执行权限&#xff0c;加上 sudo 权限进入安装&#xff0c;这样会安…...

普通人也能创业!轻资产短视频带货项目,引领普通人实现创业梦想

在这个信息爆炸的时代&#xff0c;创业似乎成为了越来越多人的梦想。然而&#xff0c;传统的创业模式 keJ0277 往往伴随着高昂的资金投入和复杂的管理流程&#xff0c;让许多普通人望而却步。然而&#xff0c;现在有一种轻资产短视频带货项目正在悄然兴起&#xff0c;它以其低…...

【Maven】Nexus简单使用

1、安装配置介绍Nexus私服&#xff1a; 安装配置指路上一篇详细教程博客 【Maven】Nexus私服简介_下载安装_登录-CSDN博客 简单介绍原有仓库类型&#xff1a; proxy代理仓库&#xff1a;代理远程仓库&#xff0c;访问全球中央仓库或其他公共仓库&#xff0c;将资源存储在私…...

winform嵌入excel 设置父窗体分辨率不是100% 嵌入excel分辨率变成双倍大小

在WinForms应用程序中嵌入Excel时&#xff0c;遇到分辨率问题可能是由于DPI缩放导致的。Windows 10及更高版本默认启用了DPI缩放&#xff0c;以便在高分辨率显示器上显示更清晰的内容。这可能会导致嵌入的应用程序&#xff08;如Excel&#xff09;看起来变大或变小。 解决方案 …...

前端系列-4 promise与async/await与fetch/axios使用方式

背景&#xff1a; 本文介绍promise使用方式&#xff0c;以及以Promise为基础的async/await用法和fetch/axios使用方式&#xff0c;主要以案例的方式进行。 1.promise 1.1 promise介绍 javascript是单线程执行的&#xff0c;异步编程的本质是事件机制和函数回调。当执行阻塞…...

微信公众号自定义分销商城小程序源码系统 带完整的安装代码吧以及系统部署搭建教程

系统概述 微信公众号自定义分销商城小程序源码系统是一款功能强大的电商解决方案&#xff0c;它集成了商品管理、订单处理、支付接口、分销管理等多种功能。该系统支持自定义界面设计&#xff0c;商家可根据自身需求调整商城的页面布局和风格&#xff0c;打造独特的品牌形象。…...

在另外一个页面,让另外一个页面弹框显示操作(调佣公共的弹框)vue

大概意思是&#xff0c;登录弹框在另外一个页面中&#xff0c;而当前页面不存在&#xff0c;在当前页面中判断如果token不存在&#xff0c;就弹框出登录的弹框 最后一行 window.location.href … 如果当前用户已登录&#xff0c;则执行后续操作(注意此处&#xff0c;可不要)...

羊毛-百度Comate领50京东E卡

给你分享一个AI编码助手——百度Comate&#xff01;扫码参与抽红包活动&#xff0c;520宠粉&#xff01;送京东卡&#xff01;https://comate.baidu.com/?inviteCodeyysudp63 流程如下 点击&#xff1a;https://comate.baidu.com/?inviteCodeyysudp63添加链接描述 验证码…...

kafka安装部署

kafka 官网下载&#xff1a; kafka https://downloads.apache.org/kafka/3.7.0/zookeeper https://downloads.apache.org/zookeeper/ run kafkazookeeper&#xff0c;conf目录下创建zoo.cfg&#xff0c;运行bin目录下的zkServer脚本文件 kafka eagle 参考&#xff1a;htt…...

VBA直连SAP RFC 接口实例

引用依赖&#xff1a; VBA 调用 SAP API的RFC函数&#xff1a;RFC_READ_TABLE Sub A() 查询SAP表数据并输出到EXCEL&#xff0c;VBA中不区分大小写&#xff08;保存后会自动把代码、变量转换大小写&#xff09;Dim iData As Integer Dim nField As Integer Dim nData As Intege…...

2024如何挑选开放式蓝牙耳机?热门爆款熬夜整理六个点!

我以前也经常使用入耳式耳机&#xff0c;但总是会感觉耳机插在耳朵里不舒服&#xff0c;戴久了耳朵很疼&#xff0c;跑步的时候还总掉。还有在过马路的时候接电话、听音乐&#xff0c;几乎感知不到周围环境音&#xff0c;很不安全。而有了一款开放式蓝牙耳机后&#xff0c;就可…...

3D数据格式转换工具HOOPS Exchange在PLM系统中的5大应用优势

在当今竞争激烈的制造业环境中&#xff0c;产品生命周期管理&#xff08;PLM&#xff09;系统已成为企业提升设计效率、缩短产品上市时间、降低成本和提高市场响应速度的关键工具。3D数据格式转换工具HOOPS Exchange&#xff0c;在PLM系统中扮演着至关重要的角色。以下是HOOPS …...

友元是一种允许某些外部函数或类访问另一个类的成员的机制

在C编程语言中&#xff0c;“友元”&#xff08;Friend&#xff09;是一种允许某些外部函数或类访问另一个类的私有&#xff08;private&#xff09;和保护&#xff08;protected&#xff09;成员的机制。友元功能在C中是非常有用的&#xff0c;尤其是在实现某些特定的功能时&a…...

儿童护眼台灯哪个牌子好,适合儿童使用的护眼台灯推荐

护眼台灯在近几年成为家长和经常与电子设备打交道的人士中备受瞩目的家用电器。对于有孩子的家庭而言&#xff0c;它几乎成为了必备品&#xff0c;许多消费者已经对其有了一定的了解并进行了购买。然而&#xff0c;仍有部分家长对护眼台灯的效果和重要性缺乏充分认识&#xff0…...

在电脑本地运行llama3-8b模型

文章目录 流程我的案例api调用llama.cpp 流程 ollama支持可运行的模型,图片这里只是一部分而已,只需要下载下面的软件和模型文件,即可直接运行,而无需配置其他 模型文件下载地址 https://ollama.com/library 支持的部分模型,实际上更多,这里只是显示部分 登陆ollama官网 htt…...

深入理解 House of Cat

Index 序言利用 FSOP 调用 House of Cat利用条件伪造IO流条件完整调用链分析 模板System (one_gadget) 模板ORW模板 Demo & Exp利用 __malloc_assert 调用 House of Cat例题&#xff1a;题目思路Exp 序言 原文章&#xff1a;深入理解 House of Cat 随着 GNU 持续不断的更…...

【Linux玩物志】Linux环境开发基本工具使用(1)——vim

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; Linux开发工具 首先我们要知道vim是什么&#xff1f; vi&#xff08;Visual Editor&#xff09;是由美国程序员比尔乌尔曼&#xff08;Bill Joy&#xff09;于1976年开发的&#xff0c;最初是为了在Unix系统上进行文本编…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...