Files
ss-crm-manage-web/src/views/Clue/Pool/Comp/DrawerClue.vue
2024-06-14 15:55:48 +08:00

356 lines
9.9 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>
<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"
@close="destroyMap"
>
<!-- 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>
<div class="mr-5px text-16px">{{ info.phone }}</div>
<el-tag type="success">{{ info.intentionState }}</el-tag>
</div>
<div>
<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>
</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">
<el-button
v-hasPermi="['clue:pool:update']"
class="mb-10px"
type="primary"
@click="addFollow"
>添加跟进记录</el-button
>
<el-timeline>
<el-timeline-item
v-for="item in followRecordList"
:key="item.recordId"
:timestamp="item.operateDate"
placement="top"
>
<el-card shadow="always" :body-style="{ padding: '10px' }">
<div>
<div>
<b class="text-18px" style="line-height: 36px">{{ item.operateUserName }}</b>
</div>
<div>{{ item.content }}</div>
<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" />
<span>本次跟进时间{{ item.followTime }}</span>
</div>
<div class="flex ml-50px" style="color: #666; align-items: center">
<Icon icon="ep:clock" class="mr-5px" />
<span>下次跟进时间{{ item.nextFollowTime }}</span>
</div>
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</el-tab-pane>
<el-tab-pane label="详细信息" name="infoDetail">
<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>
</el-tab-pane>
<el-tab-pane label="操作记录" name="operateRecord">
<el-timeline>
<el-timeline-item
v-for="item in operateRecordList"
:key="item.recordId"
:timestamp="item.operateDate"
placement="top"
>
<el-card shadow="always" :body-style="{ padding: '10px' }">
<div style="color: #666">
<div class="pt-5px">
<span>操作人{{ item.operateUserName }}</span>
</div>
<div class="pt-5px pb-5px">
<span>{{ item.content }}</span>
</div>
<div class="flex" style="align-items: center">
<Icon icon="ep:clock" class="mr-5px" />
<span>操作时间{{ item.followTime }}</span>
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</el-tab-pane>
</el-tabs>
<!-- 新建编辑跟进信息 -->
<DialogFollow ref="followRef" @success="getFollowList" />
</el-drawer>
</template>
<script setup name="DrawerClue">
import { useAppStore } from '@/store/modules/app'
import * as ClueApi from '@/api/clue'
import * as FollowApi from '@/api/clue/followRecord'
import { getPlaceList } from '@/api/school/place'
import DialogFollow from './DialogFollow.vue'
import AMapLoader from '@amap/amap-jsapi-loader'
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'
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const appStore = useAppStore()
const show = ref(false)
const info = ref(null)
const loading = ref(false)
const props = defineProps({
schema: {
type: Array
}
})
const showSchema = computed(() => {
const arr = [
{
field: 'requirement',
label: '诉求',
span: 2
},
{
field: 'remark',
label: '备注',
span: 2,
isEditor: true
}
]
return [...props.schema, ...arr]
})
const followList = ref([
{
name: '李四',
latestFollowTime: '2024-02-01',
nextFollowTime: '2024-04-01',
saleStatus: '未成交'
},
{
name: '王二',
latestFollowTime: '2024-03-01',
nextFollowTime: '2024-04-11',
saleStatus: '已成交'
}
])
const followRecordList = ref([])
const operateRecordList = ref([])
// 地图相关
const dialogMap = ref(null)
const aMap = ref(null)
const clueId = ref('')
function getFollowList() {
FollowApi.getFollowList({ clueId: clueId.value }).then((data) => {
followRecordList.value = data.map((item) => ({
operateUserName: item.operateUserName,
content: item.content,
operateDate: formatDate(item.operateTime),
followTime: formatDate(item.operateTime, 'YYYY-MM-DD HH:mm'),
nextFollowTime: formatDate(item.nextFollowTime)
}))
})
}
async function open(id) {
clueId.value = id
try {
getFollowList()
ClueApi.getOpearateRecord({ clueId: id }).then((data) => {
operateRecordList.value = data.map((item) => ({
operateUserName: item.operateUserName,
content: item.content,
operateDate: formatDate(item.operateTime),
followTime: formatDate(item.operateTime, 'YYYY-MM-DD HH:mm')
}))
})
const data = await ClueApi.getClue(id)
info.value = { ...data, ...data.diyParams }
show.value = true
infoIndex.value = 'followRecord'
if (appStore.getAppInfo?.instanceType == 1 && !dialogMap.value) {
nextTick(() => {
getSchoolPlace()
initMap(info.value)
})
}
} catch (error) {
console.log(error)
}
}
const placeList = ref([])
function getSchoolPlace() {
getPlaceList().then((data) => {
placeList.value = data.placeList
})
}
const defaultLatLng = ref({
lat: 31.86119,
lng: 117.283042
})
function initMap(data) {
AMapLoader.load({
key: '2ffb0e2ea90b1df0b8be48ed66e18fc8', //设置您的key
version: '2.0'
}).then((AMap) => {
aMap.value = AMap
if (data.lng || data.lat) {
defaultLatLng.value = {
lng: data.lng,
lat: data.lat
}
}
dialogMap.value = new AMap.Map('dialogMap', {
zoom: 12,
zooms: [2, 22],
center: [defaultLatLng.value.lng, defaultLatLng.value.lat]
})
if (data.lng || data.lat) {
addmark(data.lng, data.lat, AMap)
}
})
}
const showSchool = ref(false)
const schoolMarkers = ref([])
function handleShowSchool() {
if (showSchool.value) {
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)
}
} else {
dialogMap.value.remove(schoolMarkers.value)
}
}
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)
}
const infoIndex = ref('followRecord')
defineExpose({
open
})
const followRef = ref()
function addFollow() {
followRef.value.open(info.value.clueId)
}
function destroyMap() {
dialogMap.value = null
aMap.value = null
}
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)
}
}
</script>
<style lang="scss" scoped></style>