diff --git a/INSTALL.md b/INSTALL.md index 6cff973..03ea657 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -35,7 +35,7 @@ 1. 登录宝塔面板 2. 点击"网站" → "添加站点" 3. 填写域名,PHP 版本选择 **PHP 8.0** -4. 数据库选择"不创建"(安装向导中会创建) +4. 数据库选择"不创建"(需在安装前手动创建,安装向导不会自动创建数据库) #### 3. 上传代码 @@ -52,25 +52,33 @@ composer install #### 5. 设置目录权限 ```bash -chmod 755 uploads/ +chmod 755 public/uploads/ chmod 755 config/ ``` -#### 6. 配置 Nginx +#### 6. 配置伪静态 -1. 在宝塔面板中找到你的站点 → 设置 → 配置文件 -2. 将网站根目录修改为 `/www/wwwroot/your-domain.com/public` -3. 参考 `docs/baota-nginx-snippet.conf` 中的配置片段,添加到 server 块中 -4. 保存配置 +1. 在宝塔面板中找到你的站点 → 设置 → **网站目录** → 运行目录改为 `/public` +2. 站点设置 → **伪静态** → 将 `docs/baota-nginx-snippet.conf` 的内容粘贴进去 +3. 保存配置 -#### 7. 运行安装向导 +> 注意:如 PHP 版本不是 8.0,需将配置中的 `php-cgi-80` 改为对应版本号。 + +#### 7. 创建数据库 + +安装向导不会自动创建数据库,需要提前手动创建: + +1. 宝塔面板 → 数据库 → 添加数据库 +2. 记录数据库名、用户名和密码,安装向导中需要填写 + +#### 8. 运行安装向导 访问 `http://your-domain.com/install.php`,按照向导步骤: 1. **环境检查** — 系统自动检查 PHP 版本和扩展 -2. **数据库配置** — 填写 MySQL 连接信息 +2. **数据库配置** — 填写 MySQL 连接信息(数据库需提前创建) 3. **应用配置** — JWT 密钥(可自动生成) 4. **管理员账户** — 设置管理员用户名和密码 -5. **AI 供应商** — 配置至少一个 AI 服务供应商 +5. **AI 供应商** — (可选)配置 AI 服务供应商,安装后也可在设置页面添加 ### 方式二:手动安装 @@ -96,17 +104,40 @@ composer install ```bash chown -R www-data:www-data /var/www/ai-chat -chmod 755 uploads/ config/ +chmod 755 public/uploads/ config/ ``` #### 4. 配置 Nginx -参考 `docs/nginx.conf` 配置 Nginx 站点。 +使用 `docs/nginx.conf` 作为完整站点配置: +```bash +cp docs/nginx.conf /etc/nginx/sites-available/ai-chat +ln -s /etc/nginx/sites-available/ai-chat /etc/nginx/sites-enabled/ +# 编辑 server_name 和 root 路径 +nginx -t && nginx -s reload +``` -#### 5. 运行安装向导 +#### 5. 创建数据库 + +```sql +CREATE DATABASE ai_chat DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE USER 'ai_chat'@'localhost' IDENTIFIED BY 'your_password'; +GRANT ALL PRIVILEGES ON ai_chat.* TO 'ai_chat'@'localhost'; +FLUSH PRIVILEGES; +``` + +#### 6. 运行安装向导 访问 `http://your-domain.com/install.php` 完成安装。 +### 方式三:本地开发 + +```bash +php -S localhost:8080 -t public/ public/router.php +``` + +> 必须使用 `public/router.php` 作为路由文件,否则 `/api/*` 请求无法正确路由。 + ## 常见问题 ### Q: 安装页面空白? @@ -116,7 +147,10 @@ chmod 755 uploads/ config/ 检查 Nginx 错误日志:`tail -f /var/log/nginx/error.log` ### Q: 数据库连接失败? -确认 MySQL 服务正在运行,且数据库账号密码正确。 +确认 MySQL 服务正在运行,且数据库已提前创建、账号密码正确。 ### Q: SSE 流式响应不工作? -确认 Nginx 配置中已禁用缓冲(参考 baota-nginx-snippet.conf)。 +确认 Nginx 配置中已禁用缓冲(参考 `docs/baota-nginx-snippet.conf`)。 + +### Q: API 返回非 JSON 响应? +检查 Web 服务器是否正确配置了 `/api/` 路由转发。本地开发需使用 `public/router.php`。 diff --git a/README.md b/README.md index e7aeec6..41fd0d3 100644 --- a/README.md +++ b/README.md @@ -91,9 +91,10 @@ ai-chat/ ``` 然后访问 `http://localhost:8080/` -4. **或配置 Nginx**(生产部署) - - 将网站根目录指向 `public/` 目录 - - 参考 `docs/nginx.conf` 或 `docs/baota-nginx-snippet.conf` 配置 Nginx +4. **或配置 Web 服务器**(生产部署) + - 宝塔面板:网站运行目录设为 `/public`,伪静态填入 `docs/baota-nginx-snippet.conf` 的内容 + - 手动 Nginx:使用 `docs/nginx.conf` 作为完整站点配置 + - 两种方式的详细说明见 [DEPLOY.md](docs/DEPLOY.md) 5. **设置目录权限**(生产部署) ```bash @@ -101,11 +102,16 @@ ai-chat/ chown -R www:www . ``` -6. **运行安装向导** - - 访问 `http://your-domain.com/install.php` - - 按照向导步骤完成安装 +6. **创建数据库** + - 安装向导不会自动创建数据库,请提前手动创建 + - 宝塔面板:数据库 → 添加数据库 + - 手动:`CREATE DATABASE ai_chat DEFAULT CHARSET utf8mb4;` -详细安装说明请查看 [INSTALL.md](INSTALL.md) 和 [DEPLOY.md](docs/DEPLOY.md)。 +7. **运行安装向导** + - 访问 `http://your-domain.com/install.php` + - 填写数据库连接信息和 AI 服务商配置,完成安装 + +详细部署说明请查看 [DEPLOY.md](docs/DEPLOY.md)。 ## 页面说明 @@ -136,4 +142,11 @@ ai-chat/ | 版本 | 日期 | 说明 | |------|------|------| -| v1.0.0 | 2026.5.5 | 初始版本,PHP 8.0 全栈实现 | +| v1.0.0 | 2026-05-05 | 初始版本,PHP 8.0 全栈实现 | +| v1.0.1 | 2026-05-06 | 修复首页 403 错误 | +| v1.0.2 | 2026-05-06 | 移除页面 Emoji,优化排版与交互 | +| v1.0.3 | 2026-05-06 | 全面 UI 重构(登录页 / 安装页 / CSS 变量体系) | +| v1.0.4 | 2026-05-06 | 内联脚本与样式全部迁移至外部文件 | +| v1.1.0 | 2026-05-06 | 升级 firebase/php-jwt 至 7.0.5 | +| v1.1.1 | 2026-05-07 | 资源目录迁移至 public/ 下;修复安装页 JSON 解析错误;新增 router.php | +| v1.2.0 | 2026-05-08 | 修复 3 个致命 Bug(数据库配置键名、Provider 路由、人格 Prompt 传递);AI 提供商改为安装可选;文档全面规范化 | diff --git a/app/Config/Database.php b/app/Config/Database.php index a48db51..403b8a2 100644 --- a/app/Config/Database.php +++ b/app/Config/Database.php @@ -19,7 +19,8 @@ class Database $config = json_decode(file_get_contents($configPath), true); - $dsn = "mysql:host={$config['host']};port={$config['port']};dbname={$config['dbname']};charset=utf8mb4"; + $dbname = $config['database'] ?? $config['dbname'] ?? ''; + $dsn = "mysql:host={$config['host']};port={$config['port']};dbname={$dbname};charset=utf8mb4"; self::$instance = new PDO($dsn, $config['user'], $config['password'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, diff --git a/app/Controllers/ChatController.php b/app/Controllers/ChatController.php index ff4dff2..ca585b4 100644 --- a/app/Controllers/ChatController.php +++ b/app/Controllers/ChatController.php @@ -84,6 +84,9 @@ class ChatController ob_end_flush(); } + // 使用供应商配置中的 type 字段确定实际驱动 + $providerType = $providerConfig['type'] ?? 'newapi'; + $options = [ 'provider' => $providerConfig, 'systemPrompt' => $systemPrompt, @@ -91,7 +94,7 @@ class ChatController ]; try { - AIService::streamChat($providerKey, $model, $messages, $options, function ($chunk, $type = 'content') { + AIService::streamChat($providerType, $model, $messages, $options, function ($chunk, $type = 'content') { if ($type === 'thinking') { self::sendSSE(['thinking' => $chunk]); } else { diff --git a/app/Controllers/InstallController.php b/app/Controllers/InstallController.php index bd9f072..d3389bc 100644 --- a/app/Controllers/InstallController.php +++ b/app/Controllers/InstallController.php @@ -72,10 +72,9 @@ class InstallController echo json_encode(['success' => false, 'message' => '请填写数据库配置']); return; } - if (!is_array($providers) || count($providers) === 0) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => '请至少配置一个AI服务提供商']); - return; + // 供应商配置可选,安装后可在设置页面添加 + if (!is_array($providers)) { + $providers = []; } try { diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 6483971..d6fadc5 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -54,13 +54,32 @@ ``` ai-chat/ -├── public/ # Web 根目录 +├── public/ # Web 根目录(Nginx 指向此目录) +│ ├── index.php # 首页入口(自动路由到登录/安装页) │ ├── api.php # API 统一入口(路由分发) +│ ├── router.php # PHP 内置开发服务器路由文件 │ ├── login.php # 登录页面 │ ├── chat.php # 聊天主页面 │ ├── config.php # 配置管理页面 -│ └── install.php # 安装向导页面 -├── app/ # 应用代码(命名空间 App\) +│ ├── install.php # 安装向导页面 +│ ├── assets/ # 前端静态资源 +│ │ ├── css/ # 样式文件 +│ │ │ ├── style.css # 全局样式 +│ │ │ ├── chat.css # 聊天界面样式 +│ │ │ └── markdown.css # Markdown 渲染样式 +│ │ ├── js/ # JavaScript +│ │ │ ├── api.js # API 调用封装 +│ │ │ ├── chat.js # 聊天核心功能 +│ │ │ ├── config.js # 配置页面逻辑 +│ │ │ ├── install.js # 安装向导逻辑 +│ │ │ ├── login.js # 登录页面逻辑 +│ │ │ ├── session.js # 会话管理 +│ │ │ ├── upload.js # 文件上传 +│ │ │ ├── markdown.js # Markdown 渲染 +│ │ │ └── storage.js # 本地存储 +│ │ └── img/ # 图片 +│ └── uploads/ # 用户上传文件 +├── app/ # 应用代码(命名空间 App\,PSR-4 自动加载) │ ├── Config/ # 配置类 │ │ ├── Database.php # 数据库连接(单例 PDO) │ │ └── AppConfig.php # 应用配置读写 @@ -95,21 +114,7 @@ ai-chat/ │ └── layout/ │ ├── header.php │ └── footer.php -├── assets/ # 前端静态资源 -│ ├── css/ # 样式 -│ │ ├── style.css # 全局样式 -│ │ ├── chat.css # 聊天界面样式 -│ │ └── markdown.css # Markdown 渲染样式 -│ ├── js/ # JavaScript -│ │ ├── api.js # API 调用封装 -│ │ ├── chat.js # 聊天核心功能 -│ │ ├── session.js # 会话管理 -│ │ ├── upload.js # 文件上传 -│ │ ├── markdown.js # Markdown 渲染 -│ │ └── storage.js # 本地存储 -│ └── img/ # 图片 -├── config/ # JSON 配置文件 -├── uploads/ # 用户上传文件 +├── config/ # JSON 配置文件(安装后生成) ├── docs/ # 文档 └── composer.json # Composer 配置 ``` diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md index 9e19924..89addaa 100644 --- a/docs/DEPLOY.md +++ b/docs/DEPLOY.md @@ -14,7 +14,7 @@ 1. 网站 → 添加站点 2. 填写域名 3. PHP 版本选择 **PHP 8.0** -4. 数据库选择"不创建" +4. 数据库选择"不创建"(安装向导会连接你手动创建的数据库) ### 3. 部署代码 @@ -31,30 +31,65 @@ chmod -R 755 . chown -R www:www . ``` -### 5. 配置 Nginx +### 5. 配置伪静态 1. 站点设置 → 网站目录 → 运行目录改为 `/public` -2. 站点设置 → 配置文件 → 添加 `docs/baota-nginx-snippet.conf` 中的配置 +2. 站点设置 → **伪静态** → 将 `docs/baota-nginx-snippet.conf` 的内容粘贴进去,保存 -### 6. 运行安装向导 +> 注意:是粘贴到"伪静态"输入框,不是"配置文件"。 +> 如 PHP 版本不是 8.0,需将 `php-cgi-80` 改为对应版本号(如 `php-cgi-81`)。 -访问 `http://your-domain.com/install.php` +### 6. 创建数据库 -### 7. SSL 配置(可选) +安装向导不会自动创建数据库,需要你提前手动创建: + +1. 宝塔面板 → 数据库 → 添加数据库 +2. 记录数据库名、用户名和密码,安装向导中需要填写 + +### 7. 运行安装向导 + +访问 `http://your-domain.com/install.php`,按步骤完成安装。 + +### 8. SSL 配置(可选) 站点设置 → SSL → Let's Encrypt → 申请证书 -## 手动部署 +--- -### Nginx 配置 +## 手动部署(Nginx + PHP-FPM) -参考 `docs/nginx.conf` 文件,将 `root` 指向 `public/` 目录。 +### 1. 安装依赖 -### PHP-FPM 配置 +```bash +composer install +``` -确保 PHP-FPM 监听 socket 配置正确(通常为 `/tmp/php-cgi-80.sock` 或 `127.0.0.1:9000`)。 +### 2. Nginx 站点配置 -### 目录权限 +使用 `docs/nginx.conf` 作为完整的站点配置文件: + +```bash +# 复制到 Nginx 配置目录 +cp docs/nginx.conf /etc/nginx/sites-available/ai-chat +ln -s /etc/nginx/sites-available/ai-chat /etc/nginx/sites-enabled/ + +# 编辑配置,修改 server_name 和 root 路径 +vim /etc/nginx/sites-available/ai-chat + +# 测试并重载 +nginx -t && nginx -s reload +``` + +### 3. 创建数据库 + +```sql +CREATE DATABASE ai_chat DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE USER 'ai_chat'@'localhost' IDENTIFIED BY 'your_password'; +GRANT ALL PRIVILEGES ON ai_chat.* TO 'ai_chat'@'localhost'; +FLUSH PRIVILEGES; +``` + +### 4. 目录权限 ```bash chown -R www-data:www-data /path/to/ai-chat @@ -62,6 +97,22 @@ chmod 755 /path/to/ai-chat/public/uploads chmod 755 /path/to/ai-chat/config ``` +### 5. 运行安装向导 + +访问 `http://your-domain.com/install.php` + +--- + +## 本地开发(PHP 内置服务器) + +```bash +php -S localhost:8080 -t public/ public/router.php +``` + +> 必须使用 `public/router.php` 作为路由文件,否则 `/api/*` 请求无法正确路由到 `api.php`。 + +--- + ## 安全建议 1. 配置 SSL 证书(HTTPS) diff --git a/docs/baota-nginx-snippet.conf b/docs/baota-nginx-snippet.conf index ff3e6b4..91926b3 100644 --- a/docs/baota-nginx-snippet.conf +++ b/docs/baota-nginx-snippet.conf @@ -1,35 +1,24 @@ # ============================================================ -# AI Chat 宝塔面板 Nginx 配置片段(PHP-FPM 版本) +# AI Chat - 宝塔面板伪静态规则 # ============================================================ # -# 【使用说明】 -# 1. 本文件为宝塔面板专用的 Nginx 配置片段,不是完整的站点配置文件。 -# 2. 使用步骤: -# a. 在宝塔面板中创建网站,PHP 版本选择 PHP 8.0 -# b. 将网站根目录指向 /path/to/ai-chat/public -# c. 登录宝塔面板 → 网站 → 找到你的站点 → 点击"设置" -# d. 在左侧菜单选择"配置文件" -# e. 将下方"配置内容开始"到"配置内容结束"之间的内容, -# 复制并粘贴到 server { } 块内(注意不要重复嵌套 server 块) -# f. 保存即可生效 -# 3. 前置准备: -# - 在宝塔面板中安装 PHP 8.0 并启用 -# - 安装 MySQL 5.7+ 或 8.0 -# - 安装 Composer -# - 运行 composer install 安装 PHP 依赖 +# 使用方法: +# 宝塔面板 → 网站 → 找到你的站点 → 设置 → 伪静态 +# 将本文件内容完整粘贴到伪静态输入框中,保存即可 +# +# 前置条件: +# - 网站根目录已指向 public/ 目录 +# - PHP 8.0 已在宝塔中安装并启用 +# - 如 PHP 版本非 8.0,需将下方 php-cgi-80 改为对应版本号 # # ============================================================ -# ↓↓↓ 配置内容开始 ↓↓↓ - -# === AI Chat 网站配置(PHP-FPM) === - -# 1. 默认路由 +# 默认路由 location / { try_files $uri $uri/ /login.php; } -# 2. API 路由 - 转发到 api.php +# API 路由 — 将 /api/* 请求转发到 api.php 处理 location /api/ { try_files $uri /api.php$is_args$args; fastcgi_pass unix:/tmp/php-cgi-80.sock; @@ -40,47 +29,39 @@ location /api/ { fastcgi_param REQUEST_URI $request_uri; } -# 3. SSE 流式响应特殊配置(AI对话需要) -# 针对 Chat API 的 SSE(Server-Sent Events)流式响应, -# 需要禁用所有缓冲以确保实时输出 +# SSE 流式响应 — AI 对话需要禁用缓冲以实现实时输出 location /api/chat/completions { fastcgi_pass unix:/tmp/php-cgi-80.sock; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/api.php; fastcgi_param REQUEST_URI $request_uri; - # SSE 关键配置 fastcgi_buffering off; + fastcgi_cache off; proxy_buffering off; add_header X-Accel-Buffering no; - # 超时设置(5分钟) fastcgi_read_timeout 300s; } -# 4. 静态资源缓存(assets/ 和 uploads/ 已在 public 目录下,无需 alias) +# 静态资源缓存 location /assets/ { expires 30d; add_header Cache-Control "public, immutable"; } -# 5. 上传文件缓存 +# 上传文件缓存 location /uploads/ { expires 7d; add_header Cache-Control "public"; } -# 6. 禁止访问非公开目录(安全) -location ~ /(app|config|vendor|tests|scripts|)/ { +# 禁止访问非公开目录 +location ~ /(app|config|vendor|tests|scripts|\.cospec)/ { deny all; return 404; } -# 7. 禁止访问隐藏文件 +# 禁止访问隐藏文件 location ~ /\. { deny all; return 404; } - -# 8. 上传文件大小限制 -client_max_body_size 10m; - -# ↑↑↑ 配置内容结束 ↑↑↑ diff --git a/docs/nginx.conf b/docs/nginx.conf index eae781b..6161064 100644 --- a/docs/nginx.conf +++ b/docs/nginx.conf @@ -1,14 +1,25 @@ -# AI Chat 应用 Nginx 配置(PHP-FPM 版本) -# 将此文件复制到 /etc/nginx/sites-available/ 并创建软链接到 sites-enabled/ +# ============================================================ +# AI Chat - Nginx 完整站点配置文件 +# ============================================================ # -# 注意:本文件为完整的 Nginx 站点配置,适用于直接部署到 Nginx + PHP-FPM 的场景。 -# 如果你使用宝塔面板管理服务器,请参考 baota-nginx-snippet.conf 文件中的配置片段。 +# 适用场景:直接部署到 Nginx + PHP-FPM(不使用宝塔面板) +# +# 使用方法: +# 1. 将本文件复制到 /etc/nginx/sites-available/ai-chat +# 2. 创建软链接:ln -s /etc/nginx/sites-available/ai-chat /etc/nginx/sites-enabled/ +# 3. 修改下方 server_name 和 root 为实际值 +# 4. 如 PHP 版本非 8.0,需将 php-cgi-80 改为对应版本号 +# 5. nginx -t 测试配置,nginx -s reload 重载生效 +# +# 注意: +# 如果你使用宝塔面板,请勿使用本文件,改用 baota-nginx-snippet.conf(伪静态规则) # # 前置条件: -# - PHP 8.0+ 已安装并启用 PHP-FPM -# - MySQL 5.7+ 已安装 -# - Composer 已安装 -# - 项目已部署到 /path/to/ai-chat/ 目录 +# - PHP 8.0+ 已安装并启用 PHP-FPM +# - MySQL 5.7+ 已安装 +# - Composer 已安装 +# - 项目已部署到服务器目录 +# server { listen 80; diff --git a/public/assets/js/chat.js b/public/assets/js/chat.js index 5ffbfbb..697124b 100644 --- a/public/assets/js/chat.js +++ b/public/assets/js/chat.js @@ -97,28 +97,37 @@ const ChatManager = { // 清除文件 UploadManager.clearFiles(); +// 获取当前配置 +const provider = document.getElementById('providerSelect')?.value || 'newapi'; +const model = document.getElementById('modelSelect')?.value || 'gpt-3.5-turbo'; +const thinkingMode = document.getElementById('thinkingMode')?.checked || false; - // 获取当前配置 - const provider = document.getElementById('providerSelect')?.value || 'newapi'; - const model = document.getElementById('modelSelect')?.value || 'gpt-3.5-turbo'; - const thinkingMode = document.getElementById('thinkingMode')?.checked || false; +// 获取人格提示词 +let systemPrompt = ''; +const personalitySelect = document.getElementById('personalitySelect'); +if (personalitySelect && personalitySelect.value) { + const personality = personalitiesData.find(p => p.id == personalitySelect.value); + if (personality) { + systemPrompt = personality.prompt || ''; + } +} - // SSE 流式请求 - this.isStreaming = true; - this.updateSendButton(); +// SSE 流式请求 +this.isStreaming = true; +this.updateSendButton(); - try { - await this.streamChat(provider, model, thinkingMode); - } catch (err) { - this.addErrorMessage(err.message); - } finally { - this.isStreaming = false; - this.updateSendButton(); - } - }, +try { + await this.streamChat(provider, model, thinkingMode, systemPrompt); +} catch (err) { + this.addErrorMessage(err.message); +} finally { + this.isStreaming = false; + this.updateSendButton(); +} +}, - async streamChat(provider, model, thinkingMode) { - const token = Storage.getToken(); +async streamChat(provider, model, thinkingMode, systemPrompt) { + const token = Storage.getToken(); // 构建消息历史(只取 role 和 content) const messages = this.messages.map(m => ({ @@ -138,7 +147,8 @@ const ChatManager = { 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ - provider, model, messages, stream: true, thinkingMode + provider, model, messages, stream: true, thinkingMode, + systemPrompt: systemPrompt || '' }) }); diff --git a/public/assets/js/install.js b/public/assets/js/install.js index 8cdcd9a..1d7abf5 100644 --- a/public/assets/js/install.js +++ b/public/assets/js/install.js @@ -158,8 +158,10 @@ const InstallWizard = { }); }); - if (providers.length === 0 || !providers[0].name || !providers[0].apiKey) { - alert('请至少配置一个完整的供应商'); + // 供应商配置可选,跳过不完整的条目 + const validProviders = providers.filter(p => p.name && p.apiKey); + if (validProviders.length === 0 && providers.length > 0) { + alert('供应商信息不完整,请填写名称和 API Key,或删除该条目'); return; } @@ -180,7 +182,7 @@ const InstallWizard = { jwtSecret: document.getElementById('jwtSecret').value || undefined, jwtExpiry: parseInt(document.getElementById('jwtExpiry').value) || 86400 }, - providers: providers + providers: validProviders.length > 0 ? validProviders : [] }; try { diff --git a/public/install.php b/public/install.php index bdb6bcc..822b01f 100644 --- a/public/install.php +++ b/public/install.php @@ -84,7 +84,7 @@ $envChecks = json_encode([
填写 MySQL 数据库连接信息
+填写 MySQL 数据库连接信息。请确保数据库已提前创建。
至少配置一个 AI 供应商,安装后可在设置中添加更多
+可选步骤。现在配置或安装后在设置页面中添加