output = $output; } /** * 按快照对齐全部初始数据域(幂等,可重复执行). * * @return void */ public function align(): void { $this->writeln('开始对齐初始化数据(超管/角色/权限节点/配置/快捷入口/商城演示)'); $this->alignAdmin(); $this->alignAuth(); $this->alignAuthNode(); $this->alignConfig(); $this->alignQuick(); $this->alignMall(); $this->writeln('初始化数据对齐完成'); } /** * 超管对齐:id=1 不存在才插入,密码永不覆盖. */ protected function alignAdmin(): void { $snapshot = include __DIR__ . '/adminInitData/SystemAdmin.php'; $now = time(); foreach ($snapshot as $row) { // 原生查询不过滤软删除:软删的超管行仍占用主键,视为已存在,不复活不覆盖 $exists = Db::name('system_admin')->where('id', $row['id'])->find(); if (!empty($exists)) { $this->writeln(' - 超管 id=' . $row['id'] . ' 已存在,跳过(密码永不覆盖)'); continue; } $data = $row; $data['create_time'] = $now; $data['update_time'] = $now; $data['delete_time'] = 0; Db::name('system_admin')->insert($data); $this->writeln(' - 新增超管 id=' . $row['id'] . ' ' . $row['username']); } } /** * 角色对齐:按显式 id 逐行只插(快照含管理员 id=1 与游客权限 id=6). */ protected function alignAuth(): void { $snapshot = include __DIR__ . '/adminInitData/SystemAuth.php'; $now = time(); foreach ($snapshot as $row) { // 原生查询不过滤软删除:软删的角色行仍占用主键,视为已存在,不复活 $exists = Db::name('system_auth')->where('id', $row['id'])->find(); if (!empty($exists)) { $this->writeln(' - 角色 id=' . $row['id'] . ' ' . $row['title'] . ' 已存在,跳过'); continue; } $data = $row; $data['create_time'] = $now; $data['update_time'] = $now; $data['delete_time'] = 0; Db::name('system_auth')->insert($data); $this->writeln(' - 新增角色 id=' . $row['id'] . ' ' . $row['title']); } } /** * 权限节点对齐:快照为空数组,直接跳过(该表由 auth 注解动态扫描生成). */ protected function alignAuthNode(): void { $this->writeln(' - 权限节点由注解动态扫描生成,跳过快照对齐'); } /** * 配置对齐:按 (group, name) check-then-insert,只插缺失不覆盖 value; * 表无唯一键,判重纯靠应用层;发生过插入则清一次 sysconfig 缓存. */ protected function alignConfig(): void { $snapshot = include __DIR__ . '/adminInitData/SystemConfig.php'; $now = time(); $inserted = 0; foreach ($snapshot as $row) { $exists = Db::name('system_config') ->where('group', $row['group']) ->where('name', $row['name']) ->find(); if (!empty($exists)) { continue; } $data = $row; $data['create_time'] = $now; $data['update_time'] = $now; Db::name('system_config')->insert($data); ++$inserted; } $this->writeln(' - 系统配置新增 ' . $inserted . ' 条(缺失补齐,不覆盖已有 value)'); if ($inserted > 0) { TriggerServiceBase::updateSysconfig(); $this->writeln(' - 已刷新系统设置缓存'); } } /** * 快捷入口对齐:按 href 只插缺失;软删行存在视为已存在,不复活. */ protected function alignQuick(): void { $snapshot = include __DIR__ . '/adminInitData/SystemQuick.php'; $now = time(); $inserted = 0; foreach ($snapshot as $row) { // 原生查询不过滤软删除:软删的快捷入口仍占用 href 语义,视为已存在,不复活 $exists = Db::name('system_quick')->where('href', $row['href'])->find(); if (!empty($exists)) { continue; } $data = $row; $data['create_time'] = $now; $data['update_time'] = $now; $data['delete_time'] = 0; Db::name('system_quick')->insert($data); ++$inserted; } $this->writeln(' - 快捷入口新增 ' . $inserted . ' 条(按 href 判重)'); } /** * 商城演示对齐:分表守卫(三守卫相互独立): * - cate 空则插分类(快照无显式 id,捕获自增 id) * - goods 空则插商品,注入分类 id(复刻旧 initMall 逻辑) * - tag 空则插标签(快照含显式 id 1-4) */ protected function alignMall(): void { $now = time(); // 分类表守卫:空则插入快照分类,捕获新自增 id 供商品注入 $cateId = 0; if ($this->isTableEmpty('mall_cate')) { $snapshotCate = include __DIR__ . '/adminInitData/MallCate.php'; foreach ($snapshotCate as $row) { $data = $row; $data['create_time'] = $now; $data['update_time'] = $now; $data['delete_time'] = 0; Db::name('mall_cate')->insert($data); $cateId = (int) Db::name('mall_cate')->getLastInsID(); $this->writeln(' - 新增商品分类 id=' . $cateId . ' ' . $row['title']); } } else { $this->writeln(' - 商品分类表已有数据,跳过'); } // 商品表守卫:空则插入快照商品,cate_id 注入分类 id(无快照分类时取库内首个分类) if ($this->isTableEmpty('mall_goods')) { if ($cateId === 0) { $cateId = (int) Db::name('mall_cate')->order('id', 'asc')->value('id'); } $snapshotGoods = include __DIR__ . '/adminInitData/MallGoods.php'; foreach ($snapshotGoods as $row) { $data = $row; $data['cate_id'] = $cateId; $data['create_time'] = $now; $data['update_time'] = $now; $data['delete_time'] = 0; Db::name('mall_goods')->insert($data); $this->writeln(' - 新增商品 ' . $row['title'] . ' (cate_id=' . $cateId . ')'); } } else { $this->writeln(' - 商品表已有数据,跳过'); } // 标签表守卫:空则插入快照标签(显式 id,快照行自带时间戳与 delete_time) if ($this->isTableEmpty('mall_tag')) { $snapshotTag = include __DIR__ . '/adminInitData/MallTag.php'; foreach ($snapshotTag as $row) { Db::name('mall_tag')->insert($row); $this->writeln(' - 新增商品标签 id=' . $row['id'] . ' ' . $row['title']); } } else { $this->writeln(' - 商品标签表已有数据,跳过'); } } /** * 判断表是否为空(原生查询,不受任何作用域影响). */ protected function isTableEmpty(string $table): bool { return Db::name($table)->count() == 0; } protected function writeln(string $message): void { if ($this->output !== null) { $this->output->writeln($message); } } }