auth->id; $status = MemberService::status($userId); $this->success('', [ 'counselors' => $this->counselorList(5), 'assessments' => array_merge( AssessmentService::lists('mood', $userId), AssessmentService::lists('parenting', $userId) ), 'orders' => $this->orderList(), 'crisis' => AssessmentService::crisis(), 'member' => $status, 'discount' => MemberService::can($userId, 'consult.discount') ? 0.9 : 1, ]); } /** * 咨询师列表(含资质、价格、可预约时段) */ public function counselors() { $this->success('', ['list' => $this->counselorList(20)]); } /** * 量表列表 / 详情 / 提交 */ public function assessments() { $scope = $this->request->param('scope', ''); $this->success('', ['list' => AssessmentService::lists($scope, $this->auth->id)]); } public function assessmentDetail() { $data = AssessmentService::detail($this->request->param('id', 0)); if (!$data) { $this->error('量表不存在'); } $this->success('', $data); } public function assessmentSubmit() { $answers = $this->request->post('answers', ''); $answers = is_array($answers) ? $answers : json_decode(htmlspecialchars_decode((string)$answers, ENT_QUOTES), true); if (!is_array($answers)) { $this->error('请完成全部题目'); } $result = AssessmentService::submit($this->auth->id, (int)$this->request->post('id', 0), $answers); if (isset($result['error'])) { $this->error($result['error']); } $this->success('测评完成', $result); } /** * 预约咨询 * POST counselor_id, mode=text|voice|video, start_time=Y-m-d H:i */ public function orderCreate() { $userId = $this->auth->id; $counselorId = (int)$this->request->post('counselor_id', 0); $mode = $this->request->post('mode', 'text'); $startTime = (string)$this->request->post('start_time', ''); $counselor = Db::name('counselor')->where('id', $counselorId)->where('status', 'on')->find(); if (!$counselor) { $this->error('咨询师不可预约'); } if (!in_array($mode, ['text', 'voice', 'video'], true)) { $this->error('咨询方式不正确'); } if (!$startTime || !strtotime($startTime)) { $this->error('请选择预约时间'); } if (strtotime($startTime) < time()) { $this->error('预约时间需晚于当前时间'); } $priceField = 'price_' . $mode; $amount = (float)$counselor[$priceField]; $discount = MemberService::can($userId, 'consult.discount') ? 0.9 : 1; $amount = round($amount * $discount, 2); $rateAmount = round($amount * (float)$counselor['rate'], 2); $orderNo = 'HQ' . date('YmdHis') . Random::numeric(4); $id = Db::name('consult_order')->insertGetId([ 'order_no' => $orderNo, 'user_id' => $userId, 'counselor_id' => $counselorId, 'mode' => $mode, 'start_time' => strtotime($startTime), 'duration' => 50, 'amount' => $amount, 'pay_status' => 'unpaid', 'consult_status' => 'pending', 'rate_amount' => $rateAmount, 'createtime' => time(), ]); $this->success('预约已提交', [ 'order_id' => (int)$id, 'order_no' => $orderNo, 'amount' => $amount, 'discount' => $discount, 'start_time' => date('Y-m-d H:i', strtotime($startTime)), 'pay_hint' => '支付通道待接入,可联系客服确认支付后开始咨询', 'counselor' => ['name' => $counselor['name'], 'title' => $counselor['title']], 'note' => '咨询内容将加密保存,仅你与咨询师可见', ]); } /** * 我的咨询订单 */ public function orders() { $this->success('', ['list' => $this->orderList()]); } /** * 取消订单 */ public function cancel() { $id = (int)$this->request->post('id', 0); $row = Db::name('consult_order')->where('id', $id)->where('user_id', $this->auth->id)->find(); if (!$row) { $this->error('订单不存在'); } if ($row['consult_status'] === 'finished') { $this->error('已完成的咨询无法取消'); } Db::name('consult_order')->where('id', $id)->update(['consult_status' => 'canceled']); $this->success('已取消', ['list' => $this->orderList()]); } /** * 危机干预信息(前端在高风险结果后也可主动调用) */ public function crisis() { $this->success('', AssessmentService::crisis()); } // ---------------- 内部方法 ---------------- protected function counselorList($limit) { $rows = Db::name('counselor') ->where('status', 'on') ->where('cert_verify', 'passed') ->order('weigh', 'desc') ->limit($limit) ->select(); $member = MemberService::can($this->auth->id, 'consult.discount'); return array_map(function ($row) use ($member) { $tags = array_filter(explode(',', $row['tags'])); $slots = []; for ($i = 1; $i <= 3; $i++) { $day = date('Y-m-d', strtotime('+' . $i . ' day')); $slots[] = $day . ' 10:00'; $slots[] = $day . ' 15:00'; } return [ 'id' => (int)$row['id'], 'name' => $row['name'], 'emoji' => $row['avatar_emoji'], 'title' => $row['title'], 'cert_verify' => $row['cert_verify'], 'intro' => $row['intro'], 'tags' => $tags, 'price' => [ 'text' => (float)$row['price_text'], 'voice' => (float)$row['price_voice'], 'video' => (float)$row['price_video'], ], 'discount' => $member ? 0.9 : 1, 'slots' => $slots, ]; }, $rows); } protected function orderList() { $rows = Db::name('consult_order') ->where('user_id', $this->auth->id) ->order('id', 'desc') ->limit(20) ->select(); $names = Db::name('counselor')->column('name', 'id'); $modeText = ['text' => '文字', 'voice' => '语音', 'video' => '视频']; $statusText = ['pending' => '待开始', 'ongoing' => '进行中', 'finished' => '已完成', 'canceled' => '已取消']; return array_map(function ($row) use ($names, $modeText, $statusText) { return [ 'id' => (int)$row['id'], 'order_no' => $row['order_no'], 'counselor' => isset($names[$row['counselor_id']]) ? $names[$row['counselor_id']] : '', 'mode' => $row['mode'], 'mode_text' => isset($modeText[$row['mode']]) ? $modeText[$row['mode']] : $row['mode'], 'start_time' => $row['start_time'] ? date('Y-m-d H:i', (int)$row['start_time']) : '', 'amount' => (float)$row['amount'], 'pay_status' => $row['pay_status'], 'status' => $row['consult_status'], 'status_text' => isset($statusText[$row['consult_status']]) ? $statusText[$row['consult_status']] : $row['consult_status'], ]; }, $rows); } }