bianjunhui 13 ساعت پیش
والد
کامیت
efe19474ee

+ 1 - 0
.gitignore

@@ -7,6 +7,7 @@
 .vagrant
 *.hot
 /stubs
+/tmp/*
 /data
 /docker-compose-collection
 Homestead.json

+ 22 - 17
packages/Longyi/DynamicMenu/src/Providers/DynamicMenuServiceProvider.php

@@ -4,40 +4,45 @@ namespace Longyi\DynamicMenu\Providers;
 
 use Illuminate\Support\ServiceProvider;
 use Illuminate\Support\Facades\Route; // 添加这行!很重要
+use Illuminate\Support\Facades\Event;
 use Longyi\DynamicMenu\Http\Middleware\CheckMenuPermission;
 
 class DynamicMenuServiceProvider extends ServiceProvider
 {
     public function boot()
     {
-       
-        // 检查路由文件是否存在
-        $routePath = __DIR__ . '/../Routes/admin-routes.php';
-        $this->loadRoutesFrom($routePath);
+        $this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
+        $this->loadRoutesFrom(__DIR__ . '/../Routes/admin-routes.php');
         $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'dynamicmenu');
         $this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'dynamicmenu');
-        $this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
-        
-        $this->app['router']->aliasMiddleware('menu.permission', CheckMenuPermission::class);
-        
+
         $this->publishes([
-            __DIR__ . '/../Resources/views' => resource_path('views/vendor/longyi/dynamicmenu'),
-        ], 'views');
-        
+            __DIR__ . '/../../publishable/assets' => public_path('vendor/dynamicmenu'),
+        ], 'public');
+
         // 注册菜单
-        $this->registerMenu();
+        $this->registerAdminMenu();
     }
-    
+
     public function register()
     {
-        // 合并配置时,确保所有菜单项都有 key
-        $this->mergeConfigFrom(__DIR__ . '/../Config/menu.php', 'menu.admin');
-        
+        $this->mergeConfigFrom(
+            __DIR__ . '/../Config/menu.php', 'menu.admin'
+        );
         $this->app->singleton('dynamicmenu', function () {
             return new \Longyi\DynamicMenu\DynamicMenu();
         });
     }
-    
+
+    protected function registerAdminMenu()
+    {
+        Event::listen('bagisto.admin.menu.build', function ($menu) {
+            // 在 Settings 菜单下添加 Dynamic Menu
+            $menu->add('settings.dynamic-menu', 'dynamicmenu::app.admin.menu.title', 'admin.dynamicmenu.index', 5, 'icon-menu')
+                 ->addSub('settings.dynamic-menu.items', 'dynamicmenu::app.admin.menu.items', 'admin.dynamicmenu.index', 1, 'icon-list')
+                 ->addSub('settings.dynamic-menu.permissions', 'dynamicmenu::app.admin.menu.permissions', 'admin.dynamicmenu.permission', 2, 'icon-permission');
+        });
+    }
     protected function registerMenu()
     {
         $this->app->booted(function () {

+ 39 - 36
packages/Longyi/DynamicMenu/src/Resources/lang/en/app.php

@@ -1,40 +1,43 @@
 <?php
 
 return [
-    'menu' => [
-        'title' => 'Dynamic Menu Management',
-        'add-title' => 'Add Menu Item',
-        'edit-title' => 'Edit Menu Item',
-        'name' => 'Menu Name',
-        'key' => 'Menu Key',
-        'key-info' => 'Unique identifier for the menu item (e.g., catalog.products)',
-        'route' => 'Route Name',
-        'route-info' => 'Laravel route name (e.g., admin.catalog.products.index)',
-        'icon' => 'Icon Class',
-        'icon-info' => 'Icon class name (e.g., icon-product, icon-catalog)',
-        'parent' => 'Parent Menu',
-        'no-parent' => 'No Parent (Top Level)',
-        'sort-order' => 'Sort Order',
-        'status' => 'Status',
-        'active' => 'Active',
-        'inactive' => 'Inactive',
-        'save' => 'Save Menu Item',
-        'cancel' => 'Cancel',
-        'created-success' => 'Menu item created successfully',
-        'updated-success' => 'Menu item updated successfully',
-        'deleted-success' => 'Menu item deleted successfully',
-        'delete-warning' => 'Are you sure you want to delete this menu item?',
-        'cannot-delete' => 'Cannot delete menu item with children',
-        'delete-children-first' => 'Please delete child menu items first',
+    'admin' => [
+        'menu' => [
+            'title' => 'Dynamic Menu',
+            'items' => 'Menu Items',
+            'permissions' => 'Menu Permissions',
+            'add-title' => 'Add Menu Item',
+            'edit-title' => 'Edit Menu Item',
+            'add-btn' => 'Add Menu Item',
+            'back-btn' => 'Back',
+            'save-btn' => 'Save',
+            'cancel-btn' => 'Cancel',
+            'basic-info' => 'Basic Information',
+            'name' => 'Name',
+            'name-placeholder' => 'e.g. Dashboard',
+            'key' => 'Key',
+            'key-placeholder' => 'e.g. admin.dashboard',
+            'key-info' => 'Used for permission validation and menu activation',
+            'route' => 'URL/Route',
+            'route-placeholder' => 'e.g. admin.dashboard',
+            'route-info' => 'Can be relative path, full URL or route name',
+            'icon' => 'Icon',
+            'icon-placeholder' => 'e.g. icon-menu',
+            'icon-info' => 'Webkul admin panel icon class',
+            'parent' => 'Parent Menu',
+            'parent-none' => 'As Top Level Menu',
+            'has-children' => 'Has Children',
+            'sort-order' => 'Sort Order',
+            'sort-order-info' => 'Lower number appears first',
+            'status' => 'Status',
+            'status-active' => 'Active',
+            'status-inactive' => 'Inactive',
+            'edit' => 'Edit',
+            'delete' => 'Delete',
+            'delete-confirm' => 'Are you sure?',
+            'delete-disabled' => 'Please delete child menus first',
+            'disabled' => 'Disabled',
+            'no-identifier' => 'No identifier',
+        ],
     ],
-
-    'permission' => [
-        'title' => 'Menu Permissions',
-        'select-role' => 'Select Role',
-        'choose-role' => '-- Choose Role --',
-        'menu-items' => 'Menu Items',
-        'save' => 'Save Permissions',
-        'updated-success' => 'Menu permissions updated successfully',
-        'denied' => 'You do not have permission to access this page',
-    ],
-];
+];

+ 37 - 0
packages/Longyi/DynamicMenu/src/Resources/lang/zh_CN/app.php

@@ -0,0 +1,37 @@
+<?php
+
+return [
+    'admin' => [
+        'menu' => [
+            'title' => '动态菜单',
+            'items' => '菜单项',
+            'permissions' => '菜单权限',
+            'add-title' => '添加菜单项',
+            'edit-title' => '编辑菜单项',
+            'add-btn' => '添加菜单项',
+            'back-btn' => '返回列表',
+            'save-btn' => '保存菜单项',
+            'cancel-btn' => '取消',
+            'basic-info' => '基本信息',
+            'name' => '名称',
+            'name-placeholder' => '例如:仪表盘',
+            'key' => 'Key',
+            'key-placeholder' => '例如:admin.dashboard',
+            'key-info' => '用于权限验证和菜单激活状态判断',
+            'route' => 'URL/路由',
+            'route-placeholder' => '例如:admin.dashboard',
+            'route-info' => '可以是相对路径、完整URL或路由名称',
+            'icon' => '图标',
+            'icon-placeholder' => '例如:icon-menu',
+            'icon-info' => 'Webkul admin面板的图标类名',
+            'parent' => '父级菜单',
+            'parent-none' => '作为顶级菜单',
+            'has-children' => '有子菜单',
+            'sort-order' => '排序',
+            'sort-order-info' => '数字越小越靠前',
+            'status' => '状态',
+            'status-active' => '启用',
+            'status-inactive' => '禁用',
+        ],
+    ],
+];

+ 72 - 167
packages/Longyi/DynamicMenu/src/Resources/views/admin/menu/create.blade.php

@@ -1,132 +1,16 @@
-{{-- 不继承任何布局 --}}
-<!DOCTYPE html>
-<html lang="zh-CN">
-<head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <meta name="csrf-token" content="{{ csrf_token() }}">
-    <title>添加菜单项</title>
-    
-    {{-- 引入必要的CSS --}}
-    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
-    
-    <style>
-        body {
-            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
-            background-color: #f8f9fa;
-            padding: 20px;
-        }
-        .page-header {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            margin-bottom: 20px;
-            padding-bottom: 10px;
-            border-bottom: 1px solid #dee2e6;
-        }
-        .page-title h1 {
-            margin: 0;
-            font-size: 24px;
-            color: #333;
-        }
-        .page-action {
-            display: flex;
-            gap: 10px;
-        }
-        .btn {
-            display: inline-block;
-            padding: 8px 16px;
-            border-radius: 4px;
-            text-decoration: none;
-            cursor: pointer;
-            border: 1px solid transparent;
-        }
-        .btn-primary {
-            background-color: #007bff;
-            color: white;
-        }
-        .btn-primary:hover {
-            background-color: #0056b3;
-        }
-        .btn-secondary {
-            background-color: #6c757d;
-            color: white;
-        }
-        .btn-sm {
-            padding: 4px 8px;
-            font-size: 14px;
-        }
-        .btn-lg {
-            padding: 12px 24px;
-            font-size: 18px;
-        }
-        .panel {
-            background: white;
-            border: 1px solid #dee2e6;
-            border-radius: 4px;
-            margin-bottom: 20px;
-        }
-        .panel-header {
-            padding: 12px 20px;
-            background-color: #f8f9fa;
-            border-bottom: 1px solid #dee2e6;
-        }
-        .panel-header h3 {
-            margin: 0;
-            font-size: 18px;
-        }
-        .panel-body {
-            padding: 20px;
-        }
-        .form-group {
-            margin-bottom: 20px;
-        }
-        .form-group label {
-            display: block;
-            margin-bottom: 5px;
-            font-weight: 500;
-        }
-        .form-group label.required:after {
-            content: " *";
-            color: red;
-        }
-        .control {
-            width: 100%;
-            padding: 8px 12px;
-            border: 1px solid #dee2e6;
-            border-radius: 4px;
-            font-size: 14px;
-        }
-        .control:focus {
-            border-color: #80bdff;
-            outline: 0;
-            box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
-        }
-        .control-info {
-            display: block;
-            margin-top: 5px;
-            font-size: 12px;
-            color: #6c757d;
-        }
-        .radio-inline {
-            margin-right: 20px;
-            display: inline-flex;
-            align-items: center;
-        }
-        .radio-inline input {
-            margin-right: 5px;
-        }
-    </style>
-</head>
-<body>
-    <div class="container-fluid">
-        <div class="page-header">
+<x-admin::layouts>
+    {{-- 页面标题 --}}
+    <x-slot:title>添加菜单项</x-slot:title>
+
+    {{-- 页面内容 --}}
+    <div class="content" style="padding: 20px;">
+        {{-- 页头部分 --}}
+        <div class="page-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #dee2e6;">
             <div class="page-title">
                 <h1><i class="fas fa-plus-circle"></i> 添加菜单项</h1>
             </div>
             <div class="page-action">
-                <a href="{{ route('admin.dynamicmenu.index') }}" class="btn btn-secondary">
+                <a href="{{ route('admin.dynamicmenu.index') }}" class="btn btn-secondary" style="padding: 8px 16px; background: #6c757d; color: white; text-decoration: none; border-radius: 4px;">
                     <i class="fas fa-arrow-left"></i> 返回列表
                 </a>
             </div>
@@ -134,8 +18,8 @@
 
         {{-- 显示错误信息 --}}
         @if($errors->any())
-            <div class="alert alert-danger">
-                <ul class="mb-0">
+            <div class="alert alert-danger" style="background: #f8d7da; color: #721c24; padding: 12px; border-radius: 4px; margin-bottom: 20px; border: 1px solid #f5c6cb;">
+                <ul class="mb-0" style="margin: 0; padding-left: 20px;">
                     @foreach($errors->all() as $error)
                         <li>{{ $error }}</li>
                     @endforeach
@@ -143,64 +27,79 @@
             </div>
         @endif
 
-        <div class="panel">
-            <div class="panel-header">
-                <h3>基本信息</h3>
+        {{-- 表单面板 --}}
+        <div class="panel" style="background: white; border: 1px solid #dee2e6; border-radius: 4px; margin-bottom: 20px;">
+            <div class="panel-header" style="padding: 12px 20px; background: #f8f9fa; border-bottom: 1px solid #dee2e6;">
+                <h3 style="margin: 0; font-size: 18px;">基本信息</h3>
             </div>
             
-            <div class="panel-body">
+            <div class="panel-body" style="padding: 20px;">
                 <form method="POST" action="{{ route('admin.dynamicmenu.store') }}">
                     @csrf
                     
                     {{-- 名称 --}}
-                    <div class="form-group">
-                        <label class="required">名称</label>
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label class="required" style="display: block; margin-bottom: 5px; font-weight: 500;">
+                            名称 <span style="color: red;">*</span>
+                        </label>
                         <input type="text" 
                                name="name" 
                                class="control" 
                                value="{{ old('name') }}" 
                                required
-                               placeholder="例如:仪表盘">
+                               placeholder="例如:仪表盘"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
                     </div>
 
                     {{-- Key --}}
-                    <div class="form-group">
-                        <label class="required">Key</label>
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label class="required" style="display: block; margin-bottom: 5px; font-weight: 500;">
+                            Key <span style="color: red;">*</span>
+                        </label>
                         <input type="text" 
                                name="key" 
                                class="control" 
                                value="{{ old('key') }}" 
                                required
-                               placeholder="例如:admin.dashboard">
-                        <small class="control-info">用于权限验证和菜单激活状态判断</small>
+                               placeholder="例如:admin.dashboard"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            用于权限验证和菜单激活状态判断
+                        </small>
                     </div>
 
                     {{-- URL/路由 --}}
-                    <div class="form-group">
-                        <label>URL/路由</label>
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">URL/路由</label>
                         <input type="text" 
                                name="route" 
                                class="control" 
                                value="{{ old('route') }}"
-                               placeholder="例如:admin.dashboard">
-                        <small class="control-info">可以是相对路径、完整URL或路由名称</small>
+                               placeholder="例如:admin.dashboard"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            可以是相对路径、完整URL或路由名称
+                        </small>
                     </div>
 
                     {{-- 图标 --}}
-                    <div class="form-group">
-                        <label>图标</label>
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">图标</label>
                         <input type="text" 
                                name="icon" 
                                class="control" 
                                value="{{ old('icon', 'fas fa-file') }}"
-                               placeholder="例如:fas fa-dashboard、fas fa-users等">
-                        <small class="control-info">FontAwesome图标类名,如:fas fa-home</small>
+                               placeholder="例如:fas fa-dashboard、fas fa-users等"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            FontAwesome图标类名,如:fas fa-home
+                        </small>
                     </div>
 
                     {{-- 父级菜单 --}}
-                    <div class="form-group">
-                        <label>父级菜单</label>
-                        <select name="parent_id" class="control">
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">父级菜单</label>
+                        <select name="parent_id" class="control" style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
                             <option value="">作为顶级菜单</option>
                             @foreach($menuItems as $menuItem)
                                 <option value="{{ $menuItem->id }}" {{ old('parent_id') == $menuItem->id ? 'selected' : '' }}>
@@ -214,37 +113,40 @@
                     </div>
 
                     {{-- 排序 --}}
-                    <div class="form-group">
-                        <label>排序</label>
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">排序</label>
                         <input type="number" 
-                               name="order" 
+                               name="sort_order" 
                                class="control" 
-                               value="{{ old('order', 0) }}"
-                               min="0">
-                        <small class="control-info">数字越小越靠前</small>
+                               value="{{ old('sort_order', 0) }}"
+                               min="0"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            数字越小越靠前
+                        </small>
                     </div>
 
                     {{-- 状态 --}}
-                    <div class="form-group">
-                        <label>状态</label>
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">状态</label>
                         <div>
-                            <label class="radio-inline">
-                                <input type="radio" name="status" value="1" {{ old('is_active', 1) == 1 ? 'checked' : '' }}>
+                            <label class="radio-inline" style="margin-right: 20px; display: inline-flex; align-items: center;">
+                                <input type="radio" name="status" value="1" {{ old('status', 1) == 1 ? 'checked' : '' }} style="margin-right: 5px;">
                                 启用
                             </label>
-                            <label class="radio-inline">
-                                <input type="radio" name="status" value="0" {{ old('is_active') == 0 ? 'checked' : '' }}>
+                            <label class="radio-inline" style="margin-right: 20px; display: inline-flex; align-items: center;">
+                                <input type="radio" name="status" value="0" {{ old('status') == 0 ? 'checked' : '' }} style="margin-right: 5px;">
                                 禁用
                             </label>
                         </div>
                     </div>
 
                     {{-- 提交按钮 --}}
-                    <div class="form-group">
-                        <button type="submit" class="btn btn-primary btn-lg">
+                    <div class="form-group" style="margin-top: 30px;">
+                        <button type="submit" class="btn btn-primary" style="padding: 12px 24px; background: #007bff; color: white; border: none; border-radius: 4px; font-size: 18px; cursor: pointer; margin-right: 10px;">
                             <i class="fas fa-save"></i> 保存菜单项
                         </button>
-                        <a href="{{ route('admin.dynamicmenu.index') }}" class="btn btn-secondary btn-lg">
+                        <a href="{{ route('admin.dynamicmenu.index') }}" class="btn btn-secondary" style="padding: 12px 24px; background: #6c757d; color: white; text-decoration: none; border-radius: 4px; font-size: 18px;">
                             <i class="fas fa-times"></i> 取消
                         </a>
                     </div>
@@ -254,8 +156,8 @@
     </div>
 
     {{-- 引入必要的JavaScript --}}
+    @push('scripts')
     <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
-    
     <script>
         $(document).ready(function() {
             // 自动生成key
@@ -270,7 +172,10 @@
                     keyInput.val('admin.' + key);
                 }
             });
+            
+            // 为所有表单元素添加Bagisto样式类
+            $('.control').addClass('form-control');
         });
     </script>
-</body>
-</html>
+    @endpush
+</x-admin::layouts>

+ 181 - 0
packages/Longyi/DynamicMenu/src/Resources/views/admin/menu/edit.blade.php

@@ -0,0 +1,181 @@
+<x-admin::layouts>
+    {{-- 页面标题 --}}
+    <x-slot:title>编辑菜单项 - {{ $menuItem->name }}</x-slot:title>
+
+    {{-- 页面内容 --}}
+    <div class="content" style="padding: 20px;">
+        {{-- 页头部分 --}}
+        <div class="page-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #dee2e6;">
+            <div class="page-title">
+                <h1><i class="fas fa-edit"></i> 编辑菜单项: {{ $menuItem->name }}</h1>
+            </div>
+            <div class="page-action">
+                <a href="{{ route('admin.dynamicmenu.index') }}" class="btn btn-secondary" style="padding: 8px 16px; background: #6c757d; color: white; text-decoration: none; border-radius: 4px;">
+                    <i class="fas fa-arrow-left"></i> 返回列表
+                </a>
+            </div>
+        </div>
+
+        {{-- 显示错误信息 --}}
+        @if($errors->any())
+            <div class="alert alert-danger" style="background: #f8d7da; color: #721c24; padding: 12px; border-radius: 4px; margin-bottom: 20px; border: 1px solid #f5c6cb;">
+                <ul class="mb-0" style="margin: 0; padding-left: 20px;">
+                    @foreach($errors->all() as $error)
+                        <li>{{ $error }}</li>
+                    @endforeach
+                </ul>
+            </div>
+        @endif
+
+        {{-- 表单面板 --}}
+        <div class="panel" style="background: white; border: 1px solid #dee2e6; border-radius: 4px; margin-bottom: 20px;">
+            <div class="panel-header" style="padding: 12px 20px; background: #f8f9fa; border-bottom: 1px solid #dee2e6;">
+                <h3 style="margin: 0; font-size: 18px;">编辑基本信息</h3>
+            </div>
+            
+            <div class="panel-body" style="padding: 20px;">
+                <form method="POST" action="{{ route('admin.dynamicmenu.update', $menuItem->id) }}">
+                    @csrf
+                    @method('PUT')
+                    
+                    {{-- 名称 --}}
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label class="required" style="display: block; margin-bottom: 5px; font-weight: 500;">
+                            名称 <span style="color: red;">*</span>
+                        </label>
+                        <input type="text" 
+                               name="name" 
+                               class="control" 
+                               value="{{ old('name', $menuItem->name) }}" 
+                               required
+                               placeholder="例如:仪表盘"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                    </div>
+
+                    {{-- Key --}}
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label class="required" style="display: block; margin-bottom: 5px; font-weight: 500;">
+                            Key <span style="color: red;">*</span>
+                        </label>
+                        <input type="text" 
+                               name="key" 
+                               class="control" 
+                               value="{{ old('key', $menuItem->key) }}" 
+                               required
+                               placeholder="例如:admin.dashboard"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            用于权限验证和菜单激活状态判断
+                        </small>
+                    </div>
+
+                    {{-- URL/路由 --}}
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">URL/路由</label>
+                        <input type="text" 
+                               name="route" 
+                               class="control" 
+                               value="{{ old('route', $menuItem->route) }}"
+                               placeholder="例如:admin.dashboard"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            可以是相对路径、完整URL或路由名称
+                        </small>
+                    </div>
+
+                    {{-- 图标 --}}
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">图标</label>
+                        <input type="text" 
+                               name="icon" 
+                               class="control" 
+                               value="{{ old('icon', $menuItem->icon) }}"
+                               placeholder="例如:fas fa-dashboard、fas fa-users等"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            FontAwesome图标类名,如:fas fa-home
+                        </small>
+                    </div>
+
+                    {{-- 父级菜单 --}}
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">父级菜单</label>
+                        <select name="parent_id" class="control" style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                            <option value="">作为顶级菜单</option>
+                            @foreach($menuItems as $menuItemOption)
+                                @if($menuItemOption->id != $menuItem->id) {{-- 不能选择自己作为父级 --}}
+                                <option value="{{ $menuItemOption->id }}" {{ old('parent_id', $menuItem->parent_id) == $menuItemOption->id ? 'selected' : '' }}>
+                                    {{ $menuItemOption->name }}
+                                    @if($menuItemOption->children && $menuItemOption->children->count() > 0)
+                                        (有子菜单)
+                                    @endif
+                                </option>
+                                @endif
+                            @endforeach
+                        </select>
+                    </div>
+
+                    {{-- 排序 --}}
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">排序</label>
+                        <input type="number" 
+                               name="sort_order" 
+                               class="control" 
+                               value="{{ old('sort_order', $menuItem->sort_order) }}"
+                               min="0"
+                               style="width: 100%; padding: 8px 12px; border: 1px solid #dee2e6; border-radius: 4px; font-size: 14px;">
+                        <small class="control-info" style="display: block; margin-top: 5px; font-size: 12px; color: #6c757d;">
+                            数字越小越靠前
+                        </small>
+                    </div>
+
+                    {{-- 状态 --}}
+                    <div class="form-group" style="margin-bottom: 20px;">
+                        <label style="display: block; margin-bottom: 5px; font-weight: 500;">状态</label>
+                        <div>
+                            <label class="radio-inline" style="margin-right: 20px; display: inline-flex; align-items: center;">
+                                <input type="radio" name="status" value="1" {{ old('status', $menuItem->status) == 1 ? 'checked' : '' }} style="margin-right: 5px;">
+                                启用
+                            </label>
+                            <label class="radio-inline" style="margin-right: 20px; display: inline-flex; align-items: center;">
+                                <input type="radio" name="status" value="0" {{ old('status', $menuItem->status) == 0 ? 'checked' : '' }} style="margin-right: 5px;">
+                                禁用
+                            </label>
+                        </div>
+                    </div>
+
+                    {{-- 提交按钮 --}}
+                    <div class="form-group" style="margin-top: 30px;">
+                        <button type="submit" class="btn btn-primary" style="padding: 12px 24px; background: #007bff; color: white; border: none; border-radius: 4px; font-size: 18px; cursor: pointer; margin-right: 10px;">
+                            <i class="fas fa-save"></i> 更新菜单项
+                        </button>
+                        <a href="{{ route('admin.dynamicmenu.index') }}" class="btn btn-secondary" style="padding: 12px 24px; background: #6c757d; color: white; text-decoration: none; border-radius: 4px; font-size: 18px;">
+                            <i class="fas fa-times"></i> 取消
+                        </a>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+
+    {{-- 引入必要的JavaScript --}}
+    @push('scripts')
+    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
+    <script>
+        $(document).ready(function() {
+            // 自动生成key(如果key为空)
+            $('input[name="name"]').on('blur', function() {
+                var name = $(this).val();
+                var keyInput = $('input[name="key"]');
+                
+                if (keyInput.val() === '') {
+                    var key = name.toLowerCase()
+                                 .replace(/\s+/g, '.')
+                                 .replace(/[^a-z0-9.]/g, '');
+                    keyInput.val('admin.' + key);
+                }
+            });
+        });
+    </script>
+    @endpush
+</x-admin::layouts>

+ 61 - 131
packages/Longyi/DynamicMenu/src/Resources/views/admin/menu/index.blade.php

@@ -1,127 +1,37 @@
-{{-- 不继承任何布局,直接输出 --}}
-<!DOCTYPE html>
-<html>
-<head>
-    <title>动态菜单管理</title>
-    <link rel="stylesheet" href="{{ asset('vendor/webkul/admin/assets/css/admin.css') }}">
-    <style>
-        .accordion {
-            margin: 10px 0;
-        }
-        .accordion-item {
-            margin: 5px 0;
-            border: 1px solid #dee2e6;
-            border-radius: 4px;
-            overflow: hidden;
-        }
-        .accordion-header {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            padding: 12px 15px;
-            background: #f8f9fa;
-            cursor: pointer;
-            transition: background 0.3s;
-        }
-        .accordion-header:hover {
-            background: #e9ecef;
-        }
-        .accordion-title {
-            display: flex;
-            align-items: center;
-            gap: 8px;
-        }
-        .accordion-title i {
-            font-size: 16px;
-            color: #6c757d;
-        }
-        .accordion-title .text-muted {
-            color: #6c757d;
-            font-size: 0.9em;
-        }
-        .accordion-actions {
-            display: flex;
-            gap: 8px;
-        }
-        .btn-edit, .btn-delete {
-            padding: 4px 8px;
-            border: none;
-            background: none;
-            cursor: pointer;
-            border-radius: 4px;
-            transition: background 0.3s;
-        }
-        .btn-edit {
-            color: #0d6efd;
-        }
-        .btn-edit:hover {
-            background: #e7f1ff;
-        }
-        .btn-delete {
-            color: #dc3545;
-        }
-        .btn-delete:hover:not(.disabled) {
-            background: #f8d7da;
-        }
-        .btn-delete.disabled {
-            color: #6c757d;
-            cursor: not-allowed;
-            opacity: 0.5;
-        }
-        .accordion-content {
-            display: none;
-            padding: 15px 15px 15px 30px;
-            background: white;
-            border-top: 1px solid #dee2e6;
-        }
-        .accordion-content.expanded {
-            display: block;
-        }
-        .accordion-header::after {
-            content: '▶';
-            font-size: 12px;
-            transition: transform 0.3s;
-            margin-left: 10px;
-        }
-        .accordion-header.expanded::after {
-            transform: rotate(90deg);
-        }
-        .page-header {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            margin-bottom: 20px;
-            padding-bottom: 10px;
-            border-bottom: 1px solid #dee2e6;
-        }
-        .btn-primary {
-            display: inline-block;
-            padding: 8px 16px;
-            background: #0d6efd;
-            color: white;
-            text-decoration: none;
-            border-radius: 4px;
-            transition: background 0.3s;
-        }
-        .btn-primary:hover {
-            background: #0b5ed7;
-        }
-    </style>
-</head>
-<body>
-    <div class="content" style="padding: 20px;">
-        <div class="page-header">
-            <h1>动态菜单管理</h1>
-            <a href="{{ route('admin.dynamicmenu.create') }}" class="btn btn-primary">添加菜单项</a>
+<x-admin::layouts>
+    {{-- 页面标题 --}}
+    <x-slot:title>
+        @lang('dynamicmenu::app.admin.menu.title')
+    </x-slot>
+
+    <div class="content">
+        {{-- 页头部分 --}}
+        <div class="flex gap-4 justify-between items-center max-sm:flex-wrap">
+            <p class="py-[11px] text-xl text-gray-800 dark:text-white font-bold">
+                @lang('dynamicmenu::app.admin.menu.title')
+            </p>
+
+            <div class="flex gap-x-2.5 items-center">
+                <a href="{{ route('admin.dynamicmenu.create') }}" class="primary-button">
+                    @lang('dynamicmenu::app.admin.menu.add-btn')
+                </a>
+            </div>
         </div>
-        <div class="page-content">
+
+        {{-- 页面内容 --}}
+        <div class="mt-8">
             @if(session('success'))
-                <div class="alert alert-success">{{ session('success') }}</div>
+                <div class="alert alert-success">
+                    {{ session('success') }}
+                </div>
             @endif
+
             @if(session('error'))
-                <div class="alert alert-danger">{{ session('error') }}</div>
+                <div class="alert alert-danger">
+                    {{ session('error') }}
+                </div>
             @endif
-            
+
             <div class="accordion">
                 @foreach($menuItems as $item)
                     @include('dynamicmenu::admin.menu.partials.tree', ['item' => $item])
@@ -130,27 +40,47 @@
         </div>
     </div>
 
+    {{-- 自定义样式 --}}
+    @push('styles')
+    <style>
+        /* 将您原有的 <style> 标签内容移到这里 */
+        .accordion { margin: 10px 0; }
+        .accordion-item { margin: 5px 0; border: 1px solid #dee2e6; border-radius: 4px; overflow: hidden; }
+        .accordion-header { display: flex; justify-content: space-between; align-items: center; padding: 12px 15px; background: #f8f9fa; cursor: pointer; transition: background 0.3s; }
+        .accordion-header:hover { background: #e9ecef; }
+        .accordion-title { display: flex; align-items: center; gap: 8px; }
+        .accordion-title i { font-size: 16px; color: #6c757d; }
+        .accordion-title .text-muted { color: #6c757d; font-size: 0.9em; }
+        .accordion-actions { display: flex; gap: 8px; }
+        .btn-edit, .btn-delete { padding: 4px 8px; border: none; background: none; cursor: pointer; border-radius: 4px; transition: background 0.3s; }
+        .btn-edit { color: #0d6efd; }
+        .btn-edit:hover { background: #e7f1ff; }
+        .btn-delete { color: #dc3545; }
+        .btn-delete:hover:not(.disabled) { background: #f8d7da; }
+        .btn-delete.disabled { color: #6c757d; cursor: not-allowed; opacity: 0.5; }
+        .accordion-content { display: none; padding: 15px 15px 15px 30px; background: white; border-top: 1px solid #dee2e6; }
+        .accordion-content.expanded { display: block; }
+        .accordion-header::after { content: '▶'; font-size: 12px; transition: transform 0.3s; margin-left: 10px; }
+        .accordion-header.expanded::after { transform: rotate(90deg); }
+    </style>
+    @endpush
+
+    {{-- 自定义脚本 --}}
+    @push('scripts')
     <script>
-        // 定义切换函数
         function toggleAccordion(header) {
-            // 如果点击的是操作按钮区域,不执行切换
             if (event.target.closest('.accordion-actions')) {
                 return;
             }
-            
-            // 切换header的expanded类
+
             header.classList.toggle('expanded');
-            
-            // 获取对应的content
             var content = header.nextElementSibling;
-            
-            // 检查是否是content元素
+
             if (content && content.classList.contains('accordion-content')) {
-                // 切换content的expanded类
                 content.classList.toggle('expanded');
             }
         }
-        
+
         // 页面加载完成后,可以默认展开所有有子菜单的项(可选)
         document.addEventListener('DOMContentLoaded', function() {
             // 如果你想默认展开所有菜单,取消下面的注释
@@ -165,5 +95,5 @@
             */
         });
     </script>
-</body>
-</html>
+    @endpush
+</x-admin::layouts>

+ 7 - 5
packages/Longyi/DynamicMenu/src/Resources/views/admin/menu/partials/tree.blade.php

@@ -10,21 +10,23 @@
             @endif
         </div>
         <div class="accordion-actions" onclick="event.stopPropagation()">
+            {{-- 编辑按钮 --}}
             <a href="{{ route('admin.dynamicmenu.edit', $item->id) }}" class="btn-edit" title="编辑">
-                <i class="icon pencil">✏️</i>
+                <i class="fas fa-edit"></i> 编辑
             </a>
             
+            {{-- 删除按钮 --}}
             @if(!$item->children || $item->children->count() == 0)
-                <form action="{{ route('admin.dynamicmenu.delete', $item->id) }}" method="POST" style="display: inline;">
+                <form action="{{ route('admin.dynamicmenu.delete', $item->id) }}" method="POST" style="display: inline;" onsubmit="return confirm('确定删除这个菜单项吗?');">
                     @csrf
                     @method('DELETE')
-                    <button type="submit" class="btn-delete" onclick="return confirm('确定删除?')" title="删除">
-                        <i class="icon trash">🗑️</i>
+                    <button type="submit" class="btn-delete" title="删除">
+                        <i class="fas fa-trash"></i> 删除
                     </button>
                 </form>
             @else
                 <span class="btn-delete disabled" title="请先删除子菜单">
-                    <i class="icon trash">🗑️</i>
+                    <i class="fas fa-trash"></i> 删除
                 </span>
             @endif
         </div>