Commit bd940f2e101ae38b6c49360afc1d3141cdbf88fb
1 parent
9e022006
feat(fe-login): usrApi 登录与版本下拉取数封装 REQ-USR-004
Showing
3 changed files
with
93 additions
and
0 deletions
frontend/src/api/types.ts
0 → 100644
| 1 | +// REQ-USR-004: 前端跨 task 共享类型契约(对齐 docs/05 § REQ-USR-004 / spec § 4) | |
| 2 | + | |
| 3 | +/** 登录用户(对齐 Result<{ token, user }> 的 user 字段) */ | |
| 4 | +export interface AuthUser { | |
| 5 | + id: number; | |
| 6 | + sUserName: string; | |
| 7 | + sUserType: string; | |
| 8 | + sLanguage: string; | |
| 9 | +} | |
| 10 | + | |
| 11 | +/** POST /api/usr/login 请求体 */ | |
| 12 | +export interface LoginPayload { | |
| 13 | + sUserName: string; | |
| 14 | + password: string; | |
| 15 | + companyId: number; | |
| 16 | +} | |
| 17 | + | |
| 18 | +/** POST /api/usr/login 成功响应(已拆 Result.data) */ | |
| 19 | +export interface LoginResult { | |
| 20 | + token: string; | |
| 21 | + user: AuthUser; | |
| 22 | +} | |
| 23 | + | |
| 24 | +/** GET /api/usr/companies 列表项(登录「版本」下拉,D8;sVersion 可空) */ | |
| 25 | +export interface CompanyOption { | |
| 26 | + id: number; | |
| 27 | + sCompanyName: string; | |
| 28 | + sVersion: string | null; | |
| 29 | +} | ... | ... |
frontend/src/api/usrApi.ts
0 → 100644
| 1 | +// REQ-USR-004: USR 模块 API 封装(登录 + 版本下拉取数)。页面只调本文件,不散用 axios。 | |
| 2 | +import request from './request'; | |
| 3 | +import type { LoginPayload, LoginResult, CompanyOption } from './types'; | |
| 4 | + | |
| 5 | +// 响应拦截器已拆 Result.data,故此处返回类型即业务数据本体。 | |
| 6 | +// axios 实例的方法类型仍标注为 AxiosResponse,运行时已被拦截器解包,用 as unknown 桥接。 | |
| 7 | + | |
| 8 | +/** POST /api/usr/login —— 登录认证,成功返回 { token, user } */ | |
| 9 | +export function login(payload: LoginPayload): Promise<LoginResult> { | |
| 10 | + return request.post('/usr/login', payload) as unknown as Promise<LoginResult>; | |
| 11 | +} | |
| 12 | + | |
| 13 | +/** GET /api/usr/companies —— 登录「版本」下拉项(公司表只读) */ | |
| 14 | +export function fetchCompanies(): Promise<CompanyOption[]> { | |
| 15 | + return request.get('/usr/companies') as unknown as Promise<CompanyOption[]>; | |
| 16 | +} | ... | ... |
frontend/tests/unit/usrApi.test.ts
0 → 100644
| 1 | +import { describe, it, expect, vi, beforeEach } from 'vitest'; | |
| 2 | + | |
| 3 | +// 桩掉底层 axios 实例(request.ts 的 default 导出) | |
| 4 | +vi.mock('../../src/api/request', () => { | |
| 5 | + return { | |
| 6 | + default: { | |
| 7 | + post: vi.fn(), | |
| 8 | + get: vi.fn(), | |
| 9 | + }, | |
| 10 | + }; | |
| 11 | +}); | |
| 12 | + | |
| 13 | +import request from '../../src/api/request'; | |
| 14 | +import { login, fetchCompanies } from '../../src/api/usrApi'; | |
| 15 | + | |
| 16 | +const mockedRequest = request as unknown as { | |
| 17 | + post: ReturnType<typeof vi.fn>; | |
| 18 | + get: ReturnType<typeof vi.fn>; | |
| 19 | +}; | |
| 20 | + | |
| 21 | +describe('usrApi', () => { | |
| 22 | + beforeEach(() => { | |
| 23 | + vi.clearAllMocks(); | |
| 24 | + }); | |
| 25 | + | |
| 26 | + it('login posts to /usr/login with sUserName/password/companyId', async () => { | |
| 27 | + const result = { | |
| 28 | + token: 'tk', | |
| 29 | + user: { id: 1, sUserName: 'admin', sUserType: '超级管理员', sLanguage: '中文' }, | |
| 30 | + }; | |
| 31 | + mockedRequest.post.mockResolvedValue(result); | |
| 32 | + const payload = { sUserName: 'admin', password: 'p', companyId: 9 }; | |
| 33 | + const ret = await login(payload); | |
| 34 | + expect(mockedRequest.post).toHaveBeenCalledWith('/usr/login', payload); | |
| 35 | + expect(ret).toEqual(result); | |
| 36 | + }); | |
| 37 | + | |
| 38 | + it('fetchCompanies gets /usr/companies and returns list', async () => { | |
| 39 | + const list = [ | |
| 40 | + { id: 1, sCompanyName: '甲公司', sVersion: '标准版' }, | |
| 41 | + { id: 2, sCompanyName: '乙公司', sVersion: null }, | |
| 42 | + ]; | |
| 43 | + mockedRequest.get.mockResolvedValue(list); | |
| 44 | + const ret = await fetchCompanies(); | |
| 45 | + expect(mockedRequest.get).toHaveBeenCalledWith('/usr/companies'); | |
| 46 | + expect(ret).toEqual(list); | |
| 47 | + }); | |
| 48 | +}); | ... | ... |