crm 客户管理
parent
584d6978ae
commit
7f8f02ebf7
3
.env
3
.env
|
|
@ -26,3 +26,6 @@ VITE_APP_DEFAULT_LOGIN_PASSWORD = admin123
|
||||||
|
|
||||||
# 租户开关
|
# 租户开关
|
||||||
VUE_APP_TENANT_ENABLE=false
|
VUE_APP_TENANT_ENABLE=false
|
||||||
|
|
||||||
|
# 腾讯地图key
|
||||||
|
VITE_APP_TENCENT_MAP_KEY= EE5BZ-SMO63-I6G3P-OL4UN-BE34O-QCBOS
|
||||||
|
|
@ -4,7 +4,7 @@ NODE_ENV=development
|
||||||
VITE_DEV=true
|
VITE_DEV=true
|
||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://localhost:48080'
|
VITE_BASE_URL='http://www.woyaoshouchong.asia:48080'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||||
VITE_UPLOAD_TYPE=client
|
VITE_UPLOAD_TYPE=client
|
||||||
|
|
|
||||||
12
.env.test
12
.env.test
|
|
@ -1,10 +1,10 @@
|
||||||
# 测试环境:只在打包时使用
|
# 测试环境:只在打包时使用
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
|
|
||||||
VITE_DEV=false
|
VITE_DEV=true
|
||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://www.woyaoshouchong.asia:48080'
|
VITE_BASE_URL='http://www.woyaoshouchong.asia:88'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
VITE_UPLOAD_TYPE=client
|
VITE_UPLOAD_TYPE=client
|
||||||
|
|
@ -13,16 +13,16 @@ VITE_UPLOAD_TYPE=client
|
||||||
VITE_API_URL=/admin-api
|
VITE_API_URL=/admin-api
|
||||||
|
|
||||||
# 是否删除debugger
|
# 是否删除debugger
|
||||||
VITE_DROP_DEBUGGER=true
|
VITE_DROP_DEBUGGER=false
|
||||||
|
|
||||||
# 是否删除console.log
|
# 是否删除console.log
|
||||||
VITE_DROP_CONSOLE=true
|
VITE_DROP_CONSOLE=false
|
||||||
|
|
||||||
# 是否sourcemap
|
# 是否sourcemap
|
||||||
VITE_SOURCEMAP=false
|
VITE_SOURCEMAP=true
|
||||||
|
|
||||||
# 打包路径
|
# 打包路径
|
||||||
VITE_BASE_PATH=/admin-ui-vue3/
|
VITE_BASE_PATH=/
|
||||||
|
|
||||||
# 输出路径
|
# 输出路径
|
||||||
VITE_OUT_DIR=dist-test
|
VITE_OUT_DIR=dist-test
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,16 @@ export const FollowUpRecordApi = {
|
||||||
return await request.get({ url: `/crm/follow-up-record/page`, params })
|
return await request.get({ url: `/crm/follow-up-record/page`, params })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 查询单条跟进记录
|
||||||
|
getFollowUpRecord: async (id: number) => {
|
||||||
|
return await request.get({ url: `/crm/follow-up-record/get?id=${id}` })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新跟进记录
|
||||||
|
updateFollowUpRecord: async (data: FollowUpRecordVO) => {
|
||||||
|
return await request.put({ url: `/crm/follow-up-record/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
// 新增跟进记录
|
// 新增跟进记录
|
||||||
createFollowUpRecord: async (data: FollowUpRecordVO) => {
|
createFollowUpRecord: async (data: FollowUpRecordVO) => {
|
||||||
return await request.post({ url: `/crm/follow-up-record/create`, data })
|
return await request.post({ url: `/crm/follow-up-record/create`, data })
|
||||||
|
|
|
||||||
|
|
@ -49,17 +49,6 @@
|
||||||
</el-link>
|
</el-link>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" label="商机名称" prop="businessName" width="130">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-link
|
|
||||||
:underline="false"
|
|
||||||
type="primary"
|
|
||||||
@click="openBusinessDetail(scope.row.businessId)"
|
|
||||||
>
|
|
||||||
{{ scope.row.businessName }}
|
|
||||||
</el-link>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
align="center"
|
align="center"
|
||||||
label="合同金额(元)"
|
label="合同金额(元)"
|
||||||
|
|
@ -103,14 +92,14 @@
|
||||||
<el-table-column align="center" label="备注" prop="remark" width="200" />
|
<el-table-column align="center" label="备注" prop="remark" width="200" />
|
||||||
<el-table-column
|
<el-table-column
|
||||||
align="center"
|
align="center"
|
||||||
label="已回款金额(元)"
|
label="已付款金额(元)"
|
||||||
prop="totalReceivablePrice"
|
prop="totalReceivablePrice"
|
||||||
width="140"
|
width="140"
|
||||||
:formatter="erpPriceTableColumnFormatter"
|
:formatter="erpPriceTableColumnFormatter"
|
||||||
/>
|
/>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
align="center"
|
align="center"
|
||||||
label="未回款金额(元)"
|
label="未付款金额(元)"
|
||||||
prop="totalReceivablePrice"
|
prop="totalReceivablePrice"
|
||||||
width="140"
|
width="140"
|
||||||
:formatter="erpPriceTableColumnFormatter"
|
:formatter="erpPriceTableColumnFormatter"
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
<el-button v-if="permissionListRef?.validateWrite" @click="openForm('update', contact.id)">
|
<el-button v-if="permissionListRef?.validateWrite" @click="openForm('update', contact.id)">
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-if="permissionListRef?.validateOwnerUser" type="primary" @click="transfer">
|
<!-- <el-button v-if="permissionListRef?.validateOwnerUser" type="primary" @click="transfer">
|
||||||
转移
|
转移
|
||||||
</el-button>
|
</el-button> -->
|
||||||
</ContactDetailsHeader>
|
</ContactDetailsHeader>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-tabs>
|
<el-tabs>
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,19 @@ const uploadRef = ref()
|
||||||
|
|
||||||
const props = defineProps<{ customerId: number }>()
|
const props = defineProps<{ customerId: number }>()
|
||||||
|
|
||||||
const { uploadUrl, httpRequest } = useUpload(undefined, 'crm_consumer', props.customerId )
|
const { uploadUrl, httpRequest } = useUpload(undefined, 'crm_consumer', Number(props.customerId))
|
||||||
|
|
||||||
|
// 保证 data.value.categoryId 始终为最新 customerId
|
||||||
|
watch(() => props.customerId, (val) => {
|
||||||
|
if (val && Number(val) >= 0) {
|
||||||
|
data.value.categoryId = Number(val)
|
||||||
|
} else {
|
||||||
|
data.value.categoryId = undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = (customerId: number) => {
|
const open = (customerId: number | string) => {
|
||||||
data.value.categoryId = customerId
|
data.value.categoryId = customerId && Number(customerId) > 0 ? Number(customerId) : undefined
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
resetForm()
|
resetForm()
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +74,7 @@ const resetForm = () => {
|
||||||
const handleFileChange = (file) => {
|
const handleFileChange = (file) => {
|
||||||
data.value.path = file.name
|
data.value.path = file.name
|
||||||
data.value.category = 'crm_consumer'
|
data.value.category = 'crm_consumer'
|
||||||
data.value.categoryId = props.customerId
|
data.value.categoryId = Number(props.customerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交上传 */
|
/** 提交上传 */
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
link
|
link
|
||||||
type="danger"
|
type="danger"
|
||||||
@click="handleDelete(scope.row.id)"
|
@click="handleDelete(scope.row.id)"
|
||||||
v-hasPermi="['infra:file:delete']"
|
v-hasPermi="['crm:customer:file:delete']"
|
||||||
>
|
>
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-if="permissionListRef?.validateOwnerUser" type="primary" @click="transfer">
|
<el-button v-if="permissionListRef?.validateOwnerUser" v-hasPermi="['crm:customer:transfor']" type="primary" @click="transfer">
|
||||||
转移
|
转移
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- <el-button v-if="permissionListRef?.validateWrite" @click="handleUpdateDealStatus">
|
<!-- <el-button v-if="permissionListRef?.validateWrite" @click="handleUpdateDealStatus">
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="附件">
|
<el-tab-pane label="附件">
|
||||||
<FileList :customerId="customerId" />
|
<FileList v-if="customerId" :customerId="customerId" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="操作日志">
|
<el-tab-pane label="操作日志">
|
||||||
<OperateLogV2 :log-list="logList" />
|
<OperateLogV2 :log-list="logList" />
|
||||||
|
|
@ -208,7 +208,7 @@ onMounted(() => {
|
||||||
close()
|
close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
customerId.value = params.id as unknown as number
|
customerId.value = Number(params.id)
|
||||||
getCustomer()
|
getCustomer()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,8 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="下次联系时间" prop="nextTime">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="formData.nextTime"
|
|
||||||
placeholder="选择下次联系时间"
|
|
||||||
type="date"
|
|
||||||
value-format="x"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12" v-if="formData.bizType == BizTypeEnum.CRM_CUSTOMER">
|
<el-col :span="12" v-if="formData.bizType == BizTypeEnum.CRM_CUSTOMER">
|
||||||
<el-form-item label="关联联系人" prop="contactIds">
|
<el-form-item label="选择联系人" prop="contactIds">
|
||||||
<el-select v-model="formData.contactIds" filterable placeholder="请选择联系人">
|
<el-select v-model="formData.contactIds" filterable placeholder="请选择联系人">
|
||||||
<el-option v-for="item in contactOptions" :key="item.id" :label="item.name" :value="item.id" />
|
<el-option v-for="item in contactOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
@ -43,11 +33,6 @@
|
||||||
<Editor v-model="formData.content" height="150px" />
|
<Editor v-model="formData.content" height="150px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- <el-col :span="12">
|
|
||||||
<el-form-item label="图片" prop="picUrls">
|
|
||||||
<UploadImgs v-model="formData.picUrls" class="min-w-80px" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col> -->
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="附件" prop="fileUrls">
|
<el-form-item label="附件" prop="fileUrls">
|
||||||
<UploadFile v-model="formData.fileUrls" class="min-w-80px" />
|
<UploadFile v-model="formData.fileUrls" class="min-w-80px" />
|
||||||
|
|
@ -108,13 +93,13 @@ const formData = ref<FollowUpFormData>({
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
type: [{ required: true, message: '跟进类型不能为空', trigger: 'change' }],
|
type: [{ required: true, message: '跟进类型不能为空', trigger: 'change' }],
|
||||||
content: [{ required: true, message: '跟进内容不能为空', trigger: 'blur' }],
|
content: [{ required: true, message: '跟进内容不能为空', trigger: 'blur' }],
|
||||||
nextTime: [{ required: true, message: '下次联系时间不能为空', trigger: 'blur' }],
|
|
||||||
contactIds: [{ required: true, message: '联系人不能为空', trigger: 'change' }]
|
contactIds: [{ required: true, message: '联系人不能为空', trigger: 'change' }]
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const formRef = ref() // 表单 Ref
|
const formRef = ref() // 表单 Ref
|
||||||
const contactOptions = ref<ContactApi.ContactVO[]>([])
|
const contactOptions = ref<ContactApi.ContactVO[]>([])
|
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => formData.value.bizId,
|
() => formData.value.bizId,
|
||||||
|
|
@ -123,19 +108,38 @@ watch(
|
||||||
// 获取客户下联系人
|
// 获取客户下联系人
|
||||||
const res = await ContactApi.getContactPageByCustomer({ customerId: val, pageSize: 100 })
|
const res = await ContactApi.getContactPageByCustomer({ customerId: val, pageSize: 100 })
|
||||||
contactOptions.value = res.list || []
|
contactOptions.value = res.list || []
|
||||||
|
// 自动选中第一个联系人
|
||||||
|
if (contactOptions.value.length > 0) {
|
||||||
|
formData.value.contactIds = [contactOptions.value[0].id]
|
||||||
|
} else {
|
||||||
|
formData.value.contactIds = []
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
contactOptions.value = []
|
contactOptions.value = []
|
||||||
|
formData.value.contactIds = []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (bizType: number, bizId: number) => {
|
const open = async (bizType: number, bizId: number, id?: number) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
resetForm()
|
resetForm()
|
||||||
formData.value.bizType = bizType
|
formData.value.bizType = bizType
|
||||||
formData.value.bizId = bizId
|
formData.value.bizId = bizId
|
||||||
|
if (id) {
|
||||||
|
formType.value = 'update'
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = await FollowUpRecordApi.getFollowUpRecord(id)
|
||||||
|
Object.assign(formData.value, data)
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formType.value = 'create'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
|
|
@ -156,8 +160,16 @@ const submitForm = async () => {
|
||||||
contactIds,
|
contactIds,
|
||||||
businessIds: (formData.value.businesses || []).map((item: any) => item.id)
|
businessIds: (formData.value.businesses || []).map((item: any) => item.id)
|
||||||
} as unknown as FollowUpRecordVO
|
} as unknown as FollowUpRecordVO
|
||||||
|
|
||||||
|
if (formType.value === 'create') {
|
||||||
await FollowUpRecordApi.createFollowUpRecord(data)
|
await FollowUpRecordApi.createFollowUpRecord(data)
|
||||||
message.success(t('common.createSuccess'))
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await FollowUpRecordApi.updateFollowUpRecord(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
emit('success')
|
emit('success')
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
:timestamp="formatDate(item.createTime)"
|
:timestamp="formatDate(item.createTime)"
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
|
<span>跟进人:</span>{{ item.creatorName }}
|
||||||
<template #timestamp>
|
<template #timestamp>
|
||||||
<div style="color:#999;font-size:13px;margin-bottom:2px;">跟进时间</div>
|
<div style="color:#999;font-size:13px;margin-bottom:2px;">跟进时间</div>
|
||||||
<span>{{ formatDate(item.createTime) }}</span>
|
<span>{{ formatDate(item.createTime) }}</span>
|
||||||
|
|
@ -65,8 +66,9 @@
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>跟进人:</span>{{ item.creatorName }}
|
<el-button link type="primary" class="mr-10px followup-edit-btn" @click="openForm('update', item.id)">
|
||||||
<br />
|
<Icon icon="ep:edit" class="mr-3px" /> 编辑
|
||||||
|
</el-button>
|
||||||
<el-button link type="danger" class="mr-20px followup-delete-btn" @click="handleDelete(item.id)">
|
<el-button link type="danger" class="mr-20px followup-delete-btn" @click="handleDelete(item.id)">
|
||||||
<Icon icon="ep:delete" class="mr-3px" /> 删除
|
<Icon icon="ep:delete" class="mr-3px" /> 删除
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
@ -129,8 +131,13 @@ const getList = async () => {
|
||||||
|
|
||||||
/** 添加/修改操作 */
|
/** 添加/修改操作 */
|
||||||
const formRef = ref<InstanceType<typeof FollowUpRecordForm>>()
|
const formRef = ref<InstanceType<typeof FollowUpRecordForm>>()
|
||||||
const openForm = () => {
|
// 支持编辑和新增
|
||||||
|
const openForm = (type: 'create' | 'update' = 'create', id?: number) => {
|
||||||
|
if (type === 'update' && id) {
|
||||||
|
formRef.value?.open(props.bizType, props.bizId, id)
|
||||||
|
} else {
|
||||||
formRef.value?.open(props.bizType, props.bizId)
|
formRef.value?.open(props.bizType, props.bizId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
|
|
@ -264,4 +271,24 @@ watch(
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.followup-update-btn {
|
||||||
|
color: #7492f3 !important;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: background 0.2s, color 0.2s;
|
||||||
|
border: none;
|
||||||
|
background: #fef0f0;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
&:hover {
|
||||||
|
background: #fef0f0;
|
||||||
|
color: #c0392b !important;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
font-size: 15px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,6 @@
|
||||||
</template>
|
</template>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="bizType === BizTypeEnum.CRM_CUSTOMER" label="同时转移">
|
|
||||||
<el-checkbox-group v-model="formData.toBizTypes">
|
|
||||||
<el-checkbox :value="BizTypeEnum.CRM_CONTACT">联系人</el-checkbox>
|
|
||||||
<el-checkbox :value="BizTypeEnum.CRM_BUSINESS">商机</el-checkbox>
|
|
||||||
<el-checkbox :value="BizTypeEnum.CRM_CONTRACT">合同</el-checkbox>
|
|
||||||
</el-checkbox-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
|
@ -87,6 +80,10 @@ const open = async (bizId: number) => {
|
||||||
dialogTitle.value = getDialogTitle()
|
dialogTitle.value = getDialogTitle()
|
||||||
resetForm()
|
resetForm()
|
||||||
formData.value.id = bizId
|
formData.value.id = bizId
|
||||||
|
// 客户转移时默认勾选联系人和合同
|
||||||
|
if (props.bizType === BizTypeEnum.CRM_CUSTOMER) {
|
||||||
|
formData.value.toBizTypes = [BizTypeEnum.CRM_CONTACT, BizTypeEnum.CRM_CONTRACT, BizTypeEnum.CRM_CUSTOMER]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
// 老负责人负责方式
|
// 老负责人负责方式
|
||||||
|
|
@ -154,6 +151,10 @@ const getDialogTitle = () => {
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
formRef.value?.resetFields()
|
formRef.value?.resetFields()
|
||||||
formData.value = {} as TransferReqVO
|
formData.value = {} as TransferReqVO
|
||||||
|
// 客户转移时默认勾选联系人和合同
|
||||||
|
if (props.bizType === BizTypeEnum.CRM_CUSTOMER) {
|
||||||
|
formData.value.toBizTypes = [BizTypeEnum.CRM_CONTACT, BizTypeEnum.CRM_CONTRACT]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// 获得用户列表
|
// 获得用户列表
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="填报人" align="center" prop="creatorName" />
|
<el-table-column label="填报人" align="center" prop="creatorName" />
|
||||||
<el-table-column label="操作" fixed="right" align="center" min-width="120px">
|
<el-table-column label="操作" fixed="right" align="center" min-width="180px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
link
|
link
|
||||||
|
|
@ -108,6 +108,13 @@
|
||||||
>
|
>
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
link
|
||||||
|
type="success"
|
||||||
|
@click="openMapDialog(scope.row)"
|
||||||
|
>
|
||||||
|
获取经纬度
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -118,6 +125,10 @@
|
||||||
v-model:limit="queryParams.pageSize"
|
v-model:limit="queryParams.pageSize"
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
|
<!-- 地图弹窗 -->
|
||||||
|
<el-dialog v-model="mapDialogVisible" title="获取经纬度" append-to-body>
|
||||||
|
<IFrame class="h-609px" :src="tencentLbsUrl" />
|
||||||
|
</el-dialog>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 -->
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
|
|
@ -153,6 +164,10 @@ const queryParams = reactive({
|
||||||
const queryFormRef = ref() // 搜索的表单
|
const queryFormRef = ref() // 搜索的表单
|
||||||
const exportLoading = ref(false) // 导出的加载中
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
const areaList = ref([])
|
const areaList = ref([])
|
||||||
|
const mapDialogVisible = ref(false)
|
||||||
|
const tencentLbsUrl = ref('')
|
||||||
|
const currentRow = ref<any>(null)
|
||||||
|
const TENCENT_MAP_KEY = import.meta.env.VITE_APP_TENCENT_MAP_KEY // 你的腾讯地图key
|
||||||
|
|
||||||
/** 查询列表 */
|
/** 查询列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
|
|
@ -212,11 +227,60 @@ const handleExport = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化 **/
|
/** 地图弹窗相关操作 */
|
||||||
|
const openMapDialog = (row: any) => {
|
||||||
|
currentRow.value = row
|
||||||
|
// 拼接带初始点的 url
|
||||||
|
|
||||||
|
let url = `https://apis.map.qq.com/tools/locpicker?type=1&key=${TENCENT_MAP_KEY}&referer=myapp`
|
||||||
|
if (row.locationLat && row.locationLng) {
|
||||||
|
url += `&coord=${row.locationLat},${row.locationLng}`
|
||||||
|
}
|
||||||
|
tencentLbsUrl.value = url
|
||||||
|
mapDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(mapDialogVisible, (val) => {
|
||||||
|
if (!val) {
|
||||||
|
tencentLbsUrl.value = '' // 关闭时重置,避免缓存
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 选择经纬度回填
|
||||||
|
function selectAddress(loc: any): void {
|
||||||
|
if (loc.latlng && loc.latlng.lat) {
|
||||||
|
currentRow.value.locationLat = loc.latlng.lat
|
||||||
|
}
|
||||||
|
if (loc.latlng && loc.latlng.lng) {
|
||||||
|
currentRow.value.locationLng = loc.latlng.lng
|
||||||
|
}
|
||||||
|
mapDialogVisible.value = false
|
||||||
|
// 可选:刷新表格数据
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化腾讯地图监听
|
||||||
|
const initTencentLbsMap = () => {
|
||||||
|
// @ts-ignore
|
||||||
|
window.selectAddress = selectAddress
|
||||||
|
window.addEventListener(
|
||||||
|
'message',
|
||||||
|
function (event) {
|
||||||
|
let loc = event.data
|
||||||
|
if (loc && loc.module === 'locationPicker') {
|
||||||
|
// @ts-ignore
|
||||||
|
window.selectAddress(loc)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList()
|
getList()
|
||||||
AreaApi.getAreaTree().then(res => {
|
AreaApi.getAreaTree().then(res => {
|
||||||
areaList.value = res
|
areaList.value = res
|
||||||
})
|
})
|
||||||
|
initTencentLbsMap()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
Loading…
Reference in New Issue