Skip to content

Commit

Permalink
feat(Terminal):输出支持换行、优化类
Browse files Browse the repository at this point in the history
  • Loading branch information
build-admin committed Jun 22, 2023
1 parent dbeddfc commit 273916f
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 53 deletions.
89 changes: 54 additions & 35 deletions extend/ba/Terminal.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,59 +17,71 @@
use think\facade\Cookie;
use app\admin\library\Auth;
use think\exception\HttpResponseException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class Terminal
{
/**
* @var object 对象实例
* @var Terminal|null 对象实例
*/
protected static $instance;
protected static Terminal|null $instance = null;

/**
* 当前执行的命令,$command 的 key
* @var string 当前执行的命令 $command 的 key
*/
protected $commandKey = null;
protected string $commandKey = '';

/**
* proc_open 的参数
* @var array proc_open 的参数
*/
protected $descriptorsPec = [];
protected array $descriptorsPec = [];

protected $process = null;
/**
* @var resource|false proc_open 返回的 resource
*/
protected $process = false;

protected $pipes = null;
/**
* @var array proc_open 的管道
*/
protected array $pipes = [];

protected $procStatus = null;
/**
* @var int proc 执行状态
*/
protected int $procStatus = 0;

/**
* 命令在前台的uuid
* @var string 命令在前台的uuid
*/
protected $uuid = null;
protected string $uuid = '';

/**
* 扩展信息
* @var string 扩展信息
*/
protected $extend = null;
protected string $extend = '';

/**
* 命令执行输出文件
* @var string 命令执行输出文件
*/
protected $outputFile = null;
protected string $outputFile = '';

/**
* 命令执行实时输出内容
* @var string 命令执行实时输出内容
*/
protected $outputContent = '';
protected string $outputContent = '';

/**
* 自动构建的前端文件的 outDir(相对于根目录)
* @var string 自动构建的前端文件的 outDir(相对于根目录)
*/
protected static $distDir = 'web' . DIRECTORY_SEPARATOR . 'dist';
protected static string $distDir = 'web' . DIRECTORY_SEPARATOR . 'dist';

/**
* 状态标识
* @var array 状态标识
*/
protected $flag = [
protected array $flag = [
// 连接成功
'link-success' => 'command-link-success',
// 执行成功
Expand All @@ -83,7 +95,7 @@ class Terminal
/**
* 初始化
*/
public static function instance()
public static function instance(): Terminal
{
if (is_null(self::$instance)) {
self::$instance = new static();
Expand All @@ -96,8 +108,8 @@ public static function instance()
*/
public function __construct()
{
$this->uuid = request()->param('uuid');
$this->extend = request()->param('extend');
$this->uuid = request()->param('uuid', '');
$this->extend = request()->param('extend', '');

// 初始化日志文件
$outputDir = root_path() . 'runtime' . DIRECTORY_SEPARATOR . 'terminal';
Expand All @@ -119,7 +131,7 @@ public function __construct()
* @param string $key 命令key
* @return array|false
*/
public static function getCommand(string $key)
public static function getCommand(string $key): bool|array
{
if (!$key) {
return false;
Expand Down Expand Up @@ -153,7 +165,14 @@ public static function getCommand(string $key)
return $command;
}

public function exec(bool $authentication = true)
/**
* 执行命令
* @param bool $authentication 是否鉴权
* @throws ModelNotFoundException
* @throws DataNotFoundException
* @throws DbException
*/
public function exec(bool $authentication = true): void
{
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
Expand Down Expand Up @@ -233,7 +252,7 @@ public function getProcStatus(): bool
* @param string $data
* @param bool $callback
*/
public function output(string $data, bool $callback = true)
public function output(string $data, bool $callback = true): void
{
$data = self::outputFilter($data);
$data = [
Expand All @@ -254,15 +273,15 @@ public function output(string $data, bool $callback = true)
* 输出状态标记
* @param string $flag
*/
public function outputFlag(string $flag)
public function outputFlag(string $flag): void
{
$this->output($this->flag[$flag], false);
}

/**
* 输出后回调
*/
public function outputCallback($data)
public function outputCallback($data): void
{

}
Expand Down Expand Up @@ -307,7 +326,7 @@ public function successCallback(): bool
/**
* 执行前埋点
*/
public function beforeExecution()
public function beforeExecution(): void
{
if ($this->commandKey == 'test.pnpm') {
@unlink(root_path() . 'public' . DIRECTORY_SEPARATOR . 'npm-install-test' . DIRECTORY_SEPARATOR . 'pnpm-lock.yaml');
Expand All @@ -319,19 +338,19 @@ public function beforeExecution()
/**
* 输出过滤
*/
public static function outputFilter($str)
public static function outputFilter($str): string
{
$str = trim($str);
$preg = '/\[(.*?)m/i';
$str = preg_replace($preg, '', $str);
$str = str_replace(["\r\n", "\r", "\n"], "", $str);
$str = str_replace(["\r\n", "\r", "\n"], "\n", $str);
return mb_convert_encoding($str, 'UTF-8', 'UTF-8,GBK,GB2312,BIG5');
}

/**
* 执行错误
*/
public function execError($error, $break = false)
public function execError($error, $break = false): void
{
$this->output('Error:' . $error);
$this->outputFlag('exec-error');
Expand All @@ -341,7 +360,7 @@ public function execError($error, $break = false)
/**
* 退出执行
*/
public function break()
public function break(): void
{
throw new HttpResponseException(Response::create()->contentType('text/event-stream'));
}
Expand All @@ -352,7 +371,7 @@ public function break()
* @param $commandKey
* @return string | bool
*/
public static function getOutputFromProc($commandKey)
public static function getOutputFromProc($commandKey): bool|string
{
if (!function_exists('proc_open') || !function_exists('proc_close')) {
return false;
Expand Down
38 changes: 20 additions & 18 deletions web/src/components/terminal/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@
class="block-on-failure-tag"
v-if="(item.status == taskStatus.Failed || item.status == taskStatus.Unknown) && item.blockOnFailure"
type="warning"
>{{ t('terminal.Failure to execute this command will block the execution of the queue') }}</el-tag
>
{{ t('terminal.Failure to execute this command will block the execution of the queue') }}
</el-tag>
<el-tag
class="block-on-failure-tag"
v-if="item.status == taskStatus.Executing || item.status == taskStatus.Connecting"
type="danger"
>{{ t('terminal.Do not refresh the browser') }}</el-tag
>
{{ t('terminal.Do not refresh the browser') }}
</el-tag>
<span class="command">{{ item.command }}</span>
<div class="task-opt">
<el-button
Expand Down Expand Up @@ -68,7 +70,7 @@
class="exec-message"
:class="'exec-message-' + item.uuid"
>
<div v-for="(msg, index) in item.message" :key="index" class="message-item">{{ msg }}</div>
<pre v-for="(msg, index) in item.message" :key="index" class="message-item">{{ msg }}</pre>
</div>
</template>
</el-card>
Expand All @@ -77,24 +79,24 @@
<el-empty v-else :image-size="80" :description="t('terminal.No mission yet')" />

<el-button-group>
<el-button class="terminal-menu-item" icon="el-icon-MagicStick" v-blur @click="terminal.addTaskPM('test', false)">{{
t('terminal.Test command')
}}</el-button>
<el-button class="terminal-menu-item" icon="el-icon-Download" v-blur @click="terminal.addTaskPM('web-install')">{{
t('terminal.Install dependent packages')
}}</el-button>
<el-button class="terminal-menu-item" icon="el-icon-MagicStick" v-blur @click="terminal.addTaskPM('test', false)">
{{ t('terminal.Test command') }}
</el-button>
<el-button class="terminal-menu-item" icon="el-icon-Download" v-blur @click="terminal.addTaskPM('web-install')">
{{ t('terminal.Install dependent packages') }}
</el-button>
<el-button class="terminal-menu-item" icon="el-icon-Sell" v-blur @click="webBuild()">{{ t('terminal.Republish') }}</el-button>
<el-button v-if="!state.menuExpand" class="terminal-menu-item" icon="el-icon-Expand" v-blur @click="state.menuExpand = true"></el-button>
<template v-else>
<el-button class="terminal-menu-item" icon="el-icon-Delete" v-blur @click="terminal.clearSuccessTask()">{{
t('terminal.Clean up task list')
}}</el-button>
<el-button class="terminal-menu-item" icon="el-icon-Switch" v-blur @click="terminal.togglePackageManagerDialog(true)"
>{{ t('terminal.Package manager') }} {{ terminal.state.packageManager.toUpperCase() }}</el-button
>
<el-button class="terminal-menu-item" icon="el-icon-Tools" v-blur @click="terminal.toggleConfigDialog()">{{
t('terminal.Terminal settings')
}}</el-button>
<el-button class="terminal-menu-item" icon="el-icon-Delete" v-blur @click="terminal.clearSuccessTask()">
{{ t('terminal.Clean up task list') }}
</el-button>
<el-button class="terminal-menu-item" icon="el-icon-Switch" v-blur @click="terminal.togglePackageManagerDialog(true)">
{{ t('terminal.Package manager') }} {{ terminal.state.packageManager.toUpperCase() }}
</el-button>
<el-button class="terminal-menu-item" icon="el-icon-Tools" v-blur @click="terminal.toggleConfigDialog()">
{{ t('terminal.Terminal settings') }}
</el-button>
</template>
</el-button-group>
</el-dialog>
Expand Down

0 comments on commit 273916f

Please sign in to comment.