'', 'day' => 0, 'create' => false, ]; } foreach ($month as $item) { $c = date('d', strtotime($item['date'])) + ($week - 2); $w = date('w', strtotime($item['date'])); if ($w == 0) $w = 7; $month_list[floor($c / 7)][$w - 1] = $item; } foreach ($month_list as $key => $item) { $c = count($item); if ($c != 7) { for ($i = 0; $i < 7 - $c; $i++) { $month_list[$key][] = [ 'date' => '', 'day' => 0, 'create' => false, ]; } } } return $month_list; } public function last_day($date) { $date = strtotime($date); $count = cal_days_in_month(CAL_GREGORIAN, date('m', $date), date('Y', $date)); return date('Y-m', $date) . '-' . $count; } public function first_day($date) { $date = strtotime($date); return date('Y-m-01', $date); } public function check_create($appointment_template, $date, $list) { $weekday = $appointment_template->weekday; $holidays = $appointment_template->holidays; $weeks = json_decode($appointment_template->weeks, true); $week = date('w', strtotime($date)); $week = $week == 0 ? 7 : $week; switch ($week) { case 1: case 2: case 3: case 4: case 5: if (isset($list[$date]) && $list[$date]['type'] == 1) { if ($holidays == 2) return false; } return in_array((string)$week, $weeks); case 6: case 7: if (isset($list[$date]) && $list[$date]['type'] == 2) { if ($weekday == 1) return true; } return in_array((string)$week, $weeks); } } public function date_map($start_date, $end_date, $appointment_template, $list) { $date_map = []; $first_day = self::first_day($start_date); $last_day = self::last_day($end_date); $first_day_time = strtotime($first_day); $last_day_time = strtotime($last_day); for ($i = $first_day_time; $i <= $last_day_time; $i += 86400) { $date = date('Y-m-d', $i); $key = date('Y_m', $i); $create = self::check_create($appointment_template, $date, $list); if (strtotime($start_date) > $i) $create = false; if (strtotime($end_date) < $i) $create = false; $item = [ 'date' => $date, 'day' => date('d', $i), 'create' => $create, ]; $date_map[$key][] = $item; } $map = []; foreach ($date_map as $key => $item) { $map[] = [ 'year' => explode('_', $key)[0], 'month' => explode('_', $key)[1], 'list' => self::month_map($item), ]; } return $map; } public function create(Request $request) { Login::admin([], [13, 15, 27]); $hospital_id = $request->post('hospital'); if (Login::$info->hospital != 0) { if ($hospital_id != Login::$info->hospital) { Yo::error_echo(100000, ['机构/医院']); } } $id = $request->post('id'); $date_arr = $request->post('date_arr'); $appointment_template = AppointmentTemplate::find($id); if (!$appointment_template) Yo::error_echo(100000, ['计划模板']); if (count($date_arr) > 300) Yo::error_echo(200022); $hospital = Hospital::where('id', $hospital_id)->where('del', 2)->first(); if (!$hospital) Yo::error_echo(100000, ['机构/医院']); $list = []; $error = []; foreach ($date_arr as $date) { $week = date('w', strtotime($date)); $week = $week == 0 ? 7 : $week; $appointment = new Appointment(); $appointment->date = $date; $appointment->week = $week; $appointment->start_time = $appointment_template->start_time; $appointment->end_time = $appointment_template->end_time; $appointment->stop_time = $appointment_template->stop_time; $appointment->max_count = $appointment_template->max_count; $appointment->used_count = 0; $appointment->hospital = $hospital->id; $appointment->status = 1; $appointment->save(); if (!!$appointment->id) { $list[] = $appointment; } else { $error[] = $appointment; } } return Yo::echo([ 'list' => $list, 'error' => $error, ]); } public function create_list(Request $request) { Login::admin([], [13, 27]); $id = $request->post('id'); $start_date = $request->post('start_date'); $end_date = $request->post('end_date'); if (strtotime($start_date) > strtotime($end_date)) Yo::error_echo(200020); $appointment_template = AppointmentTemplate::find($id); if (!$appointment_template) Yo::error_echo(100000, ['计划模板']); $appointment_holiday_list = AppointmentHolidays::where('date', '>=', $start_date) ->where('date', '<=', $end_date) ->get(); $list = []; foreach ($appointment_holiday_list as $item) { $list[$item->date] = [ 'date' => $item->date, 'type' => $item->type, ]; } $date_map = self::date_map($start_date, $end_date, $appointment_template, $list); if (count($date_map) > 12) Yo::error_echo(200021); return Yo::echo([ 'list' => $date_map, ]); } public function delete(Request $request) { Login::admin([], [15, 27]); $ids = $request->post('ids'); $appointments_to_delete = Appointment::whereIn('id', $ids) ->where('used_count', '>', 0) ->get(); if (count($appointments_to_delete)) { return Yo::error_echo(200023); } if (Login::$info->id == 1) { Appointment::whereIn('id', $ids)->update(['del' => 1]); } else { Appointment::whereIn('id', $ids)->where('hospital', Login::$info->hospital)->update(['del' => 1]); } return Yo::delete_echo($ids); } public function change_status(Request $request) { Login::admin([], [15, 27]); $ids = $request->post('ids'); $status = $request->post('status'); if (Login::$info->id == 1) { Appointment::whereIn('id', $ids)->update(['status' => $status]); } else { Appointment::whereIn('id', $ids)->where('hospital', Login::$info->hospital)->update(['status' => $status]); } return Yo::update_echo($ids); } public function change_count(Request $request) { Login::admin([], [15, 27]); $ids = $request->post('ids'); $count = $request->post('count'); if (Login::$info->id == 1) { $list = Appointment::whereIn('id', $ids)->get(); } else { $list = Appointment::whereIn('id', $ids)->where('hospital', Login::$info->hospital)->get(); } foreach ($list as $item) { $item->max_count = $count; $item->save(); } return Yo::update_echo($ids); } public function list(Request $request) { Login::admin([], [15, 27]); $hospital = $request->post('hospital'); if (Login::$info->hospital != 0) { if ($hospital != Login::$info->hospital) { Yo::error_echo(100000, ['机构/医院']); } } $start_date = $request->post('start_date'); $end_date = $request->post('end_date'); $status = $request->post('status'); $weeks = $request->post('weeks'); $query = Appointment::select('*') ->selectRaw("IFNULL((select type from appointment_holidays where appointment_holidays.date = appointments.date),0) as date_type") ->where('hospital', $hospital); if ($status != 0) $query->where('status', '>=', $status); if (!!$start_date) $query->where('date', '>=', $start_date); if (!!$end_date) $query->where('date', '<=', $end_date); if (count($weeks) == 0) $weeks = [1, 2, 3, 4, 5, 6, 7]; $query->whereIn('week', $weeks); $appointments = $query->where('del', 2)->orderBy('date', 'desc')->paginate(20); return Yo::echo($appointments); } public function mp_list(Request $request) { Login::user(); $month = $request->post('month'); $hospital = $request->post('hospital'); $appointments = Appointment::where('hospital', $hospital) ->where('date', 'like', $month . '%') ->where('status', 1) ->where('del', 2) ->orderBy('date') ->get(); $list = []; foreach ($appointments as $appointment) { $date = substr($appointment->date, 8, 2); if (!isset($list[$date])) { $list[$date] = [ 'date' => $appointment->date, 'info' => 0, 'data' => [ 'list' => [] ], ]; } $item_time = strtotime($appointment->date . ' ' . $appointment->stop_time); $start_show = date('H:i', strtotime($appointment->date . ' ' . $appointment->start_time)); $end_show = date('H:i', strtotime($appointment->date . ' ' . $appointment->end_time)); $appointment->start_show = $start_show; $appointment->end_show = $end_show; if ($item_time < time()) { $appointment->used_count = $appointment->max_count; } else { $list[$date]['info'] += max($appointment->max_count - $appointment->used_count, 0); } $list[$date]['data']['list'][] = $appointment; } $l = []; foreach ($list as $item) { $l[] = $item; } return Yo::echo([ 'list' => $l, ]); } public function statistics(Request $request) { Login::admin([]); $hospital = $request->post('hospital'); if (Login::$info->hospital != 0) { if ($hospital != Login::$info->hospital) { Yo::error_echo(100000, ['机构/医院']); } } $start_date = $request->post('start_date'); $end_date = $request->post('end_date'); // 1. 查询已支付/已完成订单 (status IN 2,4) $query = UserOrder::where('hospital', $hospital) ->whereIn('status', [2, 4]); if (!!$start_date) $query->where('created_at', '>=', $start_date); if (!!$end_date) $query->where('created_at', '<=', $end_date . ' 23:59:59'); $orders = $query->orderBy('id', 'desc')->get(); // 查询已退款订单 (status = 5) $refund_query = UserOrder::where('hospital', $hospital) ->where('status', 5); if (!!$start_date) $refund_query->where('refund_time', '>=', $start_date); if (!!$end_date) $refund_query->where('refund_time', '<=', $end_date . ' 23:59:59'); $refund_orders = $refund_query->get(); // 2. 按类型汇总(个检type=1, 团检type=2) $charge_amount = round($orders->sum('true_price'), 2); $refund_amount = round($refund_orders->sum('true_price'), 2); $total_amount = round($charge_amount - $refund_amount, 2); $type_summary = []; foreach ([1 => '个人', 2 => '团检'] as $type_val => $type_name) { $type_charge = round($orders->where('type', $type_val)->sum('true_price'), 2); $type_refund = round($refund_orders->where('type', $type_val)->sum('true_price'), 2); $type_summary[] = [ 'name' => $type_name, 'charge' => $type_charge, 'refund' => $type_refund, 'total' => round($type_charge - $type_refund, 2), ]; } // 3. 收集所有项目Id $all_item_ids = []; $order_items = []; foreach ($orders as $order) { if (!$order->appointment_info) continue; $info = json_decode($order->appointment_info, true); if (!$info || !isset($info['项目列表'])) continue; $items = []; foreach ($info['项目列表'] as $item) { $all_item_ids[] = $item['Id']; $items[] = $item; } $order_items[$order->id] = $items; } $all_item_ids = array_values(array_unique($all_item_ids)); // 4. 调用"自选项目查询",获取全部项目 → 科室Id 映射 $item_clinic_map = []; if (count($all_item_ids) > 0) { $peis = new PEISApiController(); $items_data = $peis::Post('自选项目查询', $hospital, [ '价格下限' => "0", '价格上限' => "999999", "性别" => null, "妇检" => null, "套餐Id" => null, "项目Id列表" => [] ])['data']; foreach ($items_data as $item) { $item_clinic_map[$item['Id']] = $item['科室Id']; } } // 5. 调用"字典查询",获取科室Id → 别名 映射 $clinic_alias_map = []; if (count($all_item_ids) > 0) { $peis = new PEISApiController(); $dict_data = $peis::Post('字典查询', $hospital, [ '字典类别' => '科室别名字典' ])['data']; foreach ($dict_data as $item) { $clinic_alias_map[$item['Id']] = $item['值']; } } // 6. 按别名分组统计收费 $statistics = []; foreach ($order_items as $order_id => $items) { foreach ($items as $item) { $item_id = $item['Id']; $clinic_id = isset($item_clinic_map[$item_id]) ? $item_clinic_map[$item_id] : null; $matched = $clinic_id && isset($clinic_alias_map[$clinic_id]); $alias = $matched ? $clinic_alias_map[$clinic_id] : '未匹配科室'; $price = floatval($item['价格']); if (isset($item['优惠方式']) && $item['优惠方式'] === '打折') { $price = $price * floatval($item['优惠值']); } $key = $matched ? $alias : '__unmatched__'; if (!isset($statistics[$key])) { $statistics[$key] = [ 'name' => $alias, 'amount' => 0, 'item_names' => [], ]; } $statistics[$key]['amount'] += $price; if (!$matched) { $statistics[$key]['item_names'][] = $item['名称']; } } } // 格式化金额,未匹配项去重 $categories = []; foreach ($statistics as $item) { $item['amount'] = round($item['amount'], 2); if (isset($item['item_names'])) { $item['item_names'] = array_values(array_unique($item['item_names'])); } $categories[] = $item; } return Yo::echo([ 'type_summary' => $type_summary, 'charge_amount' => $charge_amount, 'refund_amount' => $refund_amount, 'total_amount' => $total_amount, 'total_chinese' => self::amountToChinese($total_amount), 'categories' => $categories, ]); } private function amountToChinese($amount) { $digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; $radices = ['', '拾', '佰', '仟']; $bigRadices = ['', '万', '亿']; $decimals = ['角', '分']; $amount = round($amount, 2); if ($amount == 0) return '零元整'; $amountStr = number_format($amount, 2, '.', ''); $parts = explode('.', $amountStr); $intPart = $parts[0]; $decPart = $parts[1]; $result = ''; $zeroFlag = false; $intLen = strlen($intPart); for ($i = 0; $i < $intLen; $i++) { $digit = (int)$intPart[$i]; $pos = $intLen - $i - 1; $radixPos = $pos % 4; $bigRadixPos = $pos / 4; if ($digit === 0) { $zeroFlag = true; } else { if ($zeroFlag) { $result .= '零'; $zeroFlag = false; } $result .= $digits[$digit] . $radices[$radixPos]; } if ($radixPos === 0 && $pos > 0) { if (!$zeroFlag || $pos >= 8) { $result .= $bigRadices[(int)$bigRadixPos]; } $zeroFlag = false; } } $result .= '元'; if ($decPart === '00') { $result .= '整'; } else { $jiao = (int)$decPart[0]; $fen = (int)$decPart[1]; if ($jiao > 0) { $result .= $digits[$jiao] . '角'; } elseif ($jiao === 0 && $fen > 0) { $result .= '零'; } if ($fen > 0) { $result .= $digits[$fen] . '分'; } } return $result; } }