id(); // 提交人信息(冗余 username,防止用户改名后记录混乱) $table->unsignedBigInteger('user_id')->comment('提交人 ID'); $table->string('username', 50)->comment('提交人用户名(提交时快照)'); // 反馈类型 $table->enum('type', ['bug', 'suggestion']) ->comment('类型: bug=缺陷报告 suggestion=功能建议'); // 反馈内容 $table->string('title', 200)->comment('反馈标题(一句话概括)'); $table->text('content')->comment('详细描述内容'); // 处理状态(7种) $table->enum('status', [ 'pending', // 待处理(默认) 'accepted', // 已接受(纳入计划) 'in_progress', // 开发中/修复中 'fixed', // Bug已修复 'done', // 建议已实现 'rejected', // 暂不同意 'shelved', // 已搁置 ])->default('pending')->comment('处理状态'); // 管理员回复(前台显示为特殊"开发者回复"区块) $table->text('admin_remark')->nullable()->comment('管理员官方回复(公开显示)'); // 冗余计数字段,配合排序(避免每次 COUNT JOIN) $table->unsignedInteger('votes_count')->default(0)->comment('赞同人数(冗余,方便排序)'); $table->unsignedInteger('replies_count')->default(0)->comment('补充评论数(冗余)'); $table->timestamps(); // 索引:按类型+状态筛选、按赞同数排序 $table->index(['type', 'status'], 'idx_type_status'); $table->index('user_id', 'idx_user_id'); $table->index('votes_count', 'idx_votes'); }); // ——— 表2:赞同记录 ——— Schema::create('feedback_votes', function (Blueprint $table): void { $table->id(); $table->unsignedBigInteger('feedback_id')->comment('对应反馈 ID'); $table->unsignedBigInteger('user_id')->comment('赞同用户 ID'); $table->timestamp('created_at')->nullable(); // 联合唯一索引:每个用户每条反馈只能赞同一次 $table->unique(['feedback_id', 'user_id'], 'uq_vote'); $table->index('feedback_id', 'idx_feedback_id'); }); // ——— 表3:补充评论 ——— Schema::create('feedback_replies', function (Blueprint $table): void { $table->id(); $table->unsignedBigInteger('feedback_id')->comment('对应反馈 ID'); // 回复人信息(冗余 username) $table->unsignedBigInteger('user_id')->comment('回复人 ID'); $table->string('username', 50)->comment('回复人用户名(快照)'); // 评论内容(纯文本,不支持 Markdown,防止滥用) $table->text('content')->comment('补充内容(纯文本)'); // 管理员官方回复标记(前台特殊高亮展示) $table->boolean('is_admin')->default(false)->comment('是否为 id=1 管理员的官方回复'); $table->timestamps(); $table->index('feedback_id', 'idx_feedback_id'); }); } /** * 回滚:删除用户反馈相关三张表 */ public function down(): void { Schema::dropIfExists('feedback_replies'); Schema::dropIfExists('feedback_votes'); Schema::dropIfExists('feedback_items'); } };