reminder/public/install.php
2026-01-12 12:42:48 +08:00

317 lines
13 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 数据库安装脚本
* 访问此文件创建/更新数据库表
* 安装完成后请删除此文件
*/
// 数据库配置 - 根据你的 .env 文件配置
$host = '127.0.0.1';
$port = '3306';
$database = 'reminder';
$username = 'root';
$password = '';
// 尝试从 Laravel .env 文件读取配置
$envPath = __DIR__ . '/../.env';
if (file_exists($envPath)) {
$envContent = file_get_contents($envPath);
if (preg_match('/DB_HOST=(.*)/', $envContent, $matches)) {
$host = trim($matches[1]);
}
if (preg_match('/DB_PORT=(.*)/', $envContent, $matches)) {
$port = trim($matches[1]);
}
if (preg_match('/DB_DATABASE=(.*)/', $envContent, $matches)) {
$database = trim($matches[1]);
}
if (preg_match('/DB_USERNAME=(.*)/', $envContent, $matches)) {
$username = trim($matches[1]);
}
if (preg_match('/DB_PASSWORD=(.*)/', $envContent, $matches)) {
$password = trim($matches[1]);
}
}
$messages = [];
$error = '';
try {
$dsn = "mysql:host={$host};port={$port};dbname={$database};charset=utf8mb4";
$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 1. 创建 users 表
$sql = "
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT '姓名',
`email` varchar(255) NOT NULL COMMENT '邮箱',
`email_verified_at` timestamp NULL DEFAULT NULL,
`password` varchar(255) NOT NULL COMMENT '密码',
`remember_token` varchar(100) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
";
$pdo->exec($sql);
$messages[] = '✅ 用户表 users 创建/已存在';
// 2. 检查 patients 表是否存在
$stmt = $pdo->query("SHOW TABLES LIKE 'patients'");
$patientsTableExists = $stmt->rowCount() > 0;
if ($patientsTableExists) {
// 表已存在,检查是否有 user_id 字段
$stmt = $pdo->query("SHOW COLUMNS FROM `patients` LIKE 'user_id'");
$hasUserId = $stmt->rowCount() > 0;
if (!$hasUserId) {
// 检查是否有数据
$countStmt = $pdo->query("SELECT COUNT(*) FROM `patients`");
$count = $countStmt->fetchColumn();
if ($count > 0) {
// 有数据,需要先创建一个默认用户
// 检查是否已有用户
$userCountStmt = $pdo->query("SELECT COUNT(*) FROM `users`");
$userCount = $userCountStmt->fetchColumn();
if ($userCount == 0) {
// 创建默认管理员用户
$defaultPassword = password_hash('admin123', PASSWORD_BCRYPT);
$pdo->exec("INSERT INTO `users` (`name`, `email`, `password`, `created_at`, `updated_at`)
VALUES ('管理员', 'admin@example.com', '{$defaultPassword}', NOW(), NOW())");
$messages[] = '✅ 已创建默认用户: admin@example.com (密码: admin123)';
}
// 获取第一个用户的 ID
$firstUserStmt = $pdo->query("SELECT id FROM `users` ORDER BY id ASC LIMIT 1");
$firstUserId = $firstUserStmt->fetchColumn();
// 添加 user_id 字段(允许 NULL
$pdo->exec("ALTER TABLE `patients` ADD COLUMN `user_id` bigint(20) unsigned NULL AFTER `id`");
$messages[] = '✅ 已添加 user_id 字段到 patients 表';
// 将现有数据关联到第一个用户
$pdo->exec("UPDATE `patients` SET `user_id` = {$firstUserId} WHERE `user_id` IS NULL");
$messages[] = "✅ 已将现有 {$count} 条患者数据关联到用户 ID: {$firstUserId}";
// 修改字段为 NOT NULL
$pdo->exec("ALTER TABLE `patients` MODIFY COLUMN `user_id` bigint(20) unsigned NOT NULL");
// 添加外键约束
try {
$pdo->exec("ALTER TABLE `patients` ADD KEY `patients_user_id_foreign` (`user_id`)");
$pdo->exec("ALTER TABLE `patients` ADD CONSTRAINT `patients_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE");
$messages[] = '✅ 已添加外键约束';
} catch (PDOException $e) {
// 外键可能已存在,忽略
$messages[] = '⚠️ 外键约束已存在或无法添加';
}
} else {
// 没有数据,直接添加字段和约束
$pdo->exec("ALTER TABLE `patients` ADD COLUMN `user_id` bigint(20) unsigned NOT NULL AFTER `id`");
try {
$pdo->exec("ALTER TABLE `patients` ADD KEY `patients_user_id_foreign` (`user_id`)");
$pdo->exec("ALTER TABLE `patients` ADD CONSTRAINT `patients_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE");
} catch (PDOException $e) {
// 忽略
}
$messages[] = '✅ 已添加 user_id 字段到 patients 表';
}
} else {
$messages[] = '✅ patients 表已有 user_id 字段';
}
} else {
// 创建新的 patients 表(包含 user_id
$sql = "
CREATE TABLE `patients` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL COMMENT '所属用户',
`name` varchar(255) NOT NULL COMMENT '姓名',
`gender` varchar(255) NOT NULL COMMENT '性别',
`age` int(11) NOT NULL COMMENT '年龄',
`diagnosis` varchar(255) NOT NULL COMMENT '出院诊断',
`discharge_date` date NOT NULL COMMENT '转诊时间',
`address` varchar(255) DEFAULT NULL COMMENT '户籍地址',
`phone` varchar(255) DEFAULT NULL COMMENT '联系方式',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`follow_up_count` int(11) NOT NULL DEFAULT 0 COMMENT '已随访次数',
`last_follow_up_date` date DEFAULT NULL COMMENT '上次随访日期',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `patients_user_id_foreign` (`user_id`),
CONSTRAINT `patients_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
";
$pdo->exec($sql);
$messages[] = '✅ 患者表 patients 创建成功';
}
// 3. 创建 sessions 表
$sql = "
CREATE TABLE IF NOT EXISTS `sessions` (
`id` varchar(255) NOT NULL,
`user_id` bigint(20) unsigned DEFAULT NULL,
`ip_address` varchar(45) DEFAULT NULL,
`user_agent` text DEFAULT NULL,
`payload` longtext NOT NULL,
`last_activity` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `sessions_user_id_index` (`user_id`),
KEY `sessions_last_activity_index` (`last_activity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
";
$pdo->exec($sql);
$messages[] = '✅ 会话表 sessions 创建/已存在';
// 显示表结构
$stmt = $pdo->query("SHOW TABLES");
$tables = $stmt->fetchAll(PDO::FETCH_COLUMN);
$messages[] = '📋 当前数据库表: ' . implode(', ', $tables);
} catch (PDOException $e) {
$error = '❌ 数据库操作失败: ' . $e->getMessage();
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据库安装 - 病例回访提醒系统</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #f0f4f8 0%, #e8f2ff 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: #ffffff;
border-radius: 16px;
padding: 40px;
max-width: 650px;
width: 100%;
box-shadow: 0 20px 60px rgba(0, 102, 204, 0.15);
}
h1 {
color: #333;
font-size: 24px;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 12px;
}
.message {
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 12px;
line-height: 1.6;
font-size: 14px;
}
.success {
background: rgba(16, 185, 129, 0.1);
border: 1px solid #10b981;
color: #059669;
}
.error {
background: rgba(239, 68, 68, 0.1);
border: 1px solid #ef4444;
color: #ef4444;
}
.warning {
background: rgba(245, 158, 11, 0.1);
border: 1px solid #f59e0b;
color: #d97706;
}
.info {
background: rgba(99, 102, 241, 0.1);
border: 1px solid #6366f1;
color: #666;
}
.info strong { color: #333; }
.btn {
display: inline-block;
padding: 12px 24px;
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
color: white;
text-decoration: none;
border-radius: 8px;
font-weight: 500;
transition: all 0.2s;
margin-top: 10px;
margin-right: 10px;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
}
.btn-secondary {
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
}
.config {
background: #f8fafc;
border-radius: 8px;
padding: 16px;
margin: 20px 0;
font-family: monospace;
font-size: 13px;
color: #666;
border: 1px solid #e2e8f0;
}
.config div { margin: 4px 0; }
.config span { color: #6366f1; }
</style>
</head>
<body>
<div class="container">
<h1>🏥 数据库安装/升级</h1>
<?php if (!empty($messages)): ?>
<?php foreach ($messages as $msg): ?>
<?php
$class = 'success';
if (strpos($msg, '⚠️') !== false) $class = 'warning';
if (strpos($msg, '📋') !== false) $class = 'info';
?>
<div class="message <?= $class ?>"><?= $msg ?></div>
<?php endforeach; ?>
<div class="message info">
<strong>⚠️ 安全提示:</strong>安装完成后,请删除此文件 (install.php) 以确保系统安全。
</div>
<div>
<a href="/login" class="btn">进入登录页 →</a>
<a href="/register" class="btn btn-secondary">注册新用户 →</a>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="message error"><?= htmlspecialchars($error) ?></div>
<div class="config">
<div>当前数据库配置:</div>
<div>Host: <span><?= htmlspecialchars($host) ?></span></div>
<div>Port: <span><?= htmlspecialchars($port) ?></span></div>
<div>Database: <span><?= htmlspecialchars($database) ?></span></div>
<div>Username: <span><?= htmlspecialchars($username) ?></span></div>
</div>
<div class="message info">
<strong>解决方法:</strong><br>
1. 确保 MySQL 服务已启动<br>
2. 确保数据库 "<?= htmlspecialchars($database) ?>" 已创建<br>
3. 检查 .env 文件中的数据库配置是否正确
</div>
<?php endif; ?>
</div>
</body>
</html>