| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704 |
- <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">🧠</text>
- </view>
- <view class="scale-info">
- <text class="scale-name">PHQ-9 �煾�蝑𥟇䰻</text>
- <text class="scale-desc">餈�縧銝文𪂹嚗峕��臬炏鋡思誑銝钅䔮憸睃𤌴�堆�</text>
- </view>
- <text class="scale-arrow">></text>
- </view>
- <view class="scale-card" @click="startScreen('GAD7')">
- <view class="scale-icon-wrap" style="background:#F0F4FF">
- <text class="scale-icon">💨</text>
- </view>
- <view class="scale-info">
- <text class="scale-name">GAD-7 �西�蝑𥟇䰻</text>
- <text class="scale-desc">餈�縧銝文𪂹嚗峕��臬炏鋡思誑銝钅䔮憸睃𤌴�堆�</text>
- </view>
- <text class="scale-arrow">></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">⚠️</text>
- <text class="risk-text">{{ riskFlagLabel(flag) }}</text>
- </view>
- </view>
- <!-- �望㦤�剔瑪 -->
- <view class="crisis-banner" v-if="showCrisisBanner">
- <text class="crisis-title">🚨 ��閬�葬�抬�</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>
|