From dee37e4e2bb74bf970189b4eb9967933ddc9be49 Mon Sep 17 00:00:00 2001
From: WindowBird <13870814+windows-bird@user.noreply.gitee.com>
Date: Mon, 10 Nov 2025 14:55:19 +0800
Subject: [PATCH] =?UTF-8?q?=E8=B7=9F=E8=BF=9B=E8=AF=A6=E7=BB=86=E9=A1=B5?=
=?UTF-8?q?=E9=9D=A2=E8=A1=A5=E5=85=85=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/CustomerManagement.vue | 2 +-
components/customer-detail/FollowupTab.vue | 2 +-
pages/customer/follow/detail/index.vue | 233 +++++++++++++++++++++
pages/customer/follow/edit/index.vue | 2 -
4 files changed, 235 insertions(+), 4 deletions(-)
diff --git a/components/CustomerManagement.vue b/components/CustomerManagement.vue
index f9c2bd8..0e02596 100644
--- a/components/CustomerManagement.vue
+++ b/components/CustomerManagement.vue
@@ -95,8 +95,8 @@
电话
+ +
更多
- ›
diff --git a/components/customer-detail/FollowupTab.vue b/components/customer-detail/FollowupTab.vue
index 67461c7..0eac1d6 100644
--- a/components/customer-detail/FollowupTab.vue
+++ b/components/customer-detail/FollowupTab.vue
@@ -30,7 +30,7 @@
🗑️
- ›
+
{{ item.content }}
diff --git a/pages/customer/follow/detail/index.vue b/pages/customer/follow/detail/index.vue
index 1c0de6c..feb97fc 100644
--- a/pages/customer/follow/detail/index.vue
+++ b/pages/customer/follow/detail/index.vue
@@ -62,6 +62,26 @@
+
+
+ 附件
+
+
+ {{ getFileIcon(file.name || file.path) }}
+
+ {{ file.name || getFileNameFromUrl(file.path) }}
+ {{ formatFileSize(file.size) }}
+
+ ›
+
+
+
+
时间信息
@@ -206,6 +226,60 @@ const followupImages = computed(() => {
return [];
});
+// 计算附件列表
+const followupAttachments = computed(() => {
+ const detail = followupDetail.value;
+ const attachments = [];
+
+ const normalizeAttachment = (item) => {
+ if (!item) return null;
+
+ if (typeof item === 'string') {
+ const trimmed = item.trim();
+ if (!trimmed) return null;
+ return {
+ path: trimmed,
+ name: getFileNameFromUrl(trimmed),
+ size: 0
+ };
+ }
+
+ if (typeof item === 'object' && item.path) {
+ return {
+ path: item.path,
+ name: item.name || getFileNameFromUrl(item.path),
+ size: item.size || 0
+ };
+ }
+
+ return null;
+ };
+
+ const attachSources = [
+ detail.attaches,
+ detail.attachments,
+ detail.files
+ ];
+
+ attachSources.forEach((source) => {
+ if (!source) return;
+
+ if (typeof source === 'string') {
+ source.split(',').forEach((url) => {
+ const normalized = normalizeAttachment(url);
+ if (normalized) attachments.push(normalized);
+ });
+ } else if (Array.isArray(source)) {
+ source.forEach((item) => {
+ const normalized = normalizeAttachment(item);
+ if (normalized) attachments.push(normalized);
+ });
+ }
+ });
+
+ return attachments;
+});
+
// 获取页面参数
onLoad((options) => {
if (options && options.followId) {
@@ -360,6 +434,118 @@ const previewFollowupImages = (images, currentIndex) => {
});
};
+// 获取文件名
+function getFileNameFromUrl(url = '') {
+ try {
+ const decodedUrl = decodeURIComponent(url);
+ const parts = decodedUrl.split('/');
+ return parts.pop() || decodedUrl;
+ } catch (err) {
+ return url;
+ }
+}
+
+// 获取文件图标
+function getFileIcon(filename = '') {
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
+ const iconMap = {
+ pdf: '📄',
+ doc: '📝',
+ docx: '📝',
+ xls: '📊',
+ xlsx: '📊',
+ ppt: '📈',
+ pptx: '📈',
+ txt: '📄',
+ zip: '📦',
+ rar: '📦',
+ jpg: '🖼️',
+ jpeg: '🖼️',
+ png: '🖼️',
+ gif: '🖼️',
+ mp4: '🎞️',
+ mp3: '🎵'
+ };
+ return iconMap[ext] || '📁';
+}
+
+// 格式化文件大小
+function formatFileSize(bytes) {
+ if (!bytes || bytes <= 0) return '';
+ const k = 1024;
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+ return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
+}
+
+// 预览或下载附件
+const previewAttachment = (file) => {
+ if (!file || !file.path) {
+ uni.showToast({
+ title: '文件不存在',
+ icon: 'none'
+ });
+ return;
+ }
+
+ const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
+ const filename = file.name || getFileNameFromUrl(file.path);
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
+
+ if (imageExts.includes(ext)) {
+ uni.previewImage({
+ urls: [file.path],
+ current: file.path
+ });
+ return;
+ }
+
+ // #ifdef H5
+ window.open(file.path, '_blank');
+ // #endif
+
+ // #ifdef APP-PLUS
+ if (typeof plus !== 'undefined' && plus.runtime) {
+ plus.runtime.openURL(file.path);
+ return;
+ }
+ // #endif
+
+ // 其他平台尝试下载并打开
+ uni.downloadFile({
+ url: file.path,
+ success: (res) => {
+ if (res.statusCode === 200) {
+ uni.openDocument({
+ filePath: res.tempFilePath,
+ success: () => {
+ console.log('打开附件成功');
+ },
+ fail: (err) => {
+ console.error('打开附件失败:', err);
+ uni.showToast({
+ title: '无法打开此文件',
+ icon: 'none'
+ });
+ }
+ });
+ } else {
+ uni.showToast({
+ title: '下载文件失败',
+ icon: 'none'
+ });
+ }
+ },
+ fail: (err) => {
+ console.error('下载附件失败:', err);
+ uni.showToast({
+ title: '下载文件失败',
+ icon: 'none'
+ });
+ }
+ });
+};
+
// 返回
const handleBack = () => {
uni.navigateBack();
@@ -534,6 +720,53 @@ onMounted(() => {
object-fit: cover;
}
+.attachments-list {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.attachment-item {
+ display: flex;
+ align-items: center;
+ padding: 12px 0;
+ border-bottom: 1px solid #f5f5f5;
+
+ &:last-child {
+ border-bottom: none;
+ padding-bottom: 0;
+ }
+}
+
+.file-icon {
+ font-size: 24px;
+ margin-right: 12px;
+}
+
+.file-info {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.file-name {
+ font-size: 14px;
+ color: #333;
+ word-break: break-word;
+}
+
+.file-size {
+ font-size: 12px;
+ color: #999;
+}
+
+.preview-arrow {
+ font-size: 20px;
+ color: #bbb;
+ margin-left: 12px;
+}
+
.status-badge {
display: inline-block;
padding: 4px 12px;
diff --git a/pages/customer/follow/edit/index.vue b/pages/customer/follow/edit/index.vue
index 4da4b68..0cbd4cc 100644
--- a/pages/customer/follow/edit/index.vue
+++ b/pages/customer/follow/edit/index.vue
@@ -1207,7 +1207,5 @@ const handleCancel = () => {
background-color: #fff;
border-top: 1px solid #e0e0e0;
}
-
-