|
@@ -7,6 +7,7 @@ use Illuminate\Http\Client\RequestException;
|
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Collection;
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
|
|
class QuestionServiceApi
|
|
class QuestionServiceApi
|
|
|
{
|
|
{
|
|
@@ -25,47 +26,71 @@ class QuestionServiceApi
|
|
|
*/
|
|
*/
|
|
|
public function listQuestions(int $page = 1, int $perPage = 50, array $filters = []): array
|
|
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,
|
|
|
|
|
- 'type' => $filters['type'] ?? null,
|
|
|
|
|
- 'skill' => $filters['skill'] ?? null,
|
|
|
|
|
- 'search' => $filters['search'] ?? null,
|
|
|
|
|
- ], fn ($value) => filled($value));
|
|
|
|
|
-
|
|
|
|
|
- $response = $this->request('GET', '/questions', $query);
|
|
|
|
|
-
|
|
|
|
|
- // 处理数学公式
|
|
|
|
|
- $data = $response['data'] ?? [];
|
|
|
|
|
- foreach ($data as &$question) {
|
|
|
|
|
- // 使用数学公式处理器处理题目数据
|
|
|
|
|
- $question = MathFormulaProcessor::processQuestionData($question);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 移除缓存,直接请求最新数据
|
|
|
|
|
+ $query = array_filter([
|
|
|
|
|
+ 'page' => $page,
|
|
|
|
|
+ 'per_page' => $perPage,
|
|
|
|
|
+ 'kp_code' => $filters['kp_code'] ?? null,
|
|
|
|
|
+ 'difficulty' => $filters['difficulty'] ?? null,
|
|
|
|
|
+ 'type' => $filters['type'] ?? null,
|
|
|
|
|
+ 'skill' => $filters['skill'] ?? null,
|
|
|
|
|
+ 'search' => $filters['search'] ?? null,
|
|
|
|
|
+ ], fn ($value) => filled($value));
|
|
|
|
|
|
|
|
|
|
+ // 使用更短的超时时间避免阻塞
|
|
|
|
|
+ try {
|
|
|
|
|
+ $response = Http::timeout(5) // 5秒超时
|
|
|
|
|
+ ->get($this->baseUrl . '/questions', $query);
|
|
|
|
|
+
|
|
|
|
|
+ if (!$response->successful()) {
|
|
|
|
|
+ Log::warning('题目列表API调用失败', [
|
|
|
|
|
+ 'status' => $response->status(),
|
|
|
|
|
+ 'url' => $this->baseUrl . '/questions'
|
|
|
|
|
+ ]);
|
|
|
return [
|
|
return [
|
|
|
- 'data' => $data,
|
|
|
|
|
- 'meta' => $response['meta'] ?? [
|
|
|
|
|
|
|
+ 'data' => [],
|
|
|
|
|
+ 'meta' => [
|
|
|
'page' => $page,
|
|
'page' => $page,
|
|
|
'per_page' => $perPage,
|
|
'per_page' => $perPage,
|
|
|
- 'total' => is_array($response) ? count($response) : 0,
|
|
|
|
|
- 'total_pages' => 1,
|
|
|
|
|
- ],
|
|
|
|
|
|
|
+ 'total' => 0,
|
|
|
|
|
+ 'total_pages' => 0,
|
|
|
|
|
+ ]
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
- );
|
|
|
|
|
|
|
+
|
|
|
|
|
+ $response = $response->json();
|
|
|
|
|
+ } catch (\Illuminate\Http\Client\ConnectionException $e) {
|
|
|
|
|
+ Log::error('题目列表API连接超时', [
|
|
|
|
|
+ 'error' => $e->getMessage()
|
|
|
|
|
+ ]);
|
|
|
|
|
+ // 返回空数据,避免页面卡死
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'data' => [],
|
|
|
|
|
+ 'meta' => [
|
|
|
|
|
+ 'page' => $page,
|
|
|
|
|
+ 'per_page' => $perPage,
|
|
|
|
|
+ 'total' => 0,
|
|
|
|
|
+ 'total_pages' => 0,
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理数学公式
|
|
|
|
|
+ $data = $response['data'] ?? [];
|
|
|
|
|
+ foreach ($data as &$question) {
|
|
|
|
|
+ // 使用数学公式处理器处理题目数据
|
|
|
|
|
+ $question = MathFormulaProcessor::processQuestionData($question);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'data' => $data,
|
|
|
|
|
+ 'meta' => $response['meta'] ?? [
|
|
|
|
|
+ 'page' => $page,
|
|
|
|
|
+ 'per_page' => $perPage,
|
|
|
|
|
+ 'total' => is_array($response) ? count($response) : 0,
|
|
|
|
|
+ 'total_pages' => 1,
|
|
|
|
|
+ ],
|
|
|
|
|
+ ];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -73,22 +98,42 @@ class QuestionServiceApi
|
|
|
*/
|
|
*/
|
|
|
public function getStatistics(): array
|
|
public function getStatistics(): array
|
|
|
{
|
|
{
|
|
|
- $cacheKey = 'question-statistics';
|
|
|
|
|
-
|
|
|
|
|
- return Cache::remember(
|
|
|
|
|
- $cacheKey,
|
|
|
|
|
- now()->addSeconds($this->cacheTtl),
|
|
|
|
|
- function (): array {
|
|
|
|
|
- $response = $this->request('GET', '/questions/statistics');
|
|
|
|
|
|
|
+ // 移除缓存,直接请求最新数据
|
|
|
|
|
+ try {
|
|
|
|
|
+ $response = Http::timeout(5) // 5秒超时
|
|
|
|
|
+ ->get($this->baseUrl . '/questions/statistics');
|
|
|
|
|
|
|
|
- return $response ?? [
|
|
|
|
|
|
|
+ if (!$response->successful()) {
|
|
|
|
|
+ Log::warning('统计API调用失败', [
|
|
|
|
|
+ 'status' => $response->status()
|
|
|
|
|
+ ]);
|
|
|
|
|
+ return [
|
|
|
'total' => 0,
|
|
'total' => 0,
|
|
|
'by_difficulty' => [],
|
|
'by_difficulty' => [],
|
|
|
'by_kp' => [],
|
|
'by_kp' => [],
|
|
|
'by_source' => [],
|
|
'by_source' => [],
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
- );
|
|
|
|
|
|
|
+
|
|
|
|
|
+ $response = $response->json();
|
|
|
|
|
+ } catch (\Illuminate\Http\Client\ConnectionException $e) {
|
|
|
|
|
+ Log::error('统计API连接超时', [
|
|
|
|
|
+ 'error' => $e->getMessage()
|
|
|
|
|
+ ]);
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'total' => 0,
|
|
|
|
|
+ 'by_difficulty' => [],
|
|
|
|
|
+ 'by_kp' => [],
|
|
|
|
|
+ 'by_source' => [],
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $response ?? [
|
|
|
|
|
+ 'total' => 0,
|
|
|
|
|
+ 'by_difficulty' => [],
|
|
|
|
|
+ 'by_kp' => [],
|
|
|
|
|
+ 'by_source' => [],
|
|
|
|
|
+ ];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -235,44 +280,52 @@ class QuestionServiceApi
|
|
|
*/
|
|
*/
|
|
|
public function getKnowledgePointOptions(): array
|
|
public function getKnowledgePointOptions(): array
|
|
|
{
|
|
{
|
|
|
- try {
|
|
|
|
|
- // 使用新的知识图谱API
|
|
|
|
|
- $knowledgeApiBase = config('services.knowledge_api.base_url', 'http://localhost:5011');
|
|
|
|
|
- $response = Http::timeout(10)
|
|
|
|
|
- ->get($knowledgeApiBase . '/graph/export');
|
|
|
|
|
-
|
|
|
|
|
- if ($response->successful()) {
|
|
|
|
|
- $data = $response->json();
|
|
|
|
|
- $nodes = $data['nodes'] ?? [];
|
|
|
|
|
-
|
|
|
|
|
- // 转换为键值对格式
|
|
|
|
|
- $options = [];
|
|
|
|
|
- foreach ($nodes as $node) {
|
|
|
|
|
- $code = $node['kp_code'] ?? null;
|
|
|
|
|
- $name = $node['cn_name'] ?? null;
|
|
|
|
|
-
|
|
|
|
|
- if ($code && $name) {
|
|
|
|
|
- $options[$code] = $name;
|
|
|
|
|
|
|
+ // 使用缓存来避免重复请求
|
|
|
|
|
+ $cacheKey = 'knowledge-point-options';
|
|
|
|
|
+ return Cache::remember(
|
|
|
|
|
+ $cacheKey,
|
|
|
|
|
+ now()->addHours(1), // 缓存1小时
|
|
|
|
|
+ function () {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 使用新的知识图谱API
|
|
|
|
|
+ $knowledgeApiBase = config('services.knowledge_api.base_url', 'http://localhost:5011');
|
|
|
|
|
+ $response = Http::timeout(30) // 增加超时时间到30秒
|
|
|
|
|
+ ->get($knowledgeApiBase . '/graph/export');
|
|
|
|
|
+
|
|
|
|
|
+ if ($response->successful()) {
|
|
|
|
|
+ $data = $response->json();
|
|
|
|
|
+ $nodes = $data['nodes'] ?? [];
|
|
|
|
|
+
|
|
|
|
|
+ // 转换为键值对格式
|
|
|
|
|
+ $options = [];
|
|
|
|
|
+ foreach ($nodes as $node) {
|
|
|
|
|
+ $code = $node['kp_code'] ?? null;
|
|
|
|
|
+ $name = $node['cn_name'] ?? null;
|
|
|
|
|
+
|
|
|
|
|
+ if ($code && $name) {
|
|
|
|
|
+ $options[$code] = $name;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 按代码排序
|
|
|
|
|
+ ksort($options);
|
|
|
|
|
+
|
|
|
|
|
+ \Log::info('成功获取知识点选项', ['count' => count($options)]);
|
|
|
|
|
+ return $options;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- // 按代码排序
|
|
|
|
|
- ksort($options);
|
|
|
|
|
|
|
+ \Log::warning('知识图谱API调用失败', [
|
|
|
|
|
+ 'status' => $response->status(),
|
|
|
|
|
+ 'url' => $knowledgeApiBase . '/graph/export'
|
|
|
|
|
+ ]);
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ \Log::error('Failed to get knowledge points: ' . $e->getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- \Log::info('成功获取知识点选项', ['count' => count($options)]);
|
|
|
|
|
- return $options;
|
|
|
|
|
|
|
+ // 返回空数组作为fallback
|
|
|
|
|
+ return [];
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- \Log::warning('知识图谱API调用失败', [
|
|
|
|
|
- 'status' => $response->status(),
|
|
|
|
|
- 'url' => $knowledgeApiBase . '/graph/export'
|
|
|
|
|
- ]);
|
|
|
|
|
- } catch (\Exception $e) {
|
|
|
|
|
- \Log::error('Failed to get knowledge points: ' . $e->getMessage());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 返回空数组作为fallback
|
|
|
|
|
- return [];
|
|
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|