| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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 => { |
| | | // è§£æ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> |