Files
xin-procurement/database/seeders/ProcurementSeeder.php
T
2026-07-23 20:41:25 +08:00

277 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
/**
* 订货采购系统业务菜单与权限点种子
*
* 约定(V2.0 计划):
* - local 一律留空,name 直接写中文(layout 在 local 为空时回退显示 name,无需 i18n)
* - 幂等:顶级菜单 key 已存在时跳过,可重复执行
* - 执行后自动将全部新增权限点授予超级管理员角色(role_id=1)
*
* 执行:php artisan db:seed --class=ProcurementSeeder
*/
class ProcurementSeeder extends Seeder
{
/**
* 菜单结构:menu 目录 → route 页面 → rule 权限点
*/
private function menus(): array
{
return [
[
'type' => 'menu',
'key' => 'procurement.product',
'name' => '商品中心',
'icon' => 'ShoppingOutlined',
'children' => [
[
'type' => 'route',
'key' => 'product.category',
'name' => '分类管理',
'path' => '/product/category',
'children' => [
['type' => 'rule', 'key' => 'product.category.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'product.category.create', 'name' => '新增'],
['type' => 'rule', 'key' => 'product.category.update', 'name' => '编辑'],
['type' => 'rule', 'key' => 'product.category.delete', 'name' => '删除'],
],
],
[
'type' => 'route',
'key' => 'product.goods',
'name' => '商品列表',
'path' => '/product/goods',
'children' => [
['type' => 'rule', 'key' => 'product.goods.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'product.goods.create', 'name' => '新增'],
['type' => 'rule', 'key' => 'product.goods.update', 'name' => '编辑'],
['type' => 'rule', 'key' => 'product.goods.delete', 'name' => '删除'],
['type' => 'rule', 'key' => 'product.goods.batchPrice', 'name' => '批量调价'],
],
],
],
],
[
'type' => 'menu',
'key' => 'procurement.customer',
'name' => '客户管理',
'icon' => 'ShopOutlined',
'children' => [
[
'type' => 'route',
'key' => 'customer.store',
'name' => '门店管理',
'path' => '/customer/store',
'children' => [
['type' => 'rule', 'key' => 'customer.store.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'customer.store.create', 'name' => '新增'],
['type' => 'rule', 'key' => 'customer.store.update', 'name' => '编辑'],
['type' => 'rule', 'key' => 'customer.store.delete', 'name' => '删除'],
],
],
[
'type' => 'route',
'key' => 'customer.level',
'name' => '客户等级',
'path' => '/customer/level',
'children' => [
['type' => 'rule', 'key' => 'customer.level.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'customer.level.create', 'name' => '新增'],
['type' => 'rule', 'key' => 'customer.level.update', 'name' => '编辑'],
['type' => 'rule', 'key' => 'customer.level.delete', 'name' => '删除'],
],
],
[
'type' => 'route',
'key' => 'customer.supplier',
'name' => '供应商',
'path' => '/customer/supplier',
'children' => [
['type' => 'rule', 'key' => 'customer.supplier.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'customer.supplier.create', 'name' => '新增'],
['type' => 'rule', 'key' => 'customer.supplier.update', 'name' => '编辑'],
['type' => 'rule', 'key' => 'customer.supplier.delete', 'name' => '删除'],
],
],
[
'type' => 'route',
'key' => 'customer.miniUser',
'name' => '小程序用户',
'path' => '/customer/mini-user',
'children' => [
['type' => 'rule', 'key' => 'customer.miniUser.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'customer.miniUser.update', 'name' => '启用停用'],
['type' => 'rule', 'key' => 'customer.miniUser.bind', 'name' => '绑定主体'],
],
],
[
'type' => 'route',
'key' => 'customer.notice',
'name' => '通知管理',
'path' => '/customer/notice',
'children' => [
['type' => 'rule', 'key' => 'customer.notice.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'customer.notice.create', 'name' => '发布'],
['type' => 'rule', 'key' => 'customer.notice.delete', 'name' => '删除'],
],
],
],
],
[
'type' => 'menu',
'key' => 'procurement.order',
'name' => '订货管理',
'icon' => 'FileTextOutlined',
'children' => [
[
'type' => 'route',
'key' => 'order.store',
'name' => '门店订单',
'path' => '/order/store',
'children' => [
['type' => 'rule', 'key' => 'order.store.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'order.store.update', 'name' => '状态流转'],
],
],
],
],
[
'type' => 'menu',
'key' => 'procurement.purchase',
'name' => '采购管理',
'icon' => 'ShoppingCartOutlined',
'children' => [
[
'type' => 'route',
'key' => 'purchase.order',
'name' => '采购单',
'path' => '/purchase/order',
'children' => [
['type' => 'rule', 'key' => 'purchase.order.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'purchase.order.update', 'name' => '修改'],
['type' => 'rule', 'key' => 'purchase.order.generate', 'name' => '生成采购单'],
['type' => 'rule', 'key' => 'purchase.order.export', 'name' => '导出'],
['type' => 'rule', 'key' => 'purchase.order.send', 'name' => '发送供应商'],
['type' => 'rule', 'key' => 'purchase.order.allocate', 'name' => '金额分摊'],
],
],
],
],
[
'type' => 'menu',
'key' => 'procurement.recon',
'name' => '对账管理',
'icon' => 'AccountBookOutlined',
'children' => [
[
'type' => 'route',
'key' => 'recon.list',
'name' => '财务对账',
'path' => '/recon/list',
'children' => [
['type' => 'rule', 'key' => 'recon.list.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'recon.list.create', 'name' => '新增'],
['type' => 'rule', 'key' => 'recon.list.update', 'name' => '编辑'],
['type' => 'rule', 'key' => 'recon.list.delete', 'name' => '删除'],
['type' => 'rule', 'key' => 'recon.list.build', 'name' => '生成明细'],
['type' => 'rule', 'key' => 'recon.list.settle', 'name' => '生成结算表'],
// 对账明细操作权限点在独立控制器 recon.item 下(D4/D6/D8
['type' => 'rule', 'key' => 'recon.item.item.update', 'name' => '对账明细操作'],
],
],
[
'type' => 'route',
'key' => 'recon.statement',
'name' => '门店对账单',
'path' => '/recon/statement',
'children' => [
['type' => 'rule', 'key' => 'recon.statement.query', 'name' => '查询'],
],
],
[
'type' => 'route',
'key' => 'recon.settlement',
'name' => '结算表',
'path' => '/recon/settlement',
'children' => [
['type' => 'rule', 'key' => 'recon.settlement.query', 'name' => '查询'],
['type' => 'rule', 'key' => 'recon.settlement.download', 'name' => '下载导出'],
],
],
],
],
];
}
public function run(): void
{
$existing = DB::table('sys_rule')
->whereIn('key', ['procurement.product', 'procurement.customer', 'procurement.order', 'procurement.purchase', 'procurement.recon'])
->exists();
if ($existing) {
$this->command?->warn('业务菜单已存在,跳过 ProcurementSeeder');
return;
}
DB::transaction(function () {
$ruleIds = [];
foreach ($this->menus() as $menu) {
$this->insertNode($menu, 0, $ruleIds);
}
// 授权给超级管理员角色(role_id=1),去重已存在的关联
$existingPairs = DB::table('sys_role_rule')
->where('role_id', 1)
->whereIn('rule_id', $ruleIds)
->pluck('rule_id')
->all();
$newPairs = array_map(
static fn (int $ruleId) => ['role_id' => 1, 'rule_id' => $ruleId],
array_values(array_diff($ruleIds, $existingPairs))
);
if ($newPairs !== []) {
DB::table('sys_role_rule')->insert($newPairs);
}
$this->command?->info('业务菜单与权限点已写入,共 ' . count($ruleIds) . ' 个权限点已授权给超级管理员');
});
}
/**
* 递归写入菜单节点,收集全部节点 ID(menu/route/rule)用于授权
*
* @param array<string, mixed> $node
* @param array<int> $ruleIds
*/
private function insertNode(array $node, int $parentId, array &$ruleIds): void
{
$now = now();
$id = DB::table('sys_rule')->insertGetId([
'parent_id' => $parentId,
'type' => $node['type'],
'key' => $node['key'],
'name' => $node['name'],
'path' => $node['path'] ?? '',
'icon' => $node['icon'] ?? '',
'order' => 0,
'local' => '',
'status' => 1,
'hidden' => 1,
'link' => 0,
'created_at' => $now,
'updated_at' => $now,
]);
$ruleIds[] = $id;
foreach ($node['children'] ?? [] as $child) {
$this->insertNode($child, $id, $ruleIds);
}
}
}