瀏覽代碼

✨ CRM:完善商机和联系人之间的关联

YunaiV 1 年之前
父節點
當前提交
8512fe6b43

+ 5 - 0
src/api/crm/contact/index.ts

@@ -47,6 +47,11 @@ export const getContactPageByCustomer = async (params: any) => {
   return await request.get({ url: `/crm/contact/page-by-customer`, params })
 }
 
+// 查询 CRM 联系人列表,基于指定商机
+export const getContactPageByBusiness = async (params: any) => {
+  return await request.get({ url: `/crm/contact/page-by-business`, params })
+}
+
 // 查询 CRM 联系人详情
 export const getContact = async (id: number) => {
   return await request.get({ url: `/crm/contact/get?id=` + id })

+ 23 - 4
src/views/crm/business/BusinessForm.vue

@@ -31,7 +31,12 @@
         </el-col>
         <el-col :span="8">
           <el-form-item label="客户名称" prop="customerId">
-            <el-select v-model="formData.customerId" placeholder="请选择客户" class="w-1/1">
+            <el-select
+              :disabled="formData.customerDefault"
+              v-model="formData.customerId"
+              placeholder="请选择客户"
+              class="w-1/1"
+            >
               <el-option
                 v-for="item in customerList"
                 :key="item.id"
@@ -158,7 +163,9 @@ const formData = ref({
   totalProductPrice: undefined,
   totalPrice: undefined,
   remark: undefined,
-  products: []
+  products: [],
+  contactId: undefined,
+  customerDefault: false
 })
 const formRules = reactive({
   name: [{ required: true, message: '商机名称不能为空', trigger: 'blur' }],
@@ -197,7 +204,7 @@ watch(
 )
 
 /** 打开弹窗 */
-const open = async (type: string, id?: number) => {
+const open = async (type: string, id?: number, customerId?: number, contactId?: number) => {
   dialogVisible.value = true
   dialogTitle.value = t('action.' + type)
   formType.value = type
@@ -210,7 +217,17 @@ const open = async (type: string, id?: number) => {
     } finally {
       formLoading.value = false
     }
+  } else {
+    if (customerId) {
+      formData.value.customerId = customerId
+      formData.value.customerDefault = true // 默认客户的选择,不允许变
+    }
+    // 自动关联 contactId 联系人编号
+    if (contactId) {
+      formData.value.contactId = contactId
+    }
   }
+  // 获得客户列表
   customerList.value = await CustomerApi.getCustomerSimpleList()
   // 加载商机状态类型列表
   statusTypeList.value = await BusinessStatusApi.getBusinessStatusTypeSimpleList()
@@ -264,7 +281,9 @@ const resetForm = () => {
     totalProductPrice: undefined,
     totalPrice: undefined,
     remark: undefined,
-    products: []
+    products: [],
+    contactId: undefined,
+    customerDefault: false
   }
   formRef.value?.resetFields()
 }

+ 2 - 1
src/views/crm/business/components/BusinessList.vue

@@ -76,6 +76,7 @@ const props = defineProps<{
   bizType: number // 业务类型
   bizId: number // 业务编号
   customerId?: number // 关联联系人与商机时,需要传入 customerId 进行筛选
+  contactId?: number // 特殊:联系人编号;在【联系人】详情中,可以传递联系人编号,默认新建的商机关联到该联系人
 }>()
 
 const loading = ref(true) // 列表的加载中
@@ -125,7 +126,7 @@ const handleQuery = () => {
 /** 添加操作 */
 const formRef = ref()
 const openForm = () => {
-  formRef.value.open('create')
+  formRef.value.open('create', null, props.customerId, props.contactId)
 }
 
 /** 打开联系人详情 */

+ 9 - 8
src/views/crm/business/detail/index.vue

@@ -15,6 +15,14 @@
       <el-tab-pane label="详细资料">
         <BusinessDetailsInfo :business="business" />
       </el-tab-pane>
+      <el-tab-pane label="联系人" lazy>
+        <ContactList
+          :biz-id="business.id!"
+          :biz-type="BizTypeEnum.CRM_BUSINESS"
+          :business-id="business.id"
+          :customer-id="business.customerId"
+        />
+      </el-tab-pane>
       <el-tab-pane label="操作日志">
         <OperateLogV2 :log-list="logList" />
       </el-tab-pane>
@@ -27,13 +35,6 @@
           @quit-team="close"
         />
       </el-tab-pane>
-      <el-tab-pane label="商机" lazy>
-        <BusinessList
-          :biz-id="business.id!"
-          :biz-type="BizTypeEnum.CRM_CONTACT"
-          :customer-id="business.customerId"
-        />
-      </el-tab-pane>
     </el-tabs>
   </el-col>
   <!-- 表单弹窗:添加/修改 -->
@@ -46,7 +47,6 @@ import * as ContactApi from '@/api/crm/contact'
 import * as BusinessApi from '@/api/crm/business'
 import BusinessDetailsHeader from './BusinessDetailsHeader.vue'
 import BusinessDetailsInfo from './BusinessDetailsInfo.vue'
-import BusinessList from '@/views/crm/business/components/BusinessList.vue' // 商机列表
 import PermissionList from '@/views/crm/permission/components/PermissionList.vue' // 团队成员列表(权限)
 import { BizTypeEnum } from '@/api/crm/permission'
 import { OperateLogV2VO } from '@/api/system/operatelog'
@@ -54,6 +54,7 @@ import { getOperateLogPage } from '@/api/crm/operateLog'
 import ContactForm from '@/views/crm/contact/ContactForm.vue'
 import CrmTransferForm from '@/views/crm/permission/components/TransferForm.vue'
 import FollowUpList from '@/views/crm/followup/index.vue'
+import ContactList from '@/views/crm/contact/components/ContactList.vue'
 
 defineOptions({ name: 'CrmBusinessDetail' })
 

+ 15 - 18
src/views/crm/business/index.vue

@@ -38,6 +38,11 @@
 
   <!-- 列表 -->
   <ContentWrap>
+    <el-tabs v-model="activeName" @tab-click="handleTabClick">
+      <el-tab-pane label="我负责的" name="1" />
+      <el-tab-pane label="我参与的" name="2" />
+      <el-tab-pane label="下属负责的" name="3" />
+    </el-tabs>
     <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
       <el-table-column align="center" label="商机名称" fixed="left" prop="name" width="160">
         <template #default="scope">
@@ -157,6 +162,7 @@ import download from '@/utils/download'
 import * as BusinessApi from '@/api/crm/business'
 import BusinessForm from './BusinessForm.vue'
 import { erpPriceTableColumnFormatter } from '@/utils'
+import { TabsPaneContext } from 'element-plus'
 
 defineOptions({ name: 'CrmBusiness' })
 
@@ -169,27 +175,12 @@ const list = ref([]) // 列表的数据
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
-  name: null,
-  statusTypeId: null,
-  statusId: null,
-  contactNextTime: [],
-  customerId: null,
-  dealTime: [],
-  price: null,
-  discountPercent: null,
-  productPrice: null,
-  remark: null,
-  ownerUserId: null,
-  createTime: [],
-  roUserIds: null,
-  rwUserIds: null,
-  endStatus: null,
-  endRemark: null,
-  contactLastTime: [],
-  followUpStatus: null
+  sceneType: '1', // 默认和 activeName 相等
+  name: null
 })
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
+const activeName = ref('1') // 列表 tab
 
 /** 查询列表 */
 const getList = async () => {
@@ -215,6 +206,12 @@ const resetQuery = () => {
   handleQuery()
 }
 
+/** tab 切换 */
+const handleTabClick = (tab: TabsPaneContext) => {
+  queryParams.sceneType = tab.paneName
+  handleQuery()
+}
+
 /** 打开客户详情 */
 const { currentRoute, push } = useRouter()
 const openDetail = (id: number) => {

+ 24 - 4
src/views/crm/contact/ContactForm.vue

@@ -33,7 +33,12 @@
       <el-row>
         <el-col :span="12">
           <el-form-item label="客户名称" prop="customerId">
-            <el-select v-model="formData.customerId" placeholder="请选择客户" class="w-1/1">
+            <el-select
+              :disabled="formData.customerDefault"
+              v-model="formData.customerId"
+              placeholder="请选择客户"
+              class="w-1/1"
+            >
               <el-option
                 v-for="item in customerList"
                 :key="item.id"
@@ -198,7 +203,9 @@ const formData = ref({
   master: false,
   post: undefined,
   parentId: undefined,
-  remark: undefined
+  remark: undefined,
+  businessId: undefined,
+  customerDefault: false
 })
 const formRules = reactive({
   name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
@@ -212,7 +219,7 @@ const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表
 const contactList = ref<ContactApi.ContactVO[]>([]) // 联系人列表
 
 /** 打开弹窗 */
-const open = async (type: string, id?: number) => {
+const open = async (type: string, id?: number, customerId?: number, businessId?: number) => {
   dialogVisible.value = true
   dialogTitle.value = t('action.' + type)
   formType.value = type
@@ -225,8 +232,19 @@ const open = async (type: string, id?: number) => {
     } finally {
       formLoading.value = false
     }
+  } else {
+    if (customerId) {
+      formData.value.customerId = customerId
+      formData.value.customerDefault = true // 默认客户的选择,不允许变
+    }
+    // 自动关联 businessId 商机编号
+    if (businessId) {
+      formData.value.businessId = businessId
+    }
   }
+  // 获得联系人列表
   contactList.value = await ContactApi.getSimpleContactList()
+  // 获得客户列表
   customerList.value = await CustomerApi.getCustomerSimpleList()
   // 获得地区列表
   areaList.value = await AreaApi.getAreaTree()
@@ -284,7 +302,9 @@ const resetForm = () => {
     master: false,
     post: undefined,
     parentId: undefined,
-    remark: undefined
+    remark: undefined,
+    businessId: undefined,
+    customerDefault: false
   }
   formRef.value?.resetFields()
 }

+ 7 - 2
src/views/crm/contact/components/ContactList.vue

@@ -25,7 +25,6 @@
           <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.master" />
         </template>
       </el-table-column>
-      <!-- TODO 芋艿:【操作:设为首要联系人】 -->
     </el-table>
     <!-- 分页 -->
     <Pagination
@@ -49,6 +48,8 @@ defineOptions({ name: 'CrmContactList' })
 const props = defineProps<{
   bizType: number // 业务类型
   bizId: number // 业务编号
+  customerId: number // 特殊:客户编号;在【商机】详情中,可以传递客户编号,默认新建的联系人关联到该客户
+  businessId: number // 特殊:商机编号;在【商机】详情中,可以传递商机编号,默认新建的联系人关联到该商机
 }>()
 
 const loading = ref(true) // 列表的加载中
@@ -73,6 +74,10 @@ const getList = async () => {
         queryParams.customerId = props.bizId
         data = await ContactApi.getContactPageByCustomer(queryParams)
         break
+      case BizTypeEnum.CRM_BUSINESS:
+        queryParams.businessId = props.bizId
+        data = await ContactApi.getContactPageByBusiness(queryParams)
+        break
       default:
         return
     }
@@ -92,7 +97,7 @@ const handleQuery = () => {
 /** 添加操作 */
 const formRef = ref()
 const openForm = () => {
-  formRef.value.open('create')
+  formRef.value.open('create', undefined, props.customerId, props.businessId)
 }
 
 /** 打开联系人详情 */

+ 1 - 0
src/views/crm/contact/detail/index.vue

@@ -32,6 +32,7 @@
           :biz-id="contact.id!"
           :biz-type="BizTypeEnum.CRM_CONTACT"
           :customer-id="contact.customerId"
+          :contact-id="contact.id"
         />
       </el-tab-pane>
     </el-tabs>