소스 검색

fix(checkin): 修复打卡页面双标题、输入框过小、睡眠页多余功能、心情页样式缺失

- 饮食/运动打卡:移除重复的 card-title,输入框 padding 增大
- 睡眠打卡:移除照片上传和录音功能(不需要)
- 心情打卡:补全所有缺失的基础样式,修复布局混乱
Sisyphus 1 개월 전
부모
커밋
bdfdd34c88

+ 27 - 28
cfc-frontend/pages/growth/diet-checkin.vue

@@ -12,7 +12,6 @@
       <view class="card">
         <view class="card-accent"></view>
         <view class="card-body">
-          <text class="card-title">记录饮食</text>
           <view class="form-group">
             <text class="form-label">餐次 *</text>
             <view class="tag-row">
@@ -328,54 +327,54 @@ export default {
 .content { height: calc(100vh - 88rpx); }
 .card { margin: 16rpx 24rpx; background: #fff; border-radius: 20rpx; overflow: hidden; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .card-accent { height: 6rpx; background: linear-gradient(90deg, #FF8C42, #F97316); }
-.card-body { padding: 24rpx; }
+.card-body { padding: 28rpx; }
 .card-title { font-size: 30rpx; font-weight: bold; color: #333; margin-bottom: 20rpx; display: block; }
-.form-group { margin-bottom: 20rpx; }
-.form-label { font-size: 26rpx; color: #333; font-weight: 500; margin-bottom: 12rpx; display: block; }
+.form-group { margin-bottom: 24rpx; }
+.form-label { font-size: 28rpx; color: #333; font-weight: 600; margin-bottom: 12rpx; display: block; }
 .tag-row { display: flex; flex-wrap: wrap; gap: 12rpx; }
-.tag-btn { padding: 10rpx 24rpx; border-radius: 30rpx; border: 2rpx solid #e0e0e0; background: #fafafa; }
+.tag-btn { padding: 12rpx 28rpx; border-radius: 30rpx; border: 2rpx solid #e0e0e0; background: #fafafa; }
 .tag-active { border-color: #F97316; background: #FFF3E0; }
-.tag-btn text { font-size: 24rpx; color: #666; }
-.tag-active text { font-size: 24rpx; color: #F97316; font-weight: bold; }
-.form-textarea { width: 100%; height: 120rpx; border: 1rpx solid #e0e0e0; border-radius: 12rpx; padding: 16rpx; font-size: 26rpx; background: #FAFAFA; box-sizing: border-box; }
-.form-input { width: 100%; border: 1rpx solid #e0e0e0; border-radius: 12rpx; padding: 16rpx; font-size: 26rpx; background: #FAFAFA; box-sizing: border-box; }
+.tag-btn text { font-size: 26rpx; color: #666; }
+.tag-active text { font-size: 26rpx; color: #F97316; font-weight: bold; }
+.form-textarea { width: 100%; height: 140rpx; border: 1rpx solid #e0e0e0; border-radius: 16rpx; padding: 20rpx; font-size: 28rpx; background: #FAFAFA; box-sizing: border-box; }
+.form-input { width: 100%; height: 80rpx; border: 1rpx solid #e0e0e0; border-radius: 16rpx; padding: 0 20rpx; font-size: 28rpx; background: #FAFAFA; box-sizing: border-box; }
 /* 录入框下方的并排工具栏 */
-.media-toolbar { display: flex; align-items: center; margin-top: 16rpx; padding: 18rpx 0; border-top: 1rpx solid #f0f0f0; }
-.tool-btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 10rpx; padding: 8rpx 0; }
-.tool-icon { font-size: 36rpx; }
-.tool-label { font-size: 26rpx; color: #555; }
-.tool-count { font-size: 22rpx; color: #F97316; font-weight: bold; margin-left: 4rpx; }
-.tool-divider { width: 1rpx; height: 36rpx; background: #e8e8e8; }
+.media-toolbar { display: flex; align-items: center; margin: 16rpx 24rpx; padding: 24rpx 0; border-top: 1rpx solid #f0f0f0; }
+.tool-btn { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8rpx; padding: 16rpx 0; }
+.tool-icon { font-size: 48rpx; }
+.tool-label { font-size: 24rpx; color: #666; }
+.tool-count { font-size: 22rpx; color: #F97316; font-weight: bold; }
+.tool-divider { width: 1rpx; height: 60rpx; background: #e8e8e8; }
 
 /* 照片缩略图条 */
-.photo-strip { display: flex; flex-wrap: wrap; gap: 12rpx; padding: 16rpx 0 4rpx; }
-.photo-item { position: relative; width: 120rpx; height: 120rpx; }
+.photo-strip { display: flex; flex-wrap: wrap; gap: 12rpx; padding: 0 24rpx 4rpx; }
+.photo-item { position: relative; width: 140rpx; height: 140rpx; }
 .photo-img { width: 100%; height: 100%; border-radius: 12rpx; }
-.photo-delete-overlay { position: absolute; top: -6rpx; right: -6rpx; width: 32rpx; height: 32rpx; background: #EF4444; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2rpx 6rpx rgba(239,68,68,0.3); z-index: 2; }
-.delete-icon { color: #fff; font-size: 22rpx; font-weight: bold; line-height: 32rpx; }
+.photo-delete-overlay { position: absolute; top: -6rpx; right: -6rpx; width: 36rpx; height: 36rpx; background: #EF4444; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2rpx 6rpx rgba(239,68,68,0.3); z-index: 2; }
+.delete-icon { color: #fff; font-size: 24rpx; font-weight: bold; line-height: 36rpx; }
 
 /* 录音展开区 */
-.voice-strip { display: flex; align-items: center; justify-content: space-between; padding: 16rpx 0 4rpx; gap: 16rpx; }
+.voice-strip { display: flex; align-items: center; justify-content: space-between; padding: 16rpx 24rpx 4rpx; gap: 16rpx; }
 .waveform { display: flex; align-items: center; gap: 6rpx; height: 48rpx; flex: 1; }
 .wave-bar { width: 6rpx; height: 10rpx; background: #F97316; border-radius: 3rpx; animation: wave-anim 0.8s ease-in-out infinite; }
 @keyframes wave-anim { 0%, 100% { height: 10rpx; } 50% { height: 36rpx; } }
 .voice-controls { display: flex; gap: 16rpx; }
-.mini-btn { padding: 12rpx 24rpx; border-radius: 24rpx; font-size: 24rpx; }
+.mini-btn { padding: 12rpx 28rpx; border-radius: 24rpx; font-size: 26rpx; }
 .cancel-mini { background: #f0f0f0; color: #666; }
 .done-mini { background: #F97316; color: #fff; font-weight: bold; }
 
-.voice-player { display: flex; align-items: center; gap: 12rpx; flex: 1; background: #FFF3E0; padding: 12rpx 20rpx; border-radius: 30rpx; }
+.voice-player { display: flex; align-items: center; gap: 12rpx; flex: 1; background: #FFF3E0; padding: 12rpx 24rpx; border-radius: 30rpx; }
 .play-icon { font-size: 28rpx; color: #F97316; }
-.voice-duration { font-size: 24rpx; color: #666; }
-.delete-voice { width: 40rpx; height: 40rpx; display: flex; align-items: center; justify-content: center; color: #999; font-size: 32rpx; }
+.voice-duration { font-size: 26rpx; color: #666; }
+.delete-voice { width: 44rpx; height: 44rpx; display: flex; align-items: center; justify-content: center; color: #999; font-size: 32rpx; }
 .submit-wrap { padding: 24rpx 24rpx 40rpx; }
-.submit-btn { background: linear-gradient(135deg, #FF8C42, #F97316); color: #fff; text-align: center; padding: 24rpx 0; border-radius: 16rpx; font-size: 30rpx; font-weight: bold; }
+.submit-btn { background: linear-gradient(135deg, #FF8C42, #F97316); color: #fff; text-align: center; padding: 24rpx 0; border-radius: 16rpx; font-size: 32rpx; font-weight: bold; }
 .submitting { opacity: 0.6; }
 .history-list { display: flex; flex-direction: column; gap: 16rpx; }
 .history-item { display: flex; justify-content: space-between; align-items: center; padding: 12rpx 0; border-bottom: 1rpx solid #f5f5f5; }
 .history-left { flex: 1; min-width: 0; }
-.history-type { font-size: 26rpx; font-weight: 500; color: #333; display: block; }
-.history-content { font-size: 22rpx; color: #888; display: block; margin-top: 4rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.history-type { font-size: 28rpx; font-weight: 500; color: #333; display: block; }
+.history-content { font-size: 24rpx; color: #888; display: block; margin-top: 4rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
 .history-right { text-align: right; margin-left: 16rpx; flex-shrink: 0; }
-.history-date { font-size: 22rpx; color: #999; }
+.history-date { font-size: 24rpx; color: #999; }
 </style>

+ 26 - 30
cfc-frontend/pages/growth/exercise-checkin.vue

@@ -12,7 +12,6 @@
       <view class="card">
         <view class="card-accent"></view>
         <view class="card-body">
-          <text class="card-title">记录运动</text>
           <view class="form-group">
             <text class="form-label">运动类型 *</text>
             <view class="tag-row">
@@ -48,9 +47,6 @@
         </view>
       </view>
 
-
-
-      <!-- 录入工具栏 -->
       <!-- 并排两个按钮 + 展开区域 -->
       <view class="media-toolbar">
         <view class="tool-btn" @tap="choosePhoto">
@@ -347,52 +343,52 @@ export default {
 .content { height: calc(100vh - 88rpx); }
 .card { margin: 16rpx 24rpx; background: #fff; border-radius: 20rpx; overflow: hidden; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .card-accent { height: 6rpx; background: linear-gradient(90deg, #FF8C42, #F97316); }
-.card-body { padding: 24rpx; }
+.card-body { padding: 28rpx; }
 .card-title { font-size: 30rpx; font-weight: bold; color: #333; margin-bottom: 20rpx; display: block; }
-.form-group { margin-bottom: 20rpx; }
-.form-label { font-size: 26rpx; color: #333; font-weight: 500; margin-bottom: 12rpx; display: block; }
+.form-group { margin-bottom: 24rpx; }
+.form-label { font-size: 28rpx; color: #333; font-weight: 600; margin-bottom: 12rpx; display: block; }
 .tag-row { display: flex; flex-wrap: wrap; gap: 12rpx; }
-.tag-btn { padding: 10rpx 24rpx; border-radius: 30rpx; border: 2rpx solid #e0e0e0; background: #fafafa; }
+.tag-btn { padding: 12rpx 28rpx; border-radius: 30rpx; border: 2rpx solid #e0e0e0; background: #fafafa; }
 .tag-active { border-color: #F97316; background: #FFF3E0; }
-.tag-btn text { font-size: 24rpx; color: #666; }
-.tag-active text { font-size: 24rpx; color: #F97316; font-weight: bold; }
-.form-input { width: 100%; border: 1rpx solid #e0e0e0; border-radius: 12rpx; padding: 16rpx; font-size: 26rpx; background: #FAFAFA; box-sizing: border-box; }
+.tag-btn text { font-size: 26rpx; color: #666; }
+.tag-active text { font-size: 26rpx; color: #F97316; font-weight: bold; }
+.form-input { width: 100%; height: 80rpx; border: 1rpx solid #e0e0e0; border-radius: 16rpx; padding: 0 20rpx; font-size: 28rpx; background: #FAFAFA; box-sizing: border-box; }
 /* 录入框下方的并排工具栏 */
-.media-toolbar { display: flex; align-items: center; margin-top: 16rpx; padding: 18rpx 0; border-top: 1rpx solid #f0f0f0; }
-.tool-btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 10rpx; padding: 8rpx 0; }
-.tool-icon { font-size: 36rpx; }
-.tool-label { font-size: 26rpx; color: #555; }
-.tool-count { font-size: 22rpx; color: #F97316; font-weight: bold; margin-left: 4rpx; }
-.tool-divider { width: 1rpx; height: 36rpx; background: #e8e8e8; }
+.media-toolbar { display: flex; align-items: center; margin: 16rpx 24rpx; padding: 24rpx 0; border-top: 1rpx solid #f0f0f0; }
+.tool-btn { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8rpx; padding: 16rpx 0; }
+.tool-icon { font-size: 48rpx; }
+.tool-label { font-size: 24rpx; color: #666; }
+.tool-count { font-size: 22rpx; color: #F97316; font-weight: bold; }
+.tool-divider { width: 1rpx; height: 60rpx; background: #e8e8e8; }
 
 /* 照片缩略图条 */
-.photo-strip { display: flex; flex-wrap: wrap; gap: 12rpx; padding: 16rpx 0 4rpx; }
-.photo-item { position: relative; width: 120rpx; height: 120rpx; }
+.photo-strip { display: flex; flex-wrap: wrap; gap: 12rpx; padding: 0 24rpx 4rpx; }
+.photo-item { position: relative; width: 140rpx; height: 140rpx; }
 .photo-img { width: 100%; height: 100%; border-radius: 12rpx; }
-.photo-delete-overlay { position: absolute; top: -6rpx; right: -6rpx; width: 32rpx; height: 32rpx; background: #EF4444; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2rpx 6rpx rgba(239,68,68,0.3); z-index: 2; }
-.delete-icon { color: #fff; font-size: 22rpx; font-weight: bold; line-height: 32rpx; }
+.photo-delete-overlay { position: absolute; top: -6rpx; right: -6rpx; width: 36rpx; height: 36rpx; background: #EF4444; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2rpx 6rpx rgba(239,68,68,0.3); z-index: 2; }
+.delete-icon { color: #fff; font-size: 24rpx; font-weight: bold; line-height: 36rpx; }
 
 /* 录音展开区 */
-.voice-strip { display: flex; align-items: center; justify-content: space-between; padding: 16rpx 0 4rpx; gap: 16rpx; }
+.voice-strip { display: flex; align-items: center; justify-content: space-between; padding: 16rpx 24rpx 4rpx; gap: 16rpx; }
 .waveform { display: flex; align-items: center; gap: 6rpx; height: 48rpx; flex: 1; }
 .wave-bar { width: 6rpx; height: 10rpx; background: #F97316; border-radius: 3rpx; animation: wave-anim 0.8s ease-in-out infinite; }
 @keyframes wave-anim { 0%, 100% { height: 10rpx; } 50% { height: 36rpx; } }
 .voice-controls { display: flex; gap: 16rpx; }
-.mini-btn { padding: 12rpx 24rpx; border-radius: 24rpx; font-size: 24rpx; }
+.mini-btn { padding: 12rpx 28rpx; border-radius: 24rpx; font-size: 26rpx; }
 .cancel-mini { background: #f0f0f0; color: #666; }
 .done-mini { background: #F97316; color: #fff; font-weight: bold; }
 
-.voice-player { display: flex; align-items: center; gap: 12rpx; flex: 1; background: #FFF3E0; padding: 12rpx 20rpx; border-radius: 30rpx; }
+.voice-player { display: flex; align-items: center; gap: 12rpx; flex: 1; background: #FFF3E0; padding: 12rpx 24rpx; border-radius: 30rpx; }
 .play-icon { font-size: 28rpx; color: #F97316; }
-.voice-duration { font-size: 24rpx; color: #666; }
-.delete-voice { width: 40rpx; height: 40rpx; display: flex; align-items: center; justify-content: center; color: #999; font-size: 32rpx; }
+.voice-duration { font-size: 26rpx; color: #666; }
+.delete-voice { width: 44rpx; height: 44rpx; display: flex; align-items: center; justify-content: center; color: #999; font-size: 32rpx; }
 .submit-wrap { padding: 24rpx 24rpx 40rpx; }
-.submit-btn { background: linear-gradient(135deg, #FF8C42, #F97316); color: #fff; text-align: center; padding: 24rpx 0; border-radius: 16rpx; font-size: 30rpx; font-weight: bold; }
+.submit-btn { background: linear-gradient(135deg, #FF8C42, #F97316); color: #fff; text-align: center; padding: 24rpx 0; border-radius: 16rpx; font-size: 32rpx; font-weight: bold; }
 .submitting { opacity: 0.6; }
 .history-list { display: flex; flex-direction: column; gap: 16rpx; }
 .history-item { display: flex; justify-content: space-between; align-items: center; padding: 12rpx 0; border-bottom: 1rpx solid #f5f5f5; }
 .history-left { flex: 1; min-width: 0; }
-.history-type { font-size: 26rpx; font-weight: 500; color: #333; display: block; }
-.history-content { font-size: 22rpx; color: #888; display: block; margin-top: 4rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
-.history-date { font-size: 22rpx; color: #999; flex-shrink: 0; margin-left: 16rpx; }
+.history-type { font-size: 28rpx; font-weight: 500; color: #333; display: block; }
+.history-content { font-size: 24rpx; color: #888; display: block; margin-top: 4rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.history-date { font-size: 24rpx; color: #999; flex-shrink: 0; margin-left: 16rpx; }
 </style>

+ 69 - 24
cfc-frontend/pages/growth/growth-emotion-checkin.vue

@@ -42,7 +42,7 @@
       <view class="card">
         <view class="card-accent"></view>
         <view class="card-body">
-          <text class="card-title">✍️ 文字记录</text>
+          <text class="card-title">文字记录</text>
           <textarea class="note-input" v-model="note" placeholder="今天发生了什么?说说你的感受..." maxlength="500" />
           <!-- 并排两个按钮 + 展开区域 -->
           <view class="media-toolbar">
@@ -87,10 +87,6 @@
         </view>
       </view>
 
-
-
-
-
       <!-- 提交按钮 -->
       <view class="submit-wrap">
         <view class="submit-btn" :class="{ 'submitting': submitting }" @tap="doCheckin">
@@ -103,13 +99,13 @@
         <view class="card-accent"></view>
         <view class="card-body">
           <text class="card-title">近期心情</text>
-<view class="history-list">
+          <view class="history-list">
             <view class="history-item" v-for="item in history" :key="item.id">
               <view class="history-left">
                 <text class="history-type">{{ emotionIcon(item.emotionType) }} {{ emotionLabel(item.emotionType) }}</text>
                 <text class="history-content">{{ item.note || '-' }}</text>
-                <text class="history-date">{{ formatDate(item.createdAt) }}</text>
               </view>
+              <text class="history-date">{{ formatDate(item.createdAt) }}</text>
             </view>
           </view>
         </view>
@@ -235,6 +231,13 @@ export default {
     removePhoto: function(idx) {
       this.photos.splice(idx, 1)
     },
+    toggleRecord: function() {
+      if (this.isRecording) {
+        this.recorderManager.stop()
+      } else {
+        this.recorderManager.start({ duration: 60000, format: 'mp3' })
+      }
+    },
     cancelRecord: function() {
       this.recorderManager.stop()
       this.voicePath = ''
@@ -320,33 +323,75 @@ export default {
 </script>
 
 <style scoped>
-/* 录入框下方的并排工具栏 */
-.media-toolbar { display: flex; align-items: center; margin-top: 16rpx; padding: 18rpx 0; border-top: 1rpx solid #f0f0f0; }
-.tool-btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 10rpx; padding: 8rpx 0; }
-.tool-icon { font-size: 36rpx; }
-.tool-label { font-size: 26rpx; color: #555; }
-.tool-count { font-size: 22rpx; color: #F97316; font-weight: bold; margin-left: 4rpx; }
-.tool-divider { width: 1rpx; height: 36rpx; background: #e8e8e8; }
+.page { min-height: 100vh; background: #FFF7ED; }
+.nav-bar { display: flex; align-items: center; height: 88rpx; padding-top: env(safe-area-inset-top); background: #fff; border-bottom: 1rpx solid #f0f0f0; position: relative; }
+.nav-back { position: absolute; left: 24rpx; top: 0; bottom: 0; display: flex; align-items: center; }
+.back-text { font-size: 28rpx; color: #F97316; }
+.nav-title { flex: 1; text-align: center; font-size: 32rpx; font-weight: bold; color: #333; }
+.content { height: calc(100vh - 88rpx); }
+.card { margin: 16rpx 24rpx; background: #fff; border-radius: 20rpx; overflow: hidden; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.card-accent { height: 6rpx; background: linear-gradient(90deg, #FF6B9D, #F97316); }
+.card-body { padding: 28rpx; }
+.card-title { font-size: 30rpx; font-weight: bold; color: #333; margin-bottom: 20rpx; display: block; }
+.form-group { margin-bottom: 24rpx; }
+.form-label { font-size: 28rpx; color: #333; font-weight: 600; margin-bottom: 12rpx; display: block; }
+
+/* 情绪网格 */
+.emotion-grid { display: flex; flex-wrap: wrap; gap: 16rpx; }
+.emotion-item { width: calc(25% - 12rpx); display: flex; flex-direction: column; align-items: center; padding: 20rpx 0; border-radius: 16rpx; background: #FAFAFA; border: 2rpx solid transparent; }
+.emotion-active { background: #FFF0F5; border-color: #FF6B9D; }
+.emotion-icon { font-size: 48rpx; margin-bottom: 8rpx; }
+.emotion-label { font-size: 24rpx; color: #666; }
+.emotion-active .emotion-label { color: #FF6B9D; font-weight: bold; }
+
+/* 滑块 */
+.slider-row { display: flex; align-items: center; gap: 12rpx; }
+.slider-min { font-size: 24rpx; color: #999; flex-shrink: 0; }
+.slider-val { font-size: 28rpx; color: #FF6B9D; font-weight: bold; width: 40rpx; text-align: center; }
+.slider-max { font-size: 24rpx; color: #999; flex-shrink: 0; }
+
+/* 文本输入 */
+.note-input { width: 100%; height: 160rpx; border: 1rpx solid #e0e0e0; border-radius: 16rpx; padding: 20rpx; font-size: 28rpx; background: #FAFAFA; box-sizing: border-box; margin-bottom: 20rpx; }
+
+/* 录入工具栏 */
+.media-toolbar { display: flex; align-items: center; padding: 24rpx 0; border-top: 1rpx solid #f0f0f0; }
+.tool-btn { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8rpx; padding: 16rpx 0; }
+.tool-icon { font-size: 48rpx; }
+.tool-label { font-size: 24rpx; color: #666; }
+.tool-count { font-size: 22rpx; color: #FF6B9D; font-weight: bold; }
+.tool-divider { width: 1rpx; height: 60rpx; background: #e8e8e8; }
 
 /* 照片缩略图条 */
 .photo-strip { display: flex; flex-wrap: wrap; gap: 12rpx; padding: 16rpx 0 4rpx; }
-.photo-item { position: relative; width: 120rpx; height: 120rpx; }
+.photo-item { position: relative; width: 140rpx; height: 140rpx; }
 .photo-img { width: 100%; height: 100%; border-radius: 12rpx; }
-.photo-delete-overlay { position: absolute; top: -6rpx; right: -6rpx; width: 32rpx; height: 32rpx; background: #EF4444; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2rpx 6rpx rgba(239,68,68,0.3); z-index: 2; }
-.delete-icon { color: #fff; font-size: 22rpx; font-weight: bold; line-height: 32rpx; }
+.photo-delete-overlay { position: absolute; top: -6rpx; right: -6rpx; width: 36rpx; height: 36rpx; background: #EF4444; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2rpx 6rpx rgba(239,68,68,0.3); z-index: 2; }
+.delete-icon { color: #fff; font-size: 24rpx; font-weight: bold; line-height: 36rpx; }
 
 /* 录音展开区 */
 .voice-strip { display: flex; align-items: center; justify-content: space-between; padding: 16rpx 0 4rpx; gap: 16rpx; }
 .waveform { display: flex; align-items: center; gap: 6rpx; height: 48rpx; flex: 1; }
-.wave-bar { width: 6rpx; height: 10rpx; background: #F97316; border-radius: 3rpx; animation: wave-anim 0.8s ease-in-out infinite; }
+.wave-bar { width: 6rpx; height: 10rpx; background: #FF6B9D; border-radius: 3rpx; animation: wave-anim 0.8s ease-in-out infinite; }
 @keyframes wave-anim { 0%, 100% { height: 10rpx; } 50% { height: 36rpx; } }
 .voice-controls { display: flex; gap: 16rpx; }
-.mini-btn { padding: 12rpx 24rpx; border-radius: 24rpx; font-size: 24rpx; }
+.mini-btn { padding: 12rpx 28rpx; border-radius: 24rpx; font-size: 26rpx; }
 .cancel-mini { background: #f0f0f0; color: #666; }
-.done-mini { background: #F97316; color: #fff; font-weight: bold; }
+.done-mini { background: #FF6B9D; color: #fff; font-weight: bold; }
+.voice-player { display: flex; align-items: center; gap: 12rpx; flex: 1; background: #FFF0F5; padding: 12rpx 24rpx; border-radius: 30rpx; }
+.play-icon { font-size: 28rpx; color: #FF6B9D; }
+.voice-duration { font-size: 26rpx; color: #666; }
+.delete-voice { width: 44rpx; height: 44rpx; display: flex; align-items: center; justify-content: center; color: #999; font-size: 32rpx; }
+
+/* 提交按钮 */
+.submit-wrap { padding: 24rpx 24rpx 40rpx; }
+.submit-btn { background: linear-gradient(135deg, #FF6B9D, #F97316); color: #fff; text-align: center; padding: 24rpx 0; border-radius: 16rpx; font-size: 32rpx; font-weight: bold; }
+.submitting { opacity: 0.6; }
 
-.voice-player { display: flex; align-items: center; gap: 12rpx; flex: 1; background: #FFF3E0; padding: 12rpx 20rpx; border-radius: 30rpx; }
-.play-icon { font-size: 28rpx; color: #F97316; }
-.voice-duration { font-size: 24rpx; color: #666; }
-.delete-voice { width: 40rpx; height: 40rpx; display: flex; align-items: center; justify-content: center; color: #999; font-size: 32rpx; }
+/* 历史记录 */
+.history-list { display: flex; flex-direction: column; gap: 16rpx; }
+.history-item { display: flex; justify-content: space-between; align-items: center; padding: 12rpx 0; border-bottom: 1rpx solid #f5f5f5; }
+.history-left { flex: 1; min-width: 0; }
+.history-type { font-size: 28rpx; font-weight: 500; color: #333; display: block; }
+.history-content { font-size: 24rpx; color: #888; display: block; margin-top: 4rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.history-date { font-size: 24rpx; color: #999; flex-shrink: 0; margin-left: 16rpx; }
 </style>

+ 14 - 191
cfc-frontend/pages/growth/sleep-checkin.vue

@@ -12,7 +12,6 @@
       <view class="card">
         <view class="card-accent"></view>
         <view class="card-body">
-          <text class="card-title">记录睡眠</text>
           <view class="form-group">
             <text class="form-label">入睡时间 *</text>
             <picker mode="time" :value="form.sleepTime" @change="function(e){form.sleepTime=e.detail.value}">
@@ -41,59 +40,6 @@
         </view>
       </view>
 
-      <!-- 照片上传 -->
-      <view class="card">
-        <view class="card-accent"></view>
-        <view class="card-body">
-          <view class="section-header">
-            <text class="card-title">📷 拍照记录</text>
-            <text class="photo-count">{{ form.photos.length }}/9</text>
-          </view>
-          <view class="photo-grid">
-            <view class="photo-thumb" v-for="(img, idx) in form.photos" :key="getPhotoKey(img, idx)" @tap="removePhoto(idx)">
-              <image :src="img" mode="aspectFill" class="photo-img" />
-              <view class="photo-delete">
-                <text class="photo-delete-icon">×</text>
-              </view>
-            </view>
-            <view class="photo-add-btn" v-if="form.photos.length < 9" @tap="choosePhoto">
-              <text class="camera-icon">📷</text>
-            </view>
-          </view>
-        </view>
-      </view>
-
-      <!-- 语音录入 -->
-      <view class="card">
-        <view class="card-accent"></view>
-        <view class="card-body">
-          <text class="card-title">🎙️ 语音打卡</text>
-          <view class="voice-recorder">
-            <view class="voice-active" v-if="isRecording">
-              <view class="waveform">
-                <view class="wave-bar wave-1"></view>
-                <view class="wave-bar wave-2"></view>
-                <view class="wave-bar wave-3"></view>
-                <view class="wave-bar wave-4"></view>
-                <view class="wave-bar wave-5"></view>
-              </view>
-              <text class="recording-time">{{ recordSeconds }}s</text>
-            </view>
-            <view class="voice-done" v-else-if="form.voicePath">
-              <text class="play-icon">▶</text>
-              <text class="done-text">{{ recordDurationText }}</text>
-            </view>
-            <view class="record-btn-wrap">
-              <view class="pulse-ring" v-if="isRecording"></view>
-              <view class="record-btn" :class="{ 'record-btn-active': isRecording }" @tap="toggleRecord">
-                <view class="record-btn-dot"></view>
-              </view>
-            </view>
-          </view>
-          <text class="voice-hint">点击开始录音</text>
-        </view>
-      </view>
-
       <!-- 提交按钮 -->
       <view class="submit-wrap">
         <view class="submit-btn" :class="{ 'submitting': submitting }" @tap="doCheckin">
@@ -130,54 +76,22 @@ export default {
     return {
       memberId: null,
       submitting: false,
-      isRecording: false,
-      recordSeconds: 0,
-      recordTimer: null,
-      recorderManager: null,
       history: [],
       form: {
         sleepTime: '21:00',
         wakeTime: '07:00',
         qualityScore: 7,
-        remark: '',
-        photos: [],
-        voicePath: ''
+        remark: ''
       }
     }
   },
-  computed: {
-    recordDurationText: function() {
-      if (!this.form.voicePath) return ''
-      return '录音 ' + this.recordSeconds + '秒'
-    }
-  },
   onLoad: function() {
     var role = uni.getStorageSync('currentRole') || uni.getStorageSync('role') || 'parent'
     if (role !== 'child') {
       this.memberId = uni.getStorageSync('currentChildId') || uni.getStorageSync('currentMemberId') || uni.getStorageSync('userId') || null
     }
-    this.recorderManager = uni.getRecorderManager()
-    this.recorderManager.onStart(() => {
-      this.isRecording = true
-      this.recordSeconds = 0
-      this.recordTimer = setInterval(() => { this.recordSeconds++ }, 1000)
-    })
-    this.recorderManager.onStop((res) => {
-      this.isRecording = false
-      if (this.recordTimer) { clearInterval(this.recordTimer); this.recordTimer = null }
-      this.form.voicePath = res.tempFilePath
-      this.form.voiceDuration = res.duration
-    })
-    this.recorderManager.onError(() => {
-      this.isRecording = false
-      if (this.recordTimer) { clearInterval(this.recordTimer); this.recordTimer = null }
-      uni.showToast({ title: '录音失败', icon: 'none' })
-    })
     this.loadHistory()
   },
-  onUnload: function() {
-    if (this.recordTimer) clearInterval(this.recordTimer)
-  },
   methods: {
     goBack: function() { uni.navigateBack() },
     formatDate: function(dateStr) {
@@ -204,48 +118,6 @@ export default {
         }
       })
     },
-    choosePhoto: function() {
-      var self = this
-      uni.chooseImage({
-        count: 9 - self.form.photos.length,
-        sizeType: ['compressed'],
-        sourceType: ['album', 'camera'],
-        success: function(res) {
-          res.tempFilePaths.forEach(function(path) {
-            if (self.form.photos.length < 9) self.form.photos.push(path)
-          })
-        }
-      })
-    },
-    getPhotoKey: function(img, idx) {
-      return img ? img : ('p' + idx)
-    },
-    removePhoto: function(idx) {
-      this.form.photos.splice(idx, 1)
-    },
-    toggleRecord: function() {
-      if (this.isRecording) {
-        this.recorderManager.stop()
-      } else {
-        this.recorderManager.start({ duration: 60000, format: 'mp3' })
-      }
-    },
-    uploadFile: function(filePath) {
-      var self = this
-      return new Promise(function(resolve, reject) {
-        uni.uploadFile({
-          url: config.API_BASE_URL + '/api/media/upload',
-          filePath: filePath,
-          name: 'file',
-          header: { 'Authorization': 'Bearer ' + uni.getStorageSync('token') },
-          success: function(res) {
-            try { var data = JSON.parse(res.data); resolve(data.data || data.url || '') }
-            catch (e) { resolve(res.data || '') }
-          },
-          fail: function() { reject() }
-        })
-      })
-    },
     async doCheckin() {
       var self = this
       if (!self.form.sleepTime) { uni.showToast({ title: '请选择入睡时间', icon: 'none' }); return }
@@ -253,17 +125,6 @@ export default {
       if (!self.memberId) { uni.showToast({ title: '孩子ID无效', icon: 'none' }); return }
       self.submitting = true
       try {
-        var photoUrls = []
-        if (self.form.photos && self.form.photos.length > 0) {
-          for (var i = 0; i < self.form.photos.length; i++) {
-            try { var url = await self.uploadFile(self.form.photos[i]) } catch(e) { url = '' }
-            if (url) photoUrls.push(url)
-          }
-        }
-        var voiceUrl = ''
-        if (self.form.voicePath) {
-          try { voiceUrl = await self.uploadFile(self.form.voicePath) } catch(e) { voiceUrl = '' }
-        }
         var sleepParts = self.form.sleepTime.split(':')
         var wakeParts = self.form.wakeTime.split(':')
         var sleepMin = parseInt(sleepParts[0]) * 60 + parseInt(sleepParts[1])
@@ -279,9 +140,7 @@ export default {
             wakeTime: self.form.wakeTime,
             durationMinutes: duration,
             qualityScore: self.form.qualityScore,
-            remark: self.form.remark || '',
-            photoUrls: photoUrls.join(','),
-            voiceUrl: voiceUrl
+            remark: self.form.remark || ''
           },
           header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
           success: function(res) {
@@ -292,9 +151,6 @@ export default {
               self.form.wakeTime = '07:00'
               self.form.qualityScore = 7
               self.form.remark = ''
-              self.form.photos = []
-              self.form.voicePath = ''
-              self.recordSeconds = 0
               self.loadHistory()
             } else {
               uni.showToast({ title: (res.data && res.data.message) || '打卡失败', icon: 'none' })
@@ -323,56 +179,23 @@ export default {
 .content { height: calc(100vh - 88rpx); }
 .card { margin: 16rpx 24rpx; background: #fff; border-radius: 20rpx; overflow: hidden; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
 .card-accent { height: 6rpx; background: linear-gradient(90deg, #FF8C42, #F97316); }
-.card-body { padding: 24rpx; }
+.card-body { padding: 28rpx; }
 .card-title { font-size: 30rpx; font-weight: bold; color: #333; margin-bottom: 20rpx; display: block; }
-.form-group { margin-bottom: 20rpx; }
-.form-label { font-size: 26rpx; color: #333; font-weight: 500; margin-bottom: 12rpx; display: block; }
-.picker-display { border: 1rpx solid #ddd; border-radius: 12rpx; padding: 16rpx 20rpx; font-size: 26rpx; background: #FAFAFA; color: #333; }
+.form-group { margin-bottom: 24rpx; }
+.form-label { font-size: 28rpx; color: #333; font-weight: 600; margin-bottom: 12rpx; display: block; }
+.picker-display { border: 1rpx solid #ddd; border-radius: 16rpx; padding: 20rpx; font-size: 28rpx; background: #FAFAFA; color: #333; min-height: 40rpx; }
 .slider-row { display: flex; align-items: center; gap: 12rpx; }
-.slider-min { font-size: 22rpx; color: #999; flex-shrink: 0; }
-.slider-val { font-size: 24rpx; color: #FF8C42; font-weight: bold; width: 40rpx; text-align: center; }
-.slider-max { font-size: 22rpx; color: #999; flex-shrink: 0; }
-.form-input { width: 100%; border: 1rpx solid #e0e0e0; border-radius: 12rpx; padding: 16rpx; font-size: 26rpx; background: #FAFAFA; box-sizing: border-box; }
-.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20rpx; }
-.section-header .card-title { margin-bottom: 0; }
-.photo-count { font-size: 24rpx; color: #999; }
-.photo-grid { display: flex; flex-wrap: wrap; gap: 16rpx; }
-.photo-thumb { position: relative; width: 160rpx; height: 160rpx; }
-.photo-img { width: 100%; height: 100%; border-radius: 16rpx; }
-.photo-delete { position: absolute; top: 0; right: 0; width: 36rpx; height: 36rpx; background: #EF4444; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 2rpx 8rpx rgba(239,68,68,0.3); }
-.photo-delete-icon { color: #fff; font-size: 24rpx; font-weight: bold; }
-.photo-add-btn { width: 160rpx; height: 160rpx; border-radius: 16rpx; background: linear-gradient(135deg, #FF8C42, #F97316); display: flex; align-items: center; justify-content: center; box-shadow: 0 4rpx 16rpx rgba(249,115,22,0.25); }
-.camera-icon { font-size: 52rpx; }
-.voice-recorder { display: flex; flex-direction: column; align-items: center; padding: 24rpx 0 16rpx; }
-.voice-active { display: flex; flex-direction: column; align-items: center; margin-bottom: 20rpx; }
-.waveform { display: flex; align-items: center; justify-content: center; gap: 8rpx; height: 48rpx; }
-.wave-bar { width: 6rpx; height: 8rpx; background: #EF4444; border-radius: 3rpx; }
-.wave-1 { animation: waveform-anim 0.8s ease-in-out infinite 0s; }
-.wave-2 { animation: waveform-anim 0.8s ease-in-out infinite 0.1s; }
-.wave-3 { animation: waveform-anim 0.8s ease-in-out infinite 0.2s; }
-.wave-4 { animation: waveform-anim 0.8s ease-in-out infinite 0.3s; }
-.wave-5 { animation: waveform-anim 0.8s ease-in-out infinite 0.4s; }
-.recording-time { font-size: 28rpx; color: #EF4444; font-weight: bold; margin-top: 8rpx; }
-.voice-done { display: flex; align-items: center; gap: 12rpx; margin-bottom: 20rpx; padding: 12rpx 24rpx; background: #FFF7ED; border-radius: 30rpx; }
-.play-icon { font-size: 24rpx; color: #F97316; }
-.done-text { font-size: 26rpx; color: #666; }
-.record-btn-wrap { position: relative; width: 80rpx; height: 80rpx; }
-.pulse-ring { position: absolute; top: 0; left: 0; width: 80rpx; height: 80rpx; border-radius: 50%; border: 4rpx solid #EF4444; animation: pulse-expand 1.5s ease-out infinite; }
-.record-btn { position: relative; width: 80rpx; height: 80rpx; border-radius: 50%; background: linear-gradient(135deg, #FF8C42, #F97316); display: flex; align-items: center; justify-content: center; box-shadow: 0 4rpx 16rpx rgba(249,115,22,0.3); z-index: 1; }
-.record-btn-active { background: linear-gradient(135deg, #EF4444, #DC2626); box-shadow: 0 4rpx 16rpx rgba(239,68,68,0.4); animation: btn-pulse 1s ease-in-out infinite; }
-.record-btn-dot { width: 24rpx; height: 24rpx; border-radius: 50%; background: #fff; }
-.record-btn-active .record-btn-dot { width: 20rpx; height: 20rpx; border-radius: 4rpx; background: #fff; }
-.voice-hint { font-size: 22rpx; color: #999; text-align: center; }
-@keyframes waveform-anim { 0%, 100% { height: 8rpx; } 50% { height: 40rpx; } }
-@keyframes pulse-expand { 0% { transform: scale(1); opacity: 0.6; } 100% { transform: scale(1.8); opacity: 0; } }
-@keyframes btn-pulse { 0%, 100% { box-shadow: 0 4rpx 16rpx rgba(239,68,68,0.4); } 50% { box-shadow: 0 4rpx 24rpx rgba(239,68,68,0.6); } }
+.slider-min { font-size: 24rpx; color: #999; flex-shrink: 0; }
+.slider-val { font-size: 28rpx; color: #FF8C42; font-weight: bold; width: 40rpx; text-align: center; }
+.slider-max { font-size: 24rpx; color: #999; flex-shrink: 0; }
+.form-input { width: 100%; height: 80rpx; border: 1rpx solid #e0e0e0; border-radius: 16rpx; padding: 0 20rpx; font-size: 28rpx; background: #FAFAFA; box-sizing: border-box; }
 .submit-wrap { padding: 24rpx 24rpx 40rpx; }
-.submit-btn { background: linear-gradient(135deg, #FF8C42, #F97316); color: #fff; text-align: center; padding: 24rpx 0; border-radius: 16rpx; font-size: 30rpx; font-weight: bold; }
+.submit-btn { background: linear-gradient(135deg, #FF8C42, #F97316); color: #fff; text-align: center; padding: 24rpx 0; border-radius: 16rpx; font-size: 32rpx; font-weight: bold; }
 .submitting { opacity: 0.6; }
 .history-list { display: flex; flex-direction: column; gap: 16rpx; }
 .history-item { display: flex; justify-content: space-between; align-items: center; padding: 12rpx 0; border-bottom: 1rpx solid #f5f5f5; }
 .history-left { flex: 1; min-width: 0; }
-.history-type { font-size: 26rpx; font-weight: 500; color: #333; display: block; }
-.history-content { font-size: 22rpx; color: #888; display: block; margin-top: 4rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
-.history-date { font-size: 22rpx; color: #999; flex-shrink: 0; margin-left: 16rpx; }
+.history-type { font-size: 28rpx; font-weight: 500; color: #333; display: block; }
+.history-content { font-size: 24rpx; color: #888; display: block; margin-top: 4rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.history-date { font-size: 24rpx; color: #999; flex-shrink: 0; margin-left: 16rpx; }
 </style>