[English](./README.md) | 简体中文

# @ray-js/robot-middleware

@ray-js/robot-middleware 是涂鸦扫地机机器人方案基于@ray-js/hybrid-robot-map 开发的HTML 中间产物。该组件方式以html的文件作为导出，支持在跨平台中使用Webview容器进行引用, 该方案基于@ray-js/webview-invoke 作为跨平台的中间媒介, 允许在RN/涂鸦小程序 中透过通信中间件与HTML 进行通信。

## 使用

### 在Ray 项目中使用

<!--START_SECTION:txp-usage-->

#### 安装

引入依赖包

```shell

yarn add @ray-js/robot-middleware

yarn add -D shelljs

```

需要在ray项目中的根目录下，新建一个copy-scripts.js

```js
const shell = require('shelljs');

shell.cp(
  '-R',
  'node_modules/@ray-js/robot-middleware/lib/robot-middleware/index.html',
  'src/webview'
);
```

执行node copy-scripts.js 把html文件拷贝到webview目录下


之后配置ray项目工程中的 global.config.ts文件

```ts
import { GlobalConfig } from '@ray-js/types';

export const tuya = {
  themeLocation: 'theme.json',
  window: {
    backgroundColor: '#f2f4f6',
    navigationBarTitleText: '',
    navigationBarBackgroundColor: '#f2f4f6',
    navigationBarTextStyle: 'black',
  },
  // 需要指定对应的html 目录, 编译时才能正常加载
  webviewRoot: 'webview',
  skeletonRoot: 'skeleton',
};

const globalConfig: GlobalConfig = {
  basename: '',
};

export default globalConfig;

```

#### 开发组件

小程序视图层

</br>

```xml
<web-view src="{{src}}" id="{{ webviewId }}" bind:message="onMessage" bind:load="onLoadEnd" bind:error="onError"></web-view>
```

小程序逻辑层
```js
const componentOptions = {
   properties: {
    src: { type: String },
    webviewId: { type: String },
  },
  data: {},
  observers: {},
  lifetimes: {
    ready() {
      this.bindWebViewInvoke();
      this.defineCallbacks();
      this.bindFunctions();
    },
  },
  methods: {
    onLoadEnd() {
       // 这里模拟发送数据到WebView中
      setTimeout(() => {
        this.postBundleBinaryWEB({
          key: 'file',
          id: 'file',
          bundle: 'bundle',
          index: 1,
          total: 10,
        });
      }, 3000);
    },
    /**
     * 创建webviewContext 对象并和invoke进行绑定
     */
    bindWebViewInvoke() {
      if (ty.createWebviewContext) {
        this.webviewContext = ty.createWebviewContext(this.data.webviewId);
        /**
         * 给webviewContext 注入platform 属性
         */
        Object.defineProperty(this.webviewContext, 'platform', {
          value: 'mini',
          writable: false,
        });
        this.invoke = createInvoke(() => this.webviewContext);
      }
    },
    /**
     * 创建定义的回调函数,可以把数据从WebView中, 把数据抛出来
     */
    defineCallbacks() {
      if (this.invoke) {
        this.invoke.define('onLoggerInfo', this.onLoggerInfo);
      }
    },
    /**
     * 定义从逻辑层，把数据抛到WebView中的指定方法里
     */
    bindFunctions() {
      if (this.invoke) {
        this.postBundleBinaryWEB = this.invoke.bind('postBundleBinary');
      }
    },
    // 这里接受来自WebView的消息
    onMessage(evt) {
      if (this.invoke) {
        this.invoke.listener(evt);
      }
    },
    // WebView加载失败
    onError() {},
    /**
     * 以下方法都是绑定小程序原生组件和ray组件之间的通信
     * @param {*} data
     */
    onLoggerInfo(data) {
      this.triggerEvent('onLoggerInfo'.toLowerCase(), data);
    },
  }
};
Component(componentOptions);
```

Ray组件中使用小程序的组件进行混合开发

```tsx
import React, { useState, useEffect, useCallback, useRef } from 'react';
// 这个是你的小程序组件
import WebView from '../webview';

interface IProps {}
const MapView: React.FC<IProps> = props => {
  const webviewId: any = useRef(`webviewId_${new Date().getTime()}`).current;

  const onLoggerInfo = (data: any) => {
    console.log('收到了来自WebView中回调过来的数据',data);
  };

  const onEvent = useCallback((evt: { type: string; detail: any}) => {
    const { detail } = evt;
    switch (evt.type) {
      case 'onLoggerInfo'.toLowerCase():
        onLoggerInfo(detail);
        break;
    }
  }, []);

  return (
    <View>
      <WebView
        //这里是你的服务地址，也可以换成本地文件
        src="webview://webview/index.html"
        webviewId={webviewId}
        // 这里不同的ray版本的写法可能有点不同
        bindonloggerinfo={onEvent}
        />
    </View>
  )
} 

```
<!--END_SECTION:txp-usage-->