diff --git a/packages/editor-framework/package.json b/packages/editor-framework/package.json
index e76f5e372..8866b4a77 100644
--- a/packages/editor-framework/package.json
+++ b/packages/editor-framework/package.json
@@ -24,12 +24,17 @@
],
"author": "xiayang.xy",
"dependencies": {
+ "debug": "^4.1.1",
+ "events": "^3.1.0",
+ "intl-messageformat": "^7.8.4",
+ "lodash": "^4.17.15",
"prop-types": "^15.5.8"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.3",
"@alifd/next": "1.x",
"@ice/spec": "^0.1.1",
+ "@types/lodash": "^4.14.149",
"@types/react": "^16.9.13",
"@types/react-dom": "^16.9.4",
"build-plugin-component": "^0.2.0",
diff --git a/packages/editor-framework/src/context.ts b/packages/editor-framework/src/context.ts
new file mode 100644
index 000000000..78d3ce177
--- /dev/null
+++ b/packages/editor-framework/src/context.ts
@@ -0,0 +1,3 @@
+import { createContext } from 'react';
+const context = createContext({});
+export default context;
diff --git a/packages/editor-framework/src/editor.ts b/packages/editor-framework/src/editor.ts
new file mode 100644
index 000000000..daeeb2182
--- /dev/null
+++ b/packages/editor-framework/src/editor.ts
@@ -0,0 +1,62 @@
+import EventEmitter from 'events';
+import Debug from 'debug';
+let instance = null;
+
+const debug = Debug('editor');
+EventEmitter.defaultMaxListeners = 100;
+
+export interface editor {
+
+};
+
+export class Editor extends EventEmitter {
+ static getInstance = () => {
+ if (!instance) {
+ instance = new Editor();
+ }
+ return instance;
+ };
+
+ constructor(config) {
+ super();
+ instance = this;
+ Object.assign(this, config);
+ }
+
+ init() {
+
+ }
+
+ destroy() {
+
+ }
+
+ get(key:string):any {
+ return this[key];
+ }
+
+ set(key, val) {
+ if (typeof key === 'string') {
+ this[key] = val;
+ } else if (typeof key === 'object') {
+ Object.keys(key).forEach(item => {
+ this[item] = key[item];
+ });
+ }
+ }
+
+ batchOn(events, lisenter) {
+ if (!Array.isArray(events)) return;
+ events.forEach(event => this.on(event, lisenter));
+ }
+
+ batchOnce(events, lisenter) {
+ if (!Array.isArray(events)) return;
+ events.forEach(event => this.once(event, lisenter));
+ }
+
+ batchOff(events, lisenter) {
+ if (!Array.isArray(events)) return;
+ events.forEach(event => this.off(event, lisenter));
+ }
+}
diff --git a/packages/editor-framework/src/index.scss b/packages/editor-framework/src/index.scss
deleted file mode 100644
index 3a0f72cfb..000000000
--- a/packages/editor-framework/src/index.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-/* write style here */
-.TSDemo {
-
-}
diff --git a/packages/editor-framework/src/index.ts b/packages/editor-framework/src/index.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/editor-framework/src/index.tsx b/packages/editor-framework/src/index.tsx
deleted file mode 100644
index 9752a43b7..000000000
--- a/packages/editor-framework/src/index.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import * as React from 'react';
-
-export default function TSDemo(props) {
- const { type, ...others } = props;
-
- return (
-
Hello TSDemo
- );
-}
-
-TSDemo.propTypes = {
-};
-
-TSDemo.defaultProps = {
-};
diff --git a/packages/editor-framework/src/plugin.ts b/packages/editor-framework/src/plugin.ts
new file mode 100644
index 000000000..e42aa73cc
--- /dev/null
+++ b/packages/editor-framework/src/plugin.ts
@@ -0,0 +1,87 @@
+import { PureComponent } from 'react';
+
+import EditorContext from './context';
+import { isEmpty, generateI18n, goldlog } from './utils';
+
+export interface pluginProps {
+ config: object,
+ editor: object,
+ locale: string,
+ messages: object
+}
+
+
+
+export class Plugin extends PureComponent {
+ static displayName = 'lowcode-editor-plugin';
+ static defaultProps = {
+ config: {}
+ };
+ static contextType = EditorContext;
+ constructor(props, context) {
+ super(props, context);
+ if (isEmpty(props.config) || !props.config.addonKey) {
+ console.warn('luna addon has wrong config');
+ return;
+ }
+
+
+ const { locale, messages, editor } = props;
+ // 注册插件
+ this.editor = editor;
+ this.i18n = generateI18n(locale, messages);
+ this.pluginKey = props.config.pluginKey;
+ editor.plugins = editor.plugins || {};
+ editor.plugins[this.pluginKey] = this;
+ }
+
+ async componentWillUnmount() {
+ // 销毁插件
+ if (this.editor && this.editor.plugins) {
+ delete this.editor.plugins[this.pluginKey];
+ }
+ }
+
+ open = () => {
+ return true;
+ };
+
+ close = () => {
+ return true;
+ };
+
+ goldlog = (goKey:string, params:any) => {
+ const { pluginKey, config = {} } = this.props.config || {};
+ goldlog(
+ goKey,
+ {
+ pluginKey,
+ package: config.package,
+ version: config.version,
+ ...this.editor.logParams,
+ ...params
+ },
+ 'addon'
+ );
+ };
+
+ get utils() {
+ return this.editor.utils;
+ }
+
+ get constants() {
+ return this.editor.constants;
+ }
+
+ get history() {
+ return this.editor.history;
+ }
+
+ get location() {
+ return this.editor.location;
+ }
+
+ render() {
+ return null;
+ }
+}
diff --git a/packages/editor-framework/src/utils.ts b/packages/editor-framework/src/utils.ts
new file mode 100644
index 000000000..5cc738bca
--- /dev/null
+++ b/packages/editor-framework/src/utils.ts
@@ -0,0 +1,75 @@
+
+import IntlMessageFormat from 'intl-messageformat';
+import _isEmpty from 'lodash/isEmpty';
+
+export const isEmpty = _isEmpty;
+
+/**
+ * 用于构造国际化字符串处理函数
+ * @param {*} locale 国际化标识,例如 zh-CN、en-US
+ * @param {*} messages 国际化语言包
+ */
+export function generateI18n(locale = 'zh-CN', messages = {}) {
+ return (key, values = {}) => {
+ if (!messages || !messages[key]) return '';
+ const formater = new IntlMessageFormat(messages[key], locale);
+ return formater.format(values);
+ };
+}
+
+/**
+ * 序列化参数
+ * @param {*} obj 参数
+ */
+export function serializeParams(obj:object):string {
+ if (typeof obj !== 'object') return '';
+
+ const res:Array = [];
+ Object.entries(obj).forEach(([key, val]) => {
+ if (val === null || val === undefined || val === '') return;
+ if (typeof val === 'object') {
+ res.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}`);
+ } else {
+ res.push(`${encodeURIComponent(key)}=${encodeURIComponent(val)}`);
+ }
+ });
+ return res.join('&');
+}
+
+/**
+ * 黄金令箭埋点
+ * @param {String} gmKey 为黄金令箭业务类型
+ * @param {Object} params 参数
+ * @param {String} logKey 属性串
+ */
+export function goldlog(gmKey, params = {}, logKey = 'other') {
+ const sendIDEMessage = window.sendIDEMessage || window.parent.sendIDEMessage;
+ const goKey = serializeParams({
+ sdkVersion: pkg.version,
+ env: getEnv(),
+ ...params
+ });
+ if (sendIDEMessage) {
+ sendIDEMessage({
+ action: 'goldlog',
+ data: {
+ logKey: `/iceluna.core.${logKey}`,
+ gmKey,
+ goKey
+ }
+ });
+ }
+ window.goldlog && window.goldlog.record(`/iceluna.core.${logKey}`, gmKey, goKey, 'POST');
+}
+
+/**
+ * 获取当前编辑器环境
+ */
+export function getEnv() {
+ const userAgent = navigator.userAgent;
+ const isVscode = /Electron\//.test(userAgent);
+ if (isVscode) return ENV.VSCODE;
+ const isTheia = window.is_theia === true;
+ if (isTheia) return ENV.WEBIDE;
+ return ENV.WEB;
+}
\ No newline at end of file