Initial MVP for QA asset backend
This commit is contained in:
40
hy_qa_asset_backend/frontend/lib/api.ts
Normal file
40
hy_qa_asset_backend/frontend/lib/api.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
export const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://127.0.0.1:8000/api";
|
||||
|
||||
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const response = await fetch(`${API_BASE}${path}`, {
|
||||
...init,
|
||||
cache: "no-store",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...(init?.headers ?? {})
|
||||
}
|
||||
});
|
||||
if (!response.ok) {
|
||||
let message = `${response.status} ${response.statusText}`;
|
||||
try {
|
||||
const body = await response.json();
|
||||
message = body.detail ?? message;
|
||||
} catch {
|
||||
// keep response status as message
|
||||
}
|
||||
throw new Error(message);
|
||||
}
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
|
||||
export const api = {
|
||||
get: <T>(path: string) => request<T>(path),
|
||||
post: <T>(path: string, body: unknown = {}) =>
|
||||
request<T>(path, { method: "POST", body: JSON.stringify(body) }),
|
||||
patch: <T>(path: string, body: unknown) =>
|
||||
request<T>(path, { method: "PATCH", body: JSON.stringify(body) })
|
||||
};
|
||||
|
||||
export function formatDateTime(value: string | null | undefined) {
|
||||
if (!value) return "-";
|
||||
return new Intl.DateTimeFormat("zh-CN", {
|
||||
dateStyle: "short",
|
||||
timeStyle: "short"
|
||||
}).format(new Date(value));
|
||||
}
|
||||
|
||||
163
hy_qa_asset_backend/frontend/lib/types.ts
Normal file
163
hy_qa_asset_backend/frontend/lib/types.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
export type DashboardSummary = {
|
||||
total_sessions: number;
|
||||
processed_sessions: number;
|
||||
pending_review_count: number;
|
||||
high_risk_count: number;
|
||||
approved_qa_count: number;
|
||||
standard_qa_count: number;
|
||||
callable_qa_count: number;
|
||||
last_task_status: string | null;
|
||||
last_task_time: string | null;
|
||||
last_task_error: string | null;
|
||||
};
|
||||
|
||||
export type FeishuSession = {
|
||||
id: number;
|
||||
session_code: string;
|
||||
title: string;
|
||||
date: string | null;
|
||||
teachers: string | null;
|
||||
feishu_doc_url: string | null;
|
||||
feishu_record_id: string | null;
|
||||
source_file_name: string | null;
|
||||
source_text: string | null;
|
||||
process_status: string;
|
||||
qa_count: number;
|
||||
pending_review_count: number;
|
||||
approved_count: number;
|
||||
standard_qa_count: number;
|
||||
failed_reason: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type RawQAItem = {
|
||||
id: number;
|
||||
session_id: number;
|
||||
qa_code: string;
|
||||
raw_question: string;
|
||||
normalized_question: string | null;
|
||||
raw_answer: string;
|
||||
normalized_answer: string | null;
|
||||
suggested_standard_question: string | null;
|
||||
suggested_standard_answer: string | null;
|
||||
answer_person: string | null;
|
||||
primary_topic: string;
|
||||
problem_tags: string[];
|
||||
course_stage: string;
|
||||
audience_tags: string[];
|
||||
emotion_intensity: string | null;
|
||||
risk_level: string;
|
||||
risk_types: string[];
|
||||
risk_notes: string | null;
|
||||
need_desensitization: boolean;
|
||||
desensitization_status: string;
|
||||
review_status: string;
|
||||
reviewer_id: number | null;
|
||||
review_notes: string | null;
|
||||
suggested_to_standard_qa: boolean;
|
||||
source_timestamp: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type StandardQAItem = {
|
||||
id: number;
|
||||
standard_code: string;
|
||||
source_raw_qa_id: number;
|
||||
session_id: number;
|
||||
standard_question: string;
|
||||
standard_answer: string;
|
||||
similar_questions: string[];
|
||||
primary_topic: string;
|
||||
problem_tags: string[];
|
||||
course_stage: string;
|
||||
audience_tags: string[];
|
||||
answer_boundary: string | null;
|
||||
forbidden_expressions: string[];
|
||||
risk_level: string;
|
||||
audit_status: string;
|
||||
call_status: string;
|
||||
last_reviewer_id: number | null;
|
||||
disabled_reason: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type CallableQAItem = Pick<
|
||||
StandardQAItem,
|
||||
| "id"
|
||||
| "standard_code"
|
||||
| "standard_question"
|
||||
| "standard_answer"
|
||||
| "similar_questions"
|
||||
| "primary_topic"
|
||||
| "problem_tags"
|
||||
| "course_stage"
|
||||
| "audience_tags"
|
||||
| "answer_boundary"
|
||||
| "forbidden_expressions"
|
||||
| "source_raw_qa_id"
|
||||
| "session_id"
|
||||
>;
|
||||
|
||||
export type TaskRun = {
|
||||
id: number;
|
||||
task_type: string;
|
||||
task_status: string;
|
||||
started_at: string | null;
|
||||
ended_at: string | null;
|
||||
sessions_scanned: number;
|
||||
sessions_processed: number;
|
||||
qa_created: number;
|
||||
qa_failed: number;
|
||||
error_message: string | null;
|
||||
retry_count: number;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type AuditLog = {
|
||||
id: number;
|
||||
user_id: number | null;
|
||||
target_type: string;
|
||||
target_id: number;
|
||||
action: string;
|
||||
before_status: string | null;
|
||||
after_status: string | null;
|
||||
comment: string | null;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type SafeSettings = {
|
||||
feishu_configured: boolean;
|
||||
openai_configured: boolean;
|
||||
model_name: string;
|
||||
schedule_cron: string;
|
||||
schedule_timezone: string;
|
||||
mock_mode: boolean;
|
||||
database_url: string;
|
||||
feishu_tables_configured: Record<string, boolean>;
|
||||
system_settings: Array<{ key: string; value: string | null; description: string | null; updated_at: string }>;
|
||||
};
|
||||
|
||||
export type FeishuStatus = {
|
||||
configured: boolean;
|
||||
mock_mode: boolean;
|
||||
app_token_configured: boolean;
|
||||
wiki_node_token_configured: boolean;
|
||||
table_ids: Record<string, boolean>;
|
||||
token_ok: boolean;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type FeishuSetupGuide = {
|
||||
required_env: string[];
|
||||
required_permissions: string[];
|
||||
tables: Array<{
|
||||
table_key: string;
|
||||
table_name: string;
|
||||
env_name: string;
|
||||
required_fields: string[];
|
||||
}>;
|
||||
notes: string[];
|
||||
};
|
||||
Reference in New Issue
Block a user