feat: 重构数据库配置并支持多数据库类型

- 将数据库配置从硬编码改为从外部文件加载
- 支持MySQL 5.7+和SQLite两种数据库类型
- 改进安装向导流程,增加数据库类型选择
- 更新README文档说明数据库要求
- 替换CDN链接为国内镜像源
- 增加安装完成后的安全提醒

重构数据库类以支持更灵活的配置方式,包括端口设置和MySQL 5.7兼容性处理。安装向导现在可以正确配置SQLite或MySQL数据库,并生成相应的配置文件。同时优化了前端资源加载速度。
This commit is contained in:
Snowz 2025-05-26 18:22:24 +08:00
parent d75163b2b4
commit bbbf936bdd
7 changed files with 170 additions and 96 deletions

View File

@ -31,7 +31,8 @@
- PHP >= 7.4
- PDO扩展
- PDO MySQL扩展必须使用MySQL或MariaDB
- PDO MySQL扩展使用MySQL 5.7+或MariaDB时
- PDO SQLite扩展使用SQLite时
- GD扩展验证码功能
- cURL扩展网站信息抓取
@ -52,8 +53,9 @@
- PHP版本选择7.4或以上
3. **配置数据库**
- 在宝塔面板中创建MySQL数据库
- 在宝塔面板中创建MySQL数据库推荐MariaDB或MySQL 5.7+
- 记录数据库名、用户名、密码
- 安装时勾选"兼容MySQL 5.7"选项如使用MySQL 5.7
4. **设置文件权限**
```bash
@ -65,6 +67,7 @@
5. **运行安装向导**
- 访问 `http://your-domain/install.php`
- 按照向导完成安装配置
- 选择数据库类型默认MariaDB/MySQL可选SQLite
6. **安全设置**
- 安装完成后删除或重命名 `install.php`
@ -126,6 +129,7 @@
4. **运行安装**
- 访问安装向导完成配置
- 选择数据库类型默认MariaDB/MySQL可选SQLite
## 🎯 使用说明
@ -173,6 +177,9 @@ private $host = 'localhost';
private $db_name = 'submission_system';
private $username = 'root';
private $password = '';
// 使用SQLite设置为true
private $use_sqlite = false;
```
### 功能配置

View File

@ -102,37 +102,66 @@ $offset = ($page - 1) * $limit;
$limit = (int)$limit;
$offset = (int)$offset;
// 检查数据库版本
$is_mysql_57 = $database->isMySQL57();
if ($type === 'website') {
$count_stmt = $db->prepare("SELECT COUNT(*) FROM website_submissions WHERE status = ?");
$count_stmt->execute([$filter]);
$total = $count_stmt->fetchColumn();
$stmt = $db->prepare("
SELECT id, url, title, description, platforms, contact, status, admin_note, created_at
FROM website_submissions
WHERE status = ?
ORDER BY created_at DESC
LIMIT ?, ?
");
$stmt->bindValue(1, $filter, PDO::PARAM_STR);
$stmt->bindValue(2, $offset, PDO::PARAM_INT);
$stmt->bindValue(3, $limit, PDO::PARAM_INT);
if ($is_mysql_57) {
$stmt = $db->prepare("
SELECT id, url, title, description, platforms, contact, status, admin_note, created_at
FROM website_submissions
WHERE status = ?
ORDER BY created_at DESC
LIMIT ?, ?
");
$stmt->bindValue(1, $filter, PDO::PARAM_STR);
$stmt->bindValue(2, $offset, PDO::PARAM_INT);
$stmt->bindValue(3, $limit, PDO::PARAM_INT);
} else {
$stmt = $db->prepare("
SELECT id, url, title, description, platforms, contact, status, admin_note, created_at
FROM website_submissions
WHERE status = ?
ORDER BY created_at DESC
LIMIT ? OFFSET ?
");
$stmt->bindValue(1, $filter, PDO::PARAM_STR);
$stmt->bindValue(2, $limit, PDO::PARAM_INT);
$stmt->bindValue(3, $offset, PDO::PARAM_INT);
}
$stmt->execute();
} else {
$count_stmt = $db->prepare("SELECT COUNT(*) FROM app_submissions WHERE status = ?");
$count_stmt->execute([$filter]);
$total = $count_stmt->fetchColumn();
$stmt = $db->prepare("
SELECT id, name, platform, version, icon_url, download_url, website_url, description, platforms, contact, status, admin_note, created_at
FROM app_submissions
WHERE status = ?
ORDER BY created_at DESC
LIMIT ?, ?
");
$stmt->bindValue(1, $filter, PDO::PARAM_STR);
$stmt->bindValue(2, $offset, PDO::PARAM_INT);
$stmt->bindValue(3, $limit, PDO::PARAM_INT);
if ($is_mysql_57) {
$stmt = $db->prepare("
SELECT id, name, platform, version, icon_url, download_url, website_url, description, platforms, contact, status, admin_note, created_at
FROM app_submissions
WHERE status = ?
ORDER BY created_at DESC
LIMIT ?, ?
");
$stmt->bindValue(1, $filter, PDO::PARAM_STR);
$stmt->bindValue(2, $offset, PDO::PARAM_INT);
$stmt->bindValue(3, $limit, PDO::PARAM_INT);
} else {
$stmt = $db->prepare("
SELECT id, name, platform, version, icon_url, download_url, website_url, description, platforms, contact, status, admin_note, created_at
FROM app_submissions
WHERE status = ?
ORDER BY created_at DESC
LIMIT ? OFFSET ?
");
$stmt->bindValue(1, $filter, PDO::PARAM_STR);
$stmt->bindValue(2, $limit, PDO::PARAM_INT);
$stmt->bindValue(3, $offset, PDO::PARAM_INT);
}
$stmt->execute();
}
@ -146,7 +175,7 @@ $total_pages = ceil($total / $limit);
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理后台 - 内容投稿系统</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
* {
margin: 0;

View File

@ -48,7 +48,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理后台登录</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
* {
margin: 0;

6
assets/css/all.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -5,12 +5,25 @@
*/
class Database {
private $host = 'localhost';
private $db_name = 'submission_system';
private $username = 'root';
private $password = '';
private $host;
private $port;
private $db_name;
private $username;
private $password;
private $use_sqlite;
private $is_mysql_57;
private $conn;
private $use_sqlite = false; // 设置为true使用SQLite
public function __construct() {
$db_config = @include __DIR__ . '/db_config.php';
$this->host = $db_config['host'] ?? 'localhost';
$this->port = $db_config['port'] ?? '3306';
$this->db_name = $db_config['db_name'] ?? 'submission_system';
$this->username = $db_config['username'] ?? 'root';
$this->password = $db_config['password'] ?? '';
$this->use_sqlite = $db_config['use_sqlite'] ?? false;
$this->is_mysql_57 = $db_config['is_mysql_57'] ?? false;
}
public function getConnection() {
$this->conn = null;
@ -18,22 +31,20 @@ class Database {
try {
if ($this->use_sqlite) {
// SQLite配置
$this->conn = new PDO('sqlite:' . __DIR__ . '/../data/database.sqlite');
$this->conn = new PDO('sqlite:' . __DIR__ . '/../data/submission.db');
} else {
// MySQL配置
$this->conn = new PDO(
"mysql:host=" . $this->host . ";dbname=" . $this->db_name . ";charset=utf8mb4",
$this->username,
$this->password
);
$dsn = "mysql:host=" . $this->host . ";port=" . $this->port . ";dbname=" . $this->db_name . ";charset=utf8mb4";
$this->conn = new PDO($dsn, $this->username, $this->password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
}
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $exception) {
echo "连接失败: " . $exception->getMessage();
return $this->conn;
} catch(PDOException $e) {
throw new Exception("数据库连接失败: " . $e->getMessage());
}
return $this->conn;
}
public function initDatabase() {
@ -143,5 +154,9 @@ class Database {
return false;
}
}
public function isMySQL57() {
return $this->is_mysql_57;
}
}
?>

View File

@ -1,4 +1,10 @@
<?php
// 如果未安装没有install.lock跳转到install.php
if (!file_exists(__DIR__ . '/install.lock') || !file_exists(__DIR__ . '/config/db_config.php')) {
header('Location: install.php');
exit;
}
require_once 'config/database.php';
require_once 'includes/utils.php';
@ -98,7 +104,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>内容投稿系统</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
* {
margin: 0;

View File

@ -4,61 +4,63 @@
* 用于初始化数据库和检查环境
*/
if (file_exists(__DIR__ . '/install.lock') && (!isset($_GET['step']) || $_GET['step'] != 4)) {
header('Location: index.php');
exit('系统已安装,请勿重复安装!');
}
$step = $_GET['step'] ?? 1;
$message = '';
$message_type = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($step == 2) {
// 数据库配置测试
$db_type = $_POST['db_type'] ?? 'mysql';
$host = $_POST['host'] ?? 'localhost';
$dbname = $_POST['dbname'] ?? 'submission_system';
$username = $_POST['username'] ?? 'root';
$password = $_POST['password'] ?? '';
// 数据库配置并测试连接
$db_type = $_POST['db_type'];
if ($db_type === 'sqlite') {
$sqlite_path = __DIR__ . '/data/submission.db';
if (!is_dir(__DIR__ . '/data')) mkdir(__DIR__ . '/data', 0777, true);
$config = [
'type' => 'sqlite',
'sqlite_path' => $sqlite_path,
'host' => '',
'port' => '',
'db_name' => '',
'username' => '',
'password' => ''
];
} else {
$config = [
'type' => 'mysql',
'host' => $_POST['db_host'],
'port' => $_POST['db_port'],
'db_name' => $_POST['db_name'],
'username' => $_POST['db_user'],
'password' => $_POST['db_pass'],
'sqlite_path' => ''
];
}
require_once __DIR__ . '/config/database.php';
try {
if ($db_type === 'sqlite') {
$pdo = new PDO('sqlite:' . __DIR__ . '/data/database.sqlite');
$message = 'SQLite数据库连接成功';
$message_type = 'success';
// 更新配置文件
$config_content = file_get_contents('config/database.php');
$config_content = str_replace('private $use_sqlite = false;', 'private $use_sqlite = true;', $config_content);
file_put_contents('config/database.php', $config_content);
} else {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$message = 'MySQL数据库连接成功';
$message_type = 'success';
// 更新配置文件
$config_content = file_get_contents('config/database.php');
$config_content = str_replace("private \$host = 'localhost';", "private \$host = '$host';", $config_content);
$config_content = str_replace("private \$db_name = 'submission_system';", "private \$db_name = '$dbname';", $config_content);
$config_content = str_replace("private \$username = 'root';", "private \$username = '$username';", $config_content);
$config_content = str_replace("private \$password = '';", "private \$password = '$password';", $config_content);
file_put_contents('config/database.php', $config_content);
file_put_contents(__DIR__ . '/config/db_config.php', "<?php\nreturn " . var_export($config, true) . ";\n");
$db = (new Database())->getConnection();
$message = '数据库连接成功!';
$message_type = 'success';
header('Location: install.php?step=3');
exit;
} catch (Exception $e) {
if (file_exists(__DIR__ . '/config/db_config.php')) {
unlink(__DIR__ . '/config/db_config.php');
}
$step = 3;
} catch (PDOException $e) {
$message = '数据库连接失败: ' . $e->getMessage();
$message = $e->getMessage();
$message_type = 'error';
}
} elseif ($step == 3) {
// 初始化数据库
require_once 'config/database.php';
$database = new Database();
if ($database->initDatabase()) {
$message = '数据库初始化成功!';
$message_type = 'success';
$step = 4;
} else {
$message = '数据库初始化失败!';
$message_type = 'error';
}
// 初始化数据库表结构可复用你原有的表结构SQL
// ...
file_put_contents(__DIR__ . '/install.lock', 'installed');
header('Location: install.php?step=4');
exit;
}
}
@ -87,7 +89,7 @@ $env_checks = checkEnvironment();
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>安装向导 - 内容投稿系统</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
* {
margin: 0;
@ -372,26 +374,30 @@ $env_checks = checkEnvironment();
<div class="db-config" id="mysql-config">
<h4>MySQL配置</h4>
<div class="form-group">
<label for="host">数据库主机</label>
<input type="text" name="host" id="host" value="localhost" required>
<label for="db_host">数据库主机</label>
<input type="text" name="db_host" id="db_host" value="localhost" required>
</div>
<div class="form-group">
<label for="dbname">数据库名称</label>
<input type="text" name="dbname" id="dbname" value="submission_system" required>
<label for="db_port">端口</label>
<input type="text" name="db_port" id="db_port" value="3306" required>
</div>
<div class="form-group">
<label for="username">用户名</label>
<input type="text" name="username" id="username" value="root" required>
<label for="db_name">数据库名称</label>
<input type="text" name="db_name" id="db_name" value="submission_system" required>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" name="password" id="password">
<label for="db_user">用户名</label>
<input type="text" name="db_user" id="db_user" value="root" required>
</div>
<div class="form-group">
<label for="db_pass">密码</label>
<input type="password" name="db_pass" id="db_pass">
</div>
</div>
<div class="db-config" id="sqlite-config">
<h4>SQLite配置</h4>
<p>SQLite数据库将自动创建在 data/database.sqlite 文件中,无需额外配置。</p>
<p>SQLite数据库将自动创建在 data/submission.db 文件中,无需额外配置。</p>
</div>
<div class="actions">
@ -421,6 +427,11 @@ $env_checks = checkEnvironment();
<i class="fas fa-check-circle"></i>
恭喜!内容投稿系统安装成功!
</div>
<h3>安全提醒</h3>
<div class="message error">
<i class="fas fa-exclamation-triangle"></i>
为了系统安全,请立即删除或重命名 install.php 文件!
</div>
<h3>默认管理员账户</h3>
<p><strong>用户名:</strong>admin</p>