Pure moves only — zero behavior change, template untouched:
- types.ts (447), utils.ts (51), data/{auth,navigation,practice,mentor,
home,supervisor,icons}.ts, styles/app.css (4690, still global non-scoped
via <style src>)
- App.vue 9006 → 3559 lines; 98 moved declarations verbatim except
export/import syntax
- Built CSS hash identical to pre-refactor (byte-equal styles); reactive
state, computed, watchers, lifecycle and templates all stay in App.vue
- Component-level split deferred to phase two after 2026-07-10 Alpha
448 lines
8.2 KiB
TypeScript
448 lines
8.2 KiB
TypeScript
export type RoleKey = 'user' | 'candidate' | 'supervisor';
|
|
|
|
export type Tone = 'teal' | 'blue' | 'orange' | 'purple' | 'amber';
|
|
|
|
export type UserPanelKey = '' | 'tasks' | 'practice' | 'sop' | 'cases' | 'submit' | 'profile' | 'history' | 'recommend';
|
|
|
|
export type SupervisorPanelKey = '' | 'team' | 'reviews' | 'assign' | 'weakness' | 'case' | 'sop' | 'profile';
|
|
|
|
export type FlowTarget = UserPanelKey | SupervisorPanelKey;
|
|
|
|
export type MentorState = 'idle' | 'listening' | 'thinking' | 'speaking';
|
|
|
|
export type MentorMapActionKey = 'ask' | 'practice' | 'learn' | 'submit';
|
|
|
|
export type IconName =
|
|
| 'bars'
|
|
| 'book'
|
|
| 'book-search'
|
|
| 'briefcase'
|
|
| 'bulb'
|
|
| 'chevron-down'
|
|
| 'chevron-right'
|
|
| 'clipboard'
|
|
| 'document'
|
|
| 'folder'
|
|
| 'graduation'
|
|
| 'headset'
|
|
| 'home'
|
|
| 'map-pin'
|
|
| 'megaphone'
|
|
| 'mic'
|
|
| 'pen'
|
|
| 'presentation'
|
|
| 'target'
|
|
| 'upload'
|
|
| 'user'
|
|
| 'users'
|
|
| 'warning';
|
|
|
|
export interface ToolItem {
|
|
icon: IconName;
|
|
title: string;
|
|
desc: string;
|
|
tone: Tone;
|
|
}
|
|
|
|
export interface MetricItem {
|
|
icon: IconName;
|
|
title: string;
|
|
value: string;
|
|
desc: string;
|
|
tone: Tone;
|
|
progress: number;
|
|
}
|
|
|
|
export interface PrimaryTask {
|
|
badge: string;
|
|
title: string;
|
|
desc: string;
|
|
progressText: string;
|
|
progress: number;
|
|
cta: string;
|
|
icon: IconName;
|
|
}
|
|
|
|
export interface ReviewTask {
|
|
title: string;
|
|
desc: string;
|
|
}
|
|
|
|
export interface TabItem {
|
|
label: string;
|
|
icon: IconName;
|
|
active: boolean;
|
|
}
|
|
|
|
export interface FlowStep {
|
|
phase: string;
|
|
title: string;
|
|
desc: string;
|
|
target: FlowTarget;
|
|
}
|
|
|
|
export interface TeamStat {
|
|
icon: IconName;
|
|
title: string;
|
|
value: string;
|
|
tone: Tone;
|
|
}
|
|
|
|
export interface TeamOverview {
|
|
title: string;
|
|
progressText: string;
|
|
progress: number;
|
|
completionLabel: string;
|
|
detailCta: string;
|
|
stats: TeamStat[];
|
|
}
|
|
|
|
export interface TodoItem extends ToolItem {
|
|
count: number;
|
|
}
|
|
|
|
export interface SuggestionItem {
|
|
icon: IconName;
|
|
title: string;
|
|
desc: string;
|
|
tone: Tone;
|
|
}
|
|
|
|
export interface RoleHome {
|
|
role: RoleKey;
|
|
roleLabel: string;
|
|
avatarTone: string;
|
|
greeting: string;
|
|
location: string;
|
|
toolTitle?: string;
|
|
recommend?: string;
|
|
primary?: PrimaryTask;
|
|
review?: ReviewTask;
|
|
tools: ToolItem[];
|
|
metrics?: MetricItem[];
|
|
tabs: TabItem[];
|
|
team?: TeamOverview;
|
|
todos?: TodoItem[];
|
|
suggestion?: SuggestionItem;
|
|
}
|
|
|
|
export type PracticeStatus = 'idle' | 'starting' | 'active' | 'submitting' | 'finished';
|
|
|
|
export type InterviewStatus = PracticeStatus;
|
|
|
|
export type PracticeRole = 'customer' | 'trainee' | 'coach';
|
|
|
|
export type PracticeStyleKey = 'serious' | 'gentle' | 'detailed' | 'professional';
|
|
|
|
export interface PracticeTurn {
|
|
role: PracticeRole;
|
|
label: string;
|
|
text: string;
|
|
roundIndex?: number;
|
|
styleNote?: string;
|
|
}
|
|
|
|
export interface PracticeStartResponse {
|
|
sessionId: string;
|
|
customerText: string;
|
|
emotion?: number;
|
|
trust?: number;
|
|
}
|
|
|
|
export interface PracticePrepCardResponse {
|
|
keyPoints: string[];
|
|
redLines: string[];
|
|
scripts: string[];
|
|
promptVersion: string;
|
|
}
|
|
|
|
export interface PracticeTurnResponse {
|
|
customerText: string;
|
|
coachHint: string;
|
|
message?: string;
|
|
emotion?: number;
|
|
trust?: number;
|
|
redFlag?: boolean;
|
|
roundIndex: number;
|
|
finished: boolean;
|
|
}
|
|
|
|
export interface PracticeFinishResponse {
|
|
totalScore: number;
|
|
mentorRewrite: string;
|
|
aiComment: string;
|
|
}
|
|
|
|
export interface PracticeRecord {
|
|
id?: number;
|
|
sessionId?: string;
|
|
time: string;
|
|
trainee: string;
|
|
scene: string;
|
|
score: number;
|
|
status: string;
|
|
summary: string;
|
|
}
|
|
|
|
export interface PracticeScenario {
|
|
id: string;
|
|
title: string;
|
|
badge: string;
|
|
desc: string;
|
|
progressText: string;
|
|
progress: string;
|
|
}
|
|
|
|
export interface PracticeRecentItem {
|
|
scenarioId: string;
|
|
title: string;
|
|
time: string;
|
|
score: string;
|
|
record?: PracticeRecord;
|
|
}
|
|
|
|
export interface PracticeDialogue {
|
|
role: PracticeRole;
|
|
label: string;
|
|
text: string;
|
|
audioUrl?: string;
|
|
}
|
|
|
|
export interface PracticeAnnotation {
|
|
turnIndex: number;
|
|
sourceText: string;
|
|
issue: string;
|
|
rewrite: string;
|
|
sopPoint: string;
|
|
}
|
|
|
|
export interface PracticeReviewDetail extends PracticeRecord {
|
|
mentorRewrite: string;
|
|
aiComment: string;
|
|
reviewAdvice?: string;
|
|
incentivePoint?: number;
|
|
scoreItems: CompetencyDimension[];
|
|
dialogue: PracticeDialogue[];
|
|
annotations: PracticeAnnotation[];
|
|
}
|
|
|
|
export interface InterviewQuestion {
|
|
questionId: string;
|
|
seq: number;
|
|
questionText: string;
|
|
point: string;
|
|
scenario: string;
|
|
sampleAnswer: string;
|
|
}
|
|
|
|
export interface InterviewStartResponse {
|
|
sessionId: string;
|
|
candidateId: string;
|
|
candidateName: string;
|
|
positionCode: string;
|
|
questions: InterviewQuestion[];
|
|
source: string;
|
|
}
|
|
|
|
export interface InterviewRecord {
|
|
time: string;
|
|
candidate: string;
|
|
position: string;
|
|
score: number;
|
|
result: string;
|
|
summary: string;
|
|
}
|
|
|
|
export interface InterviewFinishResponse {
|
|
totalScore: number;
|
|
suggestion: string;
|
|
result: string;
|
|
aiSummary: string;
|
|
evidence: string;
|
|
dimensions: CompetencyDimension[];
|
|
records: InterviewRecord[];
|
|
source: string;
|
|
}
|
|
|
|
export interface CompetencyDimension {
|
|
label: string;
|
|
value: number | string;
|
|
note: string;
|
|
}
|
|
|
|
export interface CompetencyProfile {
|
|
score: number;
|
|
completed: number;
|
|
pendingReview: number;
|
|
trainingMinutes?: number;
|
|
contribution?: number;
|
|
assessmentScore?: number;
|
|
aiLevel?: string;
|
|
dimensions: CompetencyDimension[];
|
|
growthPath?: Array<{ level: string; progress: number; status: string; evidence: string }>;
|
|
}
|
|
|
|
export interface PracticeAlert {
|
|
type: string;
|
|
title: string;
|
|
desc: string;
|
|
severity: string;
|
|
extPartyId: string;
|
|
}
|
|
|
|
export interface PracticeAssignment {
|
|
id?: number;
|
|
extPartyId: string;
|
|
traineeName: string;
|
|
scenarioId: string;
|
|
scenarioName: string;
|
|
source: string;
|
|
reason: string;
|
|
status: string;
|
|
createTime: string;
|
|
question?: string;
|
|
referenceAnswer?: string;
|
|
userAnswer?: string;
|
|
feedback?: string;
|
|
correct?: boolean;
|
|
}
|
|
|
|
export interface DailyDrillAnswerResponse {
|
|
id: number;
|
|
status: string;
|
|
correct: boolean;
|
|
score: number;
|
|
feedback: string;
|
|
referenceAnswer: string;
|
|
}
|
|
|
|
export interface KnowledgeDoc {
|
|
title: string;
|
|
desc: string;
|
|
hit: string;
|
|
type: string;
|
|
}
|
|
|
|
export interface KnowledgeSnippet {
|
|
title: string;
|
|
text: string;
|
|
fragmentId?: number;
|
|
}
|
|
|
|
export interface KnowledgeRecord {
|
|
title: string;
|
|
category: string;
|
|
version: string;
|
|
status: string;
|
|
owner: string;
|
|
summary: string;
|
|
}
|
|
|
|
export interface KnowledgeSearchResponse {
|
|
queryText: string;
|
|
category: string;
|
|
answer: string;
|
|
reference: string;
|
|
docs: KnowledgeDoc[];
|
|
snippets: KnowledgeSnippet[];
|
|
training: string[];
|
|
records: KnowledgeRecord[];
|
|
keyPoints?: string[];
|
|
cautions?: string[];
|
|
}
|
|
|
|
export type AnswerFeedbackVerdict = 'up' | 'down';
|
|
|
|
export interface SummaryCardStep {
|
|
label: string;
|
|
desc: string;
|
|
}
|
|
|
|
export interface SummaryCardObjection {
|
|
concern: string;
|
|
response: string;
|
|
}
|
|
|
|
export interface SummaryCardResponse {
|
|
title: string;
|
|
steps: SummaryCardStep[];
|
|
objections: SummaryCardObjection[];
|
|
scripts: string[];
|
|
reminders: string[];
|
|
}
|
|
|
|
export interface CaseTag {
|
|
text: string;
|
|
type: string;
|
|
}
|
|
|
|
export interface CaseSummaryItem {
|
|
label: string;
|
|
text: string;
|
|
}
|
|
|
|
export interface CaseUploadResponse {
|
|
caseId: string;
|
|
fileName: string;
|
|
transcript: string;
|
|
tags: CaseTag[];
|
|
source: string;
|
|
}
|
|
|
|
export interface CaseOrganizeResponse {
|
|
caseId: string;
|
|
summary: CaseSummaryItem[];
|
|
tags: CaseTag[];
|
|
aiSummary: string;
|
|
source: string;
|
|
}
|
|
|
|
export interface CaseRecord {
|
|
title: string;
|
|
type: string;
|
|
status: string;
|
|
time: string;
|
|
owner: string;
|
|
summary: string;
|
|
}
|
|
|
|
export interface CaseCurateResponse {
|
|
selectedCaseIds: string[];
|
|
records: CaseRecord[];
|
|
sampleHint: string;
|
|
}
|
|
|
|
export interface MaterialResult {
|
|
upload: CaseUploadResponse;
|
|
organize: CaseOrganizeResponse;
|
|
curate: CaseCurateResponse;
|
|
}
|
|
|
|
export interface CandidateMaterialResponse {
|
|
id: number | string;
|
|
ossId: number | string;
|
|
fileName: string;
|
|
materialType: string;
|
|
fileSize: number;
|
|
status: string;
|
|
time: string;
|
|
}
|
|
|
|
export interface MobileRoute {
|
|
role: RoleKey;
|
|
page: string;
|
|
detail: string;
|
|
}
|
|
|
|
export interface ApiPayload<T> {
|
|
code?: number;
|
|
msg?: string;
|
|
data?: T;
|
|
}
|
|
|
|
export interface LoginResult {
|
|
access_token: string;
|
|
expire_in: number;
|
|
client_id: string;
|
|
}
|