瀏覽代碼

add:协作客户

ct 1 周之前
父節點
當前提交
1abd19b425

+ 62 - 0
src/api/crm/assist.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+// 查询客户员工协作列表
+export function listAssist(query) {
+  return request({
+    url: '/crm/assist/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询客户员工协作详细
+export function getAssist(id) {
+  return request({
+    url: '/crm/assist/' + id,
+    method: 'get'
+  })
+}
+
+// 新增客户员工协作
+export function addAssist(data) {
+  return request({
+    url: '/crm/assist',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改客户员工协作
+export function updateAssist(data) {
+  return request({
+    url: '/crm/assist',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除客户员工协作
+export function delAssist(id) {
+  return request({
+    url: '/crm/assist/' + id,
+    method: 'delete'
+  })
+}
+
+// 删除客户员工协作
+export function remove(data) {
+  return request({
+    url: '/crm/assist/remove',
+    method: 'post',
+    data: data
+  })
+}
+
+// 导出客户员工协作
+export function exportAssist(query) {
+  return request({
+    url: '/crm/assist/export',
+    method: 'get',
+    params: query
+  })
+}

+ 18 - 0
src/api/crm/customer.js

@@ -42,6 +42,16 @@ export function getMyCustomerList(query) {
   })
 }
 
+
+
+export function getMyAssistList(query) {
+  return request({
+    url: '/crm/customer/getMyAssistList',
+    method: 'get',
+    params: query
+  })
+}
+
 export function getCustomerDetails(query) {
   return request({
     url: '/crm/customer/getCustomerDetails/',
@@ -102,6 +112,14 @@ export function assignToUser(data) {
     data: data
   })
 }
+
+export function assistToUser(data) {
+  return request({
+    url: '/crm/customer/assistToUser',
+    method: 'post',
+    data: data
+  })
+}
 export function assignUser(data) {
   return request({
     url: '/crm/customer/assignUser',

+ 2 - 0
src/views/company/components/userSelect.vue

@@ -73,11 +73,13 @@ import {
   importTemplate,
 } from "@/api/company/companyUser";
 import { treeselect } from "@/api/company/companyDept";
+import { status } from "nprogress";
 export default {
   name: "User",
   
   data() {
     return {
+      status:0,
       selectUser:[],
       users:[],
       // 遮罩层

+ 205 - 0
src/views/crm/components/assistUser.vue

@@ -0,0 +1,205 @@
+<template>
+    <div>
+        <el-form ref="assistForm" :model="assistForm"  label-width="120px">
+            <el-form-item label="未添加协作客户" >
+            <span>{{this.noAssistCount}}个</span>
+            </el-form-item>
+            <el-form-item label="未添加协作客户" >
+            <span>{{this.assistCount}}个</span>
+            </el-form-item>
+
+            <el-form-item label="协作人" prop="users">
+                <el-row :gutter="10" class="mb8">
+                    <el-col :span="1.5">
+                        <el-button @click="handleUserSelect">添加协作人</el-button>
+                    </el-col>
+                </el-row>
+                <el-table border  :data="users" >
+                    <el-table-column label="ID" align="center" prop="userId" />
+                    <el-table-column label="员工帐号" align="center" prop="userName" />
+                    <el-table-column label="员工姓名" align="center" prop="nickName" />
+                    <el-table-column label="所属部门" align="center" prop="deptName" />
+                    <el-table-column label="添加数量" align="center"  prop="count" width="150px" >
+                        <template slot-scope="scope">
+                        <div>
+                            <el-input-number ref="stepTxtNum" :min="0" v-model="scope.row.count"  @change="changeVal(scope.row)"   size="mini"   ></el-input-number>
+                        </div>
+                    </template>
+                    </el-table-column>
+                    <el-table-column label="操作"   align="center" fixed="right" class-name="small-padding fixed-width">
+                        <template slot-scope="scope">
+                            <el-button
+                            size="mini"
+                            type="text"
+                            @click="handleRemoveUser(scope.row.$index)"
+                            >删除</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </el-form-item>
+        </el-form>
+        <div   class="footer">
+            <el-button type="primary" @click="submitAssistForm">确 定</el-button>
+        </div>
+        <el-dialog :title="userSelect.title" :visible.sync="userSelect.open" width="1000px" append-to-body>
+            <user-select ref="userSelects" @selectUser="selectUser"  ></user-select>
+        </el-dialog>
+    </div>
+</template>
+  
+<script>
+    import { assistToUser } from "@/api/crm/customer";
+    import userSelect from '../../company/components/userSelect.vue';
+    export default {
+        components: {userSelect },
+        name: "visit",
+        data() {
+            return {
+                noAssistCount:0,
+                assistCount:0,
+                customerIds:[],
+                userSelect:{
+                    title:"选择员工",
+                    open:false,
+                },
+                assistForm: {
+                },
+                // 表单校验
+                assistRules: {
+                    
+                },
+                users:[],
+                 
+            };
+        },
+        created() {
+          
+        },
+        methods: {
+            changeVal(row) {
+                this.$forceUpdate();//解决点击计数器失效问题
+                this.computeCount();
+                if(this.assistCount>this.customerIds.length){
+                    this.$nextTick(() => {
+                         row.count=0;
+                         this.computeCount();
+                    });
+                   
+                }
+            },
+            handleRemoveUser(index){
+                this.users.splice(index,1);
+                this.computeCount();
+                this.$refs.userSelects.delUser(index);
+            },
+            selectUser(data){
+                var users=[];
+                var number=parseInt(this.customerIds.length/data.length);
+                data.forEach(element => {
+                    var user={
+                        userId:element.userId,
+                        userName:element.userName,
+                        nickName:element.nickName,
+                        deptName:element.dept.deptName,
+                        nowDayCustomerCount:element.nowDayCustomerCount,
+                        phonenumber:element.phonenumber,
+                        count:number,
+                    }
+                    users.push(user)
+                });
+                this.users=users;
+                this.userSelect.open=false;
+                this.computeCount()
+            },
+            computeCount(){
+                this.assistCount=0;
+                var that=this;
+                this.users.forEach(element => {
+                    that.assistCount+=element.count;
+                });
+                this.noAssistCount=this.customerIds.length-this.assistCount
+            },
+            handleUserSelect(){
+                var that=this;
+                this.userSelect.open=true;
+                setTimeout(() => {
+                    that.$refs.userSelects.getList();
+                }, 500);
+            },
+            init(customerIds){
+                this.customerIds =  customerIds;
+                this.assistCount=0;
+                this.noAssistCount=this.customerIds.length;
+                this.users=[];
+            },
+            /** 提交按钮 */
+            submitAssistForm() {
+                var that=this;
+                this.$refs["assistForm"].validate(valid => {
+                    if (valid) {
+                        var users=[];
+                        var customerIds=[];
+                        var idIndex=0;
+                        var totalAssistCount=0;
+                        console.log("qxj users",JSON.stringify(this.users));
+                        this.users.forEach(element => {
+                            if(element.count>0){
+                                var ids=that.customerIds.slice(idIndex,idIndex+element.count)
+                                console.log("qxj customerIds:"+that.customerIds+" count:"+element.count);
+                                console.log("qxj ids:"+ids);
+                                customerIds=customerIds.concat(ids);
+                                idIndex=idIndex+element.count;
+                                var data={companyUserId:element.userId,count:element.count};
+                                users.push(data);
+                                totalAssistCount+=element.count;
+                            }
+                        });
+                        if(users.length==0){
+                            this.msgError("请选择员工");
+                            return;
+                        }
+                        if(totalAssistCount>(this.assistCount+this.noAssistCount)){
+                            this.msgError("添加数量有误");
+                            return;
+                        }
+                        this.myloading = this.$loading({
+                            lock: true,
+                            text: '处理中...',
+                            spinner: 'el-icon-loading',
+                            background: 'rgba(0, 0, 0, 0.7)'
+                        });
+                        var data={customerIds:customerIds,users:users}
+                        console.log("qxj data:",JSON.stringify(data));
+                        assistToUser(data).then(response => {
+                            this.myloading.close()
+                            if (response.code === 200) {
+                                this.msgSuccess("操作成功");
+                                this.$emit('close');
+                            }
+                        });
+                    }
+                });
+            },
+            closeAction(){
+                this.$refs.userSelects.users=[];
+            }
+        }
+    };
+</script>
+<style lang="scss" scoped>
+.contents{
+    height: 100%;
+    background-color: #fff;
+    padding: 20px;
+        
+}
+.footer{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+}
+</style>
+
+
+
+ 

+ 806 - 0
src/views/crm/customer/assist.vue

@@ -0,0 +1,806 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="客户编码" prop="customerCode">
+        <el-input
+          style="width:220px"
+          v-model="queryParams.customerCode"
+          placeholder="请输入客户编码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="客户名称" prop="customerName">
+        <el-input
+          style="width:220px"
+          v-model="queryParams.customerName"
+          placeholder="请输入客户名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="手机" prop="mobile">
+        <el-input
+        style="width:220px"
+          v-model="queryParams.mobile"
+          placeholder="请输入手机"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="跟进阶段" prop="status">
+        <el-select style="width:220px" multiple filterable  v-model="statusArr" placeholder="请选择跟进阶段" clearable size="small">
+           <el-option
+                v-for="item in statusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客户类型" prop="customerType">
+        <el-select style="width:220px" multiple filterable  v-model="ctsTypeArr" placeholder="请选择客户类型" clearable size="small">
+           <el-option
+                v-for="item in typeOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客户标签" prop="tags">
+            <el-select style="width:220px" multiple  filterable v-model="tagIds" placeholder="请选择客户标签" clearable size="small">
+              <el-option
+                    v-for="item in tagsOptions"
+                    :key="item.dictLabel"
+                    :label="item.dictLabel"
+                    :value="item.dictLabel"
+                  />
+            </el-select>
+          </el-form-item>
+      <el-form-item label="客户来源" prop="source">
+        <el-select style="width:220px" multiple filterable  v-model="sourceArr" placeholder="请选择客户来源" clearable size="small">
+           <el-option
+                v-for="item in sourceOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTimeRange">
+        <el-date-picker
+          style="width:205.4px"
+          clearable size="small"
+          v-model="createTimeRange"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="领取时间" prop="receiveTime">
+        <el-date-picker
+              style="width:220px"
+              clearable size="small"
+              v-model="dateRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+      </el-form-item>
+      <el-form-item label="历史订单" prop="isHisOrder">
+          <el-select style="width:220px" filterable v-model="queryParams.isHisOrder" placeholder="请选择历史订单" clearable size="small">
+            <el-option key="1"  label="已下单" value="1" />
+            <el-option key="0"  label="未下单" value="0" />
+          </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="multiple"
+          @click="handleAssist"
+          v-hasPermi="['crm:customer:assistToUser']"
+        >客户协作</el-button>
+      </el-col>  
+      
+      
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          size="mini"
+          :disabled="multiple"
+          @click="handleSendBatchSms"
+          v-hasPermi="['crm:customer:sendBatchSms']"
+        >批量发送短信</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-dropdown
+          @command="handleCommand"
+          trigger="click"
+          placement="bottom-start"
+        >
+          <el-dropdown-menu slot="dropdown" style="width: 120px;">
+            <el-dropdown-item
+              v-for="option in sysCreateType"
+              :key="option.dictValue"
+              :command="option.dictValue"
+            >
+              <i :class="option.iconClass" style="margin-right: 10px;"></i>
+              {{ option.dictLabel }}
+            </el-dropdown-item>
+          </el-dropdown-menu>
+          <span class="el-dropdown-link" >
+              <el-button  type="success"   size="mini" >
+                创建订单
+              </el-button>
+            </span>
+        </el-dropdown>
+
+<!--        <el-button-->
+<!--          type="success"-->
+<!--          size="mini"-->
+<!--          @click="addPackageOrder"-->
+<!--        >创建订单</el-button>-->
+      </el-col>
+      
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['crm:customer:export']"
+        >导出</el-button>
+      </el-col> -->
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table  height="500" border v-loading="loading" :data="customerList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="客户编码" align="center" prop="customerCode" />
+      <el-table-column  label="客户名称"   align="center" prop="customerName" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-link @click="handleShow(scope.row)" :underline="false" type="primary" >{{scope.row.customerName}}</el-link>
+        </template>
+      </el-table-column>
+      <el-table-column  label="手机" width="120px"  align="center" prop="mobile"   >
+        <template slot-scope="scope">
+          {{scope.row.mobile}}
+          <el-button type="text"    size="mini" @click="callNumber(scope.row.customerId,null)">拨号</el-button>
+          <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisit(scope.row)">写跟进</el-button>
+          <el-button type="text"    size="mini" @click="addPackageOrder()" style="margin-right: 15px;">创建订单</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="客户来源" align="center" prop="source">
+        <template slot-scope="scope">
+            <el-tag prop="status" v-for="(item, index) in sourceOptions"    v-if="scope.row.source==item.dictValue">{{item.dictLabel}}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column  label="跟进阶段"  width="200" align="center" prop="visitStatus">
+        <template slot-scope="scope">
+            <el-tag prop="visitStatus" v-for="(item, index) in statusOptions"    v-if="scope.row.visitStatus==item.dictValue">{{item.dictLabel}}</el-tag><br/>
+            <el-button  v-hasPermi="['crm:customer:addVisitStatus']"  type="text" size="mini" @click="handleVisitStatus(scope.row)">修改</el-button>
+          </template>
+      </el-table-column>
+      <el-table-column  label="客户类型"  width="200" align="center" prop="customerType">
+        <template slot-scope="scope">
+            <el-tag prop="status" v-for="(item, index) in typeOptions"    v-if="scope.row.customerType==item.dictValue">{{item.dictLabel}}</el-tag>
+            <el-button   v-hasPermi="['crm:customer:addCustomerType']"  type="text" size="mini" @click="handleCustomerType(scope.row)">修改</el-button>
+          </template>
+      </el-table-column>
+      <el-table-column  label="标签" width="120px"  align="center" prop="tags"   >
+        <template slot-scope="scope">
+          {{scope.row.tags}}
+          <el-button  v-hasPermi="['crm:customer:addTag']"  type="text" size="mini" @click="handleAddTag(scope.row)">打标签</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="备注" width="150px"  align="center" prop="remark"   >
+        <template slot-scope="scope">
+          {{scope.row.remark}}
+          <el-button v-hasPermi="['crm:customer:addRemark']" type="text" size="mini" @click="handleAddRemark(scope.row)">修改备注</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="邀请人" width="150px" align="center" >
+        <template slot-scope="scope">
+          <div v-for="(user, index) in scope.row.assistUser" :key="index">
+            {{ user }}
+            <br v-if="index < scope.row.assistUser.length - 1"> <!-- 在最后一个元素之前添加换行 -->
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="进线客户详情" align="center" :show-overflow-tooltip="true" prop="registerDesc" />
+      <el-table-column label="最新跟进时间" align="center" prop="lastTime" />
+      <el-table-column label="领取时间" align="center" prop="receiveTime" />
+      <el-table-column label="进线客户提交日期" align="center" prop="registerSubmitTime" />
+      <el-table-column label="创建时间" align="center" prop="customerCreateTime" width="180">
+      </el-table-column>
+      <el-table-column label="操作"   align="center" fixed="right" width="120px" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleShow(scope.row)"
+            v-hasPermi="['crm:customer:query']"
+          >查看</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleRecover(scope.row)"
+            v-hasPermi="['crm:customer:recover']"
+          >回收公海</el-button>
+          
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <el-drawer size="75%" :title="show.title" :visible.sync="show.open">
+        <customer-details  ref="customerDetails" />
+    </el-drawer>
+    <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="1000px" append-to-body>
+       <add-batch-sms ref="sms" @close="closeSms()"></add-batch-sms>
+    </el-dialog>
+
+
+    <el-dialog :title="source.title" :visible.sync="source.open" width="1000px" append-to-body>
+       <edit-source ref="editSource" @close="closeSource()"></edit-source>
+    </el-dialog>
+
+    <el-dialog :title="visit.title" :visible.sync="visit.open" width="600px" append-to-body>
+      <add-visit @closeVisit="closeVisit"   ref="addVisit" />
+    </el-dialog>
+    <el-dialog :title="customer.title" :visible.sync="customer.open" width="1000px" append-to-body>
+       <add-or-edit-customer ref="customer" @close="closeCustomer()"></add-or-edit-customer>
+    </el-dialog>
+    <el-dialog :title="assign.title" :visible.sync="assign.open" width="800px" append-to-body>
+        <assign-user  ref="assignUser" @close="closeAssign"   />
+    </el-dialog>
+    <el-dialog :title="assist.title" :visible.sync="assist.open" width="800px" append-to-body>
+        <assist-user  ref="assistUser" @close="closeAssist"   />
+    </el-dialog>
+    
+    <el-dialog :title="addTag.title" :visible.sync="addTag.open" width="600px" append-to-body>
+        <add-tag ref="tag" @close="closeTag()"></add-tag>
+    </el-dialog>
+    <el-dialog :title="addRemark.title" :visible.sync="addRemark.open" width="600px" append-to-body>
+        <add-remark ref="remark" @close="closeRemark()"></add-remark>
+    </el-dialog>
+    <el-dialog :title="addCustomerType.title" :visible.sync="addCustomerType.open" width="600px" append-to-body>
+        <add-customer-type ref="customerType" @close="closeCustomerType()"></add-customer-type>
+    </el-dialog>
+    <el-dialog :title="addVisitStatus.title" :visible.sync="addVisitStatus.open" width="600px" append-to-body>
+        <add-visit-status ref="visitStatus" @close="closeVisitStatus()"></add-visit-status>
+    </el-dialog>
+    <el-dialog title="创建线上订单" :visible.sync="addPackageOpen" width="1000px" append-to-body>
+      <addPackage  @closePackage="closePackage"   ref="addPackageVisit" />
+    </el-dialog>
+    <el-dialog title="创建线下订单" :visible.sync="addOfflineOrder.open" width="1000px" append-to-body>
+      <add-order-offline @closeOrderOffline="closeOrderOffline"   ref="addOrderOffline" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getMyAssistList,recover,exportCustomer  } from "@/api/crm/customer";
+import { remove,listAssist, getAssist, delAssist, addAssist, updateAssist, exportAssist } from "@/api/crm/assist";
+import customerDetails from '../components/customerDetails.vue';
+import addVisit from '../components/addVisit.vue';
+import {getCitys} from "@/api/store/city";
+import addBatchSms from '../components/addBatchSms.vue';
+import editSource from '../components/editSource.vue';
+import addOrEditCustomer from '../components/addOrEditCustomer.vue';
+import assignUser from '../components/assignUser.vue';
+import assistUser from '../components/assistUser.vue';
+import addTag from '../components/addTag.vue';
+import addRemark from '../components/addRemark.vue';
+import addCustomerType from '../components/addCustomerType.vue';
+import addVisitStatus from '../components/addVisitStatus.vue';
+import addPackage from "@/views/store/components/addOrder";
+import addOrderOffline from "@/views/store/components/addOrderOffline";
+export default {
+  name: "Customer",
+  components: {addPackage,addOrderOffline,addVisitStatus,addCustomerType,addRemark,addTag,assignUser,assistUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit },
+  data() {
+    return {
+      addOfflineOrder:{
+        open:false,
+      },
+      sysCreateType:[
+        { dictLabel: "线下订单", dictValue: "1" },
+
+        { dictLabel: "线上订单", dictValue: "2" },
+      ],
+      addPackageOpen:false,
+      addVisitStatus:{
+          open:false,
+          title:"跟进阶段"
+      },
+      addCustomerType:{
+          open:false,
+          title:"客户类型"
+      },
+      addRemark:{
+          open:false,
+          title:"客户备注"
+      },
+      addTag:{
+          open:false,
+          title:"打标签"
+      },
+      tagIds:[],
+      statusArr:[],
+      ctsTypeArr:[],
+      sourceArr:[],
+      tagsOptions:[],
+      createTimeRange:[],
+      customer:{
+          open:false,
+          title:"新增客户"
+      },
+      users:[],
+      visit:{
+          open:false,
+          title:"写跟进"
+      },
+      source:{
+          open:false,
+          title:"修改客户来源"
+      },
+      assign:{
+        title:"分配客户",
+        open:false,
+      },
+      assist:{
+        title:"添加协作人",
+        open:false,
+      },
+      assignForm: {
+      },
+      // 表单校验
+      assignRules: {
+        // companyUserId: [
+        //   { required: true, message: "员工不能为空", trigger: "blur" }
+        // ],
+      },
+      dateRange:[],
+      addSms:{
+          open:false,
+          title:"批量发短信"
+      },
+      cityIds:[],
+      citys:[],
+      tags:[],
+      inputVisible: false,
+      inputValue: '',
+      statusOptions:[],
+      typeOptions:[],
+      sourceOptions:[],
+      sexOptions:[],
+      show:{
+        title:"客户详情",
+        open:false,
+      },
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 客户表格数据
+      customerList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        customerCode: null,
+        customerName: null,
+        mobile: null,
+        sex: null,
+        weixin: null,
+        userId: null,
+        createUserId: null,
+        receiveUserId: null,
+        customerUserId: null,
+        address: null,
+        location: null,
+        detailAddress: null,
+        lng: null,
+        lat: null,
+        status: null,
+        deptId: null,
+        isDel: null,
+        customerType: null,
+        receiveTime: null,
+        poolTime: null,
+        companyId: null,
+        isLine: null,
+        source: null,
+        tags: null
+      },
+      // 表单参数
+      form: {
+        province:null,
+        city:null,
+        district:null,
+      },
+      // 表单校验
+      rules: {
+        customerName: [
+          { required: true, message: "客户名称不能为空", trigger: "blur" }
+        ],
+        mobile: [
+          { required: true, message: "手机号不能为空", trigger: "blur" }
+        ],
+        sex: [
+          { required: true, message: "性别不能为空", trigger: "blur" }
+        ],
+        source: [
+          { required: true, message: "客户来源不能为空", trigger: "blur" }
+        ],
+      },
+      loading:null,
+    };
+  },
+  created() {
+    this.getDicts("crm_customer_source").then((response) => {
+      this.sourceOptions = response.data;
+    });
+    this.getDicts("common_sex").then((response) => {
+      this.sexOptions = response.data;
+    });
+    this.getDicts("crm_customer_user_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("crm_customer_type").then((response) => {
+      this.typeOptions = response.data;
+    });
+    this.getDicts("crm_customer_tag").then((response) => {
+        this.tagsOptions = response.data;
+    });
+    this.getCitys();
+    this.getList();
+  },
+  methods: {
+    handleCommand(command){
+      if (command==="1"){
+        this.addOfflineOrder.open = true
+      }else {
+        this.addPackageOpen=true;
+      }
+    },
+    closeOrderOffline(){
+      this.addOfflineOrder.open = false
+    },
+    addPackageOrder(){
+       this.addPackageOpen=true;
+    },
+    closePackage(){
+      this.addPackageOpen=false;
+    },
+    closeVisitStatus(){
+        this.addVisitStatus.open=false;
+        this.getList();
+    },
+    handleVisitStatus(row){
+        this.addVisitStatus.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.visitStatus.reset(row);
+        }, 500);
+
+    },
+    closeCustomerType(){
+        this.addCustomerType.open=false;
+        this.getList();
+    },
+    handleCustomerType(row){
+        this.addCustomerType.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.customerType.reset(row);
+        }, 500);
+
+    },
+    closeRemark(){
+        this.addRemark.open=false;
+        this.getList();
+    },
+    handleAddRemark(row){
+        this.addRemark.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.remark.reset(row);
+        }, 500);
+
+    },
+    closeTag(){
+        this.addTag.open=false;
+        this.getList();
+    },
+    handleAddTag(row){
+        this.addTag.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.tag.reset(row);
+        }, 500);
+
+    },
+    handleShow(row){
+      this.show.open=true;
+      var that=this;
+      const tab = "visit";
+      setTimeout(() => {
+        that.$refs.customerDetails.getDetails(row.customerId);
+        that.$refs.customerDetails.handleClick(tab);
+
+      }, 200);
+    },
+    handleAdd() {
+      this.customer.open = true;
+      var that=this;
+      setTimeout(() => {
+        that.$refs.customer.handleAdd(2);
+      }, 200);
+    },
+    closeCustomer(){
+        this.customer.open=false;
+        this.getList();
+    },
+    closeVisit(){
+        this.visit.open=false;
+        this.getList();
+    },
+    handleAddVisit(row){
+        this.visit.open=true;
+        setTimeout(() => {
+            this.$refs.addVisit.reset(row.customerId);
+        }, 200);
+    },
+    handleAssist(){
+      var that=this;
+      var ids=this.ids;
+      that.assist.open=true;
+      setTimeout(() => {
+          that.$refs.assistUser.init(ids);
+      }, 200);
+    },
+    handleRemoveAllAssist(){
+      const ids = this.ids;
+      const data = {customerIds:ids,companyUserId:null}
+      this.$confirm('是否确认删除协作人?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    handleRemoveAssist(row,userName){
+      const match = userName.match(/\((\d+)\)/);
+      const companyUserId = match[1];
+      const data = {customerIds:[row.customerId],companyUserId:companyUserId}
+      this.$confirm('是否确认删除"' + userName + '"协作?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    handleAssign(){
+      var that=this;
+      var ids=this.ids;
+      that.assign.open=true;
+      setTimeout(() => {
+          that.$refs.assignUser.init(ids,3);
+      }, 200);
+    },
+    closeAssign(){
+      this.assign.open=false;
+      this.getList();
+    },
+    closeAssist(){
+      this.assist.open=false;
+      this.getList();
+    },
+    handleEditScource(){
+      this.source.open=true;
+      var that=this;
+      setTimeout(() => {
+        that.$refs.editSource.handleEdit(that.ids);
+      }, 200);
+
+    },
+    closeSource(){
+        this.source.open=false;
+        this.getList();
+    },
+    closeSms(){
+        this.addSms.open=false;
+    },
+    handleSendBatchSms(){
+      const customerIds =  this.ids;
+      this.addSms.open=true;
+      var that=this;
+      setTimeout(() => {
+          console.log(customerIds)
+          that.$refs.sms.reset(customerIds);
+      }, 500);
+
+    },
+    handleRecover(row) {
+      this.$confirm('是否确认回收客户"' + row.customerName + '"?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          var data={customerUserId:row.customerUserId}
+          return recover(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("操作成功");
+        }).catch(function() {});
+    },
+    handleCityChange(value) {
+      console.log(value);
+      var nodes=this.$refs.citySelect.getCheckedNodes();
+      this.form.address=nodes[0].pathLabels[0]+"-"+nodes[0].pathLabels[1]+"-"+nodes[0].pathLabels[2];
+      this.form.cityIds=value.toString();
+    },
+    getCitys(){
+        getCitys().then(res => {
+          this.loading = false;
+          this.citys=res.data;
+        })
+    },
+
+    /** 查询客户列表 */
+    getList() {
+      this.loading = true;
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.statusArr.length>0){
+        this.queryParams.status=this.statusArr.toString();
+      }
+      else{
+        this.queryParams.status=null
+      }
+
+      if(this.ctsTypeArr.length>0){
+        this.queryParams.customerType=this.ctsTypeArr.toString();
+      }
+      else{
+        this.queryParams.customerType=null
+      }
+
+      if(this.sourceArr.length>0){
+        this.queryParams.source=this.sourceArr.toString();
+      }
+      else{
+        this.queryParams.source=null
+      }
+
+      if(this.tagIds.length>0){
+        this.queryParams.tags=this.tagIds.toString();
+      }
+      else{
+        this.queryParams.tags=null
+      }
+      getMyAssistList(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.customerList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.customerId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+
+
+
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const customerIds = row.customerId || this.ids;
+      this.$confirm('是否确认删除客户编号为"' + customerIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delLineCustomer(customerIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有客户数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportCustomer(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    },
+  }
+};
+</script>
+<style>
+  .el-tag + .el-tag {
+    margin-left: 10px;
+  }
+  .button-new-tag {
+    margin-left: 10px;
+    height: 32px;
+    line-height: 30px;
+    padding-top: 0;
+    padding-bottom: 0;
+  }
+  .input-new-tag {
+    width: 90px;
+    margin-left: 10px;
+    vertical-align: bottom;
+  }
+  .el-dialog__wrapper{
+    z-index: 100000;
+  }
+</style>

+ 81 - 2
src/views/crm/customer/my.vue

@@ -115,6 +115,16 @@
             v-hasPermi="['crm:customer:addMyCustomer']"
           >新增客户</el-button>
         </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="multiple"
+          @click="handleAssist"
+          v-hasPermi="['crm:customer:assistToUser']"
+        >客户协作</el-button>
+      </el-col>  
       <el-col :span="1.5">
         <el-button
           type="success"
@@ -172,6 +182,15 @@
 <!--          @click="addPackageOrder"-->
 <!--        >创建订单</el-button>-->
       </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleRemoveAllAssist"
+        >删除协作人</el-button>
+      </el-col> 
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -226,7 +245,16 @@
       <el-table-column  label="备注" width="150px"  align="center" prop="remark"   >
         <template slot-scope="scope">
           {{scope.row.remark}}
-          <el-button   v-hasPermi="['crm:customer:addRemark']" type="text" size="mini" @click="handleAddRemark(scope.row)">修改备注</el-button>
+          <el-button v-hasPermi="['crm:customer:addRemark']" type="text" size="mini" @click="handleAddRemark(scope.row)">修改备注</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="协作人" width="150px" align="center" >
+        <template slot-scope="scope">
+          <div v-for="(user, index) in scope.row.assistUser" :key="index">
+            {{ user }}
+            <el-button icon="el-icon-remove-outline" type="text" size="mini" @click="handleRemoveAssist(scope.row,user)"></el-button>
+            <br v-if="index < scope.row.assistUser.length - 1"> <!-- 在最后一个元素之前添加换行 -->
+          </div>
         </template>
       </el-table-column>
       <el-table-column label="进线客户详情" align="center" :show-overflow-tooltip="true" prop="registerDesc" />
@@ -287,6 +315,10 @@
     <el-dialog :title="assign.title" :visible.sync="assign.open" width="800px" append-to-body>
         <assign-user  ref="assignUser" @close="closeAssign"   />
     </el-dialog>
+    <el-dialog :title="assist.title" :visible.sync="assist.open" width="800px" append-to-body>
+        <assist-user  ref="assistUser" @close="closeAssist"   />
+    </el-dialog>
+    
     <el-dialog :title="addTag.title" :visible.sync="addTag.open" width="600px" append-to-body>
         <add-tag ref="tag" @close="closeTag()"></add-tag>
     </el-dialog>
@@ -310,6 +342,7 @@
 
 <script>
 import { getMyCustomerList,recover,exportCustomer  } from "@/api/crm/customer";
+import { remove,listAssist, getAssist, delAssist, addAssist, updateAssist, exportAssist } from "@/api/crm/assist";
 import customerDetails from '../components/customerDetails.vue';
 import addVisit from '../components/addVisit.vue';
 import {getCitys} from "@/api/store/city";
@@ -317,6 +350,7 @@ import addBatchSms from '../components/addBatchSms.vue';
 import editSource from '../components/editSource.vue';
 import addOrEditCustomer from '../components/addOrEditCustomer.vue';
 import assignUser from '../components/assignUser.vue';
+import assistUser from '../components/assistUser.vue';
 import addTag from '../components/addTag.vue';
 import addRemark from '../components/addRemark.vue';
 import addCustomerType from '../components/addCustomerType.vue';
@@ -325,7 +359,7 @@ import addPackage from "@/views/store/components/addOrder";
 import addOrderOffline from "@/views/store/components/addOrderOffline";
 export default {
   name: "Customer",
-  components: {addPackage,addOrderOffline,addVisitStatus,addCustomerType,addRemark,addTag,assignUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit },
+  components: {addPackage,addOrderOffline,addVisitStatus,addCustomerType,addRemark,addTag,assignUser,assistUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit },
   data() {
     return {
       addOfflineOrder:{
@@ -376,6 +410,10 @@ export default {
         title:"分配客户",
         open:false,
       },
+      assist:{
+        title:"添加协作人",
+        open:false,
+      },
       assignForm: {
       },
       // 表单校验
@@ -586,6 +624,43 @@ export default {
             this.$refs.addVisit.reset(row.customerId);
         }, 200);
     },
+    handleAssist(){
+      var that=this;
+      var ids=this.ids;
+      that.assist.open=true;
+      setTimeout(() => {
+          that.$refs.assistUser.init(ids);
+      }, 200);
+    },
+    handleRemoveAllAssist(){
+      const ids = this.ids;
+      const data = {customerIds:ids,companyUserId:null}
+      this.$confirm('是否确认删除协作人?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    handleRemoveAssist(row,userName){
+      const match = userName.match(/\((\d+)\)/);
+      const companyUserId = match[1];
+      const data = {customerIds:[row.customerId],companyUserId:companyUserId}
+      this.$confirm('是否确认删除"' + userName + '"协作?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
     handleAssign(){
       var that=this;
       var ids=this.ids;
@@ -598,6 +673,10 @@ export default {
       this.assign.open=false;
       this.getList();
     },
+    closeAssist(){
+      this.assist.open=false;
+      this.getList();
+    },
     handleEditScource(){
       this.source.open=true;
       var that=this;