张田田 2 月之前
父節點
當前提交
c0bcb9efe2
共有 39 個文件被更改,包括 2977 次插入19 次删除
  1. 1 0
      miniprogram/app.config.ts
  2. 4 1
      miniprogram/app.json
  3. 16 0
      miniprogram/module/afterSale/pages/questionnaire/questionnaire.json
  4. 208 0
      miniprogram/module/afterSale/pages/questionnaire/questionnaire.scss
  5. 223 0
      miniprogram/module/afterSale/pages/questionnaire/questionnaire.ts
  6. 68 0
      miniprogram/module/afterSale/pages/questionnaire/questionnaire.wxml
  7. 20 0
      miniprogram/module/afterSale/request.ts
  8. 6 0
      miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.json
  9. 186 0
      miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.scss
  10. 47 0
      miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.ts
  11. 49 0
      miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.wxml
  12. 10 0
      miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.json
  13. 269 0
      miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.scss
  14. 97 0
      miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.ts
  15. 116 0
      miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.wxml
  16. 7 0
      miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.json
  17. 171 0
      miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.scss
  18. 63 0
      miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.ts
  19. 49 0
      miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.wxml
  20. 8 0
      miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.json
  21. 70 0
      miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.scss
  22. 50 0
      miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.ts
  23. 35 0
      miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.wxml
  24. 6 0
      miniprogram/module/order/pages/negotiation-history/negotiation-history.json
  25. 137 0
      miniprogram/module/order/pages/negotiation-history/negotiation-history.scss
  26. 59 0
      miniprogram/module/order/pages/negotiation-history/negotiation-history.ts
  27. 46 0
      miniprogram/module/order/pages/negotiation-history/negotiation-history.wxml
  28. 5 1
      miniprogram/module/order/pages/other-detail/other-detail.json
  29. 10 1
      miniprogram/module/order/pages/other-detail/other-detail.scss
  30. 119 4
      miniprogram/module/order/pages/other-detail/other-detail.ts
  31. 59 12
      miniprogram/module/order/pages/other-detail/other-detail.wxml
  32. 12 0
      miniprogram/module/order/pages/refund-processing/refund-processing.json
  33. 316 0
      miniprogram/module/order/pages/refund-processing/refund-processing.scss
  34. 202 0
      miniprogram/module/order/pages/refund-processing/refund-processing.ts
  35. 170 0
      miniprogram/module/order/pages/refund-processing/refund-processing.wxml
  36. 6 0
      miniprogram/module/order/pages/refund-success/refund-success.json
  37. 42 0
      miniprogram/module/order/pages/refund-success/refund-success.scss
  38. 7 0
      miniprogram/module/order/pages/refund-success/refund-success.ts
  39. 8 0
      miniprogram/module/order/pages/refund-success/refund-success.wxml

+ 1 - 0
miniprogram/app.config.ts

@@ -7,6 +7,7 @@ if (env === "trial") {
   host = "test.hzliuzhi.com";
 } else if (env === "develop") {
   host = "wx.hzliuzhi.com:4433";
+  // host="test.hzliuzhi.com"
 }
 export const HOST = host;
 export const Base_URL = `https://${host}/manager/fdhb-mobile`;

+ 4 - 1
miniprogram/app.json

@@ -101,7 +101,10 @@
         "pages/goods-evaluateDetail/goods-evaluateDetail",
         "pages/offline-evaluate/offline-evaluate",
         "pages/offline-evaluateDetail/offline-evaluateDetail",
-        "pages/logistics-detail/logistics-detail"
+        "pages/logistics-detail/logistics-detail",
+        "pages/refund-success/refund-success",
+        "pages/refund-processing/refund-processing",
+        "pages/negotiation-history/negotiation-history"
       ]
     }
   ],

+ 16 - 0
miniprogram/module/afterSale/pages/questionnaire/questionnaire.json

@@ -0,0 +1,16 @@
+{
+  "renderer": "skyline",
+  "navigationBarTextStyle": "white",
+  "navigationBarBackgroundColor": "#0f2226",
+  "backgroundColor": "#0f2226",
+  "backgroundColorContent": "#ffffff",
+  "backgroundColorTop": "#0f2226",
+  "backgroundColorBottom": "#0f2226",
+  "component": true,
+  "usingComponents": {
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-navbar": "tdesign-miniprogram/navbar/navbar",
+    "t-radio": "tdesign-miniprogram/radio/radio",
+    "t-radio-group": "tdesign-miniprogram/radio-group/radio-group"
+  }
+}

+ 208 - 0
miniprogram/module/afterSale/pages/questionnaire/questionnaire.scss

@@ -0,0 +1,208 @@
+.page-container {
+  background-color: #f5f5f5;
+  height: calc(100vh - 64px);
+  box-sizing: border-box;
+}
+
+.questionnaire-container {
+  padding: 32rpx;
+  padding-bottom: 180rpx; // 为底部固定按钮留出足够空间(按钮高度88rpx + padding 48rpx + 安全区域 + 额外空间)
+  background-color: #fff;
+  min-height: 100%;
+}
+
+/* 标题 */
+.questionnaire-title {
+  font-size: 40rpx;
+  font-weight: bold;
+  color: #333;
+  text-align: center;
+  margin-bottom: 32rpx;
+}
+
+/* 介绍文字 */
+.questionnaire-intro {
+  font-size: 28rpx;
+  color: black;
+  line-height: 1.8;
+  margin-bottom: 32rpx;
+  text-align: justify;
+}
+
+/* 分数说明 */
+.score-explanation {
+  margin-bottom: 32rpx;
+}
+
+.score-explanation-text {
+  font-size: 28rpx;
+  color: #333;
+  line-height: 1.6;
+  font-weight: bold;
+}
+
+/* 问题组 */
+.question-groups {
+  margin-bottom: 32rpx;
+}
+
+.question-group {
+  margin-bottom: 32rpx;
+}
+
+.group-title {
+  font-size: 35rpx;
+  font-weight: bold;
+  color: #333;
+}
+
+/* 问题列表 */
+.question-list {
+  display: flex;
+  flex-direction: column;
+  gap: 32rpx;
+}
+
+.question-item {
+  padding-bottom: 32rpx;
+  border-bottom: 1px solid #f0f0f0;
+
+  &:last-child {
+    border-bottom: none;
+  }
+}
+
+.question-name {
+  font-size: 28rpx;
+  color: #333;
+  line-height: 1.6;
+  font-weight: bold;
+  margin: 20rpx 0 20rpx 0;
+}
+
+/* 分数选择 */
+.score-radio-group {
+  width: 100%;
+}
+
+.score-options {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  flex-wrap: wrap;
+}
+
+.score-radio-item {
+  margin-right: 32rpx;
+
+  &:last-child {
+    margin-right: 0;
+  }
+}
+
+/* 其他意见 */
+.other-comment-section {
+  margin-top: 32rpx;
+  margin-bottom: 32rpx;
+}
+
+.other-comment-title {
+  font-size: 28rpx;
+  color: #333;
+  margin-bottom: 16rpx;
+}
+
+.other-comment-input {
+  width: 100%;
+  min-height: 200rpx;
+  padding: 20rpx;
+  background-color: #f8f8f8;
+  border: 2rpx solid #e0e0e0;
+  border-radius: 8rpx;
+  font-size: 26rpx;
+  color: #333;
+  box-sizing: border-box;
+  line-height: 1.6;
+}
+
+/* 结束语 */
+.questionnaire-end {
+  font-size: 26rpx;
+  color: black;
+  margin-top: 22rpx;
+  margin-bottom: 32rpx;
+  padding-top: 32rpx;
+  border-top: 1px solid #f0f0f0;
+}
+
+/* 加载状态 */
+.loading-container {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 400rpx;
+  padding: 32rpx;
+}
+
+.loading-text {
+  font-size: 28rpx;
+  color: #999;
+}
+
+/* 空数据状态 */
+.empty-container {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 400rpx;
+  padding: 32rpx;
+}
+
+.empty-text {
+  font-size: 28rpx;
+  color: #999;
+}
+
+/* 保存按钮 */
+.save-button-container {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 24rpx 32rpx;
+  padding-bottom: calc(env(safe-area-inset-bottom));
+  background-color: #fff;
+  border-top: 1px solid #f0f0f0;
+  box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
+  z-index: 100;
+  box-sizing: border-box;
+}
+
+.save-button {
+  width: 100%;
+  height: 88rpx;
+  line-height: 88rpx;
+  background: linear-gradient(135deg, #1d6ff6 0%, #0d5dd8 100%);
+  border-radius: 44rpx;
+  color: #fff;
+  font-size: 32rpx;
+  font-weight: bold;
+  border: none;
+  display: block;
+  text-align: center;
+  transition: all 0.3s;
+
+  &::after {
+    border: none;
+  }
+
+  &[disabled] {
+    background: #ccc;
+    opacity: 0.6;
+  }
+
+  &:not([disabled]):active {
+    opacity: 0.8;
+    transform: scale(0.98);
+  }
+}

+ 223 - 0
miniprogram/module/afterSale/pages/questionnaire/questionnaire.ts

@@ -0,0 +1,223 @@
+
+import {
+  getQuestionnaireMethod,
+  submitQuestionnaireMethod,
+} from "../../request";
+
+export interface Questionnaire {
+  id: number; //	满意度调研问卷ID
+  name: string; //满意度调研问卷名称
+  startSentence: string; //开头语
+  endSentence: string; //结束语
+  suggestion: string; //其他意见
+  groups: Array<{
+    name: string; //	问题组名称
+    items: Array<{
+      name: string;
+      score?: string; // 原始分数(可选)
+      selectedScore?: number | string; // 用户选择的分数
+    }>;
+  }>;
+}
+Page({
+  onLoad(options: { id?: string }) {
+    // 如果没有传递 id,使用默认 id 1,或者可以根据实际情况调整
+    const questionnaireId = options.id ? Number(options.id) : 1;
+    this.setData({
+      "followDetail.id": questionnaireId,
+    });
+    if (questionnaireId) {
+      this.getQuestionnaire(questionnaireId);
+    } else {
+      wx.showToast({
+        title: "问卷ID不能为空",
+        icon: "none",
+        duration: 2000,
+      });
+    }
+  },
+
+  data: {
+    scoreList: [
+      {
+        label: "1分",
+        value: "1",
+      },
+      {
+        label: "2分",
+        value: "2",
+      },
+      {
+        label: "3分",
+        value: "3",
+      },
+      {
+        label: "4分",
+        value: "4",
+      },
+      {
+        label: "5分",
+        value: "5",
+      },
+    ],
+    followDetail: {
+      id: 0,
+    } as Questionnaire,
+    loading: true, // 加载状态
+    showEmpty: false, // 显示空数据
+    saving: false, // 保存状态
+    suggestion: "", // 其他意见
+  },
+
+  async getQuestionnaire(id: number) {
+    // 模拟后端数据(根据图片内容)
+    // const mockData: Questionnaire = {
+    //   id: id,
+    //   name: "就诊体验满意度",
+    //   startSentence:
+    //     "感谢您选择我院就诊,为了持续改进医疗服务质量,我们诚挚地邀请您参与本次满意度调研。您的真实反馈对我们非常重要,我们将严格保密您的个人信息,请您根据实际就诊体验,花费几分钟时间完成本次调研。",
+    //   endSentence:
+    //     "再次感谢您的参与,我们会根据您的反馈持续改进服务质量再次感谢您的参与,我们会根据您的反馈持续改进服务质量。再次感谢您的参与,我们会根据您的反馈持续改进服务质量再次感谢您的参与,我们会根据您的反馈持续改进服务质量再次感谢您的参与,我们会根据您的反馈持续改进服务质量再次感谢您的参与,我们会根据您的反馈持续改进服务质量",
+    //   suggestion: "其他意见",
+    //   groups: [
+    //     {
+    //       name: "一、就诊环境评价",
+    //       items: [
+    //         {
+    //           name: "医院门诊/住院部的整洁度",
+    //           score: "1",
+    //         },
+    //         {
+    //           name: "医院的通风情况",
+    //           score: "2",
+    //         },
+    //         {
+    //           name: "医院的采光情况",
+    //           score: "3",
+    //         },
+    //         {
+    //           name: "医院的噪音控制",
+    //           score: "4",
+    //         },
+    //         {
+    //           name: "候诊区域的舒适度(座椅、空间等)",
+    //           score: "5",
+    //         },
+    //       ],
+    //     },
+    //   ],
+    // };
+
+    // 模拟网络延迟
+    // await new Promise((resolve) => setTimeout(resolve, 500));
+
+    // this.setData({
+    //   followDetail: mockData,
+    //   loading: false,
+    // });
+    // 实际接口调用
+    let list = await getQuestionnaireMethod(id);
+    const questionnaireData = list?.data as Questionnaire;
+    // 确保 id 字段存在,如果后端没有返回 id,使用传入的 id
+    const finalData = questionnaireData
+      ? { ...questionnaireData, id: questionnaireData.id || id }
+      : ({ id } as Questionnaire);
+    this.setData({
+      loading: false,
+      followDetail: finalData,
+      showEmpty: JSON.stringify(list?.data) === "{}" ? true : false,
+    });
+  },
+
+  // 选择分数(radio-group change 事件)
+  onScoreChange(e: WechatMiniprogram.CustomEvent) {
+    const { groupIndex, itemIndex } = e.currentTarget.dataset;
+    const score = e.detail.value;
+    const groups = [...this.data.followDetail.groups];
+    groups[groupIndex].items[itemIndex].selectedScore = score;
+
+    this.setData({
+      "followDetail.groups": groups,
+    });
+  },
+
+  // 输入其他意见
+  onCommentInput(e: WechatMiniprogram.Input) {
+    this.setData({
+      suggestion: e.detail.value,
+    });
+  },
+
+  // 保存问卷
+  async onSave() {
+    // 检查是否所有问题都已回答
+    const groups = this.data.followDetail?.groups || [];
+    // let allAnswered = true;
+    // let unansweredQuestions: string[] = [];
+    // for (const group of groups) {
+    //   for (const item of group.items) {
+    //     if (!item.selectedScore) {
+    //       allAnswered = false;
+    //       unansweredQuestions.push(item.name);
+    //     }
+    //   }
+    // }
+
+    // if (!allAnswered) {
+    //   wx.showToast({
+    //     title: "请完成所有问题的评分",
+    //     icon: "none",
+    //     duration: 2000,
+    //   });
+    //   return;
+    // }
+    // 准备提交数据
+    const submitData = {
+      groups: groups.map((group) => ({
+        name: group.name,
+        items: group.items.map((item) => ({
+          name: item.name,
+          score: item.selectedScore ? String(item.selectedScore) : "",
+        })),
+      })),
+      startSentence: this.data.followDetail.startSentence,
+      endSentence: this.data.followDetail.endSentence,
+      suggestion: this.data.suggestion,
+      name: this.data.followDetail.name,
+    };
+    this.setData({
+      saving: true,
+    });
+
+    try {
+      // 实际接口调用
+      await submitQuestionnaireMethod(
+        this.data.followDetail.id,
+        submitData as AnyObject
+      );
+      wx.showToast({
+        title: "提交成功",
+        icon: "success",
+        duration: 2000,
+      });
+      setTimeout(() => {
+        wx.redirectTo({
+          url: "/pages/home/home",
+        });
+      }, 2000);
+    } catch (error) {
+      wx.showToast({
+        title: "保存失败,请重试",
+        icon: "none",
+        duration: 2000,
+      });
+      this.setData({
+        saving: false,
+      });
+    } finally {
+      this.setData({
+        saving: false,
+      });
+    }
+  },
+});

+ 68 - 0
miniprogram/module/afterSale/pages/questionnaire/questionnaire.wxml

@@ -0,0 +1,68 @@
+<t-navbar title="满意度问卷" left-arrow />
+<scroll-view class="page-container" scroll-y>
+  <!-- 加载状态 -->
+  <view class="loading-container" wx:if="{{loading}}">
+    <view class="loading-text">加载中...</view>
+  </view>
+
+  <!-- 问卷内容 -->
+  <view class="questionnaire-container" wx:elif="{{!showEmpty}}">
+    <!-- 标题 -->
+    <view class="questionnaire-title">{{followDetail.name || '满意度问卷'}}</view>
+
+    <!-- 介绍文字 -->
+    <view class="questionnaire-intro" wx:if="{{followDetail.startSentence}}">
+      {{followDetail.startSentence}}
+    </view>
+
+    <!-- 分数说明 -->
+    <view class="score-explanation">
+      <text class="score-explanation-text">分数说明:1分表示非常不满意,2分表示不满意,3分表示一般,4分表示满意,5分表示非常满意</text>
+    </view>
+
+    <!-- 问题组 -->
+    <view class="question-groups" wx:if="{{followDetail.groups}}">
+      <view class="question-group" wx:for="{{followDetail.groups}}" wx:key="index" wx:for-index="groupIndex">
+        <!-- 问题组标题 -->
+        <view class="group-title">{{item.name}}</view>
+
+        <!-- 问题列表 -->
+        <view class="question-list">
+          <view class="question-item" wx:for="{{item.items}}" wx:key="index" wx:for-index="itemIndex">
+            <!-- 问题名称 -->
+            <view class="question-name">{{itemIndex + 1}}、{{item.name}}</view>
+
+            <!-- 分数选择(单选) -->
+            <t-radio-group value="{{item.selectedScore || item.score}}" borderless t-class="box" bind:change="onScoreChange" data-group-index="{{groupIndex}}" data-item-index="{{itemIndex}}">
+              <t-radio block="{{false}}" :label="{{item.label}}" :value="{{item.value}}" wx:for="{{scoreList}}" wx:key="value" style="margin-right:20rpx" />
+            </t-radio-group>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 其他意见 -->
+    <view class="other-comment-section">
+      <view class="other-comment-title">其他意见:</view>
+      <textarea class="other-comment-input" placeholder="请给我们留言您的其他意见" value="{{suggestion}}" bindinput="onCommentInput" maxlength="500" show-confirm-bar="{{false}}" />
+    </view>
+
+    <!-- 结束语 -->
+    <view class="questionnaire-end">
+      {{followDetail.endSentence}}
+    </view>
+  </view>
+
+  <!-- 无数据提示 -->
+  <view class="empty-container" wx:elif="{{showEmpty}}">
+    <view class="empty-text">暂无问卷数据</view>
+  </view>
+</scroll-view>
+
+<!-- 保存按钮 -->
+<view class="save-button-container" wx:if="{{!showEmpty}}">
+  <button class="save-button" bindtap="onSave" disabled="{{saving}}">
+    <text wx:if="{{saving}}">保存中...</text>
+    <text wx:else>保存</text>
+  </button>
+</view>

+ 20 - 0
miniprogram/module/afterSale/request.ts

@@ -0,0 +1,20 @@
+import { Get, Post } from "../../lib/request/method";
+
+// 获取问卷详情
+export function getQuestionnaireMethod(id: number) {
+  return Post(`/satisfiesyManage/getContent/${id}`, {
+    transform({ data }: AnyObject) {
+      return data;
+    },
+  });
+}
+// 满意度调研问卷提交
+export function submitQuestionnaireMethod(id: number, data: AnyObject) {
+  console.log(data, "data===");
+  return Post(`/satisfiesyManage/submitContent/${id}`, {
+    ...data,
+    transform({ data }: AnyObject) {
+      return data;
+    },
+  });
+}

+ 6 - 0
miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-popup": "tdesign-miniprogram/popup/popup"
+  }
+}

+ 186 - 0
miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.scss

@@ -0,0 +1,186 @@
+.after-sale-popup {
+  height: 56vh;
+  min-height: 520rpx;
+  background: #fff;
+  border-top-left-radius: 32rpx;
+  border-top-right-radius: 32rpx;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+}
+
+.after-sale-popup__header {
+  height: 116rpx;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-weight: 600;
+  font-size: 34rpx;
+  color: #1f1f1f;
+  background: #f2f2f2;
+}
+
+.after-sale-popup__close {
+  position: absolute;
+  right: 24rpx;
+  height: 116rpx;
+  width: 72rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 48rpx;
+  color: #444;
+}
+
+.after-sale-popup__header-spacer {
+  width: 72rpx;
+  height: 1px;
+}
+
+.after-sale-popup__content {
+  flex: 1;
+  overflow: auto;
+  padding: 0 24rpx;
+  box-sizing: border-box;
+  background: #fff;
+}
+
+.after-sale-popup__label {
+  margin-top: 30rpx;
+  margin-bottom: 20rpx;
+  font-size: 28rpx;
+  color: #222;
+}
+
+.after-sale-type-btn {
+  border-radius: 10rpx;
+  border: 2rpx solid #d7d7d7;
+  height: 72rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 26rpx;
+  color: #3a3a3a;
+  background: #fff;
+  width: 240rpx;
+  box-sizing: border-box;
+}
+
+.after-sale-type-btn--active {
+  border-color: #2b6df5;
+  color: #1D6FF6;
+  background: #f7faff;
+}
+
+.after-sale-type-card {
+  margin-top: 24rpx;
+  border-radius: 12rpx;
+  padding: 18rpx 20rpx;
+  display: flex;
+  align-items: center;
+  gap: 28rpx;
+  background: #f3f3f3;
+  border: 1rpx solid #ececec;
+  box-sizing: border-box;
+}
+
+.after-sale-type-card--active {
+  border-color: #2b6df5;
+  background: #fff;
+}
+
+.after-sale-type-card__left {
+  flex-shrink: 0;
+  margin-right: 20rpx;
+}
+
+.after-sale-type-card__icon {
+  width: 132rpx;
+  height: 108rpx;
+  background: #e6e6e6;
+  border-radius: 8rpx;
+  position: relative;
+}
+
+.after-sale-type-card__icon::after {
+  content: "";
+  width: 28rpx;
+  height: 20rpx;
+  border: 2rpx solid #b8b8b8;
+  border-radius: 4rpx;
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+}
+
+.after-sale-type-card__main {
+  flex: 1;
+  min-width: 0;
+  height: 90rpx;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+}
+
+.after-sale-type-card__name {
+  font-size: 28rpx;
+  font-weight: 600;
+  color: #2a2a2a;
+}
+
+.after-sale-type-card__meta {
+  font-size: 24rpx;
+  color: #989898;
+}
+
+.after-sale-type-card__right {
+  flex-shrink: 0;
+  height: 90rpx;
+  min-width: 110rpx;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  align-items: flex-end;
+}
+
+.after-sale-type-card__price {
+  font-size: 28rpx;
+  font-weight: 600;
+  color: #2a2a2a;
+}
+
+.after-sale-type-card__count {
+  font-size: 24rpx;
+  color: #989898;
+}
+
+.after-sale-popup__footer {
+  padding: 6rpx 16rpx calc(-40rpx + env(safe-area-inset-bottom));
+  background: #fff;
+  border-top: none;
+  box-shadow: none;
+}
+
+.after-sale-popup__next-btn {
+  width: 100%;
+  height: 88rpx;
+  line-height: 88rpx;
+  border-radius: 44rpx;
+  background: linear-gradient(135deg, #2f6df6 0%, #1f5de8 100%);
+  color: #fff;
+  text-align: center;
+  font-size: 30rpx;
+  font-weight: 500;
+  transition: transform 0.16s ease, opacity 0.16s ease;
+}
+
+.after-sale-popup__next-btn:active {
+  opacity: 0.92;
+  transform: scale(0.985);
+}
+
+.title {
+  line-height: 1;
+}

+ 47 - 0
miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.ts

@@ -0,0 +1,47 @@
+Component({
+  properties: {
+    visible: { type: Boolean, value: false },
+    siteOption: {
+      type: Object,
+      value: {
+        name: "肝血虚穴位站点",
+        price: 80,
+        meta1: "10贴",
+        meta2: "3",
+      },
+    },
+  },
+  data: {
+    selectedKey: "refund",
+  },
+  observers: {
+    visible(v: boolean) {
+      if (v) {
+        this.setData({ selectedKey: "refund" });
+      }
+    },
+  },
+  methods: {
+    onPopupVisibleChange(e: WechatMiniprogram.CustomEvent<{ visible: boolean }>) {
+      if (!e?.detail?.visible) {
+        this.triggerEvent("close");
+      }
+    },
+    onClose() {
+      this.triggerEvent("close");
+    },
+    onSelectType(e: WechatMiniprogram.TouchEvent) {
+      const type = (e?.currentTarget?.dataset as { type?: string })?.type;
+      if (!type) return;
+      this.setData({ selectedKey: type });
+    },
+    onNext() {
+      const key = this.data.selectedKey;
+      if (!key) {
+        wx.showToast({ title: "请选择售后类型", icon: "none" });
+        return;
+      }
+      this.triggerEvent("next", { selectedKey: key });
+    },
+  },
+});

+ 49 - 0
miniprogram/module/order/components/after-sale-type-popup/after-sale-type-popup.wxml

@@ -0,0 +1,49 @@
+<t-popup
+  placement="bottom"
+  visible="{{visible}}"
+  show-overlay="{{true}}"
+  close-on-overlay-click="{{true}}"
+  bind:visible-change="onPopupVisibleChange"
+>
+  <view class="after-sale-popup">
+    <view class="after-sale-popup__header">
+      <view class="title">选择售后类型</view>
+      <text class="after-sale-popup__close" catchtap="onClose">×</text>
+      <view class="after-sale-popup__header-spacer" />
+    </view>
+
+    <view class="after-sale-popup__content">
+      <view class="after-sale-popup__label">请选择售后类型:</view>
+
+      <view
+        class="after-sale-type-btn after-sale-type-btn--active"
+        data-type="refund"
+      >
+        仅退款
+      </view>
+
+      <view
+        class="after-sale-type-card"
+        data-type="site"
+      >
+        <view class="after-sale-type-card__left">
+          <view class="after-sale-type-card__icon" />
+        </view>
+
+        <view class="after-sale-type-card__main">
+          <view class="after-sale-type-card__name">{{siteOption.name}}</view>
+          <view class="after-sale-type-card__meta">{{siteOption.meta1}}</view>
+        </view>
+
+        <view class="after-sale-type-card__right">
+          <view class="after-sale-type-card__price">¥{{siteOption.price}}</view>
+          <view class="after-sale-type-card__count">{{siteOption.meta2}}</view>
+        </view>
+      </view>
+    </view>
+
+    <view class="after-sale-popup__footer">
+      <view class="after-sale-popup__next-btn" bindtap="onNext">下一步</view>
+    </view>
+  </view>
+</t-popup>

+ 10 - 0
miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.json

@@ -0,0 +1,10 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "t-picker": "tdesign-miniprogram/picker/picker",
+    "t-picker-item": "tdesign-miniprogram/picker-item/picker-item",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-button": "tdesign-miniprogram/button/button"
+  }
+}

+ 269 - 0
miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.scss

@@ -0,0 +1,269 @@
+.refund-confirm-popup {
+  height: 60vh;
+  min-height: 760rpx;
+  background: #fff;
+  border-top-left-radius: 24rpx;
+  border-top-right-radius: 24rpx;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+}
+
+.refund-confirm-popup__header {
+  height: 100rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+  font-size: 34rpx;
+  font-weight: 600;
+  background: #f2f2f2;
+}
+
+.refund-confirm-popup__close {
+  position: absolute;
+  right: 24rpx;
+  width: 72rpx;
+  height: 96rpx;
+  line-height: 96rpx;
+  text-align: center;
+  font-size: 42rpx;
+  color: #555;
+}
+
+.refund-confirm-popup__header-spacer {
+  width: 72rpx;
+}
+
+.refund-confirm-popup__content {
+  flex: 1;
+  padding: 14rpx 18rpx;
+  overflow: auto;
+  background: #fff;
+}
+
+.goods-card {
+  display: flex;
+  align-items: center;
+  gap: 18rpx;
+  background: #fff;
+  padding: 16rpx;
+  border-radius: 12rpx;
+  border: 1rpx solid #f3f3f3;
+  margin-bottom: 10px;
+}
+
+.goods-card__icon {
+  width: 112rpx;
+  height: 112rpx;
+  border-radius: 10rpx;
+  background: #efefef;
+}
+
+.goods-card__main {
+  flex: 1;
+  margin-left: 15px;
+}
+
+.goods-card__name {
+  font-size: 32rpx;
+  font-weight: 500;
+  margin-bottom: 10px;
+}
+
+.goods-card__meta {
+  font-size: 26rpx;
+  color: #a0a0a0;
+  margin-top: 8rpx;
+}
+
+.goods-card__right {
+  text-align: center;
+}
+
+.goods-card__price {
+  font-size: 34rpx;
+  font-weight: 600;
+  margin-bottom: 10px;
+}
+
+.goods-card__count {
+  font-size: 26rpx;
+  color: #8f8f8f;
+  margin-top: 6rpx;
+}
+
+.form-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  min-height: 74rpx;
+  padding: 0 10rpx;
+  position: relative;
+  z-index: 10;
+}
+
+.label {
+  font-size: 32rpx;
+  color: #222;
+}
+
+.value {
+  font-size: 30rpx;
+  color: #222;
+}
+
+.value.select {
+  color: #333;
+  border: 1rpx solid #c8c8c8;
+  border-radius: 10rpx;
+  font-size: 26rpx;
+  padding: 10rpx 20rpx;
+  display: flex;
+}
+
+.refund-status-value {
+  padding: 6rpx 10rpx;
+}
+
+.refund-status-radio-group {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-end;
+  gap: 18rpx;
+}
+
+.value.link {
+  color: #222;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  gap: 10rpx;
+}
+
+.arrow-icon {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #b0b0b0;
+}
+
+.edit-icon {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.value.red {
+  color: #e81818;
+}
+
+.value.amount {
+  font-weight: 600;
+}
+
+.amount-title {
+  font-weight: 600;
+}
+
+.divider {
+  height: 1rpx;
+  background: #f0f0f0;
+  margin: 20rpx 0rpx 20rpx 0rpx;
+}
+
+.refund-confirm-popup__footer {
+  background: #fff;
+  padding: 12rpx 18rpx calc(-60rpx + env(safe-area-inset-bottom));
+}
+
+.refund-amount-line {
+  color: #e81818;
+  font-size: 35rpx;
+  margin-bottom: 10rpx;
+  display: flex;
+  align-items: center;
+}
+
+.submit-btn {
+  width: 100%;
+  height: 88rpx;
+  line-height: 88rpx;
+  text-align: center;
+  border-radius: 12rpx;
+  background: #2f6df6;
+  color: #fff;
+  font-size: 30rpx;
+  font-weight: 500;
+}
+
+.wechat-price {
+  font-weight: 600;
+  color: #e81818;
+}
+
+.amount-popup {
+  width: 640rpx;
+  background: #fff;
+  border-radius: 16rpx;
+  overflow: hidden;
+  box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.18);
+}
+
+.amount-popup__header {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 30rpx 24rpx 18rpx;
+  font-size: 34rpx;
+  font-weight: 600;
+  color: #111;
+}
+
+
+.amount-popup__body {
+  padding: 8rpx 36rpx 34rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.hint {
+  width: 520rpx;
+  font-size: 26rpx;
+  color: #8a8a8a;
+  text-align: left;
+}
+
+.amount-input {
+  margin-top: 22rpx;
+  border: 2rpx solid #d8d8d8;
+  width: 520rpx;
+  height: 78rpx;
+  line-height: 78rpx;
+  padding: 0 18rpx;
+  font-size: 34rpx;
+  color: #111;
+  box-sizing: border-box;
+}
+
+.actions {
+  margin-top: 26rpx;
+  display: flex;
+  justify-content: center;
+  gap: 28rpx;
+  width: 520rpx;
+}
+
+.action-item {
+  flex: 1;
+}
+
+.action-btn {
+  border-radius: 8rpx !important;
+}
+.confirm-btn {
+ margin-left: 20rpx !important;
+}

+ 97 - 0
miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.ts

@@ -0,0 +1,97 @@
+Component({
+  properties: {
+    visible: { type: Boolean, value: false },
+    goodsName: { type: String, value: "" },
+    goodsPrice: { type: String, value: "" },
+    goodsMeta1: { type: String, value: "" },
+    goodsMeta2: { type: String, value: "" },
+    refundReason: { type: String, value: "" },
+    refundStatus: { type: String, value: "received" },
+    refundAmount: { type: Number, value: 0 },
+    maxAmount: { type: Number, value: 0 },
+    proofImages: { type: Array, value: [] },
+  },
+  data: {
+    statusPickerVisible: false,
+    statusPickerOptions: [
+      { label: "已收到货", value: "received" },
+      { label: "未收到货", value: "not-received" },
+    ],
+    statusPickerValue: ["received"],
+    // 退款金额编辑器(整屏弹窗)
+    amountEditorVisible: false,
+    amountInput: "",
+  },
+  observers: {
+    refundStatus(v: string) {
+      (this as any).setData({
+        statusPickerValue: [v === "not-received" ? "not-received" : "received"],
+      });
+    },
+  },
+  methods: {
+    onPopupVisibleChange(e: WechatMiniprogram.CustomEvent<{ visible: boolean }>) {
+      if (!e?.detail?.visible) {
+        (this as any).triggerEvent("close");
+      }
+    },
+    onAmountPopupVisibleChange(e: WechatMiniprogram.CustomEvent<{ visible: boolean }>) {
+      if (!e?.detail?.visible) {
+        (this as any).setData({ amountEditorVisible: false });
+      }
+    },
+    onClose() {
+      (this as any).triggerEvent("close");
+    },
+    onOpenStatusPicker() {
+      (this as any).setData({ statusPickerVisible: true });
+    },
+    onStatusPickerChange(e: any) {
+      const valueArr = e?.detail?.value as Array<string | number> | undefined;
+      const value0 = valueArr?.[0];
+      const status = value0 === "not-received" ? "not-received" : "received";
+      (this as any).triggerEvent("changeStatus", { status });
+      (this as any).setData({ statusPickerVisible: false });
+    },
+    onStatusPickerClose() {
+      (this as any).setData({ statusPickerVisible: false });
+    },
+    onEditReason() {
+      (this as any).triggerEvent("editReason");
+    },
+    onEditAmount() {
+      const cur = Number((this as any).data?.refundAmount ?? 0);
+      (this as any).setData({ amountInput: cur ? String(cur) : "0", amountEditorVisible: true });
+    },
+    onEditProof() {
+      (this as any).triggerEvent("editProof");
+    },
+    onAmountInput(e: WechatMiniprogram.Input) {
+      const raw = e.detail?.value || "";
+      // 保留数字与小数点
+      const cleaned = raw.replace(/[^\d.]/g, "");
+      (this as any).setData({ amountInput: cleaned });
+    },
+    onAmountClose() {
+      (this as any).setData({ amountEditorVisible: false });
+    },
+    onAmountConfirm() {
+      const maxAmount = Number((this as any).data?.maxAmount ?? 0);
+      const amount = Number((this as any).data?.amountInput ?? 0);
+      if (!amount || Number.isNaN(amount)) {
+        wx.showToast({ title: "请输入退款金额", icon: "none" });
+        return;
+      }
+      if (maxAmount && amount > maxAmount) {
+        wx.showToast({ title: "不能超过最高可退金额", icon: "none" });
+        return;
+      }
+      const fixed = Number(amount.toFixed(2));
+      (this as any).triggerEvent("amountConfirm", { amount: fixed });
+      (this as any).setData({ amountEditorVisible: false });
+    },
+    onSubmit() {
+      (this as any).triggerEvent("submit");
+    },
+  },
+});

+ 116 - 0
miniprogram/module/order/components/refund-confirm-popup/refund-confirm-popup.wxml

@@ -0,0 +1,116 @@
+<t-popup
+  placement="bottom"
+  visible="{{visible}}"
+  show-overlay="{{true}}"
+  close-on-overlay-click="{{true}}"
+  bind:visible-change="onPopupVisibleChange"
+>
+  <view class="refund-confirm-popup">
+    <view class="refund-confirm-popup__header">
+      <view class="title">确认退款信息</view>
+      <text class="refund-confirm-popup__close" catchtap="onClose">×</text>
+      <view class="refund-confirm-popup__header-spacer" />
+    </view>
+
+    <view class="refund-confirm-popup__content">
+      <view class="goods-card">
+        <view class="goods-card__icon" />
+        <view class="goods-card__main">
+          <view class="goods-card__name">{{goodsName}}</view>
+          <view class="goods-card__meta">{{goodsMeta1}}</view>
+        </view>
+        <view class="goods-card__right">
+          <view class="goods-card__price">¥{{goodsPrice || '0.00'}}</view>
+          <view class="goods-card__count">{{goodsMeta2}}</view>
+        </view>
+      </view>
+
+      <view class="form-row">
+        <text class="label">商品状态</text>
+        <view class="value select" bindtap="onOpenStatusPicker">
+          {{refundStatus === 'received' ? '已收到货' : '未收到货'}}
+          <t-icon name="chevron-right" class="arrow-icon" size="30rpx" color="#b0b0b0" />
+        </view>
+      </view>
+
+      <view class="form-row" catchtap="onEditReason">
+        <text class="label">退款原因</text>
+        <view class="value link">
+          {{refundReason || '请选择'}}
+          <t-icon name="chevron-right" class="arrow-icon" size="30rpx" color="#b0b0b0" />
+        </view>
+      </view>
+
+      <view class="divider"></view>
+
+      <view class="form-row" catchtap="onEditAmount">
+        <text class="label amount-title">退款金额</text>
+        <view class="value link">
+          <t-icon name="edit" class="edit-icon" size="28rpx" color="#b0b0b0" />
+          修改
+        </view>
+      </view>
+      <view class="form-row">
+        <text class="label">退回微信</text>
+        <view class="value amount">¥{{refundAmount}}</view>
+      </view>
+
+      <view class="form-row" catchtap="onEditProof">
+        <text class="label">上传描述和凭证<text style="color:red">*</text></text>
+        <view class="value link red">
+          {{proofImages.length ? '已上传' + proofImages.length + '张' : '上传有助处理退款'}}
+          <t-icon name="chevron-right" class="arrow-icon" size="30rpx" color="#b0b0b0" />
+        </view>
+      </view>
+    </view>
+
+    <view class="refund-confirm-popup__footer">
+      <view class="refund-amount-line"><text>退回微信¥</text><text class="wechat-price">{{refundAmount}}</text></view>
+      <view class="submit-btn" bindtap="onSubmit">提交申请</view>
+    </view>
+  </view>
+</t-popup>
+
+<t-picker
+  visible="{{statusPickerVisible}}"
+  value="{{statusPickerValue}}"
+  title=""
+  use-popup="{{true}}"
+  header="{{true}}"
+  cancel-btn="取消"
+  confirm-btn="确定"
+  bind:change="onStatusPickerChange"
+  bind:close="onStatusPickerClose"
+  z-index="12000"
+  style="--td-picker-z-index: 12000; --td-popup-z-index: 12000;"
+>
+  <t-picker-item options="{{statusPickerOptions}}" />
+</t-picker>
+
+<t-popup
+  placement="center"
+  visible="{{amountEditorVisible}}"
+  show-overlay="{{true}}"
+  close-on-overlay-click="{{true}}"
+  bind:visible-change="onAmountPopupVisibleChange"
+  z-index="12000"
+  style="--td-popup-z-index: 12000;"
+>
+  <view class="amount-popup">
+    <view class="amount-popup__header">
+      <view class="title">请输入退款总金额</view>
+    </view>
+    <view class="amount-popup__body">
+      <view class="hint">最高可退¥{{maxAmount}}元</view>
+      <input class="amount-input" type="digit" value="{{amountInput}}" bindinput="onAmountInput" />
+      <view class="actions">
+        <view class="action-item">
+          <t-button class="action-btn" block size="medium" variant="outline" theme="primary" catchtap="onAmountClose">取消</t-button>
+        </view>
+        <view class="action-item">
+          <t-button class="action-btn confirm-btn" block size="medium" theme="primary" catchtap="onAmountConfirm">确定</t-button>
+        </view>
+      </view>
+    </view>
+  </view>
+</t-popup>

+ 7 - 0
miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.json

@@ -0,0 +1,7 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "t-icon": "tdesign-miniprogram/icon/icon"
+  }
+}

+ 171 - 0
miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.scss

@@ -0,0 +1,171 @@
+.proof-popup {
+  height: 72vh;
+  min-height: 760rpx;
+  background: #fff;
+  border-top-left-radius: 24rpx;
+  border-top-right-radius: 24rpx;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+}
+
+.proof-popup__header {
+  height: 100rpx;
+  background: #f2f2f2;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 34rpx;
+  font-weight: 600;
+}
+
+.proof-popup__close {
+  position: absolute;
+  right: 24rpx;
+  width: 72rpx;
+  height: 108rpx;
+  line-height: 108rpx;
+  text-align: center;
+  font-size: 46rpx;
+}
+
+.proof-popup__header-spacer {
+  width: 72rpx;
+}
+
+.proof-popup__content {
+  flex: 1;
+  padding: 20rpx;
+  background: #f5f5f5;
+}
+
+.desc-input {
+  width: 100%;
+  min-height: 200rpx;
+  background: #fff;
+  border: 1rpx solid #ececec;
+  padding: 16rpx;
+  box-sizing: border-box;
+  font-size: 32rpx;
+  border-radius: 10rpx;
+}
+
+.desc-count {
+  text-align: right;
+  color: #888;
+  font-size: 28rpx;
+  margin: 8rpx 4rpx 12rpx;
+}
+
+.image-list {
+  margin-top: 16rpx;
+  display: flex;
+  flex-wrap: wrap;
+  // gap: 16rpx;
+}
+
+.img-item {
+  width: 160rpx;
+  height: 160rpx;
+  position: relative;
+  border-radius: 12rpx;
+  overflow: hidden;
+  margin-right: 16rpx;
+  margin-bottom: 20rpx;
+}
+
+.img {
+  width: 100%;
+  height: 100%;
+  border-radius: 12rpx;
+}
+
+.remove {
+  position: absolute;
+  top: 0;
+  right: 0;
+  width: 40rpx;
+  height: 40rpx;
+  border-bottom-left-radius: 16rpx;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #fff;
+  font-size: 24rpx;
+  z-index: 2;
+}
+
+.image-uploader {
+  width: 160rpx;
+  height: 160rpx;
+  background: #f0f2f5;
+  border-radius: 12rpx;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  box-sizing: border-box;
+}
+
+.upload-icon {
+  margin-bottom: 8rpx;
+}
+
+.upload-text {
+  font-size: 24rpx;
+  color: #666;
+}
+
+.upload-empty-container {
+  margin-top: 16rpx;
+}
+
+.image-uploader-empty {
+  border: 1rpx dashed #ccc;
+  background: #fff;
+  min-height: 200rpx;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  border-radius: 8rpx;
+}
+
+.upload-icon-empty {
+  margin-bottom: 12rpx;
+}
+
+.upload-title {
+  font-size: 30rpx;
+  color: #333;
+}
+
+.upload-sub {
+  font-size: 26rpx;
+  color: #999;
+  margin-top: 6rpx;
+}
+
+.upload-tips {
+  font-size: 26rpx;
+  color: #666;
+  margin-top: 16rpx;
+}
+
+.proof-popup__footer {
+  padding: 6rpx 16rpx calc(-40rpx + env(safe-area-inset-bottom));
+  background: #fff;
+}
+
+.done-btn {
+  width: 100%;
+  height: 88rpx;
+  line-height: 88rpx;
+  border-radius: 12rpx;
+  text-align: center;
+  color: #fff;
+  background: #2f6df6;
+  font-size: 34rpx;
+}

+ 63 - 0
miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.ts

@@ -0,0 +1,63 @@
+Component({
+  properties: {
+    visible: { type: Boolean, value: false },
+    desc: { type: String, value: "" },
+    images: { type: Array, value: [] },
+  },
+  data: {
+    inputDesc: "",
+    inputImages: [] as string[],
+  },
+  observers: {
+    visible(v: boolean) {
+      if (v) {
+        this.setData({
+          inputDesc: this.data.desc || "",
+          inputImages: [...(this.data.images as string[])],
+        });
+      }
+    },
+  },
+  methods: {
+    onPopupVisibleChange(e: WechatMiniprogram.CustomEvent<{ visible: boolean }>) {
+      if (!e?.detail?.visible) this.triggerEvent("close");
+    },
+    onClose() {
+      this.triggerEvent("close");
+    },
+    onDescInput(e: WechatMiniprogram.Input) {
+      const value = (e.detail?.value || "").slice(0, 200);
+      this.setData({ inputDesc: value });
+    },
+    onChooseImage() {
+      const current = this.data.inputImages.length;
+      const remain = 9 - current;
+      if (remain <= 0) {
+        wx.showToast({ title: "最多上传9张", icon: "none" });
+        return;
+      }
+      wx.chooseImage({
+        count: remain,
+        sizeType: ["compressed"],
+        sourceType: ["album", "camera"],
+        success: (res) => {
+          const next = [...this.data.inputImages, ...res.tempFilePaths].slice(0, 9);
+          this.setData({ inputImages: next });
+        },
+      });
+    },
+    onRemoveImage(e: WechatMiniprogram.TouchEvent) {
+      const index = Number((e.currentTarget.dataset as { index?: number })?.index ?? -1);
+      if (index < 0) return;
+      const next = [...this.data.inputImages];
+      next.splice(index, 1);
+      this.setData({ inputImages: next });
+    },
+    onConfirm() {
+      this.triggerEvent("confirm", {
+        desc: this.data.inputDesc,
+        images: this.data.inputImages,
+      });
+    },
+  },
+});

+ 49 - 0
miniprogram/module/order/components/refund-proof-popup/refund-proof-popup.wxml

@@ -0,0 +1,49 @@
+<t-popup
+  placement="bottom"
+  visible="{{visible}}"
+  show-overlay="{{true}}"
+  close-on-overlay-click="{{true}}"
+  bind:visible-change="onPopupVisibleChange"
+  z-index="12000"
+  style="--td-popup-z-index: 12000;"
+>
+  <view class="proof-popup">
+    <view class="proof-popup__header">
+      <view class="title">上传描述和凭证</view>
+      <text class="proof-popup__close" catchtap="onClose">×</text>
+      <view class="proof-popup__header-spacer" />
+    </view>
+
+    <view class="proof-popup__content">
+      <textarea class="desc-input" placeholder="补充描述,有助于商家更好的处理售后问题" maxlength="200" value="{{inputDesc}}" bindinput="onDescInput" />
+      <view class="desc-count">{{inputDesc.length}}/200</view>
+
+      <view class="upload-empty-container" wx:if="{{inputImages.length === 0}}">
+        <view class="image-uploader-empty" catchtap="onChooseImage">
+          <t-icon name="camera" size="56rpx" color="#111" class="upload-icon-empty" />
+          <view class="upload-title">上传凭证</view>
+          <view class="upload-sub">(最多9张)</view>
+        </view>
+        <view class="upload-tips">请提供以下凭证:包裹内件实物图片</view>
+      </view>
+
+      <view class="image-list" wx:else>
+        <view class="img-item" wx:for="{{inputImages}}" wx:key="index">
+          <image class="img" src="{{item}}" mode="aspectFill" />
+          <view class="remove" data-index="{{index}}" catchtap="onRemoveImage">
+            <t-icon name="close" size="24rpx" color="#fff" />
+          </view>
+        </view>
+        
+        <view class="image-uploader" catchtap="onChooseImage" wx:if="{{inputImages.length < 9}}">
+          <t-icon name="camera" size="56rpx" color="#999" class="upload-icon" />
+          <view class="upload-text">还可传{{9 - inputImages.length}}个</view>
+        </view>
+      </view>
+    </view>
+
+    <view class="proof-popup__footer">
+      <view class="done-btn" bindtap="onConfirm">完成</view>
+    </view>
+  </view>
+</t-popup>

+ 8 - 0
miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.json

@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-popup": "tdesign-miniprogram/popup/popup",
+    "t-radio": "tdesign-miniprogram/radio/radio",
+    "t-radio-group": "tdesign-miniprogram/radio-group/radio-group"
+  }
+}

+ 70 - 0
miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.scss

@@ -0,0 +1,70 @@
+.refund-reason-popup {
+  height: 70vh;
+  min-height: 560rpx;
+  background: #fff;
+  border-top-left-radius: 32rpx;
+  border-top-right-radius: 32rpx;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+}
+
+.refund-reason-popup__header {
+  height: 100rpx;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-weight: 600;
+  font-size: 34rpx;
+  color: #1f1f1f;
+  background: #f2f2f2;
+}
+
+.refund-reason-popup__close {
+  position: absolute;
+  right: 24rpx;
+  width: 72rpx;
+  height: 116rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 48rpx;
+  color: #444;
+}
+
+.refund-reason-popup__header-spacer {
+  width: 72rpx;
+  height: 1px;
+}
+
+.refund-reason-popup__content {
+  flex: 1;
+  overflow: auto;
+  background: #fff;
+  padding: 10rpx 0;
+  box-sizing: border-box;
+}
+
+.custom-radio {
+  --td-radio-icon-checked-color: #2f6df6;
+  font-size: 32rpx !important;
+  padding: 24rpx 32rpx;
+}
+
+.refund-reason-popup__footer {
+  padding: 6rpx 16rpx calc(-60rpx + env(safe-area-inset-bottom));
+  background: #fff;
+}
+
+.refund-reason-popup__next-btn {
+  width: 100%;
+  height: 88rpx;
+  line-height: 88rpx;
+  border-radius: 44rpx;
+  background: linear-gradient(135deg, #2f6df6 0%, #1f5de8 100%);
+  color: #fff;
+  text-align: center;
+  font-size: 30rpx;
+  font-weight: 500;
+}

+ 50 - 0
miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.ts

@@ -0,0 +1,50 @@
+Component({
+  properties: {
+    visible: { type: Boolean, value: false },
+    initialReason: { type: String, value: "" },
+  },
+  data: {
+    selectedReason: "",
+    reasons: [
+      "商品信息描述不符",
+      "与商家协商一致退款",
+      "质量问题",
+      "少件(含缺少配件)",
+      "包装/商品破损/污渍",
+      "未按约定时间发货",
+      "发票问题",
+      "卖家发错货",
+    ],
+  },
+  observers: {
+    visible(v: boolean) {
+      if (v) {
+        this.setData({ selectedReason: this.data.initialReason || "" });
+      }
+    },
+  },
+  methods: {
+    onPopupVisibleChange(e: WechatMiniprogram.CustomEvent<{ visible: boolean }>) {
+      if (!e?.detail?.visible) {
+        this.triggerEvent("close");
+      }
+    },
+    onClose() {
+      this.triggerEvent("close");
+    },
+    onSelectReason(e: any) {
+      const reason = e.detail?.value;
+      if (reason) {
+        this.setData({ selectedReason: reason });
+      }
+    },
+    onNext() {
+      const reason = this.data.selectedReason;
+      if (!reason) {
+        wx.showToast({ title: "请选择退款原因", icon: "none" });
+        return;
+      }
+      this.triggerEvent("next", { reason });
+    },
+  },
+});

+ 35 - 0
miniprogram/module/order/components/refund-reason-popup/refund-reason-popup.wxml

@@ -0,0 +1,35 @@
+<t-popup
+  placement="bottom"
+  visible="{{visible}}"
+  show-overlay="{{true}}"
+  close-on-overlay-click="{{true}}"
+  bind:visible-change="onPopupVisibleChange"
+  z-index="12000"
+  style="--td-popup-z-index: 12000;"
+>
+  <view class="refund-reason-popup">
+    <view class="refund-reason-popup__header">
+      <view class="title">选择退款原因</view>
+      <text class="refund-reason-popup__close" catchtap="onClose">×</text>
+      <view class="refund-reason-popup__header-spacer" />
+    </view>
+
+    <scroll-view class="refund-reason-popup__content" scroll-y>
+      <t-radio-group value="{{selectedReason}}" bind:change="onSelectReason">
+        <t-radio
+          wx:for="{{reasons}}"
+          wx:key="index"
+          value="{{item}}"
+          label="{{item}}"
+          placement="right"
+          icon="circle"
+          class="custom-radio"
+        />
+      </t-radio-group>
+    </scroll-view>
+
+    <view class="refund-reason-popup__footer">
+      <view class="refund-reason-popup__next-btn" bindtap="onNext">下一步</view>
+    </view>
+  </view>
+</t-popup>

+ 6 - 0
miniprogram/module/order/pages/negotiation-history/negotiation-history.json

@@ -0,0 +1,6 @@
+{
+  "navigationBarTitleText": "协商历史",
+  "usingComponents": {
+    "t-navbar": "tdesign-miniprogram/navbar/navbar"
+  }
+}

+ 137 - 0
miniprogram/module/order/pages/negotiation-history/negotiation-history.scss

@@ -0,0 +1,137 @@
+page {
+  background-color: #f7f8fa;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.page-container {
+  flex: 1;
+}
+
+.history-list {
+  padding-bottom: 40rpx;
+}
+
+.history-item {
+  background-color: #fff;
+  padding: 32rpx;
+  position: relative;
+  margin-bottom: 20rpx;
+  
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+
+/* Header */
+.item-header {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20rpx;
+}
+
+.user-avatar {
+  width: 72rpx;
+  height: 72rpx;
+  border-radius: 50%;
+  background-color: #e8e8e8;
+  margin-right: 20rpx;
+  flex-shrink: 0;
+}
+
+.user-info {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.user-name {
+  font-size: 30rpx;
+  color: #333;
+  font-weight: 500;
+  margin-bottom: 8rpx;
+}
+
+.action-time {
+  font-size: 24rpx;
+  color: #999;
+}
+
+/* Content */
+.item-content {
+  padding-left: 92rpx; /* Align with text, after avatar (72 + 20) */
+  margin-top: -10rpx;
+}
+
+/* Platform Styles */
+.platform-line {
+  font-size: 30rpx;
+  color: #333;
+  line-height: 1.6;
+  margin-bottom: 12rpx;
+  font-weight: 500;
+  
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+
+/* User Styles */
+.action-title {
+  font-size: 30rpx;
+  color: #333;
+  font-weight: 500;
+  margin-bottom: 16rpx;
+}
+
+.detail-line {
+  font-size: 28rpx;
+  line-height: 1.6;
+  margin-bottom: 6rpx;
+  display: flex;
+}
+
+.detail-label {
+  color: #333;
+  flex-shrink: 0;
+}
+
+.detail-value {
+  color: #333;
+  flex: 1;
+  word-break: break-all;
+}
+
+/* Image Grid */
+.image-grid {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16rpx;
+  margin-top: 24rpx;
+}
+
+.grid-img-wrap {
+  width: 120rpx;
+  height: 120rpx;
+  border-radius: 8rpx;
+  overflow: hidden;
+  background-color: #f5f5f5;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.grid-img {
+  width: 100%;
+  height: 100%;
+}
+
+.grid-placeholder {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background-color: #e8e8e8;
+}

+ 59 - 0
miniprogram/module/order/pages/negotiation-history/negotiation-history.ts

@@ -0,0 +1,59 @@
+Page({
+  data: {
+    historyList: [
+      {
+        type: 'platform',
+        avatar: 'https://tdesign.gtimg.com/mobile/demos/avatar1.png',
+        name: '平台',
+        time: '2025-02-19 14:30:35',
+        lines: [
+          '【标题】退款成功',
+          '【内容】退款金额 ¥240.00 已原路退回您的账户。'
+        ]
+      },
+      {
+        type: 'platform',
+        avatar: 'https://tdesign.gtimg.com/mobile/demos/avatar1.png',
+        name: '平台',
+        time: '2025-02-19 14:30:35',
+        lines: [
+          '【标题】平台已经同意了申请',
+          '【内容】请耐心等待财务确认打款,退款将原路退回您的账户中。'
+        ]
+      },
+      {
+        type: 'user',
+        avatar: 'https://tdesign.gtimg.com/mobile/demos/avatar2.png',
+        name: '谢芳',
+        time: '2025-02-19 14:30:27',
+        actionTitle: '发起了退款申请',
+        details: [
+          { label: '商品状态', value: '已收到货' },
+          { label: '退款金额', value: '¥240.00' },
+          { label: '退款原因', value: '与卖家协商一致' },
+          { label: '退款说明', value: 'uudksjj' }
+        ],
+        images: [
+          'placeholder',
+          'placeholder',
+          'placeholder',
+          'placeholder',
+          'placeholder'
+        ]
+      },
+      {
+        type: 'platform',
+        avatar: 'https://tdesign.gtimg.com/mobile/demos/avatar1.png',
+        name: '平台',
+        time: '2025-02-19 14:30:35',
+        lines: [
+          '【标题】平台拒绝了申请'
+        ]
+      }
+    ]
+  },
+
+  onLoad() {
+    // 实际项目中会在这里请求接口拿到由于协商历史列表
+  }
+});

+ 46 - 0
miniprogram/module/order/pages/negotiation-history/negotiation-history.wxml

@@ -0,0 +1,46 @@
+<t-navbar title="协商历史" left-arrow />
+
+<scroll-view class="page-container" scroll-y>
+  <view class="history-list">
+    <view class="history-item" wx:for="{{historyList}}" wx:key="index">
+      
+      <!-- 顶部信息 -->
+      <view class="item-header">
+        <image class="user-avatar" src="{{item.avatar}}" mode="aspectFill"></image>
+        <view class="user-info">
+          <view class="user-name">{{item.name}}</view>
+          <view class="action-time">{{item.time}}</view>
+        </view>
+      </view>
+
+      <!-- 内容区 -->
+      <view class="item-content">
+        <!-- 平台消息 -->
+        <block wx:if="{{item.type === 'platform'}}">
+          <view class="platform-line" wx:for="{{item.lines}}" wx:for-item="line" wx:key="*this">{{line}}</view>
+        </block>
+
+        <!-- 用户行为 -->
+        <block wx:elif="{{item.type === 'user'}}">
+          <view class="action-title">{{item.actionTitle}}</view>
+          
+          <view class="detail-line" wx:for="{{item.details}}" wx:for-item="detail" wx:key="label">
+            <text class="detail-label">{{detail.label}}:</text>
+            <text class="detail-value">{{detail.value}}</text>
+          </view>
+          
+          <!-- 图片矩阵 -->
+          <view class="image-grid" wx:if="{{item.images && item.images.length > 0}}">
+            <view class="grid-img-wrap" wx:for="{{item.images}}" wx:for-item="img" wx:key="index">
+              <image class="grid-img" src="{{img !== 'placeholder' ? img : ''}}" mode="aspectFill" wx:if="{{img !== 'placeholder'}}"></image>
+              <view class="grid-placeholder" wx:else>
+                <t-icon name="image" size="40rpx" color="#ccc" />
+              </view>
+            </view>
+          </view>
+        </block>
+      </view>
+
+    </view>
+  </view>
+</scroll-view>

+ 5 - 1
miniprogram/module/order/pages/other-detail/other-detail.json

@@ -3,6 +3,10 @@
   "component": true,
   "usingComponents": {
     "t-navbar": "tdesign-miniprogram/navbar/navbar",
-    "t-icon": "tdesign-miniprogram/icon/icon"
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "after-sale-type-popup": "../../components/after-sale-type-popup/after-sale-type-popup",
+    "refund-reason-popup": "../../components/refund-reason-popup/refund-reason-popup",
+    "refund-confirm-popup": "../../components/refund-confirm-popup/refund-confirm-popup",
+    "refund-proof-popup": "../../components/refund-proof-popup/refund-proof-popup"
   }
 }

+ 10 - 1
miniprogram/module/order/pages/other-detail/other-detail.scss

@@ -63,6 +63,7 @@
   margin-bottom: 0;
   text-align: center;
 }
+
 .offline-title {
   padding-left: 32rpx;
   font-size: 32rpx;
@@ -74,6 +75,7 @@
   z-index: 10;
   text-align: left;
 }
+
 .goods-item-wrapper {
   background: #fff;
 
@@ -275,6 +277,13 @@
   text-align: center;
   background-color: #e8e8e8;
   color: #666;
+
+  &.disabled-btn {
+    background-color: transparent;
+    color: #fa5151;
+    font-weight: 600;
+    padding: 12rpx 10rpx;
+  }
 }
 
 .btn-review {
@@ -701,4 +710,4 @@
 .remark-count-text {
   font-size: 24rpx;
   color: #999;
-}
+}

+ 119 - 4
miniprogram/module/order/pages/other-detail/other-detail.ts

@@ -37,6 +37,25 @@ Page({
     showDetail: false,
     isPaymentLoading: false,
     orderStatus: "", // 订单状态:pending, paid, closed, completed
+    // 售后半屏弹窗(组件 after-sale-type-popup)
+    afterSalePopupVisible: false,
+    refundReasonPopupVisible: false,
+    refundConfirmPopupVisible: false,
+    refundProofPopupVisible: false,
+    refundSubmitSuccessPopupVisible: false,
+    selectedAfterSaleType: "",
+    selectedRefundReason: "",
+    refundStatus: "received", // received | not-received
+    refundMaxAmount: 240,
+    refundAmount: 240,
+    refundDesc: "",
+    refundProofImages: [] as string[],
+    afterSaleSiteOption: {
+      name: "肝血虚穴位站点",
+      price: 80,
+      meta1: "10贴",
+      meta2: "x3",
+    },
   },
   onLoad(options: any) {
     const remark = (this.data.orderDetail as any)?.remark || '';
@@ -125,7 +144,7 @@ Page({
           if (!items || !Array.isArray(items)) {
             return [];
           }
-          return items.map((item: any) => {
+          return items.map((item: any, index: number) => {
             // 0是一口价 1按穴位/经络次数计费
             const pricingType = item?.conditioningProgramDetail?.pricingType;
             return {
@@ -156,6 +175,9 @@ Page({
               statusText: this.getGoodsStatusText(item?.sellType, item?.progress, item?.receiptStatus),
               isCanEvaluate: item?.isCanEvaluate, //是否可以评价 false-否 true-是
               evaluateTime: item?.evaluateTime, //有评价时间就是已评价,是空就是未评价
+              // [测试数据] 为了演示“申请售后”和“退款申请中”的不同状态
+              // 如果是第一个商品或者偶数商品,模拟状态为1(退款申请中),否则为0(可申请售后)
+              afterSaleStatus: index === 0 ? 1 : 0, 
             }
           });
         };
@@ -213,7 +235,7 @@ Page({
       const payResult = await orderPayMethod(this.data.id, (this.data.orderDetail as any)?.remark);
       if (payResult && payResult.data) {
         const paymentParams = payResult.data;
-        handleWeChatPayment(paymentParams, (res: any) => {
+        handleWeChatPayment(paymentParams, (_res: any) => {
           // 支付成功,跳转到成功页面
           wx.redirectTo({
             url: "/module/article/pages/success-page/success-page?title=订单支付成功",
@@ -264,8 +286,101 @@ Page({
   preventTap() {
     // 仅用于 catchtap 阻止冒泡,避免触发父级 goAppointment
   },
-  onApplyAfterSale(_e: any) {
-    wx.showToast({ title: "申请售后", icon: "none" });
+  onApplyAfterSale(e: any) {
+    const status = e.currentTarget.dataset.status;
+    if (status === 1) {
+      wx.navigateTo({
+        url: "/module/order/pages/refund-processing/refund-processing"
+      });
+      return;
+    }
+    this.setData({ afterSalePopupVisible: true });
+  },
+
+  onAfterSalePopupClose() {
+    this.setData({ afterSalePopupVisible: false });
+  },
+
+  onAfterSaleNext(e: WechatMiniprogram.CustomEvent<{ selectedKey: string }>) {
+    const key = e.detail?.selectedKey;
+    if (!key) {
+      wx.showToast({ title: "请选择售后类型", icon: "none" });
+      return;
+    }
+    this.setData({
+      selectedAfterSaleType: key,
+      afterSalePopupVisible: false,
+      refundReasonPopupVisible: true,
+    });
+  },
+
+  onRefundReasonPopupClose() {
+    this.setData({ refundReasonPopupVisible: false });
+  },
+
+  onRefundReasonNext(e: WechatMiniprogram.CustomEvent<{ reason: string }>) {
+    const reason = e.detail?.reason;
+    if (!reason) {
+      wx.showToast({ title: "请选择退款原因", icon: "none" });
+      return;
+    }
+    this.setData({
+      selectedRefundReason: reason,
+      refundReasonPopupVisible: false,
+      refundConfirmPopupVisible: true,
+      refundStatus: "received",
+      refundAmount: this.data.refundMaxAmount,
+    });
+  },
+
+  onRefundConfirmClose() {
+    this.setData({ refundConfirmPopupVisible: false });
+  },
+
+  onChangeRefundStatus(e: WechatMiniprogram.CustomEvent<{ status: "received" | "not-received" }>) {
+    this.setData({ refundStatus: e.detail?.status || "received" });
+  },
+
+  onOpenRefundReasonAgain() {
+    this.setData({ refundReasonPopupVisible: true });
+  },
+
+  onRefundAmountConfirm(e: WechatMiniprogram.CustomEvent<{ amount: number }>) {
+    const amount = Number(e.detail?.amount || 0);
+    this.setData({ refundAmount: amount });
+  },
+
+  onOpenRefundProofEditor() {
+    this.setData({ refundProofPopupVisible: true });
+  },
+
+  onRefundProofPopupClose() {
+    this.setData({ refundProofPopupVisible: false });
+  },
+
+  onRefundProofConfirm(e: WechatMiniprogram.CustomEvent<{ desc: string; images: string[] }>) {
+    this.setData({
+      refundDesc: e.detail?.desc || "",
+      refundProofImages: e.detail?.images || [],
+      refundProofPopupVisible: false,
+    });
+  },
+
+  onSubmitRefundApply() {
+    if (!this.data.selectedRefundReason) {
+      wx.showToast({ title: "请选择退款原因", icon: "none" });
+      return;
+    }
+    if (!this.data.refundProofImages.length) {
+      wx.showToast({ title: "请上传凭证图片", icon: "none" });
+      return;
+    }
+    this.setData({
+      refundConfirmPopupVisible: false,
+    });
+    wx.navigateTo({
+      url: "/module/order/pages/refund-success/refund-success",
+    });
   },
   onReview(e: WechatMiniprogram.TouchEvent) {
     // const orderId = this.data.id || "";

+ 59 - 12
miniprogram/module/order/pages/other-detail/other-detail.wxml

@@ -14,12 +14,12 @@
         <view class="express-info" wx:if="{{goods.receiptType === '0' && goods.expressTypeName && goods.expressNo && goods.receiptStatus === '1'}}">
           <view class="express-text">
             <view style="font-weight:600;margin-right: 10rpx;display: flex;align-items: center;">
-             <text style="font-size: 25rpx;"> 快件{{goodsIndex + 1}}</text>
+              <text style="font-size: 25rpx;"> 快件{{goodsIndex + 1}}</text>
               <i class="iconfont {{goods.expressTypeIcon}}" style="font-size:15px" wx:if="{{goods.expressTypeIcon}}"></i>
             </view>
             <view style="color:#9b9797;font-size: 25rpx;">{{goods.expressTypeName}} {{goods.expressNo}}</view>
           </view>
-           <t-icon name="chevron-right" color="#000" size="40rpx" slot="note" />
+          <t-icon name="chevron-right" color="#000" size="40rpx" slot="note" />
         </view>
         <view>
           <view class="goods-status {{goods.statusClass}}" wx:if="{{goods.statusText && orderStatus !== 'closed'}}" bindtap="goLogistics">{{goods.statusText}}</view>
@@ -43,7 +43,9 @@
               </view>
               <!-- 申请售后 + 评价 -->
               <view class="action-btns">
-                <!-- <view class="btn-aftersale" catchtap="onApplyAfterSale">申请售后</view> -->
+                <view class="btn-aftersale {{goods.afterSaleStatus === 1 ? 'disabled-btn' : ''}}" catchtap="onApplyAfterSale" data-status="{{goods.afterSaleStatus}}">
+                  {{goods.afterSaleStatus === 1 ? '退款申请中' : '申请售后'}}
+                </view>
                 <view class="btn-review" catchtap="onReview" data-goods="{{goods}}" wx:if="{{goods.isCanEvaluate}}">{{goods.evaluateTime?"已评价":"评价"}}</view>
               </view>
             </view>
@@ -74,8 +76,10 @@
               </view>
               <!-- 申请售后 + 评价 -->
               <view class="action-btns" catchtap="preventTap">
-                <!-- <view class="btn-aftersale" catchtap="onApplyAfterSale">申请售后</view> -->
-                  <view class="btn-review" catchtap="onReview" data-goods="{{goods}}" wx:if="{{goods.isCanEvaluate}}">{{goods.evaluateTime?"已评价":"评价"}}</view>
+                <view class="btn-aftersale {{goods.afterSaleStatus === 1 ? 'disabled-btn' : ''}}" catchtap="onApplyAfterSale" data-status="{{goods.afterSaleStatus}}">
+                  {{goods.afterSaleStatus === 1 ? '退款申请中' : '申请售后'}}
+                </view>
+                <view class="btn-review" catchtap="onReview" data-goods="{{goods}}" wx:if="{{goods.isCanEvaluate}}">{{goods.evaluateTime?"已评价":"评价"}}</view>
               </view>
             </view>
           </view>
@@ -105,8 +109,10 @@
               </view>
               <!-- 申请售后 + 评价 -->
               <view class="action-btns">
-                <!-- <view class="btn-aftersale" catchtap="onApplyAfterSale">申请售后</view> -->
-                  <view class="btn-review" catchtap="onReview" data-goods="{{goods}}" wx:if="{{goods.isCanEvaluate}}">{{goods.evaluateTime?"已评价":"评价"}}</view>
+                <view class="btn-aftersale {{goods.afterSaleStatus === 1 ? 'disabled-btn' : ''}}" catchtap="onApplyAfterSale" data-status="{{goods.afterSaleStatus}}">
+                  {{goods.afterSaleStatus === 1 ? '退款申请中' : '申请售后'}}
+                </view>
+                <view class="btn-review" catchtap="onReview" data-goods="{{goods}}" wx:if="{{goods.isCanEvaluate}}">{{goods.evaluateTime?"已评价":"评价"}}</view>
               </view>
             </view>
           </view>
@@ -158,22 +164,22 @@
         <text class="info-label">创建时间</text>
         <text class="info-value">{{orderDetail.operateTime || ''}}</text>
       </view>
-       <view class="info-divider"></view>
+      <view class="info-divider"></view>
       <view class="info-item" wx:if="{{orderStatus!=='closed'}}">
         <text class="info-label">付款时间</text>
         <text class="info-value">{{orderDetail.payTime || ''}}</text>
       </view>
-       <view class="info-divider" wx:if="{{orderStatus!=='closed'}}"></view>
+      <view class="info-divider" wx:if="{{orderStatus!=='closed'}}"></view>
       <view class="info-item" wx:if="{{orderStatus==='completed'}}">
         <text class="info-label">成交时间</text>
         <text class="info-value">{{orderDetail.finishTime || ''}}</text>
       </view>
-       <view class="info-divider" wx:if="{{orderStatus==='completed'}}"></view>
+      <view class="info-divider" wx:if="{{orderStatus==='completed'}}"></view>
       <view class="info-item" wx:if="{{orderStatus==='closed'}}">
         <text class="info-label">关闭时间</text>
         <text class="info-value">{{orderDetail.cancelTime || ''}}</text>
       </view>
-       <view class="info-divider" wx:if="{{orderStatus==='closed'}}"></view>
+      <view class="info-divider" wx:if="{{orderStatus==='closed'}}"></view>
       <view class="info-item" wx:if="{{orderStatus!=='closed'}}">
         <text class="info-label">微信交易号</text>
         <text class="info-value">{{orderDetail.payTransactionNo || ''}}</text>
@@ -205,4 +211,45 @@
   </view>
 
 
-</scroll-view>
+</scroll-view>
+
+<after-sale-type-popup
+  visible="{{afterSalePopupVisible}}"
+  site-option="{{afterSaleSiteOption}}"
+  bind:close="onAfterSalePopupClose"
+  bind:next="onAfterSaleNext"
+/>
+
+<refund-reason-popup
+  visible="{{refundReasonPopupVisible}}"
+  initial-reason="{{selectedRefundReason}}"
+  bind:close="onRefundReasonPopupClose"
+  bind:next="onRefundReasonNext"
+/>
+
+<refund-confirm-popup
+  visible="{{refundConfirmPopupVisible}}"
+  goods-name="{{afterSaleSiteOption.name}}"
+  goods-price="{{afterSaleSiteOption.price}}"
+  goods-meta1="{{afterSaleSiteOption.meta1}}"
+  goods-meta2="{{afterSaleSiteOption.meta2}}"
+  refund-reason="{{selectedRefundReason}}"
+  refund-status="{{refundStatus}}"
+  refund-amount="{{refundAmount}}"
+  max-amount="{{refundMaxAmount}}"
+  proof-images="{{refundProofImages}}"
+  bind:close="onRefundConfirmClose"
+  bind:changeStatus="onChangeRefundStatus"
+  bind:editReason="onOpenRefundReasonAgain"
+  bind:editProof="onOpenRefundProofEditor"
+  bind:amountConfirm="onRefundAmountConfirm"
+  bind:submit="onSubmitRefundApply"
+/>
+
+<refund-proof-popup
+  visible="{{refundProofPopupVisible}}"
+  desc="{{refundDesc}}"
+  images="{{refundProofImages}}"
+  bind:close="onRefundProofPopupClose"
+  bind:confirm="onRefundProofConfirm"
+/>

+ 12 - 0
miniprogram/module/order/pages/refund-processing/refund-processing.json

@@ -0,0 +1,12 @@
+{
+  "navigationBarTitleText": "商家处理",
+  "usingComponents": {
+    "t-navbar": "tdesign-miniprogram/navbar/navbar",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-button": "tdesign-miniprogram/button/button",
+    "after-sale-type-popup": "../../components/after-sale-type-popup/after-sale-type-popup",
+    "refund-reason-popup": "../../components/refund-reason-popup/refund-reason-popup",
+    "refund-confirm-popup": "../../components/refund-confirm-popup/refund-confirm-popup",
+    "refund-proof-popup": "../../components/refund-proof-popup/refund-proof-popup"
+  }
+}

+ 316 - 0
miniprogram/module/order/pages/refund-processing/refund-processing.scss

@@ -0,0 +1,316 @@
+page {
+  background-color: #f7f8fa;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.page-container {
+  flex: 1;
+  padding-bottom: 120rpx;
+  /* footer padding */
+}
+
+/* Header Section */
+.header-section {
+  background-color: #fff;
+  display: flex;
+  flex-direction: column;
+
+
+  &.header-processing,
+  &.header-revoked,
+  &.header-completed {
+    padding: 80rpx 40rpx 60rpx;
+    align-items: center;
+  }
+
+  &.header-approved,
+  &.header-rejected {
+    padding: 40rpx 40rpx 60rpx;
+    align-items: flex-start;
+  }
+}
+
+.status-title {
+  font-size: 52rpx;
+  font-weight: 600;
+  color: #333;
+  margin-bottom: 20rpx;
+
+  &.completed-title {
+    font-size: 64rpx;
+    margin-bottom: 60rpx;
+  }
+}
+
+/* Refund Success Card */
+.refund-card {
+  width: 100%;
+  padding: 30rpx 0;
+  border-top: 1rpx solid #eee;
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  margin-top: 20rpx;
+}
+
+.refund-dest-name {
+  font-size: 32rpx;
+  color: #333;
+  font-weight: 500;
+  margin-bottom: 8rpx;
+  text-align: left;
+}
+
+.refund-dest-account {
+  font-size: 26rpx;
+  color: #999;
+  text-align: left;
+}
+
+.refund-amount-text {
+  font-size: 36rpx;
+  color: #333;
+  font-weight: 600;
+}
+
+.status-sub {
+  font-size: 28rpx;
+  color: #666;
+  margin-bottom: 40rpx;
+}
+
+.countdown-container {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.time-block {
+  width: 90rpx;
+  height: 90rpx;
+  background-color: #1d6ff6;
+  color: #fff;
+  font-size: 40rpx;
+  font-weight: 600;
+  border-radius: 8rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.time-colon {
+  font-size: 40rpx;
+  color: #666;
+  margin: 0 16rpx;
+  font-weight: 600;
+}
+
+/* Approved/Rejected Common Styles */
+.approved-title {
+  font-size: 40rpx;
+  font-weight: 600;
+  color: #333;
+  line-height: 1.4;
+  margin-bottom: 16rpx;
+  text-align: left;
+}
+
+.approved-time {
+  font-size: 28rpx;
+  color: #999;
+  margin-bottom: 40rpx;
+}
+
+.approved-content {
+  width: 100%;
+}
+
+.content-row {
+  font-size: 28rpx;
+  color: #333;
+  line-height: 1.6;
+  margin-bottom: 16rpx;
+}
+
+/* Detail Section */
+.detail-section {
+  background-color: #fff;
+  margin-top: 20rpx;
+  padding: 32rpx;
+  border-radius: 16rpx 16rpx 0 0;
+}
+
+.goods-info {
+  display: flex;
+  align-items: center;
+  margin-bottom: 32rpx;
+}
+
+.goods-img {
+  width: 120rpx;
+  height: 120rpx;
+  border-radius: 8rpx;
+  background-color: #f5f5f5;
+}
+
+.service-package-placeholder {
+  width: 120rpx;
+  height: 120rpx;
+  border-radius: 8rpx;
+  background-color: #e8e8e8;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.goods-desc {
+  margin-left: 20rpx;
+  flex: 1;
+}
+
+.goods-title {
+  font-size: 30rpx;
+  color: #333;
+  margin-bottom: 12rpx;
+}
+
+.goods-meta {
+  font-size: 24rpx;
+  color: #999;
+}
+
+.divider {
+  width: 100%;
+  height: 1rpx;
+  background-color: #eee;
+  margin-bottom: 32rpx;
+}
+
+/* List Items */
+.info-list {
+  display: flex;
+  flex-direction: column;
+  gap: 24rpx;
+}
+
+.info-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-size: 28rpx;
+}
+
+.info-label {
+  color: #666;
+}
+
+.info-value {
+  color: #333;
+}
+
+.info-value-group {
+  display: flex;
+  align-items: center;
+}
+
+.clickable-text {
+  color: #333;
+  font-weight: 600;
+}
+
+.copy-btn {
+  color: #333;
+  font-weight: 600;
+  margin-left: 16rpx;
+}
+
+/* Service Action */
+.service-action {
+  display: inline-flex;
+  flex-direction: column;
+  align-items: center;
+  margin-top: 40rpx;
+}
+
+.service-text {
+  font-size: 24rpx;
+  color: #333;
+  margin-top: 8rpx;
+}
+
+/* Bottom Bar */
+.bottom-bar {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background-color: #fff;
+  padding: 20rpx 40rpx;
+  padding-bottom: env(safe-area-inset-bottom);
+  box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
+
+  &.bottom-bar-rejected {
+    padding: 30rpx 32rpx;
+    /* Matches screenshot side spacing */
+    background-color: transparent;
+    box-shadow: none;
+  }
+}
+
+.revoke-btn {
+  background-color: #1d6ff6;
+  color: #fff;
+  font-size: 32rpx;
+  font-weight: 500;
+  border-radius: 44rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 88rpx;
+  width: 100%;
+}
+
+.revoke-btn::after {
+  border: none;
+}
+
+/* Dual Button Group - Pill Shaped */
+.dual-btn-group {
+  display: flex;
+  align-items: center;
+  width: 100%;
+  height: 100rpx;
+  background-color: #1d6ff6;
+  border-radius: 50rpx;
+  /* Makes it pill shaped */
+  overflow: hidden;
+  box-shadow: 0 4rpx 20rpx rgba(29, 111, 246, 0.2);
+}
+
+.dual-btn {
+  flex: 1;
+  height: 100%;
+  background-color: transparent;
+  color: #fff;
+  font-size: 32rpx;
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 0;
+  padding: 0;
+  margin: 0;
+  line-height: normal;
+
+  &::after {
+    border: none;
+  }
+}
+
+.btn-divider {
+  width: 1rpx;
+  height: 40rpx;
+  background-color: rgba(255, 255, 255, 0.5);
+}

+ 202 - 0
miniprogram/module/order/pages/refund-processing/refund-processing.ts

@@ -0,0 +1,202 @@
+Page({
+  data: {
+    pageTitle: '商家处理',
+    refundState: 'completed', // 测试数据:processing, approved, revoked, rejected, 或 completed
+    days: '06',
+    hours: '23',
+    minutes: '43',
+    seconds: '59',
+    goods: {
+      name: "肝血贴穴位贴",
+      meta1: "10贴",
+      price: "240",
+      image: ""
+    },
+    refundDetail: {
+      reason: "少件(含缺少配件)",
+      amount: "240.00",
+      finishTime: "2025-02-19 20:30:27",
+      applyTime: "2025-02-19 14:30:27",
+      refundNo: "7364647828273462271"
+    },
+    refundDestination: {
+      type: '退回微信',
+      account: '梅*** 158******26'
+    },
+    // 弹窗状态
+    refundReasonPopupVisible: false,
+    refundConfirmPopupVisible: false,
+    refundProofPopupVisible: false,
+    refundStatus: 'received',
+    refundMaxAmount: '240',
+    refundProofImages: [],
+  },
+
+  timer: null as any,
+
+  onLoad() {
+    this.updatePageTitle();
+    if (this.data.refundState === 'processing' || this.data.refundState === 'rejected') {
+      this.startCountdown();
+    }
+  },
+
+  updatePageTitle() {
+    let title = '商家处理';
+    if (this.data.refundState === 'revoked') {
+      title = '撤销申请';
+    } else if (this.data.refundState === 'completed') {
+      title = '退款完成';
+    }
+    this.setData({ pageTitle: title });
+  },
+
+  onUnload() {
+    if (this.timer) {
+      clearInterval(this.timer);
+    }
+  },
+
+  startCountdown() {
+    // 模拟真实的倒计时,预设当前剩余时间(处理中通常为48小时,拒绝重填通常为7天)
+    const targetHours = this.data.refundState === 'rejected' ? 7 * 24 : 48;
+    const targetTime = new Date().getTime() + targetHours * 60 * 60 * 1000 - 1000;
+
+    this.timer = setInterval(() => {
+      const now = new Date().getTime();
+      const diff = targetTime - now;
+
+      if (diff <= 0) {
+        clearInterval(this.timer);
+        this.setData({ days: '00', hours: '00', minutes: '00', seconds: '00' });
+        return;
+      }
+
+      const d = Math.floor(diff / (1000 * 60 * 60 * 24));
+      const h = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
+      const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
+      const s = Math.floor((diff % (1000 * 60)) / 1000);
+
+      this.setData({
+        days: d < 10 ? '0' + d : String(d),
+        hours: h < 10 ? '0' + h : String(h),
+        minutes: m < 10 ? '0' + m : String(m),
+        seconds: s < 10 ? '0' + s : String(s),
+      });
+    }, 1000);
+  },
+
+  // 修改申请:打开确认弹窗
+  onModify() {
+    this.setData({ refundConfirmPopupVisible: true });
+  },
+
+  // 确认弹窗处理
+  onRefundConfirmClose() {
+    this.setData({ refundConfirmPopupVisible: false });
+  },
+
+  onChangeRefundStatus(e: any) {
+    this.setData({ refundStatus: e.detail.status });
+  },
+
+  onOpenRefundReasonAgain() {
+    this.setData({
+      refundConfirmPopupVisible: false,
+      refundReasonPopupVisible: true
+    });
+  },
+
+  onOpenRefundProofEditor() {
+    this.setData({
+      refundConfirmPopupVisible: false,
+      refundProofPopupVisible: true
+    });
+  },
+
+  onRefundAmountConfirm(e: any) {
+    this.setData({
+      ['refundDetail.amount']: e.detail.amount
+    });
+  },
+
+  onSubmitRefundApply() {
+    this.setData({ refundConfirmPopupVisible: false });
+    wx.showLoading({ title: '正在提交' });
+    setTimeout(() => {
+      wx.hideLoading();
+      wx.navigateTo({
+        url: '/module/order/pages/refund-success/refund-success'
+      });
+    }, 1000);
+  },
+
+  // 原因弹窗处理
+  onRefundReasonPopupClose() {
+    this.setData({ refundReasonPopupVisible: false });
+  },
+
+  onRefundReasonNext(e: any) {
+    this.setData({
+      ['refundDetail.reason']: e.detail.reason,
+      refundReasonPopupVisible: false,
+      refundConfirmPopupVisible: true
+    });
+  },
+
+  // 凭证弹窗处理
+  onRefundProofPopupClose() {
+    this.setData({ refundProofPopupVisible: false });
+  },
+
+  onRefundProofSubmit(e: any) {
+    this.setData({
+      refundProofImages: e.detail.images,
+      refundProofPopupVisible: false,
+      refundConfirmPopupVisible: true
+    });
+  },
+
+  onViewHistory() {
+    wx.navigateTo({
+      url: '/module/order/pages/negotiation-history/negotiation-history'
+    });
+  },
+
+  onCopyRefundNo() {
+    wx.setClipboardData({
+      data: this.data.refundDetail.refundNo,
+      success: () => {
+        wx.showToast({ title: '已复制', icon: 'none' });
+      }
+    });
+  },
+
+  onCallService() {
+    wx.makePhoneCall({
+      phoneNumber: '400-123-4567', // 替换为真实的客服电话
+      fail: () => {
+        // 用户取消拨打
+      }
+    });
+  },
+
+  onRevoke() {
+    wx.showModal({
+      title: '撤销退款申请',
+      content: '撤销退款申请后,可以再次发起退款申请(总共可发起2次)',
+      confirmText: '确定撤销',
+      cancelText: '暂不撤销',
+      success: (res) => {
+        if (res.confirm) {
+          wx.showToast({ title: '已撤销', icon: 'success' });
+          setTimeout(() => {
+            wx.redirectTo({
+              url: '/module/article/pages/success-page/success-page?title=撤销退款申请成功'
+            });
+          }, 1500);
+        }
+      }
+    });
+  }
+});

+ 170 - 0
miniprogram/module/order/pages/refund-processing/refund-processing.wxml

@@ -0,0 +1,170 @@
+<t-navbar title="{{pageTitle}}" left-arrow />
+
+<scroll-view class="page-container" scroll-y>
+  <!-- 头部倒计时区域 -->
+  <!-- 头部状态区域 -->
+  <view class="header-section header-{{refundState}}">
+    <!-- 处理中状态 -->
+    <block wx:if="{{refundState === 'processing'}}">
+      <view class="status-title">商家处理中</view>
+      <view class="status-sub">已提交</view>
+      
+      <view class="countdown-container">
+        <view class="time-block">{{hours}}</view>
+        <view class="time-colon">:</view>
+        <view class="time-block">{{minutes}}</view>
+        <view class="time-colon">:</view>
+        <view class="time-block">{{seconds}}</view>
+      </view>
+    </block>
+
+    <!-- 已同意状态 -->
+    <block wx:elif="{{refundState === 'approved'}}">
+      <view class="approved-title">同意退款</view>
+      <view class="approved-time">{{refundDetail.applyTime}}</view>
+      
+      <view class="approved-content">
+        <view class="content-row">【标题】平台同意了您的退款申请</view>
+        <view class="content-row">【内容】请耐心等待财务确认打款,退款将原路退回您的账户中。</view>
+      </view>
+    </block>
+
+    <!-- 撤销状态 -->
+    <block wx:elif="{{refundState === 'revoked'}}">
+      <view class="status-title" style="margin-bottom: 0;">撤销退款申请成功</view>
+    </block>
+
+    <!-- 拒绝状态 -->
+    <block wx:elif="{{refundState === 'rejected'}}">
+      <view class="approved-title">拒绝退款(请在{{days}}天{{hours}}小时{{minutes}}分钟内处理)</view>
+      <view class="approved-time">{{refundDetail.applyTime}}</view>
+      
+      <view class="approved-content">
+        <view class="content-row">【标题】平台拒绝了您的退款申请</view>
+        <view class="content-row">【内容】商品已经核销3次,麻烦修改退款金额为¥200</view>
+      </view>
+    </block>
+
+    <!-- 退款成功状态 -->
+    <block wx:elif="{{refundState === 'completed'}}">
+      <view class="status-title completed-title">退款成功</view>
+      <view class="refund-card">
+        <view class="refund-card__left">
+          <view class="refund-dest-name">{{refundDestination.type}}</view>
+          <view class="refund-dest-account">{{refundDestination.account}}</view>
+        </view>
+        <view class="refund-card__right">
+          <view class="refund-amount-text">¥{{refundDetail.amount}}</view>
+        </view>
+      </view>
+    </block>
+  </view>
+
+  <!-- 详情区域 -->
+  <view class="detail-section">
+    <!-- 商品简要信息 -->
+    <view class="goods-info">
+      <image class="goods-img" src="{{goods.image}}" mode="aspectFill" wx:if="{{goods.image}}"></image>
+      <view class="service-package-placeholder" wx:else>
+        <t-icon name="image" size="48rpx" color="#ccc" />
+      </view>
+      <view class="goods-desc">
+        <view class="goods-title">{{goods.name}}</view>
+        <view class="goods-meta">{{goods.meta1}}</view>
+      </view>
+    </view>
+
+    <!-- 分割线 -->
+    <view class="divider"></view>
+
+    <!-- 退款详情列表 -->
+    <view class="info-list">
+      <view class="info-item">
+        <text class="info-label">协商历史</text>
+        <view class="info-value clickable-text" bindtap="onViewHistory">查看</view>
+      </view>
+      <view class="info-item">
+        <text class="info-label">退款原因</text>
+        <text class="info-value">{{refundDetail.reason}}</text>
+      </view>
+      <view class="info-item">
+        <text class="info-label">申请金额</text>
+        <text class="info-value">共{{refundDetail.amount}}元</text>
+      </view>
+      
+      <!-- 根据状态不同展示不同的时间标签 -->
+      <view class="info-item" wx:if="{{refundState === 'approved' || refundState === 'completed'}}">
+        <text class="info-label">退款完结</text>
+        <text class="info-value">{{refundDetail.finishTime}}</text>
+      </view>
+      <view class="info-item" wx:elif="{{refundState === 'revoked'}}">
+        <text class="info-label">撤销时间</text>
+        <text class="info-value">{{refundDetail.finishTime}}</text>
+      </view>
+      <view class="info-item">
+        <text class="info-label">申请时间</text>
+        <text class="info-value">{{refundDetail.applyTime}}</text>
+      </view>
+      <view class="info-item">
+        <text class="info-label">退款编号</text>
+        <view class="info-value-group">
+          <text class="info-value">{{refundDetail.refundNo}}</text>
+          <text class="copy-btn" bindtap="onCopyRefundNo">复制</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- 客服按钮(放在列表下方或绝对定位) -->
+    <view class="service-action" bindtap="onCallService">
+      <t-icon name="service" size="44rpx" color="#333" />
+      <text class="service-text">客服</text>
+    </view>
+  </view>
+</scroll-view>
+
+<!-- 底部操作按钮 -->
+<view class="bottom-bar {{refundState === 'rejected' ? 'bottom-bar-rejected' : ''}}" wx:if="{{refundState === 'processing' || refundState === 'rejected'}}">
+  <!-- 处理中:单个撤销按钮 -->
+  <button class="revoke-btn" bindtap="onRevoke" wx:if="{{refundState === 'processing'}}">撤销申请</button>
+  
+  <!-- 拒绝退款:修改申请 & 撤销申请 组合按钮 -->
+  <view class="dual-btn-group" wx:if="{{refundState === 'rejected'}}">
+    <button class="dual-btn left-btn" bindtap="onModify">修改申请</button>
+    <view class="btn-divider"></view>
+    <button class="dual-btn right-btn" bindtap="onRevoke">撤销申请</button>
+  </view>
+</view>
+
+<!-- 退款修改相关弹窗 -->
+<refund-reason-popup
+  visible="{{refundReasonPopupVisible}}"
+  initial-reason="{{refundDetail.reason}}"
+  bind:close="onRefundReasonPopupClose"
+  bind:next="onRefundReasonNext"
+/>
+
+<refund-confirm-popup
+  visible="{{refundConfirmPopupVisible}}"
+  goods-name="{{goods.name}}"
+  goods-price="{{goods.price || '240'}}"
+  goods-meta1="{{goods.meta1}}"
+  goods-meta2="{{goods.meta2}}"
+  refund-reason="{{refundDetail.reason}}"
+  refund-status="{{refundStatus || '仅退款'}}"
+  refund-amount="{{refundDetail.amount}}"
+  max-amount="{{refundMaxAmount || '240'}}"
+  proof-images="{{refundProofImages || []}}"
+  bind:close="onRefundConfirmClose"
+  bind:changeStatus="onChangeRefundStatus"
+  bind:editReason="onOpenRefundReasonAgain"
+  bind:editProof="onOpenRefundProofEditor"
+  bind:amountConfirm="onRefundAmountConfirm"
+  bind:submit="onSubmitRefundApply"
+/>
+
+<refund-proof-popup
+  visible="{{refundProofPopupVisible}}"
+  initial-images="{{refundProofImages}}"
+  bind:close="onRefundProofPopupClose"
+  bind:submit="onRefundProofSubmit"
+/>

+ 6 - 0
miniprogram/module/order/pages/refund-success/refund-success.json

@@ -0,0 +1,6 @@
+{
+  "navigationBarTitleText": "提交完成",
+  "usingComponents": {
+    "t-navbar": "tdesign-miniprogram/navbar/navbar"
+  }
+}

+ 42 - 0
miniprogram/module/order/pages/refund-success/refund-success.scss

@@ -0,0 +1,42 @@
+.success-page {
+  height: 100vh;
+  background: #fff;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 200rpx 40rpx 0;
+  box-sizing: border-box;
+}
+
+.success-title {
+  font-size: 64rpx;
+  font-weight: 600;
+  color: #111;
+}
+
+.success-sub {
+  margin-top: 26rpx;
+  font-size: 32rpx;
+  color: #333;
+}
+
+.success-footer {
+  width: 100%;
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  padding: 8rpx 40rpx calc(10rpx + env(safe-area-inset-bottom));
+  box-sizing: border-box;
+}
+
+.finish-btn {
+  width: 100%;
+  height: 88rpx;
+  line-height: 88rpx;
+  text-align: center;
+  border-radius: 12rpx;
+  color: #fff;
+  background: #2f6df6;
+  font-size: 34rpx;
+}

+ 7 - 0
miniprogram/module/order/pages/refund-success/refund-success.ts

@@ -0,0 +1,7 @@
+Page({
+  data: {},
+  onLoad() {},
+  onFinish() {
+    wx.navigateBack({ delta: 1 });
+  },
+});

+ 8 - 0
miniprogram/module/order/pages/refund-success/refund-success.wxml

@@ -0,0 +1,8 @@
+<t-navbar title="提交完成" left-arrow />
+<view class="success-page">
+  <view class="success-title">提交完成</view>
+  <view class="success-sub">退款申请提交完成,请耐心等待商家处理!</view>
+  <view class="success-footer">
+    <view class="finish-btn" bindtap="onFinish">完成</view>
+  </view>
+</view>