后端 (Laravel 10 + Sanctum): - RBAC 四层权限系统 (users→roles→permissions→menus) - 门店隔离中间件 (BelongsToStore Trait + StoreIsolation Middleware) - 操作日志中间件 (自动记录写操作) - 权限检查中间件 (CheckPermission) - 16张数据库表迁移 (系统基础+RBAC+字典+配置) - 11个 Eloquent Model - Auth API (登录/登出/用户信息) - 系统设置模块 CRUD (门店/部门/职务/用户/角色/菜单/权限/字典/日志) - 45条 RESTful API 路由 - InitSeeder 初始数据 (超管/角色/76权限/31菜单) 前端 (Vue 3 + Element Plus + Vite): - Axios 请求封装 + Token 注入 - Pinia 状态管理 (user + permission store) - 动态路由 (服务端菜单→前端路由自动生成) - 后台布局 (侧边栏+顶栏+主内容区) - 登录页 + 仪表盘首页 - 系统设置 7 个 CRUD 页面 技术方案文档 (7卷): - 技术总览/数据库设计/API规范/RBAC设计/模块详设/小程序设计/部署方案
267 lines
14 KiB
PHP
267 lines
14 KiB
PHP
<?php
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use App\Models\Department;
|
|
use App\Models\Menu;
|
|
use App\Models\Permission;
|
|
use App\Models\Region;
|
|
use App\Models\Role;
|
|
use App\Models\Store;
|
|
use App\Models\User;
|
|
use Illuminate\Database\Seeder;
|
|
|
|
class InitSeeder extends Seeder
|
|
{
|
|
public function run(): void
|
|
{
|
|
// 1. 创建默认区域
|
|
$region = Region::create(['name' => '默认区域', 'sort' => 0, 'status' => 1]);
|
|
|
|
// 2. 创建默认门店
|
|
$store = Store::create([
|
|
'region_id' => $region->id,
|
|
'name' => '宫中有喜总店',
|
|
'code' => 'HQ001',
|
|
'status' => 1,
|
|
]);
|
|
|
|
// 3. 创建默认部门
|
|
Department::create(['store_id' => $store->id, 'name' => '管理层', 'sort' => 0]);
|
|
|
|
// 4. 创建超级管理员
|
|
$admin = User::create([
|
|
'store_id' => $store->id,
|
|
'username' => 'admin',
|
|
'password' => 'admin123',
|
|
'name' => '超级管理员',
|
|
'status' => 1,
|
|
'is_super' => 1,
|
|
]);
|
|
|
|
// 5. 创建默认角色
|
|
$superRole = Role::create([
|
|
'name' => '超级管理员',
|
|
'code' => 'super_admin',
|
|
'description' => '系统最高权限',
|
|
'is_system' => 1,
|
|
]);
|
|
|
|
$storeAdmin = Role::create([
|
|
'store_id' => $store->id,
|
|
'name' => '门店管理员',
|
|
'code' => 'store_admin',
|
|
'description' => '门店最高权限',
|
|
'is_system' => 1,
|
|
]);
|
|
|
|
$admin->roles()->attach($superRole->id);
|
|
|
|
// 6. 创建权限
|
|
$this->createPermissions();
|
|
|
|
// 7. 创建菜单
|
|
$this->createMenus();
|
|
|
|
// 8. 门店管理员分配所有权限
|
|
$allPermissions = Permission::pluck('id')->toArray();
|
|
$storeAdmin->permissions()->sync($allPermissions);
|
|
}
|
|
|
|
private function createPermissions(): void
|
|
{
|
|
$modules = [
|
|
['name' => 'CRM管理', 'code' => 'crm', 'children' => [
|
|
['name' => '线索管理', 'code' => 'crm.lead', 'children' => [
|
|
['name' => '查看', 'code' => 'crm.lead.view', 'type' => 2],
|
|
['name' => '新建', 'code' => 'crm.lead.create', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'crm.lead.update', 'type' => 2],
|
|
['name' => '删除', 'code' => 'crm.lead.delete', 'type' => 2],
|
|
]],
|
|
['name' => '客户管理', 'code' => 'crm.customer', 'children' => [
|
|
['name' => '查看', 'code' => 'crm.customer.view', 'type' => 2],
|
|
['name' => '新建', 'code' => 'crm.customer.create', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'crm.customer.update', 'type' => 2],
|
|
['name' => '删除', 'code' => 'crm.customer.delete', 'type' => 2],
|
|
]],
|
|
['name' => '合同管理', 'code' => 'crm.contract', 'children' => [
|
|
['name' => '查看', 'code' => 'crm.contract.view', 'type' => 2],
|
|
['name' => '新建', 'code' => 'crm.contract.create', 'type' => 2],
|
|
['name' => '审批', 'code' => 'crm.contract.approve', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '房务管理', 'code' => 'room', 'children' => [
|
|
['name' => '房间管理', 'code' => 'room.room', 'children' => [
|
|
['name' => '查看', 'code' => 'room.room.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'room.room.update', 'type' => 2],
|
|
]],
|
|
['name' => '预定管理', 'code' => 'room.reservation', 'children' => [
|
|
['name' => '查看', 'code' => 'room.reservation.view', 'type' => 2],
|
|
['name' => '新建', 'code' => 'room.reservation.create', 'type' => 2],
|
|
['name' => '操作', 'code' => 'room.reservation.operate', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '护理管理', 'code' => 'care', 'children' => [
|
|
['name' => '护理档案', 'code' => 'care.profile', 'children' => [
|
|
['name' => '查看', 'code' => 'care.profile.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'care.profile.update', 'type' => 2],
|
|
]],
|
|
['name' => '护理记录', 'code' => 'care.record', 'children' => [
|
|
['name' => '查看', 'code' => 'care.record.view', 'type' => 2],
|
|
['name' => '新建', 'code' => 'care.record.create', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '月子餐管理', 'code' => 'meal', 'children' => [
|
|
['name' => '菜品管理', 'code' => 'meal.dish', 'children' => [
|
|
['name' => '查看', 'code' => 'meal.dish.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'meal.dish.update', 'type' => 2],
|
|
]],
|
|
['name' => '排餐管理', 'code' => 'meal.plan', 'children' => [
|
|
['name' => '查看', 'code' => 'meal.plan.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'meal.plan.update', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '服务产康', 'code' => 'service', 'children' => [
|
|
['name' => '服务项目', 'code' => 'service.item', 'children' => [
|
|
['name' => '查看', 'code' => 'service.item.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'service.item.update', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '月嫂管理', 'code' => 'nanny', 'children' => [
|
|
['name' => '月嫂档案', 'code' => 'nanny.profile', 'children' => [
|
|
['name' => '查看', 'code' => 'nanny.profile.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'nanny.profile.update', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '进销存', 'code' => 'stock', 'children' => [
|
|
['name' => '库存管理', 'code' => 'stock.inventory', 'children' => [
|
|
['name' => '查看', 'code' => 'stock.inventory.view', 'type' => 2],
|
|
['name' => '操作', 'code' => 'stock.inventory.operate', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '财务管理', 'code' => 'finance', 'children' => [
|
|
['name' => '收支管理', 'code' => 'finance.record', 'children' => [
|
|
['name' => '查看', 'code' => 'finance.record.view', 'type' => 2],
|
|
['name' => '新建', 'code' => 'finance.record.create', 'type' => 2],
|
|
['name' => '审核', 'code' => 'finance.record.approve', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '人事薪资', 'code' => 'hr', 'children' => [
|
|
['name' => '员工管理', 'code' => 'hr.employee', 'children' => [
|
|
['name' => '查看', 'code' => 'hr.employee.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'hr.employee.update', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '办公协同', 'code' => 'office', 'children' => [
|
|
['name' => '审批管理', 'code' => 'office.approval', 'children' => [
|
|
['name' => '查看', 'code' => 'office.approval.view', 'type' => 2],
|
|
['name' => '审批', 'code' => 'office.approval.operate', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '统计报表', 'code' => 'report', 'children' => [
|
|
['name' => '查看报表', 'code' => 'report.view', 'type' => 2],
|
|
['name' => '导出报表', 'code' => 'report.export', 'type' => 2],
|
|
]],
|
|
['name' => '知识库', 'code' => 'kb', 'children' => [
|
|
['name' => '文章管理', 'code' => 'kb.article', 'children' => [
|
|
['name' => '查看', 'code' => 'kb.article.view', 'type' => 2],
|
|
['name' => '编辑', 'code' => 'kb.article.update', 'type' => 2],
|
|
]],
|
|
]],
|
|
['name' => '系统设置', 'code' => 'system', 'children' => [
|
|
['name' => '门店管理', 'code' => 'system.store', 'type' => 2],
|
|
['name' => '用户管理', 'code' => 'system.user', 'type' => 2],
|
|
['name' => '角色管理', 'code' => 'system.role', 'type' => 2],
|
|
['name' => '菜单管理', 'code' => 'system.menu', 'type' => 2],
|
|
['name' => '字典管理', 'code' => 'system.dict', 'type' => 2],
|
|
['name' => '操作日志', 'code' => 'system.log', 'type' => 2],
|
|
]],
|
|
];
|
|
|
|
$this->insertPermissions($modules);
|
|
}
|
|
|
|
private function insertPermissions(array $items, int $parentId = 0, int &$sort = 0): void
|
|
{
|
|
foreach ($items as $item) {
|
|
$children = $item['children'] ?? [];
|
|
unset($item['children']);
|
|
|
|
$item['parent_id'] = $parentId;
|
|
$item['type'] = $item['type'] ?? 1;
|
|
$item['module'] = explode('.', $item['code'])[0];
|
|
$item['sort'] = $sort++;
|
|
|
|
$permission = Permission::create($item);
|
|
|
|
if ($children) {
|
|
$this->insertPermissions($children, $permission->id, $sort);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function createMenus(): void
|
|
{
|
|
$menus = [
|
|
['name' => '首页', 'path' => '/dashboard', 'component' => 'dashboard/index', 'icon' => 'HomeFilled', 'sort' => 0],
|
|
['name' => 'CRM管理', 'icon' => 'User', 'sort' => 1, 'permission_code' => 'crm', 'children' => [
|
|
['name' => '线索管理', 'path' => '/crm/leads', 'component' => 'crm/leads/index', 'permission_code' => 'crm.lead'],
|
|
['name' => '客户管理', 'path' => '/crm/customers', 'component' => 'crm/customers/index', 'permission_code' => 'crm.customer'],
|
|
['name' => '合同管理', 'path' => '/crm/contracts', 'component' => 'crm/contracts/index', 'permission_code' => 'crm.contract'],
|
|
]],
|
|
['name' => '房务管理', 'icon' => 'House', 'sort' => 2, 'permission_code' => 'room', 'children' => [
|
|
['name' => '房态看板', 'path' => '/room/board', 'component' => 'room/board/index', 'permission_code' => 'room.room'],
|
|
['name' => '预定管理', 'path' => '/room/reservations', 'component' => 'room/reservations/index', 'permission_code' => 'room.reservation'],
|
|
]],
|
|
['name' => '护理管理', 'icon' => 'FirstAidKit', 'sort' => 3, 'permission_code' => 'care', 'children' => [
|
|
['name' => '护理档案', 'path' => '/care/profiles', 'component' => 'care/profiles/index', 'permission_code' => 'care.profile'],
|
|
['name' => '护理记录', 'path' => '/care/records', 'component' => 'care/records/index', 'permission_code' => 'care.record'],
|
|
]],
|
|
['name' => '月子餐', 'icon' => 'Bowl', 'sort' => 4, 'permission_code' => 'meal', 'children' => [
|
|
['name' => '菜品管理', 'path' => '/meal/dishes', 'component' => 'meal/dishes/index', 'permission_code' => 'meal.dish'],
|
|
['name' => '排餐管理', 'path' => '/meal/plans', 'component' => 'meal/plans/index', 'permission_code' => 'meal.plan'],
|
|
]],
|
|
['name' => '服务产康', 'icon' => 'Promotion', 'sort' => 5, 'permission_code' => 'service'],
|
|
['name' => '月嫂管理', 'icon' => 'Avatar', 'sort' => 6, 'permission_code' => 'nanny'],
|
|
['name' => '进销存', 'icon' => 'Box', 'sort' => 7, 'permission_code' => 'stock'],
|
|
['name' => '财务管理', 'icon' => 'Money', 'sort' => 8, 'permission_code' => 'finance'],
|
|
['name' => '人事薪资', 'icon' => 'Stamp', 'sort' => 9, 'permission_code' => 'hr'],
|
|
['name' => '办公协同', 'icon' => 'ChatDotRound', 'sort' => 10, 'permission_code' => 'office'],
|
|
['name' => '统计报表', 'icon' => 'DataAnalysis', 'sort' => 11, 'permission_code' => 'report'],
|
|
['name' => '知识库', 'icon' => 'Reading', 'sort' => 12, 'permission_code' => 'kb'],
|
|
['name' => '系统设置', 'icon' => 'Setting', 'sort' => 99, 'permission_code' => 'system', 'children' => [
|
|
['name' => '门店管理', 'path' => '/system/stores', 'component' => 'system/stores/index', 'permission_code' => 'system.store'],
|
|
['name' => '部门管理', 'path' => '/system/departments', 'component' => 'system/departments/index', 'permission_code' => 'system.store'],
|
|
['name' => '职务管理', 'path' => '/system/positions', 'component' => 'system/positions/index', 'permission_code' => 'system.store'],
|
|
['name' => '用户管理', 'path' => '/system/users', 'component' => 'system/users/index', 'permission_code' => 'system.user'],
|
|
['name' => '角色管理', 'path' => '/system/roles', 'component' => 'system/roles/index', 'permission_code' => 'system.role'],
|
|
['name' => '菜单管理', 'path' => '/system/menus', 'component' => 'system/menus/index', 'permission_code' => 'system.menu'],
|
|
['name' => '字典管理', 'path' => '/system/dictionaries', 'component' => 'system/dictionaries/index', 'permission_code' => 'system.dict'],
|
|
['name' => '操作日志', 'path' => '/system/logs', 'component' => 'system/logs/index', 'permission_code' => 'system.log'],
|
|
]],
|
|
];
|
|
|
|
$this->insertMenus($menus);
|
|
}
|
|
|
|
private function insertMenus(array $items, int $parentId = 0): void
|
|
{
|
|
foreach ($items as $index => $item) {
|
|
$children = $item['children'] ?? [];
|
|
unset($item['children']);
|
|
|
|
$item['parent_id'] = $parentId;
|
|
$item['type'] = isset($item['component']) ? 2 : 1; // 有 component = 菜单,否则目录
|
|
$item['sort'] = $item['sort'] ?? $index;
|
|
$item['visible'] = 1;
|
|
$item['status'] = 1;
|
|
|
|
$menu = Menu::create($item);
|
|
|
|
if ($children) {
|
|
$this->insertMenus($children, $menu->id);
|
|
}
|
|
}
|
|
}
|
|
}
|