Files
ss-crm-manage-web/src/views/Clue/Pool/Comp/DrawerClue.vue

356 lines
9.9 KiB
Vue
Raw Normal View History

2024-04-28 16:20:45 +08:00
<template>
<el-drawer
v-model="show"
direction="rtl"
size="60%"
style="min-width: 700px"
:with-header="false"
:destroy-on-close="true"
:show-close="true"
:wrapperClosable="true"
2024-05-10 16:21:07 +08:00
@close="destroyMap"
2024-04-28 16:20:45 +08:00
>
<!-- header -->
<el-skeleton :loading="loading" animated>
<div class="flex justify-between" style="height: 32px">
<div class="flex" style="align-items: center">
<b class="mr-5px text-24px">{{ info.name }}</b>
2024-06-11 20:29:30 +08:00
<div class="mr-5px text-16px">{{ info.phone }}</div>
<el-tag type="success">{{ info.intentionState }}</el-tag>
2024-04-28 16:20:45 +08:00
</div>
<div>
2024-06-14 15:55:48 +08:00
<el-button type="primary" v-hasPermi="['clue:pool:update']" plain @click="handleUpdate">
修改
</el-button>
<el-button type="danger" v-hasPermi="['clue:pool:delete']" plain @click="handleRemove">
删除
</el-button>
2024-04-28 16:20:45 +08:00
</div>
</div>
</el-skeleton>
<!-- 基础信息 -->
<el-skeleton :loading="loading" animated>
<el-table :data="followList" size="small" border class="mt-10px">
<el-table-column prop="name" label="跟进人" />
<el-table-column prop="latestFollowTime" label="最新跟进时间" />
<el-table-column prop="nextFollowTime" label="下次跟进时间" />
<el-table-column prop="saleStatus" label="成交状态" />
</el-table>
</el-skeleton>
<el-divider direction="horizontal" />
<!-- 详细信息 -->
<el-tabs v-model="infoIndex" type="border-card">
<el-tab-pane label="跟进记录" name="followRecord">
2024-06-14 15:55:48 +08:00
<el-button
v-hasPermi="['clue:pool:update']"
class="mb-10px"
type="primary"
@click="addFollow"
>添加跟进记录</el-button
>
2024-04-28 16:20:45 +08:00
<el-timeline>
2024-06-13 15:51:11 +08:00
<el-timeline-item
v-for="item in followRecordList"
:key="item.recordId"
:timestamp="item.operateDate"
placement="top"
>
2024-04-28 16:20:45 +08:00
<el-card shadow="always" :body-style="{ padding: '10px' }">
<div>
2024-06-13 15:51:11 +08:00
<div>
<b class="text-18px" style="line-height: 36px">{{ item.operateUserName }}</b>
2024-04-28 16:20:45 +08:00
</div>
2024-06-13 17:31:52 +08:00
<div>{{ item.content }}</div>
2024-04-28 16:20:45 +08:00
<div class="flex mt-10px" style="align-items: center">
<div class="flex" style="color: #666; align-items: center">
<Icon icon="ep:clock" class="mr-5px" />
2024-06-13 15:51:11 +08:00
<span>本次跟进时间{{ item.followTime }}</span>
2024-04-28 16:20:45 +08:00
</div>
<div class="flex ml-50px" style="color: #666; align-items: center">
<Icon icon="ep:clock" class="mr-5px" />
2024-06-13 15:51:11 +08:00
<span>下次跟进时间{{ item.nextFollowTime }}</span>
2024-04-28 16:20:45 +08:00
</div>
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</el-tab-pane>
<el-tab-pane label="详细信息" name="infoDetail">
2024-06-13 15:51:11 +08:00
<Descriptions :data="info" :schema="showSchema" :columns="2" />
<div v-if="appStore.getAppInfo?.instanceType == 1">
<el-checkbox v-model="showSchool" :label="true" @change="handleShowSchool">
展示场地
</el-checkbox>
<div id="dialogMap" class="mt-20px" style="height: 400px; width: 100%"></div>
</div>
2024-04-28 16:20:45 +08:00
</el-tab-pane>
<el-tab-pane label="操作记录" name="operateRecord">
<el-timeline>
2024-06-13 15:51:11 +08:00
<el-timeline-item
v-for="item in operateRecordList"
:key="item.recordId"
:timestamp="item.operateDate"
placement="top"
>
2024-04-28 16:20:45 +08:00
<el-card shadow="always" :body-style="{ padding: '10px' }">
<div style="color: #666">
<div class="pt-5px">
2024-06-13 15:51:11 +08:00
<span>操作人{{ item.operateUserName }}</span>
2024-04-28 16:20:45 +08:00
</div>
<div class="pt-5px pb-5px">
2024-06-13 17:31:52 +08:00
<span>{{ item.content }}</span>
2024-04-28 16:20:45 +08:00
</div>
<div class="flex" style="align-items: center">
<Icon icon="ep:clock" class="mr-5px" />
2024-06-13 15:51:11 +08:00
<span>操作时间{{ item.followTime }}</span>
2024-04-28 16:20:45 +08:00
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</el-tab-pane>
</el-tabs>
<!-- 新建编辑跟进信息 -->
2024-06-13 17:12:38 +08:00
<DialogFollow ref="followRef" @success="getFollowList" />
2024-04-28 16:20:45 +08:00
</el-drawer>
</template>
2024-06-13 17:12:38 +08:00
<script setup name="DrawerClue">
2024-06-13 15:51:11 +08:00
import { useAppStore } from '@/store/modules/app'
2024-06-11 20:29:30 +08:00
import * as ClueApi from '@/api/clue'
2024-06-13 15:51:11 +08:00
import * as FollowApi from '@/api/clue/followRecord'
import { getPlaceList } from '@/api/school/place'
2024-04-28 16:20:45 +08:00
import DialogFollow from './DialogFollow.vue'
2024-05-10 16:21:07 +08:00
import AMapLoader from '@amap/amap-jsapi-loader'
2024-06-13 15:51:11 +08:00
import { formatDate } from '@/utils/formatTime'
import ImgPostion from '@/assets/imgs/flag/position_blue.png'
import FlagRed from '@/assets/imgs/flag/flag_red.png'
import FlagYellow from '@/assets/imgs/flag/flag_yellow.png'
import FlagPurple from '@/assets/imgs/flag/flag_purple.png'
import FlagGreen from '@/assets/imgs/flag/flag_green.png'
import FlagBlue from '@/assets/imgs/flag/flag_blue.png'
import FlagBlack from '@/assets/imgs/flag/flag_black.png'
2024-06-13 17:12:38 +08:00
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
2024-06-13 15:51:11 +08:00
const appStore = useAppStore()
2024-04-28 16:20:45 +08:00
const show = ref(false)
const info = ref(null)
const loading = ref(false)
2024-06-13 15:51:11 +08:00
const props = defineProps({
schema: {
type: Array
2024-05-10 16:21:07 +08:00
}
2024-06-13 15:51:11 +08:00
})
2024-04-28 16:20:45 +08:00
2024-06-13 15:51:11 +08:00
const showSchema = computed(() => {
const arr = [
{
field: 'requirement',
label: '诉求',
span: 2
},
{
field: 'remark',
label: '备注',
2024-06-14 15:55:48 +08:00
span: 2,
isEditor: true
2024-06-13 15:51:11 +08:00
}
]
return [...props.schema, ...arr]
})
2024-04-28 16:20:45 +08:00
const followList = ref([
{
name: '李四',
latestFollowTime: '2024-02-01',
nextFollowTime: '2024-04-01',
saleStatus: '未成交'
},
{
name: '王二',
latestFollowTime: '2024-03-01',
nextFollowTime: '2024-04-11',
saleStatus: '已成交'
}
])
2024-06-13 15:51:11 +08:00
const followRecordList = ref([])
const operateRecordList = ref([])
2024-05-10 16:21:07 +08:00
// 地图相关
const dialogMap = ref(null)
const aMap = ref(null)
2024-06-13 17:18:12 +08:00
const clueId = ref('')
2024-06-13 17:12:38 +08:00
function getFollowList() {
2024-06-13 17:18:12 +08:00
FollowApi.getFollowList({ clueId: clueId.value }).then((data) => {
2024-06-13 17:12:38 +08:00
followRecordList.value = data.map((item) => ({
operateUserName: item.operateUserName,
2024-06-13 17:31:52 +08:00
content: item.content,
2024-06-13 17:12:38 +08:00
operateDate: formatDate(item.operateTime),
followTime: formatDate(item.operateTime, 'YYYY-MM-DD HH:mm'),
nextFollowTime: formatDate(item.nextFollowTime)
}))
})
}
2024-06-11 20:29:30 +08:00
async function open(id) {
2024-06-13 17:18:12 +08:00
clueId.value = id
2024-06-11 20:29:30 +08:00
try {
2024-06-13 17:12:38 +08:00
getFollowList()
2024-06-13 15:51:11 +08:00
ClueApi.getOpearateRecord({ clueId: id }).then((data) => {
operateRecordList.value = data.map((item) => ({
operateUserName: item.operateUserName,
2024-06-13 17:31:52 +08:00
content: item.content,
2024-06-13 15:51:11 +08:00
operateDate: formatDate(item.operateTime),
followTime: formatDate(item.operateTime, 'YYYY-MM-DD HH:mm')
}))
})
const data = await ClueApi.getClue(id)
info.value = { ...data, ...data.diyParams }
2024-06-11 20:29:30 +08:00
show.value = true
2024-06-13 15:51:11 +08:00
infoIndex.value = 'followRecord'
if (appStore.getAppInfo?.instanceType == 1 && !dialogMap.value) {
2024-06-11 20:29:30 +08:00
nextTick(() => {
2024-06-13 15:51:11 +08:00
getSchoolPlace()
initMap(info.value)
2024-06-11 20:29:30 +08:00
})
}
} catch (error) {
console.log(error)
2024-05-10 16:21:07 +08:00
}
}
2024-06-13 15:51:11 +08:00
const placeList = ref([])
function getSchoolPlace() {
getPlaceList().then((data) => {
placeList.value = data.placeList
})
}
const defaultLatLng = ref({
lat: 31.86119,
lng: 117.283042
})
function initMap(data) {
2024-05-10 16:21:07 +08:00
AMapLoader.load({
key: '2ffb0e2ea90b1df0b8be48ed66e18fc8', //设置您的key
version: '2.0'
}).then((AMap) => {
aMap.value = AMap
2024-06-13 15:51:11 +08:00
if (data.lng || data.lat) {
defaultLatLng.value = {
lng: data.lng,
lat: data.lat
}
}
2024-05-10 16:21:07 +08:00
dialogMap.value = new AMap.Map('dialogMap', {
zoom: 12,
zooms: [2, 22],
2024-06-13 15:51:11 +08:00
center: [defaultLatLng.value.lng, defaultLatLng.value.lat]
2024-05-10 16:21:07 +08:00
})
2024-06-13 15:51:11 +08:00
if (data.lng || data.lat) {
addmark(data.lng, data.lat, AMap)
}
2024-05-10 16:21:07 +08:00
})
}
const showSchool = ref(false)
const schoolMarkers = ref([])
function handleShowSchool() {
if (showSchool.value) {
2024-06-13 15:51:11 +08:00
const flagMap = {
red: FlagRed,
yellow: FlagYellow,
purple: FlagPurple,
green: FlagGreen,
blue: FlagBlue,
black: FlagBlack
}
schoolMarkers.value = []
for (let i = 0; i < placeList.value.length; i++) {
const place = placeList.value[i]
const marker = new aMap.value.Marker({
map: dialogMap.value,
position: [place.lng, place.lat],
label: {
content: place.name,
direction: 'left'
},
icon: flagMap[place.flagColor || 'red'],
extData: place,
clickable: true
})
schoolMarkers.value.push(marker)
}
2024-05-10 16:21:07 +08:00
} else {
dialogMap.value.remove(schoolMarkers.value)
}
2024-04-28 16:20:45 +08:00
}
2024-06-13 15:51:11 +08:00
let marker = ref(null)
function addmark(lat, lng, AMap) {
marker.value && removeMarker()
marker.value = new AMap.Marker({
position: new AMap.LngLat(lat, lng),
zoom: 13,
icon: ImgPostion
})
dialogMap.value.add(marker.value)
dialogMap.value.setCenter([lat, lng], '', 500)
}
function removeMarker() {
dialogMap.value.remove(marker.value)
}
2024-04-28 16:20:45 +08:00
const infoIndex = ref('followRecord')
defineExpose({
open
})
const followRef = ref()
function addFollow() {
2024-06-13 17:12:38 +08:00
followRef.value.open(info.value.clueId)
2024-04-28 16:20:45 +08:00
}
2024-05-10 16:21:07 +08:00
function destroyMap() {
dialogMap.value = null
aMap.value = null
}
2024-06-13 17:12:38 +08:00
const emit = defineEmits(['update', 'getList'])
// 修改
function handleUpdate() {
emit('update', info.value)
show.value = false
}
// 删除
async function handleRemove() {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await ClueApi.deleteClue(info.value.clueId)
message.success(t('common.delSuccess'))
// 刷新列表
emit('getList')
show.value = false
} catch (err) {
console.log(err)
}
}
2024-04-28 16:20:45 +08:00
</script>
<style lang="scss" scoped></style>