a5c4bcb821
- backend: career-advice module with analyze/chat/positions endpoints - frontend: career.vue page with profile form, AI advice, recommendation cards - config/api/pages/user.vue: full integration into existing flow - docs: PROJECT-STATUS v4.5, FEATURE-LIST v4.3, ROADMAP v4.3 - AGENTS.md: updated module count and career link paths
111 lines
6.0 KiB
TypeScript
111 lines
6.0 KiB
TypeScript
import { API_ENDPOINTS, api } from '../config'
|
|
|
|
async function request<T = any>(url: string, method: string = 'POST', data?: any, auth: boolean = false): Promise<T> {
|
|
const headers: Record<string, string> = { 'Content-Type': 'application/json' }
|
|
if (auth) {
|
|
const token = uni.getStorageSync('token') || ''
|
|
if (token) headers['Authorization'] = `Bearer ${token}`
|
|
}
|
|
try {
|
|
const res = await uni.request({ url: api(url), method, data, header: headers, timeout: 65000 })
|
|
if (res.statusCode >= 200 && res.statusCode < 300) return res.data as T
|
|
if (res.statusCode === 401) {
|
|
uni.removeStorageSync('token'); uni.removeStorageSync('userInfo')
|
|
uni.showToast({ title: '登录已过期', icon: 'none' })
|
|
setTimeout(() => uni.navigateTo({ url: '/pages/login/login' }), 500)
|
|
throw new Error('登录已过期')
|
|
}
|
|
throw new Error((res.data as any)?.message || '请求失败')
|
|
} catch (e: any) {
|
|
if (e.message === '登录已过期') throw e
|
|
throw new Error(e.message || '网络错误')
|
|
}
|
|
}
|
|
|
|
const apiService = {
|
|
user: {
|
|
sendCode: (phone: string) => request(API_ENDPOINTS.USER.SEND_CODE, 'POST', { phone }),
|
|
login: (phone: string, code: string) => request(API_ENDPOINTS.USER.LOGIN, 'POST', { phone, code }),
|
|
wxLogin: (code: string) => request(API_ENDPOINTS.USER.WX_LOGIN, 'POST', { code }),
|
|
getInfo: () => request(API_ENDPOINTS.USER.INFO, 'GET', undefined, true),
|
|
update: (data: any) => request(API_ENDPOINTS.USER.UPDATE, 'PUT', data, true),
|
|
usage: () => request(API_ENDPOINTS.USER.USAGE, 'GET', undefined, true),
|
|
},
|
|
interview: {
|
|
create: (position: string) => request(API_ENDPOINTS.INTERVIEW.CREATE, 'POST', { position }, true),
|
|
answer: (id: string, answer: string) => request(API_ENDPOINTS.INTERVIEW.ANSWER(id), 'POST', { answer }, true),
|
|
complete: (id: string) => request(API_ENDPOINTS.INTERVIEW.COMPLETE(id), 'POST', undefined, true),
|
|
get: (id: string) => request(API_ENDPOINTS.INTERVIEW.GET(id), 'GET', undefined, true),
|
|
list: () => request(API_ENDPOINTS.INTERVIEW.LIST, 'GET', undefined, true),
|
|
stats: () => request(API_ENDPOINTS.INTERVIEW.STATS, 'GET', undefined, true),
|
|
},
|
|
analyze: {
|
|
diagnosis: (content: string) => request(API_ENDPOINTS.ANALYZE.DIAGNOSIS, 'POST', { content }, true),
|
|
optimize: (content: string, direction: string) => request(API_ENDPOINTS.ANALYZE.OPTIMIZE, 'POST', { content, direction }, true),
|
|
skillsGap: (targetPosition?: string) =>
|
|
request(API_ENDPOINTS.ANALYZE.SKILLS_GAP, 'POST', { targetPosition }, true),
|
|
},
|
|
resume: {
|
|
create: (title: string, content: string, targetPosition?: string) =>
|
|
request(API_ENDPOINTS.RESUME.CREATE, 'POST', { title, content, targetPosition }, true),
|
|
list: () => request(API_ENDPOINTS.RESUME.LIST, 'GET', undefined, true),
|
|
delete: (id: string) => request(API_ENDPOINTS.RESUME.DELETE(id), 'DELETE', undefined, true),
|
|
},
|
|
progress: {
|
|
get: () => request(API_ENDPOINTS.PROGRESS.GET, 'GET', undefined, true),
|
|
stats: () => request(API_ENDPOINTS.PROGRESS.STATS, 'GET', undefined, true),
|
|
},
|
|
contribution: {
|
|
create: (data: any) => request(API_ENDPOINTS.CONTRIBUTION.CREATE, 'POST', data, true),
|
|
my: () => request(API_ENDPOINTS.CONTRIBUTION.MY, 'GET', undefined, true),
|
|
bank: (company: string, position: string) =>
|
|
request(API_ENDPOINTS.CONTRIBUTION.BANK(company, position), 'GET', undefined, true),
|
|
company: (company: string) =>
|
|
request(API_ENDPOINTS.CONTRIBUTION.COMPANY(company), 'GET', undefined, true),
|
|
},
|
|
member: {
|
|
plans: () => request(API_ENDPOINTS.MEMBER.PLANS, 'GET', undefined),
|
|
status: () => request(API_ENDPOINTS.MEMBER.STATUS, 'GET', undefined, true),
|
|
pay: (outTradeNo: string) => request(API_ENDPOINTS.MEMBER.PAY, 'POST', { outTradeNo }, true),
|
|
sprintDeduct: () => request(API_ENDPOINTS.MEMBER.SPRINT_DEDUCT, 'POST', undefined, true),
|
|
},
|
|
payment: {
|
|
create: (plan: string) => request(API_ENDPOINTS.PAYMENT.CREATE, 'POST', { plan }, true),
|
|
jsapi: (plan: string) => request(API_ENDPOINTS.PAYMENT.JSAPI, 'POST', { plan }, true),
|
|
check: (outTradeNo: string) => request(API_ENDPOINTS.PAYMENT.CHECK(outTradeNo), 'GET', undefined, true),
|
|
activate: (outTradeNo: string) => request(API_ENDPOINTS.PAYMENT.ACTIVATE, 'POST', { outTradeNo }, true),
|
|
},
|
|
dailyQuestion: {
|
|
today: (position?: string) => {
|
|
const query = position ? `?position=${encodeURIComponent(position)}` : ''
|
|
return request(API_ENDPOINTS.DAILY_QUESTION.TODAY + query, 'GET', undefined, true)
|
|
},
|
|
byPosition: (position: string) =>
|
|
request(API_ENDPOINTS.DAILY_QUESTION.BY_POSITION(position), 'GET', undefined, true),
|
|
},
|
|
share: {
|
|
create: (data: { type: string; refId?: string; title?: string; description?: string }) =>
|
|
request(API_ENDPOINTS.SHARE.CREATE, 'POST', data, true),
|
|
stats: () => request(API_ENDPOINTS.SHARE.STATS, 'GET', undefined, true),
|
|
records: () => request(API_ENDPOINTS.SHARE.RECORDS, 'GET', undefined, true),
|
|
visitors: () => request(API_ENDPOINTS.SHARE.VISITORS, 'GET', undefined, true),
|
|
},
|
|
review: {
|
|
list: (page = 1, limit = 20) =>
|
|
request(`${API_ENDPOINTS.REVIEW.LIST}?page=${page}&limit=${limit}`, 'GET', undefined, true),
|
|
detail: (id: string) => request(API_ENDPOINTS.REVIEW.DETAIL(id), 'GET', undefined, true),
|
|
delete: (id: string) => request(API_ENDPOINTS.REVIEW.DELETE(id), 'DELETE', undefined, true),
|
|
submitText: (position: string, text: string, company?: string) =>
|
|
request(API_ENDPOINTS.REVIEW.TEXT, 'POST', { position, text, company: company || '' }, true),
|
|
},
|
|
career: {
|
|
analyze: (profile: { major: string; grade?: string; interests?: string; gpa?: string; goal?: string }) =>
|
|
request(API_ENDPOINTS.CAREER.ANALYZE, 'POST', profile, true),
|
|
chat: (message: string, history: { role: string; content: string }[]) =>
|
|
request(API_ENDPOINTS.CAREER.CHAT, 'POST', { message, history }, true),
|
|
positions: () => request(API_ENDPOINTS.CAREER.POSITIONS, 'GET', undefined, true),
|
|
},
|
|
}
|
|
|
|
export default apiService
|