Files
x-server-mobile/backend/app/Service/BusinessTripService.php
T
root 09d4cb8054 fix: 修复页面间状态丢失问题并优化选择页面
- 修复选择审批人后再选择抄送人导致状态丢失的问题
- 使用独立的 sessionStorage key (selectedApprovers, selectedCc)
- 组件每次挂载时从 sessionStorage 恢复状态
- 只在提交/保存成功后清除 sessionStorage
- 优化人员选择页面布局和样式
- 更新 CLAUDE.md 文档记录问题和解决方案

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:22:12 +08:00

304 lines
11 KiB
PHP

<?php
namespace App\Service;
use App\Model\BusinessTrip;
use App\Model\BusinessTripItinerary;
use App\Model\ApprovalOrder;
use App\Model\ApprovalFlow;
use App\Model\ApprovalRecord;
use App\Model\User;
use App\Util\Db;
use Illuminate\Database\Connection;
class BusinessTripService
{
private Connection $db;
public function __construct()
{
Db::init();
$this->db = Db::connection();
}
/**
* 创建出差申请(草稿)
*/
public function createDraft(int $userId, array $data): BusinessTrip
{
return $this->db->transaction(function () use ($userId, $data) {
try {
// 计算最早和最晚时间
$itineraries = $data['itineraries'] ?? [];
if (empty($itineraries)) {
throw new \Exception('请至少添加一条行程');
}
$startDate = null;
$endDate = null;
$destinations = [];
foreach ($itineraries as $itinerary) {
if ($itinerary['start_time']) {
if (!$startDate || $itinerary['start_time'] < $startDate) {
$startDate = $itinerary['start_time'];
}
}
if ($itinerary['end_time']) {
if (!$endDate || $itinerary['end_time'] > $endDate) {
$endDate = $itinerary['end_time'];
}
}
if (!empty($itinerary['destination'])) {
$destinations[] = $itinerary['destination'];
}
}
// 创建出差申请
$businessTrip = BusinessTrip::create([
'user_id' => $userId,
'reason' => $data['reason'] ?? '',
'start_date' => $startDate ? date('Y-m-d', strtotime($startDate)) : null,
'end_date' => $endDate ? date('Y-m-d', strtotime($endDate)) : null,
'destination' => implode(', ', array_unique($destinations)),
'estimated_cost' => $data['estimated_cost'] ?? 0,
'status' => BusinessTrip::STATUS_DRAFT,
]);
// 创建行程明细
foreach ($itineraries as $itinerary) {
BusinessTripItinerary::create([
'business_trip_id' => $businessTrip->id,
'start_time' => $itinerary['start_time'],
'end_time' => $itinerary['end_time'] ?? null,
'departure' => $itinerary['departure'] ?? '',
'destination' => $itinerary['destination'] ?? '',
'transport' => $itinerary['transport'] ?? '',
'trip_type' => $itinerary['trip_type'] ?? 'oneway',
'remark' => $itinerary['remark'] ?? '',
]);
}
return $businessTrip->load('itineraries');
} catch (\Exception $e) {
error_log('BusinessTripService::createDraft error: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());
throw $e;
}
});
}
/**
* 提交出差申请
*/
public function submit(int $userId, int $businessTripId, array $approvers, array $ccUsers = []): BusinessTrip
{
return $this->db->transaction(function () use ($userId, $businessTripId, $approvers, $ccUsers) {
$businessTrip = BusinessTrip::with('itineraries')->findOrFail($businessTripId);
if ($businessTrip->user_id !== $userId) {
throw new \Exception('无权操作此申请');
}
if (!$businessTrip->canSubmit()) {
throw new \Exception('当前状态无法提交');
}
// 获取审批流程(简化版:直接使用第一个审批人作为单人审批)
$flow = ApprovalFlow::where('business_type', 'business_trip')
->where('status', 1)
->first();
if (!$flow) {
// 创建默认流程
$flow = ApprovalFlow::create([
'business_type' => 'business_trip',
'name' => '出差审批',
'description' => '出差申请审批流程',
'status' => 1,
]);
}
// 创建审批单
$approvalOrder = ApprovalOrder::create([
'business_type' => 'business_trip',
'business_id' => $businessTrip->id,
'title' => '出差申请 - ' . $businessTrip->user->name,
'applicant_id' => $userId,
'status' => ApprovalOrder::STATUS_PENDING,
'current_nodes' => [1], // 简化:使用节点1
'flow_id' => $flow->id,
'form_data' => [
'reason' => $businessTrip->reason,
'start_date' => $businessTrip->start_date,
'end_date' => $businessTrip->end_date,
'destination' => $businessTrip->destination,
'approvers' => $approvers,
'cc_users' => $ccUsers,
],
]);
// 更新出差申请状态
$businessTrip->status = BusinessTrip::STATUS_PENDING;
$businessTrip->approval_order_id = $approvalOrder->id;
$businessTrip->save();
// 记录提交操作
ApprovalRecord::create([
'order_id' => $approvalOrder->id,
'node_id' => 1,
'node_type' => 'single_approve',
'approver_id' => $userId,
'action' => 'submit',
'comment' => null,
]);
return $businessTrip->fresh(['itineraries', 'approvalOrder']);
});
}
/**
* 获取出差申请列表
*/
public function getList(int $userId, string $type = 'my', int $page = 1, int $pageSize = 20): array
{
$query = BusinessTrip::with(['user', 'itineraries']);
switch ($type) {
case 'my':
$query->where('user_id', $userId);
break;
case 'pending':
// 获取待审批的申请
$pendingOrderIds = ApprovalOrder::where('status', ApprovalOrder::STATUS_PENDING)
->where('business_type', 'business_trip')
->pluck('business_id')
->toArray();
$query->whereIn('id', $pendingOrderIds);
break;
}
$total = $query->count();
$list = $query->orderBy('created_at', 'desc')
->offset(($page - 1) * $pageSize)
->limit($pageSize)
->get();
return [
'list' => $list,
'total' => $total,
'page' => $page,
'page_size' => $pageSize,
];
}
/**
* 获取出差申请详情
*/
public function getDetail(int $id): BusinessTrip
{
return BusinessTrip::with(['user', 'itineraries'])
->findOrFail($id);
}
/**
* 更新出差申请
*/
public function update(int $userId, int $id, array $data): BusinessTrip
{
$businessTrip = BusinessTrip::findOrFail($id);
if ($businessTrip->user_id !== $userId) {
throw new \Exception('无权操作此申请');
}
if (!$businessTrip->canEdit()) {
throw new \Exception('当前状态无法编辑');
}
return $this->db->transaction(function () use ($businessTrip, $data) {
// 更新基本信息
if (isset($data['reason'])) {
$businessTrip->reason = $data['reason'];
}
// 更新行程
if (isset($data['itineraries'])) {
// 删除旧行程
BusinessTripItinerary::where('business_trip_id', $businessTrip->id)->delete();
// 创建新行程
$startDate = null;
$endDate = null;
$destinations = [];
foreach ($data['itineraries'] as $itinerary) {
BusinessTripItinerary::create([
'business_trip_id' => $businessTrip->id,
'start_time' => $itinerary['start_time'],
'end_time' => $itinerary['end_time'] ?? null,
'departure' => $itinerary['departure'] ?? '',
'destination' => $itinerary['destination'] ?? '',
'transport' => $itinerary['transport'] ?? '',
'trip_type' => $itinerary['trip_type'] ?? 'oneway',
'remark' => $itinerary['remark'] ?? '',
]);
if ($itinerary['start_time']) {
if (!$startDate || $itinerary['start_time'] < $startDate) {
$startDate = $itinerary['start_time'];
}
}
if ($itinerary['end_time']) {
if (!$endDate || $itinerary['end_time'] > $endDate) {
$endDate = $itinerary['end_time'];
}
}
if (!empty($itinerary['destination'])) {
$destinations[] = $itinerary['destination'];
}
}
// 更新日期和目的地
$businessTrip->start_date = $startDate ? date('Y-m-d', strtotime($startDate)) : null;
$businessTrip->end_date = $endDate ? date('Y-m-d', strtotime($endDate)) : null;
$businessTrip->destination = implode(', ', array_unique($destinations));
}
$businessTrip->save();
return $businessTrip->fresh('itineraries');
});
}
/**
* 取消出差申请
*/
public function cancel(int $userId, int $id): BusinessTrip
{
$businessTrip = BusinessTrip::findOrFail($id);
if ($businessTrip->user_id !== $userId) {
throw new \Exception('无权操作此申请');
}
if (!$businessTrip->canCancel()) {
throw new \Exception('当前状态无法取消');
}
$businessTrip->status = BusinessTrip::STATUS_CANCELLED;
$businessTrip->save();
// 同时取消审批单
if ($businessTrip->approval_order_id) {
$approvalOrder = ApprovalOrder::find($businessTrip->approval_order_id);
if ($approvalOrder) {
$approvalOrder->status = ApprovalOrder::STATUS_CANCELLED;
$approvalOrder->current_nodes = [];
$approvalOrder->save();
}
}
return $businessTrip->fresh();
}
}