Browse Source

Merge branch 'develop' of http://code.dashoo.cn/chengjian/opms_frontend into develop

Cheng Jian 3 years ago
parent
commit
479b9fc3a6

+ 1 - 1
.env.development

@@ -8,4 +8,4 @@ VUE_APP_MicroSrvProxy_API=http://127.0.0.1:9981/
 VUE_APP_AdminPath=dashoo.opms.admin-0.0.1
 
 # 业务接口微服务名称
-VUE_APP_ParentPath=dashoo.opms.parent-0.0.1
+VUE_APP_ParentPath=dashoo.opms.parent-0.0.1

+ 5 - 2
.env.production

@@ -1,8 +1,11 @@
 # 租户码
 VUE_APP_TENANT=default
+
+# GateWay地址
+VUE_APP_MicroSrvProxy_API=http://127.0.0.1:9981/
+
 # 登录验证微服务名称
 VUE_APP_AdminPath=dashoo.opms.admin-0.0.1
-VUE_APP_MicroSrvProxy_API=http://127.0.0.1:9981/
 
 # 业务接口微服务名称
-VUE_APP_ParentPath=dashoo.opms.parent-0.0.1
+VUE_APP_ParentPath=dashoo.opms.parent-0.0.1

+ 1 - 1
prettier.config.js

@@ -1,5 +1,5 @@
 module.exports = {
-  printWidth: 80,
+  printWidth: 120,
   tabWidth: 2,
   useTabs: false,
   semi: false,

+ 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) {

+ 1 - 6
src/api/system/user.js

@@ -4,12 +4,7 @@ const basePath = process.env.VUE_APP_AdminPath
 console.log(basePath)
 export default {
   login(query) {
-    return micro_request.postRequestWithClientInfo(
-      basePath,
-      'Auth',
-      'Login',
-      query
-    )
+    return micro_request.postRequestWithClientInfo(basePath, 'Auth', 'Login', query)
   },
   logout(query) {
     return micro_request.postRequest(basePath, 'Auth', 'LogOut', query)

+ 214 - 0
src/components/select/SelectUser.vue

@@ -0,0 +1,214 @@
+<template>
+  <el-dialog append-to-body :title="title" :visible.sync="innerVisible" width="40%">
+    <el-row class="transfer">
+      <el-col :span="12">
+        <header>
+          <el-input
+            v-model="queryForm.keyWords"
+            clearable
+            placeholder="请输入关键字"
+            suffix-icon="el-icon-search"
+            @change="search" />
+        </header>
+        <el-dropdown>
+          <span class="el-dropdown-link">
+            按字母顺序查看
+            <i class="el-icon-arrow-down el-icon--right"></i>
+          </span>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item>按创建顺序查看</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+        <ul v-infinite-scroll="fetchData" class="options" :infinite-scroll-disabled="disabled">
+          <li v-for="(item, index) in options" :key="index" @click="transfer(index)">
+            <span>{{ item.userName }}</span>
+            <i class="el-icon-arrow-right"></i>
+          </li>
+        </ul>
+      </el-col>
+      <el-col :span="12">
+        <header>
+          <span>已选: {{ selected.length }}个员工</span>
+          <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" @click="goBack(index)">
+            <span>{{ item.userName }}</span>
+          </li>
+        </ul>
+      </el-col>
+    </el-row>
+    <span slot="footer">
+      <el-button size="mini" type="primary" @click="save">保存</el-button>
+      <el-button size="mini" @click="innerVisible = false">取消</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+  import userApi from '@/api/system/user'
+
+  export default {
+    name: 'SelectUser',
+    props: {
+      title: {
+        type: String,
+        default: '选择',
+      },
+      multiple: Boolean,
+      queryParams: {
+        type: Object,
+        default() {
+          return {}
+        },
+      },
+    },
+    data() {
+      return {
+        innerVisible: false,
+        queryForm: {
+          keyWords: '',
+          pageNum: 1,
+          pageSize: 50,
+        },
+        disabled: false,
+        total: 0,
+        list: [],
+        options: [],
+        selected: [],
+      }
+    },
+    mounted() {
+      // this.fetchData()
+    },
+    methods: {
+      open() {
+        this.innerVisible = true
+      },
+      save() {
+        this.innerVisible = false
+        this.$emit('save', this.selected)
+      },
+      search() {
+        this.queryForm.pageNum = 1
+        this.fetchData('new')
+      },
+      async fetchData(type) {
+        let query = Object.assign(this.queryForm, this.queryParams)
+        const {
+          data: { list, total },
+        } = await userApi.getList(query)
+        this.total = total
+        if (list && list.length > 0) {
+          for (let index in list) {
+            list[index].sort = (this.queryForm.pageNum - 1) * this.queryForm.pageSize + index
+          }
+          if (type === 'new') {
+            this.list = list
+            this.options = list
+          } else {
+            this.list = this.list.concat(list)
+            this.options = this.options.concat(list)
+          }
+          this.queryForm.pageNum++
+        }
+        // 禁用加载请求
+        this.disabled = false
+        if (this.list.length >= this.total) {
+          this.disabled = true
+        }
+      },
+
+      transfer(index) {
+        if (!this.multiple && this.selected.length === 1) {
+          this.$message({
+            type: 'warning',
+            message: '只能选择一个员工,请勿多选!',
+          })
+          return
+        }
+        const arr = this.options.splice(index, 1)
+        if (arr[0]) this.selected.push(arr[0])
+        this.selected.sort(function (a, b) {
+          return a.sort - b.sort
+        })
+      },
+      goBack(index) {
+        const arr = this.selected.splice(index, 1)
+        if (arr[0]) this.options.push(arr[0])
+        this.options.sort(function (a, b) {
+          return a.sort - b.sort
+        })
+      },
+      clear() {
+        this.selected = []
+        this.options = this.list
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .transfer {
+    height: 500px;
+    border: 1px solid #ebeef5;
+
+    .el-col {
+      height: 100%;
+
+      &:first-child {
+        border-right: 1px solid #ebeef5;
+      }
+
+      .el-dropdown {
+        height: 50px;
+        line-height: 50px;
+        margin: 0 8px;
+        width: calc(100% - 16px);
+        border-bottom: 1px solid #ebeef5;
+
+        span {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+        }
+      }
+
+      .options {
+        margin: 0;
+        padding: 0 10px;
+        list-style: none;
+        height: 400px;
+        overflow-y: auto;
+
+        li {
+          height: 50px;
+          line-height: 50px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          border-bottom: 1px solid #ebeef5;
+
+          & i {
+            transition: all 0.3s;
+            cursor: pointer;
+
+            &:hover {
+              color: #1d66dc;
+              font-weight: bold;
+            }
+          }
+        }
+      }
+    }
+
+    header {
+      height: 50px;
+      padding: 9px 8px;
+      border-bottom: 1px solid #ebeef5;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+  }
+</style>

+ 11 - 1
src/main.js

@@ -1,3 +1,11 @@
+/*
+ * @Author: wanglj 471442253@qq.com
+ * @Date: 2023-01-04 16:23:23
+ * @LastEditors: wanglj
+ * @LastEditTime: 2023-01-05 10:36:59
+ * @Description: file content
+ * @FilePath: \opms_frontend\src\main.js
+ */
 import Vue from 'vue'
 import App from './App'
 import i18n from './i18n'
@@ -5,12 +13,14 @@ import store from './store'
 import router from './router'
 import '@/vab'
 
-import { parseTime, translateDataToTree } from '@/utils'
+import { parseTime, translateDataToTree, resetForm, formatPrice } from '@/utils'
 import dictApi from '@/api/system/dict'
 
 Vue.prototype.parseTime = parseTime
 Vue.prototype.translateDataToTree = translateDataToTree
 Vue.prototype.getDicts = dictApi.getDictDataByType
+Vue.prototype.resetForm = resetForm
+Vue.prototype.formatPrice = formatPrice
 
 Vue.config.productionTip = false
 new Vue({

+ 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 })
     }
   },
   /**

+ 23 - 27
src/utils/index.js

@@ -75,17 +75,7 @@ export function formatTime(time, option) {
   if (option) {
     return parseTime(time, option)
   } else {
-    return (
-      d.getMonth() +
-      1 +
-      '月' +
-      d.getDate() +
-      '日' +
-      d.getHours() +
-      '时' +
-      d.getMinutes() +
-      '分'
-    )
+    return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
   }
 }
 
@@ -101,11 +91,7 @@ export function paramObj(url) {
   }
   return JSON.parse(
     '{"' +
-      decodeURIComponent(search)
-        .replace(/"/g, '\\"')
-        .replace(/&/g, '","')
-        .replace(/=/g, '":"')
-        .replace(/\+/g, ' ') +
+      decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"').replace(/\+/g, ' ') +
       '"}'
   )
 }
@@ -117,16 +103,10 @@ export function paramObj(url) {
  */
 export function translateDataToTree(data) {
   const parent = data.filter(
-    (value) =>
-      value.parentId === 'undefined' ||
-      value.parentId === null ||
-      value.parentId === 0
+    (value) => value.parentId === 'undefined' || value.parentId === null || value.parentId === 0
   )
   const children = data.filter(
-    (value) =>
-      value.parentId !== 'undefined' &&
-      value.parentId !== null &&
-      value.parentId !== 0
+    (value) => value.parentId !== 'undefined' && value.parentId !== null && value.parentId !== 0
   )
   const translator = (parent, children) => {
     parent.forEach((parent) => {
@@ -135,9 +115,7 @@ export function translateDataToTree(data) {
           const temp = JSON.parse(JSON.stringify(children))
           temp.splice(index, 1)
           translator([current], temp)
-          typeof parent.children !== 'undefined'
-            ? parent.children.push(current)
-            : (parent.children = [current])
+          typeof parent.children !== 'undefined' ? parent.children.push(current) : (parent.children = [current])
         }
       })
     })
@@ -279,3 +257,21 @@ export function shuffle(array) {
   }
   return array
 }
+
+// 表单重置
+export function resetForm(refName) {
+  if (this.$refs[refName]) {
+    this.$refs[refName].resetFields()
+  }
+}
+
+/**
+ * @description 金额格式化
+ * @param price {Number} 金额
+ * @param currency {String} 币种 CNY 人民币;USD 美元;EUR 欧元
+ * @returns {String} 格式化后的字符串
+ */
+export function formatPrice(price, currency = 'CNY') {
+  if (!price) price = 0
+  return price.toLocaleString('zh-CN', { style: 'currency', currency })
+}

+ 12 - 31
src/utils/micro_request.js

@@ -77,10 +77,7 @@ service.postRequest = function postRequest(basePath, srvName, funcName, data) {
   var base_Path = ''
   if (basePath == process.env.VUE_APP_FOSHAN_PATH) {
     base_Path = process.env.VUE_APP_MicroSrvProxy_foshan_API + basePath
-  } else if (
-    basePath == process.env.VUE_APP_AdminPath ||
-    process.env.VUE_APP_ParentPath
-  ) {
+  } else if (basePath == process.env.VUE_APP_AdminPath || process.env.VUE_APP_ParentPath) {
     base_Path = process.env.VUE_APP_MicroSrvProxy_API + basePath
   } else {
     base_Path = process.env.VUE_APP_MicroSrvProxy_API + basePath
@@ -99,12 +96,7 @@ service.postRequest = function postRequest(basePath, srvName, funcName, data) {
   })
 }
 // 发出请求并要求把客户端信息传输给后端(IP和User-Agent)
-service.postRequestWithClientInfo = function postRequest(
-  basePath,
-  srvName,
-  funcName,
-  data
-) {
+service.postRequestWithClientInfo = function postRequest(basePath, srvName, funcName, data) {
   if (data == undefined) {
     let nullParam = { nullparam: 0 }
     data = nullParam
@@ -124,12 +116,7 @@ service.postRequestWithClientInfo = function postRequest(
 }
 
 // Excel文件下载(服务端生成文件流)
-service.downloadExcel = function downloadExcel(
-  basePath,
-  srvName,
-  funcName,
-  data
-) {
+service.downloadExcel = function downloadExcel(basePath, srvName, funcName, data) {
   if (data == undefined) {
     let nullParam = {
       nullparam: 0,
@@ -137,9 +124,9 @@ service.downloadExcel = function downloadExcel(
     data = nullParam
   }
   var base_Path = ''
-  if (basePath == process.env.VUE_APP_FOSHAN_PATH) {
-    base_Path = process.env.VUE_APP_MicroSrvProxy_foshan_API + basePath
-  } else if (basePath == process.env.VUE_APP_AdminPath) {
+  if (basePath == process.env.VUE_APP_AdminPath) {
+    base_Path = process.env.VUE_APP_MicroSrvProxy_API + basePath
+  } else if (basePath == process.env.VUE_APP_ParentPath) {
     base_Path = process.env.VUE_APP_MicroSrvProxy_API + basePath
   }
   service.request({
@@ -162,15 +149,11 @@ function processResponse(res) {
   // 获取错误信息
   const message = errorCode[code] || res.data.msg || errorCode['default']
   if (code === 401) {
-    MessageBox.confirm(
-      '登录状态已过期,您可以继续留在该页面,或者重新登录',
-      '系统提示',
-      {
-        confirmButtonText: '重新登录',
-        cancelButtonText: '取消',
-        type: 'warning',
-      }
-    ).then(() => {
+    MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
+      confirmButtonText: '重新登录',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }).then(() => {
       store.dispatch('user/logout').then(() => {
         if (process.env.SSO_LOGIN) {
           sessionStorage.removeItem('SSO_Token')
@@ -212,9 +195,7 @@ function downLoadBlobFile(res, mimeType) {
   })
   // //从response的headers中获取filename, 后端response.setHeader('Content-disposition', 'attachment filename=xxxx.docx') 设置的文件名
   var patt = new RegExp('filename=([^]+\\.[^\\.]+)*')
-  var contentDisposition = decodeURI(
-    res.headers['content-disposition'] || res.headers['Content-Disposition']
-  )
+  var contentDisposition = decodeURI(res.headers['content-disposition'] || res.headers['Content-Disposition'])
   var result = patt.exec(contentDisposition)
   var fileName = 'data.xlsx'
   if (result != undefined) {

+ 7 - 4
src/vab/components/VabQueryForm/index.vue

@@ -27,16 +27,19 @@
   .vab-query-form {
     ::v-deep {
       .el-form-item:first-child {
-        margin: 0 0 $base-margin/2 0 !important;
+        // margin: 0 0 $base-margin/2 0 !important;
+        margin-bottom: $base-margin/2 !important;
       }
-
       .el-form-item + .el-form-item {
-        margin: 0 0 $base-margin/2 0 !important;
-
+        // margin: 0 0 $base-margin/2 0 !important;
+        margin-bottom: $base-margin/2 !important;
         .el-button {
           margin: 0 0 0 10px !important;
         }
       }
+      .el-form-item {
+        margin-right: $base-margin/2;
+      }
 
       .top-panel {
         @include panel;

+ 40 - 0
src/vab/styles/default.scss

@@ -4123,3 +4123,43 @@ $--background-color-base: $base-color-background;
   background-color: transparent;
   border: none;
 }
+
+.el-tree {
+  padding-top: 10px;
+  .custom-tree-node {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    font-size: 14px;
+    padding-right: 8px;
+    span:first-child {
+      flex:1;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      width:0;
+    }
+  }
+  .el-tree-node__content {
+    height: 36px;
+    border-radius: 4px;
+    overflow: hidden;
+  }
+  .el-tree-node:focus > .el-tree-node__content {
+    /*设置选中的样式 */
+    background-color: #dde9ff !important;
+  }
+
+  .el-tree-node__content:hover {
+    /*设置鼠标飘过的颜色 */
+    background: #eaf9ff !important;
+    color: #007bff;
+  }
+
+  .el-tree-node.is-current > .el-tree-node__content {
+    /*current选中的样式 */
+    color: #4d95fd;
+    font-weight: bold;
+    background-color: #dde9ff !important;
+  }
+}

+ 47 - 126
src/views/base/distributor/index.vue

@@ -1,11 +1,11 @@
 <template>
   <div class="user-management-container">
-    <el-row :gutter="20">
-      <el-col :span="4" :xs="24">
+    <el-row :gutter="20" type="flex">
+      <el-col :span="6">
         <div class="head-container">
           <span style="font-size: 25px">所属区域</span>
         </div>
-        <div class="head-container">
+        <div class="tree-container">
           <el-tree
             ref="tree"
             :data="deptOptions"
@@ -15,138 +15,66 @@
             :filter-node-method="filterNode"
             highlight-current
             :props="defaultProps"
-            @node-click="handleNodeClick" />
+            @node-click="handleNodeClick">
+            <span slot-scope="{ node }" class="custom-tree-node">
+              <span>{{ node.label }}</span>
+              <span>
+                <i class="el-icon-more"></i>
+              </span>
+            </span>
+          </el-tree>
         </div>
       </el-col>
-
-      <el-col :span="20" :xs="24">
+      <el-col :span="18">
         <vab-query-form>
-          <vab-query-form-left-panel :span="15">
+          <vab-query-form-left-panel :span="18">
             <el-form :inline="true" :model="queryForm" @submit.native.prevent>
               <el-form-item>
-                <el-input
-                  v-model.trim="queryForm.distCode"
-                  clearable
-                  placeholder="经销商编码" />
+                <el-input v-model.trim="queryForm.distCode" clearable placeholder="经销商编码" />
               </el-form-item>
-              &nbsp;
               <el-form-item>
-                <el-input
-                  v-model.trim="queryForm.distName"
-                  clearable
-                  placeholder="经销商名称" />
+                <el-input v-model.trim="queryForm.distName" clearable placeholder="经销商名称" />
               </el-form-item>
-              &nbsp;
               <el-form-item>
-                <el-input
-                  v-model.trim="queryForm.belongSale"
-                  clearable
-                  placeholder="所属销售" />
-              </el-form-item>
-              <el-form-item>
-                <el-button
-                  icon="el-icon-search"
-                  type="primary"
-                  @click="queryData">
-                  查询
-                </el-button>
+                <el-input v-model.trim="queryForm.belongSale" clearable placeholder="所属销售" />
               </el-form-item>
             </el-form>
-            <vab-query-form-left-panel :span="2">
-              <el-button
-                icon="el-icon-plus"
-                type="primary"
-                @click="handleEdit($event)">
-                新建
-              </el-button>
-            </vab-query-form-left-panel>
           </vab-query-form-left-panel>
+          <vab-query-form-right-panel :span="6">
+            <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
+            <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">新建</el-button>
+          </vab-query-form-right-panel>
         </vab-query-form>
-
-        <el-table
-          v-loading="listLoading"
-          border
-          :data="list"
-          :height="height"
-          @selection-change="setSelectRows">
-          <el-table-column
-            align="center"
-            show-overflow-tooltip
-            type="selection" />
-          <el-table-column
-            align="center"
-            label="经销商编码"
-            prop="distCode"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="经销商名称"
-            prop="distName"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="助记名"
-            prop="abbrName"
-            show-overflow-tooltip />
+        <el-table v-loading="listLoading" border :data="list" :height="height" @selection-change="setSelectRows">
+          <el-table-column align="center" show-overflow-tooltip type="selection" />
+          <el-table-column align="center" label="经销商编码" prop="distCode" show-overflow-tooltip />
+          <el-table-column align="center" label="经销商名称" prop="distName" show-overflow-tooltip />
+          <el-table-column align="center" label="助记名" prop="abbrName" show-overflow-tooltip />
           <!-- <el-table-column
         align="center"
         label="省级ID"
         prop="parentId"
         show-overflow-tooltip /> -->
-          <el-table-column
-            align="center"
-            label="所在省份"
-            prop="provinceDesc"
-            show-overflow-tooltip />
+          <el-table-column align="center" label="所在省份" prop="provinceDesc" show-overflow-tooltip />
           <!-- <template #default="{ row }">
         {{ row.District.distName  }}
       </template>
       </el-table-column> -->
-          <el-table-column
-            align="center"
-            label="归属销售"
-            prop="belongSale"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="业务范围"
-            prop="businessScope"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="负责人"
-            prop="distBoss"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="负责人电话"
-            prop="distBossPhone"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="创建人"
-            prop="createdName"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="创建时间"
-            prop="createdTime"
-            show-overflow-tooltip />
+          <el-table-column align="center" label="归属销售" prop="belongSale" show-overflow-tooltip />
+          <el-table-column align="center" label="业务范围" prop="businessScope" show-overflow-tooltip />
+          <el-table-column align="center" label="负责人" prop="distBoss" show-overflow-tooltip />
+          <el-table-column align="center" label="负责人电话" prop="distBossPhone" show-overflow-tooltip />
+          <el-table-column align="center" label="创建人" prop="createdName" show-overflow-tooltip />
+          <el-table-column align="center" label="创建时间" prop="createdTime" show-overflow-tooltip />
 
-          <el-table-column
-            align="center"
-            label="操作"
-            show-overflow-tooltip
-            width="85">
+          <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
             <template #default="{ row }">
               <el-button type="text" @click="handleEdit(row)">编辑</el-button>
               <el-button type="text" @click="handleDelete(row)">删除</el-button>
             </template>
           </el-table-column>
           <template #empty>
-            <el-image
-              class="vab-data-empty"
-              :src="require('@/assets/empty_images/data_empty.png')" />
+            <el-image class="vab-data-empty" :src="require('@/assets/empty_images/data_empty.png')" />
           </template>
         </el-table>
         <el-pagination
@@ -271,25 +199,18 @@
     },
   }
 </script>
-<style>
-  .el-tree-node:focus > .el-tree-node__content {
-    /*设置选中的样式 */
-    background-color: #dde9ff !important;
-  }
-
-  .el-tree-node__content:hover {
-    /*设置鼠标飘过的颜色 */
-    background: #eaf9ff !important;
-    color: #007bff;
-  }
-
-  .el-tree--highlight-current
-    .el-tree-node.is-current
-    > .el-tree-node__content {
-    /*current选中的样式 */
-    color: #4d95fd;
-    font-weight: bold;
-    background-color: #dde9ff !important;
+<style lang="scss" scoped>
+  $base: '.user-management';
+  #{$base}-container {
+    > .el-row {
+      height: calc(100vh - 60px - 50px - 12px * 2 - 40px - 24px);
+    }
+    .tree-container {
+      height: calc(100% - 30px);
+      .el-tree {
+        height: 100%;
+        overflow-y: auto;
+      }
+    }
   }
 </style>
->

+ 44 - 102
src/views/base/region/index.vue

@@ -1,9 +1,12 @@
 <template>
   <div class="user-management-container">
-    <el-row :gutter="20">
-      <el-col :span="5" :xs="24">
+    <el-row :gutter="20" type="flex">
+      <el-col :span="6">
         <div class="head-container" style="margin-bottom: 5px">
           <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
+          <el-button icon="el-icon-plus" style="margin-top: 10px" type="primary" @click="getCheckedNodes($event)">
+            添加区域
+          </el-button>
           <el-tree
             ref="tree"
             class="filter-tree"
@@ -14,7 +17,14 @@
             highlight-current
             node-key="id"
             :props="defaultProps"
-            @node-click="handleNodeClick" />
+            @node-click="handleNodeClick">
+            <span slot-scope="{ node }" class="custom-tree-node">
+              <span>{{ node.label }}</span>
+              <span>
+                <i class="el-icon-more"></i>
+              </span>
+            </span>
+          </el-tree>
           <!-- <el-tree ref="tree" :data="deptOptions" node-key="id" 
           :filter-node-method="filterNode" :props="defaultProps"
           @node-click="handleNodeClick" /> -->
@@ -22,104 +32,48 @@
         <!-- <div class="buttons">
     <el-button  @click="getCheckedNodes($event)">添加区域</el-button>
   </div> -->
-        <vab-query-form-left-panel :span="2">
-          <el-button
-            icon="el-icon-plus"
-            type="primary"
-            @click="getCheckedNodes($event)">
-            添加区域
-          </el-button>
-        </vab-query-form-left-panel>
       </el-col>
-      <el-col :span="15" :xs="24">
+      <el-col :span="18">
         <vab-query-form>
-          <vab-query-form-left-panel :span="20">
+          <vab-query-form-left-panel :span="18">
             <el-form :inline="true" :model="queryForm" @submit.native.prevent>
               <el-form-item style="letter-spacing: 12px">
-                <el-input
-                  v-model.trim="queryForm.custCode"
-                  clearable
-                  placeholder="客户编码" />
-              </el-form-item>
-              &nbsp;
-
-              <el-form-item>
-                <el-input
-                  v-model.trim="queryForm.custName"
-                  clearable
-                  placeholder="客户名称" />
+                <el-input v-model.trim="queryForm.custCode" clearable placeholder="客户编码" />
               </el-form-item>
-              &nbsp;
               <el-form-item>
-                <el-input
-                  v-model.trim="queryForm.custIndustry"
-                  clearable
-                  placeholder="客户行业" />
+                <el-input v-model.trim="queryForm.custName" clearable placeholder="客户名称" />
               </el-form-item>
               <el-form-item>
-                <el-button
-                  icon="el-icon-search"
-                  type="primary"
-                  @click="queryData">
-                  查询
-                </el-button>
+                <el-input v-model.trim="queryForm.custIndustry" clearable placeholder="客户行业" />
               </el-form-item>
             </el-form>
-            <vab-query-form-left-panel :span="2">
-              <el-button
-                icon="el-icon-plus"
-                type="primary"
-                @click="handleEdit($event)">
-                添加
-              </el-button>
-            </vab-query-form-left-panel>
           </vab-query-form-left-panel>
+          <vab-query-form-right-panel :span="6">
+            <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
+            <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
+          </vab-query-form-right-panel>
         </vab-query-form>
 
         <el-table
           v-loading="listLoading"
           border
           :data="list"
-          style="width: 100%; height: 500px"
+          height="calc(100% - 52px - 43px)"
+          style="width: 100%"
           @selection-change="setSelectRows">
-          <el-table-column
-            align="center"
-            show-overflow-tooltip
-            type="selection" />
-          <el-table-column
-            align="center"
-            label="省份"
-            prop="distName"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="客户数量"
-            prop="count"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="创建人"
-            prop="createdName"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="创建时间"
-            prop="createdTime"
-            show-overflow-tooltip />
-          <el-table-column
-            align="center"
-            label="操作"
-            show-overflow-tooltip
-            width="85">
+          <el-table-column align="center" show-overflow-tooltip type="selection" />
+          <el-table-column align="center" label="省份" prop="distName" show-overflow-tooltip />
+          <el-table-column align="center" label="客户数量" prop="count" show-overflow-tooltip />
+          <el-table-column align="center" label="创建人" prop="createdName" show-overflow-tooltip />
+          <el-table-column align="center" label="创建时间" prop="createdTime" show-overflow-tooltip />
+          <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
             <template #default="{ row }">
               <el-button type="text" @click="handleEdit(row)">编辑</el-button>
               <el-button type="text" @click="handleDelete(row)">删除</el-button>
             </template>
           </el-table-column>
           <template #empty>
-            <el-image
-              class="vab-data-empty"
-              :src="require('@/assets/empty_images/data_empty.png')" />
+            <el-image class="vab-data-empty" :src="require('@/assets/empty_images/data_empty.png')" />
           </template>
         </el-table>
         <el-pagination
@@ -272,30 +226,18 @@
     },
   }
 </script>
-<style>
-  .el-tree-node:focus > .el-tree-node__content {
-    /*设置选中的样式 */
-    background-color: #dde9ff !important;
-  }
-
-  .el-tree-node__content:hover {
-    /*设置鼠标飘过的颜色 */
-    background: #eaf9ff !important;
-    color: #007bff;
-  }
-
-  .el-tree--highlight-current
-    .el-tree-node.is-current
-    > .el-tree-node__content {
-    /*current选中的样式 */
-    color: #4d95fd;
-    font-weight: bold;
-    background-color: #dde9ff !important;
-  }
-
-  .vab-query-form[data-v-64063760]
-    .el-form-item:first-child
-    .el-form-item--small {
-    margin: 0 10px 10px 0 !important;
+<style lang="scss" scoped>
+  $base: '.user-management';
+  #{$base}-container {
+    > .el-row {
+      height: calc(100vh - 60px - 50px - 12px * 2 - 40px - 24px);
+    }
+    .head-container {
+      height: calc(100% - 5px);
+      .el-tree {
+        height: calc(100% - 74px);
+        overflow-y: auto;
+      }
+    }
   }
 </style>

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

@@ -2,17 +2,12 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-26 14:34:34
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-29 11:26:07
+ * @LastEditTime: 2023-01-05 09:15:25
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\components\allocate.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">
     <el-form label-width="80px" :model="form">
       <el-form-item label="销售代表">
         <el-input v-model="form.allocate" readonly>
@@ -21,31 +16,29 @@
       </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" />-->
+    <select-user ref="selectUser" :query-params="{ roles: ['Sales', 'SalesManager'] }" @save="selectUser" />
   </el-dialog>
 </template>
 
 <script>
-  import Transfer from './Transfer.vue'
+  // 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,
+      // Transfer,
+      SelectUser,
     },
     data() {
       const generateData = () => {
         const data = []
         const cities = ['上海', '北京', '广州', '深圳', '南京', '西安', '成都']
-        const pinyin = [
-          'shanghai',
-          'beijing',
-          'guangzhou',
-          'shenzhen',
-          'nanjing',
-          'xian',
-          'chengdu',
-        ]
+        const pinyin = ['shanghai', 'beijing', 'guangzhou', 'shenzhen', 'nanjing', 'xian', 'chengdu']
         cities.forEach((city, index) => {
           data.push({
             label: city,
@@ -64,12 +57,31 @@
         allocate: [],
         data: generateData(),
         options: [],
+        ids: [],
+        userList: [],
       }
     },
     methods: {
       handleClose() {},
       choose() {
-        this.$refs.transfer.innerVisible = true
+        // this.$refs.transfer.innerVisible = true
+        this.$refs.selectUser.open()
+      },
+      selectUser(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-05 09:15:31
  * @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>

+ 4 - 17
src/views/customer/components/Transfer.vue

@@ -2,24 +2,16 @@
  * @Author: wanglj 471442253@qq.com
  * @Date: 2022-12-26 15:00:19
  * @LastEditors: wanglj
- * @LastEditTime: 2022-12-26 17:23:50
+ * @LastEditTime: 2023-01-05 09:15:39
  * @Description: file content
  * @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">

+ 149 - 177
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-05 11:50:51
  * @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="handleAllocate">分配客户</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 }}
@@ -100,40 +137,35 @@
                 {{ abstract.business }}
               </el-descriptions-item>
               <el-descriptions-item label="商机总额">
-                {{ abstract.businessTotal }}
+                {{ formatPrice(abstract.businessTotal) }}
               </el-descriptions-item>
               <el-descriptions-item label="成交次数">
                 {{ abstract.dealCotal }}
               </el-descriptions-item>
               <el-descriptions-item label="成交总额">
-                {{ abstract.dealTotal }}
+                {{ formatPrice(abstract.dealTotal) }}
               </el-descriptions-item>
               <el-descriptions-item label="回款总额">
-                {{ abstract.paymentTotal }}
+                {{ formatPrice(abstract.paymentTotal) }}
               </el-descriptions-item>
               <el-descriptions-item label="未回款总额">
-                {{ abstract.notPaymentTotal }}
+                {{ formatPrice(abstract.notPaymentTotal) }}
               </el-descriptions-item>
               <el-descriptions-item label="开票总额" :span="24">
-                {{ abstract.drawTotal }}
+                {{ formatPrice(abstract.drawTotal) }}
               </el-descriptions-item>
               <el-descriptions-item label="备注" :span="24">
                 {{ detail.remark }}
               </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>
@@ -308,11 +255,11 @@
     <Contact ref="contact" @contactSave="contactSave" />
     <Edit ref="edit" @customerSave="customerSave" />
     <!-- 分配客户 -->
-    <Allocate ref="allocate" />
+    <Allocate ref="allocate" @refresh="back" />
     <!-- 转移客户 -->
-    <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,17 +463,29 @@
           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(() => {})
       },
+      handleAllocate() {
+        this.$refs.allocate.ids = [parseInt(this.id)]
+        this.$refs.allocate.visible = true
+      },
       customerSave() {
         this.init()
         this.getDynamics()
@@ -599,7 +556,7 @@
       ::v-deep .my-label {
         font-size: 14px;
         font-weight: 600;
-        color: #fff;
+        color: #1d66dc;
       }
       ::v-deep .my-content {
         font-size: 14px;
@@ -721,7 +678,7 @@
           .comments {
             padding-left: 60px;
             margin-top: 10px;
-            max-height: 200px;
+            max-height: 190px;
             overflow: auto;
             li {
               display: flex;
@@ -781,6 +738,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 +754,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;

+ 139 - 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-05 13:39:44
  * @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'" class="link-button" 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
@@ -258,4 +329,11 @@
 
 <style lang="scss" scoped>
   $base: '.list';
+  .link-button {
+    font-size: 14px;
+    width: 100%;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
 </style>

+ 172 - 41
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-05 11:38:01
  * @Description: file content
  * @FilePath: \opms_frontend\src\views\customer\openSea.vue
 -->
@@ -16,39 +16,37 @@
         <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-button icon="el-icon-plus" type="primary" @click="fetchData">
-          查询
-        </el-button>
+      <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"
-          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="handleReceive">
-          领取
-        </el-button>
+        <el-button icon="el-icon-plus" type="primary" @click="$refs.edit.init()">新建</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
@@ -58,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'" class="link-button" 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" />
@@ -72,18 +106,18 @@
       <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>
+          <el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -96,14 +130,11 @@
       @current-change="handleCurrentChange"
       @size-change="handleSizeChange" />
     <!-- 新增编辑客户弹窗 -->
-    <Edit
-      ref="edit"
-      @createContact="createContact"
-      @customerSave="customerSave" />
+    <Edit ref="edit" @createContact="createContact" @customerSave="customerSave" />
     <!-- 新建联系人弹窗 -->
     <Contact ref="contact" />
     <!-- 分配客户 -->
-    <Allocate ref="allocate" />
+    <Allocate ref="allocate" @refresh="fetchData" />
   </div>
 </template>
 
@@ -113,12 +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 {
@@ -133,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 || []
@@ -225,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('请选择客户')
@@ -236,7 +354,12 @@
         })
           .then(async () => {
             const [err, res] = await to(
-              api.receiveCustomer({ ids: arr.join() })
+              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) {
@@ -244,9 +367,10 @@
                 type: 'success',
                 message: '领取成功!',
               })
+              this.fetchData()
             }
           })
-          .catch(() => {})
+          .catch((err) => console.log(err))
       },
     },
   }
@@ -254,4 +378,11 @@
 
 <style lang="scss" scoped>
   $base: '.open-sea';
+  .link-button {
+    font-size: 14px;
+    width: 100%;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
 </style>

+ 21 - 42
src/views/plat/task/index.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="user-management-container">
-    <el-row :gutter="20">
-      <el-col :span="2">
-        <span>操作类型</span>
+    <el-row :gutter="20" type="flex">
+      <el-col :span="6">
+        <span class="type">操作类型</span>
         <div style="margin-top: 25px; cursor: pointer" @click="search('1')">
           <i class="el-icon-message-solid" style="margin-right: 10px"></i>
           我的待办({{ statisticsForm.toDoNumber }})
@@ -15,10 +15,8 @@
           <i class="el-icon-folder-checked" style="margin-right: 10px"></i>
           我处理的({{ statisticsForm.completedNumber }})
         </div>
-        <div style="margin-top: 50px">督办类型</div>
-        <div style="margin-top: 20px; cursor: pointer" @click="searchType('')">
-          全部
-        </div>
+        <div class="type" style="margin-top: 50px">督办类型</div>
+        <div style="margin-top: 20px; cursor: pointer" @click="searchType('')">全部</div>
         <div
           v-for="item in types"
           :key="item.dictCode"
@@ -27,28 +25,19 @@
           {{ item.dictLabel }}
         </div>
       </el-col>
-      <el-col :span="22">
+      <el-col :span="18">
         <el-row :gutter="10" style="margin-bottom: 10px">
           <el-col :span="4">
-            <el-input
-              v-model.trim="queryForm.taskTitle"
-              clearable
-              placeholder="请输入督办标题" />
+            <el-input v-model.trim="queryForm.taskTitle" clearable placeholder="请输入督办标题" />
           </el-col>
           <el-col :span="12">
-            <el-button icon="el-icon-search" type="primary" @click="queryData">
-              查询
-            </el-button>
-            <el-button icon="el-icon-refresh-right" @click="reset">
-              重置
-            </el-button>
+            <el-button icon="el-icon-search" type="primary" @click="queryData">查询</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" type="primary" @click="handleAdd">
-              添加
-            </el-button>
+            <el-button icon="el-icon-plus" type="primary" @click="handleAdd">添加</el-button>
           </vab-query-form-left-panel>
           <vab-query-form-right-panel :span="12">
             <el-button icon="el-icon-download" @click="exportData" />
@@ -56,7 +45,7 @@
           </vab-query-form-right-panel>
         </vab-query-form>
         <!-- 主页面 -->
-        <el-table v-loading="listLoading" border :data="list" :height="height">
+        <el-table v-loading="listLoading" border :data="list" height="calc(100vh - 340px)">
           <el-table-column
             v-for="(item, index) in finallyColumns"
             :key="index"
@@ -76,18 +65,11 @@
               <span v-else-if="item.prop === 'isOverdue'">
                 {{ row.isOverdue === '10' ? '否' : '是' }}
               </span>
-              <span
-                v-else-if="
-                  item.prop === 'mainUserId' || item.prop === 'supervisorUserId'
-                ">
+              <span v-else-if="item.prop === 'mainUserId' || item.prop === 'supervisorUserId'">
                 {{ userMap[row[item.prop]] }}
               </span>
               <span
-                v-else-if="
-                  item.prop === 'taskStartDate' ||
-                  item.prop === 'taskEndDate' ||
-                  item.prop === 'createdTime'
-                ">
+                v-else-if="item.prop === 'taskStartDate' || item.prop === 'taskEndDate' || item.prop === 'createdTime'">
                 {{ parseTime(row[item.prop]) }}
               </span>
               <span v-else>{{ row[item.prop] }}</span>
@@ -99,9 +81,7 @@
             </template>
           </el-table-column>
           <template #empty>
-            <el-image
-              class="vab-data-empty"
-              :src="require('@/assets/empty_images/data_empty.png')" />
+            <el-image class="vab-data-empty" :src="require('@/assets/empty_images/data_empty.png')" />
           </template>
         </el-table>
         <el-pagination
@@ -115,11 +95,7 @@
       </el-col>
     </el-row>
     <!-- 新建督办 -->
-    <taskAdd
-      :do-refresh="doRefresh"
-      :self-visible.sync="addDialogVisible"
-      :types="types"
-      :users="users" />
+    <taskAdd :do-refresh="doRefresh" :self-visible.sync="addDialogVisible" :types="types" :users="users" />
     <!-- 查看详情 -->
     <taskDetail
       :do-refresh="doRefresh"
@@ -253,9 +229,7 @@
         return this.$baseTableHeight(1)
       },
       finallyColumns() {
-        return this.columns.filter((item) =>
-          this.checkList.includes(item.label)
-        )
+        return this.columns.filter((item) => this.checkList.includes(item.label))
       },
     },
     async created() {
@@ -405,3 +379,8 @@
     },
   }
 </script>
+<style lang="scss" scoped>
+  .type {
+    font-weight: bold;
+  }
+</style>

+ 15 - 64
src/views/system/group/index.vue

@@ -2,32 +2,16 @@
   <div class="user-management-container">
     <vab-query-form>
       <vab-query-form-left-panel :span="5">
-        <el-button
-          icon="el-icon-plus"
-          type="primary"
-          @click="handleEdit($event)">
-          添加
-        </el-button>
-        <el-button
-          icon="el-icon-delete"
-          type="danger"
-          @click="handleDelete($event)">
-          删除
-        </el-button>
+        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
+        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="19">
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
-          <el-form-item label="用户组名称" prop="dictName">
-            <el-input
-              v-model.trim="queryForm.groupName"
-              clearable
-              placeholder="请输入用户组名称" />
+          <el-form-item label="用户组名称" prop="groupName">
+            <el-input v-model.trim="queryForm.groupName" clearable placeholder="请输入用户组名称" />
           </el-form-item>
-          <el-form-item label="用户组编码" prop="dictType">
-            <el-input
-              v-model.trim="queryForm.groupCode"
-              clearable
-              placeholder="请输入用户组编码" />
+          <el-form-item label="用户组编码" prop="groupCode">
+            <el-input v-model.trim="queryForm.groupCode" clearable placeholder="请输入用户组编码" />
           </el-form-item>
           <el-form-item label="状态" prop="status">
             <el-select v-model="queryForm.status" clearable placeholder="状态">
@@ -36,70 +20,37 @@
             </el-select>
           </el-form-item>
           <el-form-item>
-            <el-button icon="el-icon-search" type="primary" @click="queryData">
-              查询
-            </el-button>
+            <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
           </el-form-item>
         </el-form>
       </vab-query-form-right-panel>
     </vab-query-form>
 
-    <el-table
-      v-loading="listLoading"
-      border
-      :data="list"
-      :height="height"
-      @selection-change="setSelectRows">
+    <el-table v-loading="listLoading" border :data="list" :height="height" @selection-change="setSelectRows">
       <el-table-column align="center" show-overflow-tooltip type="selection" />
-      <el-table-column
-        align="center"
-        label="用户组编号"
-        prop="id"
-        show-overflow-tooltip />
-      <el-table-column
-        align="center"
-        label="用户组名称"
-        prop="groupName"
-        show-overflow-tooltip />
-      <el-table-column
-        align="center"
-        label="用户组编码"
-        prop="groupCode"
-        show-overflow-tooltip />
+      <el-table-column align="center" label="用户组编号" prop="id" show-overflow-tooltip />
+      <el-table-column align="center" label="用户组名称" prop="groupName" show-overflow-tooltip />
+      <el-table-column align="center" label="用户组编码" prop="groupCode" show-overflow-tooltip />
       <el-table-column align="center" label="状态" prop="status">
         <template #default="{ row }">
           {{ row.status === '10' ? '正常' : '停用' }}
         </template>
       </el-table-column>
-      <el-table-column
-        align="center"
-        label="用户组排序"
-        prop="sort"
-        show-overflow-tooltip />
-      <el-table-column
-        align="center"
-        label="备注"
-        prop="remark"
-        show-overflow-tooltip />
+      <el-table-column align="center" label="用户组排序" prop="sort" show-overflow-tooltip />
+      <el-table-column align="center" label="备注" prop="remark" show-overflow-tooltip />
       <el-table-column align="center" label="创建时间" prop="createdTime">
         <template #default="scope">
           <span>{{ parseTime(scope.row.createdTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column
-        align="center"
-        label="操作"
-        show-overflow-tooltip
-        width="85">
+      <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
         <template #default="{ row }">
           <el-button type="text" @click="handleEdit(row)">编辑</el-button>
           <el-button type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>
-        <el-image
-          class="vab-data-empty"
-          :src="require('@/assets/empty_images/data_empty.png')" />
+        <el-image class="vab-data-empty" :src="require('@/assets/empty_images/data_empty.png')" />
       </template>
     </el-table>
     <el-pagination

+ 15 - 64
src/views/system/post/index.vue

@@ -2,32 +2,16 @@
   <div class="user-management-container">
     <vab-query-form>
       <vab-query-form-left-panel :span="5">
-        <el-button
-          icon="el-icon-plus"
-          type="primary"
-          @click="handleEdit($event)">
-          添加
-        </el-button>
-        <el-button
-          icon="el-icon-delete"
-          type="danger"
-          @click="handleDelete($event)">
-          删除
-        </el-button>
+        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
+        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="19">
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
-          <el-form-item label="岗位名称" prop="dictName">
-            <el-input
-              v-model.trim="queryForm.postName"
-              clearable
-              placeholder="请输入岗位名称" />
+          <el-form-item label="岗位名称" prop="postName">
+            <el-input v-model.trim="queryForm.postName" clearable placeholder="请输入岗位名称" />
           </el-form-item>
-          <el-form-item label="岗位编码" prop="dictType">
-            <el-input
-              v-model.trim="queryForm.postCode"
-              clearable
-              placeholder="请输入岗位编码" />
+          <el-form-item label="岗位编码" prop="postCode">
+            <el-input v-model.trim="queryForm.postCode" clearable placeholder="请输入岗位编码" />
           </el-form-item>
           <el-form-item label="状态" prop="status">
             <el-select v-model="queryForm.status" clearable placeholder="状态">
@@ -36,70 +20,37 @@
             </el-select>
           </el-form-item>
           <el-form-item>
-            <el-button icon="el-icon-search" type="primary" @click="queryData">
-              查询
-            </el-button>
+            <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
           </el-form-item>
         </el-form>
       </vab-query-form-right-panel>
     </vab-query-form>
 
-    <el-table
-      v-loading="listLoading"
-      border
-      :data="list"
-      :height="height"
-      @selection-change="setSelectRows">
+    <el-table v-loading="listLoading" border :data="list" :height="height" @selection-change="setSelectRows">
       <el-table-column align="center" show-overflow-tooltip type="selection" />
-      <el-table-column
-        align="center"
-        label="岗位编号"
-        prop="id"
-        show-overflow-tooltip />
-      <el-table-column
-        align="center"
-        label="岗位名称"
-        prop="postName"
-        show-overflow-tooltip />
-      <el-table-column
-        align="center"
-        label="岗位编码"
-        prop="postCode"
-        show-overflow-tooltip />
+      <el-table-column align="center" label="岗位编号" prop="id" show-overflow-tooltip />
+      <el-table-column align="center" label="岗位名称" prop="postName" show-overflow-tooltip />
+      <el-table-column align="center" label="岗位编码" prop="postCode" show-overflow-tooltip />
       <el-table-column align="center" label="状态" prop="status">
         <template #default="{ row }">
           {{ row.status === '10' ? '正常' : '停用' }}
         </template>
       </el-table-column>
-      <el-table-column
-        align="center"
-        label="岗位排序"
-        prop="sort"
-        show-overflow-tooltip />
-      <el-table-column
-        align="center"
-        label="备注"
-        prop="remark"
-        show-overflow-tooltip />
+      <el-table-column align="center" label="岗位排序" prop="sort" show-overflow-tooltip />
+      <el-table-column align="center" label="备注" prop="remark" show-overflow-tooltip />
       <el-table-column align="center" label="创建时间" prop="createdTime">
         <template #default="scope">
           <span>{{ parseTime(scope.row.createdTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column
-        align="center"
-        label="操作"
-        show-overflow-tooltip
-        width="85">
+      <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
         <template #default="{ row }">
           <el-button type="text" @click="handleEdit(row)">编辑</el-button>
           <el-button type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>
-        <el-image
-          class="vab-data-empty"
-          :src="require('@/assets/empty_images/data_empty.png')" />
+        <el-image class="vab-data-empty" :src="require('@/assets/empty_images/data_empty.png')" />
       </template>
     </el-table>
     <el-pagination

+ 12 - 39
src/views/system/role/components/RoleDataScopeEdit.vue

@@ -1,11 +1,6 @@
 <template>
   <!-- 分配角色数据权限对话框 -->
-  <el-dialog
-    append-to-body
-    :close-on-click-modal="false"
-    :title="title"
-    :visible.sync="openDataScope"
-    width="500px">
+  <el-dialog append-to-body :close-on-click-modal="false" :title="title" :visible.sync="openDataScope" width="500px">
     <el-form ref="form" label-width="80px" :model="form" :rules="rules">
       <el-form-item label="角色名称">
         <el-input v-model="form.roleName" :disabled="true" />
@@ -16,27 +11,13 @@
 
       <el-form-item label="权限范围">
         <el-select v-model="form.dataScope">
-          <el-option
-            v-for="item in dataScopeOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value" />
+          <el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
       </el-form-item>
       <el-form-item v-show="form.dataScope == 2" label="数据权限">
-        <el-checkbox
-          v-model="deptExpand"
-          @change="handleCheckedTreeExpand($event, 'dept')">
-          展开/折叠
-        </el-checkbox>
-        <el-checkbox
-          v-model="deptNodeAll"
-          @change="handleCheckedTreeNodeAll($event, 'dept')">
-          全选/全不选
-        </el-checkbox>
-        <el-checkbox
-          v-model="form.deptCheckStrictly"
-          @change="handleCheckedTreeConnect($event, 'dept')">
+        <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
+        <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
+        <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">
           父子联动
         </el-checkbox>
         <el-tree
@@ -82,23 +63,23 @@
         // 数据范围选项
         dataScopeOptions: [
           {
-            value: '1',
+            value: '10',
             label: '全部数据权限',
           },
           {
-            value: '2',
+            value: '20',
             label: '自定数据权限',
           },
           {
-            value: '3',
+            value: '30',
             label: '本部门数据权限',
           },
           {
-            value: '4',
+            value: '40',
             label: '本部门及以下数据权限',
           },
           {
-            value: '5',
+            value: '50',
             label: '仅本人数据权限',
           },
         ],
@@ -155,19 +136,11 @@
           }
           roleApi.updateRoleDataScope(data).then((response) => {
             if (response.code === 200) {
-              this.$baseMessage(
-                response.msg,
-                'success',
-                'vab-hey-message-success'
-              )
+              this.$baseMessage(response.msg, 'success', 'vab-hey-message-success')
               this.openDataScope = false
               this.getList()
             } else {
-              this.$baseMessage(
-                response.msg,
-                'error',
-                'vab-hey-message-success'
-              )
+              this.$baseMessage(response.msg, 'error', 'vab-hey-message-success')
             }
           })
         }

+ 19 - 23
template/api.hbs

@@ -1,25 +1,21 @@
-import request from '@/utils/request'
+import micro_request from '@/utils/micro_request'
 
-export function getList(params) {
-  return request({
-    url: '/{{ name }}/getList',
-    method: 'get',
-    params,
-  })
-}
-
-export function doEdit(data) {
-  return request({
-    url: '/{{ name }}/doEdit',
-    method: 'post',
-    data,
-  })
-}
-
-export function doDelete(data) {
-  return request({
-    url: '/{{ name }}/doDelete',
-    method: 'post',
-    data,
-  })
+const basePath = process.env.VUE_APP_AdminPath
+export default {
+  // 获取列表
+  getList(query) {
+    return micro_request.postRequest(basePath, '{{ properCase name }}', 'GetList', query)
+  },
+  getEntityById(query) {
+    return micro_request.postRequest(basePath, '{{ properCase name }}', 'GetEntityById', query)
+  },
+  doAdd(query) {
+    return micro_request.postRequest(basePath, '{{ properCase name }}', 'Create', query)
+  },
+  doEdit(query) {
+    return micro_request.postRequest(basePath, '{{ properCase name }}', 'UpdateById', query)
+  },
+  doDelete(query) {
+    return micro_request.postRequest(basePath, '{{ properCase name }}', 'DeleteByIds', query)
+  },
 }

+ 2 - 2
template/edit.hbs

@@ -18,7 +18,7 @@
 </template>
 
 <script>
-  import { doEdit } from '@/api/{{moduleName}}/{{ camelCase name }}'
+  import {{ camelCase name }}Api from '@/api/{{moduleName}}/{{ camelCase name }}'
 
   export default {
     name: '{{ properCase name }}Edit',
@@ -53,7 +53,7 @@
       save() {
         this.$refs['form'].validate(async (valid) => {
           if (valid) {
-            const { msg } = await doEdit(this.form)
+            const { msg } = await {{ camelCase name }}Api.doEdit(this.form)
             this.$baseMessage(msg, 'success')
             this.$emit('fetch-data')
             this.close()

+ 7 - 11
template/index.hbs

@@ -18,8 +18,7 @@
       v-loading="listLoading"
       :data="list"
       :height="height"
-      @selection-change="setSelectRows"
-    >
+      @selection-change="setSelectRows">
       <el-table-column align="center" show-overflow-tooltip type="selection" />
       <el-table-column
         v-for="(item, index) in finallyColumns"
@@ -29,9 +28,7 @@
         :prop="item.prop"
         show-overflow-tooltip
         :sortable="item.sortable"
-        :width="item.width"
-      >
-      </el-table-column>
+        :width="item.width" />
 
       <el-table-column align="center" label="操作" width="85">
         <template #default="{ row }">
@@ -47,14 +44,13 @@
       :page-size="queryForm.pageSize"
       :total="total"
       @current-change="handleCurrentChange"
-      @size-change="handleSizeChange"
-    />
+      @size-change="handleSizeChange" />
     <edit ref="edit" @fetch-data="fetchData" />
   </div>
 </template>
 
 <script>
-  import { getList, doDelete } from '@/api/{{moduleName}}/{{ camelCase name }}'
+  import {{ camelCase name }}Api from '@/api/{{moduleName}}/{{ camelCase name }}'
   import Edit from './components/{{ properCase name }}Edit'
   import TableTool from '@/components/table/TableTool'
 
@@ -102,7 +98,7 @@
       handleDelete(row) {
         if (row.id) {
           this.$baseConfirm('你确定要删除当前项吗', null, async () => {
-            const { msg } = await doDelete({ ids: [row.id] })
+            const { msg } = await {{ camelCase name }}Api.doDelete({ ids: [row.id] })
             this.$baseMessage(msg, 'success')
             await this.fetchData()
           })
@@ -110,7 +106,7 @@
           if (this.selectRows.length > 0) {
             const ids = this.selectRows.map((item) => item.id)
             this.$baseConfirm('你确定要删除选中项吗', null, async () => {
-              const { msg } = await doDelete({ ids })
+              const { msg } = await {{ camelCase name }}Api.doDelete({ ids })
               this.$baseMessage(msg, 'success')
               await this.fetchData()
             })
@@ -134,7 +130,7 @@
       },
       async fetchData() {
         this.listLoading = true
-        const { data } = await getList(this.queryForm)
+        const { data } = await {{ camelCase name }}Api.getList(this.queryForm)
         const { list, total } = data
         this.list = list
         this.total = total