Ver código fonte

我的客户-信息概览页-完成除取消预约外的其他接口调用

lm 1 mês atrás
pai
commit
03c234150f

+ 10 - 0
src/api/myCustomer.ts

@@ -128,3 +128,13 @@ export const cancelAppointmentApi = (data:any) => {
         data,
     })
 }
+
+
+// 查度历史跟进信息接口
+export const getHistoryFollowListApi = (data:any) => {
+    return request({
+        url: `${adminPrefix}/api/v1/private/customer/data/follow/history/data`,
+        method: 'post',
+        data,
+    })
+}

+ 0 - 6
src/baseComponents/FormDialog.vue

@@ -235,9 +235,6 @@
               :start-placeholder="item.placeholder.startPlaceholder"
               :end-placeholder="item.placeholder.endPlaceholder"
               type="datetimerange"
-              format="YYYY-MM-DD HH:mm:ss"
-              date-format="YYYY/MM/DD ddd"
-              time-format="A hh:mm:ss"
               :range-separator="item.placeholder.rangeSeparator"
               size="default"
               :disabled="item.disabled"
@@ -504,9 +501,6 @@
               :start-placeholder="item.placeholder.startPlaceholder"
               :end-placeholder="item.placeholder.endPlaceholder"
               type="datetimerange"
-              format="YYYY-MM-DD HH:mm:ss"
-              date-format="YYYY/MM/DD ddd"
-              time-format="A hh:mm:ss"
               :range-separator="item.placeholder.rangeSeparator"
               size="default"
               :disabled="true"

+ 62 - 36
src/views/myCustomer/myCustomerDetail/components/FollowFormDialog/index.vue

@@ -4,7 +4,6 @@
         :submitLoading="editFormDialogSubmitLoading"
         :defaultFormData="defaultFormData"
         :formItemList="finalFormItemList"
-        :formDisabled="formDisabled"
         @close="CloseFormDialog"
         @confirm="HandleConfirmFormDialog"
         @formItemChange="HandleFormItemChange">
@@ -29,15 +28,15 @@ const props = defineProps({
     defaultFormData:{
         type:Object,
         required:true
-    },
+    },  // extraAppointmentType(预约待办的判断标识)  //表单为查看(预览)模式时使用,
     title:{
         type:String,
         default:'写跟进'
     },
-    formDisabled:{
+    previewForm:{
         type:Boolean,
         default:false
-    }
+    }, //是否是查看(预览)表单
 })
 const emit = defineEmits(['confirm'])
 const editFormDialogVisible = defineModel('visible')
@@ -99,27 +98,6 @@ const HandleFormItemChange =(params)=>{
                 formData.position = null
             }
             break
-        case 'appointmentType':
-            if(val === 0){
-                finalFormItemList.value = finalFormItemList.value.map(item=>{
-                    if(item.key == 'appointmentTime'){
-                        item.hidden = false
-                    }else if(item.key == 'todoTime'){
-                        item.hidden = true
-                    }{}
-                    return item
-                })
-            }else if(val === 1){    
-                finalFormItemList.value = finalFormItemList.value.map(item=>{
-                    if(item.key == 'appointmentTime'){
-                        item.hidden = true
-                    }else if(item.key == 'todoTime'){
-                        item.hidden = false
-                    }{}
-                    return item
-                })
-            }
-            break
     }
 }
 
@@ -173,21 +151,69 @@ watch(()=>props?.defaultFormData?.contact,(newVal)=>{
     }
 },{deep:true,immediate:true})
 
-onMounted(async ()=>{
-    await store.dispatch('updateProductList')
-    await store.dispatch('updateFollowUpStatus')
-    await store.dispatch('updatePositionList')
-    await GetContactList()
+// 监听预约待办时间是否展示
+watch([()=>props?.defaultFormData?.appointmentType,
+       ()=>props.previewForm
+],([newTypeVal,newPreviewFormVal])=>{
+    let appointmentTypeFlag = null
+    if(newPreviewFormVal){
+        appointmentTypeFlag = newTypeVal ? props.defaultFormData.extraAppointmentType : null
+    }else{
+        appointmentTypeFlag = newTypeVal
+    }
+    // 0 预约  1 待办
     finalFormItemList.value = finalFormItemList.value.map(item=>{
-        if(item.key == 'product'){
-            item.selectList = store.state.productList
-        }else if(item.key == 'status'){
-            item.selectList = store.state.followUpStatus
-        }else if(item.key == 'position'){
-            item.selectList = store.state.positionList
+        if(item.key == 'appointmentTime'){
+            item.hidden = [0].includes(appointmentTypeFlag) ? false : true
+        }else if(item.key == 'todoTime'){
+            item.hidden = [1].includes(appointmentTypeFlag) ? false : true
         }
         return item
     })
+},{deep:true,immediate:true})
+
+
+watch(()=>props.previewForm,async (newVal)=>{
+    if(newVal){
+        finalFormItemList.value = finalFormItemList.value.map(item=>{
+            switch(item.key){
+                case 'school':
+                case 'product':
+                case 'status':
+                case 'contact':
+                case 'position':
+                case 'content':
+                case 'appointmentTime':
+                case 'todoTime':
+                    item.type = 'text'
+                    break
+                case 'appointmentType':
+                    item.type ='switch'
+                    break
+            }
+            item.rules = []
+            return item
+        })
+    }else{
+        await store.dispatch('updateProductList')
+        await store.dispatch('updateFollowUpStatus')
+        await store.dispatch('updatePositionList')
+        await GetContactList()
+        finalFormItemList.value = finalFormItemList.value.map(item=>{
+            if(item.key == 'product'){
+                item.selectList = store.state.productList
+            }else if(item.key == 'status'){
+                item.selectList = store.state.followUpStatus
+            }else if(item.key == 'position'){
+                item.selectList = store.state.positionList
+            }
+            return item
+        })
+    }
+},{immediate:true})
+
+onMounted(async ()=>{
+    
 })
 </script>
 

+ 12 - 0
src/views/myCustomer/myCustomerDetail/customerStatusOverview/formDialog.ts

@@ -0,0 +1,12 @@
+import { ref } from 'vue'
+
+export const cancelAppointmentFormItemList = ref([
+    {
+        key: 'cancelRemark',
+        label: '取消原因',
+        type: 'textarea',
+        rows: 5,
+        rules: [{ required: true, message: '请输入取消原因', trigger: 'blur' }],
+        placeholder: '请输入取消原因'
+    }
+])

+ 203 - 83
src/views/myCustomer/myCustomerDetail/customerStatusOverview/index.vue

@@ -9,7 +9,7 @@
                 </div>
             </div>
             
-            <div class="product_list">
+            <div class="product_list" v-if="productsFollowStatistic?.length > 0">
                 <template v-for="(item,index) in productsFollowStatistic" :key="item.productId" >
                     <div class="list_item">
                         <div class="item_title">{{item.productName}}</div>
@@ -44,8 +44,8 @@
                 <FollowCard v-if="finalRenderData?.length > 0" style="margin-top: 16px;" :cardList="finalRenderData">
                     <template #operation="{row}">
                         <div style="" class="table_row_option">
-                            <span class="button_delete">取消预约</span>
-                            <span class="option_button_editor" @click="OpenFollowlFormDialog(row)">详情</span>
+                            <span class="button_delete" @click="OpenCancelAppointmentDialog(row)">取消预约</span>
+                            <span class="option_button_editor" @click="OpenFollowlFormDialog(row,'currentFollowRecord')">详情</span>
                         </div>
                     </template>
                 </FollowCard>
@@ -55,8 +55,13 @@
             </div>
 
             <Pagination  :currentPage="currentPage" 
+                :showPageSize="true"
                 :pageSize="pageSize" :totalNum="totalNum"  
-                @paginationChange="HandlePaginationChange" />
+                @paginationChange="HandlePaginationChange">
+                <template #paginationDesc>
+                    共 {{ totalNum }} 条数据
+                </template>
+            </Pagination>
         </div>
 
         <!-- 右侧:待办与统计 -->
@@ -70,7 +75,7 @@
                                 <span class="time">{{cardItm.createdAt}}</span>
                                 <span class="title one_line_ellipsis">{{cardItm.productName}}</span>
                                 <div class="table_row_option">
-                                    <span class="button_editor"@click="OpenFollowlFormDialog(cardItm)">详情</span>
+                                    <span class="button_editor"@click="OpenFollowlFormDialog(cardItm,'pendingAppointment')">详情</span>
                                 </div>
                             </div>
                             <div class="card_tags">
@@ -133,8 +138,9 @@
 
     <!-- 查看跟进详情 -->
     <FollowFormDialog 
+        v-if="followVisible"
         title="查看详情"
-        :formDisabled="true"
+        :previewForm="true"
         v-model:visible="followVisible" 
         :defaultFormData="followDefaultFormData">
     </FollowFormDialog>
@@ -146,14 +152,19 @@
         :previewVisible="historyFollowVisible"
         :customFooter="true"
         @close="CloseHistoryFollowDialog">
-        <SearchBlock :searchList="historyFollowSearchList"></SearchBlock>
-        <FollowCard style="margin-top: 16px;" :cardList="finalRenderCard">
+        <SearchBlock :searchList="historyFollowSearchList" @searchChange="HandleSearchHistoryFollow"></SearchBlock>
+        <FollowCard style="margin-top: 16px;" :cardList="historyFollowRecord">
             <template #operation>
                 <i></i>
             </template>
         </FollowCard>
         <Pagination :currentPage="historyCurrentPage" 
-            :pageSize="historyPageSize" :totalNum="historyTotalNum">
+            :showPageSize="true"
+            :pageSize="historyPageSize" :totalNum="historyTotalNum" 
+            @paginationChange="HandleHistoryPageChange">
+            <template #paginationDesc>
+                共 {{ historyTotalNum }} 条数据
+            </template>
         </Pagination>
         <template #close>
             <el-button @click="CloseHistoryFollowDialog" class="button_background" >关闭</el-button>
@@ -161,6 +172,27 @@
         <template #confirm><i></i></template>
      </PreviewDialog>
 
+    <!-- 取消预约弹窗 -->
+    <FormDialog    
+        width="640px"
+        title="取消预约"
+        :visible="cancelVisible" 
+        :formItemList="cancelAppointmentFormItemList" 
+        :submitLoading="cancelLoading"
+        :defaultFormData="cancelDefaultFormData"
+        @close="CloseCancelAppointmentDialog"
+        @confirm="HandleCancelAppointmentConfirm">
+
+        <template #form_pre>
+            <span style="margin-bottom: 16px;color:#333333">
+                {{ cancelDefaultFormData.claimDatetime}} &nbsp;
+                {{ cancelDefaultFormData.customerName }}
+            </span>
+        </template>
+    </FormDialog>
+
+
+
 </template>
 
 <script setup lang="ts">
@@ -173,8 +205,10 @@ import FollowCard from '@/components/FollowCard.vue';
 import Pagination from '@/baseComponents/Pagination.vue';
 import FollowFormDialog from '../components/FollowFormDialog/index.vue'
 import PreviewDialog from '@/baseComponents/PreviewDialog.vue';
+import FormDialog from '@/baseComponents/FormDialog.vue';
+import { cancelAppointmentFormItemList } from './formDialog';
 
-import {getOverviewDetailApi} from '@/api/myCustomer'
+import {getOverviewDetailApi,cancelAppointmentApi,getHistoryFollowListApi} from '@/api/myCustomer'
 import {
     getTodayRange,
     getYesterdayRange,
@@ -297,7 +331,7 @@ const GetOverviewDetail = async ()=>{
         // 跟进产品-各自分析 ——左
         productsFollowStatistic.value = productData || []
         // 历史跟进统计 —— 右
-        historyFollowData.value = followOverViewData
+        historyFollowData.value = followOverViewData || {}
         //预约待办展示 —— 右
         pendingAppointmentList.value = orderData || []
         // 中间 正在进行中的跟进记录 —— 中
@@ -325,7 +359,8 @@ const GetOverviewDetail = async ()=>{
                     `职务:${item.positionName}`
                 ],
                 taskType:[0,1].includes(item.orderType) ? (item.orderType === 0 ? '预约' : '待办') : '',
-                bottomDesc:`跟进内容:${item.followContent}`
+                bottomDesc:`跟进内容:${item.followContent}`,
+                ...item,
             }
         }) || []
         const {
@@ -352,6 +387,7 @@ const GetOverviewDetail = async ()=>{
                 value:item.id
             }
         })
+        // 头部筛选项赋值
         ongoingFollowSearchList.value = ongoingFollowSearchList.value.map(item=>{
             switch(item.key){
                 case 'product':
@@ -419,98 +455,182 @@ const historyFollowData = ref({
 
 
 /**
- * 4. 
+ * 4. 预约待办/客户 跟进弹窗详情(查看)有关数据及操作 
  */
-/** 跟进弹窗详情(查看)有关数据及操作  */
 const followVisible = ref(false)
 const followDefaultFormData = ref({})
-const OpenFollowlFormDialog = (row)=>{
+const OpenFollowlFormDialog = (row,type)=>{
+    console.log('当前行信息',row)
     followVisible.value = true
     followDefaultFormData.value = {
-        ...row,
-        // school:customerBaseMsg.value.schoolName,
+        school:row.customerName,
+        product:row.productName,
+        status:row.followName,
+        contact:row.customerPersonName,
+        position:row.positionName,
+        content:row.followContent,
+        appointmentType:[0,1].includes(row.orderType),
+        appointmentTime:row.orderDatetime,
+        todoTime:row.orderDatetime,
+        extraAppointmentType:row.orderType,  //查看时候的附加值
+    }
+}
+
+/**
+ * 5. 取消预约有关操作 —— 待完善
+ */
+const cancelVisible = ref(false)
+const cancelDefaultFormData = ref({})
+const cancelLoading = ref(false)
+const OpenCancelAppointmentDialog = async (row)=>{
+    cancelVisible.value = true
+    cancelDefaultFormData.value = row
+}
+const CloseCancelAppointmentDialog = ()=>{
+    cancelVisible.value = false
+    cancelDefaultFormData.value = {}
+    cancelLoading.value = false
+}
+// 取消预约确认 —— 待完善
+const HandleCancelAppointmentConfirm = async (params)=>{
+    cancelLoading.value = true
+    const {formData} = params
+    let finalParams = {
+       id: formData.id,
+        cancelRemark: formData.cancelRemark
+    }
+    let res = await cancelAppointmentApi(finalParams)
+    if(res?.code == 200){
+        CloseCancelAppointmentDialog()
+        // 刷新预约待办数据
+        await GetOverviewDetail()
+    }else{
+        cancelLoading.value = false
     }
 }
 
 
-/** 查看历史跟进 弹窗有关数据  */
+
+/** 6. 查看历史跟进 弹窗有关数据  */
 const historyFollowVisible = ref(false)
-const OpenHistoryFollowDialog = (row)=>{
+const OpenHistoryFollowDialog = async (row)=>{
     historyFollowVisible.value = true
+    await GetHistoryFollowList()
 }
 const CloseHistoryFollowDialog = ()=>{
     historyFollowVisible.value = false
 }
 // 历史跟进记录 列表信息
-const historyFollowRecord = ref([
-  {
-    id:'1',
-    date: '26-02-19 19:00',
-    product: '大数据精准教学',
-    status: '试用测试',
-    tracker: '张三',
-    contactPerson: '严谨',
-    position: '校长',
-    content: '跟进文案跟进文案跟进文案跟进文案跟进文案北京市东城区葱店西街56号跟进文案跟进文案跟进文案跟进文案跟进文案北京市东城区葱店西街56号',
-    scheduleType: '', // 预约 / 待办
-    scheduleTime: ''
-  },
-  {
-    id:'2',
-    date: '26-02-19 16:00',
-    product: '智能判分系统',
-    status: '方案演示',
-    tracker: '张三',
-    contactPerson: '严谨',
-    position: '校长',
-    content: '跟进文案跟进文案跟进文案跟进文案跟进文案北京市东城区葱店西街56号跟进文案跟进文案跟进文案跟进文案跟进文案北京市东城区葱店西街56号',
-    scheduleType: '预约',
-    scheduleTime: '26-02-09 12:00'
-  },
-  {
-    id:'3',
-    date: '26-02-18 19:00',
-    product: '大数据精准教学',
-    status: '试用测试',
-    tracker: '张三',
-    contactPerson: '严谨',
-    position: '校长',
-    content: '跟进文案跟进文案跟进文案跟进文案跟进文案北京市东城区葱店西街56号跟进文案跟进文案跟进文案跟进文案跟进文案北京市东城区葱店西街56号',
-    scheduleType: '待办',
-    scheduleTime: '26-02-09 12:00'
-  }
-]);
-
-const finalRenderCard = historyFollowRecord.value.map(item=>{
-
-    let middleDesc = [
-        `跟进人:${item.tracker}`,
-        `联系人:${item.contactPerson}`,
-        `职务:${item.position}`
-    ]
-
-    if(item.scheduleType =='预约'){
-        middleDesc.push(`预约时间:${item.scheduleTime}`)
-    }else if(item.scheduleTime == '待办'){
-        middleDesc.push(`待办时间:${item.scheduleTime}`)
-
-    }
-    return {
-        id:item.id,
-        headerTitleList:[item.date,item.product],
-        headerTags:[item.status],
-        taskType:item.scheduleType,
-        middleDesc,
-        bottomDesc:`跟进内容:${item.content}`,
-    }
-})
-
+const historyFollowRecord = ref([])
 // 分页参数
 const historyCurrentPage = ref(1)
-const historyPageSize = ref(10)
+const historyPageSize = ref(20)
 const historyTotalNum = ref(0)
 
+const historySearchParams = ref({
+    product:'all',
+    followStatus:'all',
+    personnel:'all',
+})
 
+// 历史跟进记录 分页参数变更
+const HandleHistoryPageChange = async (params)=>{
+    const {type,val} = params
+    if(type == 'currentPage'){
+        historyCurrentPage.value = val
+    }else if(type == 'pageSize'){
+        historyPageSize.value = val
+    }
+    await GetHistoryFollowList()
+}
+
+// 历史跟进记录 筛选条件变更
+const HandleSearchHistoryFollow = async (params,key)=>{
+    historySearchParams.value = {
+        ...historySearchParams.value,
+        ...params
+    }
+    await GetHistoryFollowList()
+}
+
+// 获取历史跟进列表
+const GetHistoryFollowList = async ()=>{
+    let prams = {
+        customerId: route.query.id,
+        productId: historySearchParams.value.product == 'all' ? '' : historySearchParams.value.product,
+        followId: historySearchParams.value.followStatus == 'all' ? '' : historySearchParams.value.followStatus,
+        userId: historySearchParams.value.personnel == 'all' ? '' : historySearchParams.value.personnel,
+        pageNum: historyCurrentPage.value,
+        pageSize: historyPageSize.value
+    }
+    let res = await getHistoryFollowListApi(prams)
+    if(res.code == 200){
+        const {dataPageList, selectData} = res.data
+
+        const {productData, memberData, followData} = selectData || {}
+
+        historyFollowRecord.value = dataPageList.records?.map(item=>{
+            let middleDesc = [
+                `跟进人:${item.claimUserName}`,
+                `联系人:${item.customerPersonName}`,
+                `职务:${item.positionName}`
+            ]
+            if(item.orderType === 0) {
+                middleDesc.push(`预约时间:${item.orderDatetime}`)
+            }else if(item.orderType === 1){
+                middleDesc.push(`待办时间:${item.orderDatetime}`)
+            }
+            return {
+                headerTitleList:[item.claimDatetime,item.productName],
+                headerTags:[item.followName],
+                taskType:[0,1].includes(item.orderType) ? (item.orderType == 0 ? '预约' : '待办') : '',
+                middleDesc,
+                bottomDesc:`跟进内容:${item.followContent}`,
+                ...item,
+            }
+        })
+        historyTotalNum.value = dataPageList.total
+
+        const followDataOption = followData?.map(item=>{
+            return{
+                label:item.name,
+                value:item.id,
+            }
+        })
+        const productDataOption = productData?.map(item=>{
+            return{
+                label:item.name,
+                value:item.id,
+            }
+        })
+        const memberDataOption = memberData?.map(item=>{
+            return{
+                label:item.username,
+                value:item.id,
+            }
+        })
+        historyFollowSearchList.value = historyFollowSearchList.value.map(item=>{
+            if(item.key == 'product'){
+                item.options = [
+                    { label: '全部', value: 'all' },
+                    ...productDataOption
+                ]
+            }else if(item.key == 'personnel'){
+                item.options = [
+                    { label: '全部', value: 'all' },
+                    ...memberDataOption
+                ]
+            }else if(item.key == 'followStatus'){
+                item.options = [
+                    { label: '全部', value: 'all' },
+                    ...followDataOption
+                ]
+            }
+            item.defaultValue = historySearchParams.value[item.key]
+            return item
+        }) 
+    }
+}
 
 
 watch(()=>props.followReloadFlag,async (newVal)=>{

+ 4 - 28
src/views/myCustomer/myCustomerDetail/customerStatusOverview/searchBlock.ts

@@ -47,45 +47,21 @@ export const historyFollowSearchList = ref([
     label: '产品',
     key: 'product',
     type: 'single',
-    options: [
-      { label: '全部', value: 'all' },
-      { label: '大数据教学诊断', value: 'bigDataTeachingDiagnosis' },
-      { label: '智能判分', value: 'intelligentGrading' },
-      { label: '材料采集', value: 'materialCollection' },
-      { label: '校内通知', value: 'inSchoolNotification' },
-      { label: '校本研修', value: 'schoolBasedResearch' },
-      { label: '协同备课', value: 'collaborativeLessonPreparation' }
-    ],
+    options: [],
     defaultValue: 'all'
   },
   {
     label: '人员',
     key: 'personnel',
     type: 'single',
-    options: [
-      { label: '全部', value: 'all' },
-      { label: '员工1', value: 'employee1' },
-      { label: '员工2', value: 'employee2' },
-      { label: '员工3', value: 'employee3' },
-      { label: '员工4', value: 'employee4' },
-      { label: '员工5', value: 'employee5' }
-    ],
+    options: [],
     defaultValue: 'all'
   },
   {
     label: '状态',
-    key: 'status',
+    key: 'followStatus',
     type: 'single',
-    options: [
-      { label: '全部', value: 'all' },
-      { label: '线索建立', value: 'leadEstablishment' },
-      { label: '需求调研', value: 'requirementResearch' },
-      { label: '方案演示', value: 'proposalDemo' },
-      { label: '试用测试', value: 'trialTest' },
-      { label: '项目搁置', value: 'projectOnHold' },
-      { label: '输单', value: 'loss' },
-      { label: '赢单', value: 'win' }
-    ],
+    options: [],
     defaultValue: 'all'
   }
 ])