- 任命/撤销事件增加 type 字段区分类型 - 任命:全屏礼花 + 紫色弹窗 + 紫色系统消息 - 撤销:灰色弹窗 + 灰色系统消息,无礼花 - 消息分发:操作者/被操作者显示在私聊面板,其他人显示在公屏 - 系统消息加随机鼓励语(各5条轮换) - ChatStateService 修复 Redis key 前缀扫描问题(getAllActiveRoomIds) - 用户名片折叠优化:管理员视野、职务履历均可折叠 - 管理操作 + 职务操作合并为「🔧 管理操作」折叠区 - 悄悄话改为「🎁 送礼物」按钮,礼物面板内联展开
241 lines
12 KiB
PHP
241 lines
12 KiB
PHP
<?php
|
||
|
||
/**
|
||
* 文件功能:部门与职务数据填充器
|
||
* 预填所有部门(办公厅 / 迎宾部 / 聊务部 / 宣传部)
|
||
* 及各部门下的完整职务数据(含图标、rank、level、人数/奖励上限)
|
||
* 并写入默认的任命权限白名单(position_appoint_limits)
|
||
*
|
||
* @author ChatRoom Laravel
|
||
*
|
||
* @version 1.0.0
|
||
*/
|
||
|
||
namespace Database\Seeders;
|
||
|
||
use App\Models\Department;
|
||
use App\Models\Position;
|
||
use Illuminate\Database\Seeder;
|
||
|
||
class DepartmentPositionSeeder extends Seeder
|
||
{
|
||
/**
|
||
* 执行数据填充
|
||
*/
|
||
public function run(): void
|
||
{
|
||
// ── 1. 创建部门 ────────────────────────────────────────────────────
|
||
$depts = [];
|
||
foreach ($this->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<int, array<string, mixed>>
|
||
*/
|
||
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<int, array<string, mixed>>
|
||
*/
|
||
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<string, Position> $positions
|
||
* @return array<int, array{0: string, 1: list<string>}>
|
||
*/
|
||
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)],
|
||
];
|
||
}
|
||
}
|