| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- <?php
- namespace App\Services;
- use Illuminate\Http\Client\PendingRequest;
- use Illuminate\Http\Client\RequestException;
- use Illuminate\Support\Collection;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\Http;
- class QuestionServiceApi
- {
- public function __construct(
- protected string $baseUrl = '',
- protected int $timeout = 10,
- protected int $cacheTtl = 300,
- ) {
- $this->baseUrl = rtrim($this->baseUrl ?: config('question_bank.api_base', 'http://localhost:5015'), '/');
- $this->timeout = (int) config('question_bank.timeout', 10);
- $this->cacheTtl = (int) config('question_bank.cache_ttl', 300);
- }
- /**
- * 获取所有题目(分页)
- */
- public function listQuestions(int $page = 1, int $perPage = 50, array $filters = []): array
- {
- $cacheKey = sprintf(
- 'questions-list-%d-%d-%s',
- $page,
- $perPage,
- md5(json_encode($filters))
- );
- return Cache::remember(
- $cacheKey,
- now()->addSeconds($this->cacheTtl),
- function () use ($page, $perPage, $filters): array {
- $query = array_filter([
- 'page' => $page,
- 'per_page' => $perPage,
- 'kp_code' => $filters['kp_code'] ?? null,
- 'difficulty' => $filters['difficulty'] ?? null,
- 'skill' => $filters['skill'] ?? null,
- 'search' => $filters['search'] ?? null,
- ], fn ($value) => filled($value));
- $response = $this->request('GET', '/questions', $query);
- return [
- 'data' => $response['data'] ?? [],
- 'meta' => $response['meta'] ?? [
- 'page' => $page,
- 'per_page' => $perPage,
- 'total' => is_array($response) ? count($response) : 0,
- 'total_pages' => 1,
- ],
- ];
- }
- );
- }
- /**
- * 获取题目统计信息
- */
- public function getStatistics(): array
- {
- $cacheKey = 'question-statistics';
- return Cache::remember(
- $cacheKey,
- now()->addSeconds($this->cacheTtl),
- function (): array {
- $response = $this->request('GET', '/questions/statistics');
- return $response ?? [
- 'total' => 0,
- 'by_difficulty' => [],
- 'by_kp' => [],
- 'by_source' => [],
- ];
- }
- );
- }
- /**
- * 根据 kp_code 获取题目
- */
- public function getQuestionsByKpCode(string $kpCode, int $limit = 100): array
- {
- return $this->request('GET', '/questions', [
- 'kp_code' => $kpCode,
- 'limit' => $limit,
- ]);
- }
- /**
- * 语义搜索题目
- */
- public function searchQuestions(string $query, int $limit = 20): array
- {
- $cacheKey = sprintf('question-search-%s-%d', md5($query), $limit);
- return Cache::remember(
- $cacheKey,
- now()->addSeconds($this->cacheTtl),
- function () use ($query, $limit): array {
- try {
- $response = $this->request('POST', '/questions/search', [
- 'query' => $query,
- 'limit' => $limit,
- ]);
- return $response ?? [];
- } catch (\Exception $e) {
- \Log::error('Question search failed: ' . $e->getMessage());
- return [];
- }
- }
- );
- }
- /**
- * 获取单个题目详情
- */
- public function getQuestionById(int $id): ?array
- {
- $cacheKey = "question-{$id}";
- return Cache::remember(
- $cacheKey,
- now()->addSeconds($this->cacheTtl),
- function () use ($id): ?array {
- try {
- $response = $this->request('GET', "/questions/{$id}");
- return $response ?: null;
- } catch (\Exception $e) {
- \Log::error("Failed to get question {$id}: " . $e->getMessage());
- return null;
- }
- }
- );
- }
- /**
- * 创建题目(通过 AI 生成)
- */
- public function generateQuestions(array $params): array
- {
- try {
- $response = $this->request('POST', '/questions/generate', $params);
- return $response ?? [
- 'success' => false,
- 'message' => '生成失败',
- ];
- } catch (\Exception $e) {
- \Log::error('Question generation failed: ' . $e->getMessage());
- return [
- 'success' => false,
- 'message' => '生成失败:' . $e->getMessage(),
- ];
- }
- }
- /**
- * 导入题目(JSON 批量导入)
- */
- public function importQuestions(array $questions): array
- {
- try {
- $response = $this->request('POST', '/questions/import', [
- 'questions' => $questions,
- ]);
- return $response ?? [
- 'success' => false,
- 'message' => '导入失败',
- ];
- } catch (\Exception $e) {
- \Log::error('Question import failed: ' . $e->getMessage());
- return [
- 'success' => false,
- 'message' => '导入失败:' . $e->getMessage(),
- ];
- }
- }
- /**
- * 删除题目
- */
- public function deleteQuestion(int $id): bool
- {
- try {
- $response = $this->request('DELETE', "/questions/{$id}");
- return $response['success'] ?? false;
- } catch (\Exception $e) {
- \Log::error("Failed to delete question {$id}: " . $e->getMessage());
- return false;
- }
- }
- /**
- * 获取知识点选项(从知识图谱服务)
- */
- public function getKnowledgePointOptions(): array
- {
- try {
- $knowledgeService = app(KnowledgeServiceApi::class);
- $points = $knowledgeService->listKnowledgePoints(limit: 1000);
- return $points->pluck('cn_name', 'kp_code')
- ->sort()
- ->all();
- } catch (\Exception $e) {
- \Log::error('Failed to get knowledge points: ' . $e->getMessage());
- return [];
- }
- }
- /**
- * 获取提示词模板列表
- */
- public function listPrompts(?string $type = null, ?string $active = null): array
- {
- $cacheKey = sprintf(
- 'prompts-list-%s-%s',
- $type ?: 'all',
- $active ?: 'all'
- );
- return Cache::remember(
- $cacheKey,
- now()->addSeconds($this->cacheTtl),
- function () use ($type, $active): array {
- $query = array_filter([
- 'type' => $type,
- 'active' => $active,
- ], fn ($value) => filled($value));
- try {
- $response = $this->request('GET', '/prompts', $query);
- return $response ?? [];
- } catch (\Exception $e) {
- \Log::error('Failed to get prompts: ' . $e->getMessage());
- return [];
- }
- }
- );
- }
- /**
- * @throws RequestException
- * @return mixed
- */
- protected function request(string $method, string $path, array $params = []): mixed
- {
- $response = $this->http()->send($method, ltrim($path, '/'), [
- 'query' => $method === 'GET' ? $params : null,
- 'json' => $method !== 'GET' ? $params : null,
- ]);
- return $response->throw()->json();
- }
- protected function http(): PendingRequest
- {
- return Http::baseUrl($this->baseUrl)
- ->acceptJson()
- ->timeout($this->timeout)
- ->retry(2, 200)
- ->withHeaders([
- 'User-Agent' => 'Laravel/' . (app()->version()),
- 'Accept' => 'application/json',
- ]);
- }
- }
|