true, 'data' => TicketStatusService::all()]); } public function create_status(\WP_REST_Request $request) { $name = trim((string) $request->get_param('name')); if ($name === '' || mb_strlen($name) > 60) { return new \WP_Error('aksrt_ticket_status_name', __('请填写有效的状态名称', 'aksrt'), ['status' => 400]); } global $wpdb; $table = \AKSRT\Core\DBMigrator::table('ticket_status'); if ($table === '') { return new \WP_Error('aksrt_ticket_db', __('状态表不可用', 'aksrt'), ['status' => 500]); } $max = (int) $wpdb->get_var("SELECT MAX(sort_order) FROM {$table}"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery $inserted = $wpdb->insert($table, [ 'status_key' => TicketStatusService::make_key($name), 'name' => $name, 'color' => TicketStatusService::sanitize_color((string) $request->get_param('color')), 'is_closed' => absint($request->get_param('is_closed')) === 1 ? 1 : 0, 'sort_order' => $max + 1, 'created_at' => current_time('mysql'), ], ['%s', '%s', '%s', '%d', '%d', '%s']); if ($inserted !== 1) { return new \WP_Error('aksrt_ticket_db', __('状态创建失败', 'aksrt'), ['status' => 500]); } TicketStatusService::flush(); return rest_ensure_response(['success' => true]); } public function update_status(\WP_REST_Request $request) { $id = absint($request->get_param('id')); $row = $this->status_row($id); if ($row === null) { return new \WP_Error('aksrt_ticket_status_missing', __('工单状态不存在', 'aksrt'), ['status' => 404]); } if (!empty($row['is_default'])) { return new \WP_Error('aksrt_ticket_status_default', __('默认状态不可修改', 'aksrt'), ['status' => 409]); } $name = trim((string) $request->get_param('name')); if ($name === '' || mb_strlen($name) > 60) { return new \WP_Error('aksrt_ticket_status_name', __('请填写有效的状态名称', 'aksrt'), ['status' => 400]); } global $wpdb; $table = \AKSRT\Core\DBMigrator::table('ticket_status'); $updated = $wpdb->update($table, [ 'name' => $name, 'color' => TicketStatusService::sanitize_color((string) $request->get_param('color')), 'is_closed' => absint($request->get_param('is_closed')) === 1 ? 1 : 0, 'updated_at' => current_time('mysql'), ], ['id' => $id], ['%s', '%s', '%d', '%s'], ['%d']); if ($updated === false) { return new \WP_Error('aksrt_ticket_db', __('状态保存失败', 'aksrt'), ['status' => 500]); } TicketStatusService::flush(); return rest_ensure_response(['success' => true]); } public function delete_status(\WP_REST_Request $request) { $id = absint($request->get_param('id')); $row = $this->status_row($id); if ($row === null) { return new \WP_Error('aksrt_ticket_status_missing', __('工单状态不存在', 'aksrt'), ['status' => 404]); } if (!empty($row['is_default'])) { return new \WP_Error('aksrt_ticket_status_default', __('默认状态不可删除', 'aksrt'), ['status' => 409]); } if (TicketRepository::get_instance()->count_by_status((string) $row['status_key']) > 0) { return new \WP_Error('aksrt_ticket_status_in_use', __('该状态下还有工单,无法删除', 'aksrt'), ['status' => 409]); } global $wpdb; $table = \AKSRT\Core\DBMigrator::table('ticket_status'); $wpdb->delete($table, ['id' => $id], ['%d']); TicketStatusService::flush(); return rest_ensure_response(['success' => true]); } /** @return array|null */ private function status_row(int $id): ?array { global $wpdb; $table = \AKSRT\Core\DBMigrator::table('ticket_status'); if ($table === '' || $id <= 0) { return null; } $row = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", // phpcs:ignore WordPress.DB.PreparedSQL $id ), ARRAY_A); return is_array($row) ? $row : null; } /* ------------------------------------------------------------------ * * 部门 * ------------------------------------------------------------------ */ public function list_types(\WP_REST_Request $request) { return rest_ensure_response(['success' => true, 'data' => TicketTypeService::all()]); } public function create_type(\WP_REST_Request $request) { $name = trim((string) $request->get_param('name')); if ($name === '' || mb_strlen($name) > 120) { return new \WP_Error('aksrt_ticket_type_name', __('请填写有效的部门名称', 'aksrt'), ['status' => 400]); } if (TicketTypeService::name_taken($name)) { return new \WP_Error('aksrt_ticket_type_duplicate', __('该部门已存在', 'aksrt'), ['status' => 409]); } global $wpdb; $table = \AKSRT\Core\DBMigrator::table('ticket_type'); if ($table === '') { return new \WP_Error('aksrt_ticket_db', __('部门表不可用', 'aksrt'), ['status' => 500]); } $max = (int) $wpdb->get_var("SELECT MAX(sort_order) FROM {$table}"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery $inserted = $wpdb->insert($table, [ 'name' => $name, 'description' => sanitize_text_field((string) $request->get_param('description')), 'admin_ids' => wp_json_encode(TicketTypeService::sanitize_admin_ids((array) $request->get_param('admin_ids'))), 'sort_order' => $max + 1, 'created_at' => current_time('mysql'), ], ['%s', '%s', '%s', '%d', '%s']); if ($inserted !== 1) { return new \WP_Error('aksrt_ticket_db', __('部门创建失败', 'aksrt'), ['status' => 500]); } TicketTypeService::flush(); return rest_ensure_response(['success' => true]); } public function update_type(\WP_REST_Request $request) { $id = absint($request->get_param('id')); if (!TicketTypeService::exists($id)) { return new \WP_Error('aksrt_ticket_type_missing', __('工单部门不存在', 'aksrt'), ['status' => 404]); } $name = trim((string) $request->get_param('name')); if ($name === '' || mb_strlen($name) > 120) { return new \WP_Error('aksrt_ticket_type_name', __('请填写有效的部门名称', 'aksrt'), ['status' => 400]); } if (TicketTypeService::name_taken($name, $id)) { return new \WP_Error('aksrt_ticket_type_duplicate', __('该部门已存在', 'aksrt'), ['status' => 409]); } global $wpdb; $table = \AKSRT\Core\DBMigrator::table('ticket_type'); $updated = $wpdb->update($table, [ 'name' => $name, 'description' => sanitize_text_field((string) $request->get_param('description')), 'admin_ids' => wp_json_encode(TicketTypeService::sanitize_admin_ids((array) $request->get_param('admin_ids'))), 'updated_at' => current_time('mysql'), ], ['id' => $id], ['%s', '%s', '%s', '%s'], ['%d']); if ($updated === false) { return new \WP_Error('aksrt_ticket_db', __('部门保存失败', 'aksrt'), ['status' => 500]); } TicketTypeService::flush(); return rest_ensure_response(['success' => true]); } public function delete_type(\WP_REST_Request $request) { $id = absint($request->get_param('id')); if (!TicketTypeService::exists($id)) { return new \WP_Error('aksrt_ticket_type_missing', __('工单部门不存在', 'aksrt'), ['status' => 404]); } if (TicketRepository::get_instance()->count_by_type($id) > 0) { return new \WP_Error('aksrt_ticket_type_in_use', __('该部门下还有工单,无法删除', 'aksrt'), ['status' => 409]); } global $wpdb; $table = \AKSRT\Core\DBMigrator::table('ticket_type'); $wpdb->delete($table, ['id' => $id], ['%d']); TicketTypeService::flush(); return rest_ensure_response(['success' => true]); } /* ------------------------------------------------------------------ * * 预设回复 * ------------------------------------------------------------------ */ public function list_prereplies(\WP_REST_Request $request) { return rest_ensure_response(['success' => true, 'data' => TicketPrereplyService::all()]); } public function create_prereply(\WP_REST_Request $request) { $content = trim((string) $request->get_param('content')); if ($content === '' || mb_strlen($content) > 2000) { return new \WP_Error('aksrt_ticket_prereply_content', __('请填写有效的预设回复', 'aksrt'), ['status' => 400]); } if (TicketPrereplyService::create($content) <= 0) { return new \WP_Error('aksrt_ticket_db', __('预设回复创建失败', 'aksrt'), ['status' => 500]); } return rest_ensure_response(['success' => true]); } public function update_prereply(\WP_REST_Request $request) { $id = absint($request->get_param('id')); if (TicketPrereplyService::find($id) === null) { return new \WP_Error('aksrt_ticket_prereply_missing', __('预设回复不存在', 'aksrt'), ['status' => 404]); } $content = trim((string) $request->get_param('content')); if ($content === '' || mb_strlen($content) > 2000) { return new \WP_Error('aksrt_ticket_prereply_content', __('请填写有效的预设回复', 'aksrt'), ['status' => 400]); } if (!TicketPrereplyService::update($id, $content)) { return new \WP_Error('aksrt_ticket_db', __('预设回复保存失败', 'aksrt'), ['status' => 500]); } return rest_ensure_response(['success' => true]); } public function delete_prereply(\WP_REST_Request $request) { $id = absint($request->get_param('id')); if (!TicketPrereplyService::delete($id)) { return new \WP_Error('aksrt_ticket_db', __('预设回复删除失败', 'aksrt'), ['status' => 500]); } return rest_ensure_response(['success' => true]); } public function reorder_prereplies(\WP_REST_Request $request) { if (!TicketPrereplyService::reorder((array) $request->get_param('ids'))) { return new \WP_Error('aksrt_ticket_prereply_order', __('预设回复排序失败', 'aksrt'), ['status' => 400]); } return rest_ensure_response(['success' => true]); } /* ------------------------------------------------------------------ * * 后台备注 * ------------------------------------------------------------------ */ public function list_notes(\WP_REST_Request $request) { $id = absint($request->get_param('id')); return rest_ensure_response(['success' => true, 'data' => TicketNoteService::for_ticket($id)]); } public function create_note(\WP_REST_Request $request) { $id = absint($request->get_param('id')); if (TicketRepository::get_instance()->find($id) === null) { return new \WP_Error('aksrt_ticket_missing', __('工单不存在', 'aksrt'), ['status' => 404]); } $content = trim((string) $request->get_param('content')); if ($content === '' || mb_strlen($content) > 2000) { return new \WP_Error('aksrt_ticket_note_content', __('请填写有效的备注内容', 'aksrt'), ['status' => 400]); } if (TicketNoteService::create($id, $content, get_current_user_id()) <= 0) { return new \WP_Error('aksrt_ticket_db', __('备注创建失败', 'aksrt'), ['status' => 500]); } return rest_ensure_response(['success' => true]); } public function update_note(\WP_REST_Request $request) { $id = absint($request->get_param('id')); if (TicketNoteService::find($id) === null) { return new \WP_Error('aksrt_ticket_note_missing', __('备注不存在', 'aksrt'), ['status' => 404]); } $content = trim((string) $request->get_param('content')); if ($content === '' || mb_strlen($content) > 2000) { return new \WP_Error('aksrt_ticket_note_content', __('请填写有效的备注内容', 'aksrt'), ['status' => 400]); } if (!TicketNoteService::update($id, $content)) { return new \WP_Error('aksrt_ticket_db', __('备注保存失败', 'aksrt'), ['status' => 500]); } return rest_ensure_response(['success' => true]); } public function delete_note(\WP_REST_Request $request) { $id = absint($request->get_param('id')); if (!TicketNoteService::delete($id)) { return new \WP_Error('aksrt_ticket_db', __('备注删除失败', 'aksrt'), ['status' => 500]); } return rest_ensure_response(['success' => true]); } }