departmentsData() as $data) { $depts[$data['name']] = Department::firstOrCreate( ['name' => $data['name']], $data ); } // ── 2. 创建职务 ──────────────────────────────────────────────────── $positions = []; // key = "部门名::职务名" foreach ($this->positionsData() as $row) { $dept = $depts[$row['department']]; $position = Position::firstOrCreate( ['department_id' => $dept->id, 'name' => $row['name']], [ 'department_id' => $dept->id, 'name' => $row['name'], 'icon' => $row['icon'], 'rank' => $row['rank'], 'level' => $row['level'], 'max_persons' => $row['max_persons'], 'max_reward' => $row['max_reward'], 'sort_order' => $row['sort_order'], ] ); $positions["{$row['department']}::{$row['name']}"] = $position; } // ── 3. 设置任命权限白名单 ──────────────────────────────────────────── foreach ($this->appointLimitsData($positions) as [$appointer, $appointableList]) { /** @var Position $appointerPosition */ $appointerPosition = $positions[$appointer] ?? null; if (! $appointerPosition) { continue; } // 同步任命白名单(不附加旧数据,完整覆盖) $appointableIds = collect($appointableList) ->map(fn ($key) => $positions[$key] ?? null) ->filter() ->pluck('id') ->toArray(); $appointerPosition->appointablePositions()->sync($appointableIds); } $this->command->info('部门职务 Seeder 完成:'.count($positions).' 个职务已写入。'); } /** * 部门基础数据 * * @return array> */ private function departmentsData(): array { return [ ['name' => '办公厅', 'rank' => 99, 'color' => '#8B0000', 'sort_order' => 1, 'description' => '站级最高指挥机构'], ['name' => '迎宾部', 'rank' => 80, 'color' => '#1a5276', 'sort_order' => 2, 'description' => '负责新用户迎接与接待工作'], ['name' => '聊务部', 'rank' => 75, 'color' => '#196F3D', 'sort_order' => 3, 'description' => '负责聊天室日常管理与氛围维护'], ['name' => '宣传部', 'rank' => 70, 'color' => '#7D6608', 'sort_order' => 4, 'description' => '负责聊天室宣传推广与活动策划'], ]; } /** * 职务完整数据 * * @return array> */ private function positionsData(): array { // [部门, 职务名, icon, rank, level, max_persons, max_reward, sort_order] $rows = [ // ── 办公厅 ────────────────────────────────────────────────────── ['办公厅', '站长', '👑', 99, 100, 1, null, 1], ['办公厅', '执行站长', '⭐', 97, 99, 1, null, 2], ['办公厅', '常务副站长', '📜', 95, 98, 1, 2000, 3], ['办公厅', '副站长', '🔴', 93, 97, 1, 1500, 4], ['办公厅', '秘书长', '✏️', 91, 96, 2, 1200, 5], ['办公厅', '三部总长', '🪖', 89, 95, 1, 1000, 6], // ── 迎宾部 ────────────────────────────────────────────────────── ['迎宾部', '迎宾部长', '🏆', 87, 94, 1, 800, 1], ['迎宾部', '迎宾政委', '👤', 87, 94, 1, 800, 2], ['迎宾部', '迎宾常务副部长', '📋', 85, 93, 1, 500, 3], ['迎宾部', '迎宾副部长', '🔵', 83, 92, 1, 300, 4], ['迎宾部', '迎宾副政委', '🔵', 81, 91, 1, 300, 5], ['迎宾部', '金牌迎宾员', '🥇', 70, 90, 2, null, 6], ['迎宾部', '银牌迎宾员', '🥈', 50, 80, 3, null, 7], ['迎宾部', '铜牌迎宾员', '🥉', 30, 70, 4, null, 8], ['迎宾部', '实习迎宾员', '🌱', 10, 60, 4, null, 9], // ── 聊务部 ────────────────────────────────────────────────────── ['聊务部', '聊务部部长', '🏆', 87, 94, 1, 800, 1], ['聊务部', '聊务部政委', '👤', 87, 94, 1, 800, 2], ['聊务部', '聊务部常务副部长', '📋', 85, 93, 1, 500, 3], ['聊务部', '聊务部副部长', '🔵', 83, 92, 1, 300, 4], ['聊务部', '聊务部副政委', '🔵', 81, 91, 1, 300, 5], ['聊务部', '金牌聊务员', '🥇', 70, 90, 2, null, 6], ['聊务部', '银牌聊务员', '🥈', 50, 80, 3, null, 7], ['聊务部', '铜牌聊务员', '🥉', 30, 70, 4, null, 8], ['聊务部', '实习聊务员', '🌱', 10, 60, 4, null, 9], // ── 宣传部 ────────────────────────────────────────────────────── ['宣传部', '宣传部部长', '🏆', 87, 94, 1, 800, 1], ['宣传部', '宣传部政委', '👤', 87, 94, 1, 800, 2], ['宣传部', '宣传部常务副部长', '📋', 85, 93, 1, 500, 3], ['宣传部', '宣传部副部长', '🔵', 83, 92, 1, 300, 4], ['宣传部', '宣传部副政委', '🔵', 81, 91, 1, 300, 5], ['宣传部', '金牌宣传员', '🥇', 70, 90, 2, null, 6], ['宣传部', '银牌宣传员', '🥈', 50, 80, 3, null, 7], ['宣传部', '铜牌宣传员', '🥉', 30, 70, 4, null, 8], ['宣传部', '实习宣传员', '🌱', 10, 60, 4, null, 9], ]; return array_map(fn ($r) => [ 'department' => $r[0], 'name' => $r[1], 'icon' => $r[2], 'rank' => $r[3], 'level' => $r[4], 'max_persons' => $r[5], 'max_reward' => $r[6], 'sort_order' => $r[7], ], $rows); } /** * 默认任命权限白名单 * key = "任命人职务对应的 positions key" * value = [可被任命的职务 key 列表] * * @param array $positions * @return array}> */ private function appointLimitsData(array $positions): array { // 全三部门的所有职务 key 列表(不含办公厅) $allThreeDepts = array_keys(array_filter( $positions, fn ($k) => ! str_starts_with($k, '办公厅::'), ARRAY_FILTER_USE_KEY )); // 三部门所有部长/政委及以下(全部) $allThreeAll = $allThreeDepts; // 三部门常务副部长及以下(level <= 93) $allThreeBelowZhangzhang = array_keys(array_filter( $positions, fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 93, ARRAY_FILTER_USE_BOTH )); // 三部门副部长/副政委及以下(level <= 92) $allThreeBelowFubu = array_keys(array_filter( $positions, fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 92, ARRAY_FILTER_USE_BOTH )); // 三部门金牌及以下(level <= 90) $allThreeBelowGold = array_keys(array_filter( $positions, fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 90, ARRAY_FILTER_USE_BOTH )); // 三部门银牌及以下(level <= 80) $allThreeBelowSilver = array_keys(array_filter( $positions, fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 80, ARRAY_FILTER_USE_BOTH )); /** * 便捷闭包:获取指定部门、指定最大 level 的职务 key 列表 */ $deptBelow = fn (string $dept, int $maxLevel) => array_keys(array_filter( $positions, fn ($p, $k) => str_starts_with($k, "{$dept}::") && $p->level <= $maxLevel, ARRAY_FILTER_USE_BOTH )); return [ // 办公厅 ['办公厅::站长', array_merge( ['办公厅::执行站长', '办公厅::常务副站长', '办公厅::副站长', '办公厅::秘书长', '办公厅::三部总长'], $allThreeAll )], ['办公厅::执行站长', $allThreeAll], // 三部所有职务 ['办公厅::常务副站长', $allThreeBelowZhangzhang], // 三部常务副部长及以下 ['办公厅::副站长', $allThreeBelowFubu], // 三部副部长级及以下 ['办公厅::秘书长', $allThreeBelowGold], // 三部金牌及以下 ['办公厅::三部总长', $allThreeBelowSilver], // 三部银牌及以下 // 迎宾部 ['迎宾部::迎宾部长', $deptBelow('迎宾部', 90)], ['迎宾部::迎宾政委', $deptBelow('迎宾部', 90)], ['迎宾部::迎宾常务副部长', $deptBelow('迎宾部', 80)], ['迎宾部::迎宾副部长', $deptBelow('迎宾部', 70)], ['迎宾部::迎宾副政委', $deptBelow('迎宾部', 70)], // 聊务部 ['聊务部::聊务部部长', $deptBelow('聊务部', 90)], ['聊务部::聊务部政委', $deptBelow('聊务部', 90)], ['聊务部::聊务部常务副部长', $deptBelow('聊务部', 80)], ['聊务部::聊务部副部长', $deptBelow('聊务部', 70)], ['聊务部::聊务部副政委', $deptBelow('聊务部', 70)], // 宣传部 ['宣传部::宣传部部长', $deptBelow('宣传部', 90)], ['宣传部::宣传部政委', $deptBelow('宣传部', 90)], ['宣传部::宣传部常务副部长', $deptBelow('宣传部', 80)], ['宣传部::宣传部副部长', $deptBelow('宣传部', 70)], ['宣传部::宣传部副政委', $deptBelow('宣传部', 70)], ]; } }