统一单入口 Go 工程与前端依赖目录,增加后台供应商配置、候选审核、计划预算、成交冲正、持仓复盘和站内通知。接入策略版本、Python 回测、可配置 A 股公开行情及 zap 文件轮转日志,补充迁移、契约与验证。
This commit is contained in:
@@ -3,7 +3,7 @@ type Envelope<T> = {data:T;meta:{request_id:string;server_time?:string}}
|
||||
export class ApiError extends Error {
|
||||
constructor(public status:number,public code:string,message:string) {super(message);this.name="ApiError"}
|
||||
}
|
||||
async function request<T>(path:string,init?:RequestInit):Promise<T> {
|
||||
export async function request<T>(path:string,init?:RequestInit):Promise<T> {
|
||||
const response=await fetch(path,{...init,credentials:"same-origin",headers:{Accept:"application/json",...(init?.body ? {"Content-Type":"application/json"} : {}),...init?.headers}})
|
||||
const data=await response.json()
|
||||
if (!response.ok) throw new ApiError(response.status,data.error?.code ?? "REQUEST_FAILED",data.error?.message ?? "请求失败,请稍后重试。")
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import {request} from "./auth"
|
||||
export type CandidateContent={symbol:string;exchange:string;name:string;strategy_code:string;title:string;thesis:string;evidence:{source_url:string;locator:string;summary:string}[];counter_evidence:string;invalidation:string;reference_plan:{entry_low:string;entry_high:string;stop_loss:string;target_price:string}}
|
||||
export type Candidate={id:string;candidate_id:string;revision:number;version:number;status:string;data_mode:"simulation";content:CandidateContent;observed_at:string;valid_until:string;published_at:string|null;is_latest:boolean;is_active_publication:boolean;reviews?:{id:string;decision:string;reason:string;input_version:number;created_at:string}[]}
|
||||
export type Draft={content:CandidateContent;observed_at:string;valid_until:string}
|
||||
export const states:Record<string,string>={DRAFT:"草稿",PENDING_REVIEW:"待审核",PUBLISHED:"已发布",RETURNED:"已退回",WITHDRAWN:"已撤回"}
|
||||
export function getCandidates(signal?:AbortSignal,status=""){return request<Candidate[]>(`/api/admin/v1/candidates${status?`?status=${encodeURIComponent(status)}`:""}`,{signal})}
|
||||
export function getCandidate(id:string,signal?:AbortSignal){return request<Candidate>(`/api/admin/v1/candidates/${id}`,{signal})}
|
||||
export function saveDraft(input:Draft,source?:Candidate){return request<Candidate>(source?`/api/admin/v1/candidates/${source.id}/revisions`:"/api/admin/v1/candidates",{method:"POST",body:JSON.stringify({...input,...(source?{expected_version:source.version}:{})})})}
|
||||
export function actOnCandidate(candidate:Candidate,action:string,reason:string){return request<Candidate>(`/api/admin/v1/candidates/${candidate.id}/${action}`,{method:"POST",body:JSON.stringify({expected_version:candidate.version,reason})})}
|
||||
@@ -0,0 +1,8 @@
|
||||
import {request} from "./auth"
|
||||
export type ProviderKey = "model_primary" | "model_backup" | "model_review" | "market_primary"
|
||||
export type ProviderConfig = {id:string;config_key:ProviderKey;quote_base_url?:string;market_adapter?:string;history_base_url?:string;name:string;base_url:string;model_name:string;wire_api:"responses"|"chat_completions";model_catalog_url:string;disable_response_storage:boolean;requires_openai_auth:boolean;enabled:boolean;timeout_seconds:number;has_api_key:boolean;version:number;last_test_status:string;updated_at:string}
|
||||
export type ProviderInput = {quote_base_url?:string;market_adapter?:string;history_base_url?:string;name:string;base_url:string;model_name:string;wire_api:"responses"|"chat_completions";model_catalog_url:string;disable_response_storage:boolean;requires_openai_auth:boolean;enabled:boolean;timeout_seconds:number;api_key?:string;clear_api_key:boolean;expected_version:number}
|
||||
export const getProviders = (signal?:AbortSignal)=>request<ProviderConfig[]>("/api/admin/v1/providers",{signal})
|
||||
export const saveProvider = (key:ProviderKey,input:ProviderInput)=>request<ProviderConfig>(`/api/admin/v1/providers/${key}`,{method:"PUT",body:JSON.stringify(input)})
|
||||
export type AuditEvent = {id:string;actor_id:string;action:string;object_type:string;object_id:string;request_id:string;details:Record<string,unknown>;created_at:string}
|
||||
export const getAuditEvents = (signal?:AbortSignal)=>request<AuditEvent[]>("/api/admin/v1/audit-events",{signal})
|
||||
Reference in New Issue
Block a user