张田田 2 miesięcy temu
rodzic
commit
2285057a1b

+ 5 - 3
miniprogram/module/care/pages/care/verifyRecord.wxml

@@ -48,16 +48,18 @@
             <text class="record-index">{{index + 1}}、</text>
             <text class="record-index">{{index + 1}}、</text>
             <text class="record-time">{{item.operateTime}}</text>
             <text class="record-time">{{item.operateTime}}</text>
           </view>
           </view>
-          <view class="btn-review" catchtap="onReview" data-goods="{{item}}">评价</view>
+          <view class="btn-review" catchtap="onReview" data-goods="{{item}}">
+            {{item.evaluateTime ? "已评价" : "评价"}}
+          </view>
         </view>
         </view>
         <view class="record-row" wx:if="{{item.operateBy}}">
         <view class="record-row" wx:if="{{item.operateBy}}">
           <text class="label">操作人:</text>
           <text class="label">操作人:</text>
           <text style="color:black">{{item.operateBy}}</text>
           <text style="color:black">{{item.operateBy}}</text>
         </view>
         </view>
         <!-- 新增加的一列--机构 -->
         <!-- 新增加的一列--机构 -->
-        <view class="record-row" wx:if="{{item.operateBy}}">
+        <view class="record-row" wx:if="{{item.conditioningProgramSupplierName}}">
           <text class="label">机构:</text>
           <text class="label">机构:</text>
-          <text style="color:black">{{item.operateBy}}</text>
+          <text style="color:black">{{item.conditioningProgramSupplierName}}</text>
         </view>
         </view>
         <!-- end -->
         <!-- end -->
         <view class="record-row" wx:if="{{item.feedback}}">
         <view class="record-row" wx:if="{{item.feedback}}">

+ 0 - 7
miniprogram/module/care/pages/offlineTreatment/offlineTreatment.ts

@@ -57,13 +57,6 @@ Page({
         icon: "none",
         icon: "none",
       });
       });
     }
     }
-    // const id = e.currentTarget.dataset.id;
-    // if (id) {
-    //   // 跳转到预约页面,传递项目id
-    //   wx.navigateTo({
-    //     url: `/module/care/pages/careDetail/careDetail?id=${id}`,
-    //   });
-    // }
   },
   },
   onTabChange(e: any) {
   onTabChange(e: any) {
     const progress = e.detail.value;
     const progress = e.detail.value;

+ 3 - 3
miniprogram/module/care/pages/offlineTreatment/offlineTreatment.wxml

@@ -25,15 +25,15 @@
             </view>
             </view>
             <view class="row">
             <view class="row">
               <text class="sub-label">频次:</text>
               <text class="sub-label">频次:</text>
-              每{{item.frequencyType}}天{{item.frequencyMeasure}}{{item.convertUnit??'次'}}
+              每{{item.frequencyType}}天{{item.frequencyMeasure}}{{item.convertUnit ? item.convertUnit : '次'}}
             </view>
             </view>
             <view class="row">
             <view class="row">
               <text class="sub-label">下次时间:</text>
               <text class="sub-label">下次时间:</text>
-              {{item.arrangeDate ?? '-'}} {{item.arrangeTime ?? ''}}{{item.applyTime?'(已预约)':''}}
+              {{item.arrangeDate ? item.arrangeDate : '-'}} {{item.arrangeTime ? item.arrangeTime : ''}}{{item.applyTime ? '(已预约)' : ''}}
             </view>
             </view>
             <view class="row" wx:if="{{item.pieTime}}">
             <view class="row" wx:if="{{item.pieTime}}">
               <text class="sub-label">机构:</text>
               <text class="sub-label">机构:</text>
-              {{item.conditioningProgramSupplierName ?? '-'}}
+              {{item.conditioningProgramSupplierName ? item.conditioningProgramSupplierName : '-'}}
             </view>
             </view>
             <view class="divider"></view>
             <view class="divider"></view>
           </view>
           </view>

+ 10 - 0
miniprogram/module/order/model/evaluate.model.ts

@@ -11,3 +11,13 @@ export interface EvaluateModel {
   imageVideos:string[];  //评价图片/视频
   imageVideos:string[];  //评价图片/视频
   createTime:string;  //创建时间
   createTime:string;  //创建时间
 }
 }
+
+export interface OfflineEvaluateModel {
+  lineId:number,
+  patientConditioningRecordId: number;
+  patientConditioningProgramId: number;
+  operateTime: string;
+  operateBy: string;
+  conditioningProgramSupplierName: string;
+  image: string;
+}

+ 2 - 3
miniprogram/module/order/pages/goods-evaluate/goods-evaluate.scss

@@ -133,13 +133,12 @@
 
 
 .media-item {
 .media-item {
   position: relative;
   position: relative;
-  width: 142rpx;
-  height: 142rpx;
+  width: 140rpx;
+  height: 140rpx;
   flex-shrink: 0;
   flex-shrink: 0;
   border-radius: 12rpx;
   border-radius: 12rpx;
   overflow: hidden;
   overflow: hidden;
   background: #f5f5f5;
   background: #f5f5f5;
-  margin-right: 5px;
   margin-bottom: 10px;
   margin-bottom: 10px;
 }
 }
 
 

+ 44 - 13
miniprogram/module/order/pages/goods-evaluate/goods-evaluate.ts

@@ -2,6 +2,17 @@ import PageContainerBehavior from "../../../../core/behavior/page-container.beha
 import { EvaluateModel } from "../../model/evaluate.model";
 import { EvaluateModel } from "../../model/evaluate.model";
 import { evaluateOrderGoodsMethod } from "../../request";
 import { evaluateOrderGoodsMethod } from "../../request";
 import { upload } from "../../../../lib/request/upload";
 import { upload } from "../../../../lib/request/upload";
+
+function withMediaType(url: string, type: "image" | "video") {
+  if (!url) return url;
+  const hasQuery = url.includes("?");
+  const hasHash = url.includes("#");
+  if (hasHash) {
+    const [base, hash] = url.split("#");
+    return `${base}${hasQuery ? "&" : "?"}type=${type}#${hash ?? ""}`;
+  }
+  return `${url}${hasQuery ? "&" : "?"}type=${type}`;
+}
 Page({
 Page({
   behaviors: [PageContainerBehavior],
   behaviors: [PageContainerBehavior],
   data: {
   data: {
@@ -77,8 +88,33 @@ Page({
           path: f.tempFilePath,
           path: f.tempFilePath,
           type: (f.fileType === "video" ? "video" : "image") as "image" | "video",
           type: (f.fileType === "video" ? "video" : "image") as "image" | "video",
         }));
         }));
+        const oldLength = this.data.mediaList.length;
         const next = [...this.data.mediaList, ...list].slice(0, 9);
         const next = [...this.data.mediaList, ...list].slice(0, 9);
         this.setData({ mediaList: next });
         this.setData({ mediaList: next });
+
+        // 选取本地媒体后,调用上传接口上传到服务器
+        list.forEach((item, idx) => {
+          const index = oldLength + idx;
+          upload<string, any>({
+            params: { name: "file", file: item.path },
+            transform({ data }: any): string {
+              return (data as any)?.url || (data as any);
+            },
+          }).then(
+            (url) => {
+              const key = `mediaList[${index}].path`;
+              this.setData({ [key]: url });
+            },
+            (error: any) => {
+              wx.showToast({
+                title: error?.errMsg || "上传失败",
+                icon: "none",
+              });
+              const mediaList = this.data.mediaList.filter((_, i) => i !== index);
+              this.setData({ mediaList });
+            }
+          );
+        });
       },
       },
     });
     });
   },
   },
@@ -120,25 +156,20 @@ Page({
       patientConditioningRecordId: this.data.product.patientConditioningRecordId,
       patientConditioningRecordId: this.data.product.patientConditioningRecordId,
       complianceScore: this.data.score,
       complianceScore: this.data.score,
       depict: this.data.content,
       depict: this.data.content,
-      imageVideos: this.data.mediaList,
+      imageVideos: this.data.mediaList.map((m) => withMediaType(m.path, m.type)),
     };
     };
     console.log(data,"评价数据")
     console.log(data,"评价数据")
-    return
-    // TODO: 调用评价提交接口,将 this.data.score、content、mediaList 上传
     try {
     try {
-      await evaluateOrderGoodsMethod(data)
       wx.showLoading({ title: "发布中..." });
       wx.showLoading({ title: "发布中..." });
-      setTimeout(() => {
-        wx.hideLoading();
-        wx.showToast({ title: "发布成功", icon: "success" });
-        wx.redirectTo({
-          url: `/module/order/pages/other-detail/other-detail`,
-        });
-      }, 500);
+      await evaluateOrderGoodsMethod(data);
+      wx.hideLoading();
+      wx.showToast({ title: "发布成功", icon: "success" });
+      wx.redirectTo({
+        url: `/module/article/pages/order-list/order-list`,
+      });
     } catch (error: any) {
     } catch (error: any) {
-      wx.showToast({ title: error.errMsg || "发布失败", icon: "none" });
-    } finally {
       wx.hideLoading();
       wx.hideLoading();
+      wx.showToast({ title: error.errMsg || "发布失败", icon: "none" });
     }
     }
   },
   },
 });
 });

+ 2 - 2
miniprogram/module/order/pages/goods-evaluate/goods-evaluate.wxml

@@ -38,10 +38,10 @@
         placeholder-class="comment-placeholder"
         placeholder-class="comment-placeholder"
         value="{{content}}"
         value="{{content}}"
         bindinput="onContentInput"
         bindinput="onContentInput"
-        maxlength="{{500}}"
+        maxlength="{{200}}"
         show-confirm-bar="{{false}}"
         show-confirm-bar="{{false}}"
       />
       />
-      <view class="comment-count" wx:if="{{content.length > 0}}">{{content.length}}/500</view>
+      <view class="comment-count" wx:if="{{content.length > 0}}">{{content.length}}/200</view>
     </view>
     </view>
 
 
     <!-- 图/视频 上传(图片+视频总数不超过9个,添加按钮在最后,一行4个) -->
     <!-- 图/视频 上传(图片+视频总数不超过9个,添加按钮在最后,一行4个) -->

+ 2 - 3
miniprogram/module/order/pages/goods-evaluateDetail/goods-evaluateDetail.scss

@@ -212,13 +212,12 @@
 
 
 .media-item {
 .media-item {
   position: relative;
   position: relative;
-  width: 142rpx;
-  height: 142rpx;
+  width: 140rpx;
+  height: 140rpx;
   flex-shrink: 0;
   flex-shrink: 0;
   border-radius: 12rpx;
   border-radius: 12rpx;
   overflow: hidden;
   overflow: hidden;
   background: #f5f5f5;
   background: #f5f5f5;
-  margin-right: 5px;
   margin-bottom: 10px;
   margin-bottom: 10px;
 }
 }
 
 

+ 74 - 34
miniprogram/module/order/pages/goods-evaluateDetail/goods-evaluateDetail.ts

@@ -1,21 +1,37 @@
 import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
 import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
+import { getOrderGoodsEvaluationMethod } from "../../request";
+import { EvaluateModel } from "../../model/evaluate.model";
+
+function parseMediaType(url: string): "image" | "video" {
+  if (!url) return "image";
+  const match = /[?&]type=(image|video)\b/i.exec(url);
+  if (match) return match[1].toLowerCase() as "image" | "video";
+  const lower = url.toLowerCase();
+  if (/\.(mp4|mov|avi|rmvb|flv|mkv|webm)$/.test(lower)) return "video";
+  return "image";
+}
 
 
 Page({
 Page({
   behaviors: [PageContainerBehavior],
   behaviors: [PageContainerBehavior],
   data: {
   data: {
     orderId: "",
     orderId: "",
-    product: {} as { name: string; image: string;  description?: string },
-    score: 5,
+    product: {} as { id: number; name: string; image: string; description?: string },
+    evaluateInfo: {} as EvaluateModel,
+    // 只读展示用
+    score: 0,
     rateColor: "#F7BA2A",
     rateColor: "#F7BA2A",
-    content: "描述相符,商品质量很好,包装完整,会回购。",
+    content: "",
     mediaList: [] as { path: string; type: "image" | "video" }[],
     mediaList: [] as { path: string; type: "image" | "video" }[],
     videoFullscreen: false,
     videoFullscreen: false,
     showMediaCarousel: false,
     showMediaCarousel: false,
     mediaCarouselCurrent: 0,
     mediaCarouselCurrent: 0,
   },
   },
-  onLoad(options: Record<string, string>) {
-    const orderId = options.orderId || options.id || "";
-    let product: { name: string; image: string;  description?: string } = {
+  async onLoad(options: Record<string, string>) {
+    console.log(options, "options===");
+
+
+    let product: { id: number; name: string; image: string; description?: string } = {
+      id: 0,
       name: "",
       name: "",
       image: "",
       image: "",
       description: "",
       description: "",
@@ -24,44 +40,68 @@ Page({
     if (options.goodsInfo) {
     if (options.goodsInfo) {
       try {
       try {
         const goods = JSON.parse(decodeURIComponent(options.goodsInfo));
         const goods = JSON.parse(decodeURIComponent(options.goodsInfo));
+        console.log(goods, "goods===");
         product = {
         product = {
+          id: goods.id || 0,
           name: goods.name || "",
           name: goods.name || "",
           image: goods.image || "",
           image: goods.image || "",
           description: goods.description || "",
           description: goods.description || "",
         };
         };
-      } catch (_) {}
+      } catch (_) { }
+    }
+    this.setData({ product });
+    console.log(product, "product===");
+
+    if (product.id) {
+      try {
+        const res = await getOrderGoodsEvaluationMethod("1", product.id);
+        if (!res && !res.data) return;
+        console.log(res, "res===");
+        const mediaList: { path: string; type: "image" | "video" }[] = [];
+        if (Array.isArray(res.data.imageVideos)) {
+          res.data.imageVideos.forEach((url: string) => {
+            if (!url) return;
+            mediaList.push({
+              path: url,
+              type: parseMediaType(url),
+            });
+          });
+        }
+        this.setData({
+          evaluateInfo: res.data,
+          score: Number(res.data.complianceScore ?? 0),
+          content: res.data.depict || "",
+          mediaList,
+        });
+
+      } catch (error: any) {
+        console.log(error, "error===");
+        wx.showToast({
+          title: error?.errMsg || "获取评价详情失败",
+          icon: "none",
+        });
+      }
     }
     }
-console.log(product, "product===");
-    // 若传入评价详情数据则使用,否则用默认展示内容(含示例图片)
-    let score = 5;
-    let content = "描述相符,商品质量很好,包装完整,会回购。";
-    let mediaList: { path: string; type: "image" | "video" }[] = [
-      { path: "https://wx.hzliuzhi.com/media/healthManager/wx/share.jpg", type: "image" },
-      { path: "https://www.bing.com/ck/a?!&&p=7a26e0938030f722bac8864df3c965e36cf2569da9cb49288cb379ee8c3a662eJmltdHM9MTc3MjY2ODgwMA&ptn=3&ver=2&hsh=4&fclid=0f40599a-c9c4-6515-0a75-4f28c8bc64d0&u=a1L3ZpZGVvcy9yaXZlcnZpZXcvcmVsYXRlZHZpZGVvP3E9MTBzJWU4JWE3JTg2JWU5JWEyJTkxJiZtaWQ9MTcxMjQxNTk0MzFFQ0Y3OTFDNEExNzEyNDE1OTQzMUVDRjc5MUM0QSZGT1JNPVZBTUdaQw", type: "video" },
-      { path: "https://wx.hzliuzhi.com/media/healthManager/wx/share.jpg", type: "image" },
-      { path: "https://www.bing.com/ck/a?!&&p=7a26e0938030f722bac8864df3c965e36cf2569da9cb49288cb379ee8c3a662eJmltdHM9MTc3MjY2ODgwMA&ptn=3&ver=2&hsh=4&fclid=0f40599a-c9c4-6515-0a75-4f28c8bc64d0&u=a1L3ZpZGVvcy9yaXZlcnZpZXcvcmVsYXRlZHZpZGVvP3E9MTBzJWU4JWE3JTg2JWU5JWEyJTkxJiZtaWQ9MTcxMjQxNTk0MzFFQ0Y3OTFDNEExNzEyNDE1OTQzMUVDRjc5MUM0QSZGT1JNPVZBTUdaQw", type: "video" },
-      { path: "https://wx.hzliuzhi.com/media/healthManager/wx/share.jpg", type: "image" },
-      { path: "https://www.bing.com/ck/a?!&&p=7a26e0938030f722bac8864df3c965e36cf2569da9cb49288cb379ee8c3a662eJmltdHM9MTc3MjY2ODgwMA&ptn=3&ver=2&hsh=4&fclid=0f40599a-c9c4-6515-0a75-4f28c8bc64d0&u=a1L3ZpZGVvcy9yaXZlcnZpZXcvcmVsYXRlZHZpZGVvP3E9MTBzJWU4JWE3JTg2JWU5JWEyJTkxJiZtaWQ9MTcxMjQxNTk0MzFFQ0Y3OTFDNEExNzEyNDE1OTQzMUVDRjc5MUM0QSZGT1JNPVZBTUdaQw", type: "video" },
-    ];
-    // if (options.evaluateInfo) {
-    //   try {
-    //     const info = JSON.parse(decodeURIComponent(options.evaluateInfo));
-    //     if (info.score != null) score = Number(info.score);
-    //     if (info.content != null) content = info.content;
-    //     if (Array.isArray(info.mediaList) && info.mediaList.length > 0) mediaList = info.mediaList;
-    //   } catch (_) {}
-    // }
-    this.setData({
-      orderId,
-      product,
-      score,
-      content,
-      mediaList,
-    });
   },
   },
   onBack() {
   onBack() {
     wx.navigateBack();
     wx.navigateBack();
   },
   },
+  // 图片预览(九宫格内点击)
+  onPreviewImage(e: WechatMiniprogram.TouchEvent) {
+    const url = e.currentTarget.dataset.url as string;
+    const urls = this.data.mediaList
+      .filter((m) => m.type === "image")
+      .map((m) => m.path);
+    if (url && urls.length) {
+      wx.previewImage({ current: url, urls });
+    }
+  },
+  // 视频预览(九宫格内点击,先全屏)
+  onPreviewVideo(e: WechatMiniprogram.TouchEvent) {
+    const index = e.currentTarget.dataset.index as number;
+    const ctx = wx.createVideoContext("goods-detail-video-" + index, this);
+    ctx.requestFullScreen({});
+  },
   /** 打开图片/视频统一轮播,从指定下标开始;轮播到视频时自动播放 */
   /** 打开图片/视频统一轮播,从指定下标开始;轮播到视频时自动播放 */
   onPreviewMedia(e: WechatMiniprogram.TouchEvent) {
   onPreviewMedia(e: WechatMiniprogram.TouchEvent) {
     const index = e.currentTarget.dataset.index as number;
     const index = e.currentTarget.dataset.index as number;

+ 85 - 53
miniprogram/module/order/pages/offline-evaluate/offline-evaluate.ts

@@ -1,24 +1,22 @@
 import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
 import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
-
+import { evaluateOrderGoodsMethod } from "../../request";
+import { upload } from "../../../../lib/request/upload";
+import { OfflineEvaluateModel } from "../../model/evaluate.model";
+function withMediaType(url: string, type: "image" | "video") {
+  if (!url) return url;
+  const hasQuery = url.includes("?");
+  const hasHash = url.includes("#");
+  if (hasHash) {
+    const [base, hash] = url.split("#");
+    return `${base}${hasQuery ? "&" : "?"}type=${type}#${hash ?? ""}`;
+  }
+  return `${url}${hasQuery ? "&" : "?"}type=${type}`;
+}
 Page({
 Page({
   behaviors: [PageContainerBehavior],
   behaviors: [PageContainerBehavior],
   data: {
   data: {
     orderId: "",
     orderId: "",
-    service: {
-      name: "穴位按摩",
-      date: "2025-02-4",
-      time: "15:45:12",
-      operator: "黄医生",
-      institution: "余杭区第一人民医院",
-      image: "/assets/bg/bg_dialog@2x.png",
-    } as {
-      name: string;
-      date: string;
-      time: string;
-      operator: string;
-      institution: string;
-      image: string;
-    },
+    service: {} as OfflineEvaluateModel,
     scoreServiceQuality: 0,
     scoreServiceQuality: 0,
     scoreAttitude: 0,
     scoreAttitude: 0,
     scoreEnvironment: 0,
     scoreEnvironment: 0,
@@ -28,32 +26,28 @@ Page({
     canPublish: false,
     canPublish: false,
     videoFullscreen: false,
     videoFullscreen: false,
   },
   },
+
   onLoad(options: Record<string, string>) {
   onLoad(options: Record<string, string>) {
-    const orderId = options.orderId || options.id || "";
-    let service = this.data.service;
-    if (options.serviceInfo) {
-      try {
-        const info = JSON.parse(decodeURIComponent(options.serviceInfo));
-        service = {
-          name: info.name ?? service.name,
-          date: info.date ?? service.date,
-          time: info.time ?? service.time,
-          operator: info.operator ?? service.operator,
-          institution: info.institution ?? service.institution,
-          image: info.image ?? service.image,
-        };
-      } catch (_) {}
+    let service = {} as OfflineEvaluateModel;
+    if (options.goodsInfo) {
+      const goods = JSON.parse(decodeURIComponent(options.goodsInfo));
+      service = {
+        lineId: goods.id || 0,
+        patientConditioningRecordId: goods.patientConditioningRecordId || 0,
+        patientConditioningProgramId: goods.patientConditioningProgramId || 0,
+        operateTime: goods.operateTime || "",
+        operateBy: goods.operateBy || "",
+        conditioningProgramSupplierName: goods.conditioningProgramSupplierName || "",
+        image: goods.image || "",
+      };
+      console.log(service, "service===");
     }
     }
     this.setData({
     this.setData({
-      orderId,
       service,
       service,
-      canPublish: this._checkCanPublish(
-        this.data.scoreServiceQuality,
-        this.data.scoreAttitude,
-        this.data.scoreEnvironment
-      ),
+      canPublish: this._checkCanPublish(0, 0, 0),
     });
     });
   },
   },
+
   _checkCanPublish(
   _checkCanPublish(
     quality: number,
     quality: number,
     attitude: number,
     attitude: number,
@@ -105,8 +99,33 @@ Page({
           path: f.tempFilePath,
           path: f.tempFilePath,
           type: (f.fileType === "video" ? "video" : "image") as "image" | "video",
           type: (f.fileType === "video" ? "video" : "image") as "image" | "video",
         }));
         }));
+        const oldLength = this.data.mediaList.length;
         const next = [...this.data.mediaList, ...list].slice(0, 9);
         const next = [...this.data.mediaList, ...list].slice(0, 9);
         this.setData({ mediaList: next });
         this.setData({ mediaList: next });
+
+        // 选取本地媒体后,调用上传接口上传到服务器
+        list.forEach((item, idx) => {
+          const index = oldLength + idx;
+          upload<string, any>({
+            params: { name: "file", file: item.path },
+            transform({ data }: any): string {
+              return (data as any)?.url || (data as any);
+            },
+          }).then(
+            (url) => {
+              const key = `mediaList[${index}].path`;
+              this.setData({ [key]: url });
+            },
+            (error: any) => {
+              wx.showToast({
+                title: error?.errMsg || "上传失败",
+                icon: "none",
+              });
+              const mediaList = this.data.mediaList.filter((_, i) => i !== index);
+              this.setData({ mediaList });
+            }
+          );
+        });
       },
       },
     });
     });
   },
   },
@@ -134,32 +153,45 @@ Page({
   onRemoveService() {
   onRemoveService() {
     this.setData({
     this.setData({
       service: {
       service: {
-        name: "",
-        date: "",
-        time: "",
-        operator: "",
-        institution: "",
+        patientConditioningRecordId: 0,
+        patientConditioningProgramId: 0,
+        operateTime: "",
+        operateBy: "",
+        conditioningProgramSupplierName: "",
         image: "",
         image: "",
       },
       },
     });
     });
   },
   },
-  onPublish() {
+  async onPublish() {
     if (!this.data.canPublish) {
     if (!this.data.canPublish) {
       wx.showToast({ title: "请完成三项评分", icon: "none" });
       wx.showToast({ title: "请完成三项评分", icon: "none" });
       return;
       return;
     }
     }
-    const { orderId } = this.data;
-    wx.showLoading({ title: "发布中..." });
-    setTimeout(() => {
+
+    console.log(this.data.service, "this.data.service===");
+    try {
+      const data = {
+        lineId: this.data.service?.lineId,
+        patientConditioningRecordId: this.data.service?.patientConditioningRecordId,
+        patientConditioningProgramId: this.data.service?.patientConditioningProgramId,
+        complianceScore: this.data.scoreServiceQuality,
+        qualityScore: this.data.scoreServiceQuality,
+        attitudeScore: this.data.scoreAttitude,
+        environmentScore: this.data.scoreEnvironment,
+        depict: this.data.content,
+        imageVideos: this.data.mediaList.map((m) => withMediaType(m.path, m.type)),
+      };
+      console.log(data, "data===");
+      wx.showLoading({ title: "发布中..." });
+      await evaluateOrderGoodsMethod(data);
       wx.hideLoading();
       wx.hideLoading();
       wx.showToast({ title: "发布成功", icon: "success" });
       wx.showToast({ title: "发布成功", icon: "success" });
-      if (orderId) {
-        wx.redirectTo({
-          url: `/module/order/pages/other-detail/other-detail?id=${orderId}`,
-        });
-      } else {
-        wx.navigateBack();
-      }
-    }, 500);
+      wx.redirectTo({
+        url: `/module/order/pages/offline-evaluate/offline-evaluate`,
+      });
+    } catch (error: any) {
+      wx.hideLoading();
+      wx.showToast({ title: error.errMsg || "发布失败", icon: "none" });
+    }
   },
   },
 });
 });

+ 6 - 7
miniprogram/module/order/pages/offline-evaluate/offline-evaluate.wxml

@@ -3,17 +3,16 @@
 <scroll-view class="page-scroll__container" type="list" scroll-y style="{{containerStyle}}">
 <scroll-view class="page-scroll__container" type="list" scroll-y style="{{containerStyle}}">
   <view class="evaluate-container">
   <view class="evaluate-container">
     <!-- 服务信息卡片:缩略图 + 服务名|日期 时间 + 操作人 + 机构,右上角关闭 -->
     <!-- 服务信息卡片:缩略图 + 服务名|日期 时间 + 操作人 + 机构,右上角关闭 -->
-    <view class="service-card" wx:if="{{service.name}}">
+    <view class="service-card">
       <image class="service-img" src="{{service.image}}" mode="aspectFill" />
       <image class="service-img" src="{{service.image}}" mode="aspectFill" />
       <view class="service-info">
       <view class="service-info">
         <view class="service-name-row">
         <view class="service-name-row">
           <text class="service-name">{{service.name}}</text>
           <text class="service-name">{{service.name}}</text>
           <text class="service-divider">|</text>
           <text class="service-divider">|</text>
-          <text class="service-date">{{service.date}}</text>
-          <text class="service-time">{{service.time}}</text>
+          <text class="service-date">{{service.operateTime}}</text>
         </view>
         </view>
-        <view class="service-row" wx:if="{{service.operator}}">操作人: {{service.operator}}</view>
-        <view class="service-row" wx:if="{{service.institution}}">机构: {{service.institution}}</view>
+        <view class="service-row" wx:if="{{service.operateBy}}">操作人: {{service.operateBy}}</view>
+        <view class="service-row" wx:if="{{service.conditioningProgramSupplierName}}">机构: {{service.conditioningProgramSupplierName}}</view>
       </view>
       </view>
     </view>
     </view>
 
 
@@ -70,10 +69,10 @@
         placeholder-class="comment-placeholder"
         placeholder-class="comment-placeholder"
         value="{{content}}"
         value="{{content}}"
         bindinput="onContentInput"
         bindinput="onContentInput"
-        maxlength="{{500}}"
+        maxlength="{{200}}"
         show-confirm-bar="{{false}}"
         show-confirm-bar="{{false}}"
       />
       />
-      <view class="comment-count" wx:if="{{content.length > 0}}">{{content.length}}/500</view>
+      <view class="comment-count" wx:if="{{content.length > 0}}">{{content.length}}/200</view>
     </view>
     </view>
 
 
     <!-- 图/视频 上传(图片+视频总数不超过9个,添加按钮在最后,一行4个) -->
     <!-- 图/视频 上传(图片+视频总数不超过9个,添加按钮在最后,一行4个) -->

+ 2 - 3
miniprogram/module/order/pages/offline-evaluateDetail/offline-evaluateDetail.scss

@@ -275,13 +275,12 @@
 
 
 .media-item {
 .media-item {
   position: relative;
   position: relative;
-  width: 142rpx;
-  height: 142rpx;
+  width: 140rpx;
+  height: 140rpx;
   flex-shrink: 0;
   flex-shrink: 0;
   border-radius: 12rpx;
   border-radius: 12rpx;
   overflow: hidden;
   overflow: hidden;
   background: #f5f5f5;
   background: #f5f5f5;
-  margin-right: 5px;
   margin-bottom: 10px;
   margin-bottom: 10px;
 }
 }
 
 

+ 76 - 90
miniprogram/module/order/pages/offline-evaluateDetail/offline-evaluateDetail.ts

@@ -1,112 +1,98 @@
 import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
 import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
-
+import { OfflineEvaluateModel } from "../../model/evaluate.model";
+import { getOrderGoodsEvaluationMethod } from "../../request";
+function parseMediaType(url: string): "image" | "video" {
+  if (!url) return "image";
+  const match = /[?&]type=(image|video)\b/i.exec(url);
+  if (match) return match[1].toLowerCase() as "image" | "video";
+  const lower = url.toLowerCase();
+  if (/\.(mp4|mov|avi|rmvb|flv|mkv|webm)$/.test(lower)) return "video";
+  return "image";
+}
 Page({
 Page({
   behaviors: [PageContainerBehavior],
   behaviors: [PageContainerBehavior],
   data: {
   data: {
     orderId: "",
     orderId: "",
-    service: {} as { name: string; image: string; description?: string; date?: string; time?: string; operator?: string; institution?: string },
-    scoreServiceQuality: 5,
-    scoreAttitude: 5,
-    scoreEnvironment: 5,
+    service: {} as OfflineEvaluateModel,
+    scoreServiceQuality: 0,
+    scoreAttitude: 0,
+    scoreEnvironment: 0,
     rateColor: "#F7BA2A",
     rateColor: "#F7BA2A",
-    content: "描述相符,商品质量很好,包装完整,会回购。",
+    content: "",
     mediaList: [] as { path: string; type: "image" | "video" }[],
     mediaList: [] as { path: string; type: "image" | "video" }[],
-    showMediaCarousel: false,
-    mediaCarouselCurrent: 0,
+    videoFullscreen: false,
   },
   },
-  onLoad(options: Record<string, string>) {
-    const orderId = options.orderId || options.id || "";
-    let service: { name: string; image: string;  description?: string } = {
-      name: "",
-      image: "",
-      description: "",
-      date: "",
-      time: "",
-      operator: "",
-      institution: "",
-    };
+  async onLoad(options: Record<string, string>) {
+    let service = {} as OfflineEvaluateModel;
     console.log(options, "options.goodsInfo===");
     console.log(options, "options.goodsInfo===");
     if (options.goodsInfo) {
     if (options.goodsInfo) {
-      try {
-        const goods = JSON.parse(decodeURIComponent(options.goodsInfo));
-        service = {
-          name: goods.name || "",
-          image: goods.image || "",
-          description: goods.description || "",
-          date: "2026-03-05",
-          time: "10:00:00",
-          operator: "张三",
-          institution: "杭州第一人民医院",
-        };
-      } catch (_) {}
-    }
-console.log(service, "service===");
-    // 若传入评价详情数据则使用,否则用默认展示内容(含示例图片)
-    let scoreServiceQuality = 2;
-    let scoreAttitude = 4;
-    let scoreEnvironment = 3;
-    let content = "描述相符,商品质量很好,包装完整,会回购。";
-    let mediaList: { path: string; type: "image" | "video" }[] = [
-      { path: "/assets/bg/bg_dialog@2x.png", type: "image" },
-    ];
-    if (options.evaluateInfo) {
-      try {
-        const info = JSON.parse(decodeURIComponent(options.evaluateInfo));
-        if (info.scoreServiceQuality != null) scoreServiceQuality = Number(info.scoreServiceQuality);
-        if (info.scoreAttitude != null) scoreAttitude = Number(info.scoreAttitude);
-        if (info.scoreEnvironment != null) scoreEnvironment = Number(info.scoreEnvironment);
-        if (info.content != null) content = info.content;
-        if (Array.isArray(info.mediaList) && info.mediaList.length > 0) mediaList = info.mediaList;
-      } catch (_) {}
+      const goods = JSON.parse(decodeURIComponent(options.goodsInfo));
+      service = {
+        lineId: goods.id || 0,
+        patientConditioningRecordId: goods.patientConditioningRecordId || 0,
+        patientConditioningProgramId: goods.patientConditioningProgramId || 0,
+        operateTime: goods.operateTime || "",
+        operateBy: goods.operateBy || "",
+        conditioningProgramSupplierName: goods.conditioningProgramSupplierName || "",
+        image: goods.image || "",
+      };
     }
     }
+    console.log(service, "service===");
     this.setData({
     this.setData({
-      orderId,
       service,
       service,
-      scoreServiceQuality,
-      scoreAttitude,
-      scoreEnvironment,
-      content,
-      mediaList,
     });
     });
+    if (service.patientConditioningRecordId) {
+      try {
+        const res = await getOrderGoodsEvaluationMethod("2", service.lineId);
+        console.log(res, "res===");
+        const mediaList: { path: string; type: "image" | "video" }[] = [];
+        if (res && res.data) {
+        if (Array.isArray(res.data.imageVideos)) {
+          res.data.imageVideos.forEach((url: string) => {
+            if (!url) return;
+            mediaList.push({
+              path: url,
+              type: parseMediaType(url),
+            });
+            });
+          }
+          this.setData({
+            evaluateInfo: res.data,
+            scoreServiceQuality: Number(res.data.complianceScore ?? 0),
+            scoreAttitude: Number(res.data.attitudeScore ?? 0),
+            scoreEnvironment: Number(res.data.environmentScore ?? 0),
+            content: res.data.depict || "",
+            mediaList,
+          });
+        }
+      } catch (error: any) {
+        console.log(error, "error===");
+        wx.showToast({
+          title: error?.errMsg || "获取评价详情失败",
+          icon: "none",
+        });
+      }
+    }
   },
   },
   onBack() {
   onBack() {
     wx.navigateBack();
     wx.navigateBack();
   },
   },
-  /** 打开图片/视频统一轮播,从指定下标开始;轮播到视频时自动播放 */
-  onPreviewMedia(e: WechatMiniprogram.TouchEvent) {
-    const index = e.currentTarget.dataset.index as number;
-    const { mediaList } = this.data;
-    if (index < 0 || index >= mediaList.length) return;
-    this.setData(
-      { showMediaCarousel: true, mediaCarouselCurrent: index },
-      () => {
-        this._playVideoAtCarouselIndex(index);
-      }
-    );
-  },
-  /** 轮播切换:暂停所有视频,若当前项是视频则播放 */
-  onMediaCarouselChange(e: WechatMiniprogram.SwiperChange) {
-    const current = e.detail?.current ?? 0;
-    this.setData({ mediaCarouselCurrent: current });
-    this._pauseAllCarouselVideos();
-    this._playVideoAtCarouselIndex(current);
-  },
-  onCloseMediaCarousel() {
-    this._pauseAllCarouselVideos();
-    this.setData({ showMediaCarousel: false });
+  onPreviewImage(e: WechatMiniprogram.TouchEvent) {
+    const url = e.currentTarget.dataset.url as string;
+    const urls = this.data.mediaList
+      .filter((m) => m.type === "image")
+      .map((m) => m.path);
+    if (url && urls.length) {
+      wx.previewImage({ current: url, urls });
+    }
   },
   },
-  _playVideoAtCarouselIndex(index: number) {
-    const list = this.data.mediaList;
-    if (index < 0 || index >= list.length || list[index].type !== "video") return;
-    const ctx = wx.createVideoContext("preview-video-" + index, this);
-    ctx.play();
+  onPreviewVideo(e: WechatMiniprogram.TouchEvent) {
+    const index = e.currentTarget.dataset.index as number;
+    const ctx = wx.createVideoContext("offline-detail-video-" + index, this);
+    ctx.requestFullScreen({});
   },
   },
-  _pauseAllCarouselVideos() {
-    this.data.mediaList.forEach((item, i) => {
-      if (item.type === "video") {
-        const ctx = wx.createVideoContext("preview-video-" + i, this);
-        ctx.pause();
-      }
-    });
+  onVideoFullscreenChange(e: WechatMiniprogram.VideoFullScreenChange) {
+    const fullScreen = !!(e.detail && e.detail.fullScreen);
+    this.setData({ videoFullscreen: fullScreen });
   },
   },
 });
 });

+ 11 - 44
miniprogram/module/order/pages/offline-evaluateDetail/offline-evaluateDetail.wxml

@@ -1,19 +1,18 @@
 <!-- 线下评价详情:整页只读,不允许用户修改,仅支持查看与返回 -->
 <!-- 线下评价详情:整页只读,不允许用户修改,仅支持查看与返回 -->
-<t-navbar title="评价" left-arrow />
+<t-navbar wx:if="{{!videoFullscreen}}" title="评价" left-arrow />
 <scroll-view class="page-scroll__container" type="list" scroll-y style="{{containerStyle}}">
 <scroll-view class="page-scroll__container" type="list" scroll-y style="{{containerStyle}}">
   <view class="evaluate-container evaluate-container--readonly">
   <view class="evaluate-container evaluate-container--readonly">
     <!-- 商品信息:仅展示 -->
     <!-- 商品信息:仅展示 -->
-    <view class="service-card" wx:if="{{service.name}}">
+    <view class="service-card">
       <image class="service-img" src="{{service.image}}" mode="aspectFill" />
       <image class="service-img" src="{{service.image}}" mode="aspectFill" />
       <view class="service-info">
       <view class="service-info">
         <view class="service-name-row">
         <view class="service-name-row">
           <text class="service-name">{{service.name}}</text>
           <text class="service-name">{{service.name}}</text>
           <text class="service-divider">|</text>
           <text class="service-divider">|</text>
-          <text class="service-date">{{service.date}}</text>
-          <text class="service-time">{{service.time}}</text>
+          <text class="service-date">{{service.operateTime}}</text>
         </view>
         </view>
-        <view class="service-row" wx:if="{{service.operator}}">操作人: {{service.operator}}</view>
-        <view class="service-row" wx:if="{{service.institution}}">机构: {{service.institution}}</view>
+        <view class="service-row" wx:if="{{service.operateBy}}">操作人: {{service.operateBy}}</view>
+        <view class="service-row" wx:if="{{service.conditioningProgramSupplierName}}">机构: {{service.conditioningProgramSupplierName}}</view>
       </view>
       </view>
     </view>
     </view>
 
 
@@ -67,13 +66,13 @@
       <view class="comment-display">{{content || '暂无评价内容'}}</view>
       <view class="comment-display">{{content || '暂无评价内容'}}</view>
     </view>
     </view>
 
 
-    <!-- 图片/视频:一行4个,点击进入统一轮播,轮播到视频自动播放 -->
+    <!-- 图片/视频:一行4个,可点击预览,视频全屏时隐藏导航和底部 -->
     <view class="upload-section">
     <view class="upload-section">
       <view class="media-grid media-list--readonly" wx:if="{{mediaList.length > 0}}">
       <view class="media-grid media-list--readonly" wx:if="{{mediaList.length > 0}}">
         <view class="media-item" wx:for="{{mediaList}}" wx:key="path">
         <view class="media-item" wx:for="{{mediaList}}" wx:key="path">
-          <image wx:if="{{item.type === 'image'}}" class="media-thumb" src="{{item.path}}" mode="aspectFill" bindtap="onPreviewMedia" data-index="{{index}}" />
-          <view wx:else class="media-item-video" bindtap="onPreviewMedia" data-index="{{index}}">
-            <video id="offline-detail-video-{{index}}" class="media-thumb" src="{{item.path}}" show-center-play-btn="{{true}}" object-fit="cover" controls="{{true}}" />
+          <image wx:if="{{item.type === 'image'}}" class="media-thumb" src="{{item.path}}" mode="aspectFill" bindtap="onPreviewImage" data-url="{{item.path}}" />
+          <view wx:else class="media-item-video" bindtap="onPreviewVideo" data-index="{{index}}">
+            <video id="offline-detail-video-{{index}}" class="media-thumb" src="{{item.path}}" show-center-play-btn="{{true}}" object-fit="cover" controls="{{true}}" bindfullscreenchange="onVideoFullscreenChange" />
             <view class="media-item-play"><t-icon name="play-circle-filled" size="56rpx" color="rgba(255,255,255,0.95)" /></view>
             <view class="media-item-play"><t-icon name="play-circle-filled" size="56rpx" color="rgba(255,255,255,0.95)" /></view>
           </view>
           </view>
         </view>
         </view>
@@ -82,39 +81,7 @@
   </view>
   </view>
 </scroll-view>
 </scroll-view>
 
 
-<!-- 底部返回 -->
-<view class="publish-footer" style="padding-bottom: {{container.safeBottomOffset}}px;">
+<!-- 底部返回(视频全屏时隐藏,避免遮挡) -->
+<view class="publish-footer" wx:if="{{!videoFullscreen}}" style="padding-bottom: {{container.safeBottomOffset}}px;">
   <view class="publish-btn" bindtap="onBack">返回</view>
   <view class="publish-btn" bindtap="onBack">返回</view>
 </view>
 </view>
-
-<!-- 全屏轮播:图片+视频一起,轮播到视频自动播放 -->
-<view class="media-carousel-overlay" wx:if="{{showMediaCarousel}}">
-  <swiper
-    class="media-carousel-swiper"
-    current="{{mediaCarouselCurrent}}"
-    duration="300"
-    circular="{{true}}"
-    bindchange="onMediaCarouselChange"
-  >
-    <swiper-item wx:for="{{mediaList}}" wx:key="path" class="media-carousel-item">
-      <view wx:if="{{item.type === 'image'}}" class="media-carousel-image-wrap">
-        <image class="media-carousel-image" src="{{item.path}}" mode="aspectFit" />
-      </view>
-      <view wx:else class="media-carousel-video-wrap">
-        <video
-          id="preview-video-{{index}}"
-          class="media-carousel-video"
-          src="{{item.path}}"
-          controls="{{true}}"
-          object-fit="contain"
-          show-center-play-btn="{{true}}"
-        />
-      </view>
-    </swiper-item>
-  </swiper>
-  <view class="media-carousel-close" bindtap="onCloseMediaCarousel">
-    <t-icon name="close" size="48rpx" color="#fff" />
-  </view>
-</view>
-
-

+ 2 - 2
miniprogram/module/order/request.ts

@@ -70,14 +70,14 @@ export function getAddressListMethod(id: string, keyWord: string) {
   );
   );
 }
 }
 //获取订单商品-线下核销记录的患者个人评价 type 1-商品 2-线下核销记录 id:商品/线下核销记录id
 //获取订单商品-线下核销记录的患者个人评价 type 1-商品 2-线下核销记录 id:商品/线下核销记录id
-export function getOrderGoodsEvaluationMethod(type: string, id: string) {
+export function getOrderGoodsEvaluationMethod(type: string, id: number) {
   return Post(`/patientCrManage/getEvaluate/${type}/${id}`, {
   return Post(`/patientCrManage/getEvaluate/${type}/${id}`, {
     transform({ data }: AnyObject) {
     transform({ data }: AnyObject) {
       return data;
       return data;
     },
     },
   });
   });
 }
 }
-// 订单商品评价
+// 订单商品/线下服务评价
 export function evaluateOrderGoodsMethod(data: any) {
 export function evaluateOrderGoodsMethod(data: any) {
   return Post(`/patientCrManage/evaluate`, data, {
   return Post(`/patientCrManage/evaluate`, data, {
     transform({ data }: { data: any }) {
     transform({ data }: { data: any }) {