Bladeren bron

feat:实现用户端接口逻辑

醉梦人间三千年 4 maanden geleden
bovenliggende
commit
2d34d74dfe
39 gewijzigde bestanden met toevoegingen van 2674 en 42 verwijderingen
  1. 79 0
      app/Admin/Controllers/MemberAddressController.php
  2. 4 4
      app/Admin/Controllers/ProjectController.php
  3. 55 0
      app/Admin/Controllers/SysConfigController.php
  4. 55 0
      app/Http/Controllers/Client/AgentController.php
  5. 37 0
      app/Http/Controllers/Client/CoachController.php
  6. 38 0
      app/Http/Controllers/Client/CommentController.php
  7. 53 0
      app/Http/Controllers/Client/CommonController.php
  8. 35 0
      app/Http/Controllers/Client/ExtendOrderController.php
  9. 477 0
      app/Http/Controllers/Client/OrderController.php
  10. 26 0
      app/Http/Controllers/Client/PaymentController.php
  11. 36 0
      app/Http/Controllers/Client/ProjectController.php
  12. 25 0
      app/Http/Controllers/Client/TeamController.php
  13. 114 0
      app/Http/Controllers/Client/UserController.php
  14. 24 0
      app/Http/Controllers/Client/WalletController.php
  15. 3 6
      app/Models/MemberAddress.php
  16. 2 2
      app/Models/Order.php
  17. 2 2
      app/Models/Project.php
  18. 16 0
      app/Models/SysConfig.php
  19. 112 0
      app/Services/Client/AgentService.php
  20. 74 0
      app/Services/Client/CoachService.php
  21. 64 0
      app/Services/Client/CommentService.php
  22. 125 0
      app/Services/Client/CommonService.php
  23. 51 0
      app/Services/Client/ExtendOrderService.php
  24. 567 0
      app/Services/Client/OrderService.php
  25. 76 0
      app/Services/Client/PaymentService.php
  26. 77 0
      app/Services/Client/ProjectService.php
  27. 36 0
      app/Services/Client/TeamService.php
  28. 252 0
      app/Services/Client/UserService.php
  29. 33 0
      app/Services/Client/WalletService.php
  30. 17 0
      app/Services/MemberAddressService.php
  31. 17 0
      app/Services/ProjectService.php
  32. 0 17
      app/Services/ProjectServiceService.php
  33. 17 0
      app/Services/SysConfigService.php
  34. 2 2
      database/migrations/2024_11_14_061044_create_order_table.php
  35. 27 0
      database/migrations/2024_11_14_120000_create_user_feedbacks_table.php
  36. 2 2
      database/migrations/2024_11_18_040034_create_project_table.php
  37. 3 3
      database/migrations/2024_11_18_051648_create_member_address_table.php
  38. 35 0
      database/migrations/2024_11_18_063954_create_sys_config_table.php
  39. 6 4
      routes/admin.php

+ 79 - 0
app/Admin/Controllers/MemberAddressController.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Services\MemberAddressService;
+use Slowlyo\OwlAdmin\Controllers\AdminController;
+
+/**
+ * 用户地址
+ *
+ * @property MemberAddressService $service
+ */
+class MemberAddressController extends AdminController
+{
+	protected string $serviceName = MemberAddressService::class;
+
+	public function list()
+	{
+		$crud = $this->baseCRUD()
+			->filterTogglable(false)
+			->headerToolbar([
+				$this->createButton('dialog'),
+				...$this->baseHeaderToolBar()
+			])
+			->columns([
+				amis()->TableColumn('id', 'ID')->sortable(),
+				amis()->TableColumn('user_id', '用户编号'),
+				amis()->TableColumn('location', '定位地址'),
+				amis()->TableColumn('detail', '详细地址'),
+				amis()->TableColumn('province', '省'),
+				amis()->TableColumn('city', '市'),
+				amis()->TableColumn('district', '区'),
+				amis()->TableColumn('longitude', '经度'),
+				amis()->TableColumn('latitude', '纬度'),
+				amis()->TableColumn('area_code', '行政区划代码'),
+				amis()->TableColumn('is_default', '是否默认地址'),
+				amis()->TableColumn('created_at', admin_trans('admin.created_at'))->type('datetime')->sortable(),
+				amis()->TableColumn('updated_at', admin_trans('admin.updated_at'))->type('datetime')->sortable(),
+				$this->rowActions('dialog')
+			]);
+
+		return $this->baseList($crud);
+	}
+
+	public function form($isEdit = false)
+	{
+		return $this->baseForm()->body([
+			amis()->TextControl('user_id', '用户编号'),
+			amis()->TextControl('location', '定位地址'),
+			amis()->TextControl('detail', '详细地址'),
+			amis()->TextControl('province', '省'),
+			amis()->TextControl('city', '市'),
+			amis()->TextControl('district', '区'),
+			amis()->TextControl('longitude', '经度'),
+			amis()->TextControl('latitude', '纬度'),
+			amis()->TextControl('area_code', '行政区划代码'),
+			amis()->TextControl('is_default', '是否默认地址'),
+		]);
+	}
+
+	public function detail()
+	{
+		return $this->baseDetail()->body([
+			amis()->TextControl('id', 'ID')->static(),
+			amis()->TextControl('user_id', '用户编号')->static(),
+			amis()->TextControl('location', '定位地址')->static(),
+			amis()->TextControl('detail', '详细地址')->static(),
+			amis()->TextControl('province', '省')->static(),
+			amis()->TextControl('city', '市')->static(),
+			amis()->TextControl('district', '区')->static(),
+			amis()->TextControl('longitude', '经度')->static(),
+			amis()->TextControl('latitude', '纬度')->static(),
+			amis()->TextControl('area_code', '行政区划代码')->static(),
+			amis()->TextControl('is_default', '是否默认地址')->static(),
+			amis()->TextControl('created_at', admin_trans('admin.created_at'))->static(),
+			amis()->TextControl('updated_at', admin_trans('admin.updated_at'))->static(),
+		]);
+	}
+}

+ 4 - 4
app/Admin/Controllers/ProjectServiceController.php → app/Admin/Controllers/ProjectController.php

@@ -2,17 +2,17 @@
 
 namespace App\Admin\Controllers;
 
-use App\Services\ProjectServiceService;
+use App\Services\ProjectService;
 use Slowlyo\OwlAdmin\Controllers\AdminController;
 
 /**
  * 项目服务
  *
- * @property ProjectServiceService $service
+ * @property ProjectService $service
  */
-class ProjectServiceController extends AdminController
+class ProjectController extends AdminController
 {
-	protected string $serviceName = ProjectServiceService::class;
+	protected string $serviceName = ProjectService::class;
 
 	public function list()
 	{

+ 55 - 0
app/Admin/Controllers/SysConfigController.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Services\SysConfigService;
+use Slowlyo\OwlAdmin\Controllers\AdminController;
+
+/**
+ * 系统设置
+ *
+ * @property SysConfigService $service
+ */
+class SysConfigController extends AdminController
+{
+	protected string $serviceName = SysConfigService::class;
+
+	public function list()
+	{
+		$crud = $this->baseCRUD()
+			->filterTogglable(false)
+			->headerToolbar([
+				$this->createButton('dialog'),
+				...$this->baseHeaderToolBar()
+			])
+			->columns([
+				amis()->TableColumn('id', 'ID')->sortable(),
+				amis()->TableColumn('key', '配置项'),
+				amis()->TableColumn('value', '配置值'),
+				amis()->TableColumn('created_at', admin_trans('admin.created_at'))->type('datetime')->sortable(),
+				amis()->TableColumn('updated_at', admin_trans('admin.updated_at'))->type('datetime')->sortable(),
+				$this->rowActions('dialog')
+			]);
+
+		return $this->baseList($crud);
+	}
+
+	public function form($isEdit = false)
+	{
+		return $this->baseForm()->body([
+			amis()->TextControl('key', '配置项'),
+			amis()->TextControl('value', '配置值'),
+		]);
+	}
+
+	public function detail()
+	{
+		return $this->baseDetail()->body([
+			amis()->TextControl('id', 'ID')->static(),
+			amis()->TextControl('key', '配置项')->static(),
+			amis()->TextControl('value', '配置值')->static(),
+			amis()->TextControl('created_at', admin_trans('admin.created_at'))->static(),
+			amis()->TextControl('updated_at', admin_trans('admin.updated_at'))->static(),
+		]);
+	}
+}

+ 55 - 0
app/Http/Controllers/Client/AgentController.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\AgentService;
+use Illuminate\Http\Request;
+
+class AgentController extends Controller
+{
+    protected AgentService $service;
+
+    public function __construct(AgentService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取代理商配置
+     */
+    public function getConfig(Request $request)
+    {
+        $agentId = $request->input('agent_id');
+        return $this->service->getAgentConfig($agentId);
+    }
+
+    /**
+     * 获取代理商
+     */
+    public function getAgent(Request $request)
+    {
+        $areaCode = $request->input('area_code');
+        return $this->service->getAgent($areaCode);
+    }
+
+    /**
+     * 获取代理商项目列表
+     */
+    public function getProjectList(Request $request)
+    {
+        $categoryId = $request->input('category_id');
+        $agentId = $request->input('agent_id');
+        return $this->service->getProjectList($categoryId, $agentId);
+    }
+
+    /**
+     * 获取代理商项目详情
+     */
+    public function getProjectDetail(Request $request)
+    {
+        $projectId = $request->input('project_id');
+        $agentId = $request->input('agent_id');
+        return $this->service->getProjectDetail($projectId, $agentId);
+    }
+} 

+ 37 - 0
app/Http/Controllers/Client/CoachController.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\CoachService;
+use Illuminate\Http\Request;
+
+class CoachController extends Controller
+{
+    protected CoachService $service;
+
+    public function __construct(CoachService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取技师列表
+     */
+    public function list(Request $request)
+    {
+        $latitude = $request->input('latitude');
+        $longitude = $request->input('longitude'); 
+        return $this->service->getCoachList($latitude, $longitude);
+    }
+
+    /**
+     * 获取技师详情
+     */
+    public function detail(Request $request, $id)
+    {
+        $latitude = $request->input('latitude');
+        $longitude = $request->input('longitude');
+        return $this->service->getCoachDetail($id, $latitude, $longitude);
+    }
+} 

+ 38 - 0
app/Http/Controllers/Client/CommentController.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\CommentService;
+use Illuminate\Http\Request;
+
+class CommentController extends Controller
+{
+    protected CommentService $service;
+
+    public function __construct(CommentService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 发表评价
+     */
+    public function create(Request $request)
+    {
+        $coachId = $request->input('coach_id');
+        $content = $request->input('content');
+        $rating = $request->input('rating');
+        
+        return $this->service->createComment($coachId, $content, $rating);
+    }
+
+    /**
+     * 评价列表
+     */
+    public function list(Request $request)
+    {
+        $coachId = $request->input('coach_id');
+        return $this->service->getCommentList($coachId);
+    }
+} 

+ 53 - 0
app/Http/Controllers/Client/CommonController.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\CommonService;
+use Illuminate\Http\Request;
+
+class CommonController extends Controller
+{
+    protected CommonService $service;
+
+    public function __construct(CommonService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取代理商配置
+     */
+    public function getConfig(Request $request)
+    {
+        $agentId = $request->input('agent_id');
+        return $this->service->getAgentConfig($agentId);
+    }
+
+    /**
+     * 获取技师配置
+     */
+    public function getCoachConfig(Request $request)
+    {
+        $coachId = $request->input('coach_id');
+        return $this->service->getCoachConfig($coachId);
+    }
+
+    /**
+     * 计算路费金额
+     */
+    public function calculateDeliveryFee(Request $request)
+    {
+        $coachId = $request->input('coach_id');
+        $agentId = $request->input('agent_id');
+        $distance = $request->input('distance');
+        $latitude = $request->input('latitude'); 
+        $longitude = $request->input('longitude');
+
+        if ($agentId) {
+            return $this->service->calculateDeliveryFee($coachId, $agentId, $distance);
+        } else {
+            return $this->service->calculateDeliveryFeeByLocation($coachId, $latitude, $longitude, $distance);
+        }
+    }
+} 

+ 35 - 0
app/Http/Controllers/Client/ExtendOrderController.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\ExtendOrderService;
+use Illuminate\Http\Request;
+
+class ExtendOrderController extends Controller
+{
+    protected ExtendOrderService $service;
+
+    public function __construct(ExtendOrderService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取加钟项目列表
+     */
+    public function getProjectList(Request $request)
+    {
+        $projectId = $request->input('project_id');
+        return $this->service->getProjectList($projectId);
+    }
+
+    /**
+     * 加钟
+     */
+    public function extend(Request $request)
+    {
+        $orderId = $request->route('order_id');
+        return $this->service->extend($orderId);
+    }
+} 

+ 477 - 0
app/Http/Controllers/Client/OrderController.php

@@ -0,0 +1,477 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\OrderService;
+use Illuminate\Http\Request;
+
+class OrderController extends Controller
+{
+    protected OrderService $service;
+
+    public function __construct(OrderService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 订单初始化
+     */
+    public function initialize(Request $request)
+    {
+        $userId = Auth::id();
+        $coachId = $request->input('coach_id');
+        $areaCode = $request->input('area_code');
+        $projectId = $request->input('project_id');
+        
+        return $this->service->initialize($userId, $coachId, $areaCode, $projectId);
+    }
+
+    /**
+     * 结束订单
+     */
+    public function finish(Request $request)
+    {
+        $userId = Auth::id();
+        $orderId = $request->input('order_id');
+        
+        return $this->service->finishOrder($userId, $orderId);
+    }
+
+    /**
+     * 确认技师离开
+     */
+    public function confirmLeave(Request $request) 
+    {
+        $userId = Auth::id();
+        $orderId = $request->input('order_id');
+        
+        return $this->service->confirmLeave($userId, $orderId);
+    }
+
+    /**
+     * 取消订单
+     */
+    public function cancel(Request $request)
+    {
+        $userId = Auth::id();
+        $orderId = $request->input('order_id');
+        
+        return $this->service->cancelOrder($userId, $orderId);
+    }
+
+    /**
+     * 获取订单列表
+     */
+    public function list()
+    {
+        return $this->service->getOrderList();
+    }
+
+    /**
+     * 获取订单详情
+     */
+    public function detail($id)
+    {
+        return $this->service->getOrderDetail($id);
+    }
+
+    /**
+     * 订单退款
+     */
+    public function refund($id)
+    {
+        return $this->service->refundOrder($id);
+    }
+
+    /**
+     * 获取代理商配置
+     */
+    public function getAgentConfig(Request $request)
+    {
+        $agentId = $request->input('agent_id');
+        return $this->service->getAgentConfig($agentId);
+    }
+
+    /**
+     * 获取技师配置
+     */
+    public function getCoachConfig(Request $request)
+    {
+        $coachId = $request->input('coach_id');
+        return $this->service->getCoachConfig($coachId);
+    }
+
+    /**
+     * 计算路费金额
+     */
+    public function calculateDeliveryFee(Request $request)
+    {
+        $coachId = $request->input('coach_id');
+        $agentId = $request->input('agent_id');
+        $distance = $request->input('distance');
+        $latitude = $request->input('latitude');
+        $longitude = $request->input('longitude');
+
+        if ($agentId) {
+            return $this->service->calculateDeliveryFee($coachId, $agentId, $distance);
+        } else {
+            return $this->service->calculateDeliveryFeeByLocation($coachId, $latitude, $longitude, $distance);
+        }
+    }
+
+    /**
+     * 计算订单金额
+     */
+    public function calculateOrderAmount(Request $request)
+    {
+        $userId = Auth::id();
+        $addressId = $request->input('address_id');
+        $coachId = $request->input('coach_id');
+        $projectId = $request->input('project_id');
+        $agentId = $request->input('agent_id');
+        $useBalance = $request->input('use_balance', 0);
+
+        return $this->service->calculateOrderAmount($userId, $addressId, $coachId, $projectId, $agentId, $useBalance);
+    }
+
+    /**
+     * 创建订单
+     */
+    public function create(Request $request)
+    {
+        $userId = Auth::id();
+        $projectId = $request->input('project_id');
+        $addressId = $request->input('address_id');
+        $coachId = $request->input('coach_id');
+        $useBalance = $request->input('use_balance', 0);
+        $orderId = $request->input('order_id');
+
+        return $this->service->createOrder($userId, $projectId, $addressId, $coachId, $useBalance, $orderId);
+    }
+
+    /**
+     * 加钟
+     */
+    public function addTime(Request $request, $orderId)
+    {
+        $userId = Auth::id();
+        return $this->service->addTime($userId, $orderId);
+    }
+
+    /**
+     * 指定技师
+     */
+    public function assignCoach(Request $request, $orderId)
+    {
+        $userId = Auth::id();
+        $coachId = $request->input('coach_id');
+        return $this->service->assignCoach($userId, $orderId, $coachId);
+    }
+
+    /**
+     * 获取代理商配置
+     */
+    public function getAgentConfig($agentId)
+    {
+        $agent = AgentInfo::where('id', $agentId)
+            ->where('state', 'enable')
+            ->firstOrFail();
+
+        $config = AgentConfig::where('agent_id', $agentId)->firstOrFail();
+
+        return [
+            'min_distance' => $config->min_distance,
+            'min_fee' => $config->min_fee,
+            'per_km_fee' => $config->per_km_fee
+        ];
+    }
+
+    /**
+     * 获取技师配置
+     */
+    public function getCoachConfig($coachId)
+    {
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->firstOrFail();
+
+        $config = CoachConfig::where('coach_id', $coachId)->firstOrFail();
+
+        return [
+            'delivery_fee_type' => $config->delivery_fee_type,
+            'charge_delivery_fee' => $config->charge_delivery_fee
+        ];
+    }
+
+    /**
+     * 计算路费金额
+     */
+    public function calculateDeliveryFee($coachId, $agentId, $distance)
+    {
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->firstOrFail();
+
+        $coachConfig = CoachConfig::where('coach_id', $coachId)->firstOrFail();
+
+        if (!$coachConfig->charge_delivery_fee) {
+            return 0;
+        }
+
+        $agentConfig = AgentConfig::where('agent_id', $agentId)->firstOrFail();
+
+        $fee = 0;
+        if ($distance <= $agentConfig->min_distance) {
+            $fee = $agentConfig->min_fee;
+        } else {
+            $extraDistance = $distance - $agentConfig->min_distance;
+            $fee = $agentConfig->min_fee + ($extraDistance * $agentConfig->per_km_fee);
+        }
+
+        return $coachConfig->delivery_fee_type == 'round_trip' ? $fee * 2 : $fee;
+    }
+
+    /**
+     * 计算订单金额
+     */
+    public function calculateOrderAmount($userId, $addressId, $coachId, $projectId, $agentId, $useBalance)
+    {
+        // 参数校验
+        $user = User::where('id', $userId)
+            ->where('status', 1)
+            ->firstOrFail();
+
+        $address = UserAddress::where('id', $addressId)
+            ->where('user_id', $userId)
+            ->firstOrFail();
+
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->firstOrFail();
+
+        $project = Project::where('id', $projectId)
+            ->where('state', 'enable')
+            ->firstOrFail();
+
+        // 计算金额
+        $projectAmount = $project->price;
+        $deliveryFee = $this->calculateDeliveryFee($coachId, $agentId, $address->distance);
+        $tipAmount = request()->has('order_id') ? Order::find(request()->input('order_id'))->tip_amount : 0;
+        
+        $couponAmount = 0;
+        if (request()->has('coupon_id')) {
+            $coupon = Coupon::where('id', request()->input('coupon_id'))
+                ->where('state', 'enable')
+                ->firstOrFail();
+            $couponAmount = $coupon->amount;
+        }
+
+        $totalAmount = $projectAmount + $deliveryFee + $tipAmount - $couponAmount;
+
+        $balanceAmount = 0;
+        $payAmount = $totalAmount;
+
+        if ($useBalance) {
+            $wallet = UserWallet::where('user_id', $userId)->first();
+            if ($wallet && $wallet->balance >= $totalAmount) {
+                $balanceAmount = $totalAmount;
+                $payAmount = 0;
+            } else if ($wallet) {
+                $balanceAmount = $wallet->balance;
+                $payAmount = $totalAmount - $balanceAmount;
+            }
+        }
+
+        return [
+            'total_amount' => $totalAmount,
+            'balance_amount' => $balanceAmount,
+            'pay_amount' => $payAmount,
+            'coupon_amount' => $couponAmount,
+            'tip_amount' => $tipAmount,
+            'project_amount' => $projectAmount,
+            'delivery_fee' => $deliveryFee
+        ];
+    }
+
+    /**
+     * 创建订单
+     */
+    public function createOrder($userId, $projectId, $addressId, $coachId, $useBalance, $orderId = null)
+    {
+        return DB::transaction(function() use ($userId, $projectId, $addressId, $coachId, $useBalance, $orderId) {
+            // 参数校验
+            $user = User::where('id', $userId)
+                ->where('status', 1)
+                ->firstOrFail();
+
+            $address = UserAddress::where('id', $addressId)
+                ->where('user_id', $userId)
+                ->firstOrFail();
+
+            if (!$orderId) {
+                $coach = CoachUser::where('id', $coachId)
+                    ->where('state', 'enable')
+                    ->where('auth_state', 'passed')
+                    ->firstOrFail();
+            }
+
+            $project = Project::where('id', $projectId)
+                ->where('state', 'enable')
+                ->firstOrFail();
+
+            // 创建订单
+            $orderType = $orderId ? 'add_time' : 'normal';
+            $amounts = $this->calculateOrderAmount($userId, $addressId, $coachId, $projectId, $project->agent_id, $useBalance);
+
+            $order = new Order();
+            $order->user_id = $userId;
+            $order->project_id = $projectId;
+            $order->address_id = $addressId;
+            $order->coach_id = $coachId;
+            $order->order_type = $orderType == 'normal' ? 0 : 1;
+            $order->status = 0;
+            $order->total_amount = $amounts['total_amount'];
+            $order->balance_amount = $amounts['balance_amount'];
+            $order->pay_amount = $amounts['pay_amount'];
+            $order->coupon_amount = $amounts['coupon_amount'];
+            $order->tip_amount = $amounts['tip_amount'];
+            $order->project_amount = $amounts['project_amount'];
+            $order->delivery_fee = $orderType == 'add_time' ? 0 : $amounts['delivery_fee'];
+            $order->payment_type = $useBalance && $amounts['pay_amount'] == 0 ? 0 : 1;
+            $order->save();
+
+            // 创建订单历史
+            if ($orderType == 'add_time') {
+                OrderHistory::create([
+                    'order_id' => $order->id,
+                    'type' => 'add_time',
+                    'user_id' => $userId
+                ]);
+            } else {
+                OrderHistory::create([
+                    'order_id' => $order->id,
+                    'type' => 'create',
+                    'user_id' => $userId
+                ]);
+            }
+
+            // 余额支付处理
+            if ($order->payment_type == 0) {
+                $order->status = 1;
+                $order->save();
+
+                OrderHistory::create([
+                    'order_id' => $order->id,
+                    'type' => 'pay',
+                    'user_id' => $userId
+                ]);
+
+                CoachSchedule::create([
+                    'coach_id' => $coachId,
+                    'date' => date('Y-m-d'),
+                    'status' => 'busy'
+                ]);
+
+                return $order->id;
+            }
+
+            // 微信支付处理
+            // TODO: 调用支付接口
+
+            return $order->id;
+        });
+    }
+
+    /**
+     * 加钟
+     */
+    public function addTime($userId, $orderId)
+    {
+        $order = Order::where('id', $orderId)
+            ->where('user_id', $userId)
+            ->firstOrFail();
+
+        return $this->createOrder($userId, $order->project_id, $order->address_id, $order->coach_id, 0, $orderId);
+    }
+
+    /**
+     * 指定技师
+     */
+    public function assignCoach($userId, $orderId, $coachId)
+    {
+        return DB::transaction(function() use ($userId, $orderId, $coachId) {
+            // 参数校验
+            $user = User::where('id', $userId)
+                ->where('status', 1)
+                ->firstOrFail();
+
+            $order = Order::where('id', $orderId)
+                ->where('user_id', $userId)
+                ->whereIn('status', [0, 1, 6])
+                ->firstOrFail();
+
+            $coach = CoachUser::where('id', $coachId)
+                ->where('state', 'enable')
+                ->where('auth_state', 'passed')
+                ->firstOrFail();
+
+            $schedule = CoachSchedule::where('coach_id', $coachId)
+                ->where('date', date('Y-m-d'))
+                ->where('status', 'free')
+                ->firstOrFail();
+
+            // 修改订单
+            $order->coach_id = $coachId;
+            if ($order->status == 0) {
+                $amounts = $this->calculateOrderAmount($userId, $order->address_id, $coachId, $order->project_id, $order->agent_id, $order->payment_type == 0);
+                
+                $order->total_amount = $amounts['total_amount'];
+                $order->balance_amount = $amounts['balance_amount'];
+                $order->pay_amount = $amounts['pay_amount'];
+                $order->coupon_amount = $amounts['coupon_amount'];
+                $order->tip_amount = $amounts['tip_amount'];
+                $order->project_amount = $amounts['project_amount'];
+                $order->delivery_fee = $amounts['delivery_fee'];
+
+                if ($order->payment_type == 0) {
+                    $order->status = 1;
+                }
+            }
+            if ($order->status == 1) {
+                $order->status = 2;
+            }
+            $order->save();
+
+            // 创建订单历史
+            OrderHistory::create([
+                'order_id' => $order->id,
+                'type' => 'assign_coach',
+                'user_id' => $userId,
+                'coach_id' => $coachId
+            ]);
+
+            OrderHistory::create([
+                'order_id' => $order->id,
+                'type' => 'accept',
+                'user_id' => $userId,
+                'coach_id' => $coachId,
+                'remark' => '抢单成功'
+            ]);
+
+            // 更新抢单池
+            GrabOrder::where('order_id', $orderId)
+                ->update(['status' => 2, 'coach_id' => $coachId]);
+
+            // 更新排班
+            $schedule->status = 'busy';
+            $schedule->save();
+
+            return true;
+        });
+    }
+} 

+ 26 - 0
app/Http/Controllers/Client/PaymentController.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\PaymentService;
+use Illuminate\Http\Request;
+
+class PaymentController extends Controller
+{
+    protected PaymentService $service;
+
+    public function __construct(PaymentService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取支付配置
+     */
+    public function getConfig(Request $request)
+    {
+        $orderId = $request->input('order_id');
+        return $this->service->getPaymentConfig($orderId);
+    }
+} 

+ 36 - 0
app/Http/Controllers/Client/ProjectController.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\ProjectService;
+use Illuminate\Http\Request;
+
+class ProjectController extends Controller
+{
+    protected ProjectService $service;
+
+    public function __construct(ProjectService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取项目详情
+     */
+    public function detail(Request $request, $id)
+    {
+        $areaCode = $request->input('area_code');
+        return $this->service->getProjectDetail($id, $areaCode);
+    }
+
+    /**
+     * 获取技师开通的项目列表
+     */
+    public function coachProjectList(Request $request)
+    {
+        $coachId = $request->input('coach_id');
+        $areaCode = $request->input('area_code');
+        return $this->service->getCoachProjectList($coachId, $areaCode);
+    }
+} 

+ 25 - 0
app/Http/Controllers/Client/TeamController.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\TeamService;
+use Illuminate\Http\Request;
+
+class TeamController extends Controller
+{
+    protected TeamService $service;
+
+    public function __construct(TeamService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取我的团队列表
+     */
+    public function list()
+    {
+        return $this->service->getTeamList();
+    }
+} 

+ 114 - 0
app/Http/Controllers/Client/UserController.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\UserService;
+use Illuminate\Http\Request;
+
+class UserController extends Controller
+{
+    protected UserService $service;
+
+    public function __construct(UserService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 发送验证码
+     */
+    public function sendVerifyCode(Request $request)
+    {
+        $mobile = $request->input('mobile');
+        return $this->service->sendVerifyCode($mobile);
+    }
+
+    /**
+     * 用户登录
+     */
+    public function login(Request $request)
+    {
+        $mobile = $request->input('mobile');
+        $code = $request->input('code');
+        return $this->service->login($mobile, $code);
+    }
+
+    /**
+     * 微信登录
+     */
+    public function wxLogin(Request $request)
+    {
+        $openid = $request->input('openid');
+        return $this->service->wxLogin($openid);
+    }
+
+    /**
+     * 用户退出
+     */
+    public function logout()
+    {
+        return $this->service->logout();
+    }
+
+    /**
+     * 获取用户信息
+     */
+    public function info()
+    {
+        return $this->service->getUserInfo();
+    }
+
+    /**
+     * 修改用户信息
+     */
+    public function updateInfo(Request $request)
+    {
+        $data = $request->all();
+        return $this->service->updateUserInfo($data);
+    }
+
+    /**
+     * 获取用户钱包
+     */
+    public function wallet()
+    {
+        return $this->service->getUserWallet();
+    }
+
+    /**
+     * 用户提现
+     */
+    public function withdraw(Request $request)
+    {
+        $amount = $request->input('amount');
+        return $this->service->withdraw($amount);
+    }
+
+    /**
+     * 用户注销
+     */
+    public function delete()
+    {
+        return $this->service->deleteAccount();
+    }
+
+    /**
+     * 用户反馈
+     */
+    public function feedback(Request $request)
+    {
+        $content = $request->input('content');
+        return $this->service->feedback($content);
+    }
+
+    /**
+     * 申请成为技师
+     */
+    public function applyCoach()
+    {
+        return $this->service->applyCoach();
+    }
+
+
+} 

+ 24 - 0
app/Http/Controllers/Client/WalletController.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Controllers\Client;
+
+use App\Http\Controllers\Controller;
+use App\Services\Client\WalletService;
+
+class WalletController extends Controller
+{
+    protected WalletService $service;
+
+    public function __construct(WalletService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * 获取钱包明细
+     */
+    public function records()
+    {
+        return $this->service->getWalletRecords();
+    }
+} 

+ 3 - 6
app/Models/MemberAddresse.php → app/Models/MemberAddress.php

@@ -6,14 +6,11 @@ use Illuminate\Database\Eloquent\SoftDeletes;
 use Slowlyo\OwlAdmin\Models\BaseModel as Model;
 
 /**
- * 用户地址管理
+ * 用户地址
  */
-class MemberAddresse extends Model
+class MemberAddress extends Model
 {
 	use SoftDeletes;
 
-	protected $table = 'member_addresses';
-
-
-	
+	protected $table = 'member_address';
 }

+ 2 - 2
app/Models/OrderInfo.php → app/Models/Order.php

@@ -8,9 +8,9 @@ use Slowlyo\OwlAdmin\Models\BaseModel as Model;
 /**
  * 订单
  */
-class OrderInfo extends Model
+class Order extends Model
 {
 	use SoftDeletes;
 
-	protected $table = 'order_infos';
+	protected $table = 'order';
 }

+ 2 - 2
app/Models/ProjectService.php → app/Models/Project.php

@@ -8,9 +8,9 @@ use Slowlyo\OwlAdmin\Models\BaseModel as Model;
 /**
  * 项目服务
  */
-class ProjectService extends Model
+class Project extends Model
 {
 	use SoftDeletes;
 
-	protected $table = 'project_service';
+	protected $table = 'project';
 }

+ 16 - 0
app/Models/SysConfig.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Slowlyo\OwlAdmin\Models\BaseModel as Model;
+
+/**
+ * 系统设置
+ */
+class SysConfig extends Model
+{
+	use SoftDeletes;
+
+	protected $table = 'sys_config';
+}

+ 112 - 0
app/Services/Client/AgentService.php

@@ -0,0 +1,112 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\AgentInfo;
+use App\Models\AgentConfig;
+use App\Models\Project;
+use Exception;
+
+class AgentService
+{
+    /**
+     * 获取代理商配置
+     */
+    public function getAgentConfig($agentId)
+    {
+        // 检查代理商是否存在
+        $agent = AgentInfo::where('id', $agentId)
+            ->where('state', 'enable')
+            ->firstOrFail();
+
+        // 获取代理商配置
+        $config = AgentConfig::where('agent_id', $agentId)->firstOrFail();
+
+        return [
+            'min_distance' => $config->min_distance,
+            'min_fee' => $config->min_fee,
+            'per_km_fee' => $config->per_km_fee
+        ];
+    }
+
+    /**
+     * 获取代理商
+     */
+    public function getAgent($areaCode)
+    {
+        // 根据区域编码查询代理商
+        $agent = AgentInfo::where('business_area', 'like', "%{$areaCode}%")
+            ->where('state', 'enable')
+            ->first();
+
+        if (!$agent) {
+            // 如果找不到,按照市、省、全国逐级查找
+            $areaCodeParts = str_split($areaCode, 2);
+            foreach ($areaCodeParts as $index => $part) {
+                $searchCode = implode('', array_slice($areaCodeParts, 0, $index + 1));
+                $agent = AgentInfo::where('business_area', 'like', "%{$searchCode}%")
+                    ->where('state', 'enable')
+                    ->first();
+                if ($agent) {
+                    break;
+                }
+            }
+        }
+
+        return $agent;
+    }
+
+    /**
+     * 获取代理商项目列表
+     */
+    public function getProjectList($categoryId, $agentId)
+    {
+        // 查询代理商
+        $agent = AgentInfo::where('id', $agentId)
+            ->where('state', 'enable')
+            ->firstOrFail();
+
+        // 查询项目列表
+        $query = Project::where('state', 'enable');
+
+        if ($categoryId) {
+            $query->where('category_id', $categoryId);
+        }
+
+        $projects = $query->whereHas('agents', function($q) use ($agentId) {
+                $q->where('agent_id', $agentId);
+            })
+            ->with(['category:id,name'])
+            ->orderBy('sort', 'desc')
+            ->paginate(10);
+
+        return $projects;
+    }
+
+    /**
+     * 获取代理商项目详情
+     */
+    public function getProjectDetail($projectId, $agentId)
+    {
+        // 查询代理商
+        $agent = AgentInfo::where('id', $agentId)
+            ->where('state', 'enable')
+            ->firstOrFail();
+
+        // 查询项目
+        $project = Project::where('id', $projectId)
+            ->where('state', 'enable')
+            ->whereHas('agents', function($q) use ($agentId) {
+                $q->where('agent_id', $agentId);
+            })
+            ->with([
+                'category:id,name',
+                'agents' => function($q) use ($agentId) {
+                    $q->where('agent_id', $agentId);
+                }
+            ])
+            ->firstOrFail();
+
+        return $project;
+    }
+} 

+ 74 - 0
app/Services/Client/CoachService.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\CoachUser;
+use App\Models\MemberUser;
+use App\Models\CoachLocation;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+
+class CoachService
+{
+    /**
+     * 获取技师列表
+     */
+    public function getCoachList($latitude, $longitude)
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::findOrFail($userId);
+        
+        // 检查用户状态
+        if ($user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+
+        // 获取附近的技师
+        $coaches = CoachUser::query()
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->with(['user:id,nickname,avatar,gender'])
+            ->with(['location'])
+            ->whereHas('location', function($query) use ($latitude, $longitude) {
+                // TODO: 实现经纬度范围查询
+                $query->where('state', 'enable');
+            })
+            ->paginate(10);
+            
+        return $coaches;
+    }
+
+    /**
+     * 获取技师详情
+     */
+    public function getCoachDetail($coachId, $latitude, $longitude)
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::findOrFail($userId);
+        
+        // 检查用户状态
+        if ($user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+
+        // 获取技师信息
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->with(['user:id,nickname,avatar,gender'])
+            ->with(['location'])
+            ->firstOrFail();
+
+        // TODO: 计算距离
+        $distance = 0;
+        if ($coach->location) {
+            // 实现距离计算逻辑
+        }
+
+        $coach->distance = $distance;
+        
+        return $coach;
+    }
+} 

+ 64 - 0
app/Services/Client/CommentService.php

@@ -0,0 +1,64 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\OrderComment;
+use App\Models\CoachUser;
+use App\Models\MemberUser;
+use Illuminate\Support\Facades\Auth;
+
+class CommentService
+{
+    /**
+     * 创建评价
+     */
+    public function createComment(int $coachId, string $content, int $rating)
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::findOrFail($userId);
+        
+        // 检查用户状态
+        if ($user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+        
+        // 检查技师是否存在
+        $coach = CoachUser::findOrFail($coachId);
+        
+        // 创建评价
+        $comment = new OrderComment();
+        $comment->user_id = $userId;
+        $comment->coach_id = $coachId;
+        $comment->content = $content;
+        $comment->rating = $rating;
+        $comment->state = 'enable';
+        $comment->save();
+        
+        return ['message' => '评价成功'];
+    }
+    
+    /**
+     * 获取评价列表
+     */
+    public function getCommentList(int $coachId)
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::findOrFail($userId);
+        
+        // 检查用户状态
+        if ($user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+        
+        // 获取评价列表
+        $comments = OrderComment::where('coach_id', $coachId)
+            ->where('state', 'enable')
+            ->orderBy('created_at', 'desc')
+            ->with(['user:id,nickname,avatar'])
+            ->paginate(10);
+            
+        return $comments;
+    }
+} 

+ 125 - 0
app/Services/Client/CommonService.php

@@ -0,0 +1,125 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\AgentInfo;
+use App\Models\AgentConfig;
+use App\Models\CoachConfig;
+use Exception;
+
+class CommonService
+{
+    /**
+     * 获取代理商配置
+     *
+     * @param int $agentId 代理商编号
+     * @return array
+     * @throws Exception
+     */
+    public function getAgentConfig($agentId)
+    {
+        // 检查代理商是否存在
+        $agent = AgentInfo::find($agentId);
+        if (!$agent) {
+            throw new Exception('代理商不存在');
+        }
+
+        // 获取代理商配置
+        $config = AgentConfig::where('agent_id', $agentId)->first();
+        if (!$config) {
+            throw new Exception('代理商配置不存在');
+        }
+
+        return [
+            'agent_id' => $config->agent_id,
+            'min_distance' => $config->min_distance, // 最小路程
+            'min_fee' => $config->min_fee, // 最小路费金额  
+            'per_km_fee' => $config->per_km_fee, // 每公里路程单价
+            'commission_rate' => $config->commission_rate, // 佣金比例
+            'created_at' => $config->created_at,
+            'updated_at' => $config->updated_at
+        ];
+    }
+
+    /**
+     * 获取技师配置
+     * 
+     * @param int $coachId 技师编号
+     * @return array
+     * @throws Exception
+     */
+    public function getCoachConfig($coachId) 
+    {
+        $config = CoachConfig::where('coach_id', $coachId)->first();
+        if (!$config) {
+            throw new Exception('技师配置不存在');
+        }
+
+        return [
+            'coach_id' => $config->coach_id,
+            'delivery_fee_enabled' => $config->delivery_fee_enabled, // 是否收取路费
+            'delivery_fee_type' => $config->delivery_fee_type, // 路费类型:单程/往返
+            'created_at' => $config->created_at,
+            'updated_at' => $config->updated_at
+        ];
+    }
+
+    /**
+     * 根据代理商ID计算路费
+     */
+    public function calculateDeliveryFee($coachId, $agentId, $distance)
+    {
+        // 获取技师配置
+        $coachConfig = $this->getCoachConfig($coachId);
+        
+        // 如果技师不收取路费
+        if (!$coachConfig['delivery_fee_enabled']) {
+            return 0;
+        }
+
+        // 获取代理商配置
+        $agentConfig = $this->getAgentConfig($agentId);
+        
+        // 计算单程路费
+        $onewayFee = $this->calculateOnewayFee($distance, $agentConfig);
+
+        // 根据技师配置返回单程或往返路费
+        return $coachConfig['delivery_fee_type'] == 'round_trip' ? $onewayFee * 2 : $onewayFee;
+    }
+
+    /**
+     * 根据位置计算路费
+     */
+    public function calculateDeliveryFeeByLocation($coachId, $latitude, $longitude, $distance)
+    {
+        // 根据经纬度查询代理商
+        $agent = AgentInfo::whereRaw("ST_Contains(business_area_polygon, ST_GeomFromText('POINT($longitude $latitude)'))")
+            ->first();
+            
+        if (!$agent) {
+            throw new Exception('该区域暂无代理商');
+        }
+
+        return $this->calculateDeliveryFee($coachId, $agent->id, $distance);
+    }
+
+    /**
+     * 计算单程路费
+     */
+    private function calculateOnewayFee($distance, $agentConfig)
+    {
+        // 如果路程小于等于最小路程
+        if ($distance <= $agentConfig['min_distance']) {
+            return $agentConfig['min_fee'];
+        }
+
+        // 超出的路程
+        $extraDistance = $distance - $agentConfig['min_distance'];
+        
+        // 计算超出部分的费用
+        $extraFee = $extraDistance * $agentConfig['per_km_fee'];
+        
+        // 返回总费用
+        return $agentConfig['min_fee'] + $extraFee;
+    }
+} 

+ 51 - 0
app/Services/Client/ExtendOrderService.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\Order;
+use App\Models\Project;
+use Exception;
+
+class ExtendOrderService
+{
+    /**
+     * 获取加钟项目列表
+     */
+    public function getProjectList($projectId)
+    {
+        // 查询项目
+        $project = Project::findOrFail($projectId);
+        
+        // 查询加钟分类的项目列表
+        $projects = Project::where('state', 'enable')
+            ->where('type', 'extend')
+            ->where('agent_id', $project->agent_id)
+            ->with(['category:id,name'])
+            ->orderBy('sort', 'desc')
+            ->get();
+
+        return $projects;
+    }
+
+    /**
+     * 加钟
+     */
+    public function extend($orderId)
+    {
+        // 查询原订单
+        $order = Order::where('id', $orderId)
+            ->where('user_id', auth()->id())
+            ->firstOrFail();
+
+        // 创建加钟订单
+        $orderService = app(OrderService::class);
+        return $orderService->createOrder(
+            $order->address_id,
+            $order->coach_id,
+            $order->project_id,
+            $order->agent_id,
+            $order->use_balance,
+            $orderId
+        );
+    }
+} 

+ 567 - 0
app/Services/Client/OrderService.php

@@ -0,0 +1,567 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\Order;
+use App\Models\OrderRecord;
+use App\Models\WalletRefundRecord;
+
+use App\Models\User;
+use App\Models\MemberAddress;
+use App\Models\CoachUser;
+use App\Models\Project;
+use App\Models\AgentInfo;
+use App\Models\AgentConfig;
+use App\Models\CoachConfig;
+use App\Models\Wallet;
+use App\Models\Coupon;
+use App\Models\CoachSchedule;
+use App\Models\MemberUser;
+use App\Models\OrderHistory;
+use App\Models\OrderGrabRecord;
+
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+use Exception;
+
+class OrderService
+{
+    protected AgentService $agentService;
+    protected ProjectService $projectService;
+    
+    public function __construct(
+        AgentService $agentService,
+        ProjectService $projectService
+    ) {
+        $this->agentService = $agentService;
+        $this->projectService = $projectService;
+    }
+
+     /**
+     * 订单初始化
+     */
+    public function initialize($userId, $coachId, $areaCode, $projectId)
+    {
+        // 查询用户钱包
+        $wallet = Wallet::where('user_id', $userId)->first();
+
+        // 查询默认地址
+        $address = MemberAddress::where('user_id', $userId)
+            ->where('is_default', 1)
+            ->first();
+
+        if ($address) {
+            $areaCode = $address->area_code;
+        }
+
+        // 查询技师数据
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->first();
+
+        // 查询技师排班
+        // $schedule = CoachSchedule::where('coach_id', $coachId)
+        //     ->where('date', date('Y-m-d'))
+        //     ->first();
+
+        // // 查询用户优惠券
+        // $coupons = Coupon::where('user_id', $userId)
+        //     ->where('state', 'enable')
+        //     ->where('expire_time', '>', now())
+        //     ->get();
+
+        // 获取代理商
+        $agent = $this->agentService->getAgent($areaCode);
+
+        // 获取项目详情
+        $project = $this->projectService->getProjectDetail($projectId, $agent->id);
+
+        // 计算订单金额
+        $amounts = $this->calculateOrderAmount($userId, $address->id, $coachId, $projectId, $agent->id);
+
+        return [
+            'wallet' => $wallet,
+            'coach' => $coach,
+            'project' => $project,
+            'address' => $address,
+            // 'schedule' => $schedule,
+            'amounts' => $amounts,
+            // 'coupons' => $coupons
+        ];
+    }
+
+    /**
+     * 结束订单
+     */
+    public function finishOrder($userId, $orderId)
+    {
+        return DB::transaction(function() use ($userId, $orderId) {
+            $order = Order::where('user_id', $userId)
+                ->where('id', $orderId)
+                ->first();
+
+            if (!$order) {
+                throw new Exception('订单不存在');
+            }
+
+            // 添加订单结束记录
+            OrderRecord::create([
+                'order_id' => $orderId,
+                'user_id' => $userId,
+                'state' => 'finish',
+                'remark' => '服务完成'
+            ]);
+
+            // 修改订单状态
+            $order->status = 'finished';
+            $order->save();
+
+            return ['message' => '订单已完成'];
+        });
+    }
+
+    /**
+     * 确认技师离开
+     */
+    public function confirmLeave($userId, $orderId)
+    {
+        return DB::transaction(function() use ($userId, $orderId) {
+            $order = Order::where('user_id', $userId)
+                ->where('id', $orderId)
+                ->first();
+
+            if (!$order) {
+                throw new Exception('订单不存在');
+            }
+
+            // 添加订单撤离记录
+            OrderRecord::create([
+                'order_id' => $orderId,
+                'user_id' => $userId,
+                'state' => 'leave',
+                'remark' => '技师已离开'
+            ]);
+
+            // 修改订单状态
+            $order->status = 'allow_leave';
+            $order->save();
+
+            return ['message' => '已确认技师离开'];
+        });
+    }
+
+    /**
+     * 取消订单
+     */
+    public function cancelOrder($userId, $orderId)
+    {
+        return DB::transaction(function() use ($userId, $orderId) {
+            $order = Order::where('user_id', $userId)
+                ->where('id', $orderId)
+                ->first();
+
+            if (!$order) {
+                throw new Exception('订单不存在');
+            }
+
+            // 添加订单取消记录
+            OrderRecord::create([
+                'order_id' => $orderId,
+                'user_id' => $userId,
+                'state' => 'cancel',
+                'remark' => '用户取消订单'
+            ]);
+
+            // 修改订单状态
+            $order->status = 'cancelled';
+            $order->save();
+
+            return ['message' => '订单已取消'];
+        });
+    }
+
+    /**
+     * 获取订单列表
+     */
+    public function getOrderList()
+    {
+        $userId = Auth::id();
+        
+        return Order::where('user_id', $userId)
+            ->with([
+                'project:id,title,cover,price',
+                'coach:id,name,avatar',
+                'agent:id,company_name',
+                'address:id,address'
+            ])
+            ->orderBy('created_at', 'desc')
+            ->paginate(10);
+    }
+
+    /**
+     * 获取订单详情
+     */
+    public function getOrderDetail($orderId)
+    {
+        $userId = Auth::id();
+
+        return Order::where('id', $orderId)
+            ->where('user_id', $userId)
+            ->with([
+                'project:id,title,cover,price,duration',
+                'coach:id,name,avatar,mobile',
+                'agent:id,company_name',
+                'address:id,address,latitude,longitude',
+                'records' => function($query) {
+                    $query->orderBy('created_at', 'asc');
+                }
+            ])
+            ->firstOrFail();
+    }
+
+    /**
+     * 订单退款
+     */
+    public function refundOrder($orderId)
+    {
+        $userId = Auth::id();
+
+        return DB::transaction(function() use ($orderId, $userId) {
+            // 查询并锁定订单
+            $order = Order::where('id', $orderId)
+                ->where('user_id', $userId)
+                ->where('state', 'pending')
+                ->lockForUpdate()
+                ->firstOrFail();
+
+            // 更新订单状态
+            $order->state = 'refunded';
+            $order->save();
+
+            // 添加订单记录
+            OrderRecord::create([
+                'order_id' => $orderId,
+                'object_id' => $userId,
+                'object_type' => 'user',
+                'state' => 'refund',
+                'remark' => '订单退款'
+            ]);
+
+            // 创建退款记录
+            WalletRefundRecord::create([
+                'order_id' => $orderId,
+                'user_id' => $userId,
+                'amount' => $order->total_amount,
+                'state' => 'success'
+            ]);
+
+            return ['message' => '退款成功'];
+        });
+    }
+
+     /**
+     * 获取代理商配置
+     */
+    public function getAgentConfig($agentId)
+    {
+        $agent = AgentInfo::where('id', $agentId)
+            ->where('state', 'enable')
+            ->firstOrFail();
+
+        // $config = AgentConfig::where('agent_id', $agentId)->firstOrFail();
+
+        return [
+            // 'min_distance' => $config->min_distance,
+            // 'min_fee' => $config->min_fee,
+            // 'per_km_fee' => $config->per_km_fee
+        ];
+    }
+
+    /**
+     * 获取技师配置
+     */
+    public function getCoachConfig($coachId)
+    {
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->firstOrFail();
+
+        // $config = CoachConfig::where('coach_id', $coachId)->firstOrFail();
+
+        return [
+            // 'delivery_fee_type' => $config->delivery_fee_type,
+            // 'charge_delivery_fee' => $config->charge_delivery_fee
+        ];
+    }
+
+    /**
+     * 计算路费金额
+     */
+    public function calculateDeliveryFee($coachId, $agentId, $distance)
+    {
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->firstOrFail();
+
+        $coachConfig = CoachConfig::where('coach_id', $coachId)->firstOrFail();
+
+        if (!$coachConfig->charge_delivery_fee) {
+            return 0;
+        }
+
+        $agentConfig = AgentConfig::where('agent_id', $agentId)->firstOrFail();
+
+        $fee = 0;
+        if ($distance <= $agentConfig->min_distance) {
+            $fee = $agentConfig->min_fee;
+        } else {
+            $extraDistance = $distance - $agentConfig->min_distance;
+            $fee = $agentConfig->min_fee + ($extraDistance * $agentConfig->per_km_fee);
+        }
+
+        return $coachConfig->delivery_fee_type == 'round_trip' ? $fee * 2 : $fee;
+    }
+
+    /**
+     * 计算订单金额
+     */
+    public function calculateOrderAmount($userId, $addressId, $coachId, $projectId, $agentId, $useBalance = false)
+    {
+        // 参数校验
+        $user = MemberUser::where('id', $userId)
+            ->where('status', 1)
+            ->firstOrFail();
+
+        $address = MemberAddress::where('id', $addressId)
+            ->where('user_id', $userId)
+            ->firstOrFail();
+
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->firstOrFail();
+
+        $project = Project::where('id', $projectId)
+            ->where('state', 'enable')
+            ->firstOrFail();
+
+        // 计算金额
+        $projectAmount = $project->price;
+        $deliveryFee = $this->calculateDeliveryFee($coachId, $agentId, $address->distance);
+        $tipAmount = request()->has('order_id') ? Order::find(request()->input('order_id'))->tip_amount : 0;
+        
+        $couponAmount = 0;
+        if (request()->has('coupon_id')) {
+            // $coupon = Coupon::where('id', request()->input('coupon_id'))
+            //     ->where('state', 'enable')
+            //     ->firstOrFail();
+            // $couponAmount = $coupon->amount;
+        }
+
+        $totalAmount = $projectAmount + $deliveryFee + $tipAmount - $couponAmount;
+
+        $balanceAmount = 0;
+        $payAmount = $totalAmount;
+
+        if ($useBalance) {
+            $wallet = Wallet::where('user_id', $userId)->first();
+            if ($wallet && $wallet->balance >= $totalAmount) {
+                $balanceAmount = $totalAmount;
+                $payAmount = 0;
+            } else if ($wallet) {
+                $balanceAmount = $wallet->balance;
+                $payAmount = $totalAmount - $balanceAmount;
+            }
+        }
+
+        return [
+            'total_amount' => $totalAmount,
+            'balance_amount' => $balanceAmount,
+            'pay_amount' => $payAmount,
+            'coupon_amount' => $couponAmount,
+            'tip_amount' => $tipAmount,
+            'project_amount' => $projectAmount,
+            'delivery_fee' => $deliveryFee
+        ];
+    }
+
+    /**
+     * 创建订单
+     */
+    public function createOrder($userId, $projectId, $addressId, $coachId, $useBalance, $orderId = null)
+    {
+        return DB::transaction(function() use ($userId, $projectId, $addressId, $coachId, $useBalance, $orderId) {
+            // 参数校验
+            $user = MemberUser::where('id', $userId)
+                ->where('status', 1)
+                ->firstOrFail();
+
+            $address = MemberAddress::where('id', $addressId)
+                ->where('user_id', $userId)
+                ->firstOrFail();
+
+            if (!$orderId) {
+                $coach = CoachUser::where('id', $coachId)
+                    ->where('state', 'enable')
+                    ->where('auth_state', 'passed')
+                    ->firstOrFail();
+            }
+
+            $project = Project::where('id', $projectId)
+                ->where('state', 'enable')
+                ->firstOrFail();
+
+            // 创建订单
+            $orderType = $orderId ? 'add_time' : 'normal';
+            $amounts = $this->calculateOrderAmount($userId, $addressId, $coachId, $projectId, $project->agent_id, $useBalance);
+
+            $order = new Order();
+            $order->user_id = $userId;
+            $order->project_id = $projectId;
+            $order->address_id = $addressId;
+            $order->coach_id = $coachId;
+            $order->order_type = $orderType == 'normal' ? 0 : 1;
+            $order->status = 0;
+            $order->total_amount = $amounts['total_amount'];
+            $order->balance_amount = $amounts['balance_amount'];
+            $order->pay_amount = $amounts['pay_amount'];
+            $order->coupon_amount = $amounts['coupon_amount'];
+            $order->tip_amount = $amounts['tip_amount'];
+            $order->project_amount = $amounts['project_amount'];
+            $order->delivery_fee = $orderType == 'add_time' ? 0 : $amounts['delivery_fee'];
+            $order->payment_type = $useBalance && $amounts['pay_amount'] == 0 ? 0 : 1;
+            $order->save();
+
+            // 创建订单历史
+            if ($orderType == 'add_time') {
+                OrderRecord::create([
+                    'order_id' => $order->id,
+                    'type' => 'add_time',
+                    'user_id' => $userId
+                ]);
+            } else {
+                OrderRecord::create([
+                    'order_id' => $order->id,
+                    'type' => 'create',
+                    'user_id' => $userId
+                ]);
+            }
+
+            // 余额支付处理
+            if ($order->payment_type == 'balance') {
+                $order->status = 'paid';
+                $order->save();
+
+                OrderRecord::create([
+                    'order_id' => $order->id,
+                    'type' => 'pay',
+                    'user_id' => $userId
+                ]);
+
+                // CoachSchedule::create([
+                //     'coach_id' => $coachId,
+                //     'date' => date('Y-m-d'),
+                //     'status' => 'busy'
+                // ]);
+
+                return $order->id;
+            }
+
+            // 微信支付处理
+            // TODO: 调用支付接口
+
+            return $order->id;
+        });
+    }
+
+    /**
+     * 加钟
+     */
+    public function addTime($userId, $orderId)
+    {
+        $order = Order::where('id', $orderId)
+            ->where('user_id', $userId)
+            ->firstOrFail();
+
+        return $this->createOrder($userId, $order->project_id, $order->address_id, $order->coach_id, 0, $orderId);
+    }
+
+    /**
+     * 指定技师
+     */
+    public function assignCoach($userId, $orderId, $coachId)
+    {
+        return DB::transaction(function() use ($userId, $orderId, $coachId) {
+            // 参数校验
+            $user = MemberUser::where('id', $userId)
+                ->where('status', 'enable')
+                ->firstOrFail();
+
+            $order = Order::where('id', $orderId)
+                ->where('user_id', $userId)
+                ->whereIn('status', [0, 1, 6])
+                ->firstOrFail();
+
+            $coach = CoachUser::where('id', $coachId)
+                ->where('state', 'enable')
+                ->where('auth_state', 'passed')
+                ->firstOrFail();
+
+            // $schedule = CoachSchedule::where('coach_id', $coachId)
+            //     ->where('date', date('Y-m-d'))
+            //     ->where('status', 'free')
+            //     ->firstOrFail();
+
+            // 修改订单
+            $order->coach_id = $coachId;
+            if ($order->status == 'created') {
+                $amounts = $this->calculateOrderAmount($userId, $order->address_id, $coachId, $order->project_id, $order->agent_id, $order->payment_type == 'balance');
+                
+                $order->total_amount = $amounts['total_amount'];
+                $order->balance_amount = $amounts['balance_amount'];
+                $order->pay_amount = $amounts['pay_amount'];
+                $order->coupon_amount = $amounts['coupon_amount'];
+                $order->tip_amount = $amounts['tip_amount'];
+                $order->project_amount = $amounts['project_amount'];
+                $order->delivery_fee = $amounts['delivery_fee'];
+
+                if ($order->payment_type == 'balance') {
+                    $order->status = 'paid';
+                }
+            }
+            if ($order->status == 'paid') {
+                $order->status = 'assigned';
+            }
+            $order->save();
+
+            // 创建订单历史
+            OrderRecord::create([
+                'order_id' => $order->id,
+                'type' => 'assigned',
+                'user_id' => $userId,
+                'coach_id' => $coachId
+            ]);
+
+            OrderRecord::create([
+                'order_id' => $order->id,
+                'type' => 'accepted',
+                'user_id' => $userId,
+                'coach_id' => $coachId,
+                'remark' => '抢单成功'
+            ]);
+
+            // 更新抢单池
+            OrderGrabRecord::where('order_id', $orderId)
+                ->update(['status' => 'success', 'coach_id' => $coachId]);
+
+            // 更新排班
+            // $schedule->status = 'busy';
+            // $schedule->save();
+
+            return true;
+        });
+    }
+} 

+ 76 - 0
app/Services/Client/PaymentService.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\Order;
+use App\Models\MemberUser;
+use Illuminate\Support\Facades\Auth;
+use Exception;
+
+class PaymentService
+{
+    /**
+     * 获取支付配置
+     *
+     * @param int $orderId 订单编号
+     * @return array
+     * @throws Exception
+     */
+    public function getPaymentConfig($orderId)
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::where('state', 'enable')->findOrFail($userId);
+
+        // 查询订单
+        $order = Order::where('id', $orderId)
+            ->where('user_id', $userId)
+            ->where('state', 'unpaid')
+            ->firstOrFail();
+
+        // 生成微信支付配置
+        $outTradeNo = $this->generateOutTradeNo();
+        $config = $this->generateWxPayConfig($order, $outTradeNo);
+
+        // 更新订单外部交易号
+        $order->out_trade_no = $outTradeNo;
+        $order->save();
+
+        // 发送抢单通知
+        $this->sendGrabOrderNotification($order);
+
+        return $config;
+    }
+
+    /**
+     * 生成外部交易号
+     */
+    private function generateOutTradeNo()
+    {
+        return date('YmdHis') . mt_rand(1000, 9999);
+    }
+
+    /**
+     * 生成微信支付配置
+     */
+    private function generateWxPayConfig($order, $outTradeNo)
+    {
+        // TODO: 对接微信支付,生成JSAPI支付配置
+        return [
+            'appId' => config('wechat.payment.app_id'),
+            'timeStamp' => time(),
+            'nonceStr' => uniqid(),
+            'package' => 'prepay_id=xxx',
+            'signType' => 'MD5',
+            'paySign' => 'xxx'
+        ];
+    }
+
+    /**
+     * 发送抢单通知
+     */
+    private function sendGrabOrderNotification($order)
+    {
+        // TODO: 对接极光推送,发送抢单通知
+    }
+} 

+ 77 - 0
app/Services/Client/ProjectService.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\CoachUser;
+use App\Models\ShopCoachService;
+use App\Models\Project;
+use Illuminate\Support\Facades\DB;
+
+class ProjectService
+{
+
+    /**
+     * 获取项目详情
+     */
+    public function getProjectDetail($projectId, $areaCode)
+    {
+        // 根据区域代码获取代理商
+        $agent = AgentInfo::where('business_area', 'like', "%{$areaCode}%")
+            ->where('state', 'enable')
+            ->first();
+            
+        if (!$agent) {
+            throw new \Exception('该区域暂无代理商');
+        }
+
+        // 获取项目详情
+        $project = Project::where('id', $projectId)
+            ->where('state', 'enable')
+            ->where(function($query) use ($areaCode) {
+                // 根据区域地址过滤项目
+                $query->where('area_code', $areaCode);
+            })
+            ->with([
+                'category:id,name',
+                'agent' => function($query) use ($agent) {
+                    $query->where('id', $agent->id);
+                }
+            ])
+            ->firstOrFail();
+
+        return $project;
+    }
+    
+    /**
+     * 获取技师开通的项目列表
+     */
+    public function getCoachProjectList($coachId, $areaCode)
+    {
+        // 查询技师信息
+        $coach = CoachUser::where('id', $coachId)
+            ->where('state', 'enable')
+            ->where('auth_state', 'passed')
+            ->firstOrFail();
+
+        // 获取技师开通的项目ID列表
+        $projectIds = ShopCoachService::where('coach_id', $coachId)
+            ->where('state', 'enable')
+            ->pluck('shop_service_id');
+
+        // 查询项目列表
+        $projects = Project::whereIn('id', $projectIds)
+            ->where('state', 'enable')
+            ->where(function($query) use ($areaCode) {
+                // TODO: 根据区域地址过滤项目
+                $query->where('area_code', $areaCode);
+            })
+            ->with([
+                'category:id,name',
+                // 其他关联
+            ])
+            ->orderBy('sort', 'desc')
+            ->paginate(10);
+
+        return $projects;
+    }
+} 

+ 36 - 0
app/Services/Client/TeamService.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\CoachUser;
+use App\Models\MemberUser;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+
+class TeamService
+{
+
+    /**
+     * 获取团队列表
+     */
+    public function getTeamList()
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::findOrFail($userId);
+        
+        // 检查用户状态
+        if ($user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+        
+        // 获取下级用户列表
+        $teamList = MemberUser::where('parent_id', $userId)
+            ->where('state', 'enable')
+            ->with(['coachUser'])  // 关联技师信息
+            ->orderBy('created_at', 'desc')
+            ->paginate(10);
+            
+        return $teamList;
+    }
+} 

+ 252 - 0
app/Services/Client/UserService.php

@@ -0,0 +1,252 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\MemberUser;
+use App\Models\MemberSocialAccount;
+use App\Models\SysConfig;
+use App\Models\Wallet;
+use App\Models\CoachUser;
+use App\Models\WalletWithdrawRecord;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
+
+class UserService
+{
+    /**
+     * 发送验证码
+     */
+    public function sendVerifyCode(string $mobile)
+    {
+        // 生成验证码
+        $code = mt_rand(100000, 999999);
+        
+        // 保存验证码到缓存
+        Cache::put("verify_code:{$mobile}", $code, 300);
+        
+        // TODO: 调用短信服务发送验证码
+        
+        return ['code' => $code];
+    }
+
+    /**
+     * 用户登录
+     */
+    public function login(string $mobile, string $code)
+    {
+        // 验证验证码
+        $cacheCode = Cache::get("verify_code:{$mobile}");
+        if (!$cacheCode || $cacheCode != $code) {
+            throw new \Exception('验证码错误');
+        }
+
+        // 查找或创建用户
+        $user = MemberUser::firstOrCreate(
+            ['mobile' => $mobile],
+            [
+                'state' => 'enable',
+                'register_area' => request()->header('area_code')
+            ]
+        );
+
+        // 生成token
+        $token = $user->createToken('auth-token')->plainTextToken;
+
+        return [
+            'token' => $token,
+            'user' => $user
+        ];
+    }
+
+    /**
+     * 微信登录
+     */
+    public function wxLogin(string $openid)
+    {
+        // 查找或创建微信用户
+        $socialAccount = MemberSocialAccount::firstOrCreate(
+            [
+                'platform' => 'WECHAT',
+                'social_id' => $openid
+            ]
+        );
+
+        $user = $socialAccount->user;
+        if (!$user) {
+            $user = MemberUser::create([
+                'state' => 'enable',
+                'register_area' => request()->header('area_code')
+            ]);
+            $socialAccount->update(['user_id' => $user->id]);
+        }
+
+        // 生成token
+        $token = $user->createToken('auth-token')->plainTextToken;
+
+        return [
+            'token' => $token,
+            'user' => $user
+        ];
+    }
+
+    /**
+     * 用户退出
+     */
+    public function logout()
+    {
+        Auth::user()->tokens()->delete();
+        return ['message' => '退出成功'];
+    }
+
+    /**
+     * 获取用户信息
+     */
+    public function getUserInfo()
+    {
+        $user = Auth::user();
+        $wallet = Wallet::where('owner_id', $user->id)
+            ->where('owner_type', 'USER')
+            ->first();
+
+        return [
+            'user' => $user,
+            'wallet' => $wallet ? [
+                'id' => $wallet->id,
+                'balance' => $wallet->available_balance
+            ] : null
+        ];
+    }
+
+    /**
+     * 修改用户信息
+     */
+    public function updateUserInfo(array $data)
+    {
+        $user = Auth::user();
+        $user->update($data);
+        return ['message' => '修改成功'];
+    }
+
+    /**
+     * 获取用户钱包
+     */
+    public function getUserWallet()
+    {
+        $wallet = Wallet::where('owner_id', Auth::id())
+            ->where('owner_type', MemberUser::class)
+            ->first();
+
+        if (!$wallet) {
+            throw new \Exception('钱包不存在');
+        }
+
+        return $wallet;
+    }
+
+    /**
+     * 用户提现
+     */
+    public function withdraw($amount)
+    {
+        // 获取当前用户
+        $user = Auth::user();
+        if (!$user || $user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+        
+        $config = SysConfig::where('key', 'withdraw_min_amount')->first();
+        $configValue = json_decode($config->value, true);
+        $minAmount = $configValue['minAmount'];
+        $maxAmount = $configValue['maxAmount'];
+        $fee = $configValue['fee'];
+        
+        if ($amount < $minAmount) {
+            throw new \Exception("提现金额不能小于{$minAmount}元");
+        }
+        
+        if ($amount > $maxAmount) {
+            throw new \Exception("提现金额不能大于{$maxAmount}元"); 
+        }
+
+        // 创建提现记录
+        DB::transaction(function() use ($user, $amount, $fee) {
+            WalletWithdrawRecord::create([
+                'user_id' => $user->id,
+                'amount' => $amount,
+                'fee' => $fee,
+                'type' => MemberUser::class,
+                'state' => 'pending'
+            ]);
+        });
+
+        return ['message' => '提现申请已提交'];
+    }
+
+    /**
+     * 用户注销
+     */
+    public function deleteAccount()
+    {
+        $user = Auth::user();
+        if (!$user || $user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+
+        $user->state = 'disable';
+        $user->save();
+        $user->delete();
+
+        return ['message' => '账号已注销'];
+    }
+
+    /**
+     * 用户反馈
+     */
+    public function feedback($content)
+    {
+        $user = Auth::user();
+        if (!$user || $user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+
+        // UserFeedback::create([
+        //     'owner_id' => $user->id,
+        //     'owner_type' => MemberUser::class,
+        //     'content' => $content
+        // ]);
+
+        return ['message' => '反馈已提交'];
+    }
+
+        /**
+     * 申请成为技师
+     */
+    public function applyCoach()
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::findOrFail($userId);
+        
+        // 检查用户状态
+        if ($user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+        
+        // 检查是否已经是技师
+        $exists = CoachUser::where('user_id', $userId)->exists();
+        if ($exists) {
+            throw new \Exception('您已经是技师了');
+        }
+        
+        // 创建技师申请
+        DB::transaction(function() use ($userId) {
+            CoachUser::create([
+                'user_id' => $userId,
+                'state' => 'pending'  // 待审核状态
+            ]);
+        });
+        
+        return ['message' => '申请已提交'];
+    }
+} 

+ 33 - 0
app/Services/Client/WalletService.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Services\Client;
+
+use App\Models\MemberUser;
+use App\Models\WalletTransRecord;
+use Illuminate\Support\Facades\Auth;
+
+class WalletService
+{
+    /**
+     * 获取钱包明细
+     */
+    public function getWalletRecords()
+    {
+        // 获取当前用户
+        $userId = Auth::id();
+        $user = MemberUser::findOrFail($userId);
+        
+        // 检查用户状态
+        if ($user->state !== 'enable') {
+            throw new \Exception('用户状态异常');
+        }
+
+        // 获取钱包交易记录
+        $records = WalletTransRecord::where('wallet_id', $user->wallet->id)
+            ->where('state', 'enable')
+            ->orderBy('created_at', 'desc')
+            ->paginate(10);
+            
+        return $records;
+    }
+} 

+ 17 - 0
app/Services/MemberAddressService.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\MemberAddress;
+use Slowlyo\OwlAdmin\Services\AdminService;
+
+/**
+ * 用户地址
+ *
+ * @method MemberAddress getModel()
+ * @method MemberAddress|\Illuminate\Database\Query\Builder query()
+ */
+class MemberAddressService extends AdminService
+{
+	protected string $modelName = MemberAddress::class;
+}

+ 17 - 0
app/Services/ProjectService.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\Project;
+use Slowlyo\OwlAdmin\Services\AdminService;
+
+/**
+ * 项目服务
+ *
+ * @method Project getModel()
+ * @method Project|\Illuminate\Database\Query\Builder query()
+ */
+class ProjectService extends AdminService
+{
+	protected string $modelName = Project::class;
+}

+ 0 - 17
app/Services/ProjectServiceService.php

@@ -1,17 +0,0 @@
-<?php
-
-namespace App\Services;
-
-use App\Models\ProjectService;
-use Slowlyo\OwlAdmin\Services\AdminService;
-
-/**
- * 项目服务
- *
- * @method ProjectService getModel()
- * @method ProjectService|\Illuminate\Database\Query\Builder query()
- */
-class ProjectServiceService extends AdminService
-{
-	protected string $modelName = ProjectService::class;
-}

+ 17 - 0
app/Services/SysConfigService.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\SysConfig;
+use Slowlyo\OwlAdmin\Services\AdminService;
+
+/**
+ * 系统设置
+ *
+ * @method SysConfig getModel()
+ * @method SysConfig|\Illuminate\Database\Query\Builder query()
+ */
+class SysConfigService extends AdminService
+{
+	protected string $modelName = SysConfig::class;
+}

+ 2 - 2
database/migrations/2024_11_14_061044_create_order_infos_table.php → database/migrations/2024_11_14_061044_create_order_table.php

@@ -13,7 +13,7 @@ return new class extends Migration
      */
     public function up()
     {
-        Schema::create('order_infos', function (Blueprint $table) {
+        Schema::create('order', function (Blueprint $table) {
             $table->comment('订单');
             $table->increments('id');
             $table->unsignedBigInteger('user_id')->comment('用户编号');
@@ -49,6 +49,6 @@ return new class extends Migration
      */
     public function down()
     {
-        Schema::dropIfExists('order_infos');
+        Schema::dropIfExists('order');
     }
 };

+ 27 - 0
database/migrations/2024_11_14_120000_create_user_feedbacks_table.php

@@ -0,0 +1,27 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    public function up()
+    {
+        Schema::create('user_feedbacks', function (Blueprint $table) {
+            $table->comment('用户反馈');
+            $table->increments('id');
+            $table->unsignedBigInteger('owner_id')->comment('用户编号');
+            $table->string('owner_type')->comment('用户类型');
+            $table->text('content')->comment('反馈内容');
+            $table->string('state')->default('enable')->comment('状态');
+            $table->timestamps();
+            $table->softDeletes();
+        });
+    }
+
+    public function down()
+    {
+        Schema::dropIfExists('user_feedbacks');
+    }
+}; 

+ 2 - 2
database/migrations/2024_11_14_111905_create_project_service_table.php → database/migrations/2024_11_18_040034_create_project_table.php

@@ -13,7 +13,7 @@ return new class extends Migration
      */
     public function up()
     {
-        Schema::create('project_service', function (Blueprint $table) {
+        Schema::create('project', function (Blueprint $table) {
             $table->comment('项目服务');
             $table->increments('id');
             $table->unsignedBigInteger('cate_id')->comment('项目分类编号');
@@ -40,6 +40,6 @@ return new class extends Migration
      */
     public function down()
     {
-        Schema::dropIfExists('project_service');
+        Schema::dropIfExists('project');
     }
 };

+ 3 - 3
database/migrations/2024_11_14_024847_create_member_addresses_table.php → database/migrations/2024_11_18_051648_create_member_address_table.php

@@ -13,8 +13,8 @@ return new class extends Migration
      */
     public function up()
     {
-        Schema::create('member_addresses', function (Blueprint $table) {
-            $table->comment('用户地址管理');
+        Schema::create('member_address', function (Blueprint $table) {
+            $table->comment('用户地址');
             $table->increments('id');
             $table->unsignedBigInteger('user_id')->comment('用户编号');
             $table->string('location')->default('')->comment('定位地址');
@@ -38,6 +38,6 @@ return new class extends Migration
      */
     public function down()
     {
-        Schema::dropIfExists('member_addresses');
+        Schema::dropIfExists('member_address');
     }
 };

+ 35 - 0
database/migrations/2024_11_18_063954_create_sys_config_table.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('sys_config', function (Blueprint $table) {
+            $table->comment('系统设置');
+            $table->increments('id');
+            $table->string('key')->default('')->comment('配置项');
+            $table->json('value')->comment('配置值');
+            $table->timestamps();
+            $table->softDeletes();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('sys_config');
+    }
+};

+ 6 - 4
routes/admin.php

@@ -22,7 +22,7 @@ Route::group([
     // 用户社交账号
     $router->resource('member_social_accounts', \App\Admin\Controllers\MemberSocialAccountController::class);
     // 用户地址
-    $router->resource('member_addresses', \App\Admin\Controllers\MemberAddresseController::class);
+    $router->resource('member_address', \App\Admin\Controllers\MemberAddressController::class);
     // 用户实名认证记录
     $router->resource('member_real_auth_records', \App\Admin\Controllers\MemberRealAuthRecordController::class);
     // 技师
@@ -35,8 +35,6 @@ Route::group([
     $router->resource('coach_scores', \App\Admin\Controllers\CoachScoreController::class);
     // 技师定位
     $router->resource('coach_locations', \App\Admin\Controllers\CoachLocationController::class);
-    // 订单
-    $router->resource('order_infos', \App\Admin\Controllers\OrderInfoController::class);
     // 订单异常记录
     $router->resource('order_exc_records', \App\Admin\Controllers\OrderExcRecordController::class);
     // 订单记录
@@ -66,7 +64,7 @@ Route::group([
     // 项目分类
     $router->resource('project_cate', \App\Admin\Controllers\ProjectCateController::class);
     // 项目服务
-    $router->resource('project_service', \App\Admin\Controllers\ProjectServiceController::class);
+    $router->resource('project', \App\Admin\Controllers\ProjectController::class);
     // 店铺服务
     $router->resource('shop_services', \App\Admin\Controllers\ShopServiceController::class);
     // 店铺技师服务项目
@@ -77,5 +75,9 @@ Route::group([
     $router->resource('agent_info_records', \App\Admin\Controllers\AgentInfoRecordController::class);
     // 代理商实名认证记录
     $router->resource('agent_real_auth_records', \App\Admin\Controllers\AgentRealAuthRecordController::class);
+    // 行政区划
+    $router->resource('sys_region', \App\Admin\Controllers\SysRegionController::class);
+    // 系统设置
+    $router->resource('sys_config', \App\Admin\Controllers\SysConfigController::class);
 
 });