You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

394 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Http\Controllers\Admin;
use App\Exports\BaseExport;
use App\Exports\CommonExport;
use App\Helpers\ResponseCode;
use App\Models\AppointmentType;
use App\Models\CustomForm;
use App\Models\Dialogue;
use App\Models\Message;
use App\Models\SupplyDemand;
use App\Models\SupplyDemandType;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
class SupplyDemandController extends BaseController
{
/**
* 构造函数
*/
public function __construct()
{
parent::__construct(new SupplyDemand());
}
/**
* @OA\Get(
* path="/api/admin/supply-demand/index",
* tags={"供需信息管理"},
* summary="列表",
* description="",
* @OA\Parameter(name="is_export", in="query", @OA\Schema(type="string"), required=false, description="是否导出0否1是"),
* @OA\Parameter(name="export_fields", in="query", @OA\Schema(type="string"), required=false, description="需要导出的字段数组"),
* @OA\Parameter(name="filter", in="query", @OA\Schema(type="string"), required=false, description="查询条件。数组"),
* @OA\Parameter(name="show_relation", in="query", @OA\Schema(type="string"), required=false, description="需要输出的关联关系数组包括teachercourseSettingscoursePeriods"),
* @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="sort_name", in="query", @OA\Schema(type="string"), required=false, description="排序字段名字"),
* @OA\Parameter(name="sort_type", 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 index()
{
$all = request()->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'));
}
}