feat: 第五阶段办公协同/统计报表/知识库模块

- 新增3个migration(9张表): office(6表)/report(1表)/kb(2表)
- 新增9个Model + 9个Controller
- 新增43条API路由(总计305条)
- 新增3个前端API模块 + 10个管理页面
- 迁移运行通过, vite build验证通过
This commit is contained in:
li
2026-03-13 21:43:10 +08:00
parent fb5e0daf1a
commit 058ee507fa
34 changed files with 2595 additions and 0 deletions
@@ -0,0 +1,105 @@
<?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('approval_templates', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->string('name', 100);
$table->tinyInteger('type')->comment('1=请假 2=采购 3=合同 4=退款 5=换房');
$table->json('form_fields')->nullable();
$table->json('flow_nodes')->nullable();
$table->tinyInteger('status')->default(1);
$table->integer('sort')->default(0);
$table->timestamps();
});
// 审批记录
Schema::create('approvals', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->unsignedBigInteger('template_id')->nullable();
$table->string('title');
$table->unsignedBigInteger('applicant_id')->index();
$table->json('form_data')->nullable();
$table->tinyInteger('status')->default(0)->comment('0=待审批 1=审批中 2=已通过 3=已驳回 4=已撤回');
$table->integer('current_node')->default(0);
$table->string('related_type', 50)->nullable();
$table->unsignedBigInteger('related_id')->nullable();
$table->timestamps();
});
// 审批节点
Schema::create('approval_nodes', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('approval_id')->index();
$table->integer('node_order')->default(0);
$table->unsignedBigInteger('approver_id');
$table->tinyInteger('action')->default(0)->comment('0=待处理 1=通过 2=驳回');
$table->string('comment')->nullable();
$table->timestamp('acted_at')->nullable();
$table->timestamp('created_at')->nullable();
});
// 公告
Schema::create('announcements', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->string('title');
$table->text('content');
$table->tinyInteger('type')->default(1)->comment('1=通知 2=公告 3=制度');
$table->boolean('is_top')->default(false);
$table->tinyInteger('publish_status')->default(0)->comment('0=草稿 1=已发布');
$table->timestamp('published_at')->nullable();
$table->unsignedBigInteger('author_id')->nullable();
$table->timestamps();
});
// 交接班
Schema::create('handovers', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->date('shift_date');
$table->tinyInteger('shift_type')->comment('1=早班 2=中班 3=晚班 4=夜班');
$table->unsignedBigInteger('handover_user_id');
$table->unsignedBigInteger('receiver_user_id')->nullable();
$table->text('content');
$table->text('issues')->nullable();
$table->tinyInteger('status')->default(0)->comment('0=待确认 1=已确认');
$table->timestamp('confirmed_at')->nullable();
$table->timestamp('created_at')->nullable();
});
// 消息通知
Schema::create('notifications', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->unsignedBigInteger('user_id')->index();
$table->string('title');
$table->string('content')->nullable();
$table->tinyInteger('type')->default(1)->comment('1=系统 2=审批 3=待办 4=提醒');
$table->string('related_type', 50)->nullable();
$table->unsignedBigInteger('related_id')->nullable();
$table->boolean('is_read')->default(false);
$table->timestamp('read_at')->nullable();
$table->timestamp('created_at')->nullable();
});
}
public function down(): void
{
Schema::dropIfExists('notifications');
Schema::dropIfExists('handovers');
Schema::dropIfExists('announcements');
Schema::dropIfExists('approval_nodes');
Schema::dropIfExists('approvals');
Schema::dropIfExists('approval_templates');
}
};
@@ -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('report_exports', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->string('name');
$table->string('type', 50)->comment('report type key');
$table->json('params')->nullable();
$table->string('file_path')->nullable();
$table->tinyInteger('status')->default(0)->comment('0=生成中 1=已完成 2=失败');
$table->unsignedBigInteger('operator_id')->nullable();
$table->timestamp('created_at')->nullable();
});
}
public function down(): void
{
Schema::dropIfExists('report_exports');
}
};
@@ -0,0 +1,46 @@
<?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('kb_categories', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->unsignedBigInteger('parent_id')->default(0)->index();
$table->string('name', 100);
$table->integer('sort')->default(0);
$table->tinyInteger('status')->default(1);
$table->timestamps();
});
Schema::create('kb_articles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->index();
$table->unsignedBigInteger('category_id')->nullable()->index();
$table->string('title');
$table->longText('content')->nullable();
$table->unsignedBigInteger('author_id')->nullable();
$table->tinyInteger('status')->default(0)->comment('0=草稿 1=待审核 2=已发布 3=已下架');
$table->tinyInteger('visibility')->default(1)->comment('1=内部 2=公开');
$table->string('cover_image')->nullable();
$table->json('attachments')->nullable();
$table->unsignedInteger('views')->default(0);
$table->unsignedInteger('likes')->default(0);
$table->unsignedInteger('favorites')->default(0);
$table->timestamp('published_at')->nullable();
$table->timestamps();
$table->fullText(['title', 'content']);
});
}
public function down(): void
{
Schema::dropIfExists('kb_articles');
Schema::dropIfExists('kb_categories');
}
};