From 2c8a663d12ef967a6378d9f38a4224d14201f9d9 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 28 五月 2026 21:53:18 +0800
Subject: [PATCH] chore: 使用 dev_NEW_pro 覆盖当前分支代码

---
 src/views/customerService/feedbackRegistration/index.vue |  523 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 523 insertions(+), 0 deletions(-)

diff --git a/src/views/customerService/feedbackRegistration/index.vue b/src/views/customerService/feedbackRegistration/index.vue
new file mode 100644
index 0000000..1e57bdb
--- /dev/null
+++ b/src/views/customerService/feedbackRegistration/index.vue
@@ -0,0 +1,523 @@
+<template>
+  <div class="app-container">
+    <div class="workorder-stats">
+      <div v-for="(item, index) in statsList"
+           :key="index"
+           class="stat-card">
+        <div class="stat-icon"
+             :style="{ backgroundColor: item.bgColor }">
+          <el-icon :color="item.color"
+                   :size="20">
+            <component :is="item.icon" />
+          </el-icon>
+        </div>
+        <div class="stat-info">
+          <div class="stat-number">{{ item.count }}</div>
+          <div class="stat-label">{{ item.label }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="search-wrapper">
+      <el-form :model="searchForm"
+               class="demo-form-inline">
+        <el-row :gutter="20">
+          <el-col :span="4">
+            <el-form-item>
+              <el-input v-model="searchForm.afterSalesServiceNo"
+                        placeholder="璇疯緭鍏ュ伐鍗曠紪鍙�"
+                        clearable />
+            </el-form-item>
+          </el-col>
+          <el-col :span="4">
+            <el-form-item>
+              <el-select v-model="searchForm.status"
+                         placeholder="璇烽�夋嫨宸ュ崟鐘舵��"
+                         clearable>
+                <el-option v-for="dict in workOrderStatusOptions"
+                           :key="dict.value"
+                           :label="dict.label"
+                           :value="dict.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="4">
+            <el-form-item>
+              <el-select v-model="searchForm.urgency"
+                         placeholder="璇烽�夋嫨绱ф�ョ▼搴�"
+                         clearable>
+                <el-option v-for="dict in degreeOfUrgencyOptions"
+                           :key="dict.value"
+                           :label="dict.label"
+                           :value="dict.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="4">
+            <el-form-item>
+              <el-select v-model="searchForm.serviceType"
+                         placeholder="璇烽�夋嫨鍞悗绫诲瀷"
+                         clearable>
+                <el-option v-for="dict in classificationOptions"
+                           :key="dict.value"
+                           :label="dict.label"
+                           :value="dict.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="4">
+            <el-form-item>
+              <el-input v-model="searchForm.orderNo"
+                        placeholder="璇疯緭鍏ラ攢鍞崟鍙�"
+                        clearable />
+            </el-form-item>
+          </el-col>
+          <!-- 鎸夐挳 -->
+          <el-col :span="4">
+            <el-form-item>
+              <el-button type="primary"
+                         @click="handleQuery">
+                鎼滅储
+              </el-button>
+              <el-button @click="handleReset">
+                閲嶇疆
+              </el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </div>
+    <div class="table_list">
+      <div class="table_header"
+           style="display: flex; justify-content: space-between; align-items: center;">
+        <div>
+          <el-button type="primary"
+                     @click="openForm('add')">鏂板鍞悗鍗�</el-button>
+        </div>
+        <div>
+          <el-button @click="handleOut">瀵煎嚭</el-button>
+          <el-button type="danger"
+                     plain
+                     @click="handleDelete">鍒犻櫎</el-button>
+        </div>
+      </div>
+      <PIMTable rowKey="id"
+                :column="tableColumn"
+                :tableData="tableData"
+                :page="page"
+                :height="tableHeight"
+                :isSelection="true"
+                @selection-change="handleSelectionChange"
+                :tableLoading="tableLoading"
+                @pagination="pagination"></PIMTable>
+    </div>
+    <form-dia ref="formDia"
+              @close="handleQuery"></form-dia>
+  </div>
+</template>
+
+<script setup>
+  import {
+    onMounted,
+    reactive,
+    ref,
+    toRefs,
+    computed,
+    getCurrentInstance,
+    nextTick,
+  } from "vue";
+  import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue";
+  import { ElMessageBox } from "element-plus";
+  import {
+    afterSalesServiceDelete,
+    afterSalesServiceListPage,
+    getSalesLedgerDetail,
+  } from "@/api/customerService/index.js";
+  import useUserStore from "@/store/modules/user.js";
+  const { proxy } = getCurrentInstance();
+  const userStore = useUserStore();
+  import { Document, FolderOpened, UserFilled } from "@element-plus/icons-vue";
+  import { markRaw } from "vue";
+
+  const statsList = ref([
+    {
+      icon: markRaw(Document),
+      count: 0,
+      label: "鍏ㄩ儴宸ュ崟",
+      color: "#4080ff",
+      bgColor: "#eaf2ff",
+    },
+    {
+      icon: markRaw(FolderOpened),
+      count: 0,
+      label: "宸插鐞�",
+      color: "#ff9a2e",
+      bgColor: "#fff5e6",
+    },
+    {
+      icon: markRaw(UserFilled),
+      count: 0,
+      label: "宸插畬鎴�",
+      color: "#00b42a",
+      bgColor: "#e6f7ed",
+    },
+  ]);
+
+  const data = reactive({
+    searchForm: {
+      customerName: "",
+      status: "",
+      urgency: "",
+      serviceType: "",
+      reviewStatus: "",
+      orderNo: "",
+    },
+  });
+  const { searchForm } = toRefs(data);
+
+  const tableColumn = ref([
+    {
+      label: "宸ュ崟缂栧彿",
+      prop: "afterSalesServiceNo",
+      width: 150,
+      align: "center",
+    },
+    {
+      label: "閿�鍞崟鍙�",
+      prop: "salesContractNo",
+      width: 150,
+      align: "center",
+    },
+    {
+      label: "澶勭悊鐘舵��",
+      prop: "status",
+      dataType: "tag",
+
+      formatData: params => {
+        if (params) {
+          let part = String(params);
+          const item = workOrderStatusOptions.value.find(
+            item => item.value === part
+          );
+          return item?.label || params;
+        }
+        return null;
+      },
+      formatType: params => {
+        if (params === 1) {
+          return "danger";
+        } else if (params === 2) {
+          return "success";
+        } else {
+          return null;
+        }
+      },
+      align: "center",
+    },
+    {
+      label: "鍙嶉鏃ユ湡",
+      prop: "feedbackDate",
+      width: 150,
+      align: "center",
+    },
+    {
+      label: "鐧昏浜�",
+      prop: "checkNickName",
+      align: "center",
+    },
+    {
+      label: "绱ф�ョ▼搴�",
+      prop: "urgency",
+      // 鏍规嵁degreeOfUrgencyOptions瀛楀吀鍘昏嚜鍔ㄥ尮閰�
+      formatData: params => {
+        if (params) {
+          const item = degreeOfUrgencyOptions.value.find(
+            item => item.value === params
+          );
+          return item?.label || params;
+        }
+        return null;
+      },
+      align: "center",
+    },
+    {
+      label: "鍞悗绫诲瀷",
+      prop: "serviceType",
+      // 鏍规嵁classificationOptions瀛楀吀鍘昏嚜鍔ㄥ尮閰�
+      formatData: params => {
+        if (params) {
+          const item = classificationOptions.value.find(
+            item => item.value === params
+          );
+          return item?.label || params;
+        }
+        return null;
+      },
+      align: "center",
+    },
+    {
+      label: "瀹㈡埛璇夋眰",
+      prop: "proDesc",
+      width: 300,
+    },
+    {
+      label: "鍏宠仈閮ㄩ棬",
+      prop: "deptName",
+      width: 200,
+      align: "center",
+    },
+    {
+      dataType: "action",
+      label: "鎿嶄綔",
+      fixed: "right",
+      operation: [
+        {
+          name: "缂栬緫",
+          type: "text",
+          clickFun: row => {
+            console.log(row);
+            openForm("edit", row);
+          },
+          disabled: row => {
+            return row.status !== 1;
+          },
+        },
+      ],
+      align: "center",
+    },
+  ]);
+  const tableData = ref([]);
+  const tableLoading = ref(false);
+  const page = reactive({
+    current: 1,
+    size: 100,
+    total: 0,
+  });
+  const selectedRows = ref([]);
+  const tableHeight = computed(() => "calc(100% -80px)");
+
+  const handleReset = () => {
+    Object.keys(searchForm.value).forEach(key => {
+      searchForm.value[key] = "";
+    });
+    page.current = 1;
+    getList();
+  };
+  // 琛ㄦ牸閫夋嫨鏁版嵁
+  const handleSelectionChange = selection => {
+    selectedRows.value = selection;
+  };
+  const formDia = ref();
+
+  // 瀛楀吀鑾峰彇
+  /*
+  post_sale_waiting_list 鏂板鐨勫敭鍚庡垎绫�
+  degree_of_urgency 鏂板鐨勭揣鎬ョ▼搴�
+  work_order_status 涓婚〉鐨勫伐鍗曠姸鎬�
+  review_status 棣栭〉鐨勫鏍哥姸鎬�
+  */
+  const {
+    post_sale_waiting_list,
+    degree_of_urgency,
+    work_order_status,
+    review_status,
+  } = proxy.useDict(
+    "post_sale_waiting_list",
+    "degree_of_urgency",
+    "work_order_status",
+    "review_status"
+  );
+
+  const classificationOptions = computed(
+    () => post_sale_waiting_list?.value || []
+  );
+  const degreeOfUrgencyOptions = computed(() => degree_of_urgency?.value || []);
+  const workOrderStatusOptions = computed(() => work_order_status?.value || []);
+
+  // 鏌ヨ鍒楄〃
+  /** 鎼滅储鎸夐挳鎿嶄綔 */
+  const handleQuery = () => {
+    page.current = 1;
+    getList();
+  };
+  const pagination = obj => {
+    page.current = obj.page;
+    page.size = obj.limit;
+    getList();
+  };
+  const getList = () => {
+    tableLoading.value = true;
+    getSalesLedgerDetails();
+    afterSalesServiceListPage({ ...searchForm.value, ...page }).then(res => {
+      tableLoading.value = false;
+      tableData.value = res.data.records;
+      page.total = res.data.total;
+    });
+  };
+
+  // 鎵撳紑寮规
+  const openForm = (type, row) => {
+    nextTick(() => {
+      formDia.value?.openDialog(type, row);
+    });
+  };
+
+  function handleDelete() {
+    let ids = [];
+    if (selectedRows.value.length > 0) {
+      // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+      const unauthorizedData = selectedRows.value.filter(
+        item => item.checkUserId !== userStore.id
+      );
+      if (unauthorizedData.length > 0) {
+        proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+        return;
+      }
+      ids = selectedRows.value.map(item => item.id);
+    } else {
+      proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+      return;
+    }
+    ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        tableLoading.value = true;
+        afterSalesServiceDelete(ids)
+          .then(() => {
+            proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+            getList();
+          })
+          .finally(() => {
+            tableLoading.value = false;
+          });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+  }
+
+  // 瀵煎嚭
+  const handleOut = () => {
+    ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        proxy.download("/afterSalesService/export", {}, "鍙嶉鐧昏.xlsx");
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+  };
+
+  const getStatsCountByStatus = (list, status) => {
+    if (!Array.isArray(list)) return 0;
+    return list.find(item => item?.status === status)?.count || 0;
+  };
+
+  // 鑾峰彇缁熻鏁版嵁骞跺埛鏂伴《閮ㄥ崱鐗�
+  const getSalesLedgerDetails = () => {
+    getSalesLedgerDetail({}).then(res => {
+      if (res.code === 200) {
+        const statsData = Array.isArray(res.data) ? res.data : [];
+        statsList.value[0].count = getStatsCountByStatus(statsData, 3);
+        statsList.value[1].count = getStatsCountByStatus(statsData, 2);
+        statsList.value[2].count = getStatsCountByStatus(statsData, 1);
+      }
+    });
+  };
+
+  onMounted(() => {
+    getList();
+  });
+</script>
+
+<style scoped lang="scss">
+  .search-wrapper {
+    background: white;
+    padding: 1rem 1rem 0 1rem;
+    border: 8px;
+    border-radius: 16px;
+  }
+
+  .expand-btn {
+    width: 100%;
+    padding: 20px; /* 涓婁笅宸﹀彸鍚�20px锛岀偣鍑昏繖涓寖鍥撮兘鑳借Е鍙戜簨浠� */
+    cursor: pointer; /* 榧犳爣鎮诞鏄剧ず鎵嬪瀷锛屾彁鍗囦綋楠� */
+    text-align: center;
+  }
+
+  .workorder-stats {
+    display: flex;
+    gap: 16px;
+    padding-bottom: 1rem;
+    border-radius: 8px;
+  }
+
+  .stat-card {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    gap: 12px;
+    padding: 20px;
+    background-color: #fff;
+    border-radius: 8px;
+    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
+  }
+
+  .stat-icon {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 48px;
+    height: 48px;
+    border-radius: 8px;
+  }
+
+  .stat-info {
+    display: flex;
+    flex-direction: column;
+    gap: 4px;
+  }
+
+  .stat-number {
+    font-size: 24px;
+    font-weight: 600;
+    color: #303133;
+    line-height: 1;
+  }
+
+  .stat-label {
+    font-size: 14px;
+    color: #909399;
+    line-height: 1;
+  }
+  .table_header {
+    padding-bottom: 10px;
+  }
+
+  .table_list {
+    height: calc(100vh - 380px);
+    background: #fff;
+    margin-top: 20px;
+    display: flex;
+    flex-direction: column;
+  }
+
+  :deep(.table_list .pagination-container) {
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    margin-top: auto;
+    padding: 12px 0 0;
+  }
+
+  :deep(.table_list .el-pagination) {
+    flex-wrap: nowrap;
+    justify-content: flex-end;
+    width: 100%;
+  }
+</style>

--
Gitblit v1.9.3