Forráskód Böngészése

feat(mind): add PHQ-9/GAD-7 screening page and route

Create screening.vue with full PHQ-9/GAD-7 questionnaire, scoring display, severity classification, crisis banner, and navigation. Register screening route in pages.json under mind-detail subpackage.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Xiaogang Liao 2 hónapja
szülő
commit
9a4bb05256

+ 4 - 0
cfc-frontend/pages.json

@@ -641,6 +641,10 @@
         {
           "path": "soothe-toolbox",
           "style": { "navigationBarTitleText": "疏导工具箱" }
+        },
+        {
+          "path": "screening",
+          "style": { "navigationBarTitleText": "心理状态自评" }
         }
       ]
     },

+ 283 - 0
cfc-frontend/pages/mind-detail/screening.vue

@@ -0,0 +1,283 @@
+<template>
+  <view class="screen-container">
+    <view class="screen-header">
+      <text class="screen-title">心理状态自评</text>
+      <text class="screen-subtitle">定期评估,了解自己的心理状态</text>
+    </view>
+
+    <view class="section" v-if="!currentScreen">
+      <view class="scale-card" @click="startScreen('PHQ9')">
+        <view class="scale-icon-wrap" style="background:#FFF0F5">
+          <text class="scale-icon">&#x1F9E0;</text>
+        </view>
+        <view class="scale-info">
+          <text class="scale-name">PHQ-9 抑郁筛查</text>
+          <text class="scale-desc">过去两周,您是否被以下问题困扰?</text>
+        </view>
+        <text class="scale-arrow">&gt;</text>
+      </view>
+      <view class="scale-card" @click="startScreen('GAD7')">
+        <view class="scale-icon-wrap" style="background:#F0F4FF">
+          <text class="scale-icon">&#x1F4A8;</text>
+        </view>
+        <view class="scale-info">
+          <text class="scale-name">GAD-7 焦虑筛查</text>
+          <text class="scale-desc">过去两周,您是否被以下问题困扰?</text>
+        </view>
+        <text class="scale-arrow">&gt;</text>
+      </view>
+    </view>
+
+    <view class="section" v-if="currentScreen">
+      <view class="quiz-header">
+        <text class="quiz-title">{{ currentScreen === 'PHQ9' ? 'PHQ-9 抑郁筛查' : 'GAD-7 焦虑筛查' }}</text>
+        <text class="quiz-progress">{{ currentStep + 1 }}/{{ questions.length }}</text>
+      </view>
+      <view class="progress-track">
+        <view class="progress-fill" :style="{ width: ((currentStep + 1) / questions.length * 100) + '%' }"></view>
+      </view>
+
+      <view class="question-card">
+        <text class="question-num">Q{{ currentStep + 1 }}</text>
+        <text class="question-text">{{ questions[currentStep] }}</text>
+      </view>
+
+      <view class="options-list">
+        <view
+          v-for="(opt, oi) in answerOptions"
+          :key="oi"
+          :class="['option-btn', answers[currentStep] === oi ? 'option-active' : '']"
+          @click="selectAnswer(oi)">
+          <view :class="['option-radio', answers[currentStep] === oi ? 'radio-checked' : '']">
+            <view v-if="answers[currentStep] === oi" class="radio-dot"></view>
+          </view>
+          <text class="option-text">{{ opt }}</text>
+        </view>
+      </view>
+
+      <view class="quiz-nav">
+        <button class="nav-btn prev-btn" v-if="currentStep > 0" @click="prevStep">上一题</button>
+        <button class="nav-btn next-btn" v-if="currentStep < questions.length - 1" @click="nextStep">下一题</button>
+        <button class="nav-btn submit-btn" v-if="currentStep === questions.length - 1" @click="submitScreen">提交问卷</button>
+      </view>
+    </view>
+
+    <view class="section" v-if="result">
+      <view class="result-header">
+        <text class="result-type">{{ currentScreen === 'PHQ9' ? 'PHQ-9 抑郁筛查' : 'GAD-7 焦虑筛查' }}</text>
+        <view :class="['result-score-circle', severityClass]">
+          <text class="result-score">{{ result.totalScore }}</text>
+          <text class="result-score-label">分</text>
+        </view>
+        <text :class="['result-severity', severityClass]">{{ severityLabel }}</text>
+      </view>
+
+      <view class="suggestion-card">
+        <text class="suggestion-title">评估建议</text>
+        <text class="suggestion-text">{{ result.suggestions }}</text>
+      </view>
+
+      <view class="risk-section" v-if="result.riskFlags && result.riskFlags.length > 0">
+        <view class="risk-item" v-for="flag in result.riskFlags" :key="flag">
+          <text class="risk-icon">&#x26A0;&#xFE0F;</text>
+          <text class="risk-text">{{ riskFlagLabel(flag) }}</text>
+        </view>
+      </view>
+
+      <view class="crisis-banner" v-if="showCrisisBanner">
+        <text class="crisis-title">&#x1F6A8; 需要帮助?</text>
+        <text class="crisis-phone">全国心理危机干预热线</text>
+        <text class="crisis-number">400-161-9995</text>
+        <text class="crisis-hint">24小时 · 免费 · 专业</text>
+      </view>
+
+      <view class="result-actions">
+        <button class="action-btn primary-btn" @click="goTrend">查看情绪趋势</button>
+        <button class="action-btn secondary-btn" @click="resetScreen">再测一次</button>
+      </view>
+    </view>
+
+    <view class="loading-mask" v-if="submitting">
+      <view class="loading-box">
+        <text class="loading-text">提交中...</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import config from '../../config'
+
+export default {
+  data() {
+    return {
+      currentScreen: null,
+      currentStep: 0,
+      answers: [],
+      submitting: false,
+      result: null,
+      phq9Questions: [
+        '\u505A\u4E8B\u65F6\u63D0\u4E0D\u8D77\u52B2\u6216\u6CA1\u6709\u5174\u8DA3',
+        '\u611F\u5230\u5FC3\u60C5\u4F4E\u843D\u3001\u6CAE\u4E27\u6216\u7EDD\u671B',
+        '\u5165\u7761\u56F0\u96BE\u3001\u7761\u4E0D\u5B89\u7A33\u6216\u7761\u7720\u8FC7\u591A',
+        '\u611F\u89C9\u75B2\u4E4F\u6216\u6CA1\u6709\u6D3B\u529B',
+        '\u98DF\u6B32\u4E0D\u632F\u6216\u5403\u592A\u591A',
+        '\u89C9\u5F97\u81EA\u5DF1\u5F88\u7CDF\u2014\u2014\u6216\u89C9\u5F97\u81EA\u5DF1\u5F88\u5931\u8D25',
+        '\u5BF9\u4E8B\u7269\u4E13\u6CE8\u6709\u56F0\u96BE',
+        '\u884C\u52A8\u6216\u8BF4\u8BDD\u901F\u5EA6\u7F13\u6162',
+        '\u6709\u4E0D\u5982\u6B7B\u6389\u6216\u4F24\u5BB3\u81EA\u5DF1\u7684\u5FF5\u5934'
+      ],
+      gad7Questions: [
+        '\u611F\u5230\u7D27\u5F20\u3001\u7126\u8651\u6216\u70E6\u8E81',
+        '\u65E0\u6CD5\u505C\u6B62\u6216\u63A7\u5236\u62C5\u5FE7',
+        '\u5BF9\u5404\u79CD\u5404\u6837\u7684\u4E8B\u60C5\u62C5\u5FE7\u8FC7\u591A',
+        '\u5F88\u96BE\u653E\u677E\u4E0B\u6765',
+        '\u7531\u4E8E\u4E0D\u5B89\u800C\u65E0\u6CD5\u9759\u5750',
+        '\u53D8\u5F97\u5BB9\u6613\u70E6\u607C\u6216\u6025\u8E81',
+        '\u611F\u5230\u5BB3\u6015\uFF0C\u597D\u50CF\u53EF\u80FD\u53D1\u751F\u53EF\u6015\u7684\u4E8B\u60C5'
+      ],
+      answerOptions: ['\u5B8C\u5168\u4E0D\u4F1A', '\u597D\u51E0\u5929', '\u4E00\u534A\u4EE5\u4E0A\u7684\u5929\u6570', '\u51E0\u4E4E\u6BCF\u5929'],
+      riskFlagLabels: {
+        'suicide_ideation': '存在自杀/自伤相关念头,请立即寻求帮助',
+        'core_depression_symptoms': '核心抑郁症状明显,建议关注',
+        'core_anxiety_symptoms': '核心焦虑症状明显,建议关注'
+      }
+    }
+  },
+
+  computed: {
+    questions() {
+      if (this.currentScreen === 'PHQ9') return this.phq9Questions
+      if (this.currentScreen === 'GAD7') return this.gad7Questions
+      return []
+    },
+    severityLabel() {
+      if (!this.result) return ''
+      var map = { 'none': '状态良好', 'mild': '轻度', 'moderate': '中度', 'moderately_severe': '中重度', 'severe': '重度' }
+      return map[this.result.severityLevel] || this.result.severityLevel
+    },
+    severityClass() {
+      if (!this.result) return ''
+      var map = { 'none': 'severity-good', 'mild': 'severity-mild', 'moderate': 'severity-moderate', 'moderately_severe': 'severity-moderate', 'severe': 'severity-severe' }
+      return map[this.result.severityLevel] || ''
+    },
+    showCrisisBanner() {
+      return this.result && this.result.riskFlags && this.result.riskFlags.indexOf('suicide_ideation') !== -1
+    }
+  },
+
+  methods: {
+    startScreen(type) {
+      this.currentScreen = type
+      this.currentStep = 0
+      this.answers = []
+      this.result = null
+      var count = type === 'PHQ9' ? 9 : 7
+      for (var i = 0; i < count; i++) { this.answers.push(-1) }
+    },
+    selectAnswer(oi) {
+      var newAnswers = this.answers.slice()
+      newAnswers[this.currentStep] = oi
+      this.answers = newAnswers
+    },
+    nextStep() {
+      if (this.answers[this.currentStep] === -1) { uni.showToast({ title: '请先选择一项', icon: 'none' }); return }
+      this.currentStep++
+    },
+    prevStep() {
+      if (this.currentStep > 0) this.currentStep--
+    },
+    submitScreen() {
+      for (var i = 0; i < this.answers.length; i++) {
+        if (this.answers[i] === -1) { uni.showToast({ title: '请回答所有问题', icon: 'none' }); this.currentStep = i; return }
+      }
+      this.submitting = true
+      const app = getApp()
+      const childId = app.globalData.currentChildId
+      uni.request({
+        url: config.API_BASE_URL + '/api/mind/screening/submit',
+        method: 'POST',
+        data: { childId, screenType: this.currentScreen, answers: this.answers },
+        success: (res) => {
+          this.submitting = false
+          if (res.data && res.data.code === 200) { this.result = res.data.data }
+          else { uni.showToast({ title: (res.data && res.data.message) || '提交失败', icon: 'none' }) }
+        },
+        fail: () => { this.submitting = false; uni.showToast({ title: '网络错误', icon: 'none' }) }
+      })
+    },
+    resetScreen() { this.currentScreen = null; this.currentStep = 0; this.answers = []; this.result = null },
+    goTrend() { uni.navigateTo({ url: '/pages/mind-detail/emotion-trend' }) },
+    riskFlagLabel(flag) { return this.riskFlagLabels[flag] || flag }
+  }
+}
+</script>
+
+<style scoped>
+.screen-container { min-height: 100vh; background: linear-gradient(180deg, #F0F4FF 0%, #FFFFFF 100%); padding-bottom: 40rpx; }
+.screen-header { padding: 40rpx 32rpx 20rpx; }
+.screen-title { font-size: 36rpx; font-weight: 700; color: #333; display: block; }
+.screen-subtitle { font-size: 26rpx; color: #999; margin-top: 8rpx; display: block; }
+.section { margin: 20rpx 32rpx; background: #fff; border-radius: 20rpx; padding: 28rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.04); }
+.scale-card { display: flex; align-items: center; padding: 24rpx; background: #FAFAFA; border-radius: 16rpx; margin-bottom: 16rpx; gap: 20rpx; }
+.scale-icon-wrap { width: 72rpx; height: 72rpx; border-radius: 36rpx; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
+.scale-icon { font-size: 36rpx; }
+.scale-info { flex: 1; }
+.scale-name { font-size: 28rpx; font-weight: 600; color: #333; display: block; }
+.scale-desc { font-size: 22rpx; color: #999; margin-top: 4rpx; display: block; }
+.scale-arrow { font-size: 28rpx; color: #ccc; }
+.quiz-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16rpx; }
+.quiz-title { font-size: 28rpx; font-weight: 600; color: #333; }
+.quiz-progress { font-size: 24rpx; color: #999; }
+.progress-track { height: 6rpx; background: #F0F0F0; border-radius: 3rpx; margin-bottom: 24rpx; overflow: hidden; }
+.progress-fill { height: 100%; background: linear-gradient(90deg, #6366F1, #8B5CF6); border-radius: 3rpx; transition: width 0.3s; }
+.question-card { background: #F8F6FF; border-radius: 16rpx; padding: 24rpx; margin-bottom: 24rpx; }
+.question-num { font-size: 22rpx; color: #8B5CF6; font-weight: 600; display: block; margin-bottom: 8rpx; }
+.question-text { font-size: 30rpx; color: #333; line-height: 1.5; }
+.options-list { display: flex; flex-direction: column; gap: 12rpx; }
+.option-btn { display: flex; align-items: center; padding: 20rpx 24rpx; border-radius: 14rpx; border: 2rpx solid #F0F0F0; gap: 16rpx; }
+.option-active { border-color: #8B5CF6; background: #F8F6FF; }
+.option-radio { width: 40rpx; height: 40rpx; border-radius: 20rpx; border: 3rpx solid #D0D0D0; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
+.radio-checked { border-color: #8B5CF6; }
+.radio-dot { width: 22rpx; height: 22rpx; border-radius: 11rpx; background: #8B5CF6; }
+.option-text { font-size: 28rpx; color: #444; }
+.option-active .option-text { color: #333; font-weight: 500; }
+.quiz-nav { display: flex; gap: 16rpx; margin-top: 32rpx; }
+.nav-btn { flex: 1; height: 80rpx; line-height: 80rpx; border-radius: 40rpx; font-size: 28rpx; text-align: center; }
+.prev-btn { background: #F0F0F0; color: #666; }
+.next-btn { background: #6366F1; color: #fff; }
+.submit-btn { background: linear-gradient(135deg, #6366F1, #8B5CF6); color: #fff; }
+.result-header { display: flex; flex-direction: column; align-items: center; padding: 20rpx 0; }
+.result-type { font-size: 24rpx; color: #999; margin-bottom: 16rpx; }
+.result-score-circle { width: 120rpx; height: 120rpx; border-radius: 60rpx; display: flex; flex-direction: column; align-items: center; justify-content: center; margin-bottom: 12rpx; }
+.result-score { font-size: 48rpx; font-weight: 700; color: #fff; line-height: 1; }
+.result-score-label { font-size: 20rpx; color: rgba(255,255,255,0.8); margin-top: 2rpx; }
+.result-severity { font-size: 30rpx; font-weight: 600; }
+.severity-good { background: #10B981; color: #10B981; }
+.severity-mild { background: #F59E0B; color: #F59E0B; }
+.severity-moderate { background: #FF8C42; color: #FF8C42; }
+.severity-severe { background: #EF4444; color: #EF4444; }
+.result-score-circle.severity-good { background: #10B981; }
+.result-score-circle.severity-mild { background: #F59E0B; }
+.result-score-circle.severity-moderate { background: #FF8C42; }
+.result-score-circle.severity-severe { background: #EF4444; }
+.suggestion-card { background: #F0FFF4; border-radius: 14rpx; padding: 20rpx; margin-top: 16rpx; }
+.suggestion-title { font-size: 24rpx; color: #10B981; font-weight: 600; display: block; margin-bottom: 8rpx; }
+.suggestion-text { font-size: 26rpx; color: #555; line-height: 1.6; }
+.risk-section { margin-top: 16rpx; }
+.risk-item { display: flex; align-items: flex-start; gap: 8rpx; padding: 12rpx 16rpx; background: #FFF5F5; border-radius: 12rpx; margin-bottom: 8rpx; }
+.risk-icon { font-size: 24rpx; flex-shrink: 0; }
+.risk-text { font-size: 24rpx; color: #E53E3E; line-height: 1.5; }
+.crisis-banner { margin-top: 16rpx; padding: 24rpx; background: linear-gradient(135deg, #FF6B6B, #E53E3E); border-radius: 16rpx; text-align: center; }
+.crisis-title { font-size: 28rpx; color: #fff; font-weight: 700; display: block; }
+.crisis-phone { font-size: 22rpx; color: rgba(255,255,255,0.8); margin-top: 12rpx; display: block; }
+.crisis-number { font-size: 40rpx; color: #fff; font-weight: 700; margin-top: 4rpx; display: block; letter-spacing: 2rpx; }
+.crisis-hint { font-size: 20rpx; color: rgba(255,255,255,0.7); margin-top: 4rpx; display: block; }
+.result-actions { display: flex; gap: 16rpx; margin-top: 28rpx; }
+.action-btn { flex: 1; height: 76rpx; line-height: 76rpx; border-radius: 38rpx; font-size: 26rpx; text-align: center; }
+.primary-btn { background: #FF6B9D; color: #fff; }
+.secondary-btn { background: #F0F0F0; color: #666; }
+.loading-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.3); display: flex; align-items: center; justify-content: center; z-index: 999; }
+.loading-box { background: #fff; padding: 40rpx 60rpx; border-radius: 20rpx; }
+.loading-text { font-size: 28rpx; color: #666; }
+</style>

+ 704 - 0
cfc-frontend/pages/mind/screening.vue

@@ -0,0 +1,704 @@
+<template>
+  <view class="screen-container">
+    <!-- 头部 -->
+    <view class="screen-header">
+      <text class="screen-title">心理状态自评</text>
+      <text class="screen-subtitle">定期评估,了解自己的心理状态</text>
+    </view>
+
+    <!-- 量表选择 -->
+    <view class="section" v-if="!currentScreen">
+      <view class="scale-card" @click="startScreen('PHQ9')">
+        <view class="scale-icon-wrap" style="background:#FFF0F5">
+          <text class="scale-icon">&#x1F9E0;</text>
+        </view>
+        <view class="scale-info">
+          <text class="scale-name">PHQ-9 抑郁筛查</text>
+          <text class="scale-desc">过去两周,您是否被以下问题困扰?</text>
+        </view>
+        <text class="scale-arrow">&gt;</text>
+      </view>
+      <view class="scale-card" @click="startScreen('GAD7')">
+        <view class="scale-icon-wrap" style="background:#F0F4FF">
+          <text class="scale-icon">&#x1F4A8;</text>
+        </view>
+        <view class="scale-info">
+          <text class="scale-name">GAD-7 焦虑筛查</text>
+          <text class="scale-desc">过去两周,您是否被以下问题困扰?</text>
+        </view>
+        <text class="scale-arrow">&gt;</text>
+      </view>
+    </view>
+
+    <!-- 问卷页面 -->
+    <view class="section" v-if="currentScreen">
+      <view class="quiz-header">
+        <text class="quiz-title">{{ currentScreen === 'PHQ9' ? 'PHQ-9 抑郁筛查' : 'GAD-7 焦虑筛查' }}</text>
+        <text class="quiz-progress">{{ currentStep + 1 }}/{{ questions.length }}</text>
+      </view>
+      <view class="progress-track">
+        <view class="progress-fill" :style="{ width: ((currentStep + 1) / questions.length * 100) + '%' }"></view>
+      </view>
+
+      <!-- 当前问题 -->
+      <view class="question-card">
+        <text class="question-num">Q{{ currentStep + 1 }}</text>
+        <text class="question-text">{{ questions[currentStep] }}</text>
+      </view>
+
+      <!-- 选项 -->
+      <view class="options-list">
+        <view
+          v-for="(opt, oi) in answerOptions"
+          :key="oi"
+          :class="['option-btn', answers[currentStep] === oi ? 'option-active' : '']"
+          @click="selectAnswer(oi)">
+          <view :class="['option-radio', answers[currentStep] === oi ? 'radio-checked' : '']">
+            <view v-if="answers[currentStep] === oi" class="radio-dot"></view>
+          </view>
+          <text class="option-text">{{ opt }}</text>
+        </view>
+      </view>
+
+      <!-- 导航按钮 -->
+      <view class="quiz-nav">
+        <button class="nav-btn prev-btn" v-if="currentStep > 0" @click="prevStep">上一题</button>
+        <button class="nav-btn next-btn" v-if="currentStep < questions.length - 1" @click="nextStep">下一题</button>
+        <button class="nav-btn submit-btn" v-if="currentStep === questions.length - 1" @click="submitScreen">提交问卷</button>
+      </view>
+    </view>
+
+    <!-- 结果页面 -->
+    <view class="section" v-if="result">
+      <view class="result-header">
+        <text class="result-type">{{ currentScreen === 'PHQ9' ? 'PHQ-9 抑郁筛查' : 'GAD-7 焦虑筛查' }}</text>
+        <view :class="['result-score-circle', severityClass]">
+          <text class="result-score">{{ result.totalScore }}</text>
+          <text class="result-score-label">分</text>
+        </view>
+        <text :class="['result-severity', severityClass]">{{ severityLabel }}</text>
+      </view>
+
+      <!-- 自动建议 -->
+      <view class="suggestion-card">
+        <text class="suggestion-title">评估建议</text>
+        <text class="suggestion-text">{{ result.suggestions }}</text>
+      </view>
+
+      <!-- 风险标志 -->
+      <view class="risk-section" v-if="result.riskFlags && result.riskFlags.length > 0">
+        <view class="risk-item" v-for="flag in result.riskFlags" :key="flag">
+          <text class="risk-icon">&#x26A0;&#xFE0F;</text>
+          <text class="risk-text">{{ riskFlagLabel(flag) }}</text>
+        </view>
+      </view>
+
+      <!-- 危机热线 -->
+      <view class="crisis-banner" v-if="showCrisisBanner">
+        <text class="crisis-title">&#x1F6A8; 需要帮助?</text>
+        <text class="crisis-phone">全国心理危机干预热线</text>
+        <text class="crisis-number">400-161-9995</text>
+        <text class="crisis-hint">24小时 · 免费 · 专业</text>
+      </view>
+
+      <view class="result-actions">
+        <button class="action-btn primary-btn" @click="goTrend">查看情绪趋势</button>
+        <button class="action-btn secondary-btn" @click="resetScreen">再测一次</button>
+      </view>
+    </view>
+
+    <!-- 提交中 / 历史记录  -->
+    <view class="loading-mask" v-if="submitting">
+      <view class="loading-box">
+        <text class="loading-text">提交中...</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import config from '../../config'
+
+export default {
+  data() {
+    return {
+      currentScreen: null,    // null / 'PHQ9' / 'GAD7'
+      currentStep: 0,
+      answers: [],
+      submitting: false,
+      result: null,
+
+      // PHQ-9 题目
+      phq9Questions: [
+        '做事时提不起劲或没有兴趣',
+        '感到心情低落、沮丧或绝望',
+        '入睡困难、睡不安稳或睡眠过多',
+        '感觉疲倦或没有活力',
+        '食欲不振或吃太多',
+        '觉得自己很糟——或觉得自己很失败,或让自己或家人失望',
+        '对事物专注有困难,例如阅读报纸或看电视时',
+        '行动或说话速度缓慢到别人已经觉察?或正好相反——比平常更多话',
+        '有不如死掉或用某种方式伤害自己的念头'
+      ],
+
+      // GAD-7 题目
+      gad7Questions: [
+        '感到紧张、焦虑或烦躁',
+        '无法停止或控制担忧',
+        '对各种各样的事情担忧过多',
+        '很难放松下来',
+        '由于不安而无法静坐',
+        '变得容易烦恼或急躁',
+        '感到害怕,好像可能发生可怕的事情'
+      ],
+
+      answerOptions: [
+        '完全不会',
+        '好几天',
+        '一半以上的天数',
+        '几乎每天'
+      ],
+
+      riskFlagLabels: {
+        'suicide_ideation': '存在自杀/自伤相关念头,请立即寻求帮助',
+        'core_depression_symptoms': '核心抑郁症状明显,建议关注',
+        'core_anxiety_symptoms': '核心焦虑症状明显,建议关注'
+      }
+    }
+  },
+
+  computed: {
+    questions() {
+      if (this.currentScreen === 'PHQ9') return this.phq9Questions
+      if (this.currentScreen === 'GAD7') return this.gad7Questions
+      return []
+    },
+
+    severityLabel() {
+      if (!this.result) return ''
+      var map = {
+        'none': '状态良好',
+        'mild': '轻度',
+        'moderate': '中度',
+        'moderately_severe': '中重度',
+        'severe': '重度'
+      }
+      return map[this.result.severityLevel] || this.result.severityLevel
+    },
+
+    severityClass() {
+      if (!this.result) return ''
+      var map = {
+        'none': 'severity-good',
+        'mild': 'severity-mild',
+        'moderate': 'severity-moderate',
+        'moderately_severe': 'severity-moderate',
+        'severe': 'severity-severe'
+      }
+      return map[this.result.severityLevel] || ''
+    },
+
+    showCrisisBanner() {
+      if (!this.result || !this.result.riskFlags) return false
+      return this.result.riskFlags.indexOf('suicide_ideation') !== -1
+    }
+  },
+
+  onLoad() {
+    // 加载历史记录(可选)
+  },
+
+  methods: {
+    startScreen(type) {
+      this.currentScreen = type
+      this.currentStep = 0
+      this.answers = []
+      this.result = null
+      var count = type === 'PHQ9' ? 9 : 7
+      for (var i = 0; i < count; i++) {
+        this.answers.push(-1)
+      }
+    },
+
+    selectAnswer(oi) {
+      var newAnswers = this.answers.slice()
+      newAnswers[this.currentStep] = oi
+      this.answers = newAnswers
+    },
+
+    nextStep() {
+      if (this.answers[this.currentStep] === -1) {
+        uni.showToast({ title: '请先选择一项', icon: 'none' })
+        return
+      }
+      this.currentStep++
+    },
+
+    prevStep() {
+      if (this.currentStep > 0) this.currentStep--
+    },
+
+    submitScreen() {
+      // 检查所有题目是否已回答
+      for (var i = 0; i < this.answers.length; i++) {
+        if (this.answers[i] === -1) {
+          uni.showToast({ title: '请回答所有问题', icon: 'none' })
+          this.currentStep = i
+          return
+        }
+      }
+
+      this.submitting = true
+
+      const app = getApp()
+      const childId = app.globalData.currentChildId
+
+      uni.request({
+        url: config.API_BASE_URL + '/api/mind/screening/submit',
+        method: 'POST',
+        data: {
+          childId: childId,
+          screenType: this.currentScreen,
+          answers: this.answers
+        },
+        success: (res) => {
+          this.submitting = false
+          if (res.data && res.data.code === 200) {
+            this.result = res.data.data
+          } else {
+            uni.showToast({ title: res.data && res.data.message || '提交失败', icon: 'none' })
+          }
+        },
+        fail: () => {
+          this.submitting = false
+          uni.showToast({ title: '网络错误', icon: 'none' })
+        }
+      })
+    },
+
+    resetScreen() {
+      this.currentScreen = null
+      this.currentStep = 0
+      this.answers = []
+      this.result = null
+    },
+
+    goTrend() {
+      uni.navigateTo({ url: '/pages/mind/emotion-trend' })
+    },
+
+    riskFlagLabel(flag) {
+      return this.riskFlagLabels[flag] || flag
+    }
+  }
+}
+</script>
+
+<style scoped>
+.screen-container {
+  min-height: 100vh;
+  background: linear-gradient(180deg, #F0F4FF 0%, #FFFFFF 100%);
+  padding-bottom: 40rpx;
+}
+
+.screen-header {
+  padding: 40rpx 32rpx 20rpx;
+}
+
+.screen-title {
+  font-size: 36rpx;
+  font-weight: 700;
+  color: #333;
+  display: block;
+}
+
+.screen-subtitle {
+  font-size: 26rpx;
+  color: #999;
+  margin-top: 8rpx;
+  display: block;
+}
+
+.section {
+  margin: 20rpx 32rpx;
+  background: #fff;
+  border-radius: 20rpx;
+  padding: 28rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
+}
+
+/* ===== 量表选择 ===== */
+.scale-card {
+  display: flex;
+  align-items: center;
+  padding: 24rpx;
+  background: #FAFAFA;
+  border-radius: 16rpx;
+  margin-bottom: 16rpx;
+  gap: 20rpx;
+}
+
+.scale-card:active {
+  background: #F0F0F0;
+}
+
+.scale-icon-wrap {
+  width: 72rpx;
+  height: 72rpx;
+  border-radius: 36rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
+}
+
+.scale-icon {
+  font-size: 36rpx;
+}
+
+.scale-info {
+  flex: 1;
+}
+
+.scale-name {
+  font-size: 28rpx;
+  font-weight: 600;
+  color: #333;
+  display: block;
+}
+
+.scale-desc {
+  font-size: 22rpx;
+  color: #999;
+  margin-top: 4rpx;
+  display: block;
+}
+
+.scale-arrow {
+  font-size: 28rpx;
+  color: #ccc;
+}
+
+/* ===== 问卷 ===== */
+.quiz-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 16rpx;
+}
+
+.quiz-title {
+  font-size: 28rpx;
+  font-weight: 600;
+  color: #333;
+}
+
+.quiz-progress {
+  font-size: 24rpx;
+  color: #999;
+}
+
+.progress-track {
+  height: 6rpx;
+  background: #F0F0F0;
+  border-radius: 3rpx;
+  margin-bottom: 24rpx;
+  overflow: hidden;
+}
+
+.progress-fill {
+  height: 100%;
+  background: linear-gradient(90deg, #6366F1, #8B5CF6);
+  border-radius: 3rpx;
+  transition: width 0.3s;
+}
+
+.question-card {
+  background: #F8F6FF;
+  border-radius: 16rpx;
+  padding: 24rpx;
+  margin-bottom: 24rpx;
+}
+
+.question-num {
+  font-size: 22rpx;
+  color: #8B5CF6;
+  font-weight: 600;
+  display: block;
+  margin-bottom: 8rpx;
+}
+
+.question-text {
+  font-size: 30rpx;
+  color: #333;
+  line-height: 1.5;
+}
+
+.options-list {
+  display: flex;
+  flex-direction: column;
+  gap: 12rpx;
+}
+
+.option-btn {
+  display: flex;
+  align-items: center;
+  padding: 20rpx 24rpx;
+  border-radius: 14rpx;
+  border: 2rpx solid #F0F0F0;
+  gap: 16rpx;
+}
+
+.option-active {
+  border-color: #8B5CF6;
+  background: #F8F6FF;
+}
+
+.option-radio {
+  width: 40rpx;
+  height: 40rpx;
+  border-radius: 20rpx;
+  border: 3rpx solid #D0D0D0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
+}
+
+.radio-checked {
+  border-color: #8B5CF6;
+}
+
+.radio-dot {
+  width: 22rpx;
+  height: 22rpx;
+  border-radius: 11rpx;
+  background: #8B5CF6;
+}
+
+.option-text {
+  font-size: 28rpx;
+  color: #444;
+}
+
+.option-active .option-text {
+  color: #333;
+  font-weight: 500;
+}
+
+.quiz-nav {
+  display: flex;
+  gap: 16rpx;
+  margin-top: 32rpx;
+}
+
+.nav-btn {
+  flex: 1;
+  height: 80rpx;
+  line-height: 80rpx;
+  border-radius: 40rpx;
+  font-size: 28rpx;
+  text-align: center;
+}
+
+.prev-btn {
+  background: #F0F0F0;
+  color: #666;
+}
+
+.next-btn {
+  background: #6366F1;
+  color: #fff;
+}
+
+.submit-btn {
+  background: linear-gradient(135deg, #6366F1, #8B5CF6);
+  color: #fff;
+}
+
+/* ===== 结果 ===== */
+.result-header {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 20rpx 0;
+}
+
+.result-type {
+  font-size: 24rpx;
+  color: #999;
+  margin-bottom: 16rpx;
+}
+
+.result-score-circle {
+  width: 120rpx;
+  height: 120rpx;
+  border-radius: 60rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 12rpx;
+}
+
+.result-score {
+  font-size: 48rpx;
+  font-weight: 700;
+  color: #fff;
+  line-height: 1;
+}
+
+.result-score-label {
+  font-size: 20rpx;
+  color: rgba(255,255,255,0.8);
+  margin-top: 2rpx;
+}
+
+.result-severity {
+  font-size: 30rpx;
+  font-weight: 600;
+}
+
+.severity-good { background: #10B981; color: #10B981; }
+.severity-mild { background: #F59E0B; color: #F59E0B; }
+.severity-moderate { background: #FF8C42; color: #FF8C42; }
+.severity-severe { background: #EF4444; color: #EF4444; }
+
+.result-score-circle.severity-good { background: #10B981; }
+.result-score-circle.severity-mild { background: #F59E0B; }
+.result-score-circle.severity-moderate { background: #FF8C42; }
+.result-score-circle.severity-severe { background: #EF4444; }
+
+.suggestion-card {
+  background: #F0FFF4;
+  border-radius: 14rpx;
+  padding: 20rpx;
+  margin-top: 16rpx;
+}
+
+.suggestion-title {
+  font-size: 24rpx;
+  color: #10B981;
+  font-weight: 600;
+  display: block;
+  margin-bottom: 8rpx;
+}
+
+.suggestion-text {
+  font-size: 26rpx;
+  color: #555;
+  line-height: 1.6;
+}
+
+.risk-section {
+  margin-top: 16rpx;
+}
+
+.risk-item {
+  display: flex;
+  align-items: flex-start;
+  gap: 8rpx;
+  padding: 12rpx 16rpx;
+  background: #FFF5F5;
+  border-radius: 12rpx;
+  margin-bottom: 8rpx;
+}
+
+.risk-icon {
+  font-size: 24rpx;
+  flex-shrink: 0;
+}
+
+.risk-text {
+  font-size: 24rpx;
+  color: #E53E3E;
+  line-height: 1.5;
+}
+
+.crisis-banner {
+  margin-top: 16rpx;
+  padding: 24rpx;
+  background: linear-gradient(135deg, #FF6B6B, #E53E3E);
+  border-radius: 16rpx;
+  text-align: center;
+}
+
+.crisis-title {
+  font-size: 28rpx;
+  color: #fff;
+  font-weight: 700;
+  display: block;
+}
+
+.crisis-phone {
+  font-size: 22rpx;
+  color: rgba(255,255,255,0.8);
+  margin-top: 12rpx;
+  display: block;
+}
+
+.crisis-number {
+  font-size: 40rpx;
+  color: #fff;
+  font-weight: 700;
+  margin-top: 4rpx;
+  display: block;
+  letter-spacing: 2rpx;
+}
+
+.crisis-hint {
+  font-size: 20rpx;
+  color: rgba(255,255,255,0.7);
+  margin-top: 4rpx;
+  display: block;
+}
+
+.result-actions {
+  display: flex;
+  gap: 16rpx;
+  margin-top: 28rpx;
+}
+
+.action-btn {
+  flex: 1;
+  height: 76rpx;
+  line-height: 76rpx;
+  border-radius: 38rpx;
+  font-size: 26rpx;
+  text-align: center;
+}
+
+.primary-btn {
+  background: #FF6B9D;
+  color: #fff;
+}
+
+.secondary-btn {
+  background: #F0F0F0;
+  color: #666;
+}
+
+.loading-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0, 0, 0, 0.3);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 999;
+}
+
+.loading-box {
+  background: #fff;
+  padding: 40rpx 60rpx;
+  border-radius: 20rpx;
+}
+
+.loading-text {
+  font-size: 28rpx;
+  color: #666;
+}
+</style>