一个 完整的 TinyEngine 自定义组件 + 保存 JSON 到后端 的最小示例

当然可以!下面是一个 完整的最小示例,包含:

  1. OpenTiny TinyEngine 中注册一个自定义组件(如 UniSwiper
  2. 在设计器中使用该组件并拖拽配置
  3. 通过按钮将当前页面 Schema 保存为 JSON 并发送到后端 API

前提条件

  • 已克隆并启动 TinyEngine 项目git clone https://github.com/opentiny/tiny-engine.git cd tiny-engine pnpm install pnpm run dev
  • 本地运行一个简易后端(如 Node.js/Express)用于接收 JSON(文末提供)

第一步:创建自定义组件 UniSwiper

1. 创建组件文件

packages/materials/custom-component/src/components/ 下新建:

// packages/materials/custom-component/src/components/UniSwiper.vue
<template>
  <div class="uni-swiper" style="border: 2px dashed #007AFF; padding: 10px; margin: 10px 0;">
    <p>【UniApp 轮播图组件】</p>
    <ul>
      <li v-for="(img, i) in images" :key="i">{{ img }}</li>
    </ul>
    <p>自动播放:{{ autoplay ? '是' : '否' }}</p>
  </div>
</template>

<script>
export default {
  name: 'UniSwiper',
  props: {
    images: {
      type: Array,
      default: () => []
    },
    autoplay: {
      type: Boolean,
      default: true
    }
  }
};
</script>

💡 注意:这个组件只用于 设计器预览,真实渲染在 UniApp 中完成。


2. 注册组件到物料库

编辑 packages/materials/custom-component/src/index.ts

import UniSwiper from './components/UniSwiper.vue';

// 导出组件
export { UniSwiper };

然后在 packages/materials/custom-component/package.jsonexports 中确保导出:

{
  "exports": {
    ".": "./src/index.ts"
  }
}

3. 配置组件元数据(支持拖拽和属性面板)

创建 packages/materials/custom-component/src/meta/UniSwiper.meta.ts

// UniSwiper.meta.ts
export default {
  componentName: 'UniSwiper',
  title: 'UniApp 轮播图',
  category: '自定义组件',
  props: [
    {
      name: 'images',
      title: '图片列表',
      setter: 'ArraySetter',
      defaultValue: ['https://example.com/banner1.jpg']
    },
    {
      name: 'autoplay',
      title: '自动播放',
      setter: 'BoolSetter',
      defaultValue: true
    }
  ]
};

4. 在物料注册表中引入

编辑 packages/materials/lowcode-materials/src/index.ts

// 引入组件和元数据
import { UniSwiper } from '@opentiny/tiny-engine-custom-component';
import UniSwiperMeta from '@opentiny/tiny-engine-custom-component/src/meta/UniSwiper.meta';

// 注册
export const components = [
  // ...其他组件
  {
    component: UniSwiper,
    meta: UniSwiperMeta
  }
];

⚠️ 确保 tsconfig.jsonvite.config.ts 已正确配置路径别名。


第二步:添加“保存页面”按钮插件

1. 创建插件目录

mkdir -p packages/plugins/save-page-plugin

2. 插件主文件

// packages/plugins/save-page-plugin/src/index.ts
import { on, events, getCurrentPage } from '@opentiny/tiny-engine-controller/adapter';

const SavePagePlugin = () => {
  const saveToBackend = async (schema) => {
    try {
      const res = await fetch('http://localhost:3001/api/save-homepage', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ schema })
      });
      if (res.ok) {
        alert('✅ 页面已保存到后端!');
      } else {
        alert('❌ 保存失败');
      }
    } catch (err) {
      console.error('保存失败:', err);
      alert('网络错误,请检查后端是否运行');
    }
  };

  const handleSave = () => {
    const page = getCurrentPage();
    if (!page) {
      alert('没有可保存的页面');
      return;
    }
    const schema = page.export(); // 获取标准 JSON
    saveToBackend(schema);
  };

  // 在设计器顶部添加按钮(简单方式:注入 DOM)
  const initButton = () => {
    const toolbar = document.querySelector('.tiny-engine-toolbar');
    if (toolbar && !toolbar.querySelector('#save-page-btn')) {
      const btn = document.createElement('button');
      btn.id = 'save-page-btn';
      btn.innerText = '💾 保存首页JSON';
      btn.style.marginLeft = '10px';
      btn.style.padding = '6px 12px';
      btn.style.backgroundColor = '#007AFF';
      btn.style.color = 'white';
      btn.style.border = 'none';
      btn.style.borderRadius = '4px';
      btn.onclick = handleSave;
      toolbar.appendChild(btn);
    }
  };

  // 等待设计器加载完成
  setTimeout(initButton, 2000);

  return null;
};

export default SavePagePlugin;

3. 注册插件

编辑 packages/editor-skeleton/src/pluginConfig.ts

import SavePagePlugin from '@opentiny/tiny-engine-save-page-plugin';

export const pluginList = [
  // ...其他插件
  SavePagePlugin
];

第三步:启动并测试

  1. 重新构建物料和插件: pnpm run build:materials pnpm run build:plugins
  2. 启动设计器: pnpm run dev
  3. 打开 http://localhost:9527
    • 从左侧组件栏找到 “UniApp 轮播图”
    • 拖到画布上,修改图片列表和 autoplay
    • 点击顶部 “💾 保存首页JSON” 按钮

第四步:简易后端接收 JSON(Node.js 示例)

创建 backend/server.js

// backend/server.js
const express = require('express');
const cors = require('cors');
const fs = require('fs');

const app = express();
app.use(cors());
app.use(express.json({ limit: '5mb' }));

app.post('/api/save-homepage', (req, res) => {
  const { schema } = req.body;
  console.log('收到页面配置:', JSON.stringify(schema, null, 2));

  // 保存到文件(或数据库)
  fs.writeFileSync('./homepage-schema.json', JSON.stringify(schema, null, 2));
  
  res.json({ code: 200, message: '保存成功' });
});

app.listen(3001, () => {
  console.log('后端运行在 http://localhost:3001');
});

安装依赖并运行:

cd backend
npm init -y
npm install express cors
node server.js

最终效果

  • 你在 TinyEngine 中拖拽 UniSwiper
  • 点击“保存” → JSON 被发送到 http://localhost:3001/api/save-homepage
  • JSON 文件保存在 backend/homepage-schema.json
  • 你可在 UniApp 中读取该 JSON 并动态渲染!

下一步:在 UniApp 中渲染

你只需在 UniApp 中写一个递归组件,识别 componentName === 'UniSwiper',然后渲染 <swiper> + <swiper-item> 即可。

Comments

No comments yet. Why don’t you start the discussion?

发表回复