feat: 实现出差申请页面

- 创建出差申请表单,包含出差事由、行程明细、审批人选择
- 实现行程明细的增删改功能,支持开始/结束时间、出发地、目的地等
- 添加单程/往返类型选择和交通工具下拉选择
- 实现自动计算行程时长和总时长
- 创建审批人和抄送人选择页面
- 添加前后端API接口定义
- 更新i18n国际化翻译
- 整理开发文档和UI设计图

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-02-24 23:44:40 +08:00
parent 49fa9c3f92
commit 2d39357cc3
14 changed files with 1337 additions and 27 deletions
+85
View File
@@ -0,0 +1,85 @@
import { api } from './api'
// 出差申请接口类型定义
export interface BusinessTripItinerary {
startTime: string
endTime: string
departure?: string
destination: string
transport?: string
tripType?: 'oneway' | 'roundtrip'
remark?: string
}
export interface CreateBusinessTripDto {
reason: string
itineraries: BusinessTripItinerary[]
approvers: number[]
cc_users?: number[]
}
export interface BusinessTripItem {
id: number
user_id: number
user_name: string
reason: string
start_date: string
end_date: string
duration: number
status: 'draft' | 'pending' | 'approved' | 'rejected' | 'cancelled'
approval_order_id: number | null
created_at: string
updated_at: string
}
export interface BusinessTripDetail extends BusinessTripItem {
itineraries: BusinessTripItinerary[]
approvers: ApproverInfo[]
cc_users: ApproverInfo[]
}
export interface ApproverInfo {
id: number
name: string
avatar?: string
position?: string
}
// 出差申请 API
export const businessTripApi = {
// 创建出差申请
create: (data: CreateBusinessTripDto) =>
api.post('/business-trip', data),
// 获取出差列表
getList: (params?: { status?: string; page?: number; page_size?: number }) =>
api.get<BusinessTripItem[]>('/business-trip', { params }),
// 获取出差详情
getDetail: (id: number) =>
api.get<BusinessTripDetail>(`/business-trip/${id}`),
// 更新出差申请(草稿状态)
update: (id: number, data: Partial<CreateBusinessTripDto>) =>
api.put(`/business-trip/${id}`, data),
// 提交审批
submit: (id: number) =>
api.post(`/business-trip/${id}/submit`),
// 撤销申请
cancel: (id: number) =>
api.post(`/business-trip/${id}/cancel`),
// 获取用户列表(用于选择审批人和抄送)
getUsers: (params?: { search?: string }) =>
api.get<ApproverInfo[]>('/users', { params }),
// 保存草稿
saveDraft: (data: CreateBusinessTripDto) =>
api.post('/business-trip/draft', data),
// 获取草稿
getDrafts: () =>
api.get<BusinessTripItem[]>('/business-trip/drafts'),
}