فهرست منبع

律师中台开发完毕

sgc 3 هفته پیش
والد
کامیت
e55dfa36a4

+ 7 - 4
src/api/modules/lawyer.ts

@@ -108,10 +108,13 @@ 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 getAppealPage = (params?: any) => {
+  return http.get(url + `/commentAppeal/getPage`, params);
+};
+export const appealApprove = (params?: any) => {
+  return http.post(url + `/commentAppeal/audit`, params);
+};
 
 //////////////////////////// 导入导出 ////////////////////////////
 //  导入律所数据

+ 60 - 66
src/views/appeal/detailDialog.vue

@@ -1,23 +1,37 @@
 <template>
-  <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-dialog v-model="dialogShow" title="申诉详情" width="70%" class="appeal-detail-dialog" @close="handleClose">
+    <el-descriptions border :column="1" label-width="140px" class="detail-descriptions">
       <el-descriptions-item label="订单编号">
-        {{ detailData.orderNumber || "--" }}
+        {{ detailData.orderNumber }}
+      </el-descriptions-item>
+      <el-descriptions-item label="用户名称">
+        {{ detailData.userName }}
+      </el-descriptions-item>
+      <el-descriptions-item label="用户电话">
+        {{ detailData.userPhone }}
       </el-descriptions-item>
-      <el-descriptions-item label="举报类型">
-        {{ violationDisplay }}
+      <el-descriptions-item label="用户评价">
+        {{ detailData.reviewContent }}
       </el-descriptions-item>
-      <el-descriptions-item label="举报人姓名">
-        {{ detailData.nickname || "--" }}
+      <el-descriptions-item label="评价图片">
+        <div class="image-grid">
+          <el-image
+            v-for="(img, index) in detailData.reviewImgList"
+            :key="`${detailData.id}-${index}`"
+            :src="img"
+            :preview-src-list="detailData.reviewImgList"
+            fit="cover"
+          />
+        </div>
       </el-descriptions-item>
-      <el-descriptions-item label="举报时间">
-        {{ detailData.createdTime || "--" }}
+      <el-descriptions-item label="律师姓名">
+        {{ detailData.lawyerName }}
+      </el-descriptions-item>
+      <el-descriptions-item label="律师电话">
+        {{ detailData.lawyerPhone }}
       </el-descriptions-item>
-      <el-descriptions-item v-if="detailData.processingTime" label="处理时间">
-        {{ detailData.processingTime || "--" }}
+      <el-descriptions-item label="申诉理由">
+        {{ detailData.appealReason }}
       </el-descriptions-item>
       <el-descriptions-item label="当前状态">
         <el-tag v-if="currentStatus" :type="currentStatus.tagType">
@@ -25,27 +39,28 @@
         </el-tag>
         <span v-else> -- </span>
       </el-descriptions-item>
-      <el-descriptions-item label="处理说明">
-        {{ detailData.reportResult || "--" }}
+      <el-descriptions-item label="申诉图片">
+        <div class="image-grid">
+          <el-image
+            v-for="(img, index) in detailData.imgList"
+            :key="`${img}-${index}`"
+            :src="img"
+            :preview-src-list="detailData.imgList"
+            fit="cover"
+          />
+        </div>
+      </el-descriptions-item>
+      <el-descriptions-item label="申诉时间">
+        {{ detailData.appealTime }}
+      </el-descriptions-item>
+      <el-descriptions-item v-if="detailData.appealReviewTime" label="审核时间">
+        {{ detailData.appealReviewTime }}
       </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>
-
     <template #footer>
       <span class="dialog-footer">
-        <el-button type="primary" @click="handleClose">关闭</el-button>
+        <el-button @click="handleClose"> 关闭 </el-button>
       </span>
     </template>
   </el-dialog>
@@ -58,39 +73,21 @@ const dialogShow = ref(false);
 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: "其他原因" }
+  { value: 0, label: "审核中", tagType: "info" },
+  { value: 1, label: "已通过", tagType: "success" },
+  { value: 2, label: "已驳回", tagType: "danger" }
 ] 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 resolveNumber = (value?: number | string | null) => {
+  if (value === null || value === undefined || value === "") return undefined;
+  return typeof value === "string" ? Number(value) : value;
 };
+const getStatusMeta = (status?: number) => statusMeta.find(item => item.value === status);
 
-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 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 statusValue = computed(() =>
+  resolveNumber(detailData.value.status ?? detailData.value.processingStatus ?? detailData.value.appealStatus)
+);
+const currentStatus = computed(() => getStatusMeta(statusValue.value));
 
 const open = (data: any) => {
   detailData.value = { ...data };
@@ -108,9 +105,6 @@ defineExpose({
 </script>
 
 <style scoped lang="scss">
-.detail-descriptions {
-  margin-bottom: 16px;
-}
 .block-title {
   margin-bottom: 8px;
   font-weight: 600;
@@ -118,12 +112,12 @@ defineExpose({
 }
 .image-grid {
   display: grid;
-  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
-  gap: 8px;
+  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
+  gap: 12px;
 }
 .image-grid :deep(.el-image) {
-  width: 100%;
-  height: 100%;
+  width: 80px;
+  height: 80px;
   overflow: hidden;
   border-radius: 8px;
 }

+ 68 - 70
src/views/appeal/index.vue

@@ -1,16 +1,16 @@
 <template>
   <div class="table-box">
     <ProTable ref="proTable" :columns="columns" :request-api="getTableList" :data-callback="dataCallback">
-      <template #processingStatus="scope">
-        <el-tag v-if="getStatusMeta(scope.row.processingStatus)" :type="getStatusMeta(scope.row.processingStatus)?.tagType">
-          {{ getStatusMeta(scope.row.processingStatus)?.label }}
+      <template #status="scope">
+        <el-tag v-if="getStatusMetaInfo(scope.row)" :type="getStatusMetaInfo(scope.row)?.tagType">
+          {{ getStatusMetaInfo(scope.row)?.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.processingStatus == 0" link @click="handleReview(scope.row)">
+        <el-button v-if="isPendingStatus(scope.row)" type="primary" :icon="Setting" link @click="handleReview(scope.row)">
           审核
         </el-button>
       </template>
@@ -29,7 +29,7 @@ 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";
+import { getAppealPage, appealApprove } from "@/api/modules/lawyer";
 
 const proTable = ref<ProTableInstance>();
 
@@ -38,27 +38,21 @@ 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" }
+  { value: 0, label: "审核中", tagType: "info" },
+  { value: 1, label: "已通过", tagType: "success" },
+  { value: 2, label: "已驳回", tagType: "danger" }
 ] 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 resolveNumber = (value?: number | string | null) => {
+  if (value === null || value === undefined || value === "") return undefined;
+  return typeof value === "string" ? Number(value) : value;
 };
 
+const getStatusValue = (row?: any) => resolveNumber(row?.status ?? row?.processingStatus ?? row?.appealStatus);
+const getStatusMeta = (status?: number) => statusMeta.find(item => item.value === status);
+const getStatusMetaInfo = (row?: any) => getStatusMeta(getStatusValue(row));
+const isPendingStatus = (row?: any) => getStatusValue(row) === 0;
+
 const columns = reactive<ColumnProps<any>[]>([
   {
     label: "序号",
@@ -68,66 +62,69 @@ const columns = reactive<ColumnProps<any>[]>([
     fixed: "left" // 固定在左侧
   },
   {
-    label: "律师姓名",
-    prop: "reportedUserName",
-    width: 200,
-    search: { el: "input", tooltip: "请输入律师姓名" },
-    fixed: "left", // 固定在左侧
-    showOverflowTooltip: true
-  },
-  {
     label: "订单编号",
     prop: "orderNumber",
-    width: 220,
-    fixed: "left", // 固定在左侧
+    fixed: "left",
+    search: { el: "input" },
     showOverflowTooltip: true
   },
   {
-    label: "举报类型",
-    prop: "violationReason",
+    label: "用户名称",
+    prop: "userName",
+    width: 180,
     showOverflowTooltip: true,
-    search: {
-      el: "select",
-      props: { clearable: true }
-    },
-    enum: violationTypeMeta as any,
-    render: scope => getViolationDisplay(scope.row)
+    search: { el: "input" }
   },
   {
-    label: "处理说明",
-    prop: "reportResult",
-    width: 200,
-    align: "center"
+    label: "用户电话",
+    prop: "userPhone",
+    width: 180,
+    showOverflowTooltip: true,
+    search: { el: "input" }
   },
   {
-    label: "举报人姓名",
-    prop: "nickname",
+    label: "律师姓名",
+    prop: "lawyerName",
     width: 200,
-    align: "center"
+    search: { el: "input" },
+    showOverflowTooltip: true
   },
   {
-    label: "举报时间",
-    prop: "createdTime",
-    width: 200,
-    align: "center"
+    label: "律师电话",
+    prop: "lawyerPhone",
+    width: 180,
+    showOverflowTooltip: true,
+    search: { el: "input" }
   },
   {
-    label: "当前状态",
-    prop: "processingStatus",
-    width: 100,
+    label: "状态",
+    prop: "status",
+    width: 120,
     search: {
       el: "select",
-      tooltip: "请选择状态",
       props: { clearable: true }
     },
-    enum: [
-      { value: 0, label: "未处理" },
-      { value: 1, label: "违规" },
-      { value: 2, label: "未违规" }
-    ],
+    enum: statusMeta as any,
     fieldNames: { label: "label", value: "value" }
   },
   {
+    label: "举报时间",
+    prop: "createdTime",
+    width: 200,
+    align: "center",
+    search: {
+      el: "date-picker",
+      props: {
+        type: "datetimerange",
+        valueFormat: "YYYY-MM-DD",
+        rangeSeparator: "至",
+        startPlaceholder: "开始时间",
+        endPlaceholder: "结束时间"
+      }
+    },
+    showOverflowTooltip: true
+  },
+  {
     label: "操作",
     prop: "operation",
     width: 200,
@@ -137,13 +134,14 @@ const columns = reactive<ColumnProps<any>[]>([
 
 const getTableList = async (params: any) => {
   const newParams = {
-    ...params,
-    page: params.pageNum,
-    size: params.pageSize
+    ...params
   };
-  delete newParams.pageNum;
-  delete newParams.pageSize;
-  const res = await getViolationPage(newParams);
+  if (Array.isArray(newParams.createdTime) && newParams.createdTime.length === 2) {
+    newParams.startTime = newParams.createdTime[0];
+    newParams.endTime = newParams.createdTime[1];
+  }
+  delete newParams.createdTime;
+  const res = await getAppealPage(newParams);
   return res;
 };
 
@@ -165,13 +163,13 @@ const handleReview = (row: any) => {
   reviewDialog.value?.open(row);
 };
 
-const handleReviewSubmit = async (payload: { processingStatus: number; reportResult: string }) => {
+const handleReviewSubmit = async (payload: { status: number; reviewReasons: string }) => {
   if (!currentRow.value) return;
   try {
-    await violationApprove({
+    await appealApprove({
       id: currentRow.value.id,
-      processingStatus: payload.processingStatus,
-      reportResult: payload.reportResult
+      status: payload.status,
+      reviewReasons: payload.reviewReasons?.trim()
     });
     ElMessage.success("审核结果已提交");
     reviewDialog.value?.close?.();

+ 85 - 126
src/views/appeal/reviewDialog.vue

@@ -1,23 +1,37 @@
 <template>
-  <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-dialog v-model="dialogShow" title="申诉审核" width="70%" class="appeal-review-dialog" @close="handleClose">
+    <el-descriptions border :column="1" label-width="140px" class="review-descriptions">
       <el-descriptions-item label="订单编号">
-        {{ detailData.orderNumber || "--" }}
+        {{ detailData.orderNumber }}
       </el-descriptions-item>
-      <el-descriptions-item label="举报人姓名">
-        {{ detailData.nickname || "--" }}
+      <el-descriptions-item label="用户名称">
+        {{ detailData.userName }}
       </el-descriptions-item>
-      <el-descriptions-item label="举报类型">
-        {{ violationDisplay }}
+      <el-descriptions-item label="用户电话">
+        {{ detailData.userPhone }}
       </el-descriptions-item>
-      <el-descriptions-item label="举报时间">
-        {{ detailData.createdTime || "--" }}
+      <el-descriptions-item label="用户评价">
+        {{ detailData.reviewContent }}
       </el-descriptions-item>
-      <el-descriptions-item v-if="detailData.processingTime" label="处理时间">
-        {{ detailData.processingTime || "--" }}
+      <el-descriptions-item label="评价图片">
+        <div class="image-grid">
+          <el-image
+            v-for="(img, index) in detailData.reviewImgList"
+            :key="`${detailData.id}-${index}`"
+            :src="img"
+            :preview-src-list="detailData.reviewImgList"
+            fit="cover"
+          />
+        </div>
+      </el-descriptions-item>
+      <el-descriptions-item label="律师姓名">
+        {{ detailData.lawyerName }}
+      </el-descriptions-item>
+      <el-descriptions-item label="律师电话">
+        {{ detailData.lawyerPhone || "--" }}
+      </el-descriptions-item>
+      <el-descriptions-item label="申诉理由">
+        {{ detailData.appealReason }}
       </el-descriptions-item>
       <el-descriptions-item label="当前状态">
         <el-tag v-if="currentStatus" :type="currentStatus.tagType">
@@ -25,138 +39,95 @@
         </el-tag>
         <span v-else> -- </span>
       </el-descriptions-item>
-      <el-descriptions-item label="举报描述" :span="2">
-        {{ detailData.otherReasonContent || "暂无" }}
+      <el-descriptions-item label="申诉图片">
+        <div class="image-grid">
+          <el-image
+            v-for="(img, index) in detailData.imgList"
+            :key="`${img}-${index}`"
+            :src="img"
+            :preview-src-list="detailData.imgList"
+            fit="cover"
+          />
+        </div>
+      </el-descriptions-item>
+      <el-descriptions-item label="申诉时间">
+        {{ detailData.appealTime }}
+      </el-descriptions-item>
+      <el-descriptions-item v-if="detailData.appealReviewTime" label="审核时间">
+        {{ detailData.appealReviewTime }}
       </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>
-
-    <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 @click="handleClose">取消</el-button>
-        <el-button type="primary" @click="handleSubmit">提交</el-button>
+        <el-button type="primary" @click="handleApprove"> 同意 </el-button>
+        <el-button type="danger" @click="handleReject"> 驳回 </el-button>
+        <el-button @click="handleClose"> 取消 </el-button>
       </span>
     </template>
   </el-dialog>
 </template>
 
 <script setup lang="ts">
-import { computed, reactive, ref } from "vue";
-import type { FormInstance, FormRules } from "element-plus";
+import { computed, ref } from "vue";
+import { ElMessageBox } from "element-plus";
 
 const dialogShow = ref(false);
 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" }
+  { value: 0, label: "审核中", tagType: "info" },
+  { value: 1, label: "已通过", tagType: "success" },
+  { value: 2, label: "已驳回", tagType: "danger" }
 ] as const;
 
-const violationTypeMeta = [
-  { value: 1, label: "服务态度差" },
-  { value: 2, label: "专业能力差" },
-  { value: 3, label: "响应时间超过24小时" },
-  { value: 4, label: "其他原因" }
-] as const;
+const APPROVE_STATUS = 1;
+const REJECT_STATUS = 2;
 
-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 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 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 currentStatus = computed(() => {
+  const rawStatus = detailData.value?.status;
+  return statusMeta.find(item => item.value == rawStatus);
 });
 
-const rules: FormRules = {
-  processingStatus: [{ required: true, message: "请选择处理结果", trigger: "change" }],
-  reportResult: [{ required: true, message: "请输入处理说明", trigger: "blur" }]
-};
-
 const emit = defineEmits<{
-  submit: [{ processingStatus: number; reportResult: string }];
+  submit: [{ status: number; reviewReasons: string }];
   close: [];
 }>();
 
-const resetForm = () => {
-  reviewForm.processingStatus = 1;
-  reviewForm.reportResult = "";
-  formRef.value?.clearValidate();
-};
-
 const open = (data: any) => {
   detailData.value = { ...data };
-  reviewForm.processingStatus = data?.processingStatus ?? 1;
-  reviewForm.reportResult = data?.reportResult || "";
   dialogShow.value = true;
 };
 
-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()
+const handleApprove = async () => {
+  try {
+    await ElMessageBox.confirm("确认同意该申诉吗?", "确认操作", {
+      confirmButtonText: "确认同意",
+      cancelButtonText: "取消",
+      type: "success"
     });
-  });
+    emit("submit", { status: APPROVE_STATUS, reviewReasons: "" });
+  } catch (error) {}
+};
+
+const handleReject = async () => {
+  try {
+    const { value } = await ElMessageBox.prompt("请输入驳回原因", "驳回确认", {
+      inputPlaceholder: "请输入驳回原因",
+      confirmButtonText: "确认驳回",
+      cancelButtonText: "取消",
+      inputValidator: val => {
+        if (!val || !val.trim()) return "请输入驳回原因";
+        return true;
+      }
+    });
+    emit("submit", { status: REJECT_STATUS, reviewReasons: value.trim() });
+  } catch (error) {}
 };
 
 const handleClose = () => {
   dialogShow.value = false;
   emit("close");
-  resetForm();
 };
 
 defineExpose({
@@ -166,27 +137,15 @@ defineExpose({
 </script>
 
 <style scoped lang="scss">
-.review-descriptions {
-  margin-bottom: 16px;
-}
-.block-title {
-  margin-bottom: 8px;
-  font-weight: 600;
-  color: #303133;
-}
 .image-grid {
   display: grid;
-  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
-  gap: 8px;
-  margin-bottom: 20px;
+  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
+  gap: 12px;
 }
 .image-grid :deep(.el-image) {
-  width: 100%;
-  height: 100%;
+  width: 80px;
+  height: 80px;
   overflow: hidden;
   border-radius: 8px;
 }
-.review-form {
-  padding-top: 8px;
-}
 </style>

+ 3 - 3
src/views/lawyerManagement/lawyer/index.vue

@@ -55,7 +55,7 @@ const ensureAdmin = () => {
 
 const columns = reactive<ColumnProps<any>[]>([
   { label: "序号", type: "index", width: 60, align: "center" },
-  { label: "律师姓名", prop: "name", width: 110, search: { el: "input", props: { placeholder: "请输入律师姓名" } } },
+  { label: "律师姓名", prop: "name", width: 140, search: { el: "input", props: { placeholder: "请输入律师姓名" } } },
   { label: "联系电话", prop: "phone", width: 140, search: { el: "input", props: { placeholder: "请输入联系电话" } } },
   {
     label: "从业时间",
@@ -83,8 +83,8 @@ const columns = reactive<ColumnProps<any>[]>([
     ],
     fieldNames: { label: "label", value: "value" }
   },
-  { label: "收款账号", prop: "paymentNum" },
-  { label: "所属律所", prop: "firmName" },
+  { label: "收款账号", prop: "paymentNum", width: 220 },
+  { label: "所属律所", prop: "firmName", width: 220 },
   { label: "操作", prop: "operation", width: 200, fixed: "right" }
 ]);
 

+ 9 - 2
src/views/lawyerManagement/reconciliation/detailDialog.vue

@@ -2,7 +2,7 @@
   <el-dialog
     v-model="dialogShow"
     title="订单详情"
-    width="920px"
+    width="60%"
     destroy-on-close
     :close-on-click-modal="false"
     @close="handleClose"
@@ -10,6 +10,12 @@
     <div class="detail-table">
       <ProTable ref="proTable" :data="detailList" :columns="columns" :tool-button="false" :border="true" height="360" />
     </div>
+
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="handleClose"> 关闭 </el-button>
+      </span>
+    </template>
   </el-dialog>
 </template>
 
@@ -25,6 +31,7 @@ const detailList = ref<any[]>([]);
 const currentQuery = ref<String>("");
 
 const columns: ColumnProps[] = [
+  { prop: "index", label: "序号", type: "index", width: 60, align: "center" },
   { label: "用户ID", prop: "clientUserId", minWidth: 120 },
   { label: "用户名", prop: "clientUserName", minWidth: 160, showOverflowTooltip: true },
   { label: "订单编号", prop: "orderNumber", minWidth: 160, showOverflowTooltip: true },
@@ -64,7 +71,7 @@ defineExpose({
 <style scoped lang="scss">
 .detail-table {
   min-height: 360px;
-  max-height: 460px;
+  max-height: 560px;
   overflow: hidden;
 }
 .detail-table :deep(.el-table__body-wrapper) {

+ 12 - 6
src/views/lawyerManagement/reconciliation/index.vue

@@ -60,16 +60,22 @@ const canExport = computed(() => {
   return false;
 });
 
-const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
+const columns = reactive<ColumnProps[]>([
+  { prop: "index", label: "序号", type: "index", width: 60, align: "center" },
   { label: "律所名称", prop: "firmName", minWidth: 280, search: { el: "input", props: { placeholder: "请输入律所名称" } } },
-  { label: "订单数量", prop: "totalOrderCount", width: 160, align: "center" },
-  { label: "订单金额", prop: "totalOrderAmountYuan", width: 200, align: "center" },
-  { label: "平台信息服务费", prop: "platformServiceFeeYuan", width: 220, align: "center" },
+  { label: "订单数量(元)", prop: "totalOrderCount", width: 260, align: "center" },
+  { label: "订单金额(元)", prop: "totalOrderAmountYuan", width: 260, align: "center" },
+  {
+    label: "平台信息服务费",
+    prop: "platformServiceFeeYuan",
+    width: 260,
+    align: "center",
+    render: scope => scope.row.platformServiceFeeYuan * 100 + "%"
+  },
   {
     label: "订单日期",
     prop: "orderTime",
     isShow: false,
-    width: 180,
     search: {
       el: "date-picker",
       props: {
@@ -83,7 +89,7 @@ const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
       }
     }
   },
-  { label: "操作", prop: "operation", width: 160, align: "center", fixed: "right" }
+  { label: "操作", prop: "operation", width: 260, align: "center", fixed: "right" }
 ]);
 const buildQueryParams = (params: any) => {
   const tempParams = { ...params };

+ 12 - 5
src/views/lawyerManagement/reconciliation/lawyerDetail.vue

@@ -86,11 +86,18 @@ const currentFirmId = computed(() => {
   return fallbackFirmId.value;
 });
 
-const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
+const columns = reactive<ColumnProps[]>([
+  { prop: "index", label: "序号", type: "index", width: 60, align: "center" },
   { label: "律师信息", prop: "lawyerName", minWidth: 280, search: { el: "input", props: { placeholder: "请输入律师姓名" } } },
-  { label: "订单数量", prop: "totalOrderCount", width: 160, align: "center" },
-  { label: "订单金额", prop: "totalOrderAmountYuan", width: 200, align: "center" },
-  { label: "平台信息服务费", prop: "platformServiceFeeYuan", width: 220, align: "center" },
+  { label: "订单数量", prop: "totalOrderCount", width: 260, align: "center" },
+  { label: "订单金额", prop: "totalOrderAmountYuan", width: 260, align: "center" },
+  {
+    label: "平台信息服务费",
+    prop: "platformServiceFeeYuan",
+    width: 260,
+    align: "center",
+    render: scope => scope.row.platformServiceFeeYuan * 100 + "%"
+  },
   {
     label: "订单日期",
     prop: "orderTime",
@@ -109,7 +116,7 @@ const columns = reactive<ColumnProps<Course.ReqCourseParams>[]>([
       }
     }
   },
-  { label: "操作", prop: "operation", width: 160, align: "center", fixed: "right" }
+  { label: "操作", prop: "operation", width: 260, align: "center", fixed: "right" }
 ]);
 const buildQueryParams = (params: any) => {
   const tempParams = { ...params };

+ 5 - 9
src/views/refund/detailDialog.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog v-model="dialogShow" title="举报详情" width="760px" @close="handleClose">
+  <el-dialog v-model="dialogShow" title="举报详情" width="70%" class="refund-detail-dialog" @close="handleClose">
     <div v-if="detailData.imageList.length > 0" class="image-gallery">
       <div class="block-title">举报凭证</div>
       <div class="image-grid">
@@ -16,7 +16,7 @@
       </div>
     </div>
 
-    <el-descriptions :column="2" border class="detail-descriptions">
+    <el-descriptions border :column="1" label-width="140px" class="detail-descriptions">
       <el-descriptions-item label="举报理由">
         {{ detailData.reportedUserName || "--" }}
       </el-descriptions-item>
@@ -57,7 +57,7 @@
 
     <template #footer>
       <span class="dialog-footer">
-        <el-button type="primary" @click="handleClose">关闭</el-button>
+        <el-button @click="handleClose"> 关闭 </el-button>
       </span>
     </template>
   </el-dialog>
@@ -110,9 +110,6 @@ defineExpose({
 </script>
 
 <style scoped lang="scss">
-.detail-descriptions {
-  margin-bottom: 16px;
-}
 .block-title {
   margin-bottom: 8px;
   font-weight: 600;
@@ -120,7 +117,6 @@ defineExpose({
 }
 .image-gallery {
   padding: 10px;
-  margin-bottom: 20px;
   background-color: #f5f7fa;
   border-radius: 4px;
   .image-grid {
@@ -128,8 +124,8 @@ defineExpose({
     flex-wrap: wrap;
     gap: 10px;
     .image-item {
-      width: 100px;
-      height: 100px;
+      width: 80px;
+      height: 80px;
       cursor: pointer;
       transition: all 0.3s;
       &:hover {

+ 5 - 6
src/views/refund/index.vue

@@ -72,34 +72,34 @@ const columns = reactive<ColumnProps<any>[]>([
     prop: "orderNumber",
     width: 220,
     fixed: "left", // 固定在左侧
-    search: { el: "input", tooltip: "请输入订单编号" },
+    search: { el: "input" },
     showOverflowTooltip: true
   },
   {
     label: "律师姓名",
     prop: "reportedUserName",
     width: 140,
-    search: { el: "input", tooltip: "请输入律师姓名" },
+    search: { el: "input" },
     fixed: "left", // 固定在左侧
     showOverflowTooltip: true
   },
   {
     label: "律师电话",
     prop: "reportedPhone",
-    search: { el: "input", tooltip: "请输入律师电话" },
+    search: { el: "input" },
     align: "center"
   },
   {
     label: "用户姓名",
     prop: "nickname",
-    search: { el: "input", tooltip: "请输入用户姓名" },
+    search: { el: "input" },
     width: 140,
     align: "center"
   },
   {
     label: "用户电话",
     prop: "phone",
-    search: { el: "input", tooltip: "请输入用户电话" },
+    search: { el: "input" },
     align: "center"
   },
   {
@@ -132,7 +132,6 @@ const columns = reactive<ColumnProps<any>[]>([
     width: 100,
     search: {
       el: "select",
-      tooltip: "请选择状态",
       props: { clearable: true }
     },
     enum: [

+ 17 - 25
src/views/refund/reviewDialog.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog v-model="dialogShow" title="举报审核" width="780px" @close="handleClose">
+  <el-dialog v-model="dialogShow" title="举报审核" width="70%" class="refund-review-dialog" @close="handleClose">
     <div v-if="detailData.imageList.length > 0" class="image-gallery">
       <div class="block-title">举报凭证</div>
       <div class="image-grid">
@@ -16,13 +16,13 @@
       </div>
     </div>
 
-    <el-descriptions :column="2" border class="review-descriptions">
+    <el-descriptions border :column="1" label-width="140px" 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.createdTime || "--" }}
-      </el-descriptions-item>
       <el-descriptions-item label="用户昵称">
         {{ detailData.nickname || "--" }}
       </el-descriptions-item>
@@ -44,11 +44,20 @@
         </el-tag>
         <span v-else> -- </span>
       </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="处理说明">
+        {{ detailData.reportResult || "--" }}
+      </el-descriptions-item>
     </el-descriptions>
 
     <template #footer>
       <span class="dialog-footer">
-        <el-button @click="handleClose">取消</el-button>
+        <el-button @click="handleClose"> 取消 </el-button>
         <el-button type="danger" @click="handleReject"> 驳回 </el-button>
         <el-button type="primary" @click="handleApprove"> 同意 </el-button>
       </span>
@@ -82,16 +91,6 @@ const getViolationMeta = (type?: number | string) => {
   return violationTypeMeta.find(item => item.value === value);
 };
 
-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 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 || "其他原因";
@@ -160,9 +159,6 @@ defineExpose({
 </script>
 
 <style scoped lang="scss">
-.review-descriptions {
-  margin-bottom: 16px;
-}
 .block-title {
   margin-bottom: 8px;
   font-weight: 600;
@@ -170,7 +166,6 @@ defineExpose({
 }
 .image-gallery {
   padding: 10px;
-  margin-bottom: 20px;
   background-color: #f5f7fa;
   border-radius: 4px;
   .image-grid {
@@ -178,8 +173,8 @@ defineExpose({
     flex-wrap: wrap;
     gap: 10px;
     .image-item {
-      width: 100px;
-      height: 100px;
+      width: 80px;
+      height: 80px;
       cursor: pointer;
       transition: all 0.3s;
       &:hover {
@@ -208,7 +203,4 @@ defineExpose({
     }
   }
 }
-.review-form {
-  padding-top: 8px;
-}
 </style>

+ 6 - 4
src/views/userManagement/components/UserDialog.vue

@@ -1,6 +1,6 @@
 <template>
-  <el-dialog v-model="visible" :title="dialogTitle" width="520px" destroy-on-close>
-    <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" label-suffix=":">
+  <el-dialog v-model="visible" :title="dialogTitle" width="640px" destroy-on-close>
+    <el-form ref="formRef" class="dialog-form" :model="form" :rules="rules" label-width="100px" label-suffix=":">
       <el-form-item label="登录账号" prop="userName">
         <el-input v-model="form.userName" placeholder="请输入登录账号" clearable />
       </el-form-item>
@@ -11,7 +11,6 @@
       </el-form-item>
       <el-form-item label="登录密码" prop="userPassword">
         <el-input v-model="form.userPassword" placeholder="请输入登录密码" type="userPassword" show-user-password />
-        <span v-if="isEdit" class="form-tip">若无需修改密码,可留空</span>
       </el-form-item>
       <el-form-item label="账号状态" prop="status">
         <el-switch v-model="form.status" :active-value="1" :inactive-value="0" />
@@ -63,7 +62,6 @@ const form = reactive({
 });
 
 const dialogTitle = computed(() => options.value.title);
-const isEdit = computed(() => options.value.mode === "edit");
 
 const rules = reactive({
   userName: [{ required: true, message: "请输入登录账号", trigger: "blur" }],
@@ -150,6 +148,10 @@ defineExpose({
 </script>
 
 <style scoped lang="scss">
+.dialog-form {
+  max-width: 520px;
+  margin: 0 auto;
+}
 .form-tip {
   display: inline-block;
   margin-left: 12px;