Browse Source

海外客户列表

Karsa 10 tháng trước cách đây
mục cha
commit
b5c63389d9

+ 12 - 11
src/router/modules/customRoutes.js

@@ -266,17 +266,18 @@ export default [
           title: '客户区域统计'
         },
       },
-      // {
-      //   path: "regionCustomerDetail",
-      //   component: () => import("@/views/custom_manage/customList/regionCustomDetail.vue"),
-      //   name: "正式客户列表",
-      //   hidden: false,
-      //   meta: {
-      //     pathFrom: "regionCustomerList",
-      //     pathName: "客户区域统计",
-      //     keepAlive: false,
-      //   },
-      // },
+      {
+        path: "regionCustomerDetail",
+        component: () => import("@/views/custom_manage/custom/regionCustomDetail.vue"),
+        name: "regionCustomerDetail",
+        hidden: false,
+        meta: {
+          title: '正式客户列表',
+          pathFrom: "regionCustomerList",
+          pathName: "客户区域统计",
+          keepAlive: false,
+        },
+      },
       {
         path: "contactsList",
         component: () => import("@/views/custom_manage/contacts/contactsList.vue"),

+ 22 - 77
src/views/custom_manage/custom/hooks/customlistHook.js

@@ -41,83 +41,6 @@ export function customListHook(){
 		isShareRecodeDialogShow.value = true
 		customInfo.value = data
 	}
-/* 切换标签状态 */
-// const changeTagStatus=({ TryStage })=>{
-// 	act_trialTag.value = TryStage;
-// 	this.$refs.userTable.clearSort();
-// 	this.sort_type =  '';
-// 	this.sort_param = '';
-// 	this.SortByTodo = false;
-// 	this.page_no = 1;
-// 	this.getTableData()
-// }
-
-/* 改变客户的试用标签 */
-// changeTrialHandle({ CompanyId },trialItem) {
-// 	const { ProductId,TryStage } = trialItem;
-
-// 	customInterence.setTrialTag({
-// 		CompanyId,
-// 		ProductId,
-// 		TryStage
-// 	}).then(res => {
-// 		if(res.Ret !== 200) return
-// 		this.$message.success('设置成功');
-
-// 		this.getTableData()
-// 	})
-// },
-
-/* 打开 累计试用天数弹窗 */
-// handleTotalDayClick(data){
-// 	this.isTotalDayDialogShow = true
-// 	this.customInfo = data
-// },
-/* 打开关闭理由弹窗 */
-// openCloseReasonDialog(data){
-// 	this.customInfo = data
-// 	this.closeReason=''
-// 	this.isCloseCustomDialogShow = true
-// },
-/* 关闭客户 */
-// closeCustom(){
-// 	if(!this.closeReason){
-// 		this.$message.warning('请填写关闭理由')
-// 		return
-// 	}
-// 	customInterence.closeCustom({
-// 		CompanyId:this.customInfo.CompanyId,
-// 		Remark:this.closeReason
-// 	}).then(res=>{
-// 		if(res.Ret!==200) return 
-// 		this.getTableData()
-// 		this.$message.success('关闭客户成功')
-// 		this.isCloseCustomDialogShow = false
-// 	})
-	
-// },
-/* 确认将客户转流失 */
-// turnLose(data){
-// 	this.$confirm(`是否确认将【${data.CompanyName}】转为流失客户?`,'提示',{
-// 		confirmButtonText:'确认',
-// 		cancelButtonText:'取消',
-// 		type: 'warning'
-// 	}).then(()=>{
-// 		customInterence.turnLose({
-// 			CompanyId:data.CompanyId
-// 		}).then(res=>{
-// 			if(res.Ret!==200) return 
-// 			this.getTableData()
-// 			this.$message.success('转流失成功')
-// 		})
-		
-// 	}).catch(()=>{})
-// },
-/* 筛选所属区域 */
-// changeFromArea(){
-// 	this.page_no = 1;
-// 	this.getTableData()
-// },
 	return {
 		isShareRecodeDialogShow,
 		customInfo,
@@ -188,6 +111,28 @@ export function useClickNumDia() {
 }
 
 
+/* 沟通记录弹窗 */
+export function useCommunicaRecordDia() {
+	const customInfo = ref({})
+	const isShareRecodeDialogShow = ref(false)//控制服务记录弹窗
+	const allowEdit = ref(true)//是否允许编辑服务记录
+
+	 //打开服务记录弹窗
+	function handleShowShareRecode(data,type=''){
+			if(data.ServiceTimes===0&&type==='list') return
+			allowEdit.value = type==='list'?false:true
+			isShareRecodeDialogShow.value = true
+			customInfo.value = data
+	}
+
+	return {
+		customInfo,
+		isShareRecodeDialogShow,
+		allowEdit,
+		handleShowShareRecode
+	}
+}
+
 export function useViewPermissionDia() {
 	
 }

+ 323 - 0
src/views/custom_manage/custom/regionCustomDetail.vue

@@ -0,0 +1,323 @@
+<script setup>
+import { ref,computed } from 'vue';
+import { useRoute } from 'vue-router'
+import { dataMainInterface,customInterence } from '@/api/api.js';
+import mPage from '@/components/mPage.vue';
+
+const route = useRoute()
+
+const tableColumns =[
+  {
+    label: '客户名称',
+    key: 'CompanyName',
+    minwidthsty: '180px',
+  },
+  {
+    label: '客户类型',
+    key: 'CompanyType',
+    widthsty: '80px',
+  },
+  {
+    label: '所属行业',
+    key: 'IndustryName',
+  },
+  {
+    label: '客户地址',
+    key: 'City',
+    widthsty: '110px',
+  },
+  {
+    label: '所属销售',
+    key: 'SellerName',
+  },
+  {
+    label: '分配销售',
+    key: 'ShareSeller',
+  },
+  {
+    label: '客户状态',
+    key: 'Status',
+    // widthsty: '180px',
+  },
+  {
+    label: '累计阅读次数',
+    key: 'viewTotal',
+  },
+  {
+    label: '累计路演次数',
+    key: 'RoadShowTotal',
+  },
+  {
+    label: '最近一次阅读时间',
+    key: 'LastViewTime',
+    widthsty: '200px',
+  },
+  {
+    label: '服务期限',
+    key: 'EndDate',
+    minwidthsty: '180px',
+  },
+  {
+    label: '到期天数',
+    key: 'ExpireDay',
+    widthsty: '110px'
+  }
+]
+
+const title = route.query.title||'';
+const ids = decodeURIComponent(route.query.ids)
+const showMore = computed(() =>{
+  const AdminName = localStorage.getItem('AdminName')
+  return AdminName==='ydlou'
+})
+const tableColumnsComputed = computed(() =>{
+  if(title.includes('正式')){
+    return tableColumns
+  }else{
+    return tableColumns.filter(item => item.label!='分配销售')
+  }
+})
+
+
+const total = ref(0)
+const page_no = ref(1)
+const pageSize = ref(10)
+const sort_obj = ref({
+  param: '',
+  type: ''
+})
+const tableData = ref([])
+function getTableData() {
+  const { param, type } = sort_obj.value;
+
+  dataMainInterface.newcustomList({
+    PageSize: pageSize.value,
+    CurrentIndex: page_no.value,
+    SortParam: param,
+    SortType: type,
+    CompanyIds: ids
+  }).then(res => {
+    const { Ret,Data } = res;
+    if(Ret !== 200) return
+
+    total.value = res.Data.Paging.Totals;
+    tableData.value = Data.List || [];
+  })
+}
+getTableData()
+
+function sortChangeHandle({ prop,order }) {
+  page_no.value = 1;
+
+  const typeMap = {
+    'RoadShowTotal': 'roadShowTotal',
+    'LastViewTime': 'viewTime',
+    'ExpireDay': 'expireDay',
+  }
+
+  sort_obj.value = {
+    type: order === 'ascending' ? 'asc' : order === 'descending' ? 'desc' : '',
+    param: typeMap[prop] || prop
+  }
+  getTableData();
+}
+
+/* 切换页码 */
+function handleCurrentChange(page) {
+  page_no.value = page;
+  getTableData();
+}
+
+
+/* 获取客户套餐详情 */
+const showMoreText = ref('加载中...')
+function getCustomDetail(row,column){
+  showMoreText.value = '加载中...'
+  if(column.label!=='客户类型') return
+  if(!showMore.value) return 
+  customInterence.lookauth({
+    CompanyId:row.CompanyId
+  }).then(res=>{
+    if(res.Ret!==200) return 
+    const ficcList = res.Data.List||[]
+    const raiList = res.Data.ListRai||[]
+    let ficcStr = formatStr(ficcList)
+    let raiStr = formatStr(raiList)
+    //console.log('text',ficcStr+raiStr)
+    showMoreText.value = ficcStr+raiStr
+  })
+}
+
+function formatStr(list){
+  let showText = ''
+  list.forEach(item=>{
+    const listName = item.ClassifyName
+    let itemNames = []
+    if(item.Items&&item.Items.length){
+      item.Items.forEach(i=>{
+        if(i.Status&&i.Status!=='关闭'){
+          itemNames.push(`${i.PermissionName}${i.PermissionTypeName?'('+i.PermissionTypeName+')':''}`)
+        }
+      })
+    }
+    if(itemNames.length){
+      showText+=`${listName}:${itemNames.join('、')}<br/>`
+    }
+  })
+  return showText
+}
+
+
+</script>
+<template>
+  <div class="region-custom-detail">
+    <span class="title">{{title}}</span>
+    <div class="list">
+        <el-table
+            :data="tableData"
+            @sort-change="sortChangeHandle"
+            border
+            class="table-cont"
+            @cell-mouse-enter="getCustomDetail"
+        >
+            <el-table-column
+                v-for="item in tableColumnsComputed"
+                :key="item.label"
+                :label="item.label"
+                :width="item.widthsty"
+                :min-width="item.minwidthsty"
+                :prop="item.key"
+                align="center"
+                :sortable="['viewTotal','RoadShowTotal','LastViewTime','ExpireDay'].includes(item.key) ? 'custom' : false"
+            >
+                <template #default="{row}">
+
+                    <span v-if="item.key === 'CompanyName'" class="customName">
+                        {{row.CompanyName}}
+                    </span>
+
+                    <span v-else-if="item.key === 'CompanyType'">
+                        <template v-if="!showMore">
+                          <span :style="row.IsSuspend===1?'color:#bbb':''">{{row.CompanyType}}</span> 
+                          <span v-if="row.FiccPackageType"  class="ficc-package">{{row.FiccPackageType == 1 ? '大套餐': '小套餐'}}</span>
+                        </template>
+                        <template v-else>
+                          <el-tooltip class="item" effect="dark" :visible-arrow="false"  placement="right">
+                            <div>
+                              <span :style="row.IsSuspend===1?'color:#bbb':''">{{row.CompanyType}}</span> 
+                              <span v-if="row.FiccPackageType"  class="ficc-package">{{row.FiccPackageType == 1 ? '大套餐': '小套餐'}}</span>
+                            </div>
+                            <template #content>
+                              <div v-html="showMoreText"></div>
+                            </template>
+                          </el-tooltip>
+                        </template>
+                    </span>
+
+                    <span v-else-if="item.key === 'City'">
+                        {{`${row.Province}/${row.City}`}}
+                    </span>
+
+                    <span v-else-if="item.key === 'Status'">
+                        {{row.Status}}
+                    </span>
+
+                    <span v-else-if="item.key === 'viewTotal'">
+                        {{row.AllViewTotal}}
+                    </span>
+
+                    <span v-else-if="item.key === 'LastViewTime'">
+                        {{
+                            row.FiccLastViewTime 
+                            ? `ficc: ${row.FiccLastViewTime}` 
+                            :row.RaiLastViewTime?
+                            `权益: ${row.RaiLastViewTime}`:'--'
+                        }}
+                    </span>
+
+                    <span v-else-if="item.key === 'EndDate'">
+                        <!-- 正常的时间显示 -->
+                        <template v-if="row.StartDate.indexOf('/')==-1">
+                            <!-- <template v-if="act_status=='流失'">
+                                创建时间:{{row.CreatedTime}}
+                            </template>
+                            <template v-else-if="row.Status == '永续'">
+                                永久
+                            </template>
+                            <template v-else-if="act_status == '冻结'">
+                                {{row.FreezeStartDate}}~{{row.FreezeEndDate}}
+                            </template> -->
+                            <template>
+                                {{row.StartDate}}~{{row.EndDate}}
+                            </template>
+                        </template>
+                        <!-- 公用客户的时间显示 -->
+                        <template v-else>
+                            {{row.StartDate.substr(0,10)}}~{{row.EndDate.substr(0,10)}}/{{row.StartDate.substr(11)}}~{{row.EndDate.substr(11)}}
+                        </template>
+                    </span>
+
+                    <span v-else>{{ row[item.key]}}</span>
+                </template>
+            </el-table-column>
+            <el-table-column
+                :prop="title.includes('正式') ? 'formalTime' : 'createTime'"
+                :label="title.includes('正式') ? '转正时间' : '创建时间'"
+                sortable="custom"
+                align="center" 
+                min-width="120"
+            >
+                <template #default="scope">
+                    <span>
+                        <template v-if="title.includes('正式')">
+                            {{scope.row.FormalTime}}
+                        </template>
+                        <template v-else>
+                            {{scope.row.CreatedTime}}
+                        </template>
+                    </span> 
+                </template>
+            </el-table-column>
+            <template #empty>
+              <div style="lineHeight:44px;margin:60px 0;color:#999;">
+                  <img src="~@/assets/img/cus_m/nodata.png" alt="" style="display:block;width:160px;height:128px;margin: auto;">
+                  <span>暂无数据</span>
+              </div>
+            </template>
+        </el-table>
+        <div class="bottom">
+            <m-page
+                :total="total"
+                :page_no="page_no"
+                @handleCurrentChange="handleCurrentChange"
+            />
+        </div>
+    </div>
+  </div>
+</template>
+<style scoped lang="scss">
+.region-custom-detail{
+  padding:30px;
+	background: #fff;
+	border: 1px solid #ECECEC;
+	border-radius: 4px;
+	box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    min-height: 70vh;
+    .title{
+        padding: 10px 24px;
+        display: inline-block;
+        background: #e8f3ff;
+        color: #2d8cf0;
+        font-size: 14px;
+        border-radius: 4px;
+        margin-bottom: 30px;
+    }
+    .table-cont {
+		margin-top: 20px;
+		margin-bottom: 20px;
+	}
+	.bottom {
+		height: 40px;
+	}
+}
+</style>

+ 92 - 0
src/views/custom_manage/overseas/components/roadShowsDialog.vue

@@ -0,0 +1,92 @@
+
+<script setup>
+import { ref,watch } from 'vue';
+import { customInterence } from "@/api/api.js";
+const props = defineProps({
+    isRoadDetailShow:{
+        type:Boolean,
+        default:false
+    },
+    customData:{
+        type:Object,
+        default:{}
+    },
+})
+const emit = defineEmits(['close'])
+
+const columns = [{
+			label:"路演日期",
+			key:'RoadShowTime'
+	},{
+			label:"路演形式",
+			key:'RoadshowType'
+	},{
+			label:"路演平台/路演城市",
+			key:'RoadshowPlatform'
+	},{
+			label:"研究员",
+			key:'Researchers'
+	},{
+			label:"对接销售",
+			key:'SysUserRealName'
+	}
+]
+
+const dataList = ref([])
+const tableLoading = ref(false)
+function getTableData(){
+		tableLoading.value = true
+		customInterence.roadShowList({
+				CompanyId:props.customData.CompanyId
+		}).then(res=>{
+				tableLoading.value = false
+				if(res.Ret!==200) return 
+				dataList.value = res.Data||[]
+		})
+}
+
+watch(
+	() =>props.isRoadDetailShow,
+	(newVal) => {
+		if(newVal){
+			getTableData()
+		}else{
+				dataList.value=[]
+		}
+	}
+)
+       
+</script>
+
+<template>
+    <el-dialog 
+				class="total-click-dialog"
+        :title="`${customData.CompanyName}-路演详情`"
+        :model-value="isRoadDetailShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="emit('close')"
+        width="842px"
+        draggable
+        center
+    >
+        <div class="table-wrap" v-loading="tableLoading">
+            <p>累计路演次数:{{dataList.length}}</p>
+            <el-table :data="dataList"  height="300" border @sort-change="clickNumSortChange" v-loading="showLoading" element-loading-text="加载中">
+                <el-table-column  v-for="column in columns" :key="column.key" :label="column.label" align="center" :prop="column.key">
+                    <template #default="{row}">
+                    {{row[column.key]}}
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+    </el-dialog>
+</template>
+
+<style scoped lang="scss">
+.table-wrap{
+    .el-table{
+        margin:20px 0 30px 0;
+    }
+}
+</style>

+ 181 - 0
src/views/custom_manage/overseas/components/selectSaleDialog.vue

@@ -0,0 +1,181 @@
+
+<script setup>
+import { ref,watch,nextTick } from 'vue';
+import {dataAuthInterface , customInterence } from '@/api/api.js'
+
+
+const props = defineProps({
+		isSelectSaleShow:{
+				type:Boolean,
+				default:false
+		},
+		selectedSalesArr:{
+				type:Array,
+				default:[]
+		}
+})
+const emit = defineEmits(['saveSales','close'])
+
+
+const sales= ref([])
+const AllSalesArr = ref([])
+const dialogLoading = ref(false)
+//获取销售列表
+//由于中英文客户的销售列表不一致,获取系统全部人员列表作为销售列表
+function getSalesList(){
+	dialogLoading.value = true
+	customInterence.getSale({Status:0}).then(res=>{
+			dialogLoading.value = false
+			if(res.Ret!==200) {
+					AllSalesArr.value = []
+					sales.value=[]
+					selectList.value=[]
+					return 
+			}
+			AllSalesArr.value = res.Data?(res.Data.List||[]):[]
+			//有选择的指标,回显
+			if(selectedSalesArr.value.length){
+					sales.value = selectedSalesArr.value.map(i=>(i.SellerId))
+					nextTick(()=>{
+							changeSelect()
+					})
+			}
+	})
+}
+
+const saleCascader = ref(null)
+const selectList= ref([])
+const saleCascaderKey= ref(0)
+function changeSelect(){
+		const nodes = saleCascader.value.getCheckedNodes()
+		selectList.value = nodes.filter(i=>{
+				/* if(i.value<10000&&!i.children.length){
+						return i
+				} */
+				if(!Number.isNaN(Number(i.value))&&!i.children.length){
+						return i
+				}
+		})
+}
+
+
+function cancelSelect(item){
+		const index = selectList.value.findIndex(i=>i.value==item.value)
+		index!==-1&&selectList.value.splice(index,1)
+		const saleIndex = sales.value.findIndex(i=>i==item.value)
+		saleIndex!==-1&&sales.value.splice(saleIndex,1)
+		saleCascaderKey.value++
+}
+
+
+//对比上次选择的销售,保存
+const loadingText= ref('')
+function choosedSales(){
+		let AddSellerIdArr = []
+		let DelSellerIdArr = []
+		const oldSales = selectedSalesArr.value.map(i=>(Number(i.SellerId)))
+		const tempSales = sales.value.map(i=>(Number(i)))
+		oldSales.forEach(i=>{
+				if(tempSales.includes(i)){
+						AddSellerIdArr.push(i)
+				}else{
+						DelSellerIdArr.push(i)
+				}
+		})
+		AddSellerIdArr = Array.from(new Set([...AddSellerIdArr,...tempSales]))
+		loadingText.value = '保存销售中,请勿关闭弹窗...'
+		dialogLoading.value = true
+		emit('saveSales',{AddSellerIdArr,DelSellerIdArr,sales:selectList.value})
+}
+
+
+watch(
+	() => props.isSelectSaleShow,
+	(newval) =>{
+		if(newval){
+				getSalesList()
+		}else{
+				loadingText.value = ''
+		}
+})
+    
+</script>
+
+<template>
+    <el-dialog 
+				class="select-sale-dialog"
+        title="选择销售"
+        :model-value="isSelectSaleShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="emit('close')"
+        width="692px"
+        draggable
+        center
+    >
+        <div class="dialog-content-wrap" v-loading="dialogLoading" :element-loading-text="loadingText">
+            <el-cascader v-model="sales" 
+                ref="saleCascader"
+                placeholder="请选择销售"
+                :key="saleCascaderKey"
+                :options="AllSalesArr" 
+                :props="{
+                    value: 'AdminId',
+                    label: 'RealName',
+                    children: 'ChildrenList',
+                    multiple: true,
+                    emitPath:false,
+                }"
+                collapse-tags :show-all-levels="false"
+                clearable filterable
+                @change="changeSelect"
+                ></el-cascader>
+            <p style="margin-top:20px;">已选用户</p>
+            <div class="selected-wrap">
+                <div class="select-item" v-for="item in selectList" :key="item.value">
+                    <span>{{ item.label }}</span>
+                    <i class="el-icon-error" @click="cancelSelect(item)"></i>
+                </div>
+            </div>
+        </div>
+        <div class="btn-wrap">
+            <el-button type="primary" plain @click="emit('close')">取消</el-button>
+            <el-button type="primary" @click="choosedSales" :disabled="dialogLoading">确认</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<style lang="scss">
+.select-sale-dialog{
+    .el-cascader{
+        width:100%;
+        .el-input{
+            width:100% !important;
+        }
+    }
+    .selected-wrap{
+        margin:20px 0;
+        display: flex;
+        flex-wrap: wrap;
+        gap:10px;
+        .select-item{
+            cursor: pointer;
+            padding: 5px 10px;
+            background-color: #f0f2f5;
+            border-radius: 4px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            i{
+                margin-left: 5px;
+                color: #909399;
+                font-size: 14px;
+            }
+        }
+    }
+    .btn-wrap{
+        text-align: center;
+        padding-bottom: 20px;
+    }
+}
+</style>

+ 147 - 0
src/views/custom_manage/overseas/components/totalClicksDialog.vue

@@ -0,0 +1,147 @@
+<script setup>
+import { reactive, ref,watch } from 'vue';
+import { customInterence } from '@/api/api.js'
+
+const props = defineProps({
+    customData:{
+        type:Object,
+        default:{}
+    },
+    isTotalClickShow:{
+        type:Boolean,
+        default:false
+    }
+})
+const emit = defineEmits(['close'])
+
+const columns = [{
+		label:"联系人姓名",
+		key:"UserName"
+	},{
+			label:"手机号/邮箱",
+			key:"Email"
+	},{
+			label:"点击次数",
+			key:"ViewTotal",
+			sortable:true
+	},{
+			label:"最近点击时间",
+			key:"LastViewTime",
+			sortable:true
+	}
+]
+
+const tableParams = reactive({
+		CurrentIndex:1,
+		PageSize:5,
+		SortParam:'',
+		SortType:'',
+})
+const total = ref(0)
+const dataList = ref([])
+const tableLoading = ref(false)
+function getTableData(){
+	tableLoading.value = true
+	if(props.customData.Source===1){
+			customInterence.customEnHitNumber({
+					...tableParams,
+					CompanyId:props.customData.CompanyId - 10000000,
+					EmailId:props.customData.CompanyId - 10000000,
+			}).then(res=>{
+					tableLoading.value = false
+					if(res.Ret!==200) return 
+					dataList.value = res.Data.List || []
+					total.value = res.Data.Paging.Totals
+					dataList.value = dataList.value.map(i=>{
+							return {
+									...i,
+									Email:(i.Mobile?i.Mobile:i.Email)||''
+							}
+					})
+			})
+	}else{
+			customInterence.getZNCustomClickList({
+					...tableParams,
+					CompanyId:props.customData.CompanyId
+			}).then(res=>{
+					tableLoading.value = false
+					if(res.Ret!==200) return 
+					dataList.value = res.Data.List||[]
+					total.value = res.Data.Paging.Totals
+					dataList.value = dataList.value.map(i=>{
+							return {
+									...i,
+									Email:(i.Mobile?i.Mobile:i.Email)||''
+							}
+					})
+			})
+	}
+}
+
+function handlePageChange(page){
+		tableParams.CurrentIndex = page
+		getTableData()
+}
+
+function clickNumSortChange({prop,order}){
+		const map = {
+				'ViewTotal':1,
+				'LastViewTime':2
+		}
+		tableParams.SortParam = order?map[prop]:''
+		tableParams.SortType = order=="ascending"?2:1
+		handlePageChange(1)
+}
+
+watch(
+	() => props.isTotalClickShow,
+	(newVal) => {
+		if(newVal){
+				tableParams.CurrentIndex=1
+				tableParams.PageSize=5
+				tableParams.SortParam=''
+				tableParams.SortType=''
+
+				getTableData()
+		}else{
+				dataList.value = []
+		}
+	}
+)
+</script>
+<template>
+    <el-dialog 
+				class="total-click-dialog"
+        :title="`${customData.CompanyName}-点击量详情`"
+        :model-value="isTotalClickShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="emit('close')"
+        width="842px"
+        draggable
+        center
+    >
+        <div class="table-wrap" v-loading="tableLoading">
+            <el-table :data="dataList" border @sort-change="clickNumSortChange" v-loading="showLoading" element-loading-text="加载中">
+                <el-table-column  v-for="column in columns" :key="column.key" 
+                    :label="column.label" align="center" :prop="column.key"
+                    :sortable="column.sortable?'custom':false">
+                    <template #default="{row}">
+                    {{row[column.key]}}
+                    </template>
+                </el-table-column>
+            </el-table>
+            <el-pagination 
+                layout="total,prev,pager,next,jumper" 
+                background 
+                :current-page="tableParams.CurrentIndex"
+                @current-change="handlePageChange"
+                :page-size="tableParams.PageSize"
+                :total="total"
+                style="text-align: right;margin-top:20px;margin-bottom:20px;"/>
+        </div>
+    </el-dialog>
+</template>
+<style scoped lang="scss">
+
+</style>

+ 575 - 2
src/views/custom_manage/overseas/overseasCustomList.vue

@@ -1,10 +1,583 @@
 <script setup>
-import { ref } from 'vue'
+import { computed, reactive, ref } from 'vue';
+import { ElMessage } from 'element-plus'
+import { useRouter } from 'vue-router'
+import { overseasCustomInterence} from '@/api/modules/overseasCustom.js'
+import SelectSaleDialog from './components/selectSaleDialog.vue';
+import TotalClicksDialog from './components/totalClicksDialog.vue';
+import RoadShowsDialog from './components/roadShowsDialog.vue';
+import ShareListDialog from '../custom/components/shareListDialog.vue';
+import { useCommunicaRecordDia } from '../custom/hooks/customlistHook'
+
+const router = useRouter()
+
+const tryArr = ['','未分类','推进','跟踪','预备']
+const trialTags = [{ label: '推进', value: 2 },
+    { label: '跟踪', value: 3 },
+    { label: '预备', value: 4 },
+    { label: '未分类', value: 1 },
+]
+const columns = [{
+      label: "客户名称",
+      key: 'CompanyName'
+  }, {
+      label: "国家",
+      key: 'Nation'
+  }, {
+      label: "销售",
+      key: 'SellerName'
+  }, {
+      label: "状态",
+      key: 'OverseasStatus'
+  }, {
+      label: "累计点击量",
+      key: 'ViewTotal',
+      sortable: true
+  }, {
+      label: "路演数量",
+      key: 'RoadShowTotal',
+      sortable: true
+  }, {
+      label: "最近阅读时间",
+      key: 'LastViewTime',
+      sortable: true
+  }, {
+      label: "创建时间",
+      key: 'CreateTime',
+      sortable: true
+  }
+]
+
+const Role = computed(() => {
+    return localStorage.Role || '';
+})
+const isDataSelectBtnShow = computed(()=> {
+    return (['admin','ficc_admin'].includes(Role));
+})
+
+
+//客户列表
+const tableParams = reactive({
+    Keywords:'',
+    SortField:'ViewTotal',//排序字段
+    SortDesc:1,//排序方式
+    SellerId:'',//选择的销售
+    CompanyStatus:'全部',//客户状态
+    tagStatusSelect:'全部',//客户的试用状态
+    tryStatusSelect:0,//客户试用状态对应的OverseasLabel
+})
+const tableLoading = ref(false)
+const tableData = ref([])
+const currentPage = ref(1)
+const pageSize = ref(10)
+const total = ref(0)
+const pageSelect = ref(1)
+async function getTableData(type) {
+    tableLoading.value = true
+    const {Keywords,SortField,SortDesc,SellerId,CompanyStatus,tryStatusSelect} = tableParams
+    //重新请求统计数据
+    if(type!=='sort'){
+        await getStatisticData()
+        if(CompanyStatus==='试用'){
+            await getTryStatisticData()
+        }
+    }
+
+    overseasCustomInterence.getCustomList({
+        PageSize: pageSize.value,
+        CurrentIndex: currentPage.value,
+        Keywords,
+        CompanyStatus,
+        SellerId:(Array.isArray(SellerId)?SellerId.join(','):'')+'',
+        OverseasLabel:tryStatusSelect,
+        CustomType:pageSelect.value,
+        SortField,SortDesc,
+    }).then(res=>{
+        tableLoading.value = false
+        if(res.Ret!==200) return 
+        if(!res.Data) return 
+       
+        //客户列表
+        tableData.value = res.Data.List||[]
+        total.value = res.Data.Paging.Totals||0
+    })
+}
+getTableData('static');
+
+
+//获取客户统计数据
+const tableTabs = ref([])
+async function getStatisticData(){
+    const {Keywords,SellerId,CompanyStatus} = tableParams
+    const statisticRes = await overseasCustomInterence.getStatisticData({
+        CustomType:pageSelect.value,
+        SellerId:(Array.isArray(SellerId)?SellerId.join(','):'')+'',
+        Keywords
+    })
+    if(statisticRes.Ret!==200) return 
+    //客户状态
+    tableTabs.value = statisticRes.Data||[]
+    //手动添加一个全部
+    let total = tableTabs.value.map(i=>(i.Total)).reduce((acc,curr)=>acc+curr,0)
+    tableTabs.value.unshift({CompanyStatus:'全部',Total:total})
+}
+
+
+//客户试用状态统计数据
+const tryTabs = ref([])
+async function getTryStatisticData(){
+    const {Keywords,SellerId} = tableParams
+    const statisticTryRes = await overseasCustomInterence.overseasCustomInterence({
+        CustomType:pageSelect.value,
+        SellerId:(Array.isArray(SellerId)?SellerId.join(','):'')+'',
+        Keywords
+    })
+    if(statisticTryRes.Ret!==200) return 
+    //客户试用状态
+    tryTabs.value = statisticTryRes.Data||[]
+    tryTabs.value = tryTabs.value.map(tab=>({
+        TryStatus:tryArr[tab.OverseasLabel],
+        Total:tab.Total,
+        OverseasLabel:tab.OverseasLabel}))
+    //手动添加一个全部
+    let tryTotal = tryTabs.value.map(i=>(i.Total)).reduce((acc,curr)=>acc+curr,0)
+    tryTabs.value.unshift({TryStatus:'全部',Total:tryTotal,OverseasLabel:0})
+}
+
+
+//切换客户状态
+function changeStatus(item) {
+    tableParams.CompanyStatus = item.CompanyStatus;
+    if(item.CompanyStatus!=='试用'){
+        tableParams.tagStatusSelect = '全部';
+        tableParams.tryStatusSelect = 0
+    }
+    handlePageChange(1);
+}
+
+//切换客户试用状态
+function changeTagStatus(item) {
+    tableParams.tagStatusSelect = item.TryStatus;
+    tableParams.tryStatusSelect = item.OverseasLabel
+    handlePageChange(1);
+}
+//列表排序
+function handleSortChange({prop,order}) {
+  tableParams.SortDesc = order==='ascending'?2:1
+  tableParams.SortField = order?prop:'ViewTotal'
+  handlePageChange(1,'sort')
+}
+
+//切换页码
+function handlePageChange(page,type) {
+    currentPage.value = page;
+    getTableData(type);
+}
+
+
+//获取已保存选择的销售
+const salesArr = ref([])
+function getSavedSales(){
+    overseasCustomInterence.getSavedSalesList().then(res=>{
+        if(res.Ret!==200) return 
+        salesArr.value = res.Data||[]
+    })
+}
+getSavedSales()
+
+//保存选择的销售
+const isSelectSaleShow = ref(false)//选择销售弹窗
+const selectDialog = ref(null)
+function saveSales({AddSellerIdArr,DelSellerIdArr,sales}){
+    overseasCustomInterence.saveSelectedSales({
+        AddSellerIdArr,DelSellerIdArr
+    }).then(res=>{
+        selectDialog.value&&(selectDialog.value.dialogLoading = false)
+        if(res.Ret!==200) return
+        ElMessage.success("选择销售成功")
+
+        tableParams.Keywords=''
+        tableParams.SortField='ViewTotal'
+        tableParams.SortDesc=1
+        tableParams.SellerId=''
+        tableParams.CompanyStatus='全部'
+        tableParams.tagStatusSelect='全部'
+        tableParams.tryStatusSelect=0
+
+        salesArr.value = sales.map(i=>({SellerId:i.value,RealName:i.label}))
+        handlePageChange(1)
+        isSelectSaleShow.value = false
+    })
+}
+
+
+//跳转至客户详情
+function toCustomDetail(data) { 
+    const path = data.Source===1?'/detailCustomEn':'/customDetail'
+    const query = {
+        ...data.Source===1?{
+            companyId:data.CompanyId - 10000000
+        }:{
+            id:data.CompanyId
+        },
+        from:'overseas'
+    }
+    const href = router.resolve({path,query}).href
+    window.open(href,"_blank")
+}
+
+//设置客户的试用状态
+function handleChangeTryStatus(data) {
+    const { OverseasLabel, CompanyId } = data;
+    overseasCustomInterence.setCustomTryStatus({
+        CompanyId,OverseasLabel
+    }).then(res=>{
+        if(res.Ret!==200) return 
+        ElMessage.success("设置成功")
+        getTableData()
+    })
+}
+
+
+//打开累计点击量/路演数量弹窗
+const customData = ref({})//选择的客户信息
+const isRoadDetailShow = ref(false)//路演详情弹窗
+const isTotalClickShow = ref(false) //累计点击量弹窗
+function handleDialogShow(type,data){
+    customData.value = data
+    if(type==='click'){
+        if(!data.ViewTotal>0) return
+        isTotalClickShow.value = true
+    }else{
+        if(!data.RoadShowTotal>0) return
+        isRoadDetailShow.value = true
+    }
+}
+
+
+//设置客户隐藏/取消隐藏
+function handleSetCustomHide({CompanyId}){
+    overseasCustomInterence.setCustomHide({CompanyId}).then(res=>{
+        if(res.Ret!==200) return 
+        ElMessage.success(`设置${pageSelect.value===1?'隐藏':'取消隐藏'}成功`)
+        handlePageChange(1)
+    })
+}
+
+function handleSetCustomStatus({CompanyId},type){
+    overseasCustomInterence.setCustomStatus({CompanyId}).then(res=>{
+        if(res.Ret!==200) return 
+        ElMessage.success(`${type==='reset'?'重置':'转正式'}成功`)
+        handlePageChange(1)
+    })
+}
+
+
+const { customInfo,isShareRecodeDialogShow,allowEdit,handleShowShareRecode } = useCommunicaRecordDia();
 
 </script>
 <template>
-  <div></div>
+  <div class="overseas-custom-list-wrap">
+        <div class="top-box" v-show="isDataSelectBtnShow">
+            <div class="switch-box">
+                <el-radio-group v-model="pageSelect" >
+                    <el-radio-button :label="1">海外客户</el-radio-button>
+                    <el-radio-button :label="2">已隐藏客户</el-radio-button>
+                </el-radio-group>
+            </div>
+            <div class="select-box">
+                <el-select placeholder="请选择销售" v-if="pageSelect===1"
+                    v-model="tableParams.SellerId" 
+                    @change="handlePageChange(1)"
+                    multiple collapse-tags clearable>
+                    <el-option
+                        v-for="item in salesArr"
+                        :key="item.SellerId"
+                        :label="item.RealName"
+                        :value="item.SellerId"
+                    />
+                </el-select>
+                <el-input 
+                    prefix-icon="el-icon-search" 
+                    placeholder="客户名称/社会信用码/手机号码/邮箱" 
+                    style="width:317px;" clearable
+                    v-model="tableParams.Keywords"
+                    @input="handlePageChange(1)"
+                />
+            </div>
+        </div>
+        <div class="data-box" v-loading="tableLoading">
+            <div class="data-select-box">
+                <div class="table-select-box">
+                    <ul class="status-box">
+                        <li v-for="item in tableTabs" :key="item.Status"
+                            :class="['tab',{'act':tableParams.CompanyStatus === item.CompanyStatus}]"
+                            @click="changeStatus(item)"
+                        >
+                            {{`${item.CompanyStatus}(${item.Total})`}}
+                        </li>
+                    </ul>
+                    <!-- 试用小分类 -->
+                    <ul class="try-status-box" v-if="tableParams.CompanyStatus==='试用'">
+                        <li v-for="item in tryTabs" :key="item.TryStatus"
+                            :class="['trial-item',{'act':tableParams.tagStatusSelect === item.TryStatus}]" 
+                            @click="changeTagStatus(item)"
+                        >
+                            {{item.TryStatus+'('+item.Total+')'}}
+                        </li>
+                    </ul>
+                </div>
+                <!-- 管理员-选择销售 -->
+                <div class="data-select" v-if="isDataSelectBtnShow&&this.salesArr.length">
+                    <el-button v-if="pageSelect===1" type="primary" link @click="isSelectSaleShow=true"><i class="el-icon-plus"  style="font-weight: bold;margin-right: 5px;"/>选择销售</el-button>
+                </div>
+                <!--非管理员 筛选-->
+                <div class="data-select" v-if="!isDataSelectBtnShow" style="flex:1;">
+                    <div class="select-box" style="display: flex;justify-content: flex-end;gap: 30px;">
+                        <el-select placeholder="请选择销售" v-if="pageSelect===1"
+                            v-model="tableParams.SellerId" 
+                            @change="handlePageChange(1)"
+                            multiple collapse-tags clearable>
+                            <el-option
+                                v-for="item in salesArr"
+                                :key="item.SellerId"
+                                :label="item.RealName"
+                                :value="item.SellerId"
+                            />
+                        </el-select>
+                        <el-input 
+                            prefix-icon="el-icon-search" 
+                            placeholder="客户名称/社会信用码/手机号码/邮箱" 
+                            style="width:317px;" clearable
+                            v-model="tableParams.Keywords"
+                            @input="handlePageChange(1)"
+                        />
+                    </div>
+                </div>
+            </div>
+            <div class="table-box">
+                <el-table
+                    ref="overseasTable"
+                    :data="tableData"
+                    border
+                    @sort-change="handleSortChange"
+                >
+                    <el-table-column 
+                        align="center"
+                        v-for="item in columns" :key="item.key"
+                        :prop="item.key" :label="item.label"
+                        :min-width="item.minWidth"
+                        :sortable="item.sortable?'custom':false"
+                    >
+                        <template #default="{row}">
+                            <!-- 客户名称 -->
+                            <div v-if="item.key==='CompanyName'" class="editor" @click="toCustomDetail(row)">{{row[item.key]}}</div>
+                            <!-- 状态 -->
+                            <div  v-else-if="item.key==='OverseasStatus'" class="status-box">
+                                    <span>{{row[item.key]}}</span>
+                                    <div class="select" v-if="row[item.key]==='试用'">
+                                        <el-select 
+                                            v-model="row.OverseasLabel"
+                                            size="small" 
+                                            style="width: 50px" 
+                                            placeholder=""
+                                            @change="handleChangeTryStatus(row)"
+                                        >
+                                            <el-option
+                                                v-for="item in trialTags"
+                                                :key="item.value"
+                                                :label="item.label"
+                                                :value="item.value">
+                                            </el-option>
+                                        </el-select>
+                                    </div>
+                            </div>
+                            <span v-else-if="item.key==='ViewTotal'" :class="{'editor':row[item.key]>0}" @click="handleDialogShow('click',row)">{{row[item.key]}}</span>
+                            <span v-else-if="item.key==='RoadShowTotal'" :class="{'editor':row[item.key]>0}" @click="handleDialogShow('road',row)">{{row[item.key]}}</span>
+                            <span v-else-if="['LastViewTime','CreateTime'].includes(item.key)">
+                                {{
+                                    row[item.key].slice(0,10)==='0000-00-00'?'':row[item.key].slice(0,10)
+                                }}
+                            </span>
+                            <span v-else>{{row[item.key]}}</span>
+                        </template>
+                    </el-table-column>
+                    <!-- 操作列 -->
+                    <el-table-column label="操作" align="center">
+                        <template #default="{row}">
+                            <el-button type="primary" link v-if="pageSelect===1&&row.IsHide===0" @click="handleSetCustomHide(row)">隐藏</el-button>
+                            <el-button type="primary" link v-if="pageSelect===2&&row.IsHide===1" @click="handleSetCustomHide(row)">取消隐藏</el-button>
+                            <!--英文客户且状态为试用-->
+                            <el-button type="primary" link v-if="pageSelect===1&&row.Source===1&&row.OverseasStatus==='试用'" @click="handleSetCustomStatus(row,'change')">转正式</el-button>
+                            <!--英文客户且状态为正式且可以重置-->
+                            <el-button type="primary" link v-if="pageSelect===1&&row.Source===1&&row.OverseasStatus==='正式'&&row.ResetBtn===2" @click="handleSetCustomStatus(row,'reset')">重置</el-button>
+                            
+                            <el-button type="primary" link @click="handleShowShareRecode(row)">沟通记录</el-button>
+                        </template>
+                    </el-table-column>
+                    <template #empty>
+                        <!-- 管理员展示按钮 -->
+                        <div class="data-select" v-if="isDataSelectBtnShow&&!salesArr.length">
+                            <el-button type="primary" link @click="isSelectSaleShow=true"><i class="el-icon-plus"  style="font-weight: bold;margin-right: 5px;" />选择销售</el-button>
+                        </div>
+                        <!-- 非管理员显示暂无数据 -->
+                        <div v-else>暂无数据</div>
+                    </template>
+                    
+                </el-table>
+                <el-pagination 
+                    layout="total,prev,pager,next,jumper" 
+                    background 
+                    :current-page="currentPage"
+                    @current-change="(page)=>handlePageChange(page,'sort')"
+                    :page-size="pageSize"
+                    :total="total"
+                    style="text-align: right;margin-top:20px"/>
+            </div>
+        </div>
+        <!-- 选择销售弹窗 -->
+        <SelectSaleDialog 
+            ref="selectDialog"
+            :isSelectSaleShow="isSelectSaleShow"
+            :selectedSalesArr="salesArr"
+            @close="isSelectSaleShow=false"
+            @saveSales="saveSales"
+        />
+        <!-- 累计点击量弹窗 -->
+        <TotalClicksDialog 
+            :isTotalClickShow="isTotalClickShow"
+            :customData="customData"
+            @close="isTotalClickShow = false"
+        />
+        <!-- 路演数量弹窗 -->
+        <RoadShowsDialog 
+            :isRoadDetailShow="isRoadDetailShow"
+            :customData="customData"
+            @close="isRoadDetailShow = false"
+        />
+
+         <!-- 服务记录弹窗 -->
+        <ShareListDialog
+            :isShareRecodeDialogShow="isShareRecodeDialogShow"
+            :customInfo="customInfo"
+            :allowEdit="allowEdit"
+            @close="()=>{isShareRecodeDialogShow=false;}"
+        />
+    </div>
 </template>
 <style scoped lang="scss">
+.overseas-custom-list-wrap{
+    box-sizing: border-box;
 
+    :deep(.el-select--small) {
+        .el-input__inner{
+            padding: 0 6px !important;
+            height: 24px;
+            line-height: 24px;
+            color: #409EFF;
+            background: #ECF5FF;
+            border-color: #409EFF;
+            text-align: center;
+        }
+        .el-input__wrapper {
+          padding: 0;
+        }
+        .el-input__inner {
+            border-color: #E4E7ED;
+        }
+        .el-input__suffix {
+            display: none;
+        }
+    }
+    .top-box,.data-box{
+        box-sizing: border-box;
+        padding:30px;
+        background-color: #fff;
+    }
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 20px;
+    }
+    .data-box{
+        .data-select-box{
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            ul{
+                display: flex;
+                align-items: center;
+            }
+            .status-box{
+                .tab {
+                    width: 129px;
+                    height: 22px;
+                    line-height: 22px;
+                    text-align: center;
+                    font-size: 14px;
+                    border-right:1px solid #707070;
+                    cursor: pointer;
+                    transition-delay: 0.05s;
+                    &:hover {
+                        color: #409EFF;
+                    }
+                    &.act {
+                        // padding: 9px 24px;
+                        height: 40px;
+                        line-height: 40px;
+                        background: #409EFF;
+                        border-radius: 4px;
+                        color: #fff;
+                        border-color: #409EFF;
+                        transform: scale(1.014);
+                    }
+                    &:last-child {
+                        border: none;
+                    }
+                }
+            }
+            .try-status-box{
+                padding: 20px 0 0 30px;
+                .trial-item {
+                    cursor: pointer;
+                    margin-right: 30px;
+                    &:hover {
+                        color: #409EFF;
+                    }
+                    &.act {
+                        color: #409EFF;
+                        position: relative;
+                        &::after {
+                            content: "";
+                            width: 100%;
+                            height: 2px;
+                            position: absolute;
+                            bottom: -10px;
+                            left: 50%;
+                            transform: translateX(-50%);
+                            background: #409EFF;
+                        }
+                    }
+                }
+            }
+        }
+        .table-box{
+            margin-top:20px;
+            .status-box{
+                display: flex;
+                justify-content: center;
+                .el-select{
+                    margin-left: 10px;
+                }
+            }
+            .editor{
+                color:#409EFF;
+                cursor: pointer;
+                &:hover{
+                    text-decoration: underline;
+                }
+            }
+        }
+    }
+}
 </style>