Просмотр исходного кода

refactor(frontend): 健康报告上传页 report-upload.vue 重构

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Xiaogang Liao 1 месяц назад
Родитель
Сommit
bbbe0131a3
1 измененных файлов с 104 добавлено и 245 удалено
  1. 104 245
      cfc-frontend/pages/health/report-upload.vue

+ 104 - 245
cfc-frontend/pages/health/report-upload.vue

@@ -61,69 +61,18 @@
 
 
     <!-- 表单 -->
     <!-- 表单 -->
     <view class="form-section">
     <view class="form-section">
-      <!-- 上传方式:两种独立操作单元(上下分层,视觉差异明显) -->
+      <!-- 上传方式:并排卡片 -->
       <view class="upload-methods">
       <view class="upload-methods">
-        <!-- 方式 1:上传文件(PDF/Word/图片,从聊天记录选择) -->
-        <view class="upload-method method-file">
-          <view class="method-header">
-            <view class="method-tag tag-file">方式 1</view>
-            <text class="method-title">上传报告文件</text>
-            <text class="method-sub">体检报告、肠道检测报告等正式 PDF/Word 文档</text>
-          </view>
-          <view class="method-body" @click="pickFile">
-            <view class="method-icon-file">📄</view>
-            <view class="method-cta-file">
-              <text class="method-cta-file-main">从微信聊天选择文件</text>
-              <text class="method-cta-file-sub">支持 PDF / Word / 图片</text>
-            </view>
-            <text class="method-arrow">›</text>
-          </view>
-        </view>
-
-        <!-- 分隔提示 -->
-        <view class="method-divider">
-          <text class="method-divider-text">或</text>
-        </view>
-
-        <!-- 方式 2:拍照上传(相机拍照,主要用于舌象) -->
-        <view class="upload-method method-photo">
-          <view class="method-header">
-            <view class="method-tag tag-photo">方式 2</view>
-            <text class="method-title">拍照上传</text>
-            <text class="method-sub">拍摄舌象照片或单页纸质报告</text>
-          </view>
-          <view class="method-body" @click="takePhoto">
-            <view class="method-icon-photo">📷</view>
-            <view class="method-cta-photo">
-              <text class="method-cta-photo-main">打开相机拍照</text>
-              <text class="method-cta-photo-sub">舌象分析 · 即拍即传</text>
-            </view>
-            <text class="method-arrow">›</text>
-          </view>
+        <view class="upload-card card-file" @click="pickFile">
+          <view class="upload-card-icon">📄</view>
+          <text class="upload-card-title">从聊天选择文件</text>
+          <text class="upload-card-desc">PDF / Word / 图片<br/>体检报告、肠道检测报告</text>
         </view>
         </view>
-      </view>
-
-      <!-- 购买推荐 -->
-      <view class="purchase-section" v-if="recommendedProducts.length > 0">
-        <view class="purchase-header">
-          <text class="purchase-icon">📦</text>
-          <text class="purchase-title">为家人购买检测服务</text>
+        <view class="upload-card card-photo" @click="takePhoto">
+          <view class="upload-card-icon">📷</view>
+          <text class="upload-card-title">拍照上传</text>
+          <text class="upload-card-desc">拍摄舌象照片<br/>或单页纸质报告</text>
         </view>
         </view>
-        <scroll-view class="purchase-scroll" scroll-x enable-flex show-scrollbar="false">
-          <view
-            class="purchase-card"
-            v-for="item in recommendedProducts"
-            :key="item.id"
-            @click="goToProduct(item.id)"
-          >
-            <image class="purchase-cover" :src="getImageUrl(item.coverImage) || '/static/default-product.png'" mode="aspectFill" />
-            <text class="purchase-name">{{ item.name }}</text>
-            <text class="purchase-price">{{ formatPriceWithSymbol(item.price) }}</text>
-            <view class="purchase-btn">
-              <text class="purchase-btn-text">去购买</text>
-            </view>
-          </view>
-        </scroll-view>
       </view>
       </view>
 
 
       <!-- 已选文件 -->
       <!-- 已选文件 -->
@@ -165,6 +114,29 @@
 
 
     <!-- 底部占位 -->
     <!-- 底部占位 -->
     <view class="bottom-spacer"></view>
     <view class="bottom-spacer"></view>
+
+    <!-- 菌群测评商品 -->
+    <view class="product-section" v-if="recommendedProducts.length > 0">
+      <view class="product-header">
+        <text class="product-header-icon">📦</text>
+        <text class="product-header-title">为家人购买检测服务</text>
+      </view>
+      <view class="product-grid">
+        <view
+          class="product-card"
+          v-for="item in recommendedProducts"
+          :key="item.id"
+          @click="goToProduct(item.id)"
+        >
+          <image class="product-cover" :src="getImageUrl(item.coverImage) || '/static/default-product.png'" mode="aspectFill" />
+          <text class="product-name">{{ item.name }}</text>
+          <text class="product-price">{{ formatPriceWithSymbol(item.price) }}</text>
+          <view class="product-btn">
+            <text class="product-btn-text">去购买</text>
+          </view>
+        </view>
+      </view>
+    </view>
   </view>
   </view>
 </template>
 </template>
 
 
@@ -986,249 +958,136 @@ export default {
   height: 60rpx;
   height: 60rpx;
 }
 }
 
 
-/* ===== 上传方式(两种方式差异化) ===== */
+/* ===== 上传方式:并排卡片 ===== */
 .upload-methods {
 .upload-methods {
+  display: flex;
+  flex-direction: row;
+  gap: 20rpx;
   margin-bottom: 20rpx;
   margin-bottom: 20rpx;
 }
 }
-
-.upload-method {
-  background: #fff;
-  border-radius: 20rpx;
-  overflow: hidden;
-}
-
-/* 方式 1:文件上传(蓝色基调,大块虚线风格) */
-.method-file {
-  border: 2rpx dashed #93C5FD;
-  background: #F0F7FF;
-}
-.method-file .method-body {
-  background: #fff;
-  margin: 0 24rpx 24rpx;
-  border-radius: 16rpx;
-  padding: 32rpx 24rpx;
+.upload-card {
+  flex: 1;
   display: flex;
   display: flex;
-  flex-direction: row;
+  flex-direction: column;
   align-items: center;
   align-items: center;
-  border: 2rpx solid #DBEAFE;
-}
-.method-file .method-body:active {
-  background: #EFF6FF;
-}
-
-.method-tag {
-  display: inline-block;
-  font-size: 20rpx;
-  padding: 4rpx 14rpx;
+  justify-content: center;
+  padding: 40rpx 20rpx;
   border-radius: 20rpx;
   border-radius: 20rpx;
-  margin-bottom: 12rpx;
-  font-weight: 500;
-}
-.tag-file {
-  background: #DBEAFE;
-  color: #1D4ED8;
-}
-.tag-photo {
-  background: #FED7AA;
-  color: #C2410C;
-}
-
-.method-header {
-  padding: 24rpx 24rpx 16rpx;
-}
-.method-title {
-  display: block;
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #1E3A8A;
-  margin-bottom: 6rpx;
+  text-align: center;
+  min-height: 240rpx;
 }
 }
-.method-sub {
-  display: block;
-  font-size: 22rpx;
-  color: #64748B;
-  line-height: 1.4;
+.upload-card:active {
+  opacity: 0.85;
 }
 }
-
-.method-icon-file {
-  width: 88rpx;
-  height: 88rpx;
-  border-radius: 20rpx;
-  background: linear-gradient(135deg, #3B82F6, #1D4ED8);
-  color: #fff;
+.upload-card-icon {
+  width: 96rpx;
+  height: 96rpx;
+  border-radius: 24rpx;
   font-size: 48rpx;
   font-size: 48rpx;
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
   justify-content: center;
   justify-content: center;
-  margin-right: 20rpx;
-  flex-shrink: 0;
-  box-shadow: 0 4rpx 12rpx rgba(59, 130, 246, 0.3);
-}
-
-.method-cta-file {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
+  margin-bottom: 20rpx;
 }
 }
-.method-cta-file-main {
+.upload-card-title {
   font-size: 28rpx;
   font-size: 28rpx;
   font-weight: 600;
   font-weight: 600;
-  color: #1E3A8A;
-  margin-bottom: 6rpx;
+  color: #333;
+  margin-bottom: 10rpx;
 }
 }
-.method-cta-file-sub {
+.upload-card-desc {
   font-size: 22rpx;
   font-size: 22rpx;
-  color: #64748B;
-}
-
-.method-arrow {
-  font-size: 40rpx;
   color: #94A3B8;
   color: #94A3B8;
-  font-weight: 300;
-  margin-left: 12rpx;
+  line-height: 1.5;
 }
 }
-
-/* 分隔提示 */
-.method-divider {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  justify-content: center;
-  margin: 24rpx 0;
+.card-file {
+  background: #F0F7FF;
+  border: 2rpx dashed #93C5FD;
 }
 }
-.method-divider-text {
-  font-size: 24rpx;
-  color: #94A3B8;
-  background: #F5F7FA;
-  padding: 6rpx 24rpx;
-  border-radius: 20rpx;
-  letter-spacing: 4rpx;
+.card-file .upload-card-icon {
+  background: linear-gradient(135deg, #3B82F6, #1D4ED8);
+  color: #fff;
+  box-shadow: 0 4rpx 12rpx rgba(59, 130, 246, 0.3);
 }
 }
-
-/* 方式 2:拍照上传(橙色基调,实心卡片风格) */
-.method-photo {
-  border: 2rpx solid #FED7AA;
+.card-photo {
   background: #FFF7ED;
   background: #FFF7ED;
+  border: 2rpx solid #FED7AA;
 }
 }
-.method-photo .method-body {
+.card-photo .upload-card-icon {
   background: linear-gradient(135deg, #FB923C, #EA580C);
   background: linear-gradient(135deg, #FB923C, #EA580C);
-  margin: 0 24rpx 24rpx;
-  border-radius: 16rpx;
-  padding: 32rpx 24rpx;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  box-shadow: 0 6rpx 16rpx rgba(234, 88, 12, 0.25);
-}
-.method-photo .method-body:active {
-  opacity: 0.92;
-}
-
-.method-photo .method-title {
-  color: #7C2D12;
-}
-.method-icon-photo {
-  width: 88rpx;
-  height: 88rpx;
-  border-radius: 20rpx;
-  background: rgba(255, 255, 255, 0.95);
-  color: #EA580C;
-  font-size: 48rpx;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-right: 20rpx;
-  flex-shrink: 0;
-}
-
-.method-cta-photo {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-}
-.method-cta-photo-main {
-  font-size: 28rpx;
-  font-weight: 600;
   color: #fff;
   color: #fff;
-  margin-bottom: 6rpx;
-}
-.method-cta-photo-sub {
-  font-size: 22rpx;
-  color: rgba(255, 255, 255, 0.85);
+  box-shadow: 0 4rpx 12rpx rgba(234, 88, 12, 0.25);
 }
 }
 
 
-.method-photo .method-arrow {
-  color: rgba(255, 255, 255, 0.9);
-}
-
-/* ===== 购买推荐 ===== */
-.purchase-section {
-  background: #F0F9FF;
-  border-radius: 16rpx;
-  padding: 24rpx;
-  margin: 0 30rpx 20rpx;
-  border: 2rpx solid #BAE6FD;
+/* ===== 菌群测评商品 ===== */
+.product-section {
+  margin: 0 30rpx 30rpx;
 }
 }
-.purchase-header {
+.product-header {
   display: flex;
   display: flex;
   flex-direction: row;
   flex-direction: row;
   align-items: center;
   align-items: center;
   margin-bottom: 16rpx;
   margin-bottom: 16rpx;
 }
 }
-.purchase-icon {
+.product-header-icon {
   font-size: 28rpx;
   font-size: 28rpx;
   margin-right: 8rpx;
   margin-right: 8rpx;
 }
 }
-.purchase-title {
+.product-header-title {
   font-size: 26rpx;
   font-size: 26rpx;
   font-weight: bold;
   font-weight: bold;
-  color: #0369A1;
+  color: #333;
 }
 }
-.purchase-scroll {
+.product-grid {
   display: flex;
   display: flex;
   flex-direction: row;
   flex-direction: row;
-  white-space: nowrap;
+  flex-wrap: wrap;
+  gap: 16rpx;
 }
 }
-.purchase-card {
-  display: inline-flex;
-  flex-direction: column;
-  width: 220rpx;
+.product-card {
+  width: calc(50% - 8rpx);
   background: #fff;
   background: #fff;
-  border-radius: 12rpx;
-  padding: 16rpx;
-  margin-right: 16rpx;
-  flex-shrink: 0;
+  border-radius: 16rpx;
+  padding: 20rpx;
+  box-sizing: border-box;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
 }
 }
-.purchase-cover {
-  width: 188rpx;
-  height: 120rpx;
-  border-radius: 8rpx;
+.product-card:active {
+  opacity: 0.85;
+}
+.product-cover {
+  width: 100%;
+  height: 160rpx;
+  border-radius: 10rpx;
   background: #F1F5F9;
   background: #F1F5F9;
-  margin-bottom: 8rpx;
+  margin-bottom: 12rpx;
 }
 }
-.purchase-name {
-  font-size: 22rpx;
+.product-name {
+  display: block;
+  font-size: 24rpx;
   color: #333;
   color: #333;
+  font-weight: 500;
   line-height: 1.3;
   line-height: 1.3;
   overflow: hidden;
   overflow: hidden;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
   white-space: nowrap;
   white-space: nowrap;
-  margin-bottom: 4rpx;
+  margin-bottom: 6rpx;
 }
 }
-.purchase-price {
-  font-size: 24rpx;
+.product-price {
+  display: block;
+  font-size: 26rpx;
   color: #EF4444;
   color: #EF4444;
   font-weight: bold;
   font-weight: bold;
-  margin-bottom: 8rpx;
+  margin-bottom: 12rpx;
 }
 }
-.purchase-btn {
-  background: #3B82F6;
+.product-btn {
+  background: linear-gradient(135deg, #5B9BD5, #3A7CC4);
   border-radius: 8rpx;
   border-radius: 8rpx;
-  padding: 8rpx 0;
+  padding: 12rpx 0;
   text-align: center;
   text-align: center;
 }
 }
-.purchase-btn-text {
-  font-size: 22rpx;
+.product-btn-text {
+  font-size: 24rpx;
   color: #fff;
   color: #fff;
   font-weight: 500;
   font-weight: 500;
 }
 }