📈 CRM:code review 联系人商机功能

This commit is contained in:
YunaiV 2023-12-06 19:26:39 +08:00
parent d6291382e8
commit ce79dd68a3
7 changed files with 82 additions and 56 deletions

View File

@ -1,4 +1,3 @@
import { getBusiness } from './../business/index';
import request from '@/config/axios' import request from '@/config/axios'
export interface ContactBusinessLinkVO { export interface ContactBusinessLinkVO {
@ -29,7 +28,7 @@ export const updateContactBusinessLink = async (data: ContactBusinessLinkVO) =>
// 删除联系人商机关联 // 删除联系人商机关联
export const deleteContactBusinessLink = async (data: ContactBusinessLinkVO) => { export const deleteContactBusinessLink = async (data: ContactBusinessLinkVO) => {
return await request.delete({ url: `/crm/contact-business-link/delete-batch` , data }) return await request.delete({ url: `/crm/contact-business-link/delete-batch`, data })
} }
// 导出联系人商机关联 Excel // 导出联系人商机关联 Excel
@ -43,5 +42,6 @@ export const createContactBusinessLinkBatch = async (data: ContactBusinessLinkVO
} }
// 查询联系人关联商机列表 // 查询联系人关联商机列表
export const getBusinessByContactPage = async (params) => { export const getBusinessByContactPage = async (params) => {
return await request.get({ url: `/crm/contact-business-link/page-by-contact` , params }) return await request.get({ url: `/crm/contact-business-link/page-by-contact`, params })
} }
// TODO @zyna根据后端调整下请求

View File

@ -3,9 +3,11 @@
* @Date: 2023-12-02 13:08:57 * @Date: 2023-12-02 13:08:57
* @LastEditTime: 2023-12-03 13:47:16 * @LastEditTime: 2023-12-03 13:47:16
* @FilePath: \yudao-ui-admin-vue3\src\views\crm\contact\detail\ContactDetailsHeader.vue * @FilePath: \yudao-ui-admin-vue3\src\views\crm\contact\detail\ContactDetailsHeader.vue
* @Description: * @Description:
--> -->
<!-- TODO @zyna上面这个不加哈 -->
<template> <template>
<!-- TODO @zynaloading 缺了 -->
<div v-loading="loading"> <div v-loading="loading">
<div class="flex items-start justify-between"> <div class="flex items-start justify-between">
<div> <div>

View File

@ -65,13 +65,13 @@
</el-collapse> </el-collapse>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// TODO review
import * as ContactApi from '@/api/crm/contact' import * as ContactApi from '@/api/crm/contact'
import { DICT_TYPE } from '@/utils/dict' import { DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime' import { formatDate } from '@/utils/formatTime'
const { contact } = defineProps<{ contact: ContactApi.ContactVO }>() const { contact } = defineProps<{
contact: ContactApi.ContactVO
}>()
// //
const activeNames = ref(['basicInfo', 'systemInfo']) const activeNames = ref(['basicInfo', 'systemInfo'])
</script> </script>
<style scoped lang="scss"></style>

View File

@ -10,12 +10,11 @@
<PermissionList :biz-id="contact.id!" :biz-type="BizTypeEnum.CRM_CONTACT" /> <PermissionList :biz-id="contact.id!" :biz-type="BizTypeEnum.CRM_CONTACT" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="商机" lazy> <el-tab-pane label="商机" lazy>
<BusinessList :biz-id="contact.id!" :biz-type="BizTypeEnum.CRM_CONTACT"/> <BusinessList :biz-id="contact.id!" :biz-type="BizTypeEnum.CRM_CONTACT" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-col> </el-col>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { useTagsViewStore } from '@/store/modules/tagsView' import { useTagsViewStore } from '@/store/modules/tagsView'
@ -27,18 +26,13 @@ import PermissionList from '@/views/crm/permission/components/PermissionList.vue
import { BizTypeEnum } from '@/api/crm/permission' import { BizTypeEnum } from '@/api/crm/permission'
defineOptions({ name: 'CrmContactDetail' }) defineOptions({ name: 'CrmContactDetail' })
const { delView } = useTagsViewStore() //
const route = useRoute() const route = useRoute()
const { currentRoute } = useRouter() // const id = Number(route.params.id) //
const id = Number(route.params.id)
const loading = ref(true) // const loading = ref(true) //
// const contact = ref<ContactApi.ContactVO>({} as ContactApi.ContactVO) //
const contact = ref<ContactApi.ContactVO>({} as ContactApi.ContactVO)
/** /** 获取详情 */
* 获取详情
*
* @param id
*/
const getContactData = async (id: number) => { const getContactData = async (id: number) => {
loading.value = true loading.value = true
try { try {
@ -47,9 +41,10 @@ const getContactData = async (id: number) => {
loading.value = false loading.value = false
} }
} }
/**
* 初始化 /** 初始化 */
*/ const { delView } = useTagsViewStore() //
const { currentRoute } = useRouter() //
onMounted(async () => { onMounted(async () => {
if (!id) { if (!id) {
ElMessage.warning('参数错误,联系人不能为空!') ElMessage.warning('参数错误,联系人不能为空!')

View File

@ -1,7 +1,7 @@
<template> <template>
<Dialog :title="dialogTitle" v-model="dialogVisible"> <Dialog :title="dialogTitle" v-model="dialogVisible">
<!-- 搜索工作栏 -->
<ContentWrap> <ContentWrap>
<!-- 搜索工作栏 -->
<el-form <el-form
class="-mb-15px" class="-mb-15px"
:model="queryParams" :model="queryParams"
@ -27,9 +27,17 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</ContentWrap> </ContentWrap>
<!-- 列表 --> <!-- 列表 -->
<!-- TODO @zyna字段按照他们对齐下 -->
<ContentWrap class="mt-10px"> <ContentWrap class="mt-10px">
<el-table v-loading="loading" ref="businessRef" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table
v-loading="loading"
ref="businessRef"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
>
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="商机名称" fixed="left" align="center" prop="name"> <el-table-column label="商机名称" fixed="left" align="center" prop="name">
<template #default="scope"> <template #default="scope">
@ -38,7 +46,12 @@
</el-link> </el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="商机金额" align="center" prop="price" :formatter="fenToYuanFormat" /> <el-table-column
label="商机金额"
align="center"
prop="price"
:formatter="fenToYuanFormat"
/>
<el-table-column label="客户名称" align="center" prop="customerName" /> <el-table-column label="客户名称" align="center" prop="customerName" />
<el-table-column label="商机组" align="center" prop="statusTypeName" /> <el-table-column label="商机组" align="center" prop="statusTypeName" />
<el-table-column label="商机阶段" align="center" prop="statusName" /> <el-table-column label="商机阶段" align="center" prop="statusName" />
@ -55,6 +68,7 @@
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button> <el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
</template> </template>
<!-- 表单弹窗添加 --> <!-- 表单弹窗添加 -->
<BusinessForm ref="formRef" @success="getList" /> <BusinessForm ref="formRef" @success="getList" />
</Dialog> </Dialog>
@ -62,31 +76,37 @@
<script setup lang="ts"> <script setup lang="ts">
import * as BusinessApi from '@/api/crm/business' import * as BusinessApi from '@/api/crm/business'
import BusinessForm from '../../business/BusinessForm.vue' import BusinessForm from '../../business/BusinessForm.vue'
import { BizTypeEnum } from '@/api/crm/permission'
import { fenToYuanFormat } from '@/utils/formatter' import { fenToYuanFormat } from '@/utils/formatter'
// TODO @zyna
import * as ContactbusinesslinkApi from '@/api/crm/contactbusinesslink' import * as ContactbusinesslinkApi from '@/api/crm/contactbusinesslink'
const message = useMessage() // const message = useMessage() //
defineOptions({ name: 'CrmBusinessLinkContactList' }) defineOptions({ name: 'CrmBusinessLinkContactList' })
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
const dialogTitle = ref('') // const dialogTitle = ref('') // TODO @zyna
const loading = ref(true) // const loading = ref(true) //
const total = ref(0) // const total = ref(0) //
const list = ref([]) // const list = ref([]) //
const queryFormRef = ref() // const queryFormRef = ref() //
const formLoading = ref(false) // 12 const formLoading = ref(false) // 12
const contactIdProp = ref(undefined)
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
name: undefined as unknown, // undefined + number // TODO @zyna customerId
name: undefined
}) })
const contactIdProp = ref(0) //
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (contactId?: number) => { const open = async (contactId: number) => {
dialogVisible.value = true dialogVisible.value = true
contactIdProp.value = contactId contactIdProp.value = contactId
// TODO @zyna await idea
getList() getList()
} }
defineExpose({ open }) // open defineExpose({ open }) // open
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
@ -104,32 +124,38 @@ const handleQuery = () => {
queryParams.pageNo = 1 queryParams.pageNo = 1
getList() getList()
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value.resetFields()
handleQuery() handleQuery()
} }
/** 添加操作 */ /** 添加操作 */
const formRef = ref() const formRef = ref()
const openForm = () => { const openForm = () => {
formRef.value.open('create') formRef.value.open('create')
} }
/**关联商机提交 */
/** 关联商机提交 */
const emit = defineEmits(['success']) // success const emit = defineEmits(['success']) // success
const businessRef = ref() const businessRef = ref()
const submitForm = async () =>{ const submitForm = async () => {
if(businessRef.value.getSelectionRows().length === 0){ // TODO @zyna if return
if (businessRef.value.getSelectionRows().length === 0) {
message.success('未选择商机') message.success('未选择商机')
}else{ } else {
// TODO @zyna postData ref
const postData = ref<ContactbusinesslinkApi.ContactBusinessLinkVO[]>([]) const postData = ref<ContactbusinesslinkApi.ContactBusinessLinkVO[]>([])
businessRef.value.getSelectionRows().forEach(element => { businessRef.value.getSelectionRows().forEach((element) => {
// TODO @zyna push data
let data = { let data = {
id:undefined, id: undefined,
businessId : element.id, businessId: element.id,
contactId : contactIdProp.value contactId: contactIdProp.value
} }
postData.value.push(data) postData.value.push(data)
}); })
await ContactbusinesslinkApi.createContactBusinessLinkBatch(postData.value) await ContactbusinesslinkApi.createContactBusinessLinkBatch(postData.value)
dialogVisible.value = false dialogVisible.value = false
emit('success') emit('success')

View File

@ -5,17 +5,19 @@
<Icon class="mr-5px" icon="ep:opportunity" /> <Icon class="mr-5px" icon="ep:opportunity" />
创建商机 创建商机
</el-button> </el-button>
<el-button @click="openBusinessLink"> <el-button @click="openBusinessLink"> 关联 </el-button>
关联 <el-button @click="deleteBusinessLink"> 解除关联 </el-button>
</el-button>
<el-button @click="deleteBusinessLink">
解除关联
</el-button>
</el-row> </el-row>
<!-- 列表 --> <!-- 列表 -->
<ContentWrap class="mt-10px"> <ContentWrap class="mt-10px">
<el-table v-loading="loading" ref="businessRef" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table
v-loading="loading"
ref="businessRef"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
>
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="商机名称" fixed="left" align="center" prop="name"> <el-table-column label="商机名称" fixed="left" align="center" prop="name">
<template #default="scope"> <template #default="scope">
@ -39,9 +41,9 @@
</ContentWrap> </ContentWrap>
<!-- 表单弹窗添加 --> <!-- 表单弹窗添加 -->
<BusinessForm ref="formRef" @success="getList"/> <BusinessForm ref="formRef" @success="getList" />
<!----> <!---->
<BusinessLink ref="businessLinkRef" @success="getList"/> <BusinessLink ref="businessLinkRef" @success="getList" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import * as ContactBusinessLinkApi from '@/api/crm/contactbusinesslink' import * as ContactBusinessLinkApi from '@/api/crm/contactbusinesslink'
@ -50,6 +52,7 @@ import { BizTypeEnum } from '@/api/crm/permission'
import { fenToYuanFormat } from '@/utils/formatter' import { fenToYuanFormat } from '@/utils/formatter'
import BusinessLink from './BusinessLinkContactList.vue' import BusinessLink from './BusinessLinkContactList.vue'
const message = useMessage() // const message = useMessage() //
// TODO @zyna BusinessList
defineOptions({ name: 'CrmBusinessContactList' }) defineOptions({ name: 'CrmBusinessContactList' })
const props = defineProps<{ const props = defineProps<{
bizType: number // bizType: number //
@ -107,18 +110,18 @@ const openBusinessLink = () => {
/**解除关联 */ /**解除关联 */
const businessRef = ref() const businessRef = ref()
const deleteBusinessLink = async () => { const deleteBusinessLink = async () => {
if(businessRef.value.getSelectionRows().length === 0){ if (businessRef.value.getSelectionRows().length === 0) {
message.success('未选择商机') message.success('未选择商机')
}else{ } else {
const postData = ref<ContactBusinessLinkApi.ContactBusinessLinkVO[]>([]) const postData = ref<ContactBusinessLinkApi.ContactBusinessLinkVO[]>([])
businessRef.value.getSelectionRows().forEach(element => { businessRef.value.getSelectionRows().forEach((element) => {
let data = { let data = {
id:undefined, id: undefined,
businessId : element.id, businessId: element.id,
contactId : props.bizId contactId: props.bizId
} }
postData.value.push(data) postData.value.push(data)
}); })
await ContactBusinessLinkApi.deleteContactBusinessLink(postData.value) await ContactBusinessLinkApi.deleteContactBusinessLink(postData.value)
handleQuery() handleQuery()
} }