This commit is contained in:
Eric 1549169735@qq.com
2026-09-13 20:08:13 +08:00
parent 7cc06976ab
commit da3f16e6db
65 changed files with 3855 additions and 2153 deletions

83
sdk/dist/index.d.ts vendored
View File

@@ -42,27 +42,54 @@ export type NodePresentation = {
content: string;
};
};
export type KnowledgeCollectionOption = {
value: string;
label: string;
parents?: string[];
suggested?: boolean;
};
export type KnowledgeCollectionStep = {
field_key: string;
export type DimensionValue = {
value_key: string;
name: string;
weight: number;
hot: boolean;
};
export type DimensionState = {
dim_key: string;
name: string;
values: DimensionValue[];
};
export type ScriptOption = {
option_key: string;
label: string;
};
export type ScriptProduct = {
sku_code: string;
product_name: string;
};
export type ScriptItem = {
script_key: string;
name: string;
script_type: string;
content: string;
dimension_value_key?: string;
weight?: number;
confirm_threshold?: number;
show_threshold?: number;
options?: ScriptOption[];
products?: ScriptProduct[];
feedback: boolean;
required: boolean;
multiple: boolean;
from_field?: string;
options: KnowledgeCollectionOption[];
};
export type KnowledgeCollection = {
context_fields: NodeField[];
context_title?: string;
context_hint?: string;
selection_title?: string;
selection_hint?: string;
steps: KnowledgeCollectionStep[];
export type StageForm = {
fields: NodeField[];
};
export type StageState = {
stage_key: string;
name: string;
purpose: string;
dimensions: DimensionState[];
scripts: ScriptItem[];
fallback?: string;
form?: StageForm;
screening_required: boolean;
can_next: boolean;
can_next_reason?: string;
};
export type NodeView = {
node_key: string;
@@ -71,8 +98,8 @@ export type NodeView = {
content: string;
fields?: NodeField[];
presentation?: NodePresentation;
stage?: StageState;
outputs?: unknown[];
collection?: KnowledgeCollection;
};
export type ScenarioState = {
run_id: number;
@@ -98,6 +125,21 @@ export type FinishOptions = {
result?: string;
finalResult?: Record<string, unknown> | null;
};
export type ScriptAnswer = {
script_key: string;
option_keys?: string[];
value?: string;
};
export type AnswerOptions = {
scriptKey?: string;
optionKeys?: string[];
value?: string;
scriptAnswers?: ScriptAnswer[];
dimensionSelects?: Record<string, boolean>;
answers?: ScenarioInput;
dimensionValueKey?: string;
selected?: boolean;
};
export declare class SalesScenario {
private readonly options;
private token;
@@ -106,9 +148,14 @@ export declare class SalesScenario {
constructor(options: CreateOptions);
start(): Promise<ScenarioState>;
getState(): ScenarioState;
getStage(): StageState;
getCurrentNode(): Promise<ScenarioState>;
/** Answer stage questions without advancing. Answer locally on the client and submit the whole stage once: pass every answered script in scriptAnswers together with dimensionSelects and the content form in answers. */
answer(options?: AnswerOptions): Promise<ScenarioState>;
submit(values: ScenarioInput): Promise<ScenarioState>;
next(): Promise<ScenarioState>;
back(): Promise<ScenarioState>;
feedback(scriptKey: string, feedbackType: 'like' | 'report' | 'unreasonable', note?: string): Promise<boolean>;
finish(options?: FinishOptions): Promise<ScenarioState>;
reset(): Promise<ScenarioState>;
destroy(): void;

View File

@@ -43,9 +43,19 @@ var IqudooSalesScenario = (() => {
if (!this.state) throw new Error("SDK has not started");
return this.state;
}
getStage() {
const stage = this.getState().node.stage;
if (!stage) throw new Error("current node is not a script stage");
return stage;
}
async getCurrentNode() {
return this.update(`/public/runs/${this.getState().run_id}/current`);
}
/** Answer stage questions without advancing. Answer locally on the client and submit the whole stage once: pass every answered script in scriptAnswers together with dimensionSelects and the content form in answers. */
async answer(options = {}) {
const state = await this.update(`/public/runs/${this.getState().run_id}/answer`, { method: "POST", body: JSON.stringify({ node_key: this.getState().node.node_key, script_key: options.scriptKey || "", option_keys: options.optionKeys || [], value: options.value || "", script_answers: options.scriptAnswers || [], dimension_selects: options.dimensionSelects || {}, answers: options.answers || {}, dimension_value_key: options.dimensionValueKey || "", selected: options.selected ?? false }) });
return state;
}
async submit(values) {
const state = await this.update(`/public/runs/${this.getState().run_id}/submit`, { method: "POST", body: JSON.stringify({ node_key: this.getState().node.node_key, answers: values }) });
this.emit("form_submit", { values, state });
@@ -54,6 +64,13 @@ var IqudooSalesScenario = (() => {
async next() {
return this.update(`/public/runs/${this.getState().run_id}/next`, { method: "POST" });
}
async back() {
return this.update(`/public/runs/${this.getState().run_id}/back`, { method: "POST" });
}
async feedback(scriptKey, feedbackType, note = "") {
await this.request(`/public/runs/${this.getState().run_id}/feedback`, { method: "POST", body: JSON.stringify({ node_key: this.getState().node.node_key, script_key: scriptKey, feedback_type: feedbackType, note }) });
return true;
}
async finish(options = {}) {
const state = await this.update(`/public/runs/${this.getState().run_id}/finish`, { method: "POST", body: JSON.stringify({ result: options.result || "", final_result: options.finalResult ?? null }) });
this.emit("finish", state);

6
sdk/dist/index.js vendored
View File

@@ -10,9 +10,15 @@ export class SalesScenario {
this.token = state.session_token; this.setState(state); this.emit('ready', state); return state; }
getState() { if (!this.state)
throw new Error('SDK has not started'); return this.state; }
getStage() { const stage = this.getState().node.stage; if (!stage)
throw new Error('current node is not a script stage'); return stage; }
async getCurrentNode() { return this.update(`/public/runs/${this.getState().run_id}/current`); }
/** Answer stage questions without advancing. Answer locally on the client and submit the whole stage once: pass every answered script in scriptAnswers together with dimensionSelects and the content form in answers. */
async answer(options = {}) { const state = await this.update(`/public/runs/${this.getState().run_id}/answer`, { method: 'POST', body: JSON.stringify({ node_key: this.getState().node.node_key, script_key: options.scriptKey || '', option_keys: options.optionKeys || [], value: options.value || '', script_answers: options.scriptAnswers || [], dimension_selects: options.dimensionSelects || {}, answers: options.answers || {}, dimension_value_key: options.dimensionValueKey || '', selected: options.selected ?? false }) }); return state; }
async submit(values) { const state = await this.update(`/public/runs/${this.getState().run_id}/submit`, { method: 'POST', body: JSON.stringify({ node_key: this.getState().node.node_key, answers: values }) }); this.emit('form_submit', { values, state }); return state; }
async next() { return this.update(`/public/runs/${this.getState().run_id}/next`, { method: 'POST' }); }
async back() { return this.update(`/public/runs/${this.getState().run_id}/back`, { method: 'POST' }); }
async feedback(scriptKey, feedbackType, note = '') { await this.request(`/public/runs/${this.getState().run_id}/feedback`, { method: 'POST', body: JSON.stringify({ node_key: this.getState().node.node_key, script_key: scriptKey, feedback_type: feedbackType, note }) }); return true; }
async finish(options = {}) { const state = await this.update(`/public/runs/${this.getState().run_id}/finish`, { method: 'POST', body: JSON.stringify({ result: options.result || '', final_result: options.finalResult ?? null }) }); this.emit('finish', state); return state; }
async reset() { return this.update(`/public/runs/${this.getState().run_id}/reset`, { method: 'POST' }); }
destroy() { this.handlers.clear(); this.token = ''; this.state = undefined; }

View File

@@ -5,14 +5,20 @@ export type ResultSchema = { fields:ResultField[] }
export type NodeField = { key:string; name:string; type:string; required:boolean; options:unknown[]; validation:Record<string,unknown> }
export type PresentationField = { key:string; label:string; kind:'text'|'image'; value:unknown }
export type NodePresentation = { summary:PresentationField[]; items:Array<{fields:PresentationField[]}>; opening?:{title:string; content:string} }
export type KnowledgeCollectionOption = { value:string; label:string; parents?:string[]; suggested?:boolean }
export type KnowledgeCollectionStep = { field_key:string; name:string; required:boolean; multiple:boolean; from_field?:string; options:KnowledgeCollectionOption[] }
export type KnowledgeCollection = { context_fields:NodeField[]; context_title?:string; context_hint?:string; selection_title?:string; selection_hint?:string; steps:KnowledgeCollectionStep[] }
export type NodeView = { node_key:string; type:string; title:string; content:string; fields?:NodeField[]; presentation?:NodePresentation; outputs?:unknown[]; collection?:KnowledgeCollection }
export type DimensionValue = { value_key:string; name:string; weight:number; hot:boolean }
export type DimensionState = { dim_key:string; name:string; values:DimensionValue[] }
export type ScriptOption = { option_key:string; label:string }
export type ScriptProduct = { sku_code:string; product_name:string }
export type ScriptItem = { script_key:string; name:string; script_type:string; content:string; dimension_value_key?:string; weight?:number; confirm_threshold?:number; show_threshold?:number; options?:ScriptOption[]; products?:ScriptProduct[]; feedback:boolean; required:boolean; multiple:boolean }
export type StageForm = { fields:NodeField[] }
export type StageState = { stage_key:string; name:string; purpose:string; dimensions:DimensionState[]; scripts:ScriptItem[]; fallback?:string; form?:StageForm; screening_required:boolean; can_next:boolean; can_next_reason?:string }
export type NodeView = { node_key:string; type:string; title:string; content:string; fields?:NodeField[]; presentation?:NodePresentation; stage?:StageState; outputs?:unknown[] }
export type ScenarioState = { run_id:number; external_ref:string; status:string; final_result?:Record<string, unknown>|null; result_schema:ResultSchema; session_token?:string; node:NodeView; outputs:OutputField[] }
export type SDKEvent = 'ready'|'node_change'|'form_submit'|'finish'|'error'
export type CreateOptions = { baseURL?:string; publicKey:string; scenarioKey:string; sopId?:number; input?:ScenarioInput; initialValues?:ScenarioInput; externalRef?:string }
export type FinishOptions = { result?:string; finalResult?:Record<string, unknown>|null }
export type ScriptAnswer = { script_key:string; option_keys?:string[]; value?:string }
export type AnswerOptions = { scriptKey?:string; optionKeys?:string[]; value?:string; scriptAnswers?:ScriptAnswer[]; dimensionSelects?:Record<string, boolean>; answers?:ScenarioInput; dimensionValueKey?:string; selected?:boolean }
export class SalesScenario {
private token=''
@@ -21,9 +27,14 @@ export class SalesScenario {
constructor(private readonly options:CreateOptions){}
async start(){const state=await this.request<ScenarioState>(`/public/scenarios/${encodeURIComponent(this.options.scenarioKey)}/runs`,{method:'POST',body:JSON.stringify({public_key:this.options.publicKey,sop_id:this.options.sopId,input:this.options.input||{},initial_values:this.options.initialValues||{},external_ref:this.options.externalRef||''})});if(state.session_token)this.token=state.session_token;this.setState(state);this.emit('ready',state);return state}
getState(){if(!this.state)throw new Error('SDK has not started');return this.state}
getStage(){const stage=this.getState().node.stage;if(!stage)throw new Error('current node is not a script stage');return stage}
async getCurrentNode(){return this.update(`/public/runs/${this.getState().run_id}/current`)}
/** Answer stage questions without advancing. Answer locally on the client and submit the whole stage once: pass every answered script in scriptAnswers together with dimensionSelects and the content form in answers. */
async answer(options:AnswerOptions={}){const state=await this.update(`/public/runs/${this.getState().run_id}/answer`,{method:'POST',body:JSON.stringify({node_key:this.getState().node.node_key,script_key:options.scriptKey||'',option_keys:options.optionKeys||[],value:options.value||'',script_answers:options.scriptAnswers||[],dimension_selects:options.dimensionSelects||{},answers:options.answers||{},dimension_value_key:options.dimensionValueKey||'',selected:options.selected??false})});return state}
async submit(values:ScenarioInput){const state=await this.update(`/public/runs/${this.getState().run_id}/submit`,{method:'POST',body:JSON.stringify({node_key:this.getState().node.node_key,answers:values})});this.emit('form_submit',{values,state});return state}
async next(){return this.update(`/public/runs/${this.getState().run_id}/next`,{method:'POST'})}
async back(){return this.update(`/public/runs/${this.getState().run_id}/back`,{method:'POST'})}
async feedback(scriptKey:string,feedbackType:'like'|'report'|'unreasonable',note=''){await this.request<{recorded:boolean}>(`/public/runs/${this.getState().run_id}/feedback`,{method:'POST',body:JSON.stringify({node_key:this.getState().node.node_key,script_key:scriptKey,feedback_type:feedbackType,note})});return true}
async finish(options:FinishOptions={}){const state=await this.update(`/public/runs/${this.getState().run_id}/finish`,{method:'POST',body:JSON.stringify({result:options.result||'',final_result:options.finalResult??null})});this.emit('finish',state);return state}
async reset(){return this.update(`/public/runs/${this.getState().run_id}/reset`,{method:'POST'})}
destroy(){this.handlers.clear();this.token='';this.state=undefined}