refactor(mobile): extract types, static data, utils, styles from App.vue

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
This commit is contained in:
2026-07-08 21:07:45 +08:00
parent 15cd789da6
commit e4070c8b8c
11 changed files with 5649 additions and 5528 deletions
+447
View File
@@ -0,0 +1,447 @@
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;
}