salary
qsh 4 months ago
parent e35a32e985
commit cff4280705
  1. 2
      src/api/clue/source.js
  2. 259
      src/views/Clue/Pool/Comp/DialogClue.vue
  3. 9
      src/views/Clue/Pool/cluePool.data.js
  4. 11
      src/views/Clue/Pool/index.vue

@ -2,7 +2,7 @@ import request from '@/config/axios'
// 查询(精简)列表 // 查询(精简)列表
export const getSimpleSourceList = async () => { export const getSimpleSourceList = async () => {
return await request.get({ url: '/admin-api/crm/source/list-all-simple' }) return await request.get({ url: '/admin-api/crm/source/list' })
} }
// 查询列表 // 查询列表

@ -2,45 +2,51 @@
<Dialog :title="dialogTitle" v-model="dialogVisible" width="800px"> <Dialog :title="dialogTitle" v-model="dialogVisible" width="800px">
<el-tabs v-model="tabName"> <el-tabs v-model="tabName">
<el-tab-pane label="线索信息" name="info"> <el-tab-pane label="线索信息" name="info">
<Form <Form ref="formRef" v-loading="formLoading" :rules="rules" isCol :schema="formSchema" />
ref="formRef"
v-loading="formLoading"
:rules="rules"
isCol
:schema="allSchemas.formSchema"
/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="跟进信息" name="follow"> <el-tab-pane label="跟进信息" name="follow">
<el-button type="primary" @click="handleAppendFollow">新增跟进人</el-button> <el-button type="primary" @click="handleAppendFollow">新增跟进人</el-button>
<el-table :data="followList"> <el-table :data="followList">
<el-table-column label="跟进人"> <el-table-column label="跟进人">
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.followUser" placeholder="选择跟进人" filterable> <el-select
v-model="row.userId"
placeholder="选择跟进人"
filterable
:disabled="!row.editable"
>
<el-option <el-option
v-for="item in userOptions" v-for="item in userOptions"
:key="item.value" :key="item.id"
:label="item.label" :label="item.nickname"
:value="item.value" :value="item.id"
/> />
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="nextFollowTime" label="下次跟进时间"> <el-table-column prop="followTime" label="下次跟进时间">
<template #default="{ row }"> <template #default="{ row }">
<el-date-picker v-model="row.nextFollowTime" type="date" placeholder="选择日期时间" /> <el-date-picker
v-model="row.followTime"
type="date"
placeholder="选择日期时间"
:disabled="!row.editable"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="80"> <el-table-column label="操作" width="80">
<template #default="{ $index }"> <template #default="{ row, $index }">
<Icon icon="ep:remove-filled" class="text-red-500" @click="handleRemove($index)" /> <Icon
<!-- <el-button @click="handleRemove(row, $index)"> v-if="row.editable"
icon="ep:remove-filled"
</el-button> --> class="text-red-500"
@click="handleRemove($index)"
/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="位置信息" name="map"> <el-tab-pane v-if="appStore.getAppInfo?.instanceType == 1" label="位置信息" name="map">
<div class="flex justify-between"> <div class="flex justify-between">
<el-select <el-select
v-model="areaValue" v-model="areaValue"
@ -64,11 +70,15 @@
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.district }}</span> <span style="float: right; color: #8492a6; font-size: 13px">{{ item.district }}</span>
</el-option> </el-option>
</el-select> </el-select>
<el-checkbox v-model="showSchool" :label="true" @change="handleShowSchool" <el-checkbox v-model="showSchool" :label="true" @change="handleShowSchool">
>展示场地</el-checkbox 展示场地
> </el-checkbox>
</div> </div>
<div id="dialogMap" class="mt-20px" style="height: 400px; width: 100%"></div> <div id="dialogMap" class="mt-20px" style="height: 400px; width: 100%"></div>
<div class="flex items-center mt-10px mb-10px">
<div class="w-100px">线索位置</div>
<el-input v-model="address" placeholder="请输入线索位置" clearable />
</div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<template #footer> <template #footer>
@ -80,12 +90,55 @@
</Dialog> </Dialog>
</template> </template>
<script setup> <script setup name="DialogClue">
import { allSchemas, rules } from '../cluePool.data' import { useAppStore } from '@/store/modules/app'
import { getSimpleUserList as getUserOption } from '@/api/system/user'
import { getPlaceList } from '@/api/school/place'
import * as ClueApi from '@/api/clue'
import { formatDate } from '@/utils/formatTime' import { formatDate } from '@/utils/formatTime'
import AMapLoader from '@amap/amap-jsapi-loader' import AMapLoader from '@amap/amap-jsapi-loader'
import ImgPostion from '@/assets/imgs/flag/flag_red.png' import ImgPostion from '@/assets/imgs/flag/flag_red.png'
import ImgFlag 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 props = defineProps({
schema: {
type: Array
}
})
const formSchema = computed(() => {
return [
...props.schema,
{
component: 'Input',
label: '诉求',
field: 'requirement',
componentProps: {
type: 'textarea'
},
colProps: {
span: 24
}
},
{
component: 'Editor',
label: '备注',
field: 'remark',
colProps: {
span: 24
}
}
]
})
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
const dialogTitle = ref('') // const dialogTitle = ref('') //
@ -93,47 +146,106 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
const formType = ref('') // create - update - const formType = ref('') // create - update -
const formRef = ref() // Ref const formRef = ref() // Ref
const rules = {
name: { required: true, message: '线索名称不可为空', trigger: 'blur' },
phone: { required: true, message: '联系方式不可为空', trigger: 'blur' },
source: { required: true, message: '线索来源不可为空', trigger: 'change' },
intentionState: { required: true, message: '意向状态不可为空', trigger: 'change' }
}
const tabName = ref('info') const tabName = ref('info')
const followList = ref([]) const followList = ref([])
const userOptions = ref([]) const userOptions = ref([])
const areaValue = ref('新天地国际') const areaValue = ref('')
const areaList = ref([]) const areaList = ref([])
const address = ref('')
const defaultLatLng = ref({
lat: 31.86119,
lng: 117.283042
})
const info = ref({})
const open = async (type, info) => { const open = async (type, id) => {
dialogVisible.value = true dialogVisible.value = true
dialogTitle.value = type == 'create' ? '新增线索' : '修改线索' dialogTitle.value = type == 'create' ? '新增线索' : '修改线索'
formType.value = type formType.value = type
// //
if (info) { if (id) {
formLoading.value = true formLoading.value = true
try { try {
const data = { ...info } const data = await ClueApi.getClue(id)
info.value = { ...data, ...data.diyParams }
nextTick(() => { nextTick(() => {
formRef.value.setValues(data) followList.value = data.followUser
address.value = data.address || ''
formRef.value.setValues(info.value)
}) })
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
} }
if (!dialogMap.value) { if (appStore.getAppInfo?.instanceType == 1 && !dialogMap.value) {
nextTick(() => { nextTick(() => {
initMap() getSchoolPlace()
remoteMethod('新天地国际') initMap(info.value)
remoteMethod(address.value)
}) })
} }
} }
defineExpose({ open }) // open defineExpose({ open }) // open
function handleSave() { const placeList = ref([])
console.log('保存') function getSchoolPlace() {
getPlaceList().then((data) => {
placeList.value = data.placeList
})
}
async function handleSave() {
//
if (!formRef.value) return
const valid = await formRef.value.getElFormRef().validate()
if (!valid) return
if (followList.value && followList.value.length && followList.value.some((it) => !it.userId)) {
message.info('请将跟进人填写完整!')
return
}
//
formLoading.value = true
try {
let params = { ...formRef.value.formModel, address: address.value }
params.lat = defaultLatLng.value.lat
params.lng = defaultLatLng.value.lng
params.followUsers = [...followList.value]
params.diyParams = {}
debugger
for (const key in info.value.diyParams) {
if (Object.hasOwnProperty.call(info.value.diyParams, key)) {
params.diyParams[key] = params.key
}
}
if (formType.value === 'create') {
await ClueApi.createClue(params)
message.success(t('common.createSuccess'))
} else {
await ClueApi.updateClue(params)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
} }
function handleAppendFollow() { function handleAppendFollow() {
followList.value.push({ followList.value.push({
followUser: undefined, userId: undefined,
nextFollowTime: formatDate(new Date()) followTime: formatDate(new Date()),
editable: true
}) })
} }
function handleRemove(index) { function handleRemove(index) {
@ -145,28 +257,55 @@ const dialogMap = ref(null)
const aMap = ref(null) const aMap = ref(null)
let AutoComplete = ref(null) let AutoComplete = ref(null)
let geoCoder = ref(null) let geoCoder = ref(null)
function initMap() {
function initMap(data) {
AMapLoader.load({ AMapLoader.load({
key: '2ffb0e2ea90b1df0b8be48ed66e18fc8', //key key: '2ffb0e2ea90b1df0b8be48ed66e18fc8', //key
version: '2.0', version: '2.0',
plugins: ['AMap.Geocoder', 'AMap.AutoComplete'] plugins: ['AMap.Geocoder', 'AMap.AutoComplete']
}).then((AMap) => { }).then((AMap) => {
aMap.value = AMap aMap.value = AMap
if (data.lng || data.lat) {
defaultLatLng.value = {
lng: data.lng,
lat: data.lat
}
addmark(data.lng, data.lat, AMap)
}
dialogMap.value = new AMap.Map('dialogMap', { dialogMap.value = new AMap.Map('dialogMap', {
zoom: 12, zoom: 12,
zooms: [2, 22], zooms: [2, 22],
center: [117.283042, 31.86119] center: [defaultLatLng.value.lng, defaultLatLng.value.lat]
}) })
AutoComplete.value = new AMap.AutoComplete({ AutoComplete.value = new AMap.AutoComplete({
city: '全国' city: '全国'
}) })
geoCoder.value = new AMap.Geocoder() geoCoder.value = new AMap.Geocoder()
dialogMap.value.on('click', (e) => { dialogMap.value.on('click', (e) => {
defaultLatLng.value = {
lng: e.lnglat.getLng(),
lat: e.lnglat.getLat()
}
addmark(e.lnglat.getLng(), e.lnglat.getLat(), AMap) addmark(e.lnglat.getLng(), e.lnglat.getLat(), AMap)
regeoCode(e.lnglat.getLng(), e.lnglat.getLat())
}) })
}) })
} }
function regeoCode(lng, lat) {
try {
geoCoder.value.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.regeocode) {
address.value = result.regeocode.formattedAddress
} else {
message.error('根据经纬度查询地址失败')
}
})
} catch (error) {
console.log(error)
}
}
let marker = ref(null) let marker = ref(null)
function addmark(lat, lng, AMap) { function addmark(lat, lng, AMap) {
marker.value && removeMarker() marker.value && removeMarker()
@ -186,29 +325,30 @@ const showSchool = ref(false)
const schoolMarkers = ref([]) const schoolMarkers = ref([])
function handleShowSchool() { function handleShowSchool() {
if (showSchool.value) { if (showSchool.value) {
let marker1 = new aMap.value.Marker({ const flagMap = {
map: dialogMap.value, red: FlagRed,
position: [117.258001, 31.895216], yellow: FlagYellow,
label: { purple: FlagPurple,
content: '慧安驾校桃花社区训练基地', green: FlagGreen,
direction: 'left' blue: FlagBlue,
}, black: FlagBlack
icon: ImgFlag, }
// extData: element, schoolMarkers.value = []
clickable: true for (let i = 0; i < placeList.value.length; i++) {
}) const place = placeList.value[i]
let marker2 = new aMap.value.Marker({ const marker = new aMap.value.Marker({
map: dialogMap.value, map: dialogMap.value,
position: [117.286731, 31.902396], position: [place.lng, place.lat],
label: { label: {
content: '(皖西)瑞星驾校总校(D)', content: place.name,
direction: 'left' direction: 'left'
}, },
icon: ImgFlag, icon: flagMap[place.flagColor || 'red'],
// extData: element, extData: place,
clickable: true clickable: true
}) })
schoolMarkers.value = [marker1, marker2] schoolMarkers.value.push(marker)
}
} else { } else {
dialogMap.value.remove(schoolMarkers.value) dialogMap.value.remove(schoolMarkers.value)
} }
@ -231,8 +371,15 @@ function currentSelect(val) {
if (area) { if (area) {
addmark(area.location?.lng, area.location?.lat, aMap.value) addmark(area.location?.lng, area.location?.lat, aMap.value)
dialogMap.value.setCenter([area.location?.lng, area.location?.lat], '', 500) dialogMap.value.setCenter([area.location?.lng, area.location?.lat], '', 500)
regeoCode(area.location?.lng, area.location?.lat)
} }
} }
onMounted(() => {
getUserOption().then((data) => {
userOptions.value = data
})
})
</script> </script>
<style scoped> <style scoped>

@ -4,11 +4,10 @@ import { dateFormatter } from '@/utils/formatTime'
// 表单校验 // 表单校验
export const rules = reactive({ export const rules = reactive({
username: [required], name: [required],
password: [required], phone: [required],
host: [required], source: [required],
port: [required], intentionState: [required]
sslEnable: [required]
}) })
// const userList = await MailAccountApi.getSimpleMailAccountList() // const userList = await MailAccountApi.getSimpleMailAccountList()

@ -115,7 +115,12 @@
</el-table-column> </el-table-column>
</SSTable> </SSTable>
<DialogClue ref="formRef" /> <DialogClue
v-if="!loading"
ref="formRef"
:schema="allSchemas.formSchema"
@sucess="getTableList"
/>
<DrawerClue ref="drawerRef" /> <DrawerClue ref="drawerRef" />
<DialogSuccess ref="successRef" /> <DialogSuccess ref="successRef" />
<DialogFollow ref="followRef" /> <DialogFollow ref="followRef" />
@ -192,7 +197,7 @@ async function getTableList() {
queryType: queryType.value queryType: queryType.value
} }
const data = await ClueApi.getCluePage(removeNullField(params)) const data = await ClueApi.getCluePage(removeNullField(params))
tableObject.value.tableList = data.list tableObject.value.tableList = data.list.map((it) => ({ ...it, ...it.diyParams }))
tableObject.value.total = data.total tableObject.value.total = data.total
} finally { } finally {
tableObject.value.loading = false tableObject.value.loading = false
@ -216,7 +221,7 @@ function handleInsert() {
} }
// //
function handleEdit(row) { function handleEdit(row) {
formRef.value.open('update', row) formRef.value.open('update', row.clueId)
} }
// //
function handleDetail(row) { function handleDetail(row) {

Loading…
Cancel
Save