['text' => '开心', 'emoji' => '☀️', 'score' => 5, 'color' => '#F5A65B'], 'calm' => ['text' => '平静', 'emoji' => '🌤', 'score' => 4, 'color' => '#9BC1A6'], 'anxious' => ['text' => '焦虑', 'emoji' => '🌪', 'score' => 2, 'color' => '#E8A87C'], 'low' => ['text' => '低落', 'emoji' => '🌧', 'score' => 2, 'color' => '#8FA6C4'], 'angry' => ['text' => '烦躁', 'emoji' => '⚡', 'score' => 1, 'color' => '#E8604C'], ]; /** * 记录情绪(一天可多条) * POST log_date, mood, intensity, triggers, content */ public function save() { $userId = $this->auth->id; $mood = (string)$this->request->post('mood', ''); if (!isset(self::$moods[$mood])) { $this->error('请选择情绪'); } $logDate = $this->request->post('log_date', date('Y-m-d')); if (!strtotime($logDate)) { $this->error('日期格式不正确'); } if (strtotime($logDate) > strtotime('+1 day')) { $this->error('不能记录未来日期'); } $content = mb_substr((string)$this->request->post('content', ''), 0, 1000); $id = Db::name('mood_log')->insertGetId([ 'user_id' => $userId, 'log_date' => $logDate, 'mood' => $mood, 'intensity' => min(5, max(1, (int)$this->request->post('intensity', 3))), 'triggers' => mb_substr((string)$this->request->post('triggers', ''), 0, 255), 'content' => $content, 'createtime' => time(), 'updatetime' => time(), ]); $this->success('已记录', [ 'id' => (int)$id, 'mood' => self::$moods[$mood], ]); } /** * 情绪急救包(M2) * 返回 4 个即时可用的安抚工具,按当前情绪排序 */ public function firstaid() { $data = \app\common\service\ContentService::lists($this->auth->id, [ 'type' => 'firstaid', 'limit' => 10, ]); // 按当前情绪优先排序(若今日有记录) $today = Db::name('mood_log') ->where('user_id', $this->auth->id) ->where('log_date', date('Y-m-d')) ->order('id', 'desc') ->find(); $mood = $today ? $today['mood'] : ''; if ($mood) { usort($data['list'], function ($a, $b) use ($mood) { $aHit = strpos((string)$a['summary'] . (string)$a['title'], $mood) !== false ? 1 : 0; $bHit = strpos((string)$b['summary'] . (string)$b['title'], $mood) !== false ? 1 : 0; return $bHit - $aHit; }); } $this->success('', [ 'list' => $data['list'], 'today_mood' => $mood, 'tip' => '情绪上头时,先照顾身体,再处理问题', 'hotline' => ['name' => '心理援助热线', 'phone' => '12356'], ]); } /** * 情绪列表 * GET limit=20 month=2026-11 */ public function index() { $userId = $this->auth->id; $limit = min(100, max(1, (int)$this->request->param('limit', 20))); $month = $this->request->param('month', ''); $query = Db::name('mood_log') ->where('user_id', $userId) ->whereNull('deletetime'); if ($month && Validate::regex($month, '/^\d{4}-\d{2}$/')) { $query->whereBetween('log_date', [$month . '-01', date('Y-m-t', strtotime($month . '-01'))]); } $list = $query->order('log_date', 'desc')->order('id', 'desc')->limit($limit)->select(); $list = array_map([$this, 'format'], $list); $this->success('', ['list' => $list, 'moods' => $this->moodOptions()]); } /** * 情绪趋势 * GET days=7|30 */ public function trend() { $userId = $this->auth->id; $days = (int)$this->request->param('days', 7); $days = in_array($days, [7, 14, 30]) ? $days : 7; $start = date('Y-m-d', strtotime('-' . ($days - 1) . ' day')); $logs = Db::name('mood_log') ->where('user_id', $userId) ->whereNull('deletetime') ->where('log_date', '>=', $start) ->order('log_date', 'asc') ->select(); $bucket = []; for ($i = $days - 1; $i >= 0; $i--) { $d = date('Y-m-d', strtotime('-' . $i . ' day')); $bucket[$d] = ['date' => $d, 'label' => date('n/j', strtotime($d)), 'score' => null, 'count' => 0, 'mood' => '']; } foreach ($logs as $log) { if (!isset($bucket[$log['log_date']])) { continue; } $score = self::$moods[$log['mood']]['score'] ?? 3; $item = &$bucket[$log['log_date']]; $item['count']++; $item['score'] = $item['score'] === null ? $score : round(($item['score'] * ($item['count'] - 1) + $score) / $item['count'], 1); $item['mood'] = $log['mood']; unset($item); } $recorded = array_values(array_filter($bucket, function ($v) { return $v['score'] !== null; })); $avg = $recorded ? round(array_sum(array_column($recorded, 'score')) / count($recorded), 1) : 0; // 主情绪统计 $count = []; foreach ($logs as $log) { $count[$log['mood']] = isset($count[$log['mood']]) ? $count[$log['mood']] + 1 : 1; } arsort($count); $topMood = key($count) ?: ''; $this->success('', [ 'days' => $days, 'list' => array_values($bucket), 'recorded' => count($recorded), 'avg_score' => $avg, 'top_mood' => $topMood ? array_merge(['key' => $topMood], self::$moods[$topMood]) : null, 'moods' => $this->moodOptions(), ]); } /** * 删除一条情绪记录 */ public function remove() { $id = (int)$this->request->post('id', 0); $row = Db::name('mood_log')->where('id', $id)->where('user_id', $this->auth->id)->find(); if (!$row) { $this->error('记录不存在'); } Db::name('mood_log')->where('id', $id)->update(['deletetime' => time()]); $this->success('已删除'); } protected function moodOptions() { $list = []; foreach (self::$moods as $key => $item) { $list[] = array_merge(['key' => $key], $item); } return $list; } protected function format($log) { $mood = self::$moods[$log['mood']] ?? ['text' => '', 'emoji' => '', 'score' => 0, 'color' => '']; return [ 'id' => (int)$log['id'], 'log_date' => $log['log_date'], 'date_text' => date('n月j日', strtotime($log['log_date'])), 'week_text' => '周' . ['日', '一', '二', '三', '四', '五', '六'][(int)date('w', strtotime($log['log_date']))], 'mood' => $log['mood'], 'mood_text' => $mood['text'], 'emoji' => $mood['emoji'], 'color' => $mood['color'], 'intensity' => (int)$log['intensity'], 'triggers' => $log['triggers'], 'content' => $log['content'], 'time_text' => date('H:i', (int)$log['createtime']), ]; } }