0.9.238 • Published 9 months ago

@dao42/clacky-paas-front v0.9.238

Weekly downloads
-
License
UNLICENSED
Repository
github
Last release
9 months ago

PaaS SDK 示例

欢迎来到PaaS SDK示例,本文是DaoPaaS的一个简单使用示例。

温馨提示

  • SDK接口文档api地址
  • 本案例的axios为封装后的axios, baseUrl默认为“www.1024paas.com”。
  • 真实接口请求过程中,请按照接口文档的要求携带头信息。
  • 本案例使用React,非React项目请参考逻辑。
  • 请用户自行优化代码逻辑并做合适的错误处理。

PART-ONE 请求获取ticket(票)流程

第一步:定义接口

/*
 * 获取codeZone环境列表
 * @returns { {id: int, versionList: {id: string, name: string}[]}[] }
*/
export async function getEnvironmentsApi() {
    const res = await axios.get('/api/v1/sdk/environments')
    return res.data // 环境列表(数组)
}
/*
 * 创建codeZone, 获取codeZoneId
 * @param { string } environmentVerId 环境id
 * @returns { string }
*/
async function getCodeZoneIdApi(environmentVerId: string): string {
    const res = await axios.post('/api/v1/sdk/codeZones',{environmentVerId})
    return res.data.id
}
/*
 * 通过 codeZoneId 获取 playgroundId
 * @param { string } codeZoneId
 * @returns { string }
*/
async function getPlaygroundIdApi(codeZoneId: string): string {
    const res = await axios.get('/api/v1/sdk/codeZones/'+codeZoneId+'/playground')
    return res.data.id
}
/*
 * 通过 playgroundId 获取 ticket
 * @param { string } playgroundId
 * @returns { string }
*/
async function getTicketApi(playgroundId: string): string {
    const res = await axios.post('/api/v1/sdk/ticket', {
        playgroundId,
        tillTime: Date.now() + 12*60*60*1000, // 截止时间(时间戳)
        userInfo: {}, // 数据格式请参考接口文档
    })
    return res.data.ticket
}

第二步:封装逻辑

// 通过调用 getEnvironmentsApi() 我们获取到了codeZone环境列表, 并渲染到页面上
const environments = await getEnvironmentsApi()
// 假设用户点击了某一个环境,我们得到了一个具体的 environmentVerId
const environmentVerId = environments[0].versionList[0].id
// 封装获取ticket(票)逻辑
export async function handleGetTicket(environmentVerId: string) {
    const codeZoneId = await getCodeZoneIdApi(environmentVerId)
    const playgroundId = await getPlaygroundIdApi(codeZoneId)
    const ticket = await getTicketApi(playgroundId)
    return ticket
}

PART-TWO 在组件中使用

第一步:引入SDK和样式

import { DaoPaaS, Messages } from 'DaoPaaS.cjs';
import 'style.css'

第二步:初始化实例

  1. 创建实例
const dao = new DaoPaaS({
    tenantId: '租户id',
    ticket: '动态获取的ticket', // ticket(票)
    userInfo: { username: '用户名'}, // 用户信息
});
  1. 监听消息
dao.onMessage((message: Message) => {
    const { name, payload } = message;
    let status: PlaygroundStatus;
    let dockerStatus: DockerStatus;
    let lspStatus: LspStatusEnum;
    switch (name) {
    case Messages.Ready:
        console.log('appStatus readyBasic');
        console.log('playgroundInfo状态', dao.playgroundInfo.status);
        console.log('语法补全状态', dao.playgroundInfo.lspStatus);
        console.log('docker运行状态', dao.playgroundInfo.runStatus);
        break;
    case Messages.Online:
        console.log('网络已恢复');
        setSpinLoading(false);
        break;
    case Messages.Offline:
        console.log('网络掉线');
        break;
    case Messages.StatusChanged:
        console.log('playground状态发生变化', payload.status);
        break;
    case Messages.PlaygroundChanged:
        console.log('playground环境变了,比如换题');
        break;
    case Messages.LspStatusChanged:
        console.log('Lsp状态发生变化', payload.status);
        break;
    case Messages.RunStatusChanged:
        console.log('docker运行状态变化', payload.status);
        if (dockerStatus != 'STOP') {
            return;
        } else if (payload.runResult === 0) {
            console.log(`运行结果成功`);
        } else {
            console.log(`运行结果失败: ${payload.runResult}`);
        }
        break;
    }
});
  1. 监听错误消息
dao.onError((message: Message) => {
    const { name, error } = message;
    switch (name) {
    case Messages.ConnectionBroken:
        console.log('与服务器的连接中断,可以尝试连接到另一个服务器');
        break;
    case Messages.AuthorizationFailed:
        console.log('授权失败,所以您需要再次登录或获得一个新的ticket');
        break;
    case 'errorFromServer':
        console.log('与服务器的连接中断');
        break;
    }
});
  1. 把实例的组件挂载到dom节点
// container: 项目中真实节点的选择器, item: 要挂载的dao内部组件的名称
// 这个方法运行后,会把item对应名称的dao内部组件挂载到container配置类名的dom节点上
dao.mapRender([
    { container: '.tree-section', item: 'Tree' },
    { container: '.editor-section', item: 'Editor' },
    { container: '.browser-section', item: 'Browser'},
    { container: '.terminal-section', item: 'Shell' },
    { container: '.console-section', item: 'Console' },
]);
  1. 创建HTML标签

运行dao.mapRender([...])方法后,会把dao内部组件渲染到对应的dom节点

<div>
    <div className="tree-section"></div>
    <div className="editor-section"></div>
    <div className="browser-section"></div>
    <div className="console-section"></div>
    <div className="terminal-section"></div>
</div>

第三步:销毁实例

在页面卸载的时候需要销毁dao实例和相关的缓存数据

useEffect(() => {
    // ...
    return () => {
        dao.dispose()
    }
}, [])

PART-THREE SDK部分其他方法

// 配置是否在控制台开启DaoPaaS内部打印
dao.loggerEnable(true);
// 修改主题
dao.loadTheme('dark')
// 激活容器
dao.activePlayground()
// 运行容器
dao.runPlayground()
// 停止容器运行
dao.stopPlayground()
// ...

PART-FOUR 基础案例

import React, { useEffect, useState } from 'react';
import { DaoPaaS, Messages } from '~/DaoPaaS';

enum LspStatusEnum {
  NOT_SUPPORT = 'notSupport',
  LOADING = 'loading',
  RUNNING = 'running',
  SHUTDOWN = 'shutdown',
}

export default function SimpleExample({environmentVerId}) {
  const [daoPaasObj, setDaoPaasObj] = useState<DaoPaaS | null>(null);
  const [playgroundStatus, setPlaygroundStatus] =
    useState<PlaygroundStatus>('EMPTY');
  const [dockerStatus, setDockerStatus] = useState<DockerStatus>('STOP');
  const {setLspStatus, LspStatusFC} = useLspStatus();
  const [remindVisible, setRemindVisible] = useState(false);

  // SDK初始化
  const initSDK = async () => {
    console.log('开始连接运行环境...')
    // 获取ticket(票)
    const ticket = handleGetTicket(environmentVerId)
    // 生成实例
    const dao = new DaoPaaS({
      paasDomain: 'www.1024paas.com',
      tenantId: '请输入租户id',
      ticket: ticket,
      userInfo: { username: "***" },
    });
    // 保存实例
    setDaoPaasObj(dao);
    // 监听消息
    dao.onMessage((message: Message) => {
      const { name, payload } = message;
      let status: PlaygroundStatus;
      let dockerStatus: DockerStatus;
      let lspStatus: LspStatusEnum;
      switch (name) {
        case Messages.Ready:
          console.log('连接运行环境已经停止')
          setRemindVisible(dao.playgroundInfo.status === 'INACTIVE');
          setPlaygroundStatus(dao.playgroundInfo.status);
          setLspStatus(
            dao.playgroundInfo.lspStatus as LspStatusEnum,
          );
          setDockerStatus(
            dao.playgroundInfo.runStatus as DockerStatus,
          );
          break;
        case Messages.Online:
          console.log('网络已恢复');
          console.log('连接运行环境已经停止')
          break;
        case Messages.Offline:
          console.log('网络掉线');
          break;
        case Messages.StatusChanged:
          status = payload.status;
          setRemindVisible(status === 'INACTIVE');
          setPlaygroundStatus(payload.status);
          break;
        case Messages.PlaygroundChanged:
          setRemindVisible(false);
          break;
        case Messages.LspStatusChanged:
          lspStatus = payload.status;
          setLspStatus(lspStatus);
          break;
        case Messages.RunStatusChanged:
          dockerStatus = payload.status;
          setDockerStatus(dockerStatus);
          if (dockerStatus != 'STOP') {
            return;
          }
          if (payload.runResult === 0) {
            console.log(`运行结果成功`);
          } else {
            console.warn(`运行结果失败: ${payload.runResult}`);
          }
          break;
      }
    });
    // 监听报错消息
    dao.onError((message: Message) => {
      const { name, error } = message;
      switch (name) {
        case Messages.ConnectionBroken:
          console.error(error, 0);
          break;
        case Messages.AuthorizationFailed:
          console.error(error, 0);
          break;
        case 'errorFromServer':
          console.log('连接运行环境已经停止')
          console.error(error, 0);
          break;
      }
    });
    // 挂载实例组件
    dao.mapRender([
      { container: '.tree-section', item: 'Tree'},
      { container: '.editor-section', item: 'Editor'},
      { container: '.browser-section', item: 'Browser'},
      { container: '.terminal-section', item: 'Shell'},
      { container: '.console-section', item: 'Console'},
    ]);
  };
  // 语法补全连接状态
  function useLspStatus() {
    const [lspStatus, setLspStatus] = useState<LspStatusEnum>(
      LspStatusEnum.LOADING,
    );
    function LspStatusFC() {
      const textMap = {
        [LspStatusEnum.NOT_SUPPORT]: '不支持',
        [LspStatusEnum.LOADING]: '连接中',
        [LspStatusEnum.RUNNING]: '运行中',
        [LspStatusEnum.SHUTDOWN]: '已关闭',
      };
      return (
        <div> 代码补全·({textMap[lspStatus]})</div>
      );
    }
    return {
      setLspStatus,
      LspStatusFC,
    };
  }
  useEffect(() => {
    initSDK();
    return () => {
      // 在页面卸载的时候需要销毁实例和相关的缓存数据
      daoPaasObj && daoPaasObj.dispose();
      setDaoPaasObj(null);
    };
  }, []);
  return (
    <>
      {remindVisible && <button
        onClick={() => {
          daoPaasObj?.activePlayground();
          setRemindVisible(false);
        }}
      >
        容器状态为失活,点击确认激活容器
      </button>}
      <div>
        <LspStatusFC />
        <div>
          {playgroundStatus !== 'ACTIVE' ? (
            <button onClick={() =>  daoPaasObj?.activePlayground() }>激活</button>
          ) : (
            <div>已激活</div>
          )}
          {dockerStatus !== 'RUNNING' ? (
            <button
              disabled={playgroundStatus !== 'ACTIVE'}
              onClick={() => {
                daoPaasObj?.runPlayground();
              }}
            >
              运行
            </button>
          ) : (
            <button
              disabled={playgroundStatus !== 'ACTIVE'}
              onClick={() => daoPaasObj?.stopPlayground()}
            >
              停止
            </button>
          )}
        </div>
      </div>
      <div>
        <div className="tree-section"></div>
        <div className="editor-section"></div>
        <div className="browser-section"></div>
        <div className="console-section"></div>
        <div className="terminal-section"></div>
      </div>
    </>
  );
}