# 广场作品审核功能说明 ## 📋 功能概述 为广场功能添加了完整的审核流程,所有用户发布的作品都需要经过管理员审核通过后才能在广场展示。 --- ## 🔄 审核流程 ``` 用户发布作品 ↓ 作品状态: pending (待审核) ↓ 管理员审核 ├─ 通过 → audit_status: approved → 广场展示 └─ 拒绝 → audit_status: rejected → 不展示,记录拒绝原因 ``` --- ## 📊 数据库变更 ### 1. 新增字段 (plaza_work表) | 字段名 | 类型 | 默认值 | 说明 | |-------|------|--------|------| | `audit_status` | VARCHAR(20) | `pending` | 审核状态:pending-待审核, approved-已通过, rejected-已拒绝 | | `audit_admin_id` | BIGINT | NULL | 审核管理员ID | | `audit_time` | DATETIME | NULL | 审核时间 | | `audit_remark` | TEXT | NULL | 审核备注(拒绝原因等) | ### 2. 新增表 (plaza_work_audit_log) 审核记录表,记录所有审核操作的历史: ```sql CREATE TABLE `plaza_work_audit_log` ( `id` BIGINT AUTO_INCREMENT PRIMARY KEY, `work_no` VARCHAR(64) NOT NULL COMMENT '作品编号', `work_id` BIGINT NOT NULL COMMENT '作品ID', `audit_status` VARCHAR(20) NOT NULL COMMENT '审核结果', `audit_admin_id` BIGINT NOT NULL COMMENT '审核管理员ID', `audit_admin_name` VARCHAR(100) NULL COMMENT '审核管理员名称', `audit_remark` TEXT NULL COMMENT '审核备注', `audit_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); ``` ### 3. 更新视图 - `v_plaza_hot_works` - 只显示审核通过的热门作品 - `v_plaza_latest_works` - 只显示审核通过的最新作品 - `v_plaza_pending_works` (新增) - 待审核作品列表(管理端使用) --- ## 🎯 核心功能 ### 用户端 #### 1. 发布作品 - **状态**: 发布后自动设置为 `audit_status = 'pending'` - **可见性**: 不在广场展示,用户可在"我的作品"中看到 - **提示**: 建议前端显示"作品审核中"状态 #### 2. 查询作品列表 - **规则**: 只返回 `audit_status = 'approved'` 的作品 - **影响**: 所有广场列表查询、统计都只包含已审核通过的作品 ### 管理端 #### 1. 查询待审核作品 ```http GET /admin/plaza/audit/pending?page=1&size=20&taskType=text_to_image ``` **响应**: ```json { "code": 200, "data": { "works": [{ "workNo": "WORK-xxx", "title": "作品标题", "description": "作品描述", "coverUrl": "https://...", "taskType": "text_to_image", "createTime": "2025-10-28T10:00:00", "author": { "userId": 123, "username": "用户123", "phone": "138****1234" } }], "total": 100, "page": 1, "size": 20, "totalPages": 5 } } ``` #### 2. 审核作品(单个) ```http POST /admin/plaza/audit/audit Authorization: Bearer ADMIN_TOKEN { "workNo": "WORK-xxx", "auditStatus": "approved", // 或 "rejected" "auditRemark": "拒绝原因(拒绝时必填)" } ``` **响应**: ```json { "code": 200, "data": { "workNo": "WORK-xxx", "auditStatus": "approved", "auditTime": "2025-10-28T10:30:00", "auditAdminId": 1, "auditRemark": null } } ``` #### 3. 批量审核 ```http POST /admin/plaza/audit/batch-audit?auditStatus=approved&auditRemark=批准 Authorization: Bearer ADMIN_TOKEN workNos: ["WORK-xxx1", "WORK-xxx2", "WORK-xxx3"] ``` #### 4. 审核统计 ```http GET /admin/plaza/audit/stats ``` **响应**: ```json { "code": 200, "data": { "pendingCount": 50, "todayApprovedCount": 120, "todayRejectedCount": 8, "totalAuditedCount": 5000 } } ``` #### 5. 审核历史 ```http GET /admin/plaza/audit/history?page=1&size=20&auditStatus=approved&startTime=2025-10-01&endTime=2025-10-31 ``` --- ## 🔒 权限控制 ### 管理端接口 - **要求**: `@PreAuthorize("hasRole('ADMIN')")` - **认证**: 需要管理员JWT Token - **记录**: 所有审核操作都记录管理员ID和名称 ### 用户端接口 - **发布作品**: 需要登录 - **查看广场**: 无需登录(只能看到审核通过的) - **查看自己作品**: 需要登录(可看到pending状态) --- ## 📝 文件清单 ### 数据库脚本 - ✅ `V11__add_plaza_audit_feature.sql` - 添加审核相关字段和表 ### 实体类 - ✅ `PlazaWork.java` - 添加审核相关字段 - ✅ `PlazaWorkAuditLog.java` (新增) - 审核记录实体 ### DTO - ✅ `AdminPlazaAuditDto.java` (新增) - 审核相关请求和响应DTO - AuditWorkRequest - 审核请求 - PendingWorksQueryRequest - 待审核列表查询 - PendingWorkDetailResponse - 待审核作品详情 - PendingWorksListResponse - 待审核列表响应 - AuditResultResponse - 审核结果 - AuditStatsResponse - 审核统计 - AuditHistoryQueryRequest - 审核历史查询 - AuditHistoryRecord - 审核历史记录 ### Mapper - ✅ `PlazaWorkMapper.java` - 添加待审核作品查询方法,更新所有查询添加audit_status判断 - ✅ `PlazaWorkAuditLogMapper.java` (新增) - 审核记录数据访问层 ### Service - ✅ `AdminPlazaAuditService.java` (新增) - 审核服务接口 - ✅ `AdminPlazaAuditServiceImpl.java` (新增) - 审核服务实现 - ✅ `PlazaServiceImpl.java` - 修改发布逻辑,设置audit_status为pending ### Controller - ✅ `AdminPlazaAuditController.java` (新增) - 管理端审核控制器 --- ## 🚀 部署步骤 ### 1. 执行数据库脚本 ```bash mysql -u root -p 1818ai < src/main/resources/db/migration/V11__add_plaza_audit_feature.sql ``` ### 2. 重启服务 ```bash ./mvnw spring-boot:run ``` ### 3. 测试审核功能 #### 用户发布作品 ```bash curl -X POST "http://localhost:8081/user/plaza/works/publish" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer USER_TOKEN" \ -d '{ "taskNo": "TASK-xxx", "title": "测试作品", "description": "测试描述", "isPublic": true }' ``` #### 管理员查看待审核 ```bash curl "http://localhost:8081/admin/plaza/audit/pending?page=1&size=20" \ -H "Authorization: Bearer ADMIN_TOKEN" ``` #### 管理员审核通过 ```bash curl -X POST "http://localhost:8081/admin/plaza/audit/audit" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ADMIN_TOKEN" \ -d '{ "workNo": "WORK-xxx", "auditStatus": "approved" }' ``` --- ## 📊 API 端点汇总 ### 管理端审核接口 | 方法 | 路径 | 功能 | 权限 | |------|------|------|------| | GET | /admin/plaza/audit/pending | 查询待审核作品列表 | ADMIN | | GET | /admin/plaza/audit/pending/{workNo} | 查询待审核作品详情 | ADMIN | | POST | /admin/plaza/audit/audit | 审核作品 | ADMIN | | POST | /admin/plaza/audit/batch-audit | 批量审核作品 | ADMIN | | GET | /admin/plaza/audit/stats | 审核统计数据 | ADMIN | | GET | /admin/plaza/audit/history | 审核历史记录 | ADMIN | --- ## ⚠️ 重要提示 ### 1. 已有数据处理 - 脚本会自动将现有的已发布作品标记为 `approved` - 确保执行脚本前备份数据库 ### 2. 前端调整建议 #### 用户端 - 发布成功后提示:"作品已提交,正在审核中" - "我的作品"中显示审核状态标签 - 待审核作品显示"审核中"标签 - 拒绝作品显示拒绝原因 #### 管理端 - 添加审核管理页面 - 显示待审核数量提醒 - 支持筛选、搜索待审核作品 - 支持批量操作 - 显示审核历史和统计 ### 3. 审核规则建议 - 内容违规:色情、暴力、政治敏感等 - 质量不达标:模糊、失败、无意义内容 - 版权问题:侵权内容 - 其他:广告、垃圾信息等 --- ## 🎨 前端集成示例 ### React 示例 - 显示审核状态 ```jsx const AuditStatusBadge = ({ status, remark }) => { const statusConfig = { pending: { text: '审核中', color: 'orange' }, approved: { text: '已通过', color: 'green' }, rejected: { text: '已拒绝', color: 'red' } }; const config = statusConfig[status] || statusConfig.pending; return (
{config.text} {status === 'rejected' && remark && (
拒绝原因:{remark}
)}
); }; ``` ### 管理端审核组件 ```jsx const WorkAuditPanel = ({ work, onAudit }) => { const [remark, setRemark] = useState(''); const handleAudit = async (status) => { try { await axios.post('/admin/plaza/audit/audit', { workNo: work.workNo, auditStatus: status, auditRemark: status === 'rejected' ? remark : null }); onAudit(); message.success(`审核${status === 'approved' ? '通过' : '拒绝'}成功`); } catch (error) { message.error('审核失败'); } }; return (

{work.title}

{work.title}

{work.description}