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.

685 lines
24 KiB

4 weeks ago
<?php
namespace App\Http\Controllers\Admin;
use App\Helpers\ResponseCode;
3 weeks ago
use App\Models\CourseType;
4 weeks ago
use App\Models\ScheduleOverviewCourse;
3 weeks ago
use App\Models\ScheduleOverviewLocation;
use App\Models\ScheduleOverviewOwner;
4 weeks ago
use App\Models\ScheduleOverviewSchedule;
3 weeks ago
use App\Models\ScheduleOverviewScheduleGroup;
use App\Models\ScheduleOverviewScheduleModule;
4 weeks ago
use App\Models\ScheduleOverviewSystem;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
class ScheduleOverviewController extends CommonController
{
protected ScheduleOverviewSystem $systemModel;
protected ScheduleOverviewCourse $courseModel;
protected ScheduleOverviewSchedule $scheduleModel;
3 weeks ago
protected ScheduleOverviewScheduleGroup $scheduleGroupModel;
protected ScheduleOverviewScheduleModule $scheduleModuleModel;
protected ScheduleOverviewLocation $locationModel;
protected ScheduleOverviewOwner $ownerModel;
4 weeks ago
public function __construct()
{
$this->systemModel = new ScheduleOverviewSystem();
$this->courseModel = new ScheduleOverviewCourse();
$this->scheduleModel = new ScheduleOverviewSchedule();
3 weeks ago
$this->scheduleGroupModel = new ScheduleOverviewScheduleGroup();
$this->scheduleModuleModel = new ScheduleOverviewScheduleModule();
$this->locationModel = new ScheduleOverviewLocation();
$this->ownerModel = new ScheduleOverviewOwner();
4 weeks ago
}
public function overview()
{
$year = request('year', date('Y'));
return $this->success([
4 weeks ago
'systems' => $this->getSystems($year),
'courses' => $this->getCourses($year),
3 weeks ago
// 兼容前端矩阵/统计:展开带班组 modules 为“按月扁平记录”
'schedules' => $this->getSchedulesFlatFromGroups($year),
4 weeks ago
]);
}
public function systemIndex()
{
4 weeks ago
return $this->success($this->getSystems(request('year', date('Y'))));
4 weeks ago
}
public function systemShow()
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
'id.required' => '体系ID必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$detail = $this->systemModel->with('courses')->find($all['id']);
if (empty($detail)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '体系不存在']);
}
return $this->success($detail);
}
public function systemSave()
{
$all = request()->all();
$validator = Validator::make($all, [
4 weeks ago
'year' => 'required|string|size:4',
4 weeks ago
'name' => 'required|string|max:255',
'sort' => 'nullable|integer',
], [
4 weeks ago
'year.required' => '年份必填',
4 weeks ago
'name.required' => '体系名称必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
if (!empty($all['id'])) {
$model = $this->systemModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '体系不存在']);
}
} else {
$model = new ScheduleOverviewSystem();
$model->admin_id = $this->getUserId();
$model->department_id = optional($this->getUser())->department_id;
}
DB::beginTransaction();
try {
4 weeks ago
$model->year = $all['year'];
4 weeks ago
$model->name = $all['name'];
$model->sort = (int) ($all['sort'] ?? 0);
$model->save();
DB::commit();
return $this->success($model);
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
}
public function systemDestroy()
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
'id.required' => '体系ID必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$model = $this->systemModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '体系不存在']);
}
DB::beginTransaction();
try {
$courseIds = $this->courseModel->where('system_id', $model->id)->pluck('id')->toArray();
$this->scheduleModel->where('system_id', $model->id)->delete();
if (!empty($courseIds)) {
$this->scheduleModel->whereIn('course_id', $courseIds)->delete();
$this->courseModel->whereIn('id', $courseIds)->delete();
}
$model->delete();
DB::commit();
return $this->success('删除成功');
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
}
public function courseIndex()
{
4 weeks ago
return $this->success($this->getCourses(request('year', date('Y'))));
4 weeks ago
}
public function courseShow()
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
'id.required' => '课程ID必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
3 weeks ago
$detail = $this->courseModel->with(['system', 'courseType'])->find($all['id']);
4 weeks ago
if (empty($detail)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '课程不存在']);
}
return $this->success($detail);
}
public function courseSave()
{
$all = request()->all();
$validator = Validator::make($all, [
'system_id' => 'required|integer',
3 weeks ago
'course_type_id' => 'nullable|integer',
4 weeks ago
'name' => 'required|string|max:255',
'sort' => 'nullable|integer',
], [
'system_id.required' => '所属体系必填',
'name.required' => '课程名称必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$system = $this->systemModel->find($all['system_id']);
if (empty($system)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '所属体系不存在']);
}
3 weeks ago
$courseType = null;
if (!empty($all['course_type_id'])) {
$courseType = CourseType::query()->find($all['course_type_id']);
if (empty($courseType)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '课程类别不存在']);
}
}
4 weeks ago
if (!empty($all['id'])) {
$model = $this->courseModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '课程不存在']);
}
} else {
$model = new ScheduleOverviewCourse();
$model->admin_id = $this->getUserId();
$model->department_id = optional($this->getUser())->department_id;
}
DB::beginTransaction();
try {
$originSystemId = $model->system_id;
$model->system_id = (int) $all['system_id'];
3 weeks ago
$model->course_type_id = !empty($all['course_type_id']) ? (int) $all['course_type_id'] : null;
$model->name = $courseType ? $courseType->name : $all['name'];
4 weeks ago
$model->sort = (int) ($all['sort'] ?? 0);
$model->save();
if (!empty($originSystemId) && (int) $originSystemId !== (int) $model->system_id) {
$this->scheduleModel->where('course_id', $model->id)->update([
'system_id' => $model->system_id,
]);
}
DB::commit();
3 weeks ago
return $this->success($model->load(['system', 'courseType']));
4 weeks ago
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
}
public function courseDestroy()
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
'id.required' => '课程ID必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$model = $this->courseModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '课程不存在']);
}
DB::beginTransaction();
try {
$this->scheduleModel->where('course_id', $model->id)->delete();
$model->delete();
DB::commit();
return $this->success('删除成功');
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
}
public function scheduleIndex()
{
$year = request('year', date('Y'));
3 weeks ago
$list = $this->scheduleGroupModel
->with(['system', 'course', 'modules.location', 'modules.owner'])
->where('year', $year)
->orderBy('system_id')
->orderBy('course_id')
->orderBy('id')
->get();
return $this->success($list);
4 weeks ago
}
public function scheduleShow()
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
3 weeks ago
'id.required' => '带班ID必填',
4 weeks ago
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
3 weeks ago
$detail = $this->scheduleGroupModel->with(['system', 'course', 'modules.location', 'modules.owner'])->find($all['id']);
4 weeks ago
if (empty($detail)) {
3 weeks ago
return $this->fail([ResponseCode::ERROR_BUSINESS, '带班不存在']);
4 weeks ago
}
return $this->success($detail);
}
public function scheduleSave()
{
$all = request()->all();
4 weeks ago
$rules = [
4 weeks ago
'year' => 'required|string|size:4',
'system_id' => 'required|integer',
3 weeks ago
'course_id' => 'nullable|integer',
4 weeks ago
'title' => 'required|string|max:255',
3 weeks ago
'modules' => 'required|array|min:1',
'modules.*.name' => 'nullable|string|max:255',
'modules.*.month' => 'required|integer|between:1,12',
'modules.*.location_id' => 'required|integer',
'modules.*.owner_id' => 'required|integer',
'modules.*.count_text' => 'nullable|string|max:255',
4 weeks ago
];
$validator = Validator::make($all, $rules, [
4 weeks ago
'year.required' => '年份必填',
'system_id.required' => '体系必填',
3 weeks ago
'title.required' => '课程名称必填',
'modules.required' => '模块/期数必填',
'modules.array' => '模块/期数格式不正确',
'modules.min' => '模块/期数至少需要一条数据',
'modules.*.month.required' => '月份必填',
'modules.*.month.integer' => '月份格式不正确',
'modules.*.month.between' => '月份范围需在1到12之间',
'modules.*.location_id.required' => '地点必填',
'modules.*.owner_id.required' => '负责人必填',
4 weeks ago
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
3 weeks ago
$system = $this->systemModel->find($all['system_id']);
if (empty($system)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '体系不存在']);
4 weeks ago
}
3 weeks ago
$course = null;
if (!empty($all['course_id'])) {
$course = $this->courseModel->find($all['course_id']);
if (empty($course)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '课程不存在']);
}
if ((int) $course->system_id !== (int) $system->id) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '课程不属于当前体系']);
4 weeks ago
}
}
3 weeks ago
if ((string) $system->year !== (string) $all['year']) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '体系不属于当前年份']);
4 weeks ago
}
3 weeks ago
$modules = $all['modules'] ?? [];
$locationIds = collect($modules)->pluck('location_id')->filter()->unique()->values()->toArray();
$ownerIds = collect($modules)->pluck('owner_id')->filter()->unique()->values()->toArray();
$locations = $this->locationModel->whereIn('id', $locationIds)->get()->keyBy('id');
$owners = $this->ownerModel->whereIn('id', $ownerIds)->get()->keyBy('id');
foreach ($locationIds as $locationId) {
if (!$locations->has($locationId)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '地点不存在']);
}
}
foreach ($ownerIds as $ownerId) {
if (!$owners->has($ownerId)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '负责人不存在']);
}
4 weeks ago
}
3 weeks ago
if (!empty($all['id'])) {
$model = $this->scheduleGroupModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '带班不存在']);
}
} else {
$model = new ScheduleOverviewScheduleGroup();
$model->admin_id = $this->getUserId();
$model->department_id = optional($this->getUser())->department_id;
4 weeks ago
}
3 weeks ago
DB::beginTransaction();
try {
$model->year = $all['year'];
$model->system_id = (int) $all['system_id'];
$model->course_id = !empty($all['course_id']) ? (int) $all['course_id'] : null;
$model->title = $all['title'];
$model->save();
// 简化:保存时用“全量覆盖”的方式更新 modules
$this->scheduleModuleModel->where('group_id', $model->id)->delete();
foreach ($modules as $index => $moduleData) {
$module = new ScheduleOverviewScheduleModule();
$module->group_id = $model->id;
$module->name = $moduleData['name'] ?? null;
$module->month = (int) $moduleData['month'];
$module->location_id = (int) $moduleData['location_id'];
$module->owner_id = (int) $moduleData['owner_id'];
$module->count_text = $moduleData['count_text'] ?? '';
$module->sort = (int) ($moduleData['sort'] ?? $index);
$module->admin_id = $this->getUserId();
$module->department_id = optional($this->getUser())->department_id;
$module->save();
}
DB::commit();
return $this->success($model->load(['system', 'course', 'modules.location', 'modules.owner']));
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
}
public function scheduleDestroy()
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
'id.required' => '带班ID必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$model = $this->scheduleGroupModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '带班不存在']);
}
DB::beginTransaction();
try {
$this->scheduleModuleModel->where('group_id', $model->id)->delete();
$model->delete();
DB::commit();
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
return $this->success('删除成功');
}
public function locationIndex()
{
$list = $this->locationModel
->orderBy('sort')
->orderBy('id')
->get();
return $this->success($list);
}
public function locationSave()
{
$all = request()->all();
$validator = Validator::make($all, [
'name' => 'required|string|max:255',
'sort' => 'nullable|integer',
'status' => 'nullable|integer|in:0,1',
], [
'name.required' => '地点名称必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
4 weeks ago
}
4 weeks ago
if (!empty($all['id'])) {
3 weeks ago
$model = $this->locationModel->find($all['id']);
4 weeks ago
if (empty($model)) {
3 weeks ago
return $this->fail([ResponseCode::ERROR_BUSINESS, '地点不存在']);
4 weeks ago
}
} else {
3 weeks ago
$model = new ScheduleOverviewLocation();
4 weeks ago
$model->admin_id = $this->getUserId();
$model->department_id = optional($this->getUser())->department_id;
}
DB::beginTransaction();
try {
3 weeks ago
$model->name = $all['name'];
$model->sort = (int) ($all['sort'] ?? 0);
$model->status = (int) ($all['status'] ?? 1);
$model->save();
DB::commit();
return $this->success($model);
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
}
public function locationDestroy()
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
'id.required' => '地点ID必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$model = $this->locationModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '地点不存在']);
}
$used = $this->scheduleModuleModel->where('location_id', $model->id)->exists();
if ($used) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '地点已被使用,无法删除']);
}
$model->delete();
return $this->success('删除成功');
}
public function ownerIndex()
{
$list = $this->ownerModel
->orderBy('sort')
->orderBy('id')
->get();
return $this->success($list);
}
public function ownerSave()
{
$all = request()->all();
$validator = Validator::make($all, [
'name' => 'required|string|max:255',
'sort' => 'nullable|integer',
'status' => 'nullable|integer|in:0,1',
], [
'name.required' => '负责人名称必填',
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
if (!empty($all['id'])) {
$model = $this->ownerModel->find($all['id']);
if (empty($model)) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '负责人不存在']);
4 weeks ago
}
3 weeks ago
} else {
$model = new ScheduleOverviewOwner();
$model->admin_id = $this->getUserId();
$model->department_id = optional($this->getUser())->department_id;
}
4 weeks ago
3 weeks ago
DB::beginTransaction();
try {
$model->name = $all['name'];
$model->sort = (int) ($all['sort'] ?? 0);
$model->status = (int) ($all['status'] ?? 1);
$model->save();
4 weeks ago
DB::commit();
3 weeks ago
return $this->success($model);
4 weeks ago
} catch (\Throwable $throwable) {
DB::rollBack();
return $this->fail([ResponseCode::ERROR_INSIDE, $throwable->getMessage()]);
}
}
3 weeks ago
public function ownerDestroy()
4 weeks ago
{
$all = request()->all();
$validator = Validator::make($all, [
'id' => 'required',
], [
3 weeks ago
'id.required' => '负责人ID必填',
4 weeks ago
]);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
3 weeks ago
$model = $this->ownerModel->find($all['id']);
4 weeks ago
if (empty($model)) {
3 weeks ago
return $this->fail([ResponseCode::ERROR_BUSINESS, '负责人不存在']);
}
$used = $this->scheduleModuleModel->where('owner_id', $model->id)->exists();
if ($used) {
return $this->fail([ResponseCode::ERROR_BUSINESS, '负责人已被使用,无法删除']);
4 weeks ago
}
$model->delete();
return $this->success('删除成功');
}
4 weeks ago
protected function getSystems($year)
4 weeks ago
{
return $this->systemModel
4 weeks ago
->where('year', $year)
4 weeks ago
->orderBy('sort')
->orderBy('id')
->get();
}
4 weeks ago
protected function getCourses($year)
4 weeks ago
{
return $this->courseModel
3 weeks ago
->with(['system', 'courseType'])
4 weeks ago
->whereHas('system', function ($query) use ($year) {
$query->where('year', $year);
})
4 weeks ago
->orderBy('sort')
->orderBy('id')
->get();
}
protected function getSchedules($year)
{
return $this->scheduleModel
->with(['system', 'course'])
->where('year', $year)
->orderBy('month')
->orderBy('id')
->get();
}
3 weeks ago
protected function getSchedulesFlatFromGroups($year)
{
$groups = $this->scheduleGroupModel
->with(['system', 'course', 'modules.location', 'modules.owner'])
->where('year', $year)
->orderBy('id')
->get();
$flat = [];
foreach ($groups as $group) {
foreach ($group->modules as $module) {
$flat[] = [
'id' => $module->id,
'group_id' => $group->id,
'year' => $group->year,
'system_id' => $group->system_id,
'course_id' => $group->course_id,
'month' => $module->month,
'module_name' => $module->name,
'location_id' => $module->location_id,
'owner_id' => $module->owner_id,
'title' => $group->title,
'owner' => optional($module->owner)->name ?? '',
'location' => optional($module->location)->name ?? '',
'count_text' => $module->count_text ?? '',
'system' => $group->system,
'course' => $group->course,
];
}
}
usort($flat, function ($a, $b) {
$yearDiff = strcmp((string) ($a['year'] ?? ''), (string) ($b['year'] ?? ''));
if ($yearDiff !== 0) {
return $yearDiff;
}
$monthDiff = (int) ($a['month'] ?? 0) - (int) ($b['month'] ?? 0);
if ($monthDiff !== 0) {
return $monthDiff;
}
return (int) ($a['id'] ?? 0) - (int) ($b['id'] ?? 0);
});
return $flat;
}
4 weeks ago
}