Commit 47ff3e98 authored by 罗超's avatar 罗超

1

parent 712561e9
...@@ -176,22 +176,16 @@ class customerService { ...@@ -176,22 +176,16 @@ class customerService {
data data
}) })
} }
// 获取客户标签/分组 列表 // 获取客户标签/分组 列表
static async getWeChatLableList(data: any): Promise<HttpResponse> { static async getWeChatLableList(data: any): Promise<HttpResponse> {
return Axios('/QYWeChat/GetWeChatLableList', { return Axios('/QYWeChat/GetWeChatLableList', {
method: 'post', method: 'post',
responseType: 'json', responseType: 'json',
data data
}) })
} }
// 新增修改分组/标签 // 新增修改分组/标签
static async setWeChatLable(data: { static async setWeChatLable(data: { Id: number; ParentId: number; Name: string; Sort: string; ChildList: Array<{ Name: string; Sort: string }> }): Promise<HttpResponse> {
Id:number,
ParentId:number,
Name:string,
Sort:string,
ChildList:Array<{Name:string, Sort:string}>
}): Promise<HttpResponse> {
return Axios('/QYWeChat/SetWeChatLable', { return Axios('/QYWeChat/SetWeChatLable', {
method: 'post', method: 'post',
responseType: 'json', responseType: 'json',
...@@ -199,7 +193,7 @@ class customerService { ...@@ -199,7 +193,7 @@ class customerService {
}) })
} }
// 新增修改分组/标签 // 新增修改分组/标签
static async delWeChatLable(data: {LableId:number}): Promise<HttpResponse> { static async delWeChatLable(data: { LableId: number }): Promise<HttpResponse> {
return Axios('/QYWeChat/DelWeChatLable', { return Axios('/QYWeChat/DelWeChatLable', {
method: 'post', method: 'post',
responseType: 'json', responseType: 'json',
...@@ -207,14 +201,7 @@ class customerService { ...@@ -207,14 +201,7 @@ class customerService {
}) })
} }
// 保存客户阶段流程 // 保存客户阶段流程
static async setCustomerStageFlowInfo(data: { static async setCustomerStageFlowInfo(data: { Id: number; FlowName: string; DeptEmpList: Array<{ Id: number; Name: string; Type: number }>; UseStage: string; LoseCause: string; InvalidCause: string }): Promise<HttpResponse> {
Id:number,
FlowName:string,
DeptEmpList:Array<{Id:number,Name:string,Type:number}>,
UseStage:string,
LoseCause:string,
InvalidCause:string,
}): Promise<HttpResponse> {
return Axios('/QYCustomer/SetCustomerStageFlowInfo', { return Axios('/QYCustomer/SetCustomerStageFlowInfo', {
method: 'post', method: 'post',
responseType: 'json', responseType: 'json',
...@@ -222,15 +209,29 @@ class customerService { ...@@ -222,15 +209,29 @@ class customerService {
}) })
} }
// 获取客户阶段流程详情 // 获取客户阶段流程详情
static async getCustomerStageFlowInfo(data: { static async getCustomerStageFlowInfo(data: { FlowId: number }): Promise<HttpResponse> {
FlowId:number,
}): Promise<HttpResponse> {
return Axios('/QYCustomer/GetCustomerStageFlowInfo', { return Axios('/QYCustomer/GetCustomerStageFlowInfo', {
method: 'post', method: 'post',
responseType: 'json', responseType: 'json',
data data
}) })
} }
// 获取获取客户操作配置
static async getCustomerConfig(data: any): Promise<HttpResponse> {
return Axios('/QYCustomer/GetCustomerConfig', {
method: 'post',
responseType: 'json',
data
})
}
// 保存客户操作
static async setCustomerConfig(data: any): Promise<HttpResponse> {
return Axios('/QYCustomer/SetCustomerConfig', {
method: 'post',
responseType: 'json',
data
})
}
} }
export default customerService export default customerService
import { boot } from 'quasar/wrappers' import { boot } from 'quasar/wrappers'
import axios, { AxiosInstance } from 'axios' import axios, { AxiosInstance } from 'axios'
import {UploadSelfFile} from '@/utils/common' // import {UploadSelfFile} from '@/utils/upload'
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
interface ComponentCustomProperties { interface ComponentCustomProperties {
$axios: AxiosInstance $axios: AxiosInstance
...@@ -24,7 +24,7 @@ export default boot(({ app }) => { ...@@ -24,7 +24,7 @@ export default boot(({ app }) => {
* @deprecated 弃用的方法 * @deprecated 弃用的方法
*/ */
app.config.globalProperties.$api = api app.config.globalProperties.$api = api
app.config.globalProperties.$UploadSelfFile = UploadSelfFile // app.config.globalProperties.$UploadSelfFile = UploadSelfFile
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
// so you can easily perform requests against your app's API // so you can easily perform requests against your app's API
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
:val="_item[optionValue]" :val="_item[optionValue]"
:label="_item[optionLabel]" :label="_item[optionLabel]"
v-if="multiple" v-if="multiple"
indeterminate-value
@mouseenter.stop="getChild2(_index)" @mouseenter.stop="getChild2(_index)"
@update:model-value="getLabel($event, _item[optionLabel], _item[optionValue])" @update:model-value="getLabel($event, _item[optionLabel], _item[optionValue])"
/> />
...@@ -94,6 +95,7 @@ ...@@ -94,6 +95,7 @@
:val="_item[optionValue]" :val="_item[optionValue]"
:label="_item[optionLabel]" :label="_item[optionLabel]"
v-if="multiple" v-if="multiple"
indeterminate-value
@mouseenter.stop="getChild3(_index)" @mouseenter.stop="getChild3(_index)"
@update:model-value="getLabel($event, _item[optionLabel], _item[optionValue])" @update:model-value="getLabel($event, _item[optionLabel], _item[optionValue])"
/> />
...@@ -120,6 +122,7 @@ ...@@ -120,6 +122,7 @@
:val="_item[optionValue]" :val="_item[optionValue]"
:label="_item[optionLabel]" :label="_item[optionLabel]"
v-if="multiple" v-if="multiple"
indeterminate-value
@update:model-value="getLabel($event, _item[optionLabel], _item[optionValue])" @update:model-value="getLabel($event, _item[optionLabel], _item[optionValue])"
/> />
<q-icon <q-icon
...@@ -198,7 +201,6 @@ export default { ...@@ -198,7 +201,6 @@ export default {
watch(() => [...checkbox.value], (val) => { watch(() => [...checkbox.value], (val) => {
check.value = val check.value = val
selectArray.value = [] selectArray.value = []
// console.log('多选', selectArray.value)
console.log('多选2', checkbox.value) console.log('多选2', checkbox.value)
}) })
const getChild = (index) => { const getChild = (index) => {
...@@ -221,11 +223,10 @@ export default { ...@@ -221,11 +223,10 @@ export default {
if (labelIndex > -1) { if (labelIndex > -1) {
checkBoxLabel.value.splice(labelIndex, 1) checkBoxLabel.value.splice(labelIndex, 1)
} }
} }
const newVal=JSON.parse(JSON.stringify(val)) console.log(228, label, curVal)
getselectArray(props.options, newVal) getselectArray(props.options, curVal)
console.log(228,newVal)
} }
...@@ -237,24 +238,81 @@ export default { ...@@ -237,24 +238,81 @@ export default {
radio.value = "" radio.value = ""
} }
} }
//处理选中------------- //处理选中-------------
let selectArray = ref<Array<any>>([]) let selectArray = ref<Array<any>>([])
const getselectArray = (arr: any[], checkVal) => { const getselectArray = (arr: any[], checkVal) => {
const index = checkbox.value.indexOf(checkVal)
//父级id数组
arr.map(e => { arr.map(e => {
const flag = checkVal.indexOf(e[props.optionValue]) > -1&&e[props.optionValue].slice(0,1)==1
if (flag) { const child = e[props.optionChildren]
checkbox.value.push(e[props.optionValue]) if (checkVal == e[props.optionValue]) {
console.log(246,checkVal) if (index > -1) {
if(e[props.optionChildren]&&e[props.optionChildren].length>0){ mapChildAdd(child)
getselectArray(e[props.optionChildren],checkVal) } else {
mapChildDel(child)
} }
} else {
getselectArray(child, checkVal)
}
if(child.length>0){
//处理父级
mapfather(child, e[props.optionValue],checkVal)
} }
}) })
} }
const mapChildAdd = (arr: any[]) => {
arr.map(e => {
const index = checkbox.value.indexOf(e[props.optionValue])
if (index == -1) {
checkbox.value.push(e[props.optionValue])
}
const child = e[props.optionChildren]
if (child.length > 0) {
mapChildAdd(child)
}
})
}
const mapChildDel = (arr: any[]) => {
arr.map(e => {
const delIndex = checkbox.value.indexOf(e[props.optionValue])
checkbox.value.splice(delIndex, 1)
const child = e[props.optionChildren]
if (child.length > 0) {
mapChildDel(child)
}
})
}
const mapfather = (arr: any[], faId,checkVal) => {
// 判断自己是否选中
const self = checkbox.value.indexOf(checkVal) > -1
// 判断兄弟节点是否选中
// const bro = child.every(e=>.indexOf(checkVal) > -1
arr.map(e => {
if (self) {
const child = e[props.optionChildren]
if (child.length > 0) {
faId=faId+','+e[props.optionValue]
mapfather(child, faId,checkVal)
}
} else {
if(checkVal===e[props.optionValue]){
console.log('当前',e[props.optionValue])
console.log('Ids',faId.split(','))
faId.split(',').map(_e=>{
const faIndex = checkbox.value.indexOf(_e)
checkbox.value.splice(faIndex,1)
})
}
return
}
})
}
return { return {
selectRef, selectRef,
radio, radio,
......
<template>
<div class="q-mt-md q-pa-md page flex">
<div class="customer-operation-category">
<div
v-for="(item) in leftList"
:key="item.Id"
:class="{ 'active': curItem == item.Id }"
class="customer-operation-category--item"
@click="changeActive(item)"
>{{ item.Name }}</div>
</div>
<div class="customer-operation-content">
<div v-if="curItem == 1" class="row">
<div class="col-2 content-left">领取公海客户:</div>
<div class="col-10">
<div class="flex items-center">
<q-toggle v-model="data.IsPublicAudit" :true-value="1" :false-value="2" />开启后,员工领取公海客户时需要企微端设置的部门上级审批,审批同意后才可领取
</div>
<div class="flex items-center">
<q-toggle v-model="data.PublicGetDept" false-value="-1" />以下部门允许领取公海客户
<q-btn color="primary" label="修改" size="xs" @click="checkedPublicGetDept" />
</div>
<div>
<div v-for="item in items" :key="item.id">{{ item }}</div>
</div>
</div>
</div>
<div v-if="curItem == 2">
<div class="row">
<div class="col-2 content-left">可放弃客户:</div>
<div class="col-10">
<div class="q-gutter-sm">
<q-radio v-model="data.AbandonType" :val="1" label="全部客户" />
<q-radio v-model="data.AbandonType" :val="2" label="部分客户" />
</div>
<div v-if="data.AbandonType == 2">x</div>
</div>
</div>
<div class="row">
<div class="col-2 content-left">可操作员工:</div>
<div class="col-10">
<div class="flex items-center">
<q-toggle v-model="data.AbandonDept" false-value="-1" />以下部门允许将客户放弃到公海
<q-btn
color="primary"
label="修改"
size="xs"
@click="checkedPublicGetDept"
/>
</div>
</div>
</div>
<div class="row">
<div class="col-2 content-left">放弃后审核:</div>
<div class="col-10">
<div class="flex items-center">
<q-toggle v-model="data.AbandonAudit" false-value="-1" />开启后,员工放弃客户时需要企微端设置的部门上级审批,审批同意后才可放弃。
</div>
</div>
</div>
<div class="row">
<div class="col-2 content-left" style="padding-top:15px">放弃原因:</div>
<div class="col-10">
<draggable v-model="data.AbandonReasonList" tag="div" item-key="Id">
<template #item="{ element }">
<div class="flex items-center">
<i
class="iconfont icon-drag"
style="font-size: 20px;color: #777;"
></i>
<div class="AbandonReasonItem flex items-center">{{ element }}</div>
</div>
</template>
</draggable>
</div>
</div>
</div>
</div>
<departmentStaff
v-model="showDptDialog"
:defaultArray="defaultDpt"
nodeKey="newId"
labelKey="DeptName"
childrenKey="ChildList"
strategy="leaf"
:treeData="DptDataTree"
@select="getdpt"
/>
</div>
</template>
<script lang="ts">
import {
ref,
toRefs,
reactive,
defineComponent,
onMounted
} from 'vue'
import customerService from '@/api/customer'
// import customerService2 from '@/api/customer2'
import departmentStaff from '@/components/common/departmentStaff.vue'
import draggable from "vuedraggable";
export default defineComponent({
components: {
departmentStaff,
draggable
},
setup() {
const leftList = ref([
{
Id: 1,
Name: "领取公海客户"
}, {
Id: 2,
Name: "放弃到公海"
}, {
Id: 3,
Name: "申请成为协作人"
}, {
Id: 4,
Name: "添加协作人"
}, {
Id: 5,
Name: "转移客户"
}, {
Id: 6,
Name: "删除客户跟进记录"
}, {
Id: 7,
Name: "签到拜访设置"
}, {
Id: 8,
Name: "创建企业"
}, {
Id: 9,
Name: "写跟进"
}
])
let curItem = ref(1)
let data = reactive({
data: {
IsPublicAudit: 1,
PublicGetDept: -1,
AbandonType: 1,
},
showDptDialog: false,
defaultDpt: [],
DptDataTree: []
})
const changeActive = (item) => {
curItem.value = item.Id
}
const getConfig = () => {
customerService.getCustomerConfig({}).then((res) => {
console.log('CONFIG', res.data.Data)
data.data = res.data.Data
})
}
const getDptTree = () => {
customerService.getDeptTree({}).then((res) => {
console.log('DptDataTree', res.data.Data)
data.DptDataTree = res.data.Data
// 重组唯一id
if (data.DptDataTree.length == 0) return
data.DptDataTree.forEach((x: any) => {
x.newId = x.DataType + '-' + x.DeptId
if (x.ChildList && x.ChildList.length > 0) {
getChildList(x.ChildList)
}
})
})
}
const getChildList = (ChildList: Array<any>) => {
ChildList.forEach(x => {
x.newId = x.DataType + '-' + x.DeptId
if (x.ChildList && x.ChildList.length > 0) {
getChildList(x.ChildList)
}
})
}
const getdpt = (val) => {
console.log('dpt', val)
}
//领取公海客户
const checkedPublicGetDept = () => {
data.showDptDialog = true
}
const setCustomerConfig = () => {
customerService.setCustomerConfig(data.data).then((res) => {
console.log('set', res.data.Data)
})
}
onMounted(() => {
getDptTree()
getConfig()
})
return {
leftList,
curItem,
changeActive,
...toRefs(data),
getdpt,
checkedPublicGetDept,
setCustomerConfig,
}
}
})
</script>
<style lang="scss" scoped>
.page {
background-color: rgb(243, 246, 249);
}
.customer-operation-category {
margin-right: 10px;
width: 200px;
flex: none;
background-color: #fff;
border-radius: 8px;
padding: 15px 0;
overflow: auto;
.customer-operation-category--item {
padding: 15px 25px;
cursor: pointer;
font-weight: 600;
user-select: none;
color: #333;
font-size: 14px;
}
.active {
background-color: #eaf0ff;
color: #3470ff;
}
}
.customer-operation-content {
background: #fff;
flex: 1;
border-radius: 8px;
padding: 25px;
overflow: auto;
}
.content-left {
line-height: 40px;
font-weight: 600;
white-space: nowrap;
}
.AbandonReasonItem {
width: 453px;
height: 50px;
line-height: 50px;
padding-left: 22px;
background-color: #fff;
border-radius: 5px;
border: 1px solid #d7d7d7;
margin: 10px;
}
</style>
\ No newline at end of file
...@@ -15,12 +15,14 @@ ...@@ -15,12 +15,14 @@
<q-tab name="label" label="标签" /> <q-tab name="label" label="标签" />
<q-tab name="clue" label="线索分配规则" /> <q-tab name="clue" label="线索分配规则" />
<q-tab name="phase" label="客户阶段" /> <q-tab name="phase" label="客户阶段" />
<q-tab name="operation" label="客户操作" />
</q-tabs> </q-tabs>
<div class="container fit"> <div class="container fit">
<customer-Field v-if="tab == 'field'"></customer-Field> <customer-Field v-if="tab == 'field'"></customer-Field>
<clue-rule v-if="tab == 'clue'"></clue-rule> <clue-rule v-if="tab == 'clue'"></clue-rule>
<customer-phase v-if="tab == 'phase'"></customer-phase> <customer-phase v-if="tab == 'phase'"></customer-phase>
<customerlabel v-if="tab == 'label'"></customerlabel> <customerlabel v-if="tab == 'label'"></customerlabel>
<CustomerOperation v-if="tab == 'operation'"></CustomerOperation>
</div> </div>
</q-page> </q-page>
</div> </div>
...@@ -31,6 +33,7 @@ import customerField from './components/customerField.vue' ...@@ -31,6 +33,7 @@ import customerField from './components/customerField.vue'
import clueRule from './components/clueRule.vue' import clueRule from './components/clueRule.vue'
import customerPhase from './components/customerPhase.vue' import customerPhase from './components/customerPhase.vue'
import customerlabel from './components/customerlabel.vue' import customerlabel from './components/customerlabel.vue'
import CustomerOperation from "./components/CustomerOperation.vue"
import router from '@/router/index' import router from '@/router/index'
import { import {
...@@ -44,7 +47,8 @@ export default defineComponent({ ...@@ -44,7 +47,8 @@ export default defineComponent({
customerField, customerField,
clueRule, clueRule,
customerPhase, customerPhase,
customerlabel customerlabel,
CustomerOperation
}, },
setup() { setup() {
let tab = ref<string>('field') let tab = ref<string>('field')
......
...@@ -4,7 +4,14 @@ ...@@ -4,7 +4,14 @@
<div class="page-search row items-center"> <div class="page-search row items-center">
<div class="col row wrap q-mr-lg q-col-gutter-md"> <div class="col row wrap q-mr-lg q-col-gutter-md">
<div class="col-3"> <div class="col-3">
<q-input filled v-model="SeletObj.selectVal" clearable @clear="getCustomerList(msg)" @update:model-value="getSelectWay(),getCustomerList(msg)" label='请输入'> <q-input
filled
v-model="SeletObj.selectVal"
clearable
@clear="getCustomerList(msg)"
@update:model-value="getSelectWay(), getCustomerList(msg)"
label="请输入"
>
<template #before> <template #before>
<q-select <q-select
filled filled
...@@ -34,7 +41,13 @@ ...@@ -34,7 +41,13 @@
</div> </div>
<template v-if="TimeObj.timeWay == 1"> <template v-if="TimeObj.timeWay == 1">
<div class="col-3"> <div class="col-3">
<q-input filled v-model="msg.CreateSTime" mask="date" @update:model-value="getCustomerList(msg)" placeholder="创建时间"> <q-input
filled
v-model="msg.CreateSTime"
mask="date"
@update:model-value="getCustomerList(msg)"
placeholder="创建时间"
>
<template v-slot:append> <template v-slot:append>
<q-icon name="event" class="cursor-pointer"> <q-icon name="event" class="cursor-pointer">
<q-popup-proxy <q-popup-proxy
...@@ -54,7 +67,13 @@ ...@@ -54,7 +67,13 @@
</q-input> </q-input>
</div> </div>
<div class="col-3"> <div class="col-3">
<q-input filled v-model="msg.CreateETime" mask="date" @range-end="getCustomerList(msg)" placeholder="创建时间"> <q-input
filled
v-model="msg.CreateETime"
mask="date"
@range-end="getCustomerList(msg)"
placeholder="创建时间"
>
<template v-slot:append> <template v-slot:append>
<q-icon name="event" class="cursor-pointer"> <q-icon name="event" class="cursor-pointer">
<q-popup-proxy <q-popup-proxy
...@@ -156,7 +175,7 @@ ...@@ -156,7 +175,7 @@
<q-input filled v-model="msg.Q_NotFollowUpDay" label="几天未跟进"></q-input> <q-input filled v-model="msg.Q_NotFollowUpDay" label="几天未跟进"></q-input>
</div> </div>
<div class="col-3"> <div class="col-3">
<selectTree <!-- <selectTree
:treeData="data.EmployeeList" :treeData="data.EmployeeList"
:defaultArray="data.defaultArray" :defaultArray="data.defaultArray"
nodeKey="newId" nodeKey="newId"
...@@ -165,7 +184,15 @@ ...@@ -165,7 +184,15 @@
childrenKey="ChildList" childrenKey="ChildList"
tipText="选择部门/人员" tipText="选择部门/人员"
@getChild="getChild" @getChild="getChild"
></selectTree> ></selectTree>-->
<Cascader
:options="data.EmployeeList"
optionLabel="DeptName"
optionValue="newId"
optionChildren="ChildList"
label="选择部门/人员"
:multiple="true"
/>
</div> </div>
<div class="col-3"> <div class="col-3">
<q-btn color="primary" size="sm" label="导入" /> <q-btn color="primary" size="sm" label="导入" />
...@@ -189,7 +216,10 @@ ...@@ -189,7 +216,10 @@
<img :src="props.row.WeChatPhoto" style="width:100%;height:100%" /> <img :src="props.row.WeChatPhoto" style="width:100%;height:100%" />
</div> </div>
<div> <div>
<div class="cutomer_Free" @click="getCustomInfo(props)">{{ props.row.CustomerName }}</div> <div
class="cutomer_Free"
@click="getCustomInfo(props)"
>{{ props.row.CustomerName }}</div>
<div class="customer_Wechat">{{ props.row.WeChatName }}</div> <div class="customer_Wechat">{{ props.row.WeChatName }}</div>
</div> </div>
</div> </div>
...@@ -197,7 +227,7 @@ ...@@ -197,7 +227,7 @@
</template> </template>
<template v-slot:body-cell-LableList="props"> <template v-slot:body-cell-LableList="props">
<q-td auto-width :props="props"> <q-td auto-width :props="props">
<q-chip v-for="(item,index) in props.row.LableList" :key="index">{{item}}</q-chip> <q-chip v-for="(item,index) in props.row.LableList" :key="index">{{ item }}</q-chip>
</q-td> </q-td>
</template> </template>
<template v-slot:bottom> <template v-slot:bottom>
...@@ -219,12 +249,14 @@ ...@@ -219,12 +249,14 @@
<script lang='ts'> <script lang='ts'>
import { ref, defineComponent, onMounted } from 'vue' import { ref, defineComponent, onMounted } from 'vue'
import CustomerModule from '@/module/customer/customerModule' import CustomerModule from '@/module/customer/customerModule'
import selectTree from '@/components/common/selectTree.vue' // import selectTree from '@/components/common/selectTree.vue'
import customRight from '@/components/common/customRight.vue' import customRight from '@/components/common/customRight.vue'
import Cascader from "@/components/common/Cascader.vue"
export default defineComponent({ export default defineComponent({
components: { components: {
selectTree, // selectTree,
customRight customRight,
Cascader
}, },
setup() { setup() {
let { let {
...@@ -249,16 +281,16 @@ export default defineComponent({ ...@@ -249,16 +281,16 @@ export default defineComponent({
getCkedFriend getCkedFriend
} = CustomerModule() } = CustomerModule()
let isShowCustom = ref(false) let isShowCustom = ref(false)
const closeCustomer =()=>{ const closeCustomer = () => {
isShowCustom.value=false; isShowCustom.value = false;
} }
let CustomerId= ref(0); let CustomerId = ref(0);
const getCustomInfo =(item)=>{ const getCustomInfo = (item) => {
CustomerId.value = item.row.Id; CustomerId.value = item.row.Id;
isShowCustom.value=true; isShowCustom.value = true;
} }
onMounted(() => { onMounted(() => {
getCustomerList(msg) getCustomerList(msg)
getWayList({}) getWayList({})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment