Browse Source

fix(客户管理):分配、领取、转移联调

wanglj 3 years ago
parent
commit
c29a4fe606

+ 3 - 18
src/api/customer/follow.js

@@ -15,12 +15,7 @@ export default {
   },
   // 跟进记录详情
   getListByDay(query) {
-    return micro_request.postRequest(
-      basePath,
-      'FollowUp',
-      'GetListByDay',
-      query
-    )
+    return micro_request.postRequest(basePath, 'FollowUp', 'GetListByDay', query)
   },
   // 添加跟进记录
   addFollowUp(query) {
@@ -28,20 +23,10 @@ export default {
   },
   // 评论列表
   getComment(query) {
-    return micro_request.postRequest(
-      basePath,
-      'FollowUpComment',
-      'GetList',
-      query
-    )
+    return micro_request.postRequest(basePath, 'FollowUpComment', 'GetList', query)
   },
   // 添加评论
   addComment(query) {
-    return micro_request.postRequest(
-      basePath,
-      'FollowUpComment',
-      'Create',
-      query
-    )
+    return micro_request.postRequest(basePath, 'FollowUpComment', 'Create', query)
   },
 }

+ 15 - 46
src/api/customer/index.js

@@ -2,7 +2,7 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-27 11:10:39
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-30 11:24:07
+ * @LastEditTime: 2023-01-04 18:07:11
  * @Description: file content
  * @FilePath: \opms_frontend\src\api\customer\index.js
  */
@@ -11,21 +11,11 @@ const basePath = process.env.VUE_APP_ParentPath
 export default {
   // 客户详情
   getDetail(query) {
-    return micro_request.postRequest(
-      basePath,
-      'Customer',
-      'GetEntityById',
-      query
-    )
+    return micro_request.postRequest(basePath, 'Customer', 'GetEntityById', query)
   },
   // 客户详情内容摘要
   getAbstract(query) {
-    return micro_request.postRequest(
-      basePath,
-      'Customer',
-      'CustAbstract',
-      query
-    )
+    return micro_request.postRequest(basePath, 'Customer', 'CustAbstract', query)
   },
   // 客户编辑
   updateCostomer(query) {
@@ -33,30 +23,15 @@ export default {
   },
   // 客户合并
   mergeCustomer(query) {
-    return micro_request.postRequest(
-      basePath,
-      'Customer',
-      'Mergecustomer',
-      query
-    )
+    return micro_request.postRequest(basePath, 'Customer', 'Mergecustomer', query)
   },
   // 客户联系人详情
   getContact(query) {
-    return micro_request.postRequest(
-      basePath,
-      'Contant',
-      'GetEntityById',
-      query
-    )
+    return micro_request.postRequest(basePath, 'Contant', 'GetEntityById', query)
   },
   // 客户动态
   dynamicsList(query) {
-    return micro_request.postRequest(
-      basePath,
-      'Customer',
-      'DynamicsList',
-      query
-    )
+    return micro_request.postRequest(basePath, 'Customer', 'DynamicsList', query)
   },
   // 客户归属记录
   getBelongs(query) {
@@ -80,29 +55,23 @@ export default {
   },
   // 客户列表
   getPublicList(query) {
-    return micro_request.postRequest(
-      basePath,
-      'Customer',
-      'PublicGetList',
-      query
-    )
+    return micro_request.postRequest(basePath, 'Customer', 'PublicGetList', query)
   },
   // 客户删除
   deleteCustomer(query) {
     return micro_request.postRequest(basePath, 'Customer', 'DeleteById', query)
   },
   // 客户领取
-  // receiveCustomer(query) {
-  // return micro_request.postRequest(basePath, 'Contant', 'Create', query)
-  // },
+  receiveCustomer(query) {
+    return micro_request.postRequest(basePath, 'Customer', 'DistriCustomer', query)
+  },
+  // 客户转移
+  updateBytransfer(query) {
+    return micro_request.postRequest(basePath, 'Customer', 'UpdateBytransfer', query)
+  },
   // 省份
   getProvinceInfo(query) {
-    return micro_request.postRequest(
-      basePath,
-      'District',
-      'GetProvinceInfo',
-      query
-    )
+    return micro_request.postRequest(basePath, 'District', 'GetProvinceInfo', query)
   },
   // 省份详情
   getProvinceDetail(query) {

+ 10 - 11
src/store/modules/user.js

@@ -9,11 +9,13 @@ import { isArray, isString } from '@/utils/validate'
 import { title, tokenName } from '@/config'
 
 const state = () => ({
+  id: '',
   token: getToken(),
   username: '游客',
   avatar: 'https://i.gtimg.cn/club/item/face/img/2/15922_100.gif',
 })
 const getters = {
+  id: (state) => state.id,
   token: (state) => state.token,
   username: (state) => state.username,
   avatar: (state) => state.avatar,
@@ -36,6 +38,9 @@ const mutations = {
   setUsername(state, username) {
     state.username = username
   },
+  setUserId(state, id) {
+    state.id = id
+  },
   /**
    * @description 设置头像
    * @param {*} state
@@ -68,15 +73,7 @@ const actions = {
       commit('setToken', token)
       const hour = new Date().getHours()
       const thisTime =
-        hour < 8
-          ? '早上好'
-          : hour <= 11
-          ? '上午好'
-          : hour <= 13
-          ? '中午好'
-          : hour < 18
-          ? '下午好'
-          : '晚上好'
+        hour < 8 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 18 ? '下午好' : '晚上好'
       Vue.prototype.$baseNotify(`欢迎登录${title}`, `${thisTime}!`)
     } else {
       const err = `登录接口异常,未正确返回${tokenName}...`
@@ -96,6 +93,7 @@ const actions = {
     // console.log(username, avatar, roles, permissions)
 
     const res = await userApi.getUserInfo()
+    const userId = res.data.entity.id
     const username = res.data.entity.userName
     const avatar = res.data.entity.avatar
     let roles
@@ -117,6 +115,8 @@ const actions = {
       Vue.prototype.$baseMessage(err, 'error', 'vab-hey-message-error')
       throw err
     } else {
+      // 如不使用username用户名,可删除以下代码
+      if (userId) commit('setUserId', userId)
       // 如不使用username用户名,可删除以下代码
       if (username) commit('setUsername', username)
       // 如不使用avatar头像,可删除以下代码
@@ -124,8 +124,7 @@ const actions = {
       // 如不使用roles权限控制,可删除以下代码
       if (roles) dispatch('acl/setRole', roles, { root: true })
       // 如不使用permissions权限控制,可删除以下代码
-      if (permissions)
-        dispatch('acl/setPermission', permissions, { root: true })
+      if (permissions) dispatch('acl/setPermission', permissions, { root: true })
     }
   },
   /**

+ 20 - 4
src/views/customer/components/Allocate.vue

@@ -2,7 +2,7 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-26 14:34:34
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-29 11:26:07
+ * @LastEditTime: 2023-01-04 18:06:12
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\components\allocate.vue
 -->
@@ -16,7 +16,7 @@
       </el-form-item>
     </el-form>
     <span slot="footer">
-      <el-button size="mini" type="primary">保存</el-button>
+      <el-button size="mini" type="primary" @click="handleSubmit">保存</el-button>
       <el-button size="mini" @click="visible = false">取消</el-button>
     </span>
     <!--    <Transfer ref="transfer" />-->
@@ -27,7 +27,8 @@
 <script>
   // import Transfer from './Transfer.vue'
   import SelectUser from '@/components/select/SelectUser'
-
+  import api from '@/api/customer'
+  import to from 'await-to-js'
   export default {
     components: {
       // Transfer,
@@ -56,6 +57,8 @@
         allocate: [],
         data: generateData(),
         options: [],
+        ids: [],
+        userList: [],
       }
     },
     methods: {
@@ -65,7 +68,20 @@
         this.$refs.selectUser.open()
       },
       selectUser(userList) {
-        console.log(userList)
+        this.userList = userList
+        this.form.allocate = userList.map((item) => item.userName).join()
+      },
+      async handleSubmit() {
+        let params = {
+          salesId: this.userList[0].id,
+          ids: this.ids,
+          salesName: this.userList[0].userName,
+        }
+        const [err, res] = await to(api.receiveCustomer(params))
+        if (err) return
+        this.$message.success(res.msg)
+        this.visible = false
+        this.$emit('refresh')
       },
     },
   }

+ 9 - 28
src/views/customer/components/Contact.vue

@@ -1,9 +1,6 @@
 <template>
   <!-- 新建联系人弹窗 -->
-  <el-dialog
-    :title="title"
-    :visible.sync="contactVisible"
-    @close="contactClose">
+  <el-dialog :title="title" :visible.sync="contactVisible" @close="contactClose">
     <el-form ref="contactForm" :model="contactForm" :rules="contactRules">
       <el-row :gutter="20">
         <el-col :span="12">
@@ -13,19 +10,14 @@
         </el-col>
         <el-col :span="12">
           <el-form-item label="客户名称" prop="custName">
-            <el-input
-              v-model="contactForm.custName"
-              disabled
-              placeholder="请输入客户名称" />
+            <el-input v-model="contactForm.custName" disabled placeholder="请输入客户名称" />
           </el-form-item>
         </el-col>
       </el-row>
       <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="手机号码" prop="telephone">
-            <el-input
-              v-model="contactForm.telephone"
-              placeholder="请输入手机号码" />
+            <el-input v-model="contactForm.telephone" placeholder="请输入手机号码" />
           </el-form-item>
         </el-col>
         <el-col :span="12">
@@ -76,12 +68,8 @@
       </el-form-item>
     </el-form>
     <span slot="footer">
-      <el-button v-show="contactForm.id" type="primary" @click="contactEdit">
-        保存
-      </el-button>
-      <el-button v-show="!contactForm.id" type="primary" @click="contactSave">
-        保存
-      </el-button>
+      <el-button v-show="contactForm.id" type="primary" @click="contactEdit">保存</el-button>
+      <el-button v-show="!contactForm.id" type="primary" @click="contactSave">保存</el-button>
       <el-button @click="contactVisible = false">取消</el-button>
     </span>
   </el-dialog>
@@ -93,8 +81,7 @@
   export default {
     data() {
       var validateTel = (rule, value, callback) => {
-        const reg =
-          /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
+        const reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
         if (value === '') {
           callback(new Error('请输入手机号码'))
         } else if (!reg.test(value)) {
@@ -119,15 +106,9 @@
           policy: 0, //是否决策人 0 不是  1 是
         },
         contactRules: {
-          cuctName: [
-            { required: true, trigger: 'blur', message: '请输入联系人姓名' },
-          ],
-          custName: [
-            { required: true, trigger: 'blur', message: '请输入客户名称' },
-          ],
-          telephone: [
-            { required: true, trigger: 'blur', validator: validateTel },
-          ],
+          cuctName: [{ required: true, trigger: 'blur', message: '请输入联系人姓名' }],
+          custName: [{ required: true, trigger: 'blur', message: '请输入客户名称' }],
+          telephone: [{ required: true, trigger: 'blur', validator: validateTel }],
         },
       }
     },

+ 23 - 86
src/views/customer/components/Edit.vue

@@ -4,9 +4,7 @@
       <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="客户名称" prop="custName">
-            <el-input
-              v-model="editForm.custName"
-              placeholder="请输入客户名称" />
+            <el-input v-model="editForm.custName" placeholder="请输入客户名称" />
           </el-form-item>
         </el-col>
         <el-col :span="12">
@@ -18,29 +16,15 @@
       <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="客户行业" prop="custIndustry">
-            <el-select
-              v-model="editForm.custIndustry"
-              placeholder="请选择客户行业"
-              style="width: 100%">
-              <el-option
-                v-for="item in industryOptions"
-                :key="item.value"
-                :label="item.value"
-                :value="item.value" />
+            <el-select v-model="editForm.custIndustry" placeholder="请选择客户行业" style="width: 100%">
+              <el-option v-for="item in industryOptions" :key="item.value" :label="item.value" :value="item.value" />
             </el-select>
           </el-form-item>
         </el-col>
         <el-col :span="12">
           <el-form-item label="客户级别" prop="custLevel">
-            <el-select
-              v-model="editForm.custLevel"
-              placeholder="请选择客户级别"
-              style="width: 100%">
-              <el-option
-                v-for="item in levelOptions"
-                :key="item.value"
-                :label="item.value"
-                :value="item.value" />
+            <el-select v-model="editForm.custLevel" placeholder="请选择客户级别" style="width: 100%">
+              <el-option v-for="item in levelOptions" :key="item.value" :label="item.value" :value="item.value" />
             </el-select>
           </el-form-item>
         </el-col>
@@ -48,15 +32,8 @@
       <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="客户来源" prop="source">
-            <el-select
-              v-model="editForm.source"
-              placeholder="请选择客户来源"
-              style="width: 100%">
-              <el-option
-                v-for="item in sourceOptions"
-                :key="item.value"
-                :label="item.value"
-                :value="item.value" />
+            <el-select v-model="editForm.source" placeholder="请选择客户来源" style="width: 100%">
+              <el-option v-for="item in sourceOptions" :key="item.value" :label="item.value" :value="item.value" />
             </el-select>
           </el-form-item>
         </el-col>
@@ -76,39 +53,21 @@
           <el-form-item label="所在地区" required>
             <el-row :gutter="4" style="width: 100%; padding-top: 32px">
               <el-col :span="8">
-                <el-select
-                  v-model="editForm.province"
-                  placeholder="省"
-                  value-key="id"
-                  @change="provinceChange">
-                  <el-option
-                    v-for="item in provinceOptions"
-                    :key="item.id"
-                    :label="item.distName"
-                    :value="item" />
+                <el-select v-model="editForm.province" placeholder="省" value-key="id" @change="provinceChange">
+                  <el-option v-for="item in provinceOptions" :key="item.id" :label="item.distName" :value="item" />
                 </el-select>
               </el-col>
               <el-col :span="8">
-                <el-select
-                  v-model="editForm.city"
-                  placeholder="市"
-                  value-key="id"
-                  @change="cityChange">
+                <el-select v-model="editForm.city" placeholder="市" value-key="id" @change="cityChange">
                   <el-option
-                    v-for="item in editForm.province
-                      ? editForm.province.children
-                      : []"
+                    v-for="item in editForm.province ? editForm.province.children : []"
                     :key="item.id"
                     :label="item.distName"
                     :value="item" />
                 </el-select>
               </el-col>
               <el-col :span="8">
-                <el-select
-                  v-model="editForm.region"
-                  placeholder="区"
-                  value-key="id"
-                  @change="$forceUpdate()">
+                <el-select v-model="editForm.region" placeholder="区" value-key="id" @change="$forceUpdate()">
                   <el-option
                     v-for="item in editForm.city ? editForm.city.children : []"
                     :key="item.id"
@@ -121,9 +80,7 @@
         </el-col>
         <el-col :span="12">
           <el-form-item label="详细地址" prop="custAddress">
-            <el-input
-              v-model="editForm.custAddress"
-              placeholder="请输入详细地址" />
+            <el-input v-model="editForm.custAddress" placeholder="请输入详细地址" />
           </el-form-item>
         </el-col>
       </el-row>
@@ -139,15 +96,9 @@
       </el-form-item>
     </el-form>
     <span slot="footer">
-      <el-button v-show="!editForm.id" type="primary" @click="customerSave">
-        保存
-      </el-button>
-      <el-button v-show="editForm.id" type="primary" @click="customerEdit">
-        保存
-      </el-button>
-      <el-button v-if="!editForm.id" @click="createContact">
-        保存并新建联系人
-      </el-button>
+      <el-button v-show="!editForm.id" type="primary" @click="customerSave">保存</el-button>
+      <el-button v-show="editForm.id" type="primary" @click="customerEdit">保存</el-button>
+      <el-button v-if="!editForm.id" @click="createContact">保存并新建联系人</el-button>
       <el-button @click="editVisible = false">取消</el-button>
     </span>
   </el-dialog>
@@ -177,18 +128,10 @@
           region: {}, //区
         },
         editRules: {
-          custName: [
-            { required: true, trigger: 'blur', message: '请输入客户名称' },
-          ],
-          custIndustry: [
-            { required: true, trigger: 'change', message: '请选择客户行业' },
-          ],
-          custLevel: [
-            { required: true, trigger: 'change', message: '请选择客户级别' },
-          ],
-          source: [
-            { required: true, trigger: 'change', message: '请选择客户级别' },
-          ],
+          custName: [{ required: true, trigger: 'blur', message: '请输入客户名称' }],
+          custIndustry: [{ required: true, trigger: 'change', message: '请选择客户行业' }],
+          custLevel: [{ required: true, trigger: 'change', message: '请选择客户级别' }],
+          source: [{ required: true, trigger: 'change', message: '请选择客户来源' }],
         },
         provinceOptions: [],
         provinceDetail: [],
@@ -304,21 +247,15 @@
       showLocation() {
         const arr = this.editForm.custLocation.split('/')
         if (!arr.length) return
-        this.editForm.province = this.provinceOptions.find(
-          (item) => item.distName == arr[0]
-        )
+        this.editForm.province = this.provinceOptions.find((item) => item.distName == arr[0])
         if (arr[1]) {
-          this.editForm.city = this.editForm.province.children.find(
-            (item) => item.distName == arr[1]
-          )
+          this.editForm.city = this.editForm.province.children.find((item) => item.distName == arr[1])
         } else {
           this.editForm.city = {}
         }
 
         if (arr[2]) {
-          this.editForm.region = this.editForm.city.children.find(
-            (item) => item.distName == arr[2]
-          )
+          this.editForm.region = this.editForm.city.children.find((item) => item.distName == arr[2])
         } else {
           this.editForm.region = {}
         }

+ 10 - 10
src/views/customer/components/Merge.vue

@@ -2,18 +2,16 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-27 09:33:48
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-28 14:53:47
+ * @LastEditTime: 2023-01-04 18:06:10
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\components\Merge.vue
 -->
 <template>
-  <el-dialog title="合并客户" :visible.sync="visible" @close="handleClose">
+  <el-dialog title="合并客户" :visible.sync="visible" :width="width" @close="handleClose">
     <el-alert :closable="false" show-icon type="warning">
       <div slot="title">
         <h3>特别提示</h3>
-        <p>
-          1、合并后系统只保留目标客户,同时将另一个客户的联系人、商机、订单、附件、销售动态等迁移到目标客户。
-        </p>
+        <p>1、合并后系统只保留目标客户,同时将另一个客户的联系人、商机、订单、附件、销售动态等迁移到目标客户。</p>
         <p>2、红色字段表示两个客户该字段值不同。</p>
       </div>
     </el-alert>
@@ -31,10 +29,7 @@
       </ul>
       <ul v-for="(item, index) in list" :key="index" class="each">
         <li>
-          <el-radio
-            v-model="form.custName"
-            :label="item.custName"
-            @change="targetChange(item)" />
+          <el-radio v-model="form.custName" :label="item.custName" @change="targetChange(item)" />
         </li>
         <li>
           <el-radio v-model="form.abbrName" :label="item.abbrName" />
@@ -101,12 +96,15 @@
           source: false, //客户来源
         },
         list: [],
+        width: '60%',
       }
     },
     mounted() {},
     methods: {
       init(res, ids) {
         this.list = res.data.list
+        if (this.list.length > 4) this.width = '100%'
+        else this.width = '60%'
         this.ids = ids
         this.form = { ...res.data.list[0] }
         this.form.ChooseId = this.ids.filter((item) => item != this.form.id)
@@ -168,7 +166,9 @@
     }
     .each {
       flex: 1;
-      text-align: center;
+      li {
+        padding-left: 10px;
+      }
     }
   }
 </style>

+ 30 - 28
src/views/customer/components/Shift.vue

@@ -2,20 +2,16 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-26 17:21:07
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-26 17:45:03
+ * @LastEditTime: 2023-01-04 18:06:08
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\components\Shift.vue
 -->
 <template>
-  <el-dialog
-    title="转移客户"
-    :visible.sync="visible"
-    width="30%"
-    @close="handleClose">
-    <Transfer ref="transfer" />
+  <el-dialog title="转移客户" :visible.sync="visible" width="30%" @close="handleClose">
+    <select-user ref="selectUser" :query-params="{ roles: ['Sales', 'SalesManager'] }" @save="selectUser" />
     <el-form ref="form" label-width="80px" :model="form" :rules="rules">
-      <el-form-item label="接收对象" prop="allocate">
-        <el-input v-model="form.allocate" readonly>
+      <el-form-item label="接收对象" prop="SalesName">
+        <el-input v-model="form.SalesName" readonly>
           <el-button slot="append" icon="el-icon-search" @click="choose" />
         </el-input>
       </el-form-item>
@@ -25,43 +21,36 @@
         </el-checkbox-group>
       </el-form-item>
       <el-form-item label="备注信息" prop="remark">
-        <el-input
-          v-model="form.remark"
-          maxlength="500"
-          resize="none"
-          :rows="5"
-          show-word-limit
-          type="textarea" />
+        <el-input v-model="form.Remark" maxlength="500" resize="none" :rows="5" show-word-limit type="textarea" />
       </el-form-item>
     </el-form>
     <span slot="footer">
       <el-button size="mini" @click="visible = false">取消</el-button>
-      <el-button size="mini" type="primary">确定</el-button>
+      <el-button size="mini" type="primary" @click="handleSubmit">确定</el-button>
     </span>
   </el-dialog>
 </template>
 <script>
-  import Transfer from './Transfer.vue'
+  import SelectUser from '@/components/select/SelectUser'
+  import to from 'await-to-js'
+  import api from '@/api/customer'
   export default {
     components: {
-      Transfer,
+      SelectUser,
     },
     data() {
       return {
         visible: false,
         form: {
-          allocate: '',
+          SalesName: '',
           about: ['客户'],
-          remark: '',
+          Remark: '',
         },
         rules: {
-          allocate: [
-            { required: true, message: '请选择接收对象', trigger: 'change' },
-          ],
-          about: [
-            { required: true, message: '请选择转移相关', trigger: 'change' },
-          ],
+          SalesName: [{ required: true, message: '请选择接收对象', trigger: 'change' }],
+          about: [{ required: true, message: '请选择转移相关', trigger: 'change' }],
         },
+        userList: [],
       }
     },
     methods: {
@@ -69,7 +58,20 @@
         this.$refs.form.resetFields()
       },
       choose() {
-        this.$refs.transfer.innerVisible = true
+        this.$refs.selectUser.open()
+      },
+      selectUser(userList) {
+        this.userList = userList
+        this.form.SalesName = userList[0].userName
+      },
+      async handleSubmit() {
+        let params = { ...this.form }
+        params.SalesIds = this.userList[0].id
+        const [err, res] = await to(api.updateBytransfer(params))
+        if (err) return
+        this.$message.success(res.msg)
+        this.visible = false
+        this.$emit('refresh')
       },
     },
   }

+ 4 - 19
src/views/customer/components/ToOpen.vue

@@ -7,31 +7,16 @@
  * @FilePath: \opms_frontend\src\views\customer\components\ToOpen.vue
 -->
 <template>
-  <el-dialog
-    title="转移客户"
-    :visible.sync="visible"
-    width="30%"
-    @close="handleClose">
+  <el-dialog title="转移客户" :visible.sync="visible" width="30%" @close="handleClose">
     <el-form ref="form" label-width="100px" :model="form">
       <el-form-item label="移入公海原因" prop="remark">
-        <el-input
-          v-model="form.remark"
-          maxlength="300"
-          resize="none"
-          :rows="5"
-          show-word-limit
-          type="textarea" />
-        <span>
-          *
-          转移到公海后此客户数据将属于公共资源,原归属人员不能再维护跟进和更新此客户数据。
-        </span>
+        <el-input v-model="form.remark" maxlength="300" resize="none" :rows="5" show-word-limit type="textarea" />
+        <span>* 转移到公海后此客户数据将属于公共资源,原归属人员不能再维护跟进和更新此客户数据。</span>
       </el-form-item>
     </el-form>
     <span slot="footer">
       <el-button size="mini" @click="visible = false">取消</el-button>
-      <el-button size="mini" type="primary" @click="handleConfirm">
-        确定
-      </el-button>
+      <el-button size="mini" type="primary" @click="handleConfirm">确定</el-button>
     </span>
   </el-dialog>
 </template>

+ 3 - 16
src/views/customer/components/Transfer.vue

@@ -7,19 +7,11 @@
  * @FilePath: \opms_frontend\src\views\customer\components\Transfer.vue
 -->
 <template>
-  <el-dialog
-    append-to-body
-    title="选择销售工程师"
-    :visible.sync="innerVisible"
-    width="40%">
+  <el-dialog append-to-body title="选择销售工程师" :visible.sync="innerVisible" width="40%">
     <el-row class="transfer">
       <el-col :span="12">
         <header>
-          <el-input
-            v-model="keyword"
-            clearable
-            placeholder="请输入关键字"
-            suffix-icon="el-icon-search" />
+          <el-input v-model="keyword" clearable placeholder="请输入关键字" suffix-icon="el-icon-search" />
         </header>
         <el-dropdown>
           <span class="el-dropdown-link">
@@ -40,12 +32,7 @@
       <el-col :span="12">
         <header>
           <span>已选: {{ selected.length }}个员工</span>
-          <el-button
-            :disabled="selected.length == 0"
-            type="text"
-            @click="clear">
-            清空
-          </el-button>
+          <el-button :disabled="selected.length == 0" type="text" @click="clear">清空</el-button>
         </header>
         <ul class="options">
           <li v-for="(item, index) in selected" :key="index">

+ 139 - 171
src/views/customer/detail.vue

@@ -2,7 +2,7 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-26 09:30:47
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-30 14:38:40
+ * @LastEditTime: 2023-01-04 18:05:59
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\detail.vue
 -->
@@ -22,55 +22,92 @@
               </template>
               <template v-else>
                 <el-button @click="handleReceive">领取客户</el-button>
-                <el-button @click="$refs.allocate.visible = true">
-                  分配客户
-                </el-button>
+                <el-button @click="$refs.allocate.visible = true">分配客户</el-button>
               </template>
             </span>
           </h3>
         </div>
         <header>
           <el-descriptions :colon="false" :column="6" direction="vertical">
-            <el-descriptions-item
-              content-class-name="my-content"
-              label="客户编码"
-              label-class-name="my-label">
+            <el-descriptions-item content-class-name="my-content" label="客户编码" label-class-name="my-label">
               {{ detail.custCode }}
             </el-descriptions-item>
-            <el-descriptions-item
-              content-class-name="my-content"
-              label="助记名"
-              label-class-name="my-label">
+            <el-descriptions-item content-class-name="my-content" label="助记名" label-class-name="my-label">
               {{ detail.abbrName }}
             </el-descriptions-item>
-            <el-descriptions-item
-              content-class-name="my-content"
-              label="客户级别"
-              label-class-name="my-label">
+            <el-descriptions-item content-class-name="my-content" label="客户级别" label-class-name="my-label">
               {{ detail.custLevel }}
             </el-descriptions-item>
-            <el-descriptions-item
-              content-class-name="my-content"
-              label="客户行业"
-              label-class-name="my-label">
+            <el-descriptions-item content-class-name="my-content" label="客户行业" label-class-name="my-label">
               {{ detail.custIndustry }}
             </el-descriptions-item>
-            <el-descriptions-item
-              content-class-name="my-content"
-              label="客户状态"
-              label-class-name="my-label">
+            <el-descriptions-item content-class-name="my-content" label="客户状态" label-class-name="my-label">
               {{ detail.custStatus == 10 ? '正常' : '异常' }}
             </el-descriptions-item>
-            <el-descriptions-item
-              content-class-name="my-content"
-              label="最后跟进时间"
-              label-class-name="my-label">
+            <el-descriptions-item content-class-name="my-content" label="最后跟进时间" label-class-name="my-label">
               {{ detail.followUpDate }}
             </el-descriptions-item>
           </el-descriptions>
         </header>
         <el-tabs v-model="activeName" @tab-click="handleClick">
-          <el-tab-pane label="详细信息" name="first">
+          <el-tab-pane label="跟进记录" name="follow">
+            <ul v-if="followList.length" class="follow">
+              <li v-for="(date, index) in followList" :key="index">
+                <div class="date">
+                  <h2>{{ date.followDay.split('-')[2] }}</h2>
+                  <h3>
+                    {{ date.followDay.split('-').splice(0, 2).join('.') }}
+                  </h3>
+                </div>
+                <ul class="content">
+                  <li v-for="(item, idx) in date.followupList" :key="idx">
+                    <!-- <el-avatar class="user-avatar"
+              :src="avatar" />-->
+                    <div class="text-container">
+                      <vab-icon class="user-avatar" icon="account-circle-fill" />
+                      <div class="text">
+                        <p class="action">
+                          <span>{{ item.contactsName }} 跟进({{ formatType(item.followType) }})</span>
+                          <span>
+                            <vab-icon icon="time-line" />
+                            {{ item.followDate }}
+                          </span>
+                        </p>
+                        <p>{{ item.followContent }}</p>
+                        <div class="footer">
+                          <p>
+                            来自客户:
+                            <span>{{ item.custName }}</span>
+                          </p>
+                          <div>
+                            <el-button size="mini" @click="showDetail(item)">
+                              <vab-icon icon="arrow-right-circle-fill" />
+                              详情
+                            </el-button>
+                            <el-button size="mini" @click="showComment(item)">评论({{ item.commentNumber }})</el-button>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <transition name="height">
+                      <ul v-if="item.showComment" class="comments">
+                        <li v-for="comment in item.comments" :key="comment.id">
+                          <vab-icon class="user-avatar" icon="account-circle-fill" />
+                          <div class="text">
+                            <p>{{ comment.createdName }}</p>
+                            <p>{{ comment.content }}</p>
+                            <p>{{ comment.createdTime }}</p>
+                          </div>
+                        </li>
+                      </ul>
+                    </transition>
+                  </li>
+                </ul>
+              </li>
+            </ul>
+            <div v-else class="no-follow">暂无跟进记录</div>
+          </el-tab-pane>
+          <el-tab-pane label="详细信息" name="detail">
             <el-descriptions border :column="2" size="medium">
               <el-descriptions-item label="客户级别">
                 {{ detail.custLevel }}
@@ -122,18 +159,13 @@
               </el-descriptions-item>
             </el-descriptions>
           </el-tab-pane>
-          <el-tab-pane label="联系人" name="second">
+          <el-tab-pane label="联系人" name="contact">
             <vab-query-form>
               <vab-query-form-left-panel :span="12">
-                <el-input
-                  placeholder="请输入单据名称/编号"
-                  prefix-icon="el-icon-search"
-                  style="width: 50%" />
+                <el-input placeholder="请输入单据名称/编号" prefix-icon="el-icon-search" style="width: 50%" />
               </vab-query-form-left-panel>
               <vab-query-form-right-panel :span="12">
-                <el-button icon="el-icon-plus" @click="addContact">
-                  新建联系人
-                </el-button>
+                <el-button icon="el-icon-plus" @click="addContact">新建联系人</el-button>
               </vab-query-form-right-panel>
             </vab-query-form>
             <el-table
@@ -150,118 +182,33 @@
               <el-table-column align="center" label="邮箱" prop="email" />
               <el-table-column align="center" label="是否决策人">
                 <template slot-scope="scope">
-                  <el-switch
-                    v-model="scope.row.policy"
-                    :active-value="1"
-                    disabled
-                    :inactive-value="0" />
+                  <el-switch v-model="scope.row.policy" :active-value="1" disabled :inactive-value="0" />
                 </template>
               </el-table-column>
               <el-table-column align="center" label="操作">
                 <template slot-scope="scope">
-                  <el-button type="text" @click="contactEdit(scope.row)">
-                    编辑
-                  </el-button>
-                  <el-button type="text" @click="contactDel(scope.row)">
-                    删除
-                  </el-button>
+                  <el-button type="text" @click="contactEdit(scope.row)">编辑</el-button>
+                  <el-button type="text" @click="contactDel(scope.row)">删除</el-button>
                 </template>
               </el-table-column>
             </el-table>
           </el-tab-pane>
-          <el-tab-pane label="跟进记录" name="third">
-            <ul class="follow">
-              <li v-for="(date, index) in followList" :key="index">
-                <div class="date">
-                  <h2>{{ date.followDay.split('-')[2] }}</h2>
-                  <h3>
-                    {{ date.followDay.split('-').splice(0, 2).join('.') }}
-                  </h3>
-                </div>
-                <ul class="content">
-                  <li v-for="(item, idx) in date.followupList" :key="idx">
-                    <!-- <el-avatar class="user-avatar"
-              :src="avatar" />-->
-                    <div class="text-container">
-                      <vab-icon
-                        class="user-avatar"
-                        icon="account-circle-fill" />
-                      <div class="text">
-                        <p class="action">
-                          <span>
-                            {{ item.contactsName }} 跟进({{
-                              formatType(item.followType)
-                            }})
-                          </span>
-                          <span>
-                            <vab-icon icon="time-line" />
-                            {{ item.followDate }}
-                          </span>
-                        </p>
-                        <p>{{ item.followContent }}</p>
-                        <div class="footer">
-                          <p>
-                            来自客户:
-                            <span>{{ item.custName }}</span>
-                          </p>
-                          <div>
-                            <el-button size="mini" @click="showDetail(item)">
-                              <vab-icon icon="arrow-right-circle-fill" />
-                              详情
-                            </el-button>
-                            <el-button size="mini" @click="showComment(item)">
-                              评论({{ item.commentNumber }})
-                            </el-button>
-                          </div>
-                        </div>
-                      </div>
-                    </div>
-                    <transition name="height">
-                      <ul v-if="item.showComment" class="comments">
-                        <li v-for="comment in item.comments" :key="comment.id">
-                          <vab-icon
-                            class="user-avatar"
-                            icon="account-circle-fill" />
-                          <div class="text">
-                            <p>{{ comment.createdName }}</p>
-                            <p>{{ comment.content }}</p>
-                            <p>{{ comment.createdTime }}</p>
-                          </div>
-                        </li>
-                      </ul>
-                    </transition>
-                  </li>
-                </ul>
-              </li>
-            </ul>
-          </el-tab-pane>
-          <el-tab-pane label="项目记录" name="fourth">项目记录</el-tab-pane>
-          <el-tab-pane label="合同记录" name="fifth">合同记录</el-tab-pane>
-          <el-tab-pane label="工单记录" name="sixth">工单记录</el-tab-pane>
-          <el-tab-pane label="归属记录" name="seventh">
-            <el-table
-              v-loading="listLoading"
-              border
-              :data="belongs"
-              height="calc(100% - 42px)">
-              <el-table-column
-                align="center"
-                label="归属销售"
-                prop="saleName" />
-              <el-table-column
-                align="center"
-                label="原来归属"
-                prop="origSaleName" />
+          <el-tab-pane label="项目记录" name="item">项目记录</el-tab-pane>
+          <el-tab-pane label="合同记录" name="contract">合同记录</el-tab-pane>
+          <el-tab-pane label="工单记录" name="worksheet">工单记录</el-tab-pane>
+          <el-tab-pane label="归属记录" name="belong">
+            <el-table v-loading="listLoading" border :data="belongs" height="calc(100% - 42px)">
+              <el-table-column align="center" label="归属销售" prop="saleName" />
+              <el-table-column align="center" label="原来归属" prop="origSaleName" />
               <el-table-column align="center" label="操作方式" prop="opnType">
                 <template slot-scope="scope">
-                  {{ scope.row.opnType == 10 ? '分配' : '转移' }}
+                  <el-tag v-if="scope.row.opnType == 10">分配</el-tag>
+                  <el-tag v-else-if="scope.row.opnType == 20">转移</el-tag>
+                  <el-tag v-else-if="scope.row.opnType == 30">领取</el-tag>
                 </template>
               </el-table-column>
-              <el-table-column align="center" label="操作人" prop="opnPeople" />
-              <el-table-column
-                align="center"
-                label="操作时间"
-                prop="opnDatetime" />
+              <el-table-column align="center" label="操作人" prop="createdName" />
+              <el-table-column align="center" label="操作时间" min-width="160px" prop="opnDatetime" />
               <el-table-column align="center" label="备注" prop="remark" />
             </el-table>
           </el-tab-pane>
@@ -310,9 +257,9 @@
     <!-- 分配客户 -->
     <Allocate ref="allocate" />
     <!-- 转移客户 -->
-    <Shift ref="shift" />
+    <Shift ref="shift" @refresh="back" />
     <!-- 移入公海 -->
-    <ToOpen ref="toOpen" @refresh="back" />
+    <ToOpen ref="toOpen" @refresh="backToOpen" />
     <!-- 跟进详情 -->
     <FollowDetail ref="followDetail" />
   </div>
@@ -362,7 +309,7 @@
           notPaymentTotal: '', //未回款总额
           drawTotal: '', //开票总额
         },
-        activeName: 'first',
+        activeName: 'follow',
         listLoading: false,
         contactList: [],
         selectRows: [],
@@ -382,30 +329,28 @@
       this.privateCus = this.$route.query.privateCus
       this.init()
       this.getDynamics()
+      this.handleClick({ name: 'follow' })
     },
     methods: {
       async init() {
-        Promise.all([
-          api.getDetail({ ids: [parseInt(this.id)] }),
-          api.getAbstract({ id: parseInt(this.id) }),
-        ]).then(([detail, abstract]) => {
-          if (detail.data.list[0]) this.detail = detail.data.list[0]
-          if (abstract.data.list) this.abstract = abstract.data.list
-        })
+        Promise.all([api.getDetail({ ids: [parseInt(this.id)] }), api.getAbstract({ id: parseInt(this.id) })]).then(
+          ([detail, abstract]) => {
+            if (detail.data.list[0]) this.detail = detail.data.list[0]
+            if (abstract.data.list) this.abstract = abstract.data.list
+          }
+        )
       },
       async getDynamics() {
-        const [err, res] = await to(
-          api.dynamicsList({ custId: parseInt(this.id) })
-        )
+        const [err, res] = await to(api.dynamicsList({ custId: parseInt(this.id) }))
         if (err) return
         if (res.data.list[0]) {
           let obj = res.data.list[0]
-          for (const key in obj) {
-            for (const item of obj[key]) {
-              item.opnContent = JSON.parse(item.opnContent)
-            }
+          const keys = Object.keys(obj).reverse()
+          let records = {}
+          for (const item of keys) {
+            records[item] = obj[item]
           }
-          this.records = obj
+          this.records = records
         }
       },
       setSelectRows(val) {
@@ -413,11 +358,11 @@
       },
       async handleClick(tab) {
         let err, res
-        if (tab.name == 'second') {
+        if (tab.name == 'contact') {
           ;[err, res] = await to(api.getContact({ custId: parseInt(this.id) }))
           if (err) return
           this.contactList = res.data.list || []
-        } else if (tab.name == 'third') {
+        } else if (tab.name == 'follow') {
           let params = {
             custId: this.id,
             DaysBeforeToday: 9999,
@@ -425,8 +370,8 @@
           ;[err, res] = await to(follow.getListByDay(params))
           if (err) return
           this.followList = res.data.list || []
-        } else if (tab.name == 'seventh' && this.belongs.length == 0) {
-          ;[err, res] = await to(api.getBelongs({ Id: parseInt(this.id) }))
+        } else if (tab.name == 'belong' && this.belongs.length == 0) {
+          ;[err, res] = await to(api.getBelongs({ custId: parseInt(this.id) }))
           if (err) return
           this.belongs = res.data.list || []
         }
@@ -439,7 +384,7 @@
       },
       // 保存联系人
       contactSave() {
-        this.handleClick({ name: 'second' })
+        this.handleClick({ name: 'contact' })
         this.getDynamics()
       },
       // 编辑客户
@@ -462,9 +407,7 @@
           type: 'warning',
         })
           .then(async () => {
-            const [err, res] = await to(
-              api.deleteContact({ Id: row.id, custId: parseInt(this.id) })
-            )
+            const [err, res] = await to(api.deleteContact({ Id: row.id, custId: parseInt(this.id) }))
             if (err) return
             if (res.code == 200) {
               this.$message({
@@ -478,6 +421,7 @@
       },
       // 转移客户
       handleShift() {
+        this.$refs.shift.form.Ids = [parseInt(this.id)]
         this.$refs.shift.visible = true
       },
       // 移入公海
@@ -493,9 +437,7 @@
           type: 'warning',
         })
           .then(async () => {
-            const [err, res] = await to(
-              api.deleteCustomer({ Id: parseInt(this.id) })
-            )
+            const [err, res] = await to(api.deleteCustomer({ Id: parseInt(this.id) }))
             if (err) return
             if (res.code == 200) {
               this.$message({
@@ -507,9 +449,12 @@
           })
           .catch(() => {})
       },
-      back() {
+      backToOpen() {
         this.$router.push('/customer/openSea')
       },
+      back() {
+        this.$router.go(-1)
+      },
       // 领取
       handleReceive() {
         this.$confirm('确认领取客户?', '提示', {
@@ -518,13 +463,21 @@
           type: 'warning',
         })
           .then(async () => {
-            const [err, res] = await to(api.receiveCustomer({ ids: this.id }))
+            const [err, res] = await to(
+              api.receiveCustomer({
+                ids: [parseInt(this.id)],
+                salesId: this.$store.state.user.id,
+                salesName: this.$store.state.user.username,
+                receive: '1',
+              })
+            )
             if (err) return
             if (res.code == 200) {
               this.$message({
                 type: 'success',
                 message: '领取成功!',
               })
+              this.$router.push('/customer/list')
             }
           })
           .catch(() => {})
@@ -599,7 +552,7 @@
       ::v-deep .my-label {
         font-size: 14px;
         font-weight: 600;
-        color: #fff;
+        color: #1d66dc;
       }
       ::v-deep .my-content {
         font-size: 14px;
@@ -721,7 +674,7 @@
           .comments {
             padding-left: 60px;
             margin-top: 10px;
-            max-height: 200px;
+            max-height: 190px;
             overflow: auto;
             li {
               display: flex;
@@ -781,6 +734,15 @@
         }
       }
     }
+    .no-follow {
+      height: 100%;
+      width: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 12px;
+      color: rgba(0, 0, 0, 0.65);
+    }
   }
   .height-enter-active,
   .height-leave-active {
@@ -788,9 +750,15 @@
   }
   .height-enter-to,
   .height-leave {
-    height: 200px;
+    height: 190px;
   }
   .height-enter, .height-leave-to /* .fade-leave-active below version 2.1.8 */ {
     height: 0;
   }
+  ::v-deep .el-descriptions__table tbody {
+    td,
+    th {
+      width: 25%;
+    }
+  }
 </style>

+ 16 - 24
src/views/customer/follow.vue

@@ -2,7 +2,7 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-15 15:38:21
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-30 14:36:03
+ * @LastEditTime: 2023-01-04 15:10:43
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\follow.vue
 -->
@@ -22,7 +22,7 @@
           type="daterange" />
       </el-col> -->
       <el-col :span="4">
-        <el-input v-model="queryForm.daysBeforeToday" placeholder="查询天数">
+        <el-input v-model.number="queryForm.daysBeforeToday" placeholder="查询天数">
           <template slot="append">天</template>
         </el-input>
       </el-col>
@@ -36,10 +36,8 @@
         <el-input v-model="queryForm.managerId" placeholder="创建者" />
       </el-col>
       <el-col :span="4">
-        <el-button icon="el-icon-plus" type="primary" @click="search">
-          查询
-        </el-button>
-        <el-button @click="addFollowUp">添加</el-button>
+        <el-button icon="el-icon-plus" type="primary" @click="search">查询</el-button>
+        <!-- <el-button @click="addFollowUp">添加</el-button> -->
         <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
       </el-col>
     </el-row>
@@ -55,17 +53,13 @@
             <h3>{{ date.followDay.split('-').splice(0, 2).join('.') }}</h3>
           </div>
           <ul class="content">
-            <li v-for="(item, idx) in date.followupList" :key="idx">
+            <li v-for="(item, idx) in date.followupList" :key="idx" @click="showComment(item.id)">
               <!-- <el-avatar class="user-avatar"
               :src="avatar" />-->
               <vab-icon class="user-avatar" icon="account-circle-fill" />
               <div class="text">
                 <p class="action">
-                  <span>
-                    {{ item.contactsName }} 跟进({{
-                      formatType(item.followType)
-                    }})
-                  </span>
+                  <span>{{ item.contactsName }} 跟进({{ formatType(item.followType) }})</span>
                   <span>
                     <vab-icon icon="time-line" />
                     {{ item.followDate }}
@@ -105,16 +99,8 @@
           </li>
         </ul>
         <div class="form">
-          <el-input
-            v-model="comment"
-            maxlength="300"
-            resize="none"
-            :rows="5"
-            show-word-limit
-            type="textarea" />
-          <el-button size="mini" type="primary" @click="handleComment">
-            评论
-          </el-button>
+          <el-input v-model="comment" maxlength="300" resize="none" :rows="5" show-word-limit type="textarea" />
+          <el-button size="mini" type="primary" @click="handleComment">评论</el-button>
         </div>
       </div>
     </div>
@@ -181,7 +167,7 @@
     methods: {
       getOptions() {},
       search() {
-        this.queryForm.daysBeforeToday = 20
+        // this.queryForm.daysBeforeToday = 20
         this.fetchData()
       },
       async fetchData() {
@@ -191,10 +177,15 @@
         this.records = res.data.list || []
         await this.$nextTick()
         this.loadFlag = false
+        if (this.records.length) {
+          if (!this.followId) this.showComment(this.records[0].followupList[0].id)
+        } else {
+          this.comments = []
+          this.followId = ''
+        }
       },
       load() {
         this.queryForm.daysBeforeToday += 20
-        console.log('到底了', this.queryForm.daysBeforeToday)
         this.fetchData()
       },
       reset() {
@@ -346,6 +337,7 @@
         list-style: none;
         li {
           display: flex;
+          cursor: pointer;
           border: 1px solid rgb(215, 232, 244);
           background: rgb(247, 251, 254);
           border-radius: 4px;

+ 132 - 61
src/views/customer/list.vue

@@ -2,7 +2,7 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-26 16:34:37
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-30 11:21:20
+ * @LastEditTime: 2023-01-04 18:05:48
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\list.vue
 -->
@@ -21,49 +21,38 @@
         <el-input v-model="queryForm.custName" placeholder="客户名称" />
       </el-col>
       <el-col :span="4">
-        <el-input v-model="queryForm.indusTry" placeholder="客户行业" />
+        <el-select v-model="queryForm.custIndustry" placeholder="客户行业" style="width: 100%">
+          <el-option v-for="item in industryOptions" :key="item.value" :label="item.value" :value="item.value" />
+        </el-select>
       </el-col>
-      <el-col :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="fetchData">
-          查询
-        </el-button>
+      <el-col :span="4">
+        <el-select v-model="queryForm.custLevel" placeholder="客户级别" style="width: 100%">
+          <el-option v-for="item in levelOptions" :key="item.value" :label="item.value" :value="item.value" />
+        </el-select>
+      </el-col>
+      <el-col :span="4">
+        <el-date-picker
+          v-model="queryForm.followUpDate"
+          placeholder="最后跟进时间"
+          style="width: 100%"
+          type="date"
+          value-format="yyyy-MM-dd" />
+      </el-col>
+      <el-col :span="4">
+        <el-button icon="el-icon-plus" type="primary" @click="fetchData">查询</el-button>
         <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
       </el-col>
     </el-row>
     <vab-query-form>
       <vab-query-form-left-panel :span="12">
-        <el-button
-          icon="el-icon-plus"
-          size="mini"
-          type="primary"
-          @click="$refs.edit.init()">
-          新建
-        </el-button>
-        <el-button
-          icon="el-icon-plus"
-          size="mini"
-          type="primary"
-          @click="handleShift">
-          转移客户
-        </el-button>
-        <el-button
-          icon="el-icon-plus"
-          size="mini"
-          type="primary"
-          @click="handleToOpen">
-          移入公海
-        </el-button>
-        <el-button
-          icon="el-icon-plus"
-          size="mini"
-          type="primary"
-          @click="handleMerge">
-          合并客户
-        </el-button>
+        <el-button icon="el-icon-plus" size="mini" type="primary" @click="$refs.edit.init()">新建</el-button>
+        <el-button icon="el-icon-plus" size="mini" type="primary" @click="handleShift">转移客户</el-button>
+        <el-button icon="el-icon-plus" size="mini" type="primary" @click="handleToOpen">移入公海</el-button>
+        <el-button icon="el-icon-plus" size="mini" type="primary" @click="handleMerge">合并客户</el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <el-button icon="el-icon-download" />
-        <el-button icon="el-icon-setting" />
+        <table-tool :check-list.sync="checkList" :columns="columns" />
       </vab-query-form-right-panel>
     </vab-query-form>
     <el-table
@@ -73,32 +62,29 @@
       height="calc(100vh - 394px)"
       @selection-change="setSelectRows">
       <el-table-column align="center" show-overflow-tooltip type="selection" />
-      <el-table-column align="center" label="客户编码" prop="custCode" />
-      <el-table-column align="center" label="客户名称" prop="custName" />
-      <el-table-column align="center" label="助记名" prop="abbrName" />
-      <el-table-column align="center" label="所在地区" prop="custLocation" />
-      <el-table-column align="center" label="客户行业" prop="custIndustry" />
-      <el-table-column align="center" label="客户级别" prop="custLevel" />
-      <el-table-column align="center" label="客户状态" prop="custStatus">
-        <template slot-scope="scope">
-          {{ scope.row.custStatus == 10 ? '正常' : '异常' }}
-        </template>
-      </el-table-column>
       <el-table-column
+        v-for="(item, index) in finallyColumns"
+        :key="index"
         align="center"
-        label="最后跟进时间"
-        prop="followUpDate" />
-      <el-table-column align="center" label="创建人" prop="createdName" />
-      <el-table-column align="center" label="创建时间" prop="createdTime" />
+        :label="item.label"
+        :min-width="item.width"
+        :prop="item.prop"
+        show-overflow-tooltip
+        :sortable="item.sortable">
+        <template #default="{ row }">
+          <el-button v-if="item.prop === 'custName'" style="font-size: 14px" type="text" @click="handleDetail(row)">
+            {{ row.custName }}
+          </el-button>
+          <span v-else-if="item.prop === 'custStatus'">
+            {{ row.custStatus == 10 ? '正常' : '异常' }}
+          </span>
+          <span v-else>{{ row[item.prop] }}</span>
+        </template>
+      </el-table-column>
       <el-table-column align="center" label="操作">
         <template slot-scope="scope">
           <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
-          <el-button type="text" @click="handleDetail(scope.row)">
-            详情
-          </el-button>
-          <el-button type="text" @click="handleDelete(scope.row)">
-            删除
-          </el-button>
+          <el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -115,7 +101,7 @@
     <!-- 新建联系人弹窗 -->
     <Contact ref="contact" />
     <!-- 转移客户 -->
-    <Shift ref="shift" />
+    <Shift ref="shift" @refresh="fetchData" />
     <!-- 移入公海 -->
     <ToOpen ref="toOpen" @refresh="fetchData" />
     <!-- 合并客户 -->
@@ -131,6 +117,7 @@
   import Shift from './components/Shift'
   import ToOpen from './components/ToOpen'
   import Merge from './components/Merge'
+  import TableTool from '@/components/table/TableTool'
   export default {
     components: {
       Edit,
@@ -138,6 +125,7 @@
       Shift,
       ToOpen,
       Merge,
+      TableTool,
     },
     data() {
       return {
@@ -154,12 +142,95 @@
         listLoading: false,
         list: [],
         selectRows: [],
+        industryOptions: [], //客户行业
+        levelOptions: [], //客户级别
+        // 自定义列表
+        checkList: [],
+        columns: [
+          {
+            label: '客户编码',
+            width: '120px',
+            prop: 'custCode',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户名称',
+            width: '120px',
+            prop: 'custName',
+            sortable: false,
+            disableCheck: true,
+          },
+          {
+            label: '助记名',
+            width: 'auto',
+            prop: 'abbrName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '所在地区',
+            width: 'auto',
+            prop: 'custLocation',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户行业',
+            width: 'auto',
+            prop: 'custIndustry',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户级别',
+            width: 'auto',
+            prop: 'custLevel',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户状态',
+            width: 'auto',
+            prop: 'custStatus',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '最后跟进时间',
+            width: '140px',
+            prop: 'followUpDate',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '创建时间',
+            width: '140px',
+            prop: 'createdTime',
+            sortable: false,
+            disableCheck: false,
+          },
+        ],
       }
     },
+    computed: {
+      finallyColumns() {
+        return this.columns.filter((item) => this.checkList.includes(item.label))
+      },
+    },
     mounted() {
+      this.getOptions()
       this.fetchData()
     },
     methods: {
+      getOptions() {
+        Promise.all([this.getDicts('CustomerLevel'), this.getDicts('CustomerIndustry')])
+          .then(([level, industry]) => {
+            this.levelOptions = level.data.values || []
+            this.industryOptions = industry.data.values || []
+          })
+          .catch((err) => console.log(err))
+      },
       handleClick(tab) {
         console.log(tab, 'tab')
         this.fetchData()
@@ -235,18 +306,18 @@
       },
       // 转移客户
       handleShift() {
+        if (!this.selectRows.length) return this.$message.warning('请选择需要转移的客户')
+        this.$refs.shift.form.Ids = this.selectRows.map((item) => item.id)
         this.$refs.shift.visible = true
       },
       // 移入公海
       handleToOpen() {
-        if (!this.selectRows.length)
-          return this.$message.warning('请选择要移入公海的客户')
+        if (!this.selectRows.length) return this.$message.warning('请选择要移入公海的客户')
         this.$refs.toOpen.form.ids = this.selectRows.map((item) => item.id)
         this.$refs.toOpen.visible = true
       },
       async handleMerge() {
-        if (this.selectRows.length < 2)
-          return this.$message.warning('请选择两个以上客户进行合并')
+        if (this.selectRows.length < 2) return this.$message.warning('请选择两个以上客户进行合并')
         const ids = this.selectRows.map((item) => item.id)
         const [err, res] = await to(api.getDetail({ ids }))
         if (err) return

+ 166 - 17
src/views/customer/openSea.vue

@@ -2,7 +2,7 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-15 15:38:21
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-28 16:10:14
+ * @LastEditTime: 2023-01-04 18:05:32
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\openSea.vue
 -->
@@ -16,12 +16,24 @@
         <el-input v-model="queryForm.custName" placeholder="客户名称" />
       </el-col>
       <el-col :span="4">
-        <el-input v-model="queryForm.custIndustry" placeholder="客户行业" />
+        <el-select v-model="queryForm.custIndustry" placeholder="客户行业" style="width: 100%">
+          <el-option v-for="item in industryOptions" :key="item.value" :label="item.value" :value="item.value" />
+        </el-select>
       </el-col>
       <el-col :span="4">
-        <el-input v-model="queryForm.custLevel" placeholder="客户级别" />
+        <el-select v-model="queryForm.custLevel" placeholder="客户级别" style="width: 100%">
+          <el-option v-for="item in levelOptions" :key="item.value" :label="item.value" :value="item.value" />
+        </el-select>
       </el-col>
-      <el-col :span="8">
+      <el-col :span="4">
+        <el-date-picker
+          v-model="queryForm.followUpDate"
+          placeholder="最后跟进时间"
+          style="width: 100%"
+          type="date"
+          value-format="yyyy-MM-dd" />
+      </el-col>
+      <el-col :span="4">
         <el-button icon="el-icon-plus" type="primary" @click="fetchData">查询</el-button>
         <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
       </el-col>
@@ -29,12 +41,12 @@
     <vab-query-form>
       <vab-query-form-left-panel :span="12">
         <el-button icon="el-icon-plus" type="primary" @click="$refs.edit.init()">新建</el-button>
-        <el-button icon="el-icon-plus" type="primary" @click="$refs.allocate.visible = true">分配</el-button>
+        <el-button icon="el-icon-plus" type="primary" @click="handleAllocate">分配</el-button>
         <el-button icon="el-icon-plus" type="primary" @click="handleReceive">领取</el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <el-button icon="el-icon-download" />
-        <el-button icon="el-icon-setting" />
+        <table-tool :check-list.sync="checkList" :columns="columns" />
       </vab-query-form-right-panel>
     </vab-query-form>
     <el-table
@@ -44,8 +56,44 @@
       height="calc(100vh - 340px)"
       @selection-change="setSelectRows">
       <el-table-column align="center" show-overflow-tooltip type="selection" />
-      <el-table-column align="center" label="客户编码" prop="custCode" />
-      <el-table-column align="center" label="客户名称" prop="custName" />
+      <el-table-column
+        v-for="(item, index) in finallyColumns"
+        :key="index"
+        align="center"
+        :label="item.label"
+        :min-width="item.width"
+        :prop="item.prop"
+        show-overflow-tooltip
+        :sortable="item.sortable">
+        <template #default="{ row }">
+          <el-button v-if="item.prop === 'custName'" style="font-size: 14px" type="text" @click="handleDetail(row)">
+            {{ row.custName }}
+          </el-button>
+          <span v-else-if="item.prop === 'custStatus'">
+            {{ row.custStatus == 10 ? '正常' : '异常' }}
+          </span>
+          <span v-else>{{ row[item.prop] }}</span>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column
+        align="center"
+        label="客户编码"
+        min-width="120px"
+        prop="custCode" />
+        <el-table-column
+        align="center"
+        label="客户名称"
+        min-width="120px"
+        prop="custName">
+        <template slot-scope="scope">
+          <el-button
+            style="font-size: 14px"
+            type="text"
+            @click="handleDetail(scope.row)">
+            {{ scope.row.custName }}
+          </el-button>
+        </template>
+      </el-table-column>
       <el-table-column align="center" label="助记名" prop="abbrName" />
       <el-table-column align="center" label="所在地区" prop="custLocation" />
       <el-table-column align="center" label="客户行业" prop="custIndustry" />
@@ -55,13 +103,20 @@
           {{ scope.row.custStatus == 10 ? '正常' : '异常' }}
         </template>
       </el-table-column>
-      <el-table-column align="center" label="最后跟进时间" prop="followUpDate" />
+      <el-table-column
+        align="center"
+        label="最后跟进时间"
+        min-width="140px"
+        prop="followUpDate" />
       <el-table-column align="center" label="创建人" prop="createdName" />
-      <el-table-column align="center" label="创建时间" prop="createdTime" />
+      <el-table-column
+        align="center"
+        label="创建时间"
+        min-width="140px"
+        prop="createdTime" /> -->
       <el-table-column align="center" label="操作">
         <template slot-scope="scope">
           <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
-          <el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
           <el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
@@ -79,7 +134,7 @@
     <!-- 新建联系人弹窗 -->
     <Contact ref="contact" />
     <!-- 分配客户 -->
-    <Allocate ref="allocate" />
+    <Allocate ref="allocate" @refresh="fetchData" />
   </div>
 </template>
 
@@ -89,13 +144,14 @@
   import Contact from './components/Contact'
   import Edit from './components/Edit'
   import Allocate from './components/Allocate'
-
+  import TableTool from '@/components/table/TableTool'
   export default {
     name: 'OpenSea',
     components: {
       Contact,
       Edit,
       Allocate,
+      TableTool,
     },
     data() {
       return {
@@ -110,25 +166,103 @@
           custName: '', //客户名称
           custIndustry: '', // 客户行业  ()
           custLevel: '', //客户级别
+          followUpDate: '', //最后跟进时间
         },
         selectRows: [],
+        industryOptions: [], //客户行业
+        levelOptions: [], //客户级别
+        // 自定义列表
+        checkList: [],
+        columns: [
+          {
+            label: '客户编码',
+            width: '120px',
+            prop: 'custCode',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户名称',
+            width: '120px',
+            prop: 'custName',
+            sortable: false,
+            disableCheck: true,
+          },
+          {
+            label: '助记名',
+            width: 'auto',
+            prop: 'abbrName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '所在地区',
+            width: 'auto',
+            prop: 'custLocation',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户行业',
+            width: 'auto',
+            prop: 'custIndustry',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户级别',
+            width: 'auto',
+            prop: 'custLevel',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户状态',
+            width: 'auto',
+            prop: 'custStatus',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '最后跟进时间',
+            width: '140px',
+            prop: 'followUpDate',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '创建时间',
+            width: '140px',
+            prop: 'createdTime',
+            sortable: false,
+            disableCheck: false,
+          },
+        ],
       }
     },
+    computed: {
+      finallyColumns() {
+        return this.columns.filter((item) => this.checkList.includes(item.label))
+      },
+    },
     mounted() {
       this.fetchData()
       this.getOptions()
     },
     methods: {
       getOptions() {
-        Promise.all([api.getProvinceInfo()])
-          .then(([province]) => {
+        Promise.all([api.getProvinceInfo(), this.getDicts('CustomerLevel'), this.getDicts('CustomerIndustry')])
+          .then(([province, level, industry]) => {
             this.provinceOptions = province.data.list || []
+            this.levelOptions = level.data.values || []
+            this.industryOptions = industry.data.values || []
           })
           .catch((err) => console.log(err))
       },
       async fetchData() {
         this.listLoading = true
         const params = { ...this.queryForm }
+        if (!params.followUpDate) params.followUpDate = null
         const [err, res] = await to(api.getPublicList(params))
         if (err) return (this.listLoading = false)
         this.list = res.data.list || []
@@ -202,6 +336,13 @@
       handleClose(form) {
         this.$refs[form].resetFields()
       },
+      // 分配
+      handleAllocate() {
+        if (!this.selectRows.length) return this.$message.warning('请选择客户')
+        const arr = this.selectRows.map((item) => item.id)
+        this.$refs.allocate.ids = arr
+        this.$refs.allocate.visible = true
+      },
       // 领取
       handleReceive() {
         if (!this.selectRows.length) return this.$message.warning('请选择客户')
@@ -212,16 +353,24 @@
           type: 'warning',
         })
           .then(async () => {
-            const [err, res] = await to(api.receiveCustomer({ ids: arr.join() }))
+            const [err, res] = await to(
+              api.receiveCustomer({
+                ids: arr,
+                salesId: this.$store.state.user.id,
+                salesName: this.$store.state.user.username,
+                receive: '1',
+              })
+            )
             if (err) return
             if (res.code == 200) {
               this.$message({
                 type: 'success',
                 message: '领取成功!',
               })
+              this.fetchData()
             }
           })
-          .catch(() => {})
+          .catch((err) => console.log(err))
       },
     },
   }