Files
art-design/src/views/crmpc/highseas/index.vue
T
2025-12-08 11:53:02 +08:00

331 lines
9.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="boxshadow">
<div class="heard">
<div class="heard-title">公海</div>
<el-select
v-model="remindRange"
placeholder="请选择"
class="heard-select"
style="min-width: 120px"
>
<el-option label="全部" value="" />
<el-option label="当天" value="0" />
<el-option label="近三天" value="1" />
<el-option label="近七天" value="2" />
</el-select>
</div>
<div class="table">
<ArtTable
ref="tableRef"
row-key="id"
:loading="loading"
:data="tableData"
:currentPage="pagination.currentPage"
:pageSize="pagination.pageSize"
:total="pagination.total"
:marginTop="10"
@selection-change="handleSelectionChange"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
<template #default>
<el-table-column prop="contacts" label="客户名称"></el-table-column>
<!-- <el-table-column prop="phone" label="电话"></el-table-column>
<el-table-column prop="WhatsApp" label="WhatsApp"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column> -->
<el-table-column prop="follow" label="联系方式" width="240px" show-overflow-tooltip>
<template #default="scope">
<div
>WhatsApp:{{
scope.row.WhatsApp == '' ? ' --' : '【' + scope.row.WhatsApp + ' 】'
}}</div
>
<div>电话:{{ scope.row.phone == '' ? ' --' : '【' + scope.row.phone + ' 】' }}</div>
<div>邮箱:{{ scope.row.email == '' ? ' --' : '【' + scope.row.email + ' 】' }}</div>
</template>
</el-table-column>
<el-table-column prop="magnitude_txt" label="客户商机"></el-table-column>
<el-table-column prop="channel_name" label="渠道"></el-table-column>
<el-table-column prop="country_name" label="国家"></el-table-column>
<el-table-column prop="enter_user_name" label="录单人"></el-table-column>
<el-table-column prop="created_at" label="创建时间"></el-table-column>
<el-table-column fixed="right" label="操作" width="160px">
<template #default="scope">
<div
class="follow-detli"
@click="onDetail(scope.row)"
v-if="hasAuth('highseas@show')"
>
<span class="custom-clock-icon" style="vertical-align: middle; margin-right: 4px">
<i class="iconfont-sys">&#xe70f;</i>
</span>
详情
</div>
<div
class="follow-action"
@click="onFollow(scope.row)"
v-if="hasAuth('highseas@claim')"
>
<span class="custom-clock-icon" style="vertical-align: middle; margin-right: 4px">
<i class="iconfont-sys">&#xe841;</i>
</span>
领单
</div>
</template>
</el-table-column>
</template>
</ArtTable>
</div>
</div>
<el-dialog v-model="detailDialogVisible" title="详情">
<div v-if="detailRow" v-html="detailRow.desc_collect" class="detils-content"></div>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import dayjs from 'dayjs'
import { ElMessageBox } from 'element-plus'
import { CrmService } from '@/api/crmApi'
import { useAuth } from '@/composables/useAuth'
const { hasAuth } = useAuth()
defineOptions({ name: 'CrmHighseas' })
const loading = ref(false)
const pagination = reactive({
currentPage: 1,
pageSize: 10,
total: 0
})
const remindRange = ref('')
const tableData = ref<any[]>([])
watch([remindRange], () => {
pagination.currentPage = 1
gettableList()
})
// 获取列表数据
const gettableList = async () => {
loading.value = true
try {
const { currentPage, pageSize } = pagination
const params: any = {
current: currentPage,
size: pageSize,
seas: 'seas'
}
if (remindRange.value) params.follow_last = remindRange.value
const { data, current, size, total } = await CrmService.getcustomerList(params)
tableData.value = data.map((item: any) => ({
...item
}))
Object.assign(pagination, { currentPage: current, pageSize: size, total })
} catch (error) {
console.error('获取用户列表失败:', error)
} finally {
loading.value = false
}
}
// 选中的行数据
const selectedRows = ref<any[]>([])
// 处理表格行选择变化
const handleSelectionChange = (selection: any[]) => {
selectedRows.value = selection
}
// 处理表格分页变化
const handleSizeChange = (newPageSize: number) => {
pagination.pageSize = newPageSize
gettableList()
}
const handleCurrentChange = (newCurrentPage: number) => {
pagination.currentPage = newCurrentPage
gettableList()
}
const timer = ref(0)
const refreshKey = ref(0)
const detailDialogVisible = ref(false)
const detailRow = ref<any>(null)
onMounted(() => {
gettableList()
timer.value = window.setInterval(() => {
refreshKey.value++
}, 1000)
})
onUnmounted(() => {
if (timer.value) {
clearInterval(timer.value)
}
})
function getCountdown(targetDate: string) {
// 让 refreshKey 成为依赖,确保每秒刷新
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
refreshKey.value
const now = dayjs()
const target = dayjs(targetDate, 'YYYY-MM-DD HH:mm:ss')
if (!target.isValid()) return '时间格式错误'
const diff = target.diff(now)
if (diff <= 0) return '已超时'
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
const hours = Math.floor((diff / (1000 * 60 * 60)) % 24)
const minutes = Math.floor((diff / (1000 * 60)) % 60)
const seconds = Math.floor((diff / 1000) % 60)
return `${days > 0 ? days + '天' : ''}${hours}小时${minutes}分${seconds}秒`
}
function getCountdownClass(targetDate: string) {
const now = dayjs()
const target = dayjs(targetDate, 'YYYY-MM-DD HH:mm:ss')
if (!target.isValid() || target.diff(now) <= 0) {
return 'countdown-danger'
}
return 'countdown-success'
}
const onFollow = async (row: any) => {
ElMessageBox.confirm('确定要领取此客户吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
const res = await CrmService.customerclaim({ customer_id: row.id })
ElMessage.success(res?.message || '提交成功!')
gettableList()
// 你可以在这里调用接口或做后续处理
})
.catch(() => {
// 用户点击了取消
})
}
function processImages(html: string) {
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
doc.querySelectorAll('img').forEach((img) => {
img.style.maxWidth = '100%'
img.style.height = 'auto'
})
return doc.body.innerHTML
}
function onDetail(row: any) {
row.desc_collect = processImages(row.desc_collect) // 处理图片
detailRow.value = row
detailDialogVisible.value = true
}
</script>
<style lang="scss" scoped>
.detils-content {
padding-left: 15px;
img {
max-width: 100% !important;
}
}
.boxshadow {
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 10, 118, 0.1);
background: var(--el-card-bg-color);
padding: 20px;
margin-bottom: 10px;
}
.heard {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
.heard-title {
font-size: 20px;
font-weight: bold;
color: #333;
border-left: 4px solid #3471ff;
padding-left: 12px;
height: 32px;
display: flex;
align-items: center;
}
.heard-date-picker {
width: 120px;
}
.heard-select {
width: 120px;
}
}
.dark {
.card-list {
.art-custom-card {
.iconfont-sys {
background-color: #232323 !important;
}
}
}
}
.table {
:deep(.el-table__empty-block) {
height: 300px !important;
}
:deep(.el-table__header th) {
background: #f7f9fa !important;
color: #333;
font-weight: bold;
}
:deep(.el-table__body tr.custom-table-row td) {
border-bottom: 1px solid #f7f9fa !important;
border-right: 1px solid #f7f9fa !important;
}
:deep(.el-table__body tr td:last-child) {
border-right: none !important;
}
:deep(.el-table__body tr:last-child td) {
border-bottom: none !important;
}
:deep(.el-table__header-wrapper th) {
border-bottom: 1px solid #f7f9fa !important;
border-right: 1px solid #f7f9fa !important;
}
:deep(.el-table__header-wrapper th:last-child) {
border-right: none !important;
}
:deep(.el-table) {
border: 1px solid #f7f9fa !important;
border-radius: 6px;
}
:deep(.el-table th),
:deep(.el-table td) {
text-align: center !important;
}
}
.countdown-danger {
color: #ff0000 !important;
}
.countdown-success {
color: #00a43f !important;
}
.follow-detli {
display: inline-flex;
align-items: center;
cursor: pointer;
color: #00a43f;
padding: 4px 10px;
border-radius: 4px;
transition: background 0.2s;
&:hover {
background: #f5f7fa;
}
}
.follow-action {
display: inline-flex;
align-items: center;
cursor: pointer;
color: #409eff;
padding: 4px 10px;
border-radius: 4px;
transition: background 0.2s;
&:hover {
background: #f5f7fa;
}
}
</style>