⚙️ 运行模式

ThinkAdmin 支持两种运行模式:开发模式(debug)生产模式(product)。运行模式决定了系统的错误显示方式、缓存策略和性能表现。

📚 模式区别

🔨 开发模式

开发模式主要用于开发和调试阶段,系统会显示详细的错误信息,帮助开发者快速定位问题。

错误显示方式:开发模式下,当系统出现错误时,会显示完整的错误信息,包括:

  • 错误类型和消息
  • 错误发生的文件路径和行号
  • 完整的调用堆栈
  • SQL 查询语句(如果有)

模板缓存:开发模式下,模板每次请求都会重新编译,修改模板文件后立即生效,无需清理缓存。

SQL 日志:开发模式下,系统会自动记录所有 SQL 查询,方便调试和性能优化。

实际代码示例

<?php
namespace app\admin\controller;

use think\admin\Controller;
use think\admin\model\SystemUser;

class Test extends Controller
{
    public function index()
    {
        // 开发模式下,SQL 查询会自动记录到日志
        // 无需手动开启,系统会自动记录
        $list = SystemUser::mk()->select();
        
        // 开发模式下,可以使用 p() 函数输出调试信息
        if (isDebug()) {
            p($list); // 在页面上显示数据结构
        }
        
        $this->success('success', $list);
    }
}

适用场景

  • 功能开发和调试
  • 问题排查和修复
  • 性能分析和优化
  • 代码测试和验证

🚀 生产模式

生产模式经过多项优化,提升系统性能、安全性和稳定性,是系统正式上线运行的推荐模式。

错误显示方式:生产模式下,当系统出现错误时,不会显示详细的错误信息,而是显示友好的提示页面,如"页面错误,请稍后再试"。这样可以避免敏感信息泄露,提升系统安全性。

模板缓存:生产模式下,编译后的模板会被缓存到 runtime/cache/template/ 目录,提升渲染速度。修改模板文件后需要清理缓存才能生效。

SQL 日志:生产模式下,系统不会记录 SQL 查询日志,减少 I/O 操作,提升性能。

实际代码示例

<?php
namespace app\admin\controller;

use think\admin\Controller;

class Api extends Controller
{
    public function data()
    {
        try {
            // 业务逻辑
            $data = $this->processData();
            $this->success('success', $data);
        } catch (\Exception $e) {
            // 生产模式下,只返回友好提示,不暴露错误详情
            if (isOnline()) {
                $this->error('操作失败,请稍后再试');
            } else {
                // 开发模式下,显示详细错误信息
                $this->error($e->getMessage());
            }
        }
    }
}

适用场景

  • 系统正式上线运行
  • 高并发场景
  • 对安全性要求高的场景
  • 需要稳定运行的场景

🔧 判断模式

在代码中,可以使用 isDebug()isOnline() 函数来判断当前运行模式。

判断开发模式

// 使用 isDebug() 函数判断是否为开发模式
if (isDebug()) {
    // 开发模式下的逻辑
    echo "当前是开发模式";
    // 可以显示详细的调试信息
    $this->app->db->setLog(true); // 开启 SQL 日志
}

判断生产模式

// 使用 isOnline() 函数判断是否为生产模式
if (isOnline()) {
    // 生产模式下的逻辑
    echo "当前是生产模式";
    // 隐藏错误详情,只显示友好提示
}

使用服务类判断

use think\admin\service\RuntimeService;

// 判断是否为开发模式
if (RuntimeService::isDebug()) {
    // 开发模式逻辑
}

// 判断是否为生产模式
if (RuntimeService::isOnline()) {
    // 生产模式逻辑
}

🔧 应用场景

🐛 调试信息

在开发阶段,我们需要看到详细的调试信息,但在生产环境中,这些信息应该被隐藏。

代码实现

<?php
namespace app\admin\controller;

use think\admin\Controller;

class Test extends Controller
{
    public function index()
    {
        // 开发模式下,开启 SQL 日志记录
        // 这样可以在日志文件中查看所有执行的 SQL 语句
        if (isDebug()) {
            $this->app->db->setLog(true);
        }
        
        // 查询数据(推荐使用模型方法)
        $list = SystemUser::mk()->select();
        
        // 开发模式下,使用 p() 函数输出调试信息
        // p() 函数会在页面上以格式化的方式显示数据结构
        if (isDebug()) {
            p($list); // 输出调试信息,方便查看数据结构
        }
        
        $this->success('success', $list);
    }
}

说明

  • $this->app->db->setLog(true) 开启 SQL 日志,所有 SQL 查询会记录到日志文件
  • p($list) 函数用于输出调试信息,只在开发模式下使用
  • 生产模式下,这些调试代码不会影响性能,因为 isDebug() 返回 false

⚠️ 错误显示

在生产环境中,不应该向用户显示详细的错误信息,而应该显示友好的提示。

代码实现

<?php
namespace app\admin\controller;

use think\admin\Controller;

class Api extends Controller
{
    public function data()
    {
        try {
            // 业务逻辑处理
            $data = $this->processData();
            $this->success('success', $data);
        } catch (\Exception $e) {
            // 根据运行模式返回不同的错误信息
            if (isOnline()) {
                // 生产模式:只返回友好提示,不暴露错误详情
                // 这样可以避免泄露系统内部信息,提升安全性
                $this->error('操作失败,请稍后再试');
            } else {
                // 开发模式:显示详细错误信息
                // 包括错误消息、文件路径、行号等,方便调试
                $this->error($e->getMessage());
            }
        }
    }
    
    private function processData()
    {
        // 模拟可能出错的业务逻辑
        if (rand(0, 1)) {
            throw new \Exception('数据库连接失败');
        }
        return ['status' => 'success'];
    }
}

说明

  • 使用 try-catch 捕获异常
  • isOnline() 判断是否为生产模式
  • 生产模式返回友好提示,开发模式返回详细错误
  • 详细错误信息会记录到日志文件,方便后续排查

📝 日志级别

不同模式下,日志记录的详细程度应该不同。开发模式记录详细日志,生产模式只记录关键日志。

代码实现

<?php
namespace app\admin\controller;

use think\admin\Controller;

class Log extends Controller
{
    public function write()
    {
        $message = '用户操作日志';
        $params = $this->request->param();
        
        // 根据运行模式记录不同级别的日志
        if (isDebug()) {
            // 开发模式:记录详细日志
            // debug 级别:记录调试信息
            trace($message, 'debug');
            // info 级别:记录请求参数
            trace($params, 'info');
        } else {
            // 生产模式:只记录关键日志
            // error 级别:只记录错误和重要操作
            trace($message, 'error');
        }
        
        $this->success('日志记录成功');
    }
}

说明

  • trace() 函数用于记录日志,第一个参数是日志内容,第二个参数是日志级别
  • 日志级别:debug < info < error
  • 开发模式记录所有级别,生产模式只记录 error 级别
  • 日志文件保存在 runtime/log/ 目录,按日期分割

⚙️ 配置说明

📁 文件位置

运行模式配置保存在 runtime/.env 文件中,系统启动时会自动读取该文件。

配置文件路径runtime/.env

重要提示runtime/.env 文件是后台自动生成的配置文件,请勿手动修改。所有配置应通过后台管理系统或代码中的 RuntimeService::set() 方法进行,系统会自动更新该文件。

配置文件格式(仅供参考,请勿手动编辑):

[RUNTIME]
mode = debug          # debug=开发模式, product=生产模式
appmap[myadmin] = admin
domain[example.com] = admin

⚙️ 配置说明

mode(运行模式)

  • debug:开发模式,显示详细错误信息,不缓存模板
  • product:生产模式,显示友好提示,缓存模板

appmap(应用映射)

  • 用于修改后台入口路径
  • 格式:appmap[新路径] = 原应用名
  • 示例:appmap[myadmin] = admin 表示将 /admin 改为 /myadmin

domain(域名绑定)

  • 用于多域名访问不同应用
  • 格式:domain[域名] = 应用名
  • 示例:domain[example.com] = admin 表示 example.com 访问 admin 应用

📖 读取配置

在代码中读取运行模式配置:

use think\admin\service\RuntimeService;

// 获取当前运行模式
$mode = RuntimeService::get('mode');
echo $mode; // 输出:debug 或 product

// 获取所有运行配置
$config = RuntimeService::get();
print_r($config);
// 输出:
// Array
// (
//     [mode] => debug
//     [appmap] => Array
//         (
//             [myadmin] => admin
//         )
//     [domain] => Array
//         (
//             [example.com] => admin
//         )
// )

🔄 切换模式

🖥️ 后台切换

在系统后台的"系统参数配置"页面可以切换运行模式,这是最安全和推荐的方式。

操作步骤

  1. 登录后台管理系统
  2. 进入 系统管理系统参数配置
  3. 找到 运行模式 配置项
  4. 选择 开发模式生产模式
  5. 点击 保存 按钮

代码实现

// app/admin/controller/Config.php
public function system()
{
    $post = $this->request->post();
    
    // 切换运行模式
    // 从表单获取 runtime_mode 参数
    if (isset($post['runtime_mode'])) {
        // 判断是生产模式还是开发模式
        $mode = $post['runtime_mode'] === 'product' ? 'product' : 'debug';
        
        // 调用 RuntimeService::set() 方法设置运行模式
        // 该方法会更新 runtime/.env 文件
        RuntimeService::set($mode);
    }
    
    // 切换模式后,清理所有缓存
    // 确保新模式的配置立即生效
    RuntimeService::clear();
    
    $this->success('切换成功');
}

说明

  • RuntimeService::set($mode) 方法会自动更新 runtime/.env 文件中的 mode 配置
  • runtime/.env 文件是系统自动生成的,请勿手动修改
  • 切换后会自动清理缓存,确保新配置立即生效
  • 需要超级管理员权限才能切换模式

💻 代码切换

如果需要在代码中切换模式(例如在命令行脚本中),可以使用以下方法:

use think\admin\service\RuntimeService;

// 切换到生产模式
// 参数 'product' 表示生产模式
RuntimeService::set('product');

// 切换到开发模式
// 参数 'debug' 表示开发模式
RuntimeService::set('debug');

// 切换后建议清理缓存
// 确保新模式的配置立即生效
RuntimeService::clear();

实际应用示例

<?php
// 在命令行脚本中切换模式
// 例如:php think deploy

use think\admin\service\RuntimeService;

// 部署到生产环境时,切换到生产模式
RuntimeService::set('product');

// 清理缓存
RuntimeService::clear();

echo "已切换到生产模式\n";

注意事项

  • 切换模式需要使用超级管理员权限
  • 切换后建议删除 runtime 目录并刷新页面
  • 请勿手动修改 runtime/.env 文件:该文件是后台自动生成的配置文件,手动修改可能导致配置不同步或系统无法正确读取
  • 所有配置应通过后台管理系统或代码中的 RuntimeService::set() 方法进行

🗑️ 清理缓存

切换模式后,需要清理缓存才能生效。

💻 代码清理

在代码中清理缓存,这是最常用的方式:

use think\admin\service\RuntimeService;

// 清理所有缓存
// 包括:模板缓存、配置缓存、路由缓存等
RuntimeService::clear();

说明

  • RuntimeService::clear() 会清理所有类型的缓存
  • 包括模板缓存、配置缓存、路由缓存等
  • 清理后,系统会重新生成缓存

⌨️ 命令行清理

在命令行中清理缓存,适合在部署脚本中使用:

# 清理所有缓存目录
# --dir 参数表示清理目录缓存
php think clear --dir

说明

  • php think clear 是 ThinkPHP 的命令行工具
  • --dir 参数表示清理目录缓存
  • 执行后会自动清理 runtime/cache/runtime/temp/ 目录

🗂️ 手动删除

如果无法使用代码或命令行,可以手动删除缓存目录:

# 删除缓存目录
rm -rf runtime/cache/*
rm -rf runtime/temp/*

# Windows 系统使用
# rmdir /s /q runtime\cache
# rmdir /s /q runtime\temp

说明

  • runtime/cache/ 目录存放模板缓存、配置缓存等
  • runtime/temp/ 目录存放临时文件
  • 删除后,系统会在下次请求时重新生成缓存

🎯 特定缓存

如果需要只清理特定类型的缓存,可以手动删除对应目录:

# 只清理模板缓存
rm -rf runtime/cache/template/*

# 只清理配置缓存
rm -rf runtime/cache/config/*

# 只清理路由缓存
rm -rf runtime/cache/route/*

📊 模式差异

🔨 开发表现

错误显示

  • 显示完整错误信息,包括错误类型、消息、文件路径、行号、调用堆栈
  • SQL 查询错误会显示完整的 SQL 语句
  • 方便开发者快速定位问题

模板缓存

  • 每次请求都重新编译模板
  • 修改模板文件后立即生效,无需清理缓存
  • 适合频繁修改模板的开发阶段

SQL 日志

  • 自动记录所有 SQL 查询到日志文件
  • 可以在 runtime/log/ 目录查看 SQL 日志
  • 方便调试和性能优化

实际代码示例

<?php
// 开发模式下的代码示例
use think\admin\Controller;
use think\admin\model\SystemUser;

class User extends Controller
{
    public function index()
    {
        // 开发模式下,SQL 查询会自动记录
        // 无需手动开启,系统会自动记录到日志
        $list = SystemUser::mk()->select();
        
        // 开发模式下,可以使用 p() 函数输出调试信息
        if (isDebug()) {
            p($list); // 在页面上显示数据结构
        }
        
        $this->success('success', $list);
    }
}

🚀 生产表现

错误显示

  • 只显示友好提示:"页面错误,请稍后再试"
  • 不显示错误详情,避免泄露系统信息
  • 详细错误信息会记录到日志文件

模板缓存

  • 编译后的模板缓存到 runtime/cache/template/ 目录
  • 提升模板渲染速度,减少重复编译
  • 修改模板后需要清理缓存才能生效

SQL 日志

  • 不记录 SQL 查询日志,减少 I/O 操作
  • 提升系统性能,适合高并发场景
  • 只记录错误和异常信息

实际代码示例

<?php
// 生产模式下的代码示例
class Api extends Controller
{
    public function data()
    {
        try {
            // 业务逻辑处理
            $data = $this->processData();
            $this->success('success', $data);
        } catch (\Exception $e) {
            // 生产模式下,只返回友好提示
            // 详细错误信息会记录到日志文件
            if (isOnline()) {
                // 记录错误到日志
                trace_file($e);
                // 返回友好提示
                $this->error('操作失败,请稍后再试');
            } else {
                // 开发模式显示详细错误
                $this->error($e->getMessage());
            }
        }
    }
}

🔧 修改后台入口

默认后台入口为 /admin,容易被猜测,建议修改。

❓ 修改原因

默认的 /admin 路径容易被攻击者猜测和扫描,修改为自定义路径可以:

  • 降低被扫描发现的概率
  • 提升系统安全性
  • 防止未授权访问

💻 代码实现

代码在 app/admin/controller/Config.php 中:

// app/admin/controller/Config.php
public function system()
{
    $post = $this->request->post();
    
    // 修改后台入口路径
    // 从表单获取 xpath 参数,这是新的入口路径
    if (!empty($post['xpath'])) {
        // 验证格式:只能包含字母、数字、下划线
        // 正则表达式:^[a-zA-Z_][a-zA-Z0-9_]*$
        // 必须以字母或下划线开头,后面可以跟字母、数字、下划线
        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $post['xpath'])) {
            $this->error('后台入口格式错误!');
        }
        
        // 检查是否与现有应用冲突
        // 如果新路径不是 'admin',需要检查是否已存在同名应用或插件
        if ($post['xpath'] !== 'admin') {
            // 检查 app 目录下是否已存在同名应用
            if (is_dir(syspath("app/{$post['xpath']}")) || !empty(Plugin::get($post['xpath']))) {
                $this->error('已存在该应用!');
            }
        }
        
        // 设置应用映射:新路径 => 原admin应用
        // RuntimeService::set() 的第二个参数是应用映射数组
        // 格式:['新路径' => '原应用名']
        RuntimeService::set(null, [$post['xpath'] => 'admin']);
    }
    
    // 保存其他配置到系统配置表
    foreach ($post as $k => $v) {
        sysconf($k, $v);
    }
    
    $this->success('保存成功');
}

代码说明

  • preg_match() 验证路径格式,确保只包含字母、数字、下划线
  • is_dir() 检查是否已存在同名应用目录
  • Plugin::get() 检查是否已存在同名插件
  • RuntimeService::set() 设置应用映射,将新路径映射到原 admin 应用
  • sysconf() 保存其他配置到系统配置表

📝 使用示例

代码修改

在代码中修改后台入口:

use think\admin\service\RuntimeService;

// 将后台入口从 /admin 改为 /myadmin
// RuntimeService::set() 的第一个参数是运行模式(null 表示不修改)
// 第二个参数是应用映射数组
RuntimeService::set(null, ['myadmin' => 'admin']);

// 修改后,访问地址变为:
// http://yourdomain.com/myadmin
// http://yourdomain.com/myadmin.html
// 原来的 /admin 路径将无法访问

应用示例

<?php
// 在部署脚本中修改后台入口
// 例如:php think deploy

use think\admin\service\RuntimeService;

// 生成随机入口路径,提升安全性
$randomPath = 'admin_' . substr(md5(time()), 0, 8);
RuntimeService::set(null, [$randomPath => 'admin']);

echo "后台入口已修改为:/{$randomPath}\n";

后台修改

在系统后台修改:

  1. 登录后台管理系统
  2. 进入 系统管理系统参数配置
  3. 找到 后台入口路径 配置项
  4. 输入新的入口路径(只能包含字母、数字和下划线)
  5. 点击 保存 按钮

注意事项

  • 入口路径只能包含字母、数字和下划线,不能包含其他字符
  • 不能与现有应用目录冲突,例如不能使用 indexapi 等已存在的应用名
  • 修改后原有 /admin 入口将被禁用,只能通过新路径访问
  • 建议使用不易猜测的路径,如 myadmin2024sys_manageadmin_abc123
  • 修改后需要记住新路径,否则无法访问后台

📋 常见问题

❓ 页面无法访问

问题描述:切换运行模式后,页面无法正常访问,可能出现空白页面或错误提示。

原因分析:切换模式后,旧的缓存可能仍然存在,导致系统使用旧的配置,从而出现访问异常。

解决方法

# 删除缓存目录
# 清理模板缓存、配置缓存等
rm -rf runtime/cache/*
rm -rf runtime/temp/*

# 检查文件权限
# 确保 runtime 目录有写入权限
chmod -R 755 runtime

如果仍然无法访问,按以下步骤排查

  1. 检查 PHP 错误日志:查看是否有 PHP 错误

    # 查看 PHP 错误日志
    tail -f /var/log/php_errors.log
    # 或查看 ThinkAdmin 日志
    tail -f runtime/log/$(date +%Y%m%d).log
  2. 检查文件权限:确保 runtime 目录有写入权限

    # 检查目录权限
    ls -la runtime/
    # 如果权限不足,修改权限
    chmod -R 755 runtime
    chown -R www-data:www-data runtime  # Linux
  3. 检查数据库连接:检查数据库配置是否正确

    // 在代码中测试数据库连接
    try {
        $this->app->db->connect();
        echo "数据库连接成功";
    } catch (\Exception $e) {
        echo "数据库连接失败:" . $e->getMessage();
    }

❓ 模板不生效

问题描述:在生产模式下修改了模板文件,但页面显示的还是旧内容。

原因分析:生产模式下,模板会被编译并缓存到 runtime/cache/template/ 目录。修改模板文件后,需要清理缓存才能看到新内容。

解决方法

// 方式1:代码清理(推荐)
use think\admin\service\RuntimeService;
// 清理所有缓存,包括模板缓存
RuntimeService::clear();
// 方式2:命令行清理
// 使用 ThinkPHP 的命令行工具清理缓存
php think clear --dir
// 方式3:手动删除模板缓存
// 只删除模板缓存,不影响其他缓存
rm -rf runtime/cache/template/*

说明

  • RuntimeService::clear() 会清理所有类型的缓存
  • php think clear --dir 会清理目录缓存
  • 手动删除只清理模板缓存,其他缓存不受影响

❓ 判断运行模式

问题描述:在代码中需要根据运行模式执行不同的逻辑,如何判断当前是开发模式还是生产模式?

解决方法

// 方式1:使用 isDebug() 函数(推荐)
// isDebug() 返回 true 表示开发模式,false 表示生产模式
if (isDebug()) {
    // 开发模式下的逻辑
    echo "当前是开发模式";
    // 可以显示详细的调试信息
} else {
    // 生产模式下的逻辑
    echo "当前是生产模式";
    // 隐藏错误详情,只显示友好提示
}
// 方式2:使用 isOnline() 函数
// isOnline() 返回 true 表示生产模式,false 表示开发模式
if (isOnline()) {
    // 生产模式下的逻辑
    echo "当前是生产模式";
} else {
    // 开发模式下的逻辑
    echo "当前是开发模式";
}
// 方式3:使用 RuntimeService 服务类
use think\admin\service\RuntimeService;

// 判断是否为开发模式
if (RuntimeService::isDebug()) {
    // 开发模式逻辑
}

// 判断是否为生产模式
if (RuntimeService::isOnline()) {
    // 生产模式逻辑
}

// 获取运行模式字符串
$mode = RuntimeService::get('mode');
if ($mode === 'debug') {
    echo "开发模式";
} elseif ($mode === 'product') {
    echo "生产模式";
}

❓ 生产模式调试

问题描述:生产模式下错误信息被隐藏,如何查看详细的错误信息进行调试?

解决方法

方式1:查看日志文件

生产模式下,所有错误和异常都会记录到日志文件,可以通过查看日志来调试:

// 在代码中读取日志文件
$logFile = syspath('runtime/log/' . date('Ymd') . '.log');
if (file_exists($logFile)) {
    // 读取日志内容
    $logs = file_get_contents($logFile);
    // 处理日志内容,例如显示最后 100 行
    $lines = explode("\n", $logs);
    $lastLines = array_slice($lines, -100);
    echo implode("\n", $lastLines);
}

方式2:记录异常到文件

在代码中捕获异常并记录到日志文件:

try {
    // 业务代码
    $data = $this->processData();
    $this->success('success', $data);
} catch (\Exception $e) {
    // 记录异常到日志文件
    // trace_file() 会将异常信息记录到 runtime/log/ 目录
    trace_file($e);
    
    // 返回友好提示给用户
    $this->error('操作失败,请稍后再试');
}

方式3:临时切换到开发模式

如果问题比较复杂,可以临时切换到开发模式进行调试:

// 临时切换到开发模式
use think\admin\service\RuntimeService;
RuntimeService::set('debug');

// 调试完成后,切回生产模式
RuntimeService::set('product');
RuntimeService::clear();

方式4:在后台查看日志

系统后台提供了日志查看功能,可以查看系统操作日志和错误日志:

  1. 登录后台管理系统
  2. 进入 系统管理系统日志
  3. 查看错误日志和操作日志

❓ 开发模式生产

问题描述:开发模式可以用于生产环境吗?会有什么影响?

答案:不建议在生产环境使用开发模式。

原因分析

  1. 安全风险:开发模式会显示详细错误信息,包括文件路径、数据库配置等敏感信息,存在安全风险。

  2. 性能影响:开发模式不缓存模板,每次请求都重新编译,影响性能。

  3. 日志占用:开发模式会记录详细的 SQL 日志,占用大量磁盘空间。

实际对比

// 开发模式下的错误显示
// 会显示完整的错误信息、文件路径、行号等
// 例如:
// Fatal error: Call to undefined method in /path/to/file.php on line 123
// Stack trace: ...

// 生产模式下的错误显示
// 只显示友好提示
// 例如:页面错误,请稍后再试

建议

  • 开发阶段使用开发模式
  • 测试阶段可以临时使用开发模式
  • 生产环境必须使用生产模式

❓ 查看配置

问题描述:如何在代码中查看当前的运行模式配置?

解决方法

use think\admin\service\RuntimeService;

// 获取当前运行模式
// 返回 'debug' 或 'product'
$mode = RuntimeService::get('mode');
echo $mode; // 输出:debug 或 product

// 获取所有运行配置
// 返回包含 mode、appmap、domain 的数组
$config = RuntimeService::get();
print_r($config);
// 输出示例:
// Array
// (
//     [mode] => debug
//     [appmap] => Array
//         (
//             [myadmin] => admin
//         )
//     [domain] => Array
//         (
//             [example.com] => admin
//         )
// )

// 获取特定配置项
$appmap = RuntimeService::get('appmap', []);
print_r($appmap);
// 输出:Array ( [myadmin] => admin )

查看配置文件(仅用于查看,请勿手动修改):

# 直接查看配置文件(仅用于查看,请勿手动修改)
cat runtime/.env

# 输出示例:
# [RUNTIME]
# mode = debug
# appmap[myadmin] = admin
# domain[example.com] = admin

📸 演示截图

运行模式操作

系统参数配置
最近更新:
Contributors: 邹景立, Anyon