all(); $list = $this->model->with('user')->where(function ($query) use ($all) { if (isset($all['filter']) && !empty($all['filter'])) { foreach ($all['filter'] as $condition) { $key = $condition['key'] ?? null; $op = $condition['op'] ?? null; $value = $condition['value'] ?? null; if (!isset($key) || !isset($op) || !isset($value)) { continue; } // 等于 if ($op == 'eq') { $query->where($key, $value); } // 不等于 if ($op == 'neq') { $query->where($key, '!=', $value); } // 大于 if ($op == 'gt') { $query->where($key, '>', $value); } // 大于等于 if ($op == 'egt') { $query->where($key, '>=', $value); } // 小于 if ($op == 'lt') { $query->where($key, '<', $value); } // 小于等于 if ($op == 'elt') { $query->where($key, '<=', $value); } // 模糊搜索 if ($op == 'like') { $query->where($key, 'like', '%' . $value . '%'); } // 否定模糊搜索 if ($op == 'notlike') { $query->where($key, 'not like', '%' . $value . '%'); } // 范围搜索 if ($op == 'range') { list($from, $to) = explode(',', $value); if (empty($from) || empty($to)) { continue; } $query->whereBetween($key, [$from, $to]); } } } })->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc'); if (isset($all['is_export']) && !empty($all['is_export'])) { $list = $list->limit(5000)->get()->toArray(); return Excel::download(new CommonExport($list, $all['export_fields'] ?? ''), $all['file_name'] ?? '' . date('YmdHis') . '.xlsx'); } else { // 输出 $list = $list->paginate($all['page_size'] ?? 20); } return $this->success($list); } /** * @OA\Get( * path="/api/admin/supply-demand/show", * tags={"供需信息管理"}, * summary="详情", * description="", * @OA\Parameter(name="id", in="query", @OA\Schema(type="string"), required=true, description="id"), * @OA\Parameter(name="show_relation", in="query", @OA\Schema(type="string"), required=false, description="需要输出的关联关系数组,填写输出指定数据"), * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Response( * response="200", * description="暂无" * ) * ) */ public function show() { $all = \request()->all(); $messages = [ 'id.required' => 'Id必填', ]; $validator = Validator::make($all, [ 'id' => 'required' ], $messages); if ($validator->fails()) { return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); } $detail = $this->model->with('user')->find($all['id']); return $this->success($detail); } /** * @OA\Post( * path="/api/admin/supply-demand/save", * tags={"供需信息管理"}, * summary="更新或新增", * @OA\Parameter(name="id", in="query", @OA\Schema(type="integer"), required=false, description="需求供应表ID(存在则更新,不存在则新增)"), * @OA\Parameter(name="title", in="query", @OA\Schema(type="string"), required=false, description="标题"), * @OA\Parameter(name="supply_demand_type_id", in="query", @OA\Schema(type="integer"), required=false, description="分类ID"), * @OA\Parameter(name="content", in="query", @OA\Schema(type="string"), required=false, description="内容"), * @OA\Parameter(name="tag", in="query", @OA\Schema(type="string"), required=false, description="标签"), * @OA\Parameter(name="wechat", in="query", @OA\Schema(type="string"), required=false, description="微信号"), * @OA\Parameter(name="mobile", in="query", @OA\Schema(type="string"), required=false, description="电话"), * @OA\Parameter(name="email", in="query", @OA\Schema(type="string"), required=false, description="邮箱"), * @OA\Parameter(name="status", in="query", @OA\Schema(type="integer"), required=false, description="状态0待审核1通过2拒绝3退回修改4永久隐藏"), * @OA\Response( * response=200, * description="操作成功" * ) * ) */ public function save() { return parent::save(); } /** * @OA\Get( * path="/api/admin/supply-demand/destroy", * tags={"供需信息管理"}, * summary="删除", * description="", * @OA\Parameter(name="id", in="query", @OA\Schema(type="string"), required=true, description="id"), * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Response( * response="200", * description="暂无" * ) * ) */ public function destroy() { return parent::destroy(); } /** * @OA\Get( * path="/api/admin/supply-demand/chart", * tags={"供需信息管理"}, * summary="交互统计", * description="", * @OA\Parameter(name="start_date", in="query", @OA\Schema(type="string"), required=true, description="开始日期"), * @OA\Parameter(name="end_date", in="query", @OA\Schema(type="string"), required=true, description="结束日期"), * @OA\Parameter(name="type", in="query", @OA\Schema(type="string"), required=true, description="type类型"), * @OA\Parameter(name="page_size", in="query", @OA\Schema(type="string"), required=false, description="每页显示的条数"), * @OA\Parameter(name="page", in="query", @OA\Schema(type="string"), required=false, description="页码"), * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Response( * response="200", * description="暂无" * ) * ) */ public function chart() { $now = date('Y-m-d'); $startDate = request('start_date', $now); $endDate = request('end_date', $now); $type = request('type'); // 计算上期时间段(与当前时间段长度相同) $daysDiff = (strtotime($endDate) - strtotime($startDate)) / (60 * 60 * 24) + 1; $prevEndDate = date('Y-m-d', strtotime($startDate) - 1); $prevStartDate = date('Y-m-d', strtotime($prevEndDate) - $daysDiff + 1); // 当期供需发布数 $supplyDemand = SupplyDemand::where(function ($query) use ($type) { if ($type) { $query->where('type', $type); } })->whereBetween('created_at', [$startDate, $endDate]) ->get(); $supplyDemandCount = $supplyDemand->count(); // 上期供需发布数 $prevSupplyDemandCount = SupplyDemand::where(function ($query) use ($type) { if ($type) { $query->where('type', $type); } })->whereBetween('created_at', [$prevStartDate, $prevEndDate]) ->count(); // 当期私信数量 $messageCount = Message::whereIn('supply_demand_id', $supplyDemand->pluck('id'))->count(); // 上期私信数量 $prevSupplyDemand = SupplyDemand::where(function ($query) use ($type) { if ($type) { $query->where('type', $type); } })->whereBetween('created_at', [$prevStartDate, $prevEndDate]) ->get(); $prevMessageCount = Message::whereIn('supply_demand_id', $prevSupplyDemand->pluck('id'))->count(); // 当期交互次数(同一个dialogue_id一来一回算一次交互) $interactionCount = Message::whereBetween('created_at', [$startDate, $endDate]) ->whereNotNull('dialogue_id') ->groupBy('dialogue_id') ->selectRaw('dialogue_id, COUNT(*) as message_count') ->having('message_count', '>=', 2) ->count(); // 上期交互次数 $prevInteractionCount = Message::whereBetween('created_at', [$prevStartDate, $prevEndDate]) ->whereNotNull('dialogue_id') ->groupBy('dialogue_id') ->selectRaw('dialogue_id, COUNT(*) as message_count') ->having('message_count', '>=', 2) ->count(); // 计算增减比率 $supplyDemandGrowthRate = $this->calculateGrowthRate($supplyDemandCount, $prevSupplyDemandCount); $messageGrowthRate = $this->calculateGrowthRate($messageCount, $prevMessageCount); $interactionGrowthRate = $this->calculateGrowthRate($interactionCount, $prevInteractionCount); // 当期供需发布分页 $list = SupplyDemand::with(['user', 'dialogues' => function ($query) { $query->with(['user', 'toUser', 'messages' => function ($q) { $q->orderBy('created_at', 'desc')->limit(10); }])->limit(2)->orderBy('created_at', 'desc'); }])->where(function ($query) use ($type) { if ($type) { $query->where('type', $type); } })->whereBetween('created_at', [$startDate, $endDate]) ->paginate($all['page_size'] ?? 20); return $this->success([ 'list' => $list, 'supply_demand_count' => $supplyDemandCount, 'prev_supply_demand_count' => $prevSupplyDemandCount, 'supply_demand_growth_rate' => $supplyDemandGrowthRate, 'message_count' => $messageCount, 'prev_message_count' => $prevMessageCount, 'message_growth_rate' => $messageGrowthRate, 'interaction_count' => $interactionCount, 'prev_interaction_count' => $prevInteractionCount, 'interaction_growth_rate' => $interactionGrowthRate, ]); } /** * 计算增长率 * @param int $current 当前数值 * @param int $previous 上期数值 * @return array 包含增长率和增长状态 */ private function calculateGrowthRate($current, $previous) { if ($previous == 0) { if ($current > 0) { return [ 'rate' => 100, 'status' => 'increase', 'display' => '+100%' ]; } else { return [ 'rate' => 0, 'status' => 'stable', 'display' => '0%' ]; } } $rate = round(($current - $previous) / $previous * 100, 2); if ($rate > 0) { $status = 'increase'; $display = '+' . $rate . '%'; } elseif ($rate < 0) { $status = 'decrease'; $display = $rate . '%'; } else { $status = 'stable'; $display = '0%'; } return [ 'rate' => $rate, 'status' => $status, 'display' => $display ]; } /** * @OA\Get( * path="/api/admin/supply-demand/message-list", * tags={"供需信息管理"}, * summary="消息列表", * description="", * @OA\Parameter(name="to_user_id", in="query", @OA\Schema(type="string"), required=true, description="接收人"), * @OA\Parameter(name="user_id", in="query", @OA\Schema(type="string"), required=true, description="发起人"), * @OA\Parameter(name="page_size", in="query", @OA\Schema(type="string"), required=false, description="每页显示的条数"), * @OA\Parameter(name="page", in="query", @OA\Schema(type="string"), required=false, description="页码"), * @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"), * @OA\Response( * response="200", * description="暂无" * ) * ) */ public function messageList() { $all = \request()->all(); $messages = [ 'to_user_id.required' => '接收人必填', 'user_id.required' => '接收人必填', ]; $validator = Validator::make($all, [ 'user_id' => 'required', 'to_user_id' => 'required' ], $messages); if ($validator->fails()) { return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); } // 获取会话id $dialogue = Dialogue::where(function ($query) use ($all) { $query->where('user_id', $all['user_id'])->where('to_user_id', $all['to_user_id']); })->orWhere(function ($query) use ($all) { $query->where('user_id', $all['to_user_id'])->where('to_user_id', $all['user_id']); })->first(); if (empty($dialogue)) { return $this->fail([ResponseCode::ERROR_BUSINESS, '会话不存在']); } $message = Message::with([ 'user' => function ($query) { $query->select('id', 'nickname', 'name', 'headimgurl', 'username'); }, 'toUser' => function ($query) { $query->select('id', 'nickname', 'name', 'headimgurl', 'username'); } ])->where(function ($query) use ($dialogue) { $query->where('dialogue_id', $dialogue->id); })->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc') ->paginate($all['page_size'] ?? 20); return $this->success(compact('message')); } }