feat: 第一阶段基础框架搭建
后端 (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设计/模块详设/小程序设计/部署方案
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('cache', function (Blueprint $table) {
|
||||
$table->string('key')->primary();
|
||||
$table->mediumText('value');
|
||||
$table->integer('expiration')->index();
|
||||
});
|
||||
|
||||
Schema::create('cache_locks', function (Blueprint $table) {
|
||||
$table->string('key')->primary();
|
||||
$table->string('owner');
|
||||
$table->integer('expiration')->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('cache');
|
||||
Schema::dropIfExists('cache_locks');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('queue');
|
||||
$table->longText('payload');
|
||||
$table->unsignedTinyInteger('attempts');
|
||||
$table->unsignedInteger('reserved_at')->nullable();
|
||||
$table->unsignedInteger('available_at');
|
||||
$table->unsignedInteger('created_at');
|
||||
|
||||
$table->index(['queue', 'reserved_at', 'available_at']);
|
||||
});
|
||||
|
||||
Schema::create('job_batches', function (Blueprint $table) {
|
||||
$table->string('id')->primary();
|
||||
$table->string('name');
|
||||
$table->integer('total_jobs');
|
||||
$table->integer('pending_jobs');
|
||||
$table->integer('failed_jobs');
|
||||
$table->longText('failed_job_ids');
|
||||
$table->mediumText('options')->nullable();
|
||||
$table->integer('cancelled_at')->nullable();
|
||||
$table->integer('created_at');
|
||||
$table->integer('finished_at')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('failed_jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->text('connection');
|
||||
$table->text('queue');
|
||||
$table->longText('payload');
|
||||
$table->longText('exception');
|
||||
$table->timestamp('failed_at')->useCurrent();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('jobs');
|
||||
Schema::dropIfExists('job_batches');
|
||||
Schema::dropIfExists('failed_jobs');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('regions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 50)->comment('区域名称');
|
||||
$table->integer('sort')->default(0);
|
||||
$table->tinyInteger('status')->default(1)->comment('1启用 0停用');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('regions');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('stores', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('region_id')->constrained()->comment('所属区域');
|
||||
$table->string('name', 100)->comment('门店名称');
|
||||
$table->string('code', 20)->unique()->nullable()->comment('门店编码');
|
||||
$table->string('address', 255)->nullable();
|
||||
$table->string('phone', 20)->nullable();
|
||||
$table->string('logo', 255)->nullable();
|
||||
$table->tinyInteger('status')->default(1)->comment('1启用 0停用');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('stores');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('departments', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('store_id')->constrained()->comment('所属门店');
|
||||
$table->unsignedBigInteger('parent_id')->default(0)->comment('上级部门');
|
||||
$table->string('name', 50)->comment('部门名称');
|
||||
$table->integer('sort')->default(0);
|
||||
$table->tinyInteger('status')->default(1)->comment('1启用 0停用');
|
||||
$table->timestamps();
|
||||
|
||||
$table->index('store_id');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('departments');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('positions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('store_id')->constrained()->comment('所属门店');
|
||||
$table->string('name', 50)->comment('职务名称');
|
||||
$table->integer('sort')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('positions');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('store_id')->constrained()->comment('所属门店');
|
||||
$table->unsignedBigInteger('department_id')->nullable();
|
||||
$table->unsignedBigInteger('position_id')->nullable();
|
||||
$table->string('username', 50)->unique()->comment('登录名');
|
||||
$table->string('password', 255);
|
||||
$table->string('name', 50)->comment('真实姓名');
|
||||
$table->string('phone', 20)->nullable();
|
||||
$table->string('email', 100)->nullable();
|
||||
$table->string('avatar', 255)->nullable();
|
||||
$table->tinyInteger('status')->default(1)->comment('0待审核 1正常 2禁用');
|
||||
$table->tinyInteger('is_super')->default(0)->comment('1超级管理员');
|
||||
$table->timestamp('last_login_at')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->index('store_id');
|
||||
$table->index('phone');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('users');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('roles', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->nullable()->comment('NULL=全局角色');
|
||||
$table->string('name', 50)->comment('角色名称');
|
||||
$table->string('code', 50)->unique()->comment('角色编码');
|
||||
$table->string('description', 255)->nullable();
|
||||
$table->tinyInteger('is_system')->default(0)->comment('1系统内置不可删');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('roles');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('permissions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('parent_id')->default(0)->comment('上级权限');
|
||||
$table->string('name', 50)->comment('权限名称');
|
||||
$table->string('code', 100)->unique()->comment('权限标识 如 crm.lead.create');
|
||||
$table->string('module', 50)->nullable()->comment('所属模块');
|
||||
$table->tinyInteger('type')->default(1)->comment('1菜单 2按钮 3接口');
|
||||
$table->string('description', 255)->nullable();
|
||||
$table->integer('sort')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('permissions');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('menus', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('parent_id')->default(0)->comment('上级菜单');
|
||||
$table->string('name', 50)->comment('菜单名称');
|
||||
$table->string('path', 255)->nullable()->comment('路由路径');
|
||||
$table->string('component', 255)->nullable()->comment('组件路径');
|
||||
$table->string('icon', 50)->nullable()->comment('图标');
|
||||
$table->string('permission_code', 100)->nullable()->comment('关联权限标识');
|
||||
$table->tinyInteger('type')->default(1)->comment('1目录 2菜单 3按钮');
|
||||
$table->tinyInteger('visible')->default(1)->comment('1显示 0隐藏');
|
||||
$table->integer('sort')->default(0);
|
||||
$table->tinyInteger('status')->default(1)->comment('1启用 0停用');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('menus');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('role_user', function (Blueprint $table) {
|
||||
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('role_id')->constrained()->onDelete('cascade');
|
||||
$table->primary(['user_id', 'role_id']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('role_user');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('role_permission', function (Blueprint $table) {
|
||||
$table->foreignId('role_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('permission_id')->constrained()->onDelete('cascade');
|
||||
$table->primary(['role_id', 'permission_id']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('role_permission');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('operation_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('store_id')->constrained();
|
||||
$table->unsignedBigInteger('user_id');
|
||||
$table->string('user_name', 50);
|
||||
$table->string('module', 50)->comment('操作模块');
|
||||
$table->string('action', 50)->comment('操作类型 create/update/delete');
|
||||
$table->string('target', 100)->nullable()->comment('操作对象');
|
||||
$table->unsignedBigInteger('target_id')->nullable();
|
||||
$table->string('ip', 45)->nullable();
|
||||
$table->string('method', 10)->nullable()->comment('HTTP方法');
|
||||
$table->string('url', 500)->nullable()->comment('请求URL');
|
||||
$table->json('before')->nullable()->comment('变更前数据');
|
||||
$table->json('after')->nullable()->comment('变更后数据');
|
||||
$table->timestamp('created_at')->nullable();
|
||||
|
||||
$table->index(['store_id', 'created_at']);
|
||||
$table->index('user_id');
|
||||
$table->index('module');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('operation_logs');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('dictionaries', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 50)->comment('字典名称');
|
||||
$table->string('code', 50)->unique()->comment('字典编码');
|
||||
$table->string('description', 255)->nullable();
|
||||
$table->tinyInteger('is_system')->default(0)->comment('系统内置不可删');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('dictionary_items', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('dictionary_id')->constrained()->onDelete('cascade');
|
||||
$table->string('label', 100)->comment('显示文本');
|
||||
$table->string('value', 100)->comment('值');
|
||||
$table->integer('sort')->default(0);
|
||||
$table->tinyInteger('status')->default(1)->comment('1启用 0停用');
|
||||
$table->timestamps();
|
||||
|
||||
$table->index('dictionary_id');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('dictionary_items');
|
||||
Schema::dropIfExists('dictionaries');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('system_configs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->nullable()->comment('NULL=全局配置');
|
||||
$table->string('group', 50)->default('general')->comment('配置分组');
|
||||
$table->string('key', 100)->comment('配置键');
|
||||
$table->text('value')->nullable()->comment('配置值');
|
||||
$table->string('description', 255)->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['store_id', 'key']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('system_configs');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->morphs('tokenable');
|
||||
$table->text('name');
|
||||
$table->string('token', 64)->unique();
|
||||
$table->text('abilities')->nullable();
|
||||
$table->timestamp('last_used_at')->nullable();
|
||||
$table->timestamp('expires_at')->nullable()->index();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('personal_access_tokens');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user