'已经装好了', 'message' => '「家书」已经安装过。如果要重新安装,请先清空数据库里的 families / persons / accounts / settings 四张表。', ]); exit; } $dbName = $GLOBALS['config']['db']['name']; if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') { csrf_check(); $familyName = trim((string)($_POST['family_name'] ?? '')); $motto = trim((string)($_POST['motto'] ?? '')); $name = trim((string)($_POST['name'] ?? '')); $phone = trim((string)($_POST['phone'] ?? '')); $password = (string)($_POST['password'] ?? ''); $errors = []; if ($familyName === '') { $errors['_'] = '家庭名称不能为空'; } if ($name === '') { $errors['name'] = '请填写你的姓名'; } if (!preg_match('/^\+?[0-9\-]{6,20}$/', $phone)) { $errors['phone'] = '手机号格式看起来不对'; } $pwErr = Account::validatePassword($password); if ($pwErr) { $errors['password'] = implode(';', $pwErr); } if (!$errors) { try { // ensure() 而不是逐条 exec(statements()):它还会补齐后加的列与枚举值, // 所以老库重新跑一次就能自动升级,不必手工改表。 Schema::ensure(); $familyId = Family::create($familyName, $motto); // 关系分组的预置值:在这里建好,免得「装完第一眼进名册发现一个分组都没有」 // (ensure() 里也会补,但那要等下一次请求) \App\PersonGroup::seedDefaults((int)$familyId); // 装完就把结构版本盖上:不盖的话,第一次进首页发现"版本对不上", // 会再跑一次 ensure()(幂等,不出错,但白跑一遍 ALTER 查询)。 \App\Setting::set($familyId, 'schema_version', Schema::VERSION); $personId = Person::create($familyId, [ 'name' => $name, 'gender' => '', 'avatar' => '', 'phone' => $phone, 'id_card' => '', 'email' => '', 'address' => '', 'note' => '', 'slogan' => '', 'kind' => 'member', ]); Account::create($personId, $password, 'admin'); // 名册是「每人一份」(v5 起)。创始人先把自己放进自己的名册 —— // 之后他每加一个人,那个人就自动进他的名册(见 index.php 的 people/create)。 // ⚠️ 这里**不能**把全家成员都塞给他:新装时除他之外还没有别人, // 而"别人"要靠他自己加或复用,这正是"每人一份"的意思。 \App\PersonRoster::ensure((int)$familyId, (int)$personId, (int)$personId, null, 'self'); // 装完就删掉自己 —— 避免把安装入口长期暴露在公网 @unlink(__FILE__); header('Location: index.php?r=auth/login'); exit; } catch (\Throwable $ex) { $errors['_'] = '安装失败:' . $ex->getMessage(); } } set_old($_POST); View::renderBare('install', [ 'title' => '安装家书', 'dbName' => $dbName, 'errors' => $errors, ]); exit; } clear_old(); View::renderBare('install', [ 'title' => '安装家书', 'dbName' => $dbName, 'errors' => [], ]);