From fc10ba09ac226832b8dd59a11b57fc3545503d82 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 05 三月 2026 11:40:19 +0800
Subject: [PATCH] 新增客户详情页面,回访提醒跳转客户详情页面

---
 src/pages/cooperativeOffice/customerManage/detail.vue |  493 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/pages.json                                        |    7 
 src/api/cooperativeOffice/clientVisit.js              |    8 
 src/App.vue                                           |   18 +
 4 files changed, 524 insertions(+), 2 deletions(-)

diff --git a/src/App.vue b/src/App.vue
index bd95a27..124164b 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -57,7 +57,21 @@
     console.log("鐐瑰嚮鎺ㄩ�佹秷鎭�:", msg);
     console.log("瑙f瀽鍚�:", msg.payload.noticeId);
     try {
-      confirmMessage(msg.payload.noticeId, 1).then(res => {
+      if (msg.payload.needMarkRead) {
+        confirmMessage(msg.payload.noticeId, 1).then(res => {
+          if (msg.payload.url) {
+            if (msg.payload.url.indexOf("/") === 0) {
+              uni.navigateTo({
+                url: msg.payload.url,
+              });
+            } else {
+              uni.navigateTo({
+                url: "/" + msg.payload.url,
+              });
+            }
+          }
+        });
+      } else {
         if (msg.payload.url) {
           if (msg.payload.url.indexOf("/") === 0) {
             uni.navigateTo({
@@ -69,7 +83,7 @@
             });
           }
         }
-      });
+      }
     } catch (error) {
       uni.showToast({
         title: "璺緞:" + msg.payload,
diff --git a/src/api/cooperativeOffice/clientVisit.js b/src/api/cooperativeOffice/clientVisit.js
index bd82c9c..d7a9b47 100644
--- a/src/api/cooperativeOffice/clientVisit.js
+++ b/src/api/cooperativeOffice/clientVisit.js
@@ -33,4 +33,12 @@
         url: '/customerVisits/'+ids,
         method: 'delete',
     })
+}
+
+// 鏌ヨ瀹㈡埛妗f璇︾粏
+export function getCustomer(id) {
+    return request({
+        url: '/basic/customer/' + id,
+        method: 'get'
+    })
 }
\ No newline at end of file
diff --git a/src/pages.json b/src/pages.json
index 903b2a7..e5a99cd 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -977,6 +977,13 @@
       }
     },
     {
+      "path": "pages/cooperativeOffice/customerManage/detail",
+      "style": {
+        "navigationBarTitleText": "瀹㈡埛璇︽儏",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/message",
       "style": {
         "navigationBarTitleText": "娑堟伅涓績"
diff --git a/src/pages/cooperativeOffice/customerManage/detail.vue b/src/pages/cooperativeOffice/customerManage/detail.vue
new file mode 100644
index 0000000..e08e729
--- /dev/null
+++ b/src/pages/cooperativeOffice/customerManage/detail.vue
@@ -0,0 +1,493 @@
+<template>
+  <view class="customer-detail-page">
+    <!-- 椤甸潰澶撮儴 -->
+    <PageHeader title="瀹㈡埛璇︽儏"
+                @back="goBack" />
+    <!-- 璇︽儏鍐呭 -->
+    <view class="detail-content">
+      <!-- 瀹㈡埛鍩烘湰淇℃伅 -->
+      <view class="section">
+        <view class="section-title">瀹㈡埛鍩烘湰淇℃伅</view>
+        <view class="info-list">
+          <view class="info-item">
+            <text class="info-label">瀹㈡埛鍚嶇О</text>
+            <text class="info-value">{{ detailData.customerName || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">瀹㈡埛绫诲瀷</text>
+            <text class="info-value">{{ detailData.customerType || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">绾崇◣浜鸿瘑鍒彿</text>
+            <text class="info-value">{{ detailData.taxpayerIdentificationNumber || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">鍏徃鍦板潃</text>
+            <text class="info-value">{{ detailData.companyAddress || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">鍏徃鐢佃瘽</text>
+            <text class="info-value">{{ detailData.companyPhone || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">鑱旂郴浜�</text>
+            <text class="info-value">{{ detailData.contactPerson || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">鑱旂郴鐢佃瘽</text>
+            <text class="info-value">{{ detailData.contactPhone || '-' }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 璺熻繘璁板綍 -->
+      <view class="section">
+        <view class="section-title">
+          <view class="title-left">
+            <up-icon name="clock-fill"
+                     size="16"
+                     color="#409eff" />
+            <text>璺熻繘璁板綍</text>
+          </view>
+          <text class="record-count"
+                v-if="detailData.followUpList && detailData.followUpList.length > 0">
+            鍏眥{ detailData.followUpList.length }}鏉�
+          </text>
+        </view>
+        <view v-if="detailData.followUpList && detailData.followUpList.length > 0"
+              class="follow-up-list">
+          <view v-for="(item, index) in detailData.followUpList"
+                :key="index"
+                class="follow-up-item">
+            <!-- 鏃堕棿杞村乏渚х嚎鏉� -->
+            <view class="timeline-left">
+              <view class="timeline-dot"></view>
+              <view class="timeline-line"
+                    v-if="index !== detailData.followUpList.length - 1"></view>
+            </view>
+            <!-- 鍐呭鍖哄煙 -->
+            <view class="follow-up-content-wrapper">
+              <view class="follow-up-header">
+                <view class="follow-up-info">
+                  <view class="user-info">
+                    <up-icon name="account-fill"
+                             size="14"
+                             color="#909399" />
+                    <text class="follow-up-name">{{ item.followerUserName || '-' }}</text>
+                  </view>
+                  <view class="time-info">
+                    <up-icon name="clock"
+                             size="12"
+                             color="#c0c4cc" />
+                    <text class="follow-up-time">{{ formatDateTime(item.followUpTime) }}</text>
+                  </view>
+                </view>
+                <view class="follow-up-tags">
+                  <up-tag type="primary"
+                          size="mini">{{ item.followUpMethod || '-' }}</up-tag>
+                  <up-tag :type="getFollowUpLevelType(item.followUpLevel)"
+                          size="mini">{{ item.followUpLevel || '-' }}</up-tag>
+                </view>
+              </view>
+              <view class="follow-up-content">
+                <view class="content-label">
+                  <up-icon name="edit-pen-fill"
+                           size="12"
+                           color="#c0c4cc" />
+                  <text>璺熻繘鍐呭</text>
+                </view>
+                <view class="content-box">
+                  <text class="content-text">{{ item.content || '-' }}</text>
+                </view>
+              </view>
+              <!-- <view v-if="item.fileList && item.fileList.length > 0"
+                    class="follow-up-files">
+                <view class="files-header">
+                  <up-icon name="folder-open"
+                           size="12"
+                           color="#c0c4cc" />
+                  <text class="files-label">闄勪欢 ({{ item.fileList.length }})</text>
+                </view>
+                <view class="files-list">
+                  <view v-for="(file, fileIndex) in item.fileList"
+                        :key="fileIndex"
+                        class="file-item">
+                    <up-icon name="attach"
+                             size="14"
+                             color="#409eff" />
+                    <text class="file-name">{{ file.name || '闄勪欢' + (fileIndex + 1) }}</text>
+                  </view>
+                </view>
+              </view> -->
+            </view>
+          </view>
+        </view>
+        <view v-else
+              class="no-data">
+          <up-empty mode="data"
+                    text="鏆傛棤璺熻繘璁板綍" />
+        </view>
+      </view>
+      <!-- 閾惰淇℃伅 -->
+      <view class="section">
+        <view class="section-title">閾惰淇℃伅</view>
+        <view class="info-list">
+          <view class="info-item">
+            <text class="info-label">鍩烘湰閾惰璐︽埛</text>
+            <text class="info-value">{{ detailData.basicBankAccount || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">寮�鎴疯</text>
+            <text class="info-value">{{ detailData.bankAccount || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">閾惰璐﹀彿</text>
+            <text class="info-value">{{ detailData.bankCode || '-' }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 缁存姢淇℃伅 -->
+      <view class="section">
+        <view class="section-title">缁存姢淇℃伅</view>
+        <view class="info-list">
+          <view class="info-item">
+            <text class="info-label">缁存姢浜�</text>
+            <text class="info-value">{{ detailData.maintainer || '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">缁存姢鏃堕棿</text>
+            <text class="info-value">{{ formatDateTime(detailData.maintenanceTime) }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+  import { ref, onMounted } from "vue";
+  import PageHeader from "@/components/PageHeader.vue";
+  import { getCustomer } from "@/api/cooperativeOffice/clientVisit";
+  import { onLoad, onShow } from "@dcloudio/uni-app";
+  import dayjs from "dayjs";
+
+  // 鑾峰彇椤甸潰鍙傛暟
+  const getPageId = () => {
+    const pages = getCurrentPages();
+    const currentPage = pages[pages.length - 1];
+    const options = currentPage.options || {};
+    return options.id || "";
+  };
+
+  // 璇︽儏鏁版嵁
+  const detailData = ref({});
+
+  // 鏍煎紡鍖栨棩鏈熸椂闂�
+  const formatDateTime = dateStr => {
+    if (!dateStr) return "-";
+    return dayjs(dateStr).format("YYYY-MM-DD HH:mm:ss");
+  };
+
+  // 鑾峰彇璺熻繘绾у埆鏍囩绫诲瀷
+  const getFollowUpLevelType = level => {
+    switch (level) {
+      case "闈炲父鐔熸倝":
+        return "success";
+      case "鐔熸倝":
+        return "primary";
+      case "涓�鑸�":
+        return "warning";
+      case "涓嶇啛鎮�":
+        return "error";
+      default:
+        return "info";
+    }
+  };
+
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    uni.navigateBack();
+  };
+  const customerId = ref("");
+  // customerId
+  onLoad(options => {
+    // 瑙f瀽customerId
+    if (options.customerId) {
+      customerId.value = options.customerId;
+      getDetail();
+    }
+  });
+
+  // 鑾峰彇璇︽儏鏁版嵁
+  const getDetail = async () => {
+    if (!customerId.value) {
+      uni.showToast({
+        title: "鍙傛暟閿欒",
+        icon: "none",
+      });
+      return;
+    }
+
+    try {
+      uni.showLoading({
+        title: "鍔犺浇涓�...",
+      });
+
+      const res = await getCustomer(customerId.value);
+
+      if (res.code === 200) {
+        detailData.value = res.data;
+      } else {
+        uni.showToast({
+          title: res.msg || "鑾峰彇璇︽儏澶辫触",
+          icon: "none",
+        });
+      }
+    } catch (error) {
+      console.error("鍔犺浇璇︽儏鏁版嵁澶辫触:", error);
+      uni.showToast({
+        title: "缃戠粶閿欒",
+        icon: "none",
+      });
+    } finally {
+      uni.hideLoading();
+    }
+  };
+
+  onMounted(() => {});
+</script>
+
+<style scoped lang="scss">
+  .customer-detail-page {
+    min-height: 100vh;
+    background-color: #f5f5f5;
+  }
+
+  .detail-content {
+    padding: 16px;
+  }
+
+  .section {
+    background: #ffffff;
+    border-radius: 12px;
+    margin-bottom: 16px;
+    overflow: hidden;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+  }
+
+  .section-title {
+    padding: 16px;
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+    border-bottom: 1px solid #f0f0f0;
+  }
+
+  .info-list {
+    padding: 8px 0;
+  }
+
+  .info-item {
+    display: flex;
+    padding: 12px 16px;
+    border-bottom: 1px solid #f8f8f8;
+  }
+
+  .info-item:last-child {
+    border-bottom: none;
+  }
+
+  .info-label {
+    width: 120px;
+    font-size: 14px;
+    color: #606266;
+  }
+
+  .info-value {
+    flex: 1;
+    font-size: 14px;
+    color: #303133;
+    text-align: right;
+  }
+
+  .section-title {
+    padding: 16px;
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+    border-bottom: 1px solid #f0f0f0;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+
+  .title-left {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+  }
+
+  .record-count {
+    font-size: 12px;
+    color: #909399;
+    font-weight: normal;
+    background: #f5f7fa;
+    padding: 2px 8px;
+    border-radius: 10px;
+  }
+
+  .follow-up-list {
+    padding: 0;
+  }
+
+  .follow-up-item {
+    display: flex;
+    padding: 16px;
+    position: relative;
+  }
+
+  .timeline-left {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    margin-right: 12px;
+    padding-top: 4px;
+  }
+
+  .timeline-dot {
+    width: 10px;
+    height: 10px;
+    border-radius: 50%;
+    background: #409eff;
+    border: 2px solid #e6f2ff;
+    flex-shrink: 0;
+  }
+
+  .timeline-line {
+    width: 2px;
+    flex: 1;
+    background: #e4e7ed;
+    margin-top: 4px;
+    min-height: 40px;
+  }
+
+  .follow-up-content-wrapper {
+    flex: 1;
+    background: #f8f9fa;
+    border-radius: 8px;
+    padding: 12px;
+  }
+
+  .follow-up-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    margin-bottom: 12px;
+  }
+
+  .follow-up-info {
+    display: flex;
+    flex-direction: column;
+    gap: 6px;
+  }
+
+  .user-info {
+    display: flex;
+    align-items: center;
+    gap: 6px;
+  }
+
+  .time-info {
+    display: flex;
+    align-items: center;
+    gap: 4px;
+  }
+
+  .follow-up-name {
+    font-size: 14px;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  .follow-up-time {
+    font-size: 12px;
+    color: #909399;
+  }
+
+  .follow-up-tags {
+    display: flex;
+    gap: 6px;
+    flex-wrap: wrap;
+  }
+
+  .follow-up-content {
+    margin-bottom: 12px;
+  }
+
+  .content-label {
+    display: flex;
+    align-items: center;
+    gap: 4px;
+    font-size: 12px;
+    color: #909399;
+    margin-bottom: 8px;
+  }
+
+  .content-box {
+    background: #ffffff;
+    border-radius: 6px;
+    padding: 10px 12px;
+    border-left: 3px solid #409eff;
+  }
+
+  .content-text {
+    font-size: 14px;
+    color: #303133;
+    line-height: 1.6;
+    word-break: break-all;
+    word-wrap: break-word;
+  }
+
+  .follow-up-files {
+    margin-top: 12px;
+    padding-top: 12px;
+    border-top: 1px dashed #e4e7ed;
+  }
+
+  .files-header {
+    display: flex;
+    align-items: center;
+    gap: 4px;
+    margin-bottom: 8px;
+  }
+
+  .files-label {
+    font-size: 12px;
+    color: #909399;
+  }
+
+  .files-list {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+  }
+
+  .file-item {
+    display: flex;
+    align-items: center;
+    gap: 4px;
+    padding: 6px 10px;
+    background: #ffffff;
+    border: 1px solid #e4e7ed;
+    border-radius: 4px;
+  }
+
+  .file-name {
+    font-size: 12px;
+    color: #606266;
+  }
+
+  .no-data {
+    padding: 40px 20px;
+    text-align: center;
+  }
+</style>
\ No newline at end of file

--
Gitblit v1.9.3