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.

672 lines
27 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\Helpers\ResponseCode;
use App\Jobs\CancelAppointMeet;
use App\Models\Admin;
use App\Models\Appointment;
use App\Models\AppointmentConfig;
use App\Models\Article;
use App\Models\Calendar;
use App\Models\CarparkLog;
use App\Models\Company;
use App\Models\CourseSign;
use App\Models\CourseType;
use App\Models\CustomFormField;
use App\Models\Department;
use App\Models\ParameterDetail;
use App\Models\SupplyDemand;
use App\Models\TimeEvent;
use App\Models\User;
use App\Repositories\DoorRepository;
use App\Repositories\EntranceRepository;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\Course;
use EasyWeChat\Factory;
use Illuminate\Filesystem\Filesystem;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\CommonExport;
class OtherController extends CommonController
{
/**
* @OA\Get(
* path="/api/admin/other/home",
* tags={"其他"},
* summary="驾驶舱",
* description="",
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function home()
{
// 校友总数
$schoolmate['schoolmate_total'] = User::where('is_schoolmate', 1)->count();
// 2025年校友数
$schoolmate['schoolmate_year'] = User::where('is_schoolmate', 1)->where('created_at', 'like', '%' . date('Y') . '%')->count();
// 开课场次(全部)
$calendar = Calendar::get();
$company['course_total'] = $calendar->count();
$company['course_day_total'] = $calendar->sum(function ($course) {
$start = Carbon::parse($course->start_time);
$end = Carbon::parse($course->end_time);
return $end->diffInDays($start) + 1; // 包含起始和结束日期
});
// 开课场次(当年)
$calendarYear = Calendar::where('date', 'like', '%' . date('Y') . '%')->get();
$company['course_total_year'] = $calendarYear->count();
$company['course_day_total_year'] = $calendarYear->sum(function ($course) {
$start = Carbon::parse($course->start_time);
$end = Carbon::parse($course->end_time);
return $end->diffInDays($start) + 1; // 包含起始和结束日期
});
// 校友企业总融资额
$company['company_fund'] = Company::where('is_schoolmate', 1)->sum('company_fund');
// 校友企业总估值
$company['valuation'] = Company::where('is_schoolmate', 1)->sum('valuation');
// 校友企业所属领域
$industryTotal = [];
$industries = ParameterDetail::where('parameter_id', 4)->get();
foreach ($industries as $item) {
$level2Names = ParameterDetail::where('parameter_id', 10)->where('remark', $item->value)->pluck('value');
$industryTotal[] = [
'industry' => $item->value,
'total' => User::whereIn('company_industry', $level2Names)->count()
];
}
// 课程统计
$courseTypes = CourseType::where('is_chart', 1)->get();
foreach ($courseTypes as $courseType) {
$courseIds = Course::where('type', $courseType->id)->pluck('id');
$courseType->course_signs_total = CourseSign::whereIn('course_id', $courseIds)
->where('status', 1)
->count();
}
// 苏州区域数据
$suzhou = Company::where('company_city', '苏州市')
// 根据company_area分组查询公司数量
->select('company_area', DB::raw('count(*) as company_total'))
->groupBy('company_area')
->get();
// 全国数据
$country = Company::select('company_city', DB::raw('count(*) as company_total'))
->groupBy('company_city')
->get();
return $this->success(compact('courseTypes', 'schoolmate', 'company', 'industryTotal', 'suzhou', 'country'));
}
/**
* @OA\Get(
* path="/api/admin/other/home-v2",
* tags={"其他"},
* summary="驾驶舱V2",
* description="",
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function homeV2()
{
// 课程统计
$courseTypes = CourseType::where('is_chart', 1)->get();
$start_date = CourseType::START_DATE;
$end_date = date('Y-m-d');
foreach ($courseTypes as $courseType) {
// 课程
$courses = Course::where('type', $courseType->id)->get();
// 已开设期数
$courseType->course_periods_total = Course::where('type', $courseType->id)->count();
// 培养人数去重
$courseType->course_signs_total = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses->pluck('id'), null);
}
// 苏州区域数据
$suzhouArea = Company::where('company_city', '苏州市')->groupBy('company_area')
->whereNotNull('company_area')
->get(['company_area']);
$suzhou = [];
foreach ($suzhouArea as $item) {
$suzhou[] = [
'company_area' => $item->company_area,
'company_total' => User::whereHas('company', function ($query) use ($item) {
$query->where('company_area', $item->company_area);
})->where('is_schoolmate', 1)->count()
];
}
// 全国数据
$countryArea = Company::groupBy('company_city')->whereNotNull('company_city')->get(['company_city']);
$country = [];
foreach ($countryArea as $item) {
$country[] = [
'company_city' => $item->company_city,
'company_total' => User::whereHas('company', function ($query) use ($item) {
$query->where('company_city', $item->company_city);
})->where('is_schoolmate', 1)->count()
];
}
// 本月课程
$monthCourses = Course::with('teacher')->where('start_date', 'like', '%' . date('Y-m') . '%')->get();
// 时间轴
$time_axis = TimeEvent::orderBy('sort', 'asc')->orderBy('id', 'desc')->get();
// 动态信息
$article['xiaoyou'] = Article::where('type', 1)->limit(6)->orderBy('sort', 'asc')->get();
$article['yejie'] = Article::where('type', 2)->limit(6)->orderBy('sort', 'asc')->get();
$article['supply_demands'] = SupplyDemand::limit(6)->orderBy('created_at', 'desc')->get();
return $this->success(compact('courseTypes', 'suzhou', 'country', 'monthCourses', 'time_axis', 'article'));
}
/**
* @OA\Get(
* path="/api/admin/other/courses-home",
* 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="course_type_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 coursesHome()
{
$params = $this->getCoursesHomeParams();
$courses = $this->getCoursesByTypeIds($params['course_type_id']);
// 报名人数
$course_signs_total = CourseSign::courseSignsTotal($params['start_date'], $params['end_date']);
// 审核通过人数
$course_signs_pass = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1);
// 审核通过人数去重
$course_signs_pass_unique = CourseSign::courseSignsTotalByUnique($params['start_date'], $params['end_date'], 1, null, null);
// 开课场次
$calendar = $this->getCalendarsByCourses($courses, $params['start_date'], $params['end_date']);
$course_total = $calendar->count();
// 开课天数
$course_day_total = $calendar->sum('days');
// 课程分类明细统计
$courseTypesSum = $this->getCourseTypesSum($params['start_date'], $params['end_date'], $params['course_type_id']);
// 区域明细统计
$areas = $this->getAreasStatistics($params['start_date'], $params['end_date'], $courses);
return $this->success(compact(
'course_signs_total',
'course_signs_pass',
'course_signs_pass_unique',
'course_total',
'course_day_total',
'courseTypesSum',
'areas'
));
}
/**
* @OA\Get(
* path="/api/admin/other/courses-home-export",
* tags={"其他"},
* summary="课程统计数据明细导出",
* description="",
* @OA\Parameter(name="export_type", in="query", @OA\Schema(type="string"), required=true, description="导出类型course_signs_total-报名人数明细, course_signs_pass-审核通过人数明细, course_signs_pass_unique-审核通过人数去重明细, course_total-开课场次明细, course_type_detail-课程分类明细, area_detail-区域明细"),
* @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="course_type_id", in="query", @OA\Schema(type="string"), required=false, description="课程体系id多个英文逗号"),
* @OA\Parameter(name="course_id", in="query", @OA\Schema(type="string"), required=false, description="课程id用于课程分类明细"),
* @OA\Parameter(name="area", 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="导出Excel文件"
* )
* )
*/
public function coursesHomeExport()
{
$export_type = request('export_type');
$params = $this->getCoursesHomeParams();
$course_id = request('course_id', '');
$area = request('area', '');
// 验证导出类型
$allowed_types = [
'course_signs_total',
'course_signs_pass',
'course_signs_pass_unique',
'course_total',
'course_type_detail',
'area_detail'
];
if (!in_array($export_type, $allowed_types)) {
return $this->fail([ResponseCode::ERROR_PARAMETER, '导出类型不正确']);
}
$courses = $this->getCoursesByTypeIds($params['course_type_id']);
$data = [];
$filename = '';
$error = '';
switch ($export_type) {
case 'course_signs_total':
$list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], null, null, null, true);
$list->load(['user', 'course']);
$data = $this->formatCourseSignsData($list);
$filename = '报名人数明细';
break;
case 'course_signs_pass':
$list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1, null, null, true);
$list->load(['user', 'course']);
$data = $this->formatCourseSignsData($list);
$filename = '审核通过人数明细';
break;
case 'course_signs_pass_unique':
$list = CourseSign::courseSignsTotalByUnique($params['start_date'], $params['end_date'], 1, null, null, true);
$data = $this->formatUsersData($list);
$filename = '审核通过人数去重明细';
break;
case 'course_total':
$list = $this->getCalendarsByCourses($courses, $params['start_date'], $params['end_date']);
$list->load('course');
$data = $this->formatCalendarData($list);
$filename = '开课场次明细';
break;
case 'course_type_detail':
if (!$course_id) {
return $this->fail([ResponseCode::ERROR_PARAMETER, '课程分类明细需要提供course_id参数']);
}
$course_ids = explode(',', $course_id);
$list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1, $course_ids, null, true);
$list->load(['user', 'course']);
$data = $this->formatCourseSignsData($list);
$filename = '课程分类明细';
break;
case 'area_detail':
if (!$area) {
return $this->fail([ResponseCode::ERROR_PARAMETER, '区域明细需要提供area参数']);
}
$list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1, $courses->pluck('id'), $area, true);
$list->load(['user', 'course']);
$data = $this->formatCourseSignsData($list);
$filename = '区域明细_' . $area;
break;
}
if (empty($data)) {
return $this->fail([ResponseCode::ERROR_PARAMETER, '没有可导出的数据']);
}
// 定义导出字段
$exportFields = $this->getExportFields($export_type);
// 导出Excel
return Excel::download(
new CommonExport($data, $exportFields),
$filename . '_' . date('YmdHis') . '.xlsx'
);
}
/**
* 获取课程统计参数
*/
private function getCoursesHomeParams()
{
$course_type_id = request('course_type_id', '');
if ($course_type_id) {
$course_type_id = explode(',', $course_type_id);
} else {
$course_type_id = CourseType::pluck('id')->toArray();
}
return [
'start_date' => request('start_date', CourseType::START_DATE),
'end_date' => request('end_date', date('Y-m-d')),
'course_type_id' => $course_type_id,
];
}
/**
* 根据课程体系ID获取课程列表
*/
private function getCoursesByTypeIds($course_type_id)
{
return Course::whereIn('type', $course_type_id)->get();
}
/**
* 根据课程列表获取日历数据
*/
private function getCalendarsByCourses($courses, $start_date, $end_date)
{
return Calendar::whereIn('course_id', $courses->pluck('id'))
->whereBetween('date', [$start_date, $end_date])
->get();
}
/**
* 获取课程分类明细统计
*/
private function getCourseTypesSum($start_date, $end_date, $course_type_id)
{
$courseTypesSum = [];
$courseTypes = CourseType::whereIn('id', $course_type_id)->get();
foreach ($courseTypes as $courseType) {
$courses2 = Course::where('type', $courseType->id)->get();
foreach ($courses2 as $course) {
$courseTypesSum[] = [
'course_type' => $courseType->name,
'course_type_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses2->pluck('id')),
'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), null),
'course_name' => $course->name,
'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id]),
];
}
}
return $courseTypesSum;
}
/**
* 获取区域明细统计
*/
private function getAreasStatistics($start_date, $end_date, $courses)
{
$areas = ParameterDetail::where('parameter_id', 5)->get();
foreach ($areas as $area) {
$area->course_signs_pass = CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses->pluck('id'), $area->value);
$area->course_signs_pass_unique = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses->pluck('id'), $area->value);
}
return $areas;
}
/**
* 格式化课程报名数据
*/
private function formatCourseSignsData($list)
{
$data = [];
foreach ($list as $item) {
$user = $item->user;
$course = $item->course;
$data[] = [
'name' => $user ? ($user->name ?? $user->username ?? '') : '',
'mobile' => $user->mobile ?? '',
'company_name' => $user->company_name ?? '',
'company_position' => $user->company_position ?? '',
'company_area' => $user->company_area ?? '',
'course_name' => $course->name ?? '',
'status_text' => $item->status_text ?? '',
'fee_status_text' => $item->fee_status_text ?? '',
'created_at' => $item->created_at ?? '',
];
}
return $data;
}
/**
* 格式化用户数据(去重)
*/
private function formatUsersData($list)
{
$data = [];
foreach ($list as $user) {
$data[] = [
'name' => $user->name ?? $user->username ?? '',
'mobile' => $user->mobile ?? '',
'company_name' => $user->company_name ?? '',
'company_position' => $user->company_position ?? '',
'company_area' => $user->company_area ?? '',
'email' => $user->email ?? '',
];
}
return $data;
}
/**
* 格式化日历数据
*/
private function formatCalendarData($list)
{
$data = [];
foreach ($list as $item) {
$course = $item->course;
$data[] = [
'course_name' => $course ? ($course->name ?? '') : '',
'date' => $item->date ?? '',
'start_time' => $item->start_time ?? '',
'end_time' => $item->end_time ?? '',
'type_text' => $item->type_text ?? '',
'is_publish_text' => $item->is_publish_text ?? '',
];
}
return $data;
}
/**
* 获取导出字段配置
*/
private function getExportFields($export_type)
{
$fields = [
'course_signs_total' => [
'name' => '姓名',
'mobile' => '手机号',
'company_name' => '公司名称',
'company_position' => '职务',
'company_area' => '公司区域',
'course_name' => '课程名称',
'status_text' => '审核状态',
'fee_status_text' => '缴费状态',
'created_at' => '报名时间',
],
'course_signs_pass' => [
'name' => '姓名',
'mobile' => '手机号',
'company_name' => '公司名称',
'company_position' => '职务',
'company_area' => '公司区域',
'course_name' => '课程名称',
'fee_status_text' => '缴费状态',
'created_at' => '报名时间',
],
'course_signs_pass_unique' => [
'name' => '姓名',
'mobile' => '手机号',
'company_name' => '公司名称',
'company_position' => '职务',
'company_area' => '公司区域',
'email' => '邮箱',
],
'course_total' => [
'course_name' => '课程名称',
'date' => '日期',
'start_time' => '开始时间',
'end_time' => '结束时间',
'type_text' => '类型',
'is_publish_text' => '是否发布',
],
'course_type_detail' => [
'name' => '姓名',
'mobile' => '手机号',
'company_name' => '公司名称',
'company_position' => '职务',
'company_area' => '公司区域',
'course_name' => '课程名称',
'fee_status_text' => '缴费状态',
'created_at' => '报名时间',
],
'area_detail' => [
'name' => '姓名',
'mobile' => '手机号',
'company_name' => '公司名称',
'company_position' => '职务',
'company_area' => '公司区域',
'course_name' => '课程名称',
'fee_status_text' => '缴费状态',
'created_at' => '报名时间',
],
];
return $fields[$export_type] ?? [];
}
/**
* @OA\Post(
* path="/api/admin/other/admin-user-list",
* tags={"其他"},
* summary="后台用户列表",
* 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="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="department_id", in="query", @OA\Schema(type="int"), required=false, description="部门id"),
* @OA\Parameter(name="keyword", 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 adminUserList()
{
$all = \request()->all();
$list = Admin::where(function ($query) use ($all) {
if (isset($all['department_id'])) {
$query->where('department_id', $all['department_id']);
}
if (isset($all['keyword'])) {
$query->where('name', 'like', '%' . $all['keyword'] . '%')->orWhere('username', 'like', '%' . $all['keyword'] . '%')->orWhere('mobile', 'like', '%' . $all['keyword'] . '%');
}
})->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')
->paginate($all['page_size'] ?? 20);
return $this->success($list);
}
/**
* @OA\Post(
* path="/api/admin/other/admin-department-list",
* tags={"其他"},
* summary="后台部门列表",
* 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="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="keyword", in="query", @OA\Schema(type="string"), required=false, description="关键词"),
* @OA\Parameter(name="show_tree", in="query", @OA\Schema(type="string"), required=false, description="是否显示树形结构 0否1是"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function adminDepartmentList()
{
$all = \request()->all();
$list = Department::with('users')->where(function ($query) use ($all) {
if (isset($all['keyword'])) {
$query->where('name', 'like', '%' . $all['keyword'] . '%');
}
});
if (isset($all['show_tree']) && $all['show_tree']) {
// 显示树形结构
$list = array2tree($list->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')->get()->toArray());
} else {
$list = $list->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')->paginate($all['page_size'] ?? 20);
}
return $this->success($list);
}
/**
* @OA\Get(
* path="/api/admin/other/table-fileds",
* tags={"其他"},
* summary="获取表字段",
* description="",
* @OA\Parameter(name="table_name", in="query", @OA\Schema(type="string"), required=true, description="table_name"),
* @OA\Parameter(name="except", in="query", @OA\Schema(type="string"), required=true, description="排除的字段数组"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function tableFileds()
{
$all = \request()->all();
$messages = [
'table_name.required' => '表名必填',
];
$validator = Validator::make($all, [
'table_name' => 'required'
], $messages);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$except = request('except');
$detail = (new CustomFormField())->getRowTableFieldsByComment($all['table_name']);
$list = [];
if ($except) {
foreach ($detail as $key => $item) {
if (in_array($key, $except)) {
continue;
}
$list[] = $item;
}
} else {
$list = $detail;
}
return $this->success($list);
}
public function test()
{
$model = new DoorRepository();
$result = $model->getAllDoorInfo();
dd(json_encode($result, JSON_UNESCAPED_UNICODE));
}
/**
* 车辆进出场日志
*/
public function postCarInInfo()
{
$all = request()->all();
CarparkLog::add(1, $all, $all['plateNo']);
return $this->success($all);
}
/**
* 车辆出场日志
*/
public function postCarOutInfo()
{
$all = request()->all();
CarparkLog::add(2, $all, $all['plateNo']);
return $this->success($all);
}
}