| | |
| | | <el-form-item label="提醒时间:" |
| | | prop="reminderTime"> |
| | | <el-date-picker v-model="reminderForm.reminderTime" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | placeholder="请选择提醒时间" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | |
| | | <!-- 客户详情对话框 --> |
| | | <el-dialog title="客户详情" |
| | | v-model="detailDialogVisible" |
| | | width="800px" |
| | | width="1000px" |
| | | @close="closeDetailDialog"> |
| | | <!-- 客户基本信息 --> |
| | | <div class="detail-section"> |
| | |
| | | label="跟进方式" |
| | | width="100" /> |
| | | <el-table-column prop="followUpLevel" |
| | | label="跟进程度" |
| | | width="120" /> |
| | | label="跟进程度" /> |
| | | <el-table-column prop="followerUserName" |
| | | label="跟进人" |
| | | width="100" /> |
| | | <el-table-column prop="content" |
| | | label="内容" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="附件" |
| | | width="100" |
| | | align="center"> |
| | | <template #default="{ row }"> |
| | | <el-button type="info" |
| | | link |
| | | size="small" |
| | | @click="openAttachmentDialog(row)"> |
| | | <el-icon> |
| | | <Paperclip /> |
| | | </el-icon> |
| | | 附件 |
| | | <!-- {{ row.fileList && row.fileList.length > 0 ? row.fileList.length : '上传' }} --> |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" |
| | | width="150" |
| | | align="center"> |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 附件上传弹窗 --> |
| | | <el-dialog title="附件管理" |
| | | v-model="attachmentDialogVisible" |
| | | width="600px" |
| | | @close="closeAttachmentDialog"> |
| | | <div class="attachment-section"> |
| | | <div class="upload-area"> |
| | | <el-upload ref="attachmentUploadRef" |
| | | :action="getAttachmentUploadUrl()" |
| | | :headers="attachmentUploadHeaders" |
| | | :file-list="currentAttachmentList" |
| | | :on-success="handleAttachmentSuccess" |
| | | :on-error="handleAttachmentError" |
| | | :on-remove="handleAttachmentRemove" |
| | | :before-upload="beforeAttachmentUpload" |
| | | multiple |
| | | :limit="10" |
| | | name="files"> |
| | | <el-button type="primary"> |
| | | <el-icon> |
| | | <Upload /> |
| | | </el-icon> |
| | | 上传附件 |
| | | </el-button> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | | 支持上传图片、文档等文件,单个文件不超过50MB |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </div> |
| | | <div v-if="currentAttachmentList.length > 0" |
| | | class="attachment-list"> |
| | | <h4>已上传附件:</h4> |
| | | <el-table :data="currentAttachmentList" |
| | | border |
| | | size="small"> |
| | | <el-table-column prop="name" |
| | | label="文件名" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="size" |
| | | label="大小" |
| | | width="100"> |
| | | <template #default="{ row }"> |
| | | {{ formatFileSize(row.size) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" |
| | | width="120" |
| | | align="center"> |
| | | <template #default="{ row, $index }"> |
| | | <el-button type="primary" |
| | | link |
| | | size="small" |
| | | @click="downloadAttachment(row)"> |
| | | 下载 |
| | | </el-button> |
| | | <el-button type="danger" |
| | | link |
| | | size="small" |
| | | @click="deleteAttachment(row, $index)"> |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <div v-else |
| | | class="no-attachment"> |
| | | 暂无附件 |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeAttachmentDialog">关闭</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive, getCurrentInstance, toRefs } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { Search, Paperclip, Upload } from "@element-plus/icons-vue"; |
| | | import { |
| | | addCustomer, |
| | | delCustomer, |
| | |
| | | addCustomerFollow, |
| | | updateCustomerFollow, |
| | | delCustomerFollow, |
| | | addReturnVisit, |
| | | getReturnVisit, |
| | | } from "@/api/basicData/customerFile.js"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | |
| | | // 回访提醒相关 |
| | | const reminderDialogVisible = ref(false); |
| | | const reminderFormRef = ref(); |
| | | const currentCustomerId = ref(); |
| | | const reminderForm = reactive({ |
| | | customerName: "", |
| | | reminderSwitch: false, |
| | |
| | | maintenanceTime: "", |
| | | }); |
| | | const negotiationRecords = ref([]); |
| | | |
| | | // 附件相关 |
| | | const attachmentDialogVisible = ref(false); |
| | | const attachmentUploadRef = ref(); |
| | | const currentAttachmentList = ref([]); |
| | | const currentFollowRecord = ref({}); |
| | | const attachmentUploadHeaders = { Authorization: "Bearer " + getToken() }; |
| | | |
| | | // 动态构建上传URL |
| | | const getAttachmentUploadUrl = () => { |
| | | const baseUrl = |
| | | import.meta.env.VITE_APP_BASE_API + "/basic/customer-follow/upload"; |
| | | return currentFollowRecord.value.id |
| | | ? `${baseUrl}/${currentFollowRecord.value.id}` |
| | | : baseUrl; |
| | | }; |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | |
| | | |
| | | // 打开回访提醒弹窗 |
| | | const openReminderDialog = row => { |
| | | currentCustomerId.value = row.id; |
| | | reminderForm.customerName = row.customerName; |
| | | reminderForm.reminderSwitch = false; |
| | | reminderForm.reminderContent = ""; |
| | | reminderForm.reminderTime = ""; |
| | | |
| | | // 尝试获取已有的回访提醒 |
| | | getReturnVisit(row.id) |
| | | .then(res => { |
| | | if (res.code === 200 && res.data) { |
| | | reminderForm.reminderSwitch = res.data.isEnabled === 1; |
| | | reminderForm.reminderContent = res.data.content; |
| | | reminderForm.reminderTime = res.data.reminderTime; |
| | | reminderForm.id = res.data.id; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("获取回访提醒失败:", error); |
| | | }); |
| | | |
| | | reminderDialogVisible.value = true; |
| | | }; |
| | |
| | | proxy.resetForm("reminderFormRef"); |
| | | reminderDialogVisible.value = false; |
| | | }; |
| | | const submitvalue = ref({}); |
| | | |
| | | // 提交回访提醒 |
| | | const submitReminderForm = () => { |
| | | console.log("提交回访提醒数据:", userStore.id, userStore); |
| | | proxy.$refs.reminderFormRef.validate(valid => { |
| | | if (valid) { |
| | | // 这里假设一个接口来提交回访提醒数据 |
| | | // 实际项目中需要根据后端接口进行调整 |
| | | console.log("提交回访提醒数据:", reminderForm); |
| | | if (reminderForm.id) { |
| | | submitvalue.value = { |
| | | id: reminderForm.id, |
| | | customerId: currentCustomerId.value, |
| | | isEnabled: reminderForm.reminderSwitch ? 1 : 0, |
| | | content: reminderForm.reminderContent, |
| | | reminderTime: reminderForm.reminderTime, |
| | | remindUserId: userStore.id, |
| | | }; |
| | | } else { |
| | | submitvalue.value = { |
| | | customerId: currentCustomerId.value, |
| | | isEnabled: reminderForm.reminderSwitch ? 1 : 0, |
| | | content: reminderForm.reminderContent, |
| | | reminderTime: reminderForm.reminderTime, |
| | | remindUserId: userStore.id, |
| | | }; |
| | | } |
| | | |
| | | // 模拟接口调用 |
| | | setTimeout(() => { |
| | | console.log("提交回访提醒数据:", submitvalue.value); |
| | | |
| | | // 调用接口 |
| | | addReturnVisit(submitvalue.value) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("回访提醒设置成功"); |
| | | closeReminderDialog(); |
| | | }, 1000); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "设置失败"); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("设置回访提醒失败:", error); |
| | | proxy.$modal.msgError("设置失败"); |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 打开附件弹窗 |
| | | const openAttachmentDialog = row => { |
| | | currentFollowRecord.value = row; |
| | | // 转换为符合Element Plus fileList格式的数组 |
| | | currentAttachmentList.value = (row.fileList || []).map((file, index) => ({ |
| | | name: file.fileName, |
| | | url: file.fileUrl, |
| | | size: file.fileSize, |
| | | id: file.id, |
| | | uid: file.id || index, |
| | | status: "success", |
| | | })); |
| | | |
| | | attachmentDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 关闭附件弹窗 |
| | | const closeAttachmentDialog = () => { |
| | | attachmentDialogVisible.value = false; |
| | | currentFollowRecord.value = {}; |
| | | currentAttachmentList.value = []; |
| | | }; |
| | | |
| | | // 附件上传成功 |
| | | const handleAttachmentSuccess = (response, file, fileList) => { |
| | | if (response.code === 200) { |
| | | proxy.$modal.msgSuccess("上传成功"); |
| | | // 更新当前记录的附件列表 |
| | | currentAttachmentList.value = fileList.map(item => ({ |
| | | name: item.name, |
| | | size: item.size, |
| | | url: item.response?.data?.url || item.url, |
| | | id: item.response?.data?.id, |
| | | uid: item.uid, |
| | | status: "success", |
| | | })); |
| | | // 更新原记录中的files字段 |
| | | if (currentFollowRecord.value) { |
| | | currentFollowRecord.value.files = [...currentAttachmentList.value]; |
| | | } |
| | | } else { |
| | | proxy.$modal.msgError(response.msg || "上传失败"); |
| | | } |
| | | }; |
| | | |
| | | // 附件上传失败 |
| | | const handleAttachmentError = (error, file, fileList) => { |
| | | console.error("上传失败:", error); |
| | | proxy.$modal.msgError("上传失败"); |
| | | }; |
| | | |
| | | // 附件移除 |
| | | const handleAttachmentRemove = (file, fileList) => { |
| | | currentAttachmentList.value = fileList; |
| | | // 更新原记录中的files字段 |
| | | if (currentFollowRecord.value) { |
| | | currentFollowRecord.value.files = [...fileList]; |
| | | } |
| | | }; |
| | | |
| | | // 附件上传前校验 |
| | | const beforeAttachmentUpload = file => { |
| | | const maxSize = 50 * 1024 * 1024; // 50MB |
| | | if (file.size > maxSize) { |
| | | proxy.$modal.msgError("文件大小不能超过50MB"); |
| | | return false; |
| | | } |
| | | return true; |
| | | }; |
| | | |
| | | // 格式化文件大小 |
| | | const formatFileSize = size => { |
| | | if (size < 1024) { |
| | | return size + " B"; |
| | | } else if (size < 1024 * 1024) { |
| | | return (size / 1024).toFixed(2) + " KB"; |
| | | } else { |
| | | return (size / (1024 * 1024)).toFixed(2) + " MB"; |
| | | } |
| | | }; |
| | | |
| | | // 下载附件 |
| | | const downloadAttachment = row => { |
| | | if (row.url) { |
| | | // proxy.download(row.url, {}, row.name); |
| | | proxy.$download.name(row.url); |
| | | } else { |
| | | proxy.$modal.msgError("下载链接不存在"); |
| | | } |
| | | }; |
| | | |
| | | // 删除附件 |
| | | const deleteAttachment = (row, index) => { |
| | | ElMessageBox.confirm("确定要删除这个附件吗?", "删除提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // 调用后端接口删除附件 |
| | | const deleteUrl = |
| | | import.meta.env.VITE_APP_BASE_API + |
| | | "/basic/customer-follow/file/" + |
| | | row.id; |
| | | fetch(deleteUrl, { |
| | | method: "DELETE", |
| | | headers: { |
| | | Authorization: "Bearer " + getToken(), |
| | | "Content-Type": "application/json", |
| | | }, |
| | | }) |
| | | .then(response => response.json()) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | // 删除成功后更新本地文件列表 |
| | | currentAttachmentList.value.splice(index, 1); |
| | | // 更新原记录中的files字段 |
| | | if (currentFollowRecord.value) { |
| | | currentFollowRecord.value.files = [ |
| | | ...currentAttachmentList.value, |
| | | ]; |
| | | } |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "删除失败"); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("删除附件失败:", error); |
| | | proxy.$modal.msgError("删除失败"); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消删除"); |
| | | }); |
| | | }; |
| | | |
| | | // 获取当前日期并格式化为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | |
| | | color: #999; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .attachment-section { |
| | | .upload-area { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background-color: #f9f9f9; |
| | | border-radius: 4px; |
| | | border: 1px dashed #d9d9d9; |
| | | |
| | | .el-upload__tip { |
| | | margin-top: 10px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .attachment-list { |
| | | h4 { |
| | | margin: 0 0 10px 0; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | } |
| | | |
| | | .no-attachment { |
| | | text-align: center; |
| | | padding: 40px; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | </style> |