Ver Fonte

举报审核模块完成

sgc há 3 semanas atrás
pai
commit
2f91e22eaa

+ 13 - 0
src/api/modules/lawyer.ts

@@ -100,6 +100,19 @@ export const exportLawyerListWithName = (params?: any) => {
   return http.get(url + `/lawyer/firm/reconciliation/exportLawyerListWithName`, params, { responseType: "blob" });
 };
 
+//////////////////////////// 举报审核 ////////////////////////////
+export const getViolationPage = (params?: any) => {
+  return http.get(url + `/lawyer/user-violation/page`, params);
+};
+export const violationApprove = (params?: any) => {
+  return http.get(url + `/lawyer/user-violation/approve`, params);
+};
+
+//////////////////////////// 审核审核 ////////////////////////////
+// export const getViolationPage = (params?: any) => {
+//   return http.get(url + `/lawyer/user-violation/page`, params, { responseType: "blob" });
+// };
+
 //////////////////////////// 导入导出 ////////////////////////////
 //  导入律所数据
 export const importData = (params: any) => {

+ 299 - 0
src/views/appeal/index.vue

@@ -0,0 +1,299 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" :request-api="getTableList" :data-callback="dataCallback">
+      <template #endFundsButton="scope">
+        <el-tag v-if="scope.row.endFundsButton == 1" type="success"> 审核中 </el-tag>
+        <el-tag v-if="scope.row.endFundsButton == 2" type="success"> 已通过 </el-tag>
+        <el-tag v-if="scope.row.endFundsButton == 3" type="primary"> 已驳回 </el-tag>
+      </template>
+      <template #promoteType="scope">
+        <el-tag v-for="(item, index) in getPromoteTypes(scope.row.promoteType)" :key="index">
+          {{ item }}
+        </el-tag>
+      </template>
+
+      <template #operation="scope">
+        <el-button type="primary" :icon="Search" link @click="handleDetail(scope.row)"> 查看详情 </el-button>
+        <el-button type="primary" :icon="Setting" v-if="scope.row.endFundsButton == 1" link @click="handleReview(scope.row)">
+          审核
+        </el-button>
+      </template>
+    </ProTable>
+
+    <ReviewDialog ref="reviewDialog" @approve="handleApprove" @reject="handleReject" />
+    <DetailDialog ref="detailDialog" />
+  </div>
+</template>
+
+<script setup lang="ts">
+import ReviewDialog from "./reviewDialog.vue";
+import DetailDialog from "./detailDialog.vue";
+import { ref, reactive, onActivated } from "vue";
+import type { Course } from "@/api/interface";
+import { ElMessage } from "element-plus";
+import ProTable from "@/components/ProTable/index.vue";
+import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
+import { Search, Setting } from "@element-plus/icons-vue";
+
+const proTable = ref<ProTableInstance>();
+
+const reviewDialog = ref<any>(null);
+const detailDialog = ref<any>(null);
+
+const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
+  {
+    label: "序号",
+    type: "index",
+    width: 60,
+    align: "center",
+    fixed: "left" // 固定在左侧
+  },
+  {
+    label: "订单编号",
+    prop: "orderNo",
+    width: 240,
+    search: { el: "input", tooltip: "请输入订单编号" },
+    fixed: "left", // 固定在左侧
+    showOverflowTooltip: true
+  },
+  {
+    label: "姓名",
+    prop: "realName",
+    width: 160,
+    search: { el: "input", tooltip: "请输入姓名" },
+    showOverflowTooltip: true
+  },
+  {
+    label: "订单金额(元)",
+    prop: "orderMoney",
+    width: 200,
+    align: "right"
+  },
+  {
+    label: "状态",
+    prop: "endFundsButton",
+    width: 100,
+    search: {
+      el: "select",
+      tooltip: "请选择状态",
+      props: { clearable: true }
+    },
+    enum: [
+      { value: 1, label: "审核中" },
+      { value: 2, label: "已通过" },
+      { value: 3, label: "已驳回" }
+    ],
+    fieldNames: { label: "label", value: "value" }
+  },
+  {
+    label: "下单时间",
+    prop: "orderTime"
+  },
+  {
+    label: "申请时间",
+    prop: "endFundsTime"
+  },
+  {
+    label: "下单时间",
+    prop: "time1",
+    isShow: false, // 关键:不在表格中显示
+    search: {
+      el: "date-picker",
+      props: {
+        type: "datetimerange",
+        valueFormat: "YYYY-MM-DD HH:mm:ss",
+        rangeSeparator: "至",
+        startPlaceholder: "开始时间",
+        endPlaceholder: "结束时间"
+      }
+    }
+  },
+  {
+    label: "申请时间",
+    prop: "time4",
+    isShow: false, // 关键:不在表格中显示
+    search: {
+      el: "date-picker",
+      props: {
+        type: "datetimerange",
+        valueFormat: "YYYY-MM-DD HH:mm:ss",
+        rangeSeparator: "至",
+        startPlaceholder: "开始时间",
+        endPlaceholder: "结束时间"
+      }
+    }
+  },
+  {
+    label: "操作",
+    prop: "operation",
+    width: 200,
+    fixed: "right" // 固定在右侧
+  }
+]);
+
+const getTableList = async (params: any) => {
+  let tempParams = JSON.parse(JSON.stringify(params));
+  delete tempParams.time1;
+  delete tempParams.time2;
+  delete tempParams.time3;
+  delete tempParams.time4;
+  // 深拷贝原始参数
+  let newParams = JSON.parse(JSON.stringify(tempParams));
+  newParams.page = newParams.pageNum;
+  newParams.size = newParams.pageSize;
+  delete newParams.pageNum;
+  delete newParams.pageSize;
+  if (params.time1) {
+    newParams.orderCreatedTime = params.time1[0];
+    newParams.orderEndTime = params.time1[1];
+  }
+  // todo  后端 现在下单时间和支付时间是一个字段,后续调整 在改动
+  if (params.time2) {
+    newParams.payCreatedTime = params.time2[0];
+    newParams.payEndTime = params.time2[1];
+  }
+  if (params.time3) {
+    newParams.firstCompleteTime = params.time3[0];
+    newParams.endCompleteTime = params.time3[1];
+  }
+  if (params.time4) {
+    newParams.createdEndPaymentTime = params.time4[0];
+    newParams.endEndPaymentTime = params.time4[1];
+  }
+  const res = await getFinalPaymentList(newParams);
+  return res;
+};
+
+const dataCallback = (data: any) => {
+  return {
+    list: data.records,
+    total: data.total
+  };
+};
+
+// 处理推广板块字符串
+const getPromoteTypes = (promoteType: string) => {
+  if (!promoteType) return [];
+  return promoteType.split(",");
+};
+
+//详情
+const handleDetail = row => {
+  detailDialog.value?.open(row);
+};
+
+// 审核
+const handleReview = (row: any) => {
+  reviewDialog.value?.open(row);
+};
+
+// 处理同意操作 endFundsButton: 2
+const handleApprove = async (payload: {
+  id: number;
+  name: string;
+  orderMoney: number;
+  orderNo: string;
+  storeTel: string;
+  userPhone: string;
+  endPaymentRefusal: string;
+  endPayment: number | string;
+}) => {
+  try {
+    const res: any = await getFinalPaymentReview({
+      ...payload,
+      endFundsButton: 2
+    });
+    if (res.data.status == 0) {
+      ElMessage.success(res.msg);
+    }
+    if (res.data.status == 1) {
+      ElMessage.error(res.data.codeMsg);
+    }
+    proTable.value?.getTableList();
+  } catch (error) {
+    console.error("审核通过失败:", error);
+    ElMessage.error("审核通过失败");
+  }
+};
+
+// 处理驳回操作 endFundsButton: 3
+const handleReject = async (payload: {
+  id: number;
+  name: string;
+  orderMoney: number;
+  orderNo: string;
+  storeTel: string;
+  userPhone: string;
+  endPaymentRefusal: string;
+  endPayment: number | string;
+}) => {
+  try {
+    const res: any = await getFinalPaymentReview({
+      ...payload,
+      endFundsButton: 3
+    });
+    if (res.data.status == 0) {
+      ElMessage.success(res.msg);
+    }
+    if (res.data.status == 1) {
+      ElMessage.error(res.data.codeMsg);
+    }
+    proTable.value?.getTableList();
+  } catch (error) {
+    console.error("审核驳回失败:", error);
+    ElMessage.error("审核驳回失败");
+  }
+};
+
+onActivated(() => {
+  proTable.value?.getTableList();
+});
+</script>
+
+<style scoped lang="scss">
+/* 操作列按钮间距优化 */
+:deep(.operation-column .cell) {
+  display: flex;
+  gap: 12px;
+  justify-content: flex-end;
+  .el-button {
+    height: auto;
+    padding: 5px 10px;
+    &.is-link {
+      min-width: auto;
+      padding: 0;
+    }
+  }
+}
+
+/* 金额列高亮显示 */
+:deep(.financial-column .cell) {
+  font-weight: 600;
+  color: #e6a23c; // Element Plus 橙色
+  text-align: center;
+}
+
+/* 表格行悬停效果增强 */
+:deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
+  background-color: #f5f9ff !important;
+  transition: background-color 0.3s;
+}
+
+/* 表头样式优化 */
+:deep(.el-table__header-wrapper th) {
+  padding: 10px 0;
+  font-weight: 600;
+  color: #303133;
+  background-color: #f8f9fa;
+  .cell {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+}
+
+/* 单元格内边距优化 */
+:deep(.el-table__cell) {
+  padding: 8px 0;
+}
+</style>

+ 47 - 1
src/views/lawyerManagement/lawFirm/index.vue

@@ -13,6 +13,15 @@
         >
           导出
         </el-button>
+        <el-button
+          type="primary"
+          :icon="Download"
+          :loading="exportAllLoading"
+          :disabled="!hasExportableData || !isAdmin"
+          @click="handleExportAll"
+        >
+          全部导出
+        </el-button>
       </template>
       <template #paymentAccount="scope">
         <div class="payment-tags">
@@ -70,6 +79,7 @@ const proTable = ref<ProTableInstance>();
 const lawFirmDialogRef = ref<InstanceType<typeof LawFirmDialog>>();
 const importVisible = ref(false);
 const exportLoading = ref(false);
+const exportAllLoading = ref(false);
 const tableTotal = ref(0);
 const hasExportableData = computed(() => tableTotal.value > 0);
 
@@ -212,6 +222,22 @@ const handleImportSuccess = () => {
   refreshTable();
 };
 
+const buildExportParams = (override: Record<string, any> = {}) => {
+  const searchParam = proTable.value?.searchParam ? { ...proTable.value.searchParam } : {};
+  const pageable = proTable.value?.pageable
+    ? { page: proTable.value.pageable.pageNum, size: proTable.value.pageable.pageSize }
+    : { page: 1, size: 10 };
+  const params: Record<string, any> = {
+    ...searchParam,
+    ...pageable,
+    ...override
+  };
+  if (!isAdmin.value && loginFirmId.value) {
+    params.firmId = loginFirmId.value;
+  }
+  return params;
+};
+
 const handleExport = async () => {
   if (!ensureAdmin()) {
     return;
@@ -222,13 +248,33 @@ const handleExport = async () => {
   }
   exportLoading.value = true;
   try {
-    const params = { ...(proTable.value?.searchParam || {}) };
+    const params = buildExportParams();
     await useDownload(exportLawFirm, "律所列表", params);
   } finally {
     exportLoading.value = false;
   }
 };
 
+const handleExportAll = async () => {
+  if (!ensureAdmin()) {
+    return;
+  }
+  if (!hasExportableData.value) {
+    ElMessage.warning("暂无可导出的数据");
+    return;
+  }
+  exportAllLoading.value = true;
+  try {
+    const params = buildExportParams({
+      page: 1,
+      size: Math.max(tableTotal.value, 1)
+    });
+    await useDownload(exportLawFirm, "律所列表-全部", params);
+  } finally {
+    exportAllLoading.value = false;
+  }
+};
+
 onActivated(() => {
   refreshTable();
 });

+ 88 - 248
src/views/refund/detailDialog.vue

@@ -1,290 +1,130 @@
 <template>
-  <el-dialog v-model="dialogShow" title="尾款详情" draggable width="860px" @close="handleClose">
-    <!-- 合并指标区域为一行 -->
-    <div class="metrics-sections">
-      <div class="metrics-section">
-        <div class="section-header">预计指标</div>
-        <div class="metrics-cards">
-          <div class="metric-card">
-            <div class="metric-label">GMV(元)</div>
-            <div class="metric-value">
-              {{ formatAmount(detailData.orderGmv) }}
-            </div>
-          </div>
-          <div class="metric-card">
-            <div class="metric-label">播放量</div>
-            <div class="metric-value">
-              {{ detailData.orderPlayCount || 0 }}
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <div class="metrics-section">
-        <div class="section-header">实际完成</div>
-        <div class="metrics-cards">
-          <div class="metric-card">
-            <div class="metric-label">GMV(元)</div>
-            <div class="metric-value">
-              {{ formatAmount(detailData.actualGmv) }}
-            </div>
-          </div>
-          <div class="metric-card">
-            <div class="metric-label">播放量</div>
-            <div class="metric-value">
-              {{ detailData.actualPlayCount || 0 }}
-            </div>
-          </div>
-        </div>
+  <el-dialog v-model="dialogShow" title="举报详情" width="760px" @close="handleClose">
+    <el-descriptions :column="2" border class="detail-descriptions">
+      <el-descriptions-item label="律师姓名">
+        {{ detailData.reportedUserName || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="订单编号">
+        {{ detailData.orderNumber || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="举报类型">
+        {{ violationDisplay }}
+      </el-descriptions-item>
+      <el-descriptions-item label="举报人姓名">
+        {{ detailData.nickname || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="举报时间">
+        {{ detailData.createdTime || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item v-if="detailData.processingTime" label="处理时间">
+        {{ detailData.processingTime || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="当前状态">
+        <el-tag v-if="currentStatus" :type="currentStatus.tagType">
+          {{ currentStatus.label }}
+        </el-tag>
+        <span v-else> -- </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="处理说明">
+        {{ detailData.reportResult || "--" }}
+      </el-descriptions-item>
+    </el-descriptions>
+
+    <div class="evidence-block" v-if="evidenceList.length">
+      <div class="block-title">举报凭证</div>
+      <div class="image-grid">
+        <el-image
+          v-for="(img, index) in evidenceList"
+          :key="`${detailData.id}-${index}`"
+          :src="img"
+          :preview-src-list="evidenceList"
+          fit="cover"
+        />
       </div>
     </div>
 
-    <!-- 详情展示区域 -->
-    <div class="review-container">
-      <div class="review-detail">
-        <el-descriptions :column="2" border>
-          <!-- 第一列:重要信息 -->
-          <el-descriptions-item label="套餐名称">
-            {{ detailData.name }}
-          </el-descriptions-item>
-          <el-descriptions-item label="订单编号">
-            {{ detailData.orderNo }}
-          </el-descriptions-item>
-          <el-descriptions-item label="达人ID">
-            {{ detailData.expertId }}
-          </el-descriptions-item>
-          <el-descriptions-item label="达人昵称">
-            {{ detailData.userName }}
-          </el-descriptions-item>
-          <el-descriptions-item label="姓名">
-            {{ detailData.realName }}
-          </el-descriptions-item>
-          <el-descriptions-item label="联系电话">
-            {{ detailData.userPhone }}
-          </el-descriptions-item>
-          <el-descriptions-item label="身份证号码" :span="2">
-            {{ detailData.idCard }}
-          </el-descriptions-item>
-
-          <!-- 第二列:财务信息 -->
-          <el-descriptions-item label="订单金额(元)" :span="2">
-            {{ formatAmount(detailData.orderMoney) }}
-          </el-descriptions-item>
-          <el-descriptions-item label="尾款比例"> {{ detailData.endPaymentRate || 0 }}% </el-descriptions-item>
-          <el-descriptions-item label="尾款(元)">
-            {{ formatAmount(detailData.endPayment) }}
-          </el-descriptions-item>
-          <el-descriptions-item label="预付款比例"> {{ detailData.advanceRate || 0 }}% </el-descriptions-item>
-          <el-descriptions-item label="预付款(元)">
-            {{ formatAmount(detailData.advance) }}
-          </el-descriptions-item>
-          <el-descriptions-item label="佣金比例"> {{ detailData.commissionRate || 0 }}% </el-descriptions-item>
-          <el-descriptions-item label="佣金(元)">
-            {{ formatAmount(detailData.commission) }}
-          </el-descriptions-item>
-
-          <!-- 底部重要信息 -->
-          <el-descriptions-item label="推广模块" :span="2">
-            <el-tag
-              v-for="(item, index) in getPromoteTypes(detailData.promoteType)"
-              :key="index"
-              style="margin-right: 5px; margin-bottom: 5px"
-            >
-              {{ item }}
-            </el-tag>
-          </el-descriptions-item>
-
-          <el-descriptions-item label="状态" :span="2">
-            <el-tag v-if="detailData.advancePaymentStatus == 0" type="success"> 审核通过 </el-tag>
-            <el-tag v-if="detailData.advancePaymentStatus == 1" type="success"> 待完成 </el-tag>
-            <el-tag v-if="detailData.advancePaymentStatus == 2" type="primary"> 已完成 </el-tag>
-          </el-descriptions-item>
-
-          <el-descriptions-item label="下单时间">
-            {{ detailData.orderTime || "--" }}
-          </el-descriptions-item>
-          <el-descriptions-item label="支付时间">
-            {{ detailData.payTime || "--" }}
-          </el-descriptions-item>
-          <el-descriptions-item label="完成时间" v-if="detailData.completeTime">
-            {{ detailData.completeTime || "--" }}
-          </el-descriptions-item>
-          <el-descriptions-item label="申请时间" v-if="detailData.endFundsTime">
-            {{ detailData.endFundsTime || "--" }}
-          </el-descriptions-item>
-          <el-descriptions-item label="审核时间" v-if="detailData.endPaymentTime">
-            {{ detailData.endPaymentTime }}
-          </el-descriptions-item>
-          <el-descriptions-item label="驳回原因" v-if="detailData.endPaymentRefusal">
-            {{ detailData.endPaymentRefusal }}
-          </el-descriptions-item>
-        </el-descriptions>
-      </div>
-    </div>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button type="primary" @click="handleClose">关闭</el-button>
+      </span>
+    </template>
   </el-dialog>
 </template>
 
 <script setup lang="ts">
-import { ref, defineExpose, defineEmits } from "vue";
+import { computed, ref } from "vue";
 
-// 定义弹窗状态
 const dialogShow = ref(false);
-
-// 详情数据
-const detailData: any = ref({});
-// 处理推广板块字符串
-const getPromoteTypes = (promoteType: string) => {
-  if (!promoteType) return [];
-  return promoteType.split(",");
+const detailData = ref<Record<string, any>>({});
+
+const statusMeta = [
+  { value: 0, label: "未处理", tagType: "info" },
+  { value: 1, label: "违规", tagType: "danger" },
+  { value: 2, label: "未违规", tagType: "success" }
+] as const;
+
+const violationTypeMeta = [
+  { value: 1, label: "服务态度差" },
+  { value: 2, label: "专业能力差" },
+  { value: 3, label: "响应时间超过24小时" },
+  { value: 4, label: "其他原因" }
+] as const;
+
+const getStatusMeta = (status?: number) => statusMeta.find(item => item.value == status);
+const getViolationMeta = (type?: number | string) => {
+  const value = typeof type === "string" ? Number(type) : type;
+  return violationTypeMeta.find(item => item.value === value);
 };
 
-// 金额格式化
-const formatAmount = (amount: number | string) => {
-  const num = typeof amount === "string" ? parseFloat(amount) : amount;
-  return isNaN(num) ? "¥0.00" : `¥${num.toFixed(2)}`;
+const parseEvidenceImages = (value: string | string[] | null | undefined) => {
+  if (!value) return [];
+  if (Array.isArray(value)) return value.filter(Boolean);
+  return value
+    .split(",")
+    .map(url => url.trim())
+    .filter(Boolean);
 };
 
-// 事件触发
-const emit = defineEmits(["close"]);
+const evidenceList = computed(() => parseEvidenceImages(detailData.value.reportEvidenceImg));
+const currentStatus = computed(() => getStatusMeta(detailData.value.processingStatus));
+const violationDisplay = computed(() => {
+  if (detailData.value.violationReason == 4) return detailData.value.otherReasonContent || "其他原因";
+  return getViolationMeta(detailData.value.violationReason)?.label || "--";
+});
 
-// 显示弹窗方法
 const open = (data: any) => {
-  detailData.value = {
-    ...data
-  };
+  detailData.value = { ...data };
   dialogShow.value = true;
 };
 
-// 关闭弹窗
 const handleClose = () => {
   dialogShow.value = false;
-  emit("close");
 };
 
-// 暴露给父组件的方法
 defineExpose({
   open,
   close: handleClose
 });
 </script>
 
-<style lang="scss" scoped>
-.section-header {
-  padding-left: 5px;
-  margin: 10px 0 12px;
-  font-size: 16px;
-  font-weight: 600;
-  color: #303133;
-  border-left: 3px solid #409eff;
-}
-.metrics-sections {
-  display: flex;
-  gap: 20px;
-  margin-bottom: 15px;
-
-  /* 在小屏幕上自动堆叠 */
-  @media (width <=600px) {
-    flex-direction: column;
-    gap: 10px;
-  }
-}
-.metrics-section {
-  flex: 1;
-  min-width: 0;
-  .section-header {
-    padding-left: 5px;
-    margin: 0 0 8px;
-    font-size: 14px;
-    font-weight: 600;
-    color: #303133;
-    border-left: 3px solid #409eff;
-  }
-}
-.metrics-cards {
-  display: grid;
-  grid-template-columns: 1fr 1fr;
-  gap: 8px;
-}
-.metric-card {
-  padding: 8px 10px;
-  background: #f8f9fa;
-  border: 1px solid #ebeef5;
-  border-radius: 6px;
-  transition: all 0.2s ease;
-  &:hover {
-    background: #f0f7ff;
-    border-color: #d6e4ff;
-  }
-}
-.metric-label {
-  margin-bottom: 4px;
-  font-size: 12px;
-  font-weight: 500;
-  color: #606266;
+<style scoped lang="scss">
+.detail-descriptions {
+  margin-bottom: 16px;
 }
-.metric-value {
-  font-size: 15px;
+.block-title {
+  margin-bottom: 8px;
   font-weight: 600;
   color: #303133;
 }
-.review-container {
-  margin-bottom: 15px;
-
-  /* 滚动条样式优化 */
-  &::-webkit-scrollbar {
-    width: 6px;
-  }
-  &::-webkit-scrollbar-track {
-    background: #f1f1f1;
-    border-radius: 3px;
-  }
-  &::-webkit-scrollbar-thumb {
-    background: #c1c1c1;
-    border-radius: 3px;
-  }
-  &::-webkit-scrollbar-thumb:hover {
-    background: #a8a8a8;
-  }
-}
-.review-detail {
-  .introduction {
-    line-height: 1.5;
-    word-break: break-word;
-    white-space: pre-wrap;
-  }
-}
-
-/* 隐藏预览时的操作栏 */
-:deep(.el-image-viewer__btn) {
-  display: none !important;
-}
-
-/* 或者更精确地隐藏操作栏区域 */
-:deep(.el-image-viewer__actions) {
-  display: none !important;
-}
 .image-grid {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
   gap: 8px;
 }
-.image-item {
-  aspect-ratio: 1;
-  overflow: hidden;
-}
-.gallery-image {
+.image-grid :deep(.el-image) {
   width: 100%;
   height: 100%;
-  cursor: pointer;
-  object-fit: cover;
-}
-
-/* 调整描述项的间距 */
-:deep(.el-descriptions__label) {
-  font-weight: 600;
-  background-color: #fafafa;
-}
-:deep(.el-descriptions__cell) {
-  padding: 10px 20px;
+  overflow: hidden;
+  border-radius: 8px;
 }
 </style>

+ 86 - 149
src/views/refund/index.vue

@@ -1,26 +1,22 @@
 <template>
   <div class="table-box">
     <ProTable ref="proTable" :columns="columns" :request-api="getTableList" :data-callback="dataCallback">
-      <template #endFundsButton="scope">
-        <el-tag v-if="scope.row.endFundsButton == 1" type="success"> 审核中 </el-tag>
-        <el-tag v-if="scope.row.endFundsButton == 2" type="success"> 已通过 </el-tag>
-        <el-tag v-if="scope.row.endFundsButton == 3" type="primary"> 已驳回 </el-tag>
-      </template>
-      <template #promoteType="scope">
-        <el-tag v-for="(item, index) in getPromoteTypes(scope.row.promoteType)" :key="index">
-          {{ item }}
+      <template #processingStatus="scope">
+        <el-tag v-if="getStatusMeta(scope.row.processingStatus)" :type="getStatusMeta(scope.row.processingStatus)?.tagType">
+          {{ getStatusMeta(scope.row.processingStatus)?.label }}
         </el-tag>
+        <span v-else> -- </span>
       </template>
 
       <template #operation="scope">
         <el-button type="primary" :icon="Search" link @click="handleDetail(scope.row)"> 查看详情 </el-button>
-        <el-button type="primary" :icon="Setting" v-if="scope.row.endFundsButton == 1" link @click="handleReview(scope.row)">
+        <el-button type="primary" :icon="Setting" v-if="scope.row.processingStatus == 0" link @click="handleReview(scope.row)">
           审核
         </el-button>
       </template>
     </ProTable>
 
-    <ReviewDialog ref="reviewDialog" @approve="handleApprove" @reject="handleReject" />
+    <ReviewDialog ref="reviewDialog" @submit="handleReviewSubmit" />
     <DetailDialog ref="detailDialog" />
   </div>
 </template>
@@ -29,18 +25,41 @@
 import ReviewDialog from "./reviewDialog.vue";
 import DetailDialog from "./detailDialog.vue";
 import { ref, reactive, onActivated } from "vue";
-import type { Course } from "@/api/interface";
 import { ElMessage } from "element-plus";
 import ProTable from "@/components/ProTable/index.vue";
 import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
 import { Search, Setting } from "@element-plus/icons-vue";
+import { getViolationPage, violationApprove } from "@/api/modules/lawyer";
 
 const proTable = ref<ProTableInstance>();
 
 const reviewDialog = ref<any>(null);
 const detailDialog = ref<any>(null);
+const currentRow = ref<any>();
+
+const statusMeta = [
+  { value: 0, label: "未处理", tagType: "info" },
+  { value: 1, label: "违规", tagType: "danger" },
+  { value: 2, label: "未违规", tagType: "success" }
+] as const;
+
+const violationTypeMeta = [
+  { value: 1, label: "服务态度差" },
+  { value: 2, label: "专业能力差" },
+  { value: 3, label: "响应时间超过24小时" },
+  { value: 4, label: "其他原因" }
+] as const;
+
+const getStatusMeta = (status?: number) => statusMeta.find(item => item.value == status);
+const getViolationMeta = (type?: number | string) => violationTypeMeta.find(item => item.value == type);
+
+const getViolationDisplay = (row: any) => {
+  if (!row) return "--";
+  if (row.violationReason == 4) return row.otherReasonContent || "其他原因";
+  return getViolationMeta(row.violationReason)?.label || "--";
+};
 
-const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
+const columns = reactive<ColumnProps<any>[]>([
   {
     label: "序号",
     type: "index",
@@ -49,79 +68,64 @@ const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
     fixed: "left" // 固定在左侧
   },
   {
-    label: "订单编号",
-    prop: "orderNo",
-    width: 240,
-    search: { el: "input", tooltip: "请输入订单编号" },
+    label: "律师姓名",
+    prop: "reportedUserName",
+    width: 200,
+    search: { el: "input", tooltip: "请输入律师姓名" },
     fixed: "left", // 固定在左侧
     showOverflowTooltip: true
   },
   {
-    label: "姓名",
-    prop: "realName",
-    width: 160,
-    search: { el: "input", tooltip: "请输入姓名" },
+    label: "订单编号",
+    prop: "orderNumber",
+    width: 220,
+    fixed: "left", // 固定在左侧
     showOverflowTooltip: true
   },
   {
-    label: "订单金额(元)",
-    prop: "orderMoney",
-    width: 200,
-    align: "right"
-  },
-  {
-    label: "状态",
-    prop: "endFundsButton",
-    width: 100,
+    label: "举报类型",
+    prop: "violationReason",
+    showOverflowTooltip: true,
     search: {
       el: "select",
-      tooltip: "请选择状态",
       props: { clearable: true }
     },
-    enum: [
-      { value: 1, label: "审核中" },
-      { value: 2, label: "已通过" },
-      { value: 3, label: "已驳回" }
-    ],
-    fieldNames: { label: "label", value: "value" }
+    enum: violationTypeMeta as any,
+    render: scope => getViolationDisplay(scope.row)
   },
   {
-    label: "下单时间",
-    prop: "orderTime"
+    label: "处理说明",
+    prop: "reportResult",
+    width: 200,
+    align: "center"
   },
   {
-    label: "申请时间",
-    prop: "endFundsTime"
+    label: "举报人姓名",
+    prop: "nickname",
+    width: 200,
+    align: "center"
   },
   {
-    label: "下单时间",
-    prop: "time1",
-    isShow: false, // 关键:不在表格中显示
-    search: {
-      el: "date-picker",
-      props: {
-        type: "datetimerange",
-        valueFormat: "YYYY-MM-DD HH:mm:ss",
-        rangeSeparator: "至",
-        startPlaceholder: "开始时间",
-        endPlaceholder: "结束时间"
-      }
-    }
+    label: "举报时间",
+    prop: "createdTime",
+    width: 200,
+    align: "center"
   },
   {
-    label: "申请时间",
-    prop: "time4",
-    isShow: false, // 关键:不在表格中显示
+    label: "当前状态",
+    prop: "processingStatus",
+    width: 100,
     search: {
-      el: "date-picker",
-      props: {
-        type: "datetimerange",
-        valueFormat: "YYYY-MM-DD HH:mm:ss",
-        rangeSeparator: "至",
-        startPlaceholder: "开始时间",
-        endPlaceholder: "结束时间"
-      }
-    }
+      el: "select",
+      tooltip: "请选择状态",
+      props: { clearable: true }
+    },
+    enum: [
+      { value: 0, label: "未处理" },
+      { value: 1, label: "违规" },
+      { value: 2, label: "未违规" }
+    ],
+    fieldNames: { label: "label", value: "value" }
   },
   {
     label: "操作",
@@ -132,35 +136,14 @@ const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
 ]);
 
 const getTableList = async (params: any) => {
-  let tempParams = JSON.parse(JSON.stringify(params));
-  delete tempParams.time1;
-  delete tempParams.time2;
-  delete tempParams.time3;
-  delete tempParams.time4;
-  // 深拷贝原始参数
-  let newParams = JSON.parse(JSON.stringify(tempParams));
-  newParams.page = newParams.pageNum;
-  newParams.size = newParams.pageSize;
+  const newParams = {
+    ...params,
+    page: params.pageNum,
+    size: params.pageSize
+  };
   delete newParams.pageNum;
   delete newParams.pageSize;
-  if (params.time1) {
-    newParams.orderCreatedTime = params.time1[0];
-    newParams.orderEndTime = params.time1[1];
-  }
-  // todo  后端 现在下单时间和支付时间是一个字段,后续调整 在改动
-  if (params.time2) {
-    newParams.payCreatedTime = params.time2[0];
-    newParams.payEndTime = params.time2[1];
-  }
-  if (params.time3) {
-    newParams.firstCompleteTime = params.time3[0];
-    newParams.endCompleteTime = params.time3[1];
-  }
-  if (params.time4) {
-    newParams.createdEndPaymentTime = params.time4[0];
-    newParams.endEndPaymentTime = params.time4[1];
-  }
-  const res = await getFinalPaymentList(newParams);
+  const res = await getViolationPage(newParams);
   return res;
 };
 
@@ -171,12 +154,6 @@ const dataCallback = (data: any) => {
   };
 };
 
-// 处理推广板块字符串
-const getPromoteTypes = (promoteType: string) => {
-  if (!promoteType) return [];
-  return promoteType.split(",");
-};
-
 //详情
 const handleDetail = row => {
   detailDialog.value?.open(row);
@@ -184,64 +161,24 @@ const handleDetail = row => {
 
 // 审核
 const handleReview = (row: any) => {
+  currentRow.value = row;
   reviewDialog.value?.open(row);
 };
 
-// 处理同意操作 endFundsButton: 2
-const handleApprove = async (payload: {
-  id: number;
-  name: string;
-  orderMoney: number;
-  orderNo: string;
-  storeTel: string;
-  userPhone: string;
-  endPaymentRefusal: string;
-  endPayment: number | string;
-}) => {
+const handleReviewSubmit = async (payload: { processingStatus: number; reportResult: string }) => {
+  if (!currentRow.value) return;
   try {
-    const res: any = await getFinalPaymentReview({
-      ...payload,
-      endFundsButton: 2
+    await violationApprove({
+      id: currentRow.value.id,
+      processingStatus: payload.processingStatus,
+      reportResult: payload.reportResult
     });
-    if (res.data.status == 0) {
-      ElMessage.success(res.msg);
-    }
-    if (res.data.status == 1) {
-      ElMessage.error(res.data.codeMsg);
-    }
-    proTable.value?.getTableList();
-  } catch (error) {
-    console.error("审核通过失败:", error);
-    ElMessage.error("审核通过失败");
-  }
-};
-
-// 处理驳回操作 endFundsButton: 3
-const handleReject = async (payload: {
-  id: number;
-  name: string;
-  orderMoney: number;
-  orderNo: string;
-  storeTel: string;
-  userPhone: string;
-  endPaymentRefusal: string;
-  endPayment: number | string;
-}) => {
-  try {
-    const res: any = await getFinalPaymentReview({
-      ...payload,
-      endFundsButton: 3
-    });
-    if (res.data.status == 0) {
-      ElMessage.success(res.msg);
-    }
-    if (res.data.status == 1) {
-      ElMessage.error(res.data.codeMsg);
-    }
+    ElMessage.success("审核结果已提交");
+    reviewDialog.value?.close?.();
     proTable.value?.getTableList();
   } catch (error) {
-    console.error("审核驳回失败:", error);
-    ElMessage.error("审核驳回失败");
+    console.error("审核失败:", error);
+    ElMessage.error("审核失败,请稍后重试");
   }
 };
 

+ 137 - 346
src/views/refund/reviewDialog.vue

@@ -1,401 +1,192 @@
 <template>
-  <el-dialog v-model="dialogShow" title="尾款审核" draggable width="860px" @close="handleClose">
-    <!-- 合并指标区域为一行 -->
-    <div class="metrics-sections">
-      <div class="metrics-section">
-        <div class="section-header">预计指标</div>
-        <div class="metrics-cards">
-          <div class="metric-card">
-            <div class="metric-label">GMV(元)</div>
-            <div class="metric-value">
-              {{ formatAmount(detailData.orderGmv) }}
-            </div>
-          </div>
-          <div class="metric-card">
-            <div class="metric-label">播放量</div>
-            <div class="metric-value">
-              {{ detailData.orderPlayCount || 0 }}
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <div class="metrics-section">
-        <div class="section-header">实际完成</div>
-        <div class="metrics-cards">
-          <div class="metric-card">
-            <div class="metric-label">GMV(元)</div>
-            <div class="metric-value">
-              {{ formatAmount(detailData.actualGmv) }}
-            </div>
-          </div>
-          <div class="metric-card">
-            <div class="metric-label">播放量</div>
-            <div class="metric-value">
-              {{ detailData.actualPlayCount || 0 }}
-            </div>
-          </div>
-        </div>
+  <el-dialog v-model="dialogShow" title="举报审核" width="780px" @close="handleClose">
+    <el-descriptions :column="2" border class="review-descriptions">
+      <el-descriptions-item label="律师姓名">
+        {{ detailData.reportedUserName || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="订单编号">
+        {{ detailData.orderNumber || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="举报人姓名">
+        {{ detailData.nickname || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="举报类型">
+        {{ violationDisplay }}
+      </el-descriptions-item>
+      <el-descriptions-item label="举报时间">
+        {{ detailData.createdTime || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item v-if="detailData.processingTime" label="处理时间">
+        {{ detailData.processingTime || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="当前状态">
+        <el-tag v-if="currentStatus" :type="currentStatus.tagType">
+          {{ currentStatus.label }}
+        </el-tag>
+        <span v-else> -- </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="举报描述" :span="2">
+        {{ detailData.otherReasonContent || "暂无" }}
+      </el-descriptions-item>
+    </el-descriptions>
+
+    <div class="evidence-block" v-if="evidenceList.length">
+      <div class="block-title">举报凭证</div>
+      <div class="image-grid">
+        <el-image
+          v-for="(img, index) in evidenceList"
+          :key="`${detailData.id}-${index}`"
+          :src="img"
+          :preview-src-list="evidenceList"
+          fit="cover"
+        />
       </div>
     </div>
 
-    <!-- 详情展示区域 -->
-    <div class="review-container">
-      <div class="review-detail">
-        <el-descriptions :column="2" border>
-          <!-- 第一列:重要信息 -->
-          <el-descriptions-item label="套餐名称">
-            {{ detailData.name }}
-          </el-descriptions-item>
-          <el-descriptions-item label="订单编号">
-            {{ detailData.orderNo }}
-          </el-descriptions-item>
-          <el-descriptions-item label="达人ID">
-            {{ detailData.expertId }}
-          </el-descriptions-item>
-          <el-descriptions-item label="达人昵称">
-            {{ detailData.userName }}
-          </el-descriptions-item>
-          <el-descriptions-item label="姓名">
-            {{ detailData.realName }}
-          </el-descriptions-item>
-          <el-descriptions-item label="联系电话">
-            {{ detailData.userPhone }}
-          </el-descriptions-item>
-          <el-descriptions-item label="身份证号码" :span="2">
-            {{ detailData.idCard }}
-          </el-descriptions-item>
-
-          <!-- 第二列:财务信息 -->
-          <el-descriptions-item label="订单金额(元)" :span="2">
-            {{ formatAmount(detailData.orderMoney) }}
-          </el-descriptions-item>
-          <el-descriptions-item label="尾款比例"> {{ detailData.endPaymentRate || 0 }}% </el-descriptions-item>
-          <el-descriptions-item label="尾款(元)">
-            {{ formatAmount(detailData.endPayment) }}
-          </el-descriptions-item>
-          <el-descriptions-item label="预付款比例"> {{ detailData.advanceRate || 0 }}% </el-descriptions-item>
-          <el-descriptions-item label="预付款(元)">
-            {{ formatAmount(detailData.advance) }}
-          </el-descriptions-item>
-          <el-descriptions-item label="佣金比例"> {{ detailData.commissionRate || 0 }}% </el-descriptions-item>
-          <el-descriptions-item label="佣金(元)">
-            {{ formatAmount(detailData.commission) }}
-          </el-descriptions-item>
-
-          <!-- 底部重要信息 -->
-          <el-descriptions-item label="推广模块" :span="2">
-            <el-tag
-              v-for="(item, index) in getPromoteTypes(detailData.promoteType)"
-              :key="index"
-              style="margin-right: 5px; margin-bottom: 5px"
-            >
-              {{ item }}
-            </el-tag>
-          </el-descriptions-item>
-
-          <el-descriptions-item label="状态" :span="2">
-            <el-tag v-if="detailData.advancePaymentStatus == 0" type="success"> 审核通过 </el-tag>
-            <el-tag v-if="detailData.advancePaymentStatus == 1" type="success"> 待完成 </el-tag>
-            <el-tag v-if="detailData.advancePaymentStatus == 2" type="primary"> 已完成 </el-tag>
-          </el-descriptions-item>
-
-          <el-descriptions-item label="下单时间">
-            {{ detailData.orderTime || "--" }}
-          </el-descriptions-item>
-          <el-descriptions-item label="支付时间">
-            {{ detailData.payTime || "--" }}
-          </el-descriptions-item>
-          <el-descriptions-item label="完成时间" v-if="detailData.completeTime">
-            {{ detailData.completeTime }}
-          </el-descriptions-item>
-          <el-descriptions-item label="申请时间" v-if="detailData.endFundsTime">
-            {{ detailData.endFundsTime }}
-          </el-descriptions-item>
-        </el-descriptions>
-      </div>
-    </div>
+    <el-form ref="formRef" :model="reviewForm" :rules="rules" label-width="90px" class="review-form">
+      <el-form-item label="处理结果" prop="processingStatus">
+        <el-radio-group v-model="reviewForm.processingStatus">
+          <el-radio :value="1"> 违规 </el-radio>
+          <el-radio :value="2"> 未违规 </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="处理说明" prop="reportResult">
+        <el-input
+          v-model="reviewForm.reportResult"
+          type="textarea"
+          :rows="3"
+          maxlength="200"
+          show-word-limit
+          placeholder="请输入处理说明"
+        />
+      </el-form-item>
+    </el-form>
 
-    <!-- 操作按钮区域 -->
     <template #footer>
       <span class="dialog-footer">
-        <el-button type="success" @click="confirmApprove"> 同意 </el-button>
-        <el-button type="warning" @click="openRejectDialog"> 驳回 </el-button>
-        <el-button @click="handleClose">关闭</el-button>
+        <el-button @click="handleClose">取消</el-button>
+        <el-button type="primary" @click="handleSubmit">提交</el-button>
       </span>
     </template>
-
-    <!-- 驳回原因弹窗 -->
-    <el-dialog title="驳回原因" v-model="rejectDialogVisible" width="520px" append-to-body>
-      <el-form :model="rejectForm" :rules="rejectRules" ref="rejectFormRef" label-width="80px">
-        <el-form-item label="原因" prop="reasonRefusal">
-          <el-input v-model="rejectForm.reasonRefusal" type="textarea" :rows="3" placeholder="请输入驳回原因" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="cancelRejectDialog">取消</el-button>
-          <el-button type="primary" @click="confirmReject">确认</el-button>
-        </span>
-      </template>
-    </el-dialog>
   </el-dialog>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, defineExpose, defineEmits } from "vue";
-import { ElMessageBox } from "element-plus";
+import { computed, reactive, ref } from "vue";
 import type { FormInstance, FormRules } from "element-plus";
 
-// 定义弹窗状态
 const dialogShow = ref(false);
-const rejectDialogVisible = ref(false);
-
-// 详情数据
-const detailData: any = ref({});
-// 处理推广板块字符串
-const getPromoteTypes = (promoteType: string) => {
-  if (!promoteType) return [];
-  return promoteType.split(",");
+const detailData = ref<Record<string, any>>({});
+const formRef = ref<FormInstance>();
+
+const statusMeta = [
+  { value: 0, label: "未处理", tagType: "info" },
+  { value: 1, label: "违规", tagType: "danger" },
+  { value: 2, label: "未违规", tagType: "success" }
+] as const;
+
+const violationTypeMeta = [
+  { value: 1, label: "服务态度差" },
+  { value: 2, label: "专业能力差" },
+  { value: 3, label: "响应时间超过24小时" },
+  { value: 4, label: "其他原因" }
+] as const;
+
+const getStatusMeta = (status?: number) => statusMeta.find(item => item.value == status);
+const getViolationMeta = (type?: number | string) => {
+  const value = typeof type === "string" ? Number(type) : type;
+  return violationTypeMeta.find(item => item.value === value);
 };
 
-// 金额格式化
-const formatAmount = (amount: number | string) => {
-  const num = typeof amount === "string" ? parseFloat(amount) : amount;
-  return isNaN(num) ? "¥0.00" : `¥${num.toFixed(2)}`;
+const parseEvidenceImages = (value: string | string[] | null | undefined) => {
+  if (!value) return [];
+  if (Array.isArray(value)) return value.filter(Boolean);
+  return value
+    .split(",")
+    .map(url => url.trim())
+    .filter(Boolean);
 };
 
-// 驳回表单
-const rejectForm = reactive({
-  reasonRefusal: ""
+const evidenceList = computed(() => parseEvidenceImages(detailData.value.reportEvidenceImg));
+const currentStatus = computed(() => getStatusMeta(detailData.value.processingStatus));
+const violationDisplay = computed(() => {
+  if (detailData.value.violationReason == 4) return detailData.value.otherReasonContent || "其他原因";
+  return getViolationMeta(detailData.value.violationReason)?.label || "--";
+});
+
+const reviewForm = reactive({
+  processingStatus: 1,
+  reportResult: ""
 });
 
-// 驳回表单验证规则
-const rejectRules: FormRules = {
-  reasonRefusal: [
-    { required: true, message: "请输入驳回原因", trigger: "blur" },
-    { min: 2, max: 200, message: "驳回原因长度为2-200个字符", trigger: "blur" }
-  ]
+const rules: FormRules = {
+  processingStatus: [{ required: true, message: "请选择处理结果", trigger: "change" }],
+  reportResult: [{ required: true, message: "请输入处理说明", trigger: "blur" }]
 };
 
-// 表单引用
-const rejectFormRef = ref<FormInstance>();
+const emit = defineEmits<{
+  submit: [{ processingStatus: number; reportResult: string }];
+  close: [];
+}>();
 
-// 事件触发
-const emit = defineEmits(["approve", "reject", "close", "refresh"]);
+const resetForm = () => {
+  reviewForm.processingStatus = 1;
+  reviewForm.reportResult = "";
+  formRef.value?.clearValidate();
+};
 
-// 显示弹窗方法
 const open = (data: any) => {
-  detailData.value = {
-    ...data
-  };
+  detailData.value = { ...data };
+  reviewForm.processingStatus = data?.processingStatus ?? 1;
+  reviewForm.reportResult = data?.reportResult || "";
   dialogShow.value = true;
 };
 
-// 关闭弹窗
-const handleClose = () => {
-  dialogShow.value = false;
-  emit("close");
-};
-
-// 直接确认同意发放尾款
-const confirmApprove = async () => {
-  try {
-    await ElMessageBox.confirm("确认同意发放尾款?", "确认同意", {
-      confirmButtonText: "确认",
-      cancelButtonText: "取消",
-      type: "warning"
+const handleSubmit = async () => {
+  if (!formRef.value) return;
+  await formRef.value.validate(async valid => {
+    if (!valid) return;
+    emit("submit", {
+      processingStatus: reviewForm.processingStatus,
+      reportResult: reviewForm.reportResult.trim()
     });
-
-    // 触发同意事件
-    emit("approve", {
-      id: detailData.value.id,
-      name: detailData.value.name,
-      orderMoney: detailData.value.orderMoney,
-      orderNo: detailData.value.orderNo,
-      storeTel: detailData.value.storeTel,
-      userPhone: detailData.value.userPhone,
-      endPayment: detailData.value.endPayment
-    });
-
-    // 关闭弹窗并通知刷新
-    dialogShow.value = false;
-    emit("refresh");
-  } catch (error) {
-    // 用户取消,不执行操作
-  }
-};
-
-// 打开驳回原因弹窗
-const openRejectDialog = () => {
-  rejectForm.reasonRefusal = "";
-  rejectDialogVisible.value = true;
-};
-
-// 取消驳回
-const cancelRejectDialog = () => {
-  rejectDialogVisible.value = false;
+  });
 };
 
-// 确认驳回(二次确认)
-const confirmReject = async () => {
-  if (!rejectFormRef.value) return;
-
-  const valid = await rejectFormRef.value.validate();
-  if (!valid) return;
-
-  try {
-    await ElMessageBox.confirm("确认取消发放尾款?", "确认驳回", {
-      confirmButtonText: "确认",
-      cancelButtonText: "取消",
-      type: "warning"
-    });
-
-    // 触发驳回事件
-    emit("reject", {
-      id: detailData.value.id,
-      name: detailData.value.name,
-      orderMoney: detailData.value.orderMoney,
-      orderNo: detailData.value.orderNo,
-      storeTel: detailData.value.storeTel,
-      userPhone: detailData.value.userPhone,
-      endPayment: detailData.value.endPayment,
-      endPaymentRefusal: rejectForm.reasonRefusal
-    });
-
-    // 关闭所有弹窗并通知刷新
-    rejectDialogVisible.value = false;
-    dialogShow.value = false;
-    emit("refresh");
-  } catch (error) {
-    // 用户取消二次确认
-  }
+const handleClose = () => {
+  dialogShow.value = false;
+  emit("close");
+  resetForm();
 };
 
-// 暴露给父组件的方法
 defineExpose({
   open,
   close: handleClose
 });
 </script>
 
-<style lang="scss" scoped>
-.section-header {
-  padding-left: 5px;
-  margin: 10px 0 12px;
-  font-size: 16px;
-  font-weight: 600;
-  color: #303133;
-  border-left: 3px solid #409eff;
-}
-.metrics-sections {
-  display: flex;
-  gap: 20px;
-  margin-bottom: 15px;
-
-  /* 在小屏幕上自动堆叠 */
-  @media (width <=600px) {
-    flex-direction: column;
-    gap: 10px;
-  }
-}
-.metrics-section {
-  flex: 1;
-  min-width: 0;
-  .section-header {
-    padding-left: 5px;
-    margin: 0 0 8px;
-    font-size: 14px;
-    font-weight: 600;
-    color: #303133;
-    border-left: 3px solid #409eff;
-  }
-}
-.metrics-cards {
-  display: grid;
-  grid-template-columns: 1fr 1fr;
-  gap: 8px;
-}
-.metric-card {
-  padding: 8px 10px;
-  background: #f8f9fa;
-  border: 1px solid #ebeef5;
-  border-radius: 6px;
-  transition: all 0.2s ease;
-  &:hover {
-    background: #f0f7ff;
-    border-color: #d6e4ff;
-  }
+<style scoped lang="scss">
+.review-descriptions {
+  margin-bottom: 16px;
 }
-.metric-label {
-  margin-bottom: 4px;
-  font-size: 12px;
-  font-weight: 500;
-  color: #606266;
-}
-.metric-value {
-  font-size: 15px;
+.block-title {
+  margin-bottom: 8px;
   font-weight: 600;
   color: #303133;
 }
-.review-container {
-  margin-bottom: 15px;
-
-  /* 滚动条样式优化 */
-  &::-webkit-scrollbar {
-    width: 6px;
-  }
-  &::-webkit-scrollbar-track {
-    background: #f1f1f1;
-    border-radius: 3px;
-  }
-  &::-webkit-scrollbar-thumb {
-    background: #c1c1c1;
-    border-radius: 3px;
-  }
-  &::-webkit-scrollbar-thumb:hover {
-    background: #a8a8a8;
-  }
-}
-.review-detail {
-  .introduction {
-    line-height: 1.5;
-    word-break: break-word;
-    white-space: pre-wrap;
-  }
-}
-
-/* 隐藏预览时的操作栏 */
-:deep(.el-image-viewer__btn) {
-  display: none !important;
-}
-
-/* 或者更精确地隐藏操作栏区域 */
-:deep(.el-image-viewer__actions) {
-  display: none !important;
-}
 .image-grid {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
   gap: 8px;
+  margin-bottom: 20px;
 }
-.image-item {
-  aspect-ratio: 1;
-  overflow: hidden;
-}
-.gallery-image {
+.image-grid :deep(.el-image) {
   width: 100%;
   height: 100%;
-  cursor: pointer;
-  object-fit: cover;
-}
-
-/* 调整描述项的间距 */
-:deep(.el-descriptions__label) {
-  font-weight: 600;
-  background-color: #fafafa;
+  overflow: hidden;
+  border-radius: 8px;
 }
-:deep(.el-descriptions__cell) {
-  padding: 10px 20px;
+.review-form {
+  padding-top: 8px;
 }
 </style>