diff --git a/api/app/lib/controllers/member/index.js b/api/app/lib/controllers/member/index.js
index 37d5b84..3b6c8fa 100644
--- a/api/app/lib/controllers/member/index.js
+++ b/api/app/lib/controllers/member/index.js
@@ -2,7 +2,7 @@
 const moment = require('moment')
 const fs = require('fs');
 
-async function add (ctx) {
+async function add(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const {
@@ -45,7 +45,7 @@ async function add (ctx) {
    }
 }
 
-async function edit (ctx) {
+async function edit(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const {
@@ -85,7 +85,7 @@ async function edit (ctx) {
    }
 }
 
-async function searchPepMember (ctx) {
+async function searchPepMember(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const { clickHouse } = ctx.app.fs
@@ -103,7 +103,8 @@ async function searchPepMember (ctx) {
       const userRes = await clickHouse.pepEmis.query(`
          SELECT 
            user.id AS pepUserId,
-           user.people_code AS userCode,
+           user.people_code AS userCode,  
+           basicdata_post.name AS userPost,
            user.name AS userName,
            role.name AS roleName,
            role.id AS roleId,
@@ -115,6 +116,8 @@ async function searchPepMember (ctx) {
             ON user_role.user = user.id
          LEFT JOIN role
             ON role.id = user_role.role
+         LEFT JOIN basicdata_post
+            ON basicdata_post.id = user.post
          LEFT JOIN department_user
             ON department_user.user = user.id
          LEFT JOIN department
@@ -146,6 +149,7 @@ async function searchPepMember (ctx) {
                pepUserId: u.pepUserId,
                name: u.userName,
                userCode: u.userCode,
+               userPost: u.userPost,
                departmrnt: u.depId ? [{
                   id: u.depId,
                   name: u.depName
@@ -153,7 +157,7 @@ async function searchPepMember (ctx) {
                role: u.roleId ? [{
                   id: u.roleId,
                   name: u.roleName
-               }] : [],
+               }] : []
             })
          }
       })
@@ -169,7 +173,7 @@ async function searchPepMember (ctx) {
    }
 }
 
-async function del (ctx) {
+async function del(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const { pepUserId } = ctx.query
@@ -181,7 +185,13 @@ async function del (ctx) {
             pepUserId,
          }
       })
-
+      await models.SalesDistribution.update({//顺便把销售人员删了
+         del: true,
+      }, {
+         where: {
+            pepUserId,
+         }
+      })
       ctx.status = 204;
    } catch (error) {
       ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
@@ -192,7 +202,7 @@ async function del (ctx) {
    }
 }
 
-async function nativePlaceList (ctx) {
+async function nativePlaceList(ctx) {
    // 获取已有的户籍地列表
    try {
       const { models } = ctx.fs.dc;
@@ -216,7 +226,7 @@ async function nativePlaceList (ctx) {
    }
 }
 
-async function workPlaceList (ctx) {
+async function workPlaceList(ctx) {
    // 获取已有的工作地列表
    try {
       const { models } = ctx.fs.dc;
@@ -240,7 +250,7 @@ async function workPlaceList (ctx) {
    }
 }
 
-async function maritalList (ctx) {
+async function maritalList(ctx) {
    // 获取已有的婚育状况列表
    try {
       const { models } = ctx.fs.dc;
@@ -264,7 +274,7 @@ async function maritalList (ctx) {
    }
 }
 
-async function list (ctx) {
+async function list(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const { judgeHoliday, memberList, packageUserData } = ctx.app.fs.utils
@@ -299,7 +309,7 @@ async function list (ctx) {
    }
 }
 
-async function overTimeStatistics (ctx) {
+async function overTimeStatistics(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const { clickHouse } = ctx.app.fs
@@ -375,7 +385,7 @@ async function overTimeStatistics (ctx) {
       let returnD = {
          ...(statisticRes.length ? statisticRes[0] : {}),
          data: dataRes,
-         dayStatisticData: statisticDayRes.sort((a,b)=>moment(a.day)-moment(b.day))
+         dayStatisticData: statisticDayRes.sort((a, b) => moment(a.day) - moment(b.day))
       }
       ctx.status = 200;
       ctx.body = returnD
@@ -388,7 +398,7 @@ async function overTimeStatistics (ctx) {
    }
 }
 
-async function vacateStatistics (ctx) {
+async function vacateStatistics(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const { clickHouse } = ctx.app.fs
@@ -465,7 +475,7 @@ async function vacateStatistics (ctx) {
       let returnD = {
          statistic: statisticRes,
          data: dataRes,
-         dayStatisticData: statisticDayRes.sort((a,b)=>moment(a.day)-moment(b.day))
+         dayStatisticData: statisticDayRes.sort((a, b) => moment(a.day) - moment(b.day))
       }
       ctx.status = 200;
       ctx.body = returnD
@@ -478,11 +488,11 @@ async function vacateStatistics (ctx) {
    }
 }
 
-async function exportData (ctx) {
+async function exportData(ctx) {
    try {
       const { models } = ctx.fs.dc;
       const { clickHouse, opts: { qiniu } } = ctx.app.fs
-      const { simpleExcelDown, memberList, packageUserData } = ctx.app.fs.utils
+      const { simpleExcelDown, memberList, packageUserData, UserAttribute } = ctx.app.fs.utils
       const {
          keywordTarget, keyword, limit, page, state, keys = '',
          hiredateStart, hiredateEnd, marital, native, workPlace,
@@ -507,7 +517,28 @@ async function exportData (ctx) {
       }, {
          title: '姓名',
          key: 'userName',
-      }]
+      }, {
+        title: '所属部门',
+        key: 'departmrnt',
+     }, {
+        title: '职位',
+        key: 'userJob',
+     }, {
+        title: '岗位',
+        key: 'userPost',
+     }, {
+        title: '在职状态',
+        key: 'userActiveStatus',
+     }, {
+        title: '绩点',
+        key: 'point',
+     }, {
+        title: '归属机构',
+        key: 'userOrganization',
+     }, {
+        title: '技术职级等级',
+        key: 'technicalGrade',
+     }]
       let header = [].concat(preHeader)
       for (let k in tableAttributes) {
          const comment = tableAttributes[k].comment
@@ -569,6 +600,10 @@ async function exportData (ctx) {
       exportD.forEach(d => {
          d.departmrnt = d.departmrnt.map(dep => dep.name).join('、')
          d.role = d.role.map(r => r.name).join('、')
+         
+         d.userJob = d.userJob? UserAttribute.jobDataSource[d.userJob - 1] : '';
+         d.userActiveStatus = d.userActiveStatus? UserAttribute.activeStatusDataSource[d.userActiveStatus - 1] : '';
+         d.userOrganization = d.userOrganization? UserAttribute.organizationDataSource[d.userOrganization - 1] : '';
 
          d.idPhoto ? d.idPhoto = qiniu.domain + '/' + d.idPhoto : ''
          d.vitae ? d.vitae = qiniu.domain + '/' + d.vitae : ''
@@ -598,7 +633,7 @@ async function exportData (ctx) {
    }
 }
 
-async function addMembersBulk (ctx) {
+async function addMembersBulk(ctx) {
    let errorMsg = { message: '导入员工信息失败' };
    const transaction = await ctx.fs.dc.orm.transaction();
    try {
diff --git a/api/app/lib/controllers/salesDistribution/index.js b/api/app/lib/controllers/salesDistribution/index.js
new file mode 100644
index 0000000..7da2d1f
--- /dev/null
+++ b/api/app/lib/controllers/salesDistribution/index.js
@@ -0,0 +1,336 @@
+'use strict';
+const moment = require('moment')
+const fs = require('fs');
+
+async function salesList(ctx) {
+   try {
+      const { memberList, packageUserData } = ctx.app.fs.utils
+      const {
+         keywordTarget, keyword, limit, page, state,
+         hiredateStart, hiredateEnd, marital, native, workPlace,
+         orderBy, orderDirection, placeSearch
+      } = ctx.query
+
+      const userRes = await memberList({
+         keywordTarget, keyword, limit: '', page: '', state,
+         hiredateStart, hiredateEnd, marital, native, workPlace,
+         orderBy, orderDirection,
+         nowAttendanceTime: true
+      })
+
+      let { packageUser: members } = await packageUserData(userRes, {
+         state: true,
+      })
+
+      const { models } = ctx.fs.dc;
+
+      let mIds = members.map(m => m.pepUserId);
+
+
+      let where = {
+         del: false,
+         pepUserId: { $in: mIds }
+      }
+      if (placeSearch) {
+         where.$or = [{
+            provinces: { $like: `%${placeSearch}%` }
+         }, {
+            cities: { $like: `%${placeSearch}%` }
+         }]
+      }
+      let res = await models.SalesDistribution.findAndCountAll({
+         where: where,
+         offset: Number(page) * Number(limit),
+         limit: Number(limit),
+         order: [['id', 'DESC']]
+      })
+
+      let rslt = []
+      res.rows.map(d => {
+         let info = members.find(m => m.pepUserId == d.dataValues.pepUserId);
+         let item = {
+            name: info.userName,
+            userCode: info.userCode,
+            post: info.userPost,
+            department: info.departmrnt,
+            hireDate: info.hiredate,//入职时间
+            regularDate: info.regularDate,//转正时间
+            ...d.dataValues
+         }
+         rslt.push(item);
+      })
+      ctx.status = 200;
+      ctx.body = {
+         count: res.count,
+         rows: rslt
+      };
+   } catch (error) {
+      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+      ctx.status = 400;
+      ctx.body = {
+         message: typeof error == 'string' ? error : undefined
+      }
+   }
+}
+
+async function add(ctx) {
+   try {
+      const { models } = ctx.fs.dc;
+      const { pepUserId, provinces, cities, businessLines } = ctx.request.body
+
+      const existRes = await models.SalesDistribution.findOne({
+         where: { pepUserId }
+      })
+
+      if (existRes && !existRes.del) {
+         throw '当前销售人员信息已存在'
+      }
+
+      let storageData = { pepUserId, provinces, cities, businessLines, del: false }
+      if (existRes && existRes.del) {
+         await models.SalesDistribution.update(storageData, {
+            where: { pepUserId }
+         })
+      } else {
+         await models.SalesDistribution.create(storageData)
+      }
+      ctx.status = 204;
+   } catch (error) {
+      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+      ctx.status = 400;
+      ctx.body = {
+         message: typeof error == 'string' ? error : undefined
+      }
+   }
+}
+
+async function edit(ctx) {
+   try {
+      const { models } = ctx.fs.dc;
+      const { pepUserId, provinces, cities, businessLines } = ctx.request.body
+
+      const existRes = await models.SalesDistribution.findOne({
+         where: { pepUserId }
+      })
+
+      if (!existRes) {
+         throw '当前销售人员信息不存在'
+      }
+
+      let storageData = { pepUserId, provinces, cities, businessLines, del: false }
+
+      await models.SalesDistribution.update(storageData, {
+         where: {
+            pepUserId: pepUserId
+         }
+      })
+
+      ctx.status = 204;
+   } catch (error) {
+      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+      ctx.status = 400;
+      ctx.body = {
+         message: typeof error == 'string' ? error : undefined
+      }
+   }
+}
+
+async function del(ctx) {
+   try {
+      const { models } = ctx.fs.dc;
+      const { pepUserId } = ctx.query
+
+      await models.SalesDistribution.update({
+         del: true,
+      }, {
+         where: {
+            pepUserId,
+         }
+      })
+      ctx.status = 204;
+   } catch (error) {
+      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+      ctx.status = 400;
+      ctx.body = {
+         message: typeof error == 'string' ? error : undefined
+      }
+   }
+}
+
+// async function exportData(ctx) {
+//    try {
+//       const { models } = ctx.fs.dc;
+//       const { clickHouse, opts: { qiniu } } = ctx.app.fs
+//       const { simpleExcelDown, memberList, packageUserData } = ctx.app.fs.utils
+//       const {
+//          keywordTarget, keyword, limit, page, state, keys = '',
+//          hiredateStart, hiredateEnd, marital, native, workPlace,
+//          orderBy, orderDirection,
+//       } = ctx.query
+
+//       const userRes = await memberList({
+//          keywordTarget, keyword, limit, page, state,
+//          hiredateStart, hiredateEnd, marital, native, workPlace,
+//          orderBy, orderDirection,
+//          nowAttendanceTime: true
+//       })
+
+//       const tableAttributes = models['Member'].tableAttributes
+//       const optionKeys = keys.split(',')
+
+//       let { packageUser: exportD, pepUserIds } = await packageUserData(userRes)
+
+//       let preHeader = [{
+//          title: '员工编号',
+//          key: 'userCode',
+//       }, {
+//          title: '姓名',
+//          key: 'userName',
+//       }]
+//       let header = [].concat(preHeader)
+//       for (let k in tableAttributes) {
+//          const comment = tableAttributes[k].comment
+//          if (k != 'id' && k != 'pepUserId' && comment) {
+//             if ([].includes(k)) {
+//                // 截住不想导出的字段
+//                continue
+//             }
+//             header.push({
+//                title: comment || '-',
+//                key: k,
+//                // index: tableAttributes[k].index,
+//             })
+//          }
+//       }
+
+//       if (optionKeys.includes('overtimeStatistic')) {
+//          header = header.concat([{
+//             title: '累计加班次数',
+//             key: 'overTimeCount',
+//          }, {
+//             title: '累计加班总时长 / h',
+//             key: 'overTimeDuration',
+//          },])
+//       }
+//       if (optionKeys.includes('vacateStatistic')) {
+//          header = header.concat([{
+//             title: '累计请假次数',
+//             key: 'vacateCount',
+//          }, {
+//             title: '累计请假总时长 / h',
+//             key: 'vacateDuration',
+//          },])
+//       }
+
+//       // 查询累计加班次数及总时长
+//       const statisticOvertimeRes = await clickHouse.hr.query(`
+//             SELECT 
+//                pep_user_id AS pepUserId,
+//                count(id) AS count,  
+//                sum(duration) AS duration
+//             FROM 
+//                overtime
+//             WHERE pep_user_id IN (${pepUserIds.join(',')})
+//             GROUP BY pep_user_id
+//          `).toPromise()
+
+//       const statisticVacateRes = await clickHouse.hr.query(`
+//             SELECT 
+//                pep_user_id AS pepUserId,
+//                count(id) AS count,
+//                sum(duration) AS duration
+//             FROM 
+//                vacate
+//             WHERE pep_user_id IN (${pepUserIds.join(',')})
+//             GROUP BY pep_user_id
+//          `).toPromise()
+
+//       exportD.forEach(d => {
+//          d.departmrnt = d.departmrnt.map(dep => dep.name).join('、')
+//          d.role = d.role.map(r => r.name).join('、')
+
+//          d.idPhoto ? d.idPhoto = qiniu.domain + '/' + d.idPhoto : ''
+//          d.vitae ? d.vitae = qiniu.domain + '/' + d.vitae : ''
+
+//          const corOverTime = statisticOvertimeRes.find(so => so.pepUserId == d.pepUserId)
+//          d.overTimeCount = corOverTime ? corOverTime.count : 0
+//          d.overTimeDuration = corOverTime ? (corOverTime.duration / 3600).toFixed(1) : 0
+//          const corVacate = statisticVacateRes.find(so => so.pepUserId == d.pepUserId)
+//          d.vacateCount = corVacate ? corVacate.count : 0
+//          d.vacateDuration = corVacate ? (corVacate.duration / 3600).toFixed(1) : 0
+//       })
+
+//       const fileName = `人员信息_${moment().format('YYYYMMDDHHmmss')}` + '.csv'
+//       const filePath = await simpleExcelDown({ data: exportD, header, fileName: fileName })
+//       const fileData = fs.readFileSync(filePath);
+
+//       ctx.status = 200;
+//       ctx.set('Content-Type', 'application/x-xls');
+//       ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
+//       ctx.body = fileData;
+//    } catch (error) {
+//       ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+//       ctx.status = 400;
+//       ctx.body = {
+//          message: typeof error == 'string' ? error : undefined
+//       }
+//    }
+// }
+
+async function addSalesMemberBulk(ctx) {
+   let errorMsg = { message: '导入销售人员信息失败' };
+   const transaction = await ctx.fs.dc.orm.transaction();
+   try {
+      const models = ctx.fs.dc.models;
+      const data = ctx.request.body;
+      let addArr = [];
+      let editArr = [];
+      let list = await models.SalesDistribution.findAll({
+         attributes: ['pepUserId']
+      });
+      data.map(d => {
+         let exist = list.find(m => m.pepUserId == d.pepUserId);//项企的人员编号字段还没有
+         if (exist) {
+            editArr.push(d);
+         } else {
+            addArr.push(d);
+         }
+      })
+
+      //处理新增的
+      if (addArr.length) {
+         await models.SalesDistribution.bulkCreate(addArr);
+      }
+
+      //处理编辑的
+      if (editArr.length) {
+         for (let i in editArr) {
+            let { pepUserId, provinces, cities, businessLines, del = false } = editArr[i];
+
+            let dataToUpdate = {
+               provinces,
+               cities,
+               businessLines,
+               del
+            }
+            await models.SalesDistribution.update(dataToUpdate, { where: { pepUserId: pepUserId } });
+         }
+      }
+      await transaction.commit();
+      ctx.status = 204;
+   } catch (error) {
+      await transaction.rollback();
+      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+      ctx.status = 400;
+      ctx.body = errorMsg;
+   }
+}
+
+module.exports = {
+   salesList,
+   add,
+   edit,
+   del,
+   //exportData,
+   addSalesMemberBulk,
+}
\ No newline at end of file
diff --git a/api/app/lib/models/sales_distribution.js b/api/app/lib/models/sales_distribution.js
new file mode 100644
index 0000000..1d46830
--- /dev/null
+++ b/api/app/lib/models/sales_distribution.js
@@ -0,0 +1,71 @@
+/* eslint-disable*/
+
+'use strict';
+
+module.exports = dc => {
+  const DataTypes = dc.ORM;
+  const sequelize = dc.orm;
+  const SalesDistribution = sequelize.define("salesDistribution", {
+    id: {
+      type: DataTypes.INTEGER,
+      allowNull: false,
+      defaultValue: null,
+      comment: null,
+      primaryKey: true,
+      field: "id",
+      autoIncrement: true,
+      unique: "sales_distribution_id_uindex"
+    },
+    pepUserId: {
+      type: DataTypes.INTEGER,
+      allowNull: false,
+      defaultValue: null,
+      comment: null,
+      primaryKey: false,
+      field: "pep_user_id",
+      autoIncrement: false
+    },
+    provinces: {
+      type: DataTypes.STRING,
+      allowNull: false,
+      defaultValue: null,
+      comment: null,
+      primaryKey: false,
+      field: "provinces",
+      autoIncrement: false
+    },
+    cities: {
+      type: DataTypes.STRING,
+      allowNull: true,
+      defaultValue: null,
+      comment: null,
+      primaryKey: false,
+      field: "cities",
+      autoIncrement: false
+    },
+    del: {
+      type: DataTypes.BOOLEAN,
+      allowNull: true,
+      defaultValue: null,
+      comment: null,
+      primaryKey: false,
+      field: "del",
+      autoIncrement: false
+    },
+    businessLines: {
+      type: DataTypes.STRING,
+      allowNull: true,
+      defaultValue: null,
+      comment: null,
+      primaryKey: false,
+      field: "business_lines",
+      autoIncrement: false
+    }
+  }, {
+    tableName: "sales_distribution",
+    comment: "",
+    indexes: []
+  });
+  dc.models.SalesDistribution = SalesDistribution;
+  return SalesDistribution;
+};
\ No newline at end of file
diff --git a/api/app/lib/routes/salesDistribution/index.js b/api/app/lib/routes/salesDistribution/index.js
new file mode 100644
index 0000000..28ed0e1
--- /dev/null
+++ b/api/app/lib/routes/salesDistribution/index.js
@@ -0,0 +1,24 @@
+'use strict';
+
+const salesDistribution = require('../../controllers/salesDistribution');
+
+module.exports = function (app, router, opts) {
+
+   app.fs.api.logAttr['GET/sales/member/list'] = { content: '查询销售人员列表', visible: true };
+   router.get('/sales/member/list', salesDistribution.salesList);
+
+   app.fs.api.logAttr['POST/sales/member/add'] = { content: '添加销售人员信息', visible: true };
+   router.post('/sales/member/add', salesDistribution.add);
+
+   app.fs.api.logAttr['PUT/sales/member/modify'] = { content: '编辑销售人员信息', visible: true };
+   router.put('/sales/member/modify', salesDistribution.edit);
+
+   app.fs.api.logAttr['DEL/sales/member/del'] = { content: '删除销售人员信息', visible: true };
+   router.del('/sales/member/del', salesDistribution.del);
+
+   app.fs.api.logAttr['POST/add/sales/members/bulk'] = { content: '导入销售人员信息', visible: true };
+   router.post('/add/sales/members/bulk', salesDistribution.addSalesMemberBulk);
+
+   // app.fs.api.logAttr['GET/sales/members/export'] = { content: '导出销售人员信息', visible: true };
+   // router.get('/sales/members/export', salesDistribution.exportData);
+};
\ No newline at end of file
diff --git a/api/app/lib/utils/constant.js b/api/app/lib/utils/constant.js
index 8012eca..67f58e8 100644
--- a/api/app/lib/utils/constant.js
+++ b/api/app/lib/utils/constant.js
@@ -2,19 +2,25 @@
 
 module.exports = function (app, opts) {
 
-   const dayType = {
-      dayoff: '普假',
-      workday: '工作日',
-      festivals: '法定假',
-   }
+    const dayType = {
+        dayoff: '普假',
+        workday: '工作日',
+        festivals: '法定假',
+    }
 
-   const overtimeType = {
-      '发放加班补偿': '折算',
-      '调休': '调休'
-   }
-
-   return {
-      dayType,
-      overtimeType,
-   }
+    const overtimeType = {
+        '发放加班补偿': '折算',
+        '调休': '调休'
+    }
+    const UserAttribute = {
+        jobDataSource: ['普通员工', '中层', '高层'],
+        activeStatusDataSource: ['在职', '离职', '特殊状态-特殊账号'],
+        organizationDataSource: ['江西飞尚科技有限公司', '江西飞尚工程质量检测有限公司',
+            '江西飞尚科技有限公司江苏分公司', '江西汇派科技有限公司'],
+    };
+    return {
+        dayType,
+        overtimeType,
+        UserAttribute
+    }
 }
\ No newline at end of file
diff --git a/api/app/lib/utils/member.js b/api/app/lib/utils/member.js
index 479d521..1a5c404 100644
--- a/api/app/lib/utils/member.js
+++ b/api/app/lib/utils/member.js
@@ -200,13 +200,11 @@ module.exports = function (app, opts) {
          `: ''}
          WHERE
             member.del = '0'
-            ${keywordTarget == 'role' && keyword ? `
-               AND user.id IN (
-                  SELECT user_role.user
-                  FROM ${pepEmis}.user_role AS user_role
-                  INNER JOIN ${pepEmis}.role AS role
-                     ON role.id = user_role.role
-                     AND role.name LIKE '%${keyword}%'
+            ${keywordTarget == 'post' && keyword ? `
+               AND user.post IN (
+                  SELECT basicDataPost.id
+                  FROM ${pepEmis}.basicdata_post AS basicDataPost
+                  where basicDataPost.name LIKE '%${keyword}%'
                )
             ` : ''}
             ${keywordTarget == 'dep' && keyword ? `
@@ -244,10 +242,14 @@ module.exports = function (app, opts) {
             hrMember.*,
             user.name AS userName,
             user.people_code AS userCode,
+            basicDataPost.name AS userPost,
             role.name AS roleName,
             role.id AS roleId,
             department.name AS depName,
-            department.id AS depId
+            department.id AS depId,
+            user.job AS userJob,
+            user.active_status AS userActiveStatus,
+            user.organization AS userOrganization
          FROM (
             SELECT 
                ${orderBy == 'overtimeTakeRestSum'
@@ -287,6 +289,8 @@ module.exports = function (app, opts) {
                ON ${pepEmis}.user_role.user = user.id
             LEFT JOIN ${pepEmis}.role AS role
                ON ${pepEmis}.role.id = user_role.role
+            LEFT JOIN ${pepEmis}.basicdata_post AS basicDataPost
+               ON ${pepEmis}.basicdata_post.id = user.post
             LEFT JOIN ${pepEmis}.department_user AS department_user
                ON department_user.user = user.id
             LEFT JOIN ${pepEmis}.department AS department
diff --git a/api/app/lib/utils/xlsxDownload.js b/api/app/lib/utils/xlsxDownload.js
index bcd060a..21f8fea 100644
--- a/api/app/lib/utils/xlsxDownload.js
+++ b/api/app/lib/utils/xlsxDownload.js
@@ -59,7 +59,7 @@ module.exports = function (app, opts) {
          indexCell.style = headerStyle
          for (let h of header) {
             const cell = row.addCell();
-            cell.value = data[i][h.key] || h.defaultValue || '';
+            cell.value = data[i][h.key] || h.defaultValue || '-';
             cell.style = style
          }
       }
diff --git a/doc/scripts/0.0.4/schema/1.sales_distribution.sql b/doc/scripts/0.0.4/schema/1.sales_distribution.sql
new file mode 100644
index 0000000..28d3160
--- /dev/null
+++ b/doc/scripts/0.0.4/schema/1.sales_distribution.sql
@@ -0,0 +1,11 @@
+
+
+CREATE TABLE sales_distribution
+(
+    id serial PRIMARY KEY NOT NULL,
+    pep_user_id int NOT NULL,
+    provinces text NOT NULL,
+    cities text,
+    del boolean DEFAULT false NULL
+);
+CREATE UNIQUE INDEX sales_distribution_id_uindex ON sales_distribution (id);
\ No newline at end of file
diff --git a/doc/scripts/PEP V3.0.0/schema/1.sales_distribution_modify.sql b/doc/scripts/PEP V3.0.0/schema/1.sales_distribution_modify.sql
new file mode 100644
index 0000000..82a1085
--- /dev/null
+++ b/doc/scripts/PEP V3.0.0/schema/1.sales_distribution_modify.sql	
@@ -0,0 +1,4 @@
+
+
+alter table sales_distribution
+	add "business_lines" text;
\ No newline at end of file
diff --git a/web/client/index.ejs b/web/client/index.ejs
index 488bfac..fb765cf 100644
--- a/web/client/index.ejs
+++ b/web/client/index.ejs
@@ -9,7 +9,7 @@
    
    
 
-    
+    
 
 
 
diff --git a/web/client/index.html b/web/client/index.html
index 9474515..45f5de1 100644
--- a/web/client/index.html
+++ b/web/client/index.html
@@ -7,7 +7,7 @@
 
     
 
-     
+     
 
 
 
diff --git a/web/client/src/layout/components/header/contant.js b/web/client/src/layout/components/header/contant.js
index b58ed2d..4aa17a0 100644
--- a/web/client/src/layout/components/header/contant.js
+++ b/web/client/src/layout/components/header/contant.js
@@ -60,6 +60,11 @@ const headerItems = [{
         itemKey: "recruitRecord",
         text: "招聘记录",
         to: "/humanAffairs/recruit/recruitRecord/appointmentRecords"
+    }, {
+        fatherKey: "recruit",
+        itemKey: "salesStatistics",
+        text: "销售统计",
+        to: "/humanAffairs/recruit/salesStatistics/personnelDistribution"
     }]
 }, {
     itemKey: "employeeRelationship",
diff --git a/web/client/src/sections/humanAffairs/actions/index.js b/web/client/src/sections/humanAffairs/actions/index.js
index f2d429b..d69a9d8 100644
--- a/web/client/src/sections/humanAffairs/actions/index.js
+++ b/web/client/src/sections/humanAffairs/actions/index.js
@@ -2,8 +2,9 @@
 
 import * as personnelFiles from './personnelFiles'
 import * as employeeInformation from './employeeInformation'
-
+import * as salesDistribution from './salesDistribution'
 export default {
     ...personnelFiles,
-    ...employeeInformation
+    ...employeeInformation,
+    ...salesDistribution
 }
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/actions/salesDistribution.js b/web/client/src/sections/humanAffairs/actions/salesDistribution.js
new file mode 100644
index 0000000..6037d8c
--- /dev/null
+++ b/web/client/src/sections/humanAffairs/actions/salesDistribution.js
@@ -0,0 +1,89 @@
+'use strict';
+
+import { ApiTable, basicAction } from '$utils'
+
+export function addSalesMemberBulk(values) {
+    return dispatch => basicAction({
+        type: 'post',
+        dispatch: dispatch,
+        actionType: 'SALES_MEMBER_BULK_ADD',
+        url: ApiTable.addSalesMemberBulk,
+        data: values,
+        msg: { option: '导入销售人员信息' },
+    });
+}
+
+export function postSalesMember(data) {//添加/编辑
+    let msg = ''
+    if (data) {
+        msg = data.msg
+    }
+    return (dispatch) =>
+        basicAction({
+            type: "post",
+            dispatch: dispatch,
+            data,
+            actionType: "POST_SALES_MEMBER",
+            url: `${ApiTable.addSalesMember}`,
+            msg: { option: msg }, //添加/编辑
+            reducer: { name: "" },
+        });
+}
+
+export function getSalesList(query) {//查询
+    return (dispatch) => basicAction({
+        type: "get",
+        dispatch: dispatch,
+        actionType: "GET_SALES_MENBER_LIST",
+        query: query,
+        url: `${ApiTable.getSalesList}`,
+        msg: { option: "查询销售人员列表" },
+        reducer: { name: "SalesMemberList", params: { noClear: true } },
+    });
+}
+export function delSalesMember(data) {//删除
+    let msg = ''
+    if (data) {
+        msg = data.msg
+    }
+    return (dispatch) =>
+        basicAction({
+            type: "del",
+            query: data,
+            dispatch: dispatch,
+            actionType: "DEL_SALES_MEMBER",
+            url: `${ApiTable.delSalesMember}`,
+            msg: { option: msg }, //删除
+            reducer: {},
+        });
+}
+
+// export function getMemberExport(query) {//导出员工信息
+//     return (dispatch) => basicAction({
+//         type: "get",
+//         dispatch: dispatch,
+//         actionType: "GET_MemberEXPORT",
+//         query: query,
+//         url: `${ApiTable.getMemberExport}`,
+//         msg: { option: "导出员工信息" },
+//         reducer: { name: "MemberExport", params: { noClear: true } },
+//     });
+// }
+
+
+export function editSalesMember(data) {//更新
+    let msg = ''
+    if (data) {
+        msg = data.msg
+    }
+    return (dispatch) =>
+        basicAction({
+            type: "put",
+            dispatch: dispatch,
+            data,
+            actionType: "PUT_SALES_MEMBER",
+            url: `${ApiTable.editSalesMember}`,
+            msg: { option: msg }, //更新
+            reducer: {},
+        });
+}
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/components/personnelModal.jsx b/web/client/src/sections/humanAffairs/components/personnelModal.jsx
index 425d835..698efb0 100644
--- a/web/client/src/sections/humanAffairs/components/personnelModal.jsx
+++ b/web/client/src/sections/humanAffairs/components/personnelModal.jsx
@@ -240,33 +240,10 @@ function pushModal (props) {
                                                          
                                                     
                                                     
-                                                        职位:
+                                                        岗位:
                                                     
                                                     
-                                                        {
-                                                            peoplePro.role.map((ite, idx) => {
-                                                                let roleArr = []
-                                                                for (let i = 0; i < peoplePro.role.length; i++) {
-                                                                    roleArr.push(peoplePro.role[i].name)
-                                                                }
-                                                                return (
-                                                                    
-                                                                        {idx == 0 ?
-                                                                            (ite.name) : ('')
-                                                                        }
-                                                                        {
-                                                                            peoplePro.role.length > 1 && idx == 1 ? (
-                                                                                
-                                                                                    
-                                                                                        +{peoplePro.role.length - 1}
-                                                                                    
-                                                                                
-                                                                            ) : ('')
-                                                                        }
-                                                                    
-                                                                )
-                                                            })
-                                                        }
+                                                        {peoplePro.userPost || '-'}
                                                     
 职位
                     
                 ),
+                width: 100,
+                dataIndex: "userJob",
+                key: "userJob",
+                render: (_, r, index) => {
+                    return r.userJob ? UserAttribute.jobDataSource[r.userJob - 1] : '-';
+                },
+            }, {
+                title: (
+
 职位
                     
                 ),
+                width: 100,
+                dataIndex: "userJob",
+                key: "userJob",
+                render: (_, r, index) => {
+                    return r.userJob ? UserAttribute.jobDataSource[r.userJob - 1] : '-';
+                },
+            }, {
+                title: (
+                    
+                        

 岗位
+                    
+                        

 在职状态
+                    
+                        

 所属机构
+                    
-                            {
-                                r.role.map((ite, idx) => {
-                                    let roleArr = []
-                                    for (let i = 0; i < r.role.length; i++) {
-                                        roleArr.push(r.role[i].name)
-                                    }
-                                    return (
-                                        
-                                            {idx == 0 ?
-                                                (ite.name) : ('')
-                                            }
-                                            {
-                                                r.role.length > 1 && idx == 1 ? (
-                                                    
-                                                        
-                                                            +{r.role.length - 1}
-                                                        
-                                                    
-                                                ) : ('')
-                                            }
-                                        
-                                    )
-                                })
-                            }
-                        
                         
                              
                                                     
-                                                        {
-                                                            item.role.map((ite, idx) => {
-                                                                let roleArr = []
-                                                                for (let i = 0; i < item.role.length; i++) {
-                                                                    roleArr.push(item.role[i].name)
-                                                                }
-                                                                return (
-                                                                    
-                                                                        {idx == 0 ?
-                                                                            (ite.name.substring(0, 6)) : ('')
-                                                                        }
-                                                                        {
-                                                                            item.role.length > 1 && idx == 1 ? (
-                                                                                
-                                                                                    
-                                                                                        +{item.role.length - 1}
-                                                                                    
-                                                                                
-                                                                            ) : ('')
-                                                                        }
-                                                                    
-                                                                )
-                                                            })
-                                                        }
+                                                        {item.userPost || '暂无'}
                                                     
 
                                                 
diff --git a/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx b/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx
index 46a4e8e..c2b889b 100644
--- a/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx
+++ b/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx
@@ -7,6 +7,7 @@ import * as echarts from 'echarts';
 import DeleteModal from '../components/deleteModal';
 import PersonnelModal from '../components/personnelModal';
 import moment from 'moment'
+import { UserAttribute } from '$utils'
 
 
 import '../style.less'
@@ -610,7 +611,7 @@ const Rest = (props) => {
                                     职务信息
                                 
                                 
-                                    
+                                    
                                         
                                             员工编号:
                                         
@@ -618,7 +619,7 @@ const Rest = (props) => {
                                             {pepObj.userCode || '暂无'}
                                         
 
                                     
-                                    
+                                    
                                         
                                             入职时间:
                                         
@@ -626,7 +627,7 @@ const Rest = (props) => {
                                             {pepObj.hiredate || '暂无'}
                                         
 
                                     
-                                    
+                                    
                                         
                                             转试用期时间:
                                         
@@ -644,43 +645,38 @@ const Rest = (props) => {
                                     
 
                                 
-                                    
+                                    
                                         
                                             员工职位:
                                         
-                                        
+                                        
+                                            {
+                                                pepObj.userJob? UserAttribute.jobDataSource[pepObj.userJob - 1] : '暂无'
+                                            }
+                                        
+                                    
+                                    
+                                        
+                                            员工岗位:
+                                        
+                                        
                                             {
-                                                pepObj?.role?.map((item, index) => {
-                                                    let roleArr = []
-                                                    for (let i = 0; i < pepObj.role.length; i++) {
-                                                        roleArr.push(pepObj.role[i].name)
-                                                    }
-                                                    return (
-                                                        
-                                                            {index < 2 ?
-                                                                (item.name) : ('')
-                                                            }
-                                                            {
-                                                                pepObj.role.length > 1 && index == 0 ?
-                                                                    (',') : ('')
-                                                            }
-                                                            {
-                                                                pepObj.role.length > 2 && index == 2 ? (
-                                                                    
-                                                                        
-                                                                            +{pepObj.role.length - 2}
-                                                                        
-                                                                    
-                                                                ) : ('')
-                                                            }
-                                                        
-                                                    )
-                                                })
+                                                pepObj.userPost || '暂无'
                                             }
                                         
-                                    
+                                    
                                         
+                                            所属机构:
+                                        
+                                        
+                                            {
+                                                pepObj.userOrganization? UserAttribute.organizationDataSource[pepObj.userOrganization - 1] : '暂无'
+                                            }
+                                        
+                                    
 
+                                    
+                                        
                                             所属部门:
                                         
                                         {
@@ -712,7 +708,7 @@ const Rest = (props) => {
                                     
-                                    
+                                    
                                         
                                             工作经验:
                                         
@@ -720,7 +716,7 @@ const Rest = (props) => {
                                             {pepObj.experienceYear ? pepObj.experienceYear + '年' : '暂无'}
                                         
 
                                     
-                                    
+                                    
                                         
                                             入职年限:
                                         
@@ -728,7 +724,7 @@ const Rest = (props) => {
                                             {pepObj.hiredate ? String(moment(new Date()).diff(pepObj.hiredate, 'years',true)).substring(0,3) + '年' : '暂无'}
                                         
 
                                     
-                                    
+                                    
                                         
                                             试用期:
                                         
diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js b/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js
new file mode 100644
index 0000000..a10cdaa
--- /dev/null
+++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js
@@ -0,0 +1,272 @@
+'use strict';
+import React, { useState, useEffect } from 'react';
+import { connect } from 'react-redux';
+import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui';
+import { IconUpload } from '@douyinfe/semi-icons';
+import cityData from '../../components/city.json';
+import XLSX from 'xlsx'
+//下载模板和上传文件读取
+const ImportSalersModal = props => {
+    const { dispatch, actions, onCancel, rzMembers } = props
+    const { humanAffairs } = actions;
+    const [msg, setMsg] = useState('')
+    const [loading, setLoading] = useState('')
+    const [postData, setPostData] = useState([])
+    const [allProvinces, setAllProvinces] = useState([])
+    //初始化
+    useEffect(() => {
+        let allProvinces = [];//所有省
+        cityData.map(cd => {
+            allProvinces.push(cd.name);
+        });
+        setAllProvinces(allProvinces);
+    }, []);
+
+    const confirm = () => {
+        if (postData.length) {
+            setLoading(true)
+            dispatch(humanAffairs.addSalesMemberBulk(postData)).then(res => {
+                if (res.success) {
+                    onCancel()
+                }
+                setLoading(false)
+            })
+        } else {
+            Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 })
+        }
+    }
+
+    const dldCsvMb = () => {
+        //表头
+        let head = "员工编号,姓名,销售区域(省/直辖市),销售区域(市),业务线\n"
+        //数据
+        //let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5
+        let templateCsv = "data:text/csv;charset=utf-8,\ufeff" + head;
+        //创建一个a标签
+        let link = document.createElement("a");
+        //为a标签设置属性
+        link.setAttribute("href", templateCsv);
+        link.setAttribute("download", "人资系统销售人员信息导入模板.csv");
+        //点击a标签
+        link.click();
+    }
+    const download = () => {
+        //dldTemplate();
+        dldCsvMb();
+        // let str = "";
+        // rule.forEach((v, i) => {
+        //     str += `${v}\r\n`
+        // })
+        // dldText("填写说明.txt", str);
+    }
+
+    // const dldText = (filename, text) => {
+    //     var element = document.createElement('a');
+    //     element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
+    //     element.setAttribute('download', filename);
+
+    //     element.style.display = 'none';
+    //     document.body.appendChild(element);
+
+    //     element.click();
+    //     document.body.removeChild(element);
+    // }
+    const fileLimit = '.csv';
+
+    const getFileBlob = (url) => {
+        return new Promise((resolve, reject) => {
+            let request = new XMLHttpRequest()
+            request.open("GET", url, true)
+            request.responseType = "blob"
+            request.onreadystatechange = e => {
+                if (request.readyState == 4) {
+                    if (request.status == 200) {
+                        if (window.FileReader) {
+                            let reader = new FileReader();
+                            reader.readAsBinaryString(request.response);
+                            reader.onload = event => {
+                                try {
+                                    const { result } = event.target;
+                                    // 以二进制流方式读取得到整份excel表格对象
+                                    const workbook = XLSX.read(result, {
+                                        type: "binary",
+                                        cellDates: true,//设为true,将天数的时间戳转为时间格式
+                                        codepage: 936//解决了乱码问题
+                                    });
+                                    let data = []; // 存储获取到的数据
+                                    // 遍历每张工作表进行读取(这里默认只读取第一张表)
+                                    for (const sheet in workbook.Sheets) {
+                                        if (workbook.Sheets.hasOwnProperty(sheet)) {
+                                            data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
+                                        }
+                                    }
+                                    resolve(data);//导出数据
+                                } catch (e) {
+                                    reject("失败");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            request.send();
+        })
+    }
+
+    const judgeProvinces = (provinces) => {
+        let noMark = 0;
+        provinces?.split('、')?.map(p => {
+            if (allProvinces.indexOf(p) == -1) {
+                noMark++
+            }
+        })
+        return !noMark;
+    }
+
+    const judgeCities = (provinces, cities) => {
+        if (!cities) {//可以不填
+            return true;
+        }
+        let nowCities = [];
+        cityData.filter(cd => provinces?.split('、').indexOf(cd.name) != -1).map(d => {
+            d.children?.map(c => {
+                nowCities.push(c.name)
+            })
+        })
+        let noMark = 0;
+        cities?.split('、')?.map(p => {
+            if (nowCities.indexOf(p) == -1) {
+                noMark++
+            }
+        })
+        return !noMark;
+    }
+
+    const judgeNull = (value) => {
+        return value ? String(value).trim().replace(/\s*/g, "") : null;
+    }
+
+    return (
+        
 {
+                setMsg('')
+                setLoading(false)
+                setPostData([])
+                onCancel()
+            }}
+        >
+            
+             {
+                        setMsg('');
+                        setPostData([]);
+                    }}
+                    customRequest={(data) => {
+                        const { file, onSuccess, onError } = data
+                        getFileBlob(file.url).then(res => {
+                            const error = (msg) => {
+                                setMsg(msg)
+                                onError({ message: msg })
+                            }
+                            if (res.length > 1000) {
+                                error('一次性上传数据行数应小于1000行,请分批上传')
+                                return
+                            }
+                            if (!res.length) {
+                                error('请填写至少一行数据')
+                                return
+                            }
+                            let postData = [];
+                            const zmsz = /^[A-Za-z0-9]+$/;//字母数字组合
+                            for (let i = 0; i < res.length; i++) {
+                                let d = res[i];
+                                let number = judgeNull(d['员工编号']);
+                                let name = judgeNull(d['姓名']);
+                                let provinces = judgeNull(d['销售区域(省/直辖市)']);
+                                let cities = judgeNull(d['销售区域(市)']);
+                                let businessLines = judgeNull(d['业务线']);
+                                if (!number) {//人员编号不为空,唯一,字母和数字
+                                    error(`第${i + 2}行人员编号为空,请填写`)
+                                    return
+                                }
+                                let rzExist = rzMembers.find(m => m.userCode == number);
+                                if (!rzExist) {
+                                    error(`第${i + 2}行的人员编号无对应的员工信息`)
+                                    return
+                                }
+                                if (postData.some(p => p.number == number)) {//人员编号 唯一
+                                    error(`第${i + 2}行人员编号重复,请更改后重新上传`)
+                                    return
+                                }
+                                if (!zmsz.test(number)) {
+                                    error(`第${i + 2}行人员编号错误,请填写字母和数字的组合`)
+                                    return
+                                }
+                                if (!name) {//姓名必填
+                                    error(`第${i + 2}行姓名为空,请填写`)
+                                    return
+                                }
+                                if (!provinces) {//销售区域(省/直辖市)必填
+                                    error(`第${i + 2}行销售区域(省/直辖市)为空,请填写`)
+                                    return
+                                }
+                                let pValid = judgeProvinces(provinces);
+                                if (!pValid) {
+                                    error(`第${i + 2}行销售区域(省/直辖市)错误`)
+                                    return
+                                }
+                                let cValid = judgeCities(provinces, cities);
+                                if (!cValid) {
+                                    error(`第${i + 2}行销售区域(市)错误`)
+                                    return
+                                }
+                                //todo 业务线判断
+                                postData.push({
+                                    pepUserId: rzExist.pepUserId, name, number,
+                                    provinces: provinces || '', cities: cities || '', businessLines: businessLines || '',
+                                    del: false
+                                })
+                            }
+                            setPostData(postData)
+                            let msg = '文件解析完成,点击确定按钮上传保存!'
+                            setMsg(msg)
+                            onSuccess({ message: msg })
+                        })
+                    }}>
+                    } theme="light">
+                        请选择文件
+                    
+                
+                {msg}
+                最大不超过200M,导入文件需与
+                     download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板
+                    一致
+                
+                    
填写要求:
+                    
员工编号:必填,唯一,数字和字母的组合;
+                    
姓名:必填,若与员工编号对应的项企用户姓名不同,将以项企数据为准;
+                    
销售区域(省/直辖市):必填,省或直辖市顿号隔开,如“北京市、江西省、江苏省”;
+                    
销售区域(市):非必填,归属所填省的地级市顿号隔开,如“南昌市、镇江市”。
+                
+    )
+}
+
+function mapStateToProps(state) {
+    const { auth, global, MemberList } = state;
+    return {
+        user: auth.user,
+        actions: global.actions,
+        rzMembers: MemberList.data?.rows || [],
+    }
+}
+
+export default connect(mapStateToProps)(ImportSalersModal);
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx b/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx
new file mode 100644
index 0000000..b472776
--- /dev/null
+++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx
@@ -0,0 +1,350 @@
+import React, { useEffect, useRef, useState, useMemo } from 'react';
+import { connect } from 'react-redux';
+import moment from 'moment'
+import { Select, Input, Button, Popconfirm, Radio, Tooltip, Table, Pagination, Skeleton } from '@douyinfe/semi-ui';
+import SalesMemberModal from './salesMemberModal'
+import ImportSalersModal from './importSalersModal'
+import { IconSearch } from '@douyinfe/semi-icons';
+import { SkeletonScreen } from "$components";
+import '../../style.less'
+
+const PersonnelDistribution = (props) => {
+    const { dispatch, actions } = props
+    const { humanAffairs } = actions;
+    const [keywordTarget, setKeywordTarget] = useState('dep');
+    const [keyword, setKeyword] = useState('');//搜索内容
+    const [limits, setLimits] = useState()//每页实际条数
+    const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息
+    const [modalV, setModalV] = useState(false);
+    const [dataToEdit, setDataToEdit] = useState(null);
+    const [tableData, setTableData] = useState([]);
+    const [importModalV, setImportModalV] = useState(false);
+    const page = useRef(query.page);
+    function seachValueChange(value) {
+        setKeyword(value)
+    }
+
+    useEffect(() => {
+        dispatch(humanAffairs.getMemberList())
+        getMemberSearchList()
+    }, []);
+
+    useEffect(() => {
+        getMemberSearchList()//查询人员列表
+    }, [query])
+
+    function getMemberSearchList() {
+        let kt = keywordTarget == 'place' ? '' : keywordTarget;
+        let k = keywordTarget == 'place' ? '' : keyword;
+        let placeSearch = keywordTarget == 'place' ? keyword : '';
+        dispatch(humanAffairs.getSalesList({ keywordTarget: kt, keyword: k, placeSearch, ...query })).then(r => {
+            if (r.success) {
+                setTableData(r.payload?.data?.rows);
+                setLimits(r.payload?.data?.count)
+            }
+        })
+    }
+
+    function handleRow(record, index) {// 给偶数行设置斑马纹
+        if (index % 2 === 0) {
+            return {
+                style: {
+                    background: '#FAFCFF',
+                }
+            };
+        } else {
+            return {};
+        }
+    }
+
+    const closeAndFetch = () => {
+        setModalV(false)
+        getMemberSearchList();
+    }
+
+    const starHeader = (header) => {
+        return 
+            

 {header}
+        
+    }
+
+    const getMultis = (arrStr) => {//默认展示2个
+        return 
+            {
+                arrStr.length ?
+                    arrStr.map((ite, idx) => {
+                        return (
+                            
+                                {idx < 2 ?
+                                    
+                                        {ite}
+                                    
 : ''
+                                }
+                                {
+                                    arrStr.length > 2 && idx == 2 ?
+                                        
+                                            
+                                                +{arrStr.length - 2}
+                                            
+                                        
+                                        : ''
+                                }
+                            
+                        )
+                    }) : '-'
+            }
+        
+    }
+
+    const columns = [{
+        title: '序号',
+        dataIndex: 'id',
+        key: 'id',
+        width: 60,
+        render: (text, record, index) => index + 1
+    }, {
+        title: starHeader('姓名'),
+        dataIndex: 'name',
+        key: 'name',
+        width: 80
+    },
+    {
+        title: starHeader('部门名称'),
+        dataIndex: 'department',
+        key: 'department',
+        width: 200,
+        render: (text, r, index) => {
+            let arrStr = text.map(t => t.name);
+            return getMultis(arrStr);
+        }
+    }, {
+        title: '销售区域(省/直辖市)',
+        dataIndex: 'provinces',
+        key: 'provinces',
+        width: 160,
+        render: (text, record, index) => {
+            return getMultis(text?.split('、') || []);
+        }
+    }, {
+        title: '销售区域(市)',
+        dataIndex: 'cities',
+        key: 'cities',
+        width: 160,
+        render: (text, record, index) => {
+            return text ? getMultis(text?.split('、') || []) : '-';
+        }
+    }, {
+        title: '业务线',
+        dataIndex: 'businessLines',
+        key: 'businessLines',
+        width: 120,
+        render: (text, record, index) => {
+            return text ? getMultis(text?.split('、') || []) : '-';
+        }
+    }, {
+        title: starHeader('岗位'),
+        dataIndex: 'post',
+        key: 'post',
+        width: 120,
+        render: (text, record) => 
{text || '-'}
+    }, {
+        title: starHeader('入职时间'),
+        dataIndex: 'hireDate',
+        key: 'hireDate',
+        width: 120,
+        render: (text, record) => 
{text || '-'}
+    }, {
+        title: starHeader('转正时间'),
+        dataIndex: 'regularDate',
+        key: 'regularDate',
+        width: 120,
+        render: (text, record) => 
{text || '-'}
+    }, {
+        title: starHeader('工龄'),
+        dataIndex: 'workYears',
+        key: 'workYears',
+        width: 120,
+        render: (_, r, index) => {
+            return (r.hireDate ? 
{String(moment(new Date()).diff(r.hireDate, 'years', true)).substring(0, 3) + '年'} : '-')
+        },
+    }, {
+        title: '操作',
+        dataIndex: 'action',
+        width: 120,
+        render: (text, record) => {
+            return 
+                
 onEdit(record)}>编辑  
+                
 confirmDelete(record.pepUserId)} style={{ width: 330 }}
+                > 删除
+            
+        }
+    }];
+
+    const onEdit = (data) => {
+        setModalV(true);
+        setDataToEdit(data);
+    }
+
+    const confirmDelete = (pepUserId) => {
+        dispatch(humanAffairs.delSalesMember({ pepUserId, msg: '删除销售人员信息' })).then(res => {
+            if (res.success) {
+                getMemberSearchList();
+            }
+        });
+    }
+    const scroll = useMemo(() => ({}), []);
+    return (
+        
+            
招聘
+            
/
+            
销售统计
+            
/
+            
销售人员分布
+        
+        
+            
+                
+                    
+                    
销售人员分布
+                    
DISTRIBUTION OF SALES PERSONNEL
+                
+            
+            
+                
+                    
+                        
 {
+                                setModalV(true);
+                                setDataToEdit(null);
+                            }}>
+                            新增
+                        
+                        
+                            
+                        
+                        
+                            }
+                                showClear
+                                placeholder='请输入关键词搜索'
+                                value={keyword}
+                                style={{ width: 346 }}
+                                onChange={seachValueChange}>
+                            
+                        
+                        
+                    
+                    
+                        
 { setImportModalV(true); }}>
+                            导入
+                        
+                        {/* 
+                            导出
+                        
 */}
+                    
+                
+
+                
+                    

+                    表格中带有认证标识"
+                    

+                    "信息的为系统基础数据,来源于项企PEP、钉钉等系统,其他数据均为导入或自定义数据
+                
+
+                
+                    
+                         {
+                                if (sorter.key == 'userCode') {
+                                    if (sorter.sortOrder == 'descend') {
+                                        setOrder({ orderBy: 'code', orderDirection: 'DESC' })
+                                    } else {
+                                        setOrder({ orderBy: 'code', orderDirection: 'ASC' })
+                                    }
+                                } else if (sorter.key == 'age') {
+                                    if (sorter.sortOrder == 'descend') {
+                                        setOrder({ orderBy: 'age', orderDirection: 'DESC' })
+                                    } else {
+                                        setOrder({ orderBy: 'age', orderDirection: 'ASC' })
+                                    }
+                                } else {
+                                    if (sorter.sortOrder == 'descend') {
+                                        setOrder({ orderBy: 'hiredate', orderDirection: 'DESC' })
+                                    } else {
+                                        setOrder({ orderBy: 'hiredate', orderDirection: 'ASC' })
+                                    }
+                                }
+                            }}
+                            onRow={handleRow}
+                            scroll={scroll}
+                        />
+                    
+                    
+                        
+                        
+                            
+                                共{limits}条信息
+                            
+                            
 {
+                                    setQuery({ limit: pageSize, page: currentPage - 1 });
+                                    page.current = currentPage - 1
+                                }}
+                            />
+                        
+                    
+            {
+                peoplePro == 'noValid' ?
+                    
+                        没有符合条件的结果
+                    
 :
+                    peoplePro?.name ? (
+                        
+                            
+                                {renderPeopleItem('姓名:', peoplePro.name)}
+                                
+                                    
+                                        

+                                    
+                                    
+                                        所属部门:
+                                    
+                                    {getMultis(arrStr)}
+                                
+                            
+                            
+                                {renderPeopleItem('入职时间:', peoplePro.hireDate)}
+                                {renderPeopleItem('岗位:', peoplePro.post)}
+                            
 
+                                {renderPeopleItem('转正时间:', peoplePro.regularDate)}
+                                {renderPeopleItem('工龄:', peoplePro.hireDate ? String(moment(new Date()).diff(peoplePro.hireDate, 'years', true)).substring(0, 3) + '年' : '-')}
+                            
+                        
+                    ) : ('')
+            }
+        
+            
+                

+            
+            
+                {label}
+            
+            
+                {value || '-'}
+            
+        
 {
+                        let formList = form.current.getValues()
+                        if (formList.userCode) {
+                            memberSeach(formList.userCode)
+                        }
+                    }}>
+                        搜索
+                    
} />
+
+                {peoplePro ? renderSimpleInfo() : ''}
+                 onClear()}
+                    onChange={value => onChange(value)}
+                    maxTagCount={5}
+                >
+                    {options}
+                
+                
+                    {cityOptions}
+                
+                
+                    {lineOptions}
+                
+            
+        
+    )
+}
+
+function mapStateToProps(state) {
+    const { auth, global, MemberList } = state;
+    return {
+        user: auth.user,
+        actions: global.actions,
+        apiRoot: global.apiRoot,
+        rzMembers: MemberList.data?.rows || [],
+    };
+}
+
+export default connect(mapStateToProps)(SalesMemberModal);
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/nav-item.jsx b/web/client/src/sections/humanAffairs/nav-item.jsx
index 3696ea1..a7b5010 100644
--- a/web/client/src/sections/humanAffairs/nav-item.jsx
+++ b/web/client/src/sections/humanAffairs/nav-item.jsx
@@ -46,6 +46,14 @@ export function getNavItem(user, dispatch) {
                     items: [{
                         itemKey: 'appointmentRecords', to: '/humanAffairs/recruit/recruitRecord/appointmentRecords', text: '任用记录'
                     }]
+                }, {
+                    itemKey: 'salesStatistics',
+                    text: '销售统计',
+                    icon: ,//wwwtodo
+                    to: '/humanAffairs/recruit/salesStatistics/personnelDistribution',
+                    items: [{
+                        itemKey: 'personnelDistribution', to: '/humanAffairs/recruit/salesStatistics/personnelDistribution', text: '销售人员分布'
+                    }]
                 }, {
                     itemKey: 'trainFiles',
                     text: '培训档案',
diff --git a/web/client/src/sections/humanAffairs/routes.js b/web/client/src/sections/humanAffairs/routes.js
index 9815cf7..91ffb0c 100644
--- a/web/client/src/sections/humanAffairs/routes.js
+++ b/web/client/src/sections/humanAffairs/routes.js
@@ -2,7 +2,7 @@ import {
     PersonnelFiles, EmployeeInformation,    //人员档案
     DeptArchives,       //部门档案
     AttendanceStatistics, LeaveStatistics, OvertimeStatistics,
-    AppointmentRecords,
+    AppointmentRecords, PersonnelDistribution,
     ResourceRepository,
     WeeklyManagement, SaleLog, PMLog,
     ProbationerKPI, RegularKPI,
@@ -89,6 +89,16 @@ export default [{
                         component: AppointmentRecords,
                         breadcrumb: '任用记录',
                     }]
+                }, {
+                    path: '/salesStatistics',
+                    key: 'salesStatistics',
+                    breadcrumb: '销售统计',
+                    childRoutes: [{
+                        path: '/personnelDistribution',
+                        key: 'personnelDistribution',
+                        component: PersonnelDistribution,
+                        breadcrumb: '销售人员分布',
+                    }]
                 }]
             }, {
                 path: '/train',
diff --git a/web/client/src/utils/index.js b/web/client/src/utils/index.js
index 0084428..860a315 100644
--- a/web/client/src/utils/index.js
+++ b/web/client/src/utils/index.js
@@ -6,7 +6,7 @@ import {
    AxyRequest, EmisRequest,
    basicAction, RouteRequest
 } from './webapi'
-
+import { UserAttribute } from './userAttribute';
 export {
    isAuthorized,
    AuthorizationCode,
@@ -17,4 +17,5 @@ export {
    EmisRequest,
    basicAction,
    RouteRequest,
+   UserAttribute
 }
\ No newline at end of file
diff --git a/web/client/src/utils/userAttribute.js b/web/client/src/utils/userAttribute.js
new file mode 100644
index 0000000..2a28e82
--- /dev/null
+++ b/web/client/src/utils/userAttribute.js
@@ -0,0 +1,8 @@
+'use strict';
+
+export const UserAttribute = {
+    jobDataSource: ['普通员工', '中层', '高层'],
+    activeStatusDataSource: ['在职', '离职', '特殊状态-特殊账号'],
+    organizationDataSource: ['江西飞尚科技有限公司', '江西飞尚工程质量检测有限公司',
+        '江西飞尚科技有限公司江苏分公司', '江西汇派科技有限公司'],
+};
diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js
index ccfc4d2..b2b85cb 100644
--- a/web/client/src/utils/webapi.js
+++ b/web/client/src/utils/webapi.js
@@ -31,6 +31,12 @@ export const ApiTable = {
    getAttendanceVacate: 'attendance/vacate',//请假统计
    getAttendanceVacateType: 'attendance/vacate/type',//请假类型
    getAttendanceOvertime: 'attendance/overtime',//加班统计
+
+   getSalesList: 'sales/member/list',
+   addSalesMember: 'sales/member/add',
+   editSalesMember: 'sales/member/modify',
+   delSalesMember: 'sales/member/del',
+   addSalesMemberBulk: 'add/sales/members/bulk'
 };
 export const RouteTable = {
    apiRoot: "/api/root",