You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
12 KiB
406 lines
12 KiB
<template>
|
|
<div>
|
|
<div class="relative">
|
|
<el-tabs v-model="queryType" size="small" @tab-change="quickChange">
|
|
<el-tab-pane label="全部" name="0" />
|
|
<el-tab-pane name="1">
|
|
<template #label>
|
|
<Tooltip message="除了无效线索和已成交的线索" />
|
|
<el-badge v-if="clueCount.unSignNum" :value="clueCount.unSignNum" :max="9999">
|
|
<span class="ml-3px">未成交</span>
|
|
</el-badge>
|
|
<span v-else class="ml-3px">未成交</span>
|
|
</template>
|
|
</el-tab-pane>
|
|
<el-tab-pane name="2">
|
|
<template #label>
|
|
<Tooltip message="下次跟进时间在今日及之前的未成交线索" />
|
|
<el-badge v-if="clueCount.followNum" :value="clueCount.followNum" :max="9999">
|
|
<span class="ml-3px">待跟进</span>
|
|
</el-badge>
|
|
<span v-else class="ml-3px">待跟进</span>
|
|
</template>
|
|
</el-tab-pane>
|
|
<el-tab-pane name="3">
|
|
<template #label>
|
|
<Tooltip message="只有创建时间,无下次跟进时间的未成交线索" />
|
|
<el-badge v-if="clueCount.newNum" :value="clueCount.newNum" :max="9999">
|
|
<span class="ml-3px">新线索</span>
|
|
</el-badge>
|
|
<span v-else class="ml-3px">新线索</span>
|
|
</template>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="公海" name="4" />
|
|
<el-tab-pane
|
|
v-if="appStore.getAppInfo?.instanceType == 1"
|
|
label="地图总览"
|
|
name="5"
|
|
style="height: calc(100vh - 160px)"
|
|
>
|
|
<ClueMap ref="mapClue" v-if="queryType == 5" />
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
<div class="absolute" style="right: 10px; top: 0">
|
|
<el-button plain v-hasPermi="['clue:pool:import']">导入</el-button>
|
|
<el-button type="primary" @click="handleInsert" v-hasPermi="['clue:pool:add']">
|
|
新增线索
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
<template v-if="queryType != 5">
|
|
<!-- 搜索工作栏 -->
|
|
<Search v-if="!loading" ref="searchRef" :schema="allSchemas.searchSchema" labelWidth="0">
|
|
<template #actionMore>
|
|
<el-button @click="getTableList" v-hasPermi="['clue:pool:search']"> 搜索 </el-button>
|
|
<el-button @click="resetQuery" v-hasPermi="['clue:pool:reset']"> 重置 </el-button>
|
|
<el-button
|
|
@click="handleBatchChangeFollow"
|
|
v-hasPermi="['clue:pool:batch-update-follow']"
|
|
>
|
|
批量修改跟进人
|
|
</el-button>
|
|
</template>
|
|
</Search>
|
|
<!-- 列表 -->
|
|
<SSTable
|
|
v-if="!loading"
|
|
class="mt-20px"
|
|
v-model:tableObject="tableObject"
|
|
:tableColumns="allSchemas.tableColumns"
|
|
@get-list="getTableList"
|
|
@get-checked-columns="getCheckedColumns"
|
|
@selection-change="handleSelectionChange"
|
|
>
|
|
<el-table-column type="selection" width="60" />
|
|
<el-table-column
|
|
v-for="item in showColumns"
|
|
:key="item.field"
|
|
:prop="item.field"
|
|
:label="item.label"
|
|
min-width="120px"
|
|
>
|
|
<template #default="{ row }">
|
|
<div v-if="item.field == 'followRecord'">
|
|
<el-button
|
|
type="primary"
|
|
text
|
|
style="padding: 0"
|
|
@click="handleFollow(row)"
|
|
v-if="queryType != 4"
|
|
v-hasPermi="['clue:pool:update']"
|
|
>
|
|
快速新增
|
|
</el-button>
|
|
</div>
|
|
<div v-else-if="item.field == 'contact'">
|
|
<span>{{ row[item.field] }}</span>
|
|
<Icon class="ml-5px" icon="ep:phone" @click="makeCall(row.contact)" />
|
|
</div>
|
|
<div v-else-if="item.form?.component == 'DatePicker'">
|
|
<span>{{ formatDate(row[item.field]) }}</span>
|
|
</div>
|
|
<div v-else-if="item.field == 'remark' || item.form?.component == 'Editor'">
|
|
<el-popover placement="top" width="500px" trigger="click" v-if="row[item.field]">
|
|
<template #reference>
|
|
<el-button type="primary" style="padding: 0" text>点击查看</el-button>
|
|
</template>
|
|
<div v-dompurify-html="row[item.field]"></div>
|
|
</el-popover>
|
|
</div>
|
|
<span v-else>{{ row[item.field] }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" width="200px" fixed="right">
|
|
<template #default="scope">
|
|
<el-button
|
|
type="primary"
|
|
link
|
|
@click="handleDetail(scope.row)"
|
|
v-hasPermi="['clue:pool:detail']"
|
|
>
|
|
详情
|
|
</el-button>
|
|
<template v-if="queryType != 4">
|
|
<el-button
|
|
type="primary"
|
|
link
|
|
@click="handleEdit(scope.row)"
|
|
v-hasPermi="['clue:pool:update']"
|
|
>
|
|
修改
|
|
</el-button>
|
|
<el-button
|
|
type="primary"
|
|
link
|
|
:disabled="scope.row.state == '成交'"
|
|
@click="handleSuccess(scope.row)"
|
|
v-hasPermi="['clue:pool:enroll']"
|
|
>
|
|
登记
|
|
</el-button>
|
|
<el-button
|
|
type="primary"
|
|
link
|
|
:disabled="scope.row.state == '成交'"
|
|
v-hasPermi="['clue:pool:release']"
|
|
@click="handleRelease(scope.row.clueId)"
|
|
>
|
|
释放
|
|
</el-button>
|
|
</template>
|
|
<template v-else>
|
|
<el-button
|
|
type="primary"
|
|
link
|
|
v-hasPermi="['clue:pool:gain']"
|
|
@click="handleGain(scope.row.clueId)"
|
|
>
|
|
获取
|
|
</el-button>
|
|
</template>
|
|
</template>
|
|
</el-table-column>
|
|
</SSTable>
|
|
</template>
|
|
|
|
<DialogClue
|
|
v-if="!loading"
|
|
ref="formRef"
|
|
:userOptions="userOptions"
|
|
:allUserOptions="allUserOptions"
|
|
:schema="allSchemas.formSchema"
|
|
@success="getTableList"
|
|
/>
|
|
<DrawerClue
|
|
v-if="!loading"
|
|
ref="drawerRef"
|
|
:schema="allSchemas.detailSchema"
|
|
@get-list="getTableList"
|
|
@update="handleEdit"
|
|
/>
|
|
<DialogSuccess
|
|
ref="successRef"
|
|
:schema="allSchemas.detailSchema"
|
|
:allUserOptions="allUserOptions"
|
|
:userOptions="userOptions"
|
|
@success="getTableList"
|
|
/>
|
|
<DialogFollow ref="followRef" @success="getTableList" />
|
|
<DialogBatchChangeFollow
|
|
ref="batchChangeFollowDialog"
|
|
:userOptions="allStatusUserOptions"
|
|
@success="getTableList"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup name="CluePool">
|
|
import { useAppStore } from '@/store/modules/app'
|
|
import { getSimpleFieldList } from '@/api/clue/clueField'
|
|
import DialogClue from './Comp/DialogClue.vue'
|
|
import DrawerClue from './Comp/DrawerClue.vue'
|
|
import DialogSuccess from './Comp/DialogSuccess.vue'
|
|
import DialogFollow from './Comp/DialogFollow.vue'
|
|
import ClueMap from './Comp/ClueMap.vue'
|
|
import DialogBatchChangeFollow from './Comp/DialogBatchChangeFollow.vue'
|
|
import {
|
|
getSimpleUserList as getUserOption,
|
|
getAllUserList,
|
|
getAllUserListWithHire
|
|
} from '@/api/system/user'
|
|
|
|
import { removeNullField } from '@/utils'
|
|
import { formatDate } from '@/utils/formatTime'
|
|
|
|
import * as ClueApi from '@/api/clue'
|
|
|
|
const message = useMessage() // 消息弹窗
|
|
const appStore = useAppStore()
|
|
|
|
const searchRef = ref()
|
|
const queryType = ref('2')
|
|
|
|
const formRef = ref()
|
|
const drawerRef = ref()
|
|
const successRef = ref()
|
|
const followRef = ref()
|
|
|
|
const loading = ref(true)
|
|
|
|
const allSchemas = ref({})
|
|
|
|
async function getCurdSchemas() {
|
|
loading.value = true
|
|
try {
|
|
const data = await getSimpleFieldList()
|
|
data.forEach((elem) => {
|
|
if (['followUser', 'convertPeople'].includes(elem.field)) {
|
|
elem.search.options = userOptions.value
|
|
} else if (['firstFollowUser'].includes(elem.field)) {
|
|
elem.search.options = allStatusUserOptions.value
|
|
}
|
|
})
|
|
allSchemas.value = useCrudSchemas(data).allSchemas
|
|
} finally {
|
|
loading.value = false
|
|
nextTick(() => {
|
|
getTableList()
|
|
})
|
|
}
|
|
}
|
|
|
|
const tableObject = ref({
|
|
tableList: [],
|
|
loading: false,
|
|
total: 1,
|
|
pageSize: 20,
|
|
pageNo: 1
|
|
})
|
|
|
|
const showColumns = ref([])
|
|
|
|
// 初始化表格
|
|
function getCheckedColumns(list) {
|
|
showColumns.value = list && list.length ? list : allSchemas.value.tableColumns
|
|
}
|
|
|
|
const mapClue = ref()
|
|
function quickChange(name) {
|
|
try {
|
|
if (name != '5') {
|
|
resetQuery()
|
|
mapClue.value && mapClue.value.destroyMap()
|
|
}
|
|
} catch (error) {
|
|
console.log(error)
|
|
}
|
|
}
|
|
|
|
function resetQuery() {
|
|
nextTick(() => {
|
|
searchRef.value && searchRef.value.reset()
|
|
tableObject.value.pageNo = 1
|
|
getTableList()
|
|
})
|
|
}
|
|
|
|
async function getTableList() {
|
|
// 查询
|
|
tableObject.value.loading = true
|
|
getSearchCount()
|
|
try {
|
|
const queryParams = await searchRef.value.getFormModel()
|
|
const params = {
|
|
...queryParams,
|
|
pageNo: tableObject.value.pageNo,
|
|
pageSize: tableObject.value.pageSize,
|
|
queryType: queryType.value
|
|
}
|
|
const data = await ClueApi.getCluePage(removeNullField(params))
|
|
tableObject.value.tableList = data.list.map((it) => ({ ...it, ...it.diyParams }))
|
|
tableObject.value.total = data.total
|
|
} finally {
|
|
tableObject.value.loading = false
|
|
}
|
|
}
|
|
|
|
const clueCount = ref({
|
|
unSignNum: 0,
|
|
followNum: 0,
|
|
newNum: 0
|
|
})
|
|
function getSearchCount() {
|
|
ClueApi.getClueCount().then((data) => {
|
|
clueCount.value = data
|
|
})
|
|
}
|
|
|
|
const batchIds = ref([])
|
|
function handleSelectionChange(val) {
|
|
batchIds.value = val.map((it) => it.clueId)
|
|
}
|
|
|
|
const batchChangeFollowDialog = ref()
|
|
function handleBatchChangeFollow() {
|
|
if (batchIds.value.length) {
|
|
batchChangeFollowDialog.value.open(batchIds.value)
|
|
} else {
|
|
message.info('请选择表格中的数据!')
|
|
}
|
|
}
|
|
|
|
// 新增
|
|
function handleInsert() {
|
|
formRef.value.open('create', null)
|
|
}
|
|
// 编辑
|
|
function handleEdit(row) {
|
|
formRef.value.open('update', row.clueId)
|
|
}
|
|
// 详情
|
|
function handleDetail(row) {
|
|
drawerRef.value.open(row.clueId)
|
|
}
|
|
|
|
function handleFollow(row) {
|
|
followRef.value.open(row.clueId, row.intentionState)
|
|
}
|
|
|
|
async function makeCall(phone) {
|
|
console.log('打电话:' + phone)
|
|
}
|
|
|
|
// 登记
|
|
function handleSuccess(row) {
|
|
successRef.value.open(row.clueId)
|
|
}
|
|
|
|
// 释放
|
|
function handleRelease(id) {
|
|
message.prompt('请先输入释放原因', '是否确认释放线索?').then((res) => {
|
|
if (res.value) {
|
|
try {
|
|
ClueApi.releaseClue({
|
|
clueId: id,
|
|
publicClue: true,
|
|
discardReason: res.value
|
|
}).then(() => {
|
|
message.success('释放成功')
|
|
})
|
|
} finally {
|
|
getTableList()
|
|
}
|
|
} else {
|
|
message.info('请将释放原因填写完整!')
|
|
}
|
|
})
|
|
}
|
|
|
|
function handleGain(id) {
|
|
message.confirm('是否确认获取公海线索?').then(() => {
|
|
try {
|
|
ClueApi.getPublicClue({
|
|
clueId: id,
|
|
publicClue: false
|
|
}).then(() => {
|
|
message.success('获取成功')
|
|
})
|
|
} finally {
|
|
getTableList()
|
|
}
|
|
})
|
|
}
|
|
|
|
const userOptions = ref([])
|
|
const allUserOptions = ref([])
|
|
const allStatusUserOptions = ref([])
|
|
|
|
onMounted(async () => {
|
|
userOptions.value = await getUserOption()
|
|
allUserOptions.value = await getAllUserList()
|
|
allStatusUserOptions.value = await getAllUserListWithHire()
|
|
getCurdSchemas()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped></style>
|
|
|