v1.0.2 更新内容

This commit is contained in:
浅念
2025-08-15 16:31:55 +08:00
parent f5deb7b8f7
commit 0e84bedb67
21 changed files with 2977 additions and 319 deletions
+221 -12
View File
@@ -3,17 +3,22 @@
<!-- 顶部操作栏 -->
<div class="customer-toolbar boxshadow">
<div class="customer-search-group">
<el-select
v-model="selectValue"
style="min-width: 120px"
filterable
multiple
collapse-tags
placeholder="请选择跟单人"
>
<el-option v-for="v in userOptions" :key="v.id" :label="v.name" :value="v.id">
</el-option>
</el-select>
<el-form-item label="关键字:" label-width="70px">
<el-input style="min-width: 120px" v-model="keyword" placeholder="请输入关键字" />
</el-form-item>
<el-form-item label="跟单人" label-width="70px">
<el-select
v-model="selectValue"
style="min-width: 120px"
filterable
multiple
collapse-tags
placeholder="请选择跟单人"
>
<el-option v-for="v in userOptions" :key="v.id" :label="v.name" :value="v.id">
</el-option>
</el-select>
</el-form-item>
</div>
<el-button type="primary" @click="exportfn" v-if="hasAuth('customer@export')">
<i class="iconfont-sys">&#xe89f;</i> 导出
@@ -103,6 +108,7 @@
>
<template #default>
<el-table-column type="selection" width="55px" align="center"></el-table-column>
<el-table-column prop="code" label="编号" align="center" />
<el-table-column prop="contacts" label="客户名称" align="center" />
<el-table-column prop="magnitude_txt" label="客户商机" align="center" />
<el-table-column prop="channel_name" label="渠道" align="center" />
@@ -142,6 +148,15 @@
>
<i class="iconfont-sys"> &#xe794;</i>转移
</el-link>
<el-link
type="warning"
underline="never"
style="margin-right: 8px"
@click="gofollowdetail(scope.row)"
v-if="hasAuth('customer@follow_detail')"
>
<i class="iconfont-sys"> &#xe64e;</i>跟进记录
</el-link>
</template>
</el-table-column>
</template>
@@ -232,6 +247,64 @@
</div>
</el-form>
</el-dialog>
<!-- 跟进记录对话框 -->
<el-dialog v-model="followRecordDialogVisible" title="跟进记录" width="800px">
<!-- 跟进记录列表 -->
<div class="follow-record-list">
<ElScrollbar>
<template v-if="followRecords.length > 0">
<ElTimeline>
<ElTimelineItem
v-for="item in followRecords"
:key="item.time"
:placement="TIMELINE_PLACEMENT"
:color="activecolor"
:center="true"
>
<div class="timeline-item">
<div class="timeline-content-row">
<div class="timeline-content">
<p class="timeline-text"
>{{ item.type_txt }}
<span class="timeline-mom">{{ item.created_at }}</span></p
>
<p class="timeline-mom"
><span v-if="item.type == 1">跟进描述</span><span v-else>拜访内容</span>
{{ item.audio_text }}</p
>
</div>
<img
v-if="item.picture_full"
:src="item.picture_full"
class="timeline-img"
alt="图片"
@click="handleImageClick(item.picture_full)"
style="cursor: pointer;"
/>
</div>
</div>
</ElTimelineItem>
</ElTimeline>
</template>
<template v-else>
<!-- 使用 Element Plus 的空状态组件 -->
<el-empty :image="emptyimg" description="暂无跟进记录" />
<!-- <el-empty /> -->
<!-- 或者自定义图片 -->
<!-- <img src="你的空图片地址.png" alt="暂无数据" class="empty-img" /> -->
</template>
</ElScrollbar>
</div>
</el-dialog>
<!-- 图片预览对话框 -->
<el-image-viewer
v-if="imageViewerVisible"
:url-list="imageList"
:initial-index="imageViewerIndex"
@close="closeImageViewer"
/>
</template>
<script setup lang="ts">
@@ -239,6 +312,9 @@
import { CrmService } from '@/api/crmApi'
import { manageService } from '@/api/adminApi'
import { useAuth } from '@/composables/useAuth'
import emptyimg from '@/assets/img/crm/empty.png'
const TIMELINE_PLACEMENT = 'top'
const activecolor = '#3471ff'
const { hasAuth } = useAuth()
const selectValue = ref<string[]>([])
const showMore = ref(false)
@@ -246,7 +322,15 @@
const detailDialogVisible = ref(false)
const zyDialogVisible = ref(false)
const plzyDialogVisible = ref(false)
const followRecordDialogVisible = ref(false)
const detailRow = ref<any>(null)
const currentCustomer = ref<any>(null)
const followRecords = ref<any[]>([])
const keyword = ref<string>('')
// 图片预览相关
const imageViewerVisible = ref(false)
const imageList = ref<string[]>([])
const imageViewerIndex = ref(0)
const pagination = reactive({
currentPage: 1,
pageSize: 10,
@@ -294,7 +378,7 @@
tagGrouplistfn()
})
// tabs 切换联动
watch([selectValue], () => {
watch([selectValue, keyword], () => {
pagination.currentPage = 1
gettableList()
})
@@ -309,6 +393,9 @@
if (selectValue.value && selectValue.value.length) {
params.user_id = selectValue.value.join(',')
}
if (keyword.value) {
params.keyword = keyword.value
}
// 标签参数,所有选中的标签id组成数组
const selectedTagIds = Object.values(tagActiveMap).filter(Boolean)
if (selectedTagIds.length) {
@@ -400,6 +487,27 @@
zyForm.customer_id = row.id
zyDialogVisible.value = true
}
// 跟进记录
const gofollowdetail = async (row: any) => {
currentCustomer.value = row
followRecordDialogVisible.value = true
await manageService.crmCustomerFollow({ id: row.id }).then((res) => {
followRecords.value = res
})
}
// 图片预览相关函数
const handleImageClick = (url: string) => {
imageList.value = [url]
imageViewerIndex.value = 0
imageViewerVisible.value = true
}
const closeImageViewer = () => {
imageViewerVisible.value = false
imageList.value = []
imageViewerIndex.value = 0
}
// 转移
const handlezySubmit = async () => {
const res = await manageService.crmCustomerTransfer({
@@ -431,6 +539,16 @@
</script>
<style scoped lang="scss">
.timeline-img {
width: 180px;
cursor: pointer;
transition: transform 0.2s ease;
&:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
}
:deep(.el-badge) {
--el-badge-size: 16px;
}
@@ -616,4 +734,95 @@
max-width: 100% !important;
}
}
.follow-record-header {
padding: 15px;
background-color: #f5f7fa;
border-radius: 4px;
margin-bottom: 15px;
.customer-info {
display: flex;
align-items: center;
.label {
font-size: 14px;
color: #606266;
margin-right: 5px;
}
.value {
font-size: 14px;
color: #303133;
font-weight: bold;
}
}
}
.follow-record-list {
padding: 15px;
max-height: 500px;
overflow-y: auto;
.list-title {
font-size: 16px;
font-weight: bold;
color: #303133;
margin-bottom: 15px;
padding-left: 10px;
}
.record-item {
background-color: #f5f7fa;
border-radius: 4px;
padding: 10px 15px;
margin-bottom: 10px;
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
.record-type {
font-size: 14px;
color: #3471ff;
font-weight: bold;
background-color: #e6f7ff;
padding: 2px 8px;
border-radius: 4px;
}
.record-time {
font-size: 14px;
color: #909399;
}
.record-user {
font-size: 14px;
color: #3471ff;
font-weight: bold;
}
}
.record-content {
font-size: 14px;
color: #303133;
line-height: 1.6;
margin-bottom: 5px;
}
.record-footer {
.next-follow {
font-size: 14px;
color: #909399;
}
}
}
.no-records {
text-align: center;
color: #909399;
padding: 20px 0;
}
}
</style>