Bläddra i källkod

Merge branch 'master' of http://47.100.37.243:10191/wutt/manHourHousekeeper

Min 11 månader sedan
förälder
incheckning
357be3d9e9
22 ändrade filer med 604 tillägg och 165 borttagningar
  1. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  2. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/index.vue
  3. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/index.vue
  4. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  5. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/index.vue
  6. 0 5
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue
  7. 4 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue
  8. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/type.d.ts
  9. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/role/index.vue
  10. 8 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/api.ts
  11. 276 48
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/index.vue
  12. 18 15
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/AddPersonnelModal.vue
  13. 100 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/BatchOperation.vue
  14. 26 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/type.ts
  15. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/type.d.ts
  16. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue
  17. 3 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/dto/TaskDto.java
  18. 25 4
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContactsServiceImpl.java
  19. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SysFormServiceImpl.java
  20. 89 70
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  21. 7 1
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ContactsMapper.xml
  22. 32 3
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/TaskMapper.xml

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue

@@ -99,7 +99,7 @@
           <h4 :id="titleId">{{ allText.newBusinessisibleText }}</h4>
           <div>
             <el-button type="primary" :loading="allLoading.newBusinessSaveLading"
-              :disabled="allLoading.businessSaveLading" @click="editBusiness(true)">保存并新建</el-button>
+              :disabled="allLoading.businessSaveLading" @click="editBusiness(true)" v-if="!businessTemplateValue.id">保存并新建</el-button>
             <el-button type="primary" @click="editBusiness(false)" :loading="allLoading.businessSaveLading"
               :disabled="allLoading.newBusinessSaveLading">保存</el-button>
             <el-button @click="closeVisible('newBusinessisible')">取消</el-button>
@@ -198,7 +198,7 @@ const businessTableRef = ref<InstanceType<typeof ElTable>>() // 商机table dom
 const businessTotalTable = ref(0)
 const businessTemplateRef = ref<typeof GenerateForm>() // 自定义表单dom
 const relatedProductsRef = ref<typeof RelatedProducts>()
-const businessTemplateValue = ref({})
+const businessTemplateValue = ref<any>({})
 const businessTemplateKey = ref(1)
 const businessTemplate = ref({
   config: {},

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/index.vue

@@ -73,7 +73,7 @@
         <div class="flex justify-between items-center border-b pb-3 dialog-header">
           <h4 :id="titleId">{{ allText.editContactsText }}</h4>
           <div>
-            <el-button type="primary" :loading="allLoading.editContactsSaveLoading"
+            <el-button type="primary" :loading="allLoading.editContactsSaveLoading" v-if="!contactsTemplateValue.id"
               @click="editContactsSave(true)">保存并新建</el-button>
             <el-button type="primary" :loading="allLoading.editContactsSaveLoading"
               @click="editContactsSave(false)">保存</el-button>
@@ -169,7 +169,7 @@ const contactsTemplate = ref({
   list: [],
   config: {}
 })
-const contactsTemplateValue = ref({})
+const contactsTemplateValue = ref<any>({})
 const contactsTemplateRefKey = ref(1)
 const contactsTemplateRef = ref<typeof GenerateForm>()
 const contactsTableRef = ref<InstanceType<typeof ElTable>>()

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/index.vue

@@ -105,7 +105,7 @@
         <div class="flex justify-between items-center border-b pb-3 dialog-header">
           <h4 :id="titleId">{{ allText.editCustomerText }}</h4>
           <div>
-            <el-button type="primary" :loading="allLoading.editCustomerSaveLoading"
+            <el-button type="primary" :loading="allLoading.editCustomerSaveLoading" v-if="!customerTemplateValue.id"
               @click="editCustomerSave(true)">保存并新建</el-button>
             <el-button type="primary" :loading="allLoading.editCustomerSaveLoading"
               @click="editCustomerSave(false)">保存</el-button>
@@ -272,7 +272,7 @@ const customerTemplate = ref({
   config: {}
 })
 const customerTemplateRef = ref<typeof GenerateForm>() // 自定义表单dom
-const customerTemplateValue = ref({})
+const customerTemplateValue = ref<any>({})
 const customerTemplateRefKey = ref(1)
 const taskModalForm = ref({})
 const taskLoading = ref<saveLoadingType>('1')

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue

@@ -7,11 +7,11 @@
       <h2 class="text-xl text-center pt-4 font-bold">客户管家</h2>
       <el-form class="pt-4" ref="ruleFormRef" :model="ruleForm" :rules="rules">
         <el-form-item prop="username">
-          <el-input clearable :prefix-icon="UserFilled" size="large" class="mt-2" v-model="ruleForm.username"
+          <el-input clearable :prefix-icon="UserFilled" size="large" class="mt-2" v-model.trim="ruleForm.username"
             autocomplete="off" placeholder="账号/手机号" />
         </el-form-item>
         <el-form-item prop="password">
-          <el-input clearable :prefix-icon="Lock" show-password size="large" class="mt-4" v-model="ruleForm.password"
+          <el-input clearable :prefix-icon="Lock" show-password size="large" class="mt-4" v-model.trim="ruleForm.password"
             autocomplete="off" placeholder="密码" />
         </el-form-item>
         <div class="pt-4">

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/index.vue

@@ -82,7 +82,7 @@
         <div class="flex justify-between items-center border-b pb-3 dialog-header">
           <h4 :id="titleId">{{ allText.orderEditText }}</h4>
           <div>
-            <el-button type="primary" :loading="allLoading.editSaveLading" @click="saveOrder(true)">保存并新建</el-button>
+            <el-button type="primary" :loading="allLoading.editSaveLading" v-if="!orderTemplateValue.id" @click="saveOrder(true)">保存并新建</el-button>
             <el-button type="primary" :loading="allLoading.editSaveLading" @click="saveOrder(false)">保存</el-button>
             <el-button @click="closeVisible('editOrderVisible')">取消</el-button>
           </div>
@@ -202,7 +202,7 @@ const filterItems = ref<FilterItem[]>([
   { label: '负责人', key: 'inchargerId', type: 'select', options: selectData.Personnel },
   { label: '下单时间', key: '', type: 'date' },
 ]) // 渲染筛选条件
-const orderTemplateValue = ref({})
+const orderTemplateValue = ref<any>({})
 const orderTemplateKey = ref(1)
 const orderTemplateRef = ref<typeof GenerateForm>()
 const relatedProductsRef = ref<typeof RelatedProducts>()

+ 0 - 5
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue

@@ -20,7 +20,6 @@
                 <el-table-column label="操作" width="180" fixed="right">
                     <template #default="scope">
                         <el-button link type="primary" size="large" @click="fileDownload(scope.row)">下载</el-button>
-                        <el-button link type="primary" size="large" @click="fileDownload2(scope.row)">下载2</el-button>
                         <el-button link type="primary" size="large" @click="showVisible(scope.row)">重命名</el-button>
                         <el-button link type="danger" size="large" @click="deteleFile(scope.row)">删除</el-button>
                     </template>
@@ -79,10 +78,6 @@ function fileDownload(item: any) {
     downloadFile(item.url, `${removeSuffix(item.attachmentName, item.attachmentSuffix)}${item.attachmentSuffix}`)
 }
 
-function fileDownload2(item: any) {
-    downloadFile(item.serverName, `${removeSuffix(item.attachmentName, item.attachmentSuffix)}${item.attachmentSuffix}`)
-}
-
 function removeSuffix(str: string, suffix: string) {
     if (str.endsWith(suffix)) {
         return str.slice(0, -suffix.length);

+ 4 - 4
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue

@@ -11,7 +11,7 @@
               <el-input v-model="filterProductForm.productName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="产品类别">
-              <el-select v-model="filterProductForm.type" placeholder="请选择" clearable filterable>
+              <el-select v-model="filterProductForm.productType" placeholder="请选择" clearable filterable>
                 <el-option v-for="item in fixedData.ProductType" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
@@ -97,7 +97,7 @@
         <div class="flex justify-between items-center border-b pb-3 dialog-header">
           <h4 :id="titleId">{{ allText.editClueText }}</h4>
           <div>
-            <el-button type="primary" @click="saveProductRow(true)" :loading="allLoading.saveLoading">保存并新建</el-button>
+            <el-button type="primary" @click="saveProductRow(true)" v-if="!genereditForm.id":loading="allLoading.saveLoading">保存并新建</el-button>
             <el-button type="primary" @click="saveProductRow(false)" :loading="allLoading.saveLoading">保存</el-button>
             <el-button @click="dialogVisible.editProductVisible = false">取消</el-button>
           </div>
@@ -157,7 +157,7 @@ const filterProductForm = reactive<filterProductFormType>({ // 筛选条件form
   pageIndex: 1,
   pageSize: 10,
   id: '',
-  type: '',
+  productType: '',
   status: '',
 })
 const allLoading = reactive({
@@ -190,7 +190,7 @@ const productTemplate = ref({
   list: [],
   config: {}
 }) // 产品模板
-const genereditForm = ref({}) // 编辑表单
+const genereditForm = ref<any>({}) // 编辑表单
 const generateFormKey = ref(1)
 
 // 方法定义

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/type.d.ts

@@ -4,7 +4,7 @@ interface filterProductFormType {
     productCode: string,
     pageIndex: number,
     pageSize: number,
-    type: string | number,
+    productType: string | number,
     id: string | number,
     startTime: string,
     endTime: string,

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/role/index.vue

@@ -65,7 +65,7 @@
       :before-close="handleClose">
       <div class="permissionsData">
         <div v-for="(item, index) in permissionsData" :key="index" class="list">
-          <div class="itemName">
+          <div class="itemName" v-if="item.name.indexOf('详情') == -1">
             <el-checkbox size="large" v-model="item.checked" style="width: 16px; font-weight: bold;"
               @change="changeCheckBox(item, true)">{{ item.name }}</el-checkbox>
           </div>

+ 8 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/api.ts

@@ -7,3 +7,11 @@ export const GET_ADDDEPT = '/department/add'
 export const DETELE_DEPT = '/department/delete'
 export const ADD_USER = '/user/insertUser'
 export const GET_USERINFO = '/user/getUserInfo'
+export const BACTHUPDATEDEPT = `/user/batchUpdateDept`
+export const BACTHUPDATEROLE = `/user/batchUpdateRole`
+export const BACTHSERROLE = `/user/setActiveByIds`
+export const SETRESETPWD = `/user/resetPwd`
+export const DEACTIVEUSER = `/user/deactiveUser`
+export const SETACTIVE = `/user/setActive`
+export const EXPOERTUSER = `/user/exportUsers`
+export const URL_IMPORTUSER = `/user/importUser`

+ 276 - 48
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="h-full flex flex-col teamstyle">
+  <div class="h-full flex flex-col teamstyle overflow-hidden">
     <!-- 头部 -->
     <div class="bg-white flex justify-between team-header">
       <div class="flex items-center">
@@ -10,7 +10,8 @@
         <span class="textSpan">共 0 人</span>
       </div>
       <div class="teamForm flex items-center">
-        <el-input v-model="teamForm.keyword" style="max-width: 650px" size="default" placeholder="请输入姓名搜索" class="mr-6">
+        <el-input v-model="teamForm.keyword" style="max-width: 650px" size="default" placeholder="请输入姓名搜索" class="mr-6"
+          clearable @clear="getTableData()" @keyup.enter.native="getTableData()">
           <template #prepend>
             <el-select v-model="teamForm.matchingType" style="width: 80px">
               <el-option label="姓名" :value="0" />
@@ -19,19 +20,21 @@
             </el-select>
           </template>
           <template #append>
-            <el-button :icon="Search" />
+            <el-button :icon="Search" @click="getTableData()" />
           </template>
         </el-input>
 
         <div class="formItem mr-6 flex items-center">
           <div class="text-nowrap">状态:</div>
-          <el-select v-model="teamForm.status" placeholder="请选择" size="default" style="width: 100px">
+          <el-select v-model="teamForm.status" placeholder="请选择" size="default" style="width: 100px"
+            @change="getTableData()">
             <el-option v-for="item in stateOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </div>
         <div class="formItem mr-6 flex items-center">
           <div class="text-nowrap">角色:</div>
-          <el-select v-model="teamForm.roleId" placeholder="请选择" size="default" style="width: 150px">
+          <el-select v-model="teamForm.roleId" placeholder="请选择" size="default" style="width: 150px" clearable
+            @change="getTableData()">
             <el-option v-for="item in roleList" :key="item.id" :label="item.rolename" :value="item.id" />
           </el-select>
         </div>
@@ -42,11 +45,9 @@
           </el-button>
           <template #dropdown>
             <el-dropdown-menu>
-              <el-dropdown-item @click="addPersone(false)">添加人员</el-dropdown-item>
-              <el-dropdown-item>导出人员</el-dropdown-item>
-              <el-dropdown-item>批量导入</el-dropdown-item>
-              <el-dropdown-item>导入薪资</el-dropdown-item>
-              <el-dropdown-item>自定义配置</el-dropdown-item>
+              <el-dropdown-item @click="addPersone(false)" v-permission="['teamAdd']">添加人员</el-dropdown-item>
+              <el-dropdown-item @click="transitionOperation('exportUser', '')" v-permission="['teamExport']">导出人员</el-dropdown-item>
+              <el-dropdown-item @click="transitionOperation('importUser', '')" v-permission="['teamImport']">批量导入</el-dropdown-item>
             </el-dropdown-menu>
           </template>
         </el-dropdown>
@@ -54,7 +55,7 @@
     </div>
     <!-- 内容 -->
     <div class="flex-1 flex">
-      <div class="p-5 w-80 pr-0">
+      <div class="p-4 w-80 pr-0">
         <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col">
           <div class="flex-1 overflow-y-auto const-left">
             <el-tree style="max-width: 600px" :data="deptList" :props="treeProps" @node-click="treeNode">
@@ -75,45 +76,53 @@
           </div>
         </div>
       </div>
-      <div class="flex-1 p-5 overflow-auto">
-        <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col">
-          <div class="flex-1 p-3">
+      <div class="flex-1 p-4 overflow-auto">
+        <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col overflow-hidden pt-2 pl-2 pr-2">
+          <div class="flex-1">
             <el-table ref="multipleTableRef" :data="tableData" v-loading="loadingFrom.tableLoading"
-              style="width: 100%;height: 100%;">
+              @selection-change="changeBatch" style="width: 100%;height: 100%;">
               <el-table-column type="selection" width="55" />
               <el-table-column label="姓名" property="name" width="150"></el-table-column>
-              <el-table-column label="手机" property="phone" ></el-table-column>
+              <el-table-column label="手机" property="phone"></el-table-column>
               <el-table-column label="工号" property="jobNumber"></el-table-column>
               <el-table-column label="部门" property="departmentName"></el-table-column>
               <el-table-column label="角色" property="roleName"></el-table-column>
               <el-table-column label="创建时间" property="createTime"></el-table-column>
-              <el-table-column label="操作" width="150" fixed="right">
+              <el-table-column label="操作" width="200" fixed="right">
                 <template #default="scope">
-                  <el-button :size="'small'">重置</el-button>
+                  <el-button :size="'small'" @click="resetPwd(scope.row)">重置</el-button>
                   <el-button type="primary" :size="'small'" @click="addPersone(scope.row)">编辑</el-button>
+                  <el-button :size="'small'" @click="transitionOperation('disable', scope.row)"
+                    v-if="scope.row.isActive == 1">停用</el-button>
+                  <el-button type="success" :size="'small'" @click="enableUser(scope.row)"
+                    v-if="scope.row.isActive == 0">启用</el-button>
                 </template>
               </el-table-column>
             </el-table>
           </div>
-          <div class="flex items-center justify-between p-3 bg-slate-100">
+          <div class="flex justify-between pb-2 pt-2 pl-3 pr-3">
             <div class="flex">
-              <el-button size="default">取消</el-button>
+              <el-button size="default" @click="changeBatch(false)"
+                :disabled="batchTableData.length == 0">取消</el-button>
               <el-dropdown class="ml-3">
                 <el-button type="primary">
                   更多操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
                 </el-button>
                 <template #dropdown>
                   <el-dropdown-menu>
-                    <el-dropdown-item>批量修改部门</el-dropdown-item>
-                    <el-dropdown-item>批量修改角色</el-dropdown-item>
-                    <el-dropdown-item>修正工时所属部门</el-dropdown-item>
-                    <el-dropdown-item>批量启用员工</el-dropdown-item>
+                    <el-dropdown-item @click="batchItem('批量修改部门', 'dept', deptList)"
+                      :disabled="batchTableData.length == 0">批量修改部门</el-dropdown-item>
+                    <el-dropdown-item @click="batchItem('批量修改角色', 'role', roleList)"
+                      :disabled="batchTableData.length == 0">批量修改角色</el-dropdown-item>
+                    <el-dropdown-item @click="batchEnableItem"
+                      :disabled="batchTableData.length == 0">批量启用员工</el-dropdown-item>
                   </el-dropdown-menu>
                 </template>
               </el-dropdown>
             </div>
             <div class="pr-4">
-              <el-pagination layout="total, prev, pager, next, sizes" :total="totalTable" :hide-on-single-page="true" />
+              <el-pagination layout="total, prev, pager, next, sizes" :total="totalTable" :page-size="teamForm.pageSize"
+                @size-change="handleSizeChange" @current-change="handleCurrentChange" />
             </div>
           </div>
         </div>
@@ -121,10 +130,21 @@
     </div>
 
     <!-- 新增部门 -->
-    <el-dialog v-model="dialogFrom.addDeptDialogVisible" :title="deptListItem.label || '创建部门'" width="500"
-      :before-close="handleClose">
-      <div>
-        <el-form ref="deptRuleFormRef" style="max-width: 500px" :model="deptForm" :rules="deptRules" label-width="auto"
+    <el-dialog v-model="dialogFrom.addDeptDialogVisible" width="600" :show-close="false" :before-close="handleClose">
+      <template #header="{ close, titleId, titleClass }">
+        <div class="flex justify-between items-center border-b pb-3 dialog-header">
+          <h4 :id="titleId">{{ deptListItem.label || '创建部门' }}</h4>
+          <div class="flex">
+            <el-button @click="dialogFrom.addDeptDialogVisible = false">取消</el-button>
+            <el-button type="primary" @click="createDepartment(deptRuleFormRef)"
+              v-bind:loading="loadingFrom.deptDialogVisibleLoading">
+              确定
+            </el-button>
+          </div>
+        </div>
+      </template>
+      <div class="pt-5">
+        <el-form ref="deptRuleFormRef" style="max-width: 500px" :model="deptForm" :rules="deptRules" label-width="140px"
           size="large" status-icon>
           <el-form-item label="部门名称" prop="name">
             <el-input v-model="deptForm.name" placeholder="请输入部门名称" clearable />
@@ -141,15 +161,75 @@
           </el-form-item>
         </el-form>
       </div>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="dialogFrom.addDeptDialogVisible = false">取消</el-button>
-          <el-button type="primary" @click="createDepartment(deptRuleFormRef)"
-            v-bind:loading="loadingFrom.deptDialogVisibleLoading">
-            确定
-          </el-button>
+    </el-dialog>
+
+    <!-- 停用 -->
+    <el-dialog v-model="dialogFrom.resignationVisible" width="600" :show-close="false" :before-close="handleClose">
+      <template #header="{ close, titleId, titleClass }">
+        <div class="flex justify-between items-center border-b pb-3 dialog-header">
+          <h4 :id="titleId">离职停用员工</h4>
+          <div class="flex">
+            <el-button @click="dialogFrom.resignationVisible = false">取消</el-button>
+            <el-button type="primary" @click="resignation" v-bind:loading="loadingFrom.resignationLoading">
+              确定
+            </el-button>
+          </div>
         </div>
       </template>
+      <div class="pt-4 pb-2">
+        <div class="flex items-center justify-center">
+          <div class="pr-2">员工离职日期:</div>
+          <el-date-picker v-model="resignationDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD"
+            :clearable="false" />
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 导出人员列表 -->
+    <el-dialog v-model="dialogFrom.exportUserVisible" width="600" :show-close="false" :before-close="handleClose">
+      <template #header="{ close, titleId, titleClass }">
+        <div class="flex justify-between items-center border-b pb-3 dialog-header">
+          <h4 :id="titleId">导出人员列表</h4>
+          <div class="flex">
+            <el-button @click="dialogFrom.exportUserVisible = false">取消</el-button>
+            <el-button type="primary" @click="exportUser" v-bind:loading="loadingFrom.exportUserLoading">
+              导出
+            </el-button>
+          </div>
+        </div>
+      </template>
+      <div class="pt-4 pb-2">
+        <div class="flex items-center justify-center">
+          <div class="pr-2">导出:</div>
+          <el-radio-group v-model="exportRadio" class="ml-4">
+            <el-radio value="1" size="large">全部人员</el-radio>
+            <el-radio value="0" size="large">仅在职人员</el-radio>
+          </el-radio-group>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 人员导入 -->
+    <el-dialog v-model="dialogFrom.importVisible" width="680" :show-close="false" top="10vh">
+      <template #header="{ close, titleId, titleClass }">
+        <div class="flex justify-between items-center border-b pb-3 dialog-header">
+          <h4 :id="titleId">人员批量导入</h4>
+          <div class="flex">
+            <el-button class="mr-3" @click="dialogFrom.importVisible = false">取消</el-button>
+            <el-upload ref="importUserRef" class="upload-demo" :limit="1" :show-file-list="false" accept=".xlsx"
+              :http-request="importUser">
+              <el-button type="primary" :loading="loadingFrom.importLoading">导入</el-button>
+            </el-upload>
+          </div>
+        </div>
+      </template>
+      <div class="p-8">
+        <div class="ml-4 mr-4">
+          <div class="flex items-center">1、点击下载 <el-link type="primary"
+              @click="downloadFile('/upload/人员导入模板.xlsx', '人员导入模板.xlsx')">人员导入模板.xlsx</el-link></div>
+          <div class="mt-4">2、填写excel模板,并上传</div>
+        </div>
+      </div>
     </el-dialog>
 
     <!-- 新增人员 -->
@@ -159,21 +239,28 @@
       roleList: roleList,
       personnelFromData: personnelFromData
     }" @closeModal="closeModal" @personnelModalConfirm="personnelModalConfirm" />
+
+    <!-- 批量操作 -->
+    <BatchOperation :batchData="visibleData" :batchNode="batchTableData" :visibleText="allText.batchText"
+      :popup="visibleType" :batchOperationVisible="dialogFrom.batchOperationVisible" @close="closeModal" />
   </div>
 </template>
 
 <script lang="ts" setup>
 import { ref, reactive, onMounted, onBeforeMount, inject } from 'vue';
-import { dayjs } from 'element-plus'
+import { UploadRequestOptions, dayjs } from 'element-plus'
 import { Search, CirclePlusFilled, Edit, CirclePlus, Delete } from '@element-plus/icons-vue'
 import { FormInstance, FormRules, ElMessageBox } from 'element-plus'
 import { useStore } from '@/store/index'
-import { GET_DATA_LIST, DETELE_DEPT, MOD, GET_USERINFO, GET_ROUTELIST, GET_DEPTLIST, GET_USERLIST, GET_ADDDEPT, ADD_USER } from './api'
-import { post } from "@/utils/request";
-import { getFromValue, updateDepTreeData, resetFromValue } from '@/utils/tools'
+import { GET_DATA_LIST, DETELE_DEPT, MOD, GET_USERINFO, GET_ROUTELIST, DEACTIVEUSER, SETACTIVE, GET_DEPTLIST, BACTHSERROLE, GET_USERLIST, GET_ADDDEPT, ADD_USER, SETRESETPWD, EXPOERTUSER } from './api'
+import { post, uploadFile } from "@/utils/request";
+import { getFromValue, updateDepTreeData, resetFromValue, confirmAction, downloadFile } from '@/utils/tools'
 
 // 导入页面
 import AddPersonnelModal from './module/AddPersonnelModal.vue'
+import BatchOperation from './module/BatchOperation.vue'
+import { formatDate } from '@/utils/times';
+import { URL_IMPORTTHREAD } from '../thread/constant';
 
 const { getFunctionList, getUserInfoVal } = useStore()
 const globalPopup = inject<GlobalPopup>('globalPopup')
@@ -190,24 +277,44 @@ interface deptRuleForm { // 部门表单类型
 // 固定数据
 const stateOptions = [{ value: '3', label: '全部' }, { value: '1', label: '在职' }, { value: '0', label: '停用' }]
 
+// ref
+const importUserRef = ref<any>()
+
 // 定义变量
+const transitiondata = ref<any>() // 过度数据(针对二次弹窗)
 const pagePermission: any = ref([]) // 功能权限
 const loadingFrom = reactive({ // 所有加载状态
   tableLoading: false,
-  deptDialogVisibleLoading: false
+  deptDialogVisibleLoading: false,
+  resignationLoading: false,
+  exportUserLoading: false,
+  importLoading: false
 })
 const dialogFrom: any = reactive({ // 所有弹窗状态
   addDeptDialogVisible: false,
-  addPersonnelDialogVisible: false
+  addPersonnelDialogVisible: false,
+  batchOperationVisible: false,
+  resignationVisible: false,
+  exportUserVisible: false,
+  importVisible: false,
 });
+const allText = reactive({
+  batchText: '批量操作'
+})
+const visibleType = ref<batchOperationType>('dept') // 弹窗类型
+const visibleData = ref<any>([]) // 批量弹窗数据源
 const totalTable = ref(0) // 表格总数
 const tableData: any = ref([]) // 表格数据
 const roleList: any = ref([]) // 角色列表
 const userList: any = ref([]) // 用户列表
 const deptList: any = ref([]) // 部门数据
+const batchTableData: any = ref([]) // 批量数据
+const multipleTableRef: any = ref()
 const deptListUntreated: any = ref([]) // 部门数据(未处理)
 const deptListItem: any = ref({}) // 选中的部门数据
 const personnelFromData = ref({}) // 人员表单数据
+const resignationDate = ref(formatDate(new Date())) // 员工离职日期
+const exportRadio = ref('1') // 导出人员列表
 const teamForm = reactive({ // 筛选条件表单
   matchingType: 0,
   keyword: '',
@@ -237,17 +344,99 @@ const deptRules = reactive<FormRules<typeof deptForm>>({ // 部门表单校验
 })
 
 // 定义方法
+async function importUser(param: UploadRequestOptions) {
+  loadingFrom.importLoading = true
+  const formData = new FormData();
+  formData.append('file', param.file)
+  const res = await uploadFile(URL_IMPORTTHREAD, formData).finally(() => {
+    importUserRef.value.clearFiles()
+    loadingFrom.importLoading = false
+  })
+  loadingFrom.importLoading = false
+  if (res.code == 'ok') {
+    globalPopup?.showSuccess('导入成功' || '')
+    closeModal('importVisible')
+    getTableData()
+    return
+  }
+  globalPopup?.showError(res.msg || '')
+}
+
+function exportUser() {
+  loadingFrom.exportUserLoading = true
+  post(EXPOERTUSER, { containInvalid: exportRadio.value }).then((res) => {
+    downloadFile(`${res.data}`, '人员列表.xlsx')
+    globalPopup?.showSuccess('导出成功')
+    closeModal('exportUserVisible')
+  }).finally(() => {
+    loadingFrom.exportUserLoading = false
+  })
+}
+
+function enableUser(row: any) {
+  const id = row.id
+  post(SETACTIVE, { id, isActive: 1 }).then(() => {
+    globalPopup?.showSuccess('启用成功')
+    getTableData()
+  })
+}
+
+function resignation() {
+  const id = transitiondata.value.id || ''
+  loadingFrom.resignationLoading = true
+  post(DEACTIVEUSER, { id, inactiveDate: resignationDate.value }).then(() => {
+    globalPopup?.showSuccess('停用成功')
+    getTableData()
+    closeModal('resignationVisible')
+  }).finally(() => {
+    loadingFrom.resignationLoading = false
+  })
+}
+
+function resetPwd(row: any) {
+  const userId = row.id
+  confirmAction(`确定要为${row.name}重置密码吗?`, '重置密码').then(() => {
+    post(SETRESETPWD, { userId }).then(() => {
+      globalPopup?.showSuccess('密码已重置为000000,请通知员工及时修改')
+    }).catch((err) => {
+      globalPopup?.showError(err.msg)
+    })
+  })
+}
+
+function batchEnableItem() {
+  const userIds = batchTableData.value.map((item: any) => item.id)
+  post(BACTHSERROLE, { ids: JSON.stringify(userIds), isActive: 1 }).then(() => {
+    globalPopup?.showSuccess('操作成功')
+    changeBatch(false)
+    getTableData()
+  }).catch((err) => {
+    globalPopup?.showError(err.msg)
+  })
+}
+
+function changeBatch(flag: boolean = true) {
+  if (flag) {
+    batchTableData.value = multipleTableRef.value && multipleTableRef.value.getSelectionRows()
+  } else {
+    batchTableData.value = []
+    multipleTableRef.value && multipleTableRef.value.clearSelection()
+  }
+}
+
 function addPersone(item: any) {
   console.log(item)
-  if(!item) {
+  if (!item) {
+    personnelFromData.value = {}
     dialogFrom.addPersonnelDialogVisible = true
     return
-  } 
+  }
   post(GET_USERINFO, { userId: item.id }).then(res => {
     const { id, name, phone, jobNumber, roleId, departmentCascade, inductionDate } = res.data
-    let newData = { id, name, phone, jobNumber, roleId, departmentId: 
-      departmentCascade && departmentCascade.split(',').map(Number).reverse(), 
-      inductionDate 
+    let newData = {
+      id, name, phone, jobNumber, roleId, departmentId:
+        departmentCascade && departmentCascade.split(',').map(Number).reverse(),
+      inductionDate
     }
     personnelFromData.value = newData
     dialogFrom.addPersonnelDialogVisible = true
@@ -382,17 +571,54 @@ function dialogFromCli(type: string, data: any = {}, flag: boolean = false) {
   dialogFrom[type] = true
 }
 
+function handleSizeChange(val: number) {
+  teamForm.pageIndex = 1
+  teamForm.pageSize = val
+  getTableData()
+}
+
+function handleCurrentChange(val: number) {
+  teamForm.pageIndex = val
+  getTableData()
+}
+
 function resetDialog() {
   let newDeptForm = resetFromValue(deptForm)
   Object.assign(deptForm, newDeptForm)
 }
 
+function batchItem(text: string, type: batchOperationType, data: any) {
+  allText.batchText = text,
+    visibleType.value = type
+  visibleData.value = data
+  dialogFrom.batchOperationVisible = true
+}
+
 function handleClose(done: any) {
   done()
 }
 
-function closeModal(modelType: string) {
+function transitionOperation(type: string, data: any) {
+  if (type == 'disable') { // 停用
+    resignationDate.value = formatDate(new Date())
+    console.log(resignationDate.value, '<==== 离职')
+    dialogFrom.resignationVisible = true
+  } else if (type == 'exportUser') { // 导出
+    exportRadio.value = '1'
+    dialogFrom.exportUserVisible = true
+  } else if (type == 'importUser') { // 导入
+    dialogFrom.importVisible = true
+  }
+
+  transitiondata.value = data
+}
+
+function closeModal(modelType: string, flag: boolean = false) {
   dialogFrom[modelType] = false
+  if (flag) {
+    changeBatch(false)
+    getTableData()
+  }
 }
 
 onBeforeMount(() => {
@@ -411,6 +637,7 @@ onMounted(() => {
 .teamstyle {
   .team-header {
     padding: 0.75rem 1.25rem;
+    box-sizing: border-box
   }
 
   .textFont {
@@ -449,6 +676,7 @@ onMounted(() => {
     }
   }
 }
+
 .operation {
   cursor: pointer;
 }

+ 18 - 15
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/AddPersonnelModal.vue

@@ -1,8 +1,19 @@
 <template>
-    <el-dialog v-model="data.addPersonnelDialogVisible" :title="'添加人员'" width="500" :before-close="handleClose">
-        <div>
+    <el-dialog v-model="data.addPersonnelDialogVisible" :title="'添加人员'" :show-close="false" width="600" :before-close="handleClose">
+        <template #header="{ close, titleId, titleClass }">
+            <div class="flex justify-between items-center border-b pb-3 dialog-header">
+                <h4 :id="titleId">添加/编辑人员</h4>
+                <div class="flex">
+                    <el-button @click="handleClose">取消</el-button>
+                    <el-button type="primary" @click="addPersonel(personnelRuleFormRef)">
+                        确定
+                    </el-button>
+                </div>
+            </div>
+        </template>
+        <div class="pt-5">
             <el-form ref="personnelRuleFormRef" style="max-width: 500px" :model="personnelFrom" :rules="personnelRules"
-                label-width="auto" size="large" status-icon>
+                label-width="120px" size="large" status-icon>
                 <el-form-item label="姓名" prop="name">
                     <el-input v-model="personnelFrom.name" placeholder="请输入姓名" clearable />
                 </el-form-item>
@@ -24,15 +35,7 @@
                     <el-date-picker v-model="personnelFrom.inductionDate" type="date" placeholder="选择入职时间" value-format="YYYY-MM-DD" style="width: 100%" />
                 </el-form-item>
             </el-form>
-        </div>
-        <template #footer>
-            <div class="dialog-footer">
-                <el-button @click="handleClose">取消</el-button>
-                <el-button type="primary" @click="addPersonel(personnelRuleFormRef)">
-                    确定
-                </el-button>
-            </div>
-        </template>
+        </div> 
     </el-dialog>
 </template>
 <script setup lang="ts">
@@ -67,7 +70,7 @@ const data = ref<Props['data']>({
     personnelFromData: {}
 })
 const personnelRuleFormRef = ref<FormInstance>() // 表单实例
-const personnelFrom = reactive<personnelFromType>({ // 填写的内容
+const personnelFrom = ref<personnelFromType>({ // 填写的内容
     id: '',
     name: '',
     phone: '',
@@ -88,7 +91,7 @@ const personnelRules = reactive<FormRules<typeof personnelFrom>>({ // 部门表
 // 定义方法
 function addPersonel(formEl: FormInstance | undefined) {
     if (!formEl) return
-    let dataForm = getFromValue(personnelFrom)
+    let dataForm = getFromValue(personnelFrom.value)
     const { departmentId } = dataForm
     emit('personnelModalConfirm', { ...dataForm, departmentId: departmentId && departmentId[departmentId.length - 1]  }, 'addPersonnelDialogVisible')
 }
@@ -96,7 +99,7 @@ function addPersonel(formEl: FormInstance | undefined) {
 // 监听 Props 的变化
 watch(() => props.data, (newValue) => {
     data.value = newValue
-    Object.assign(personnelFrom, newValue.personnelFromData)
+    personnelFrom.value = newValue.personnelFromData
 });
 
 const handleClose = () => {

+ 100 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/BatchOperation.vue

@@ -0,0 +1,100 @@
+<template>
+    <el-dialog v-model="props.batchOperationVisible" width="800px" :show-close="false" :close-on-click-modal="false"
+        top="10vh">
+        <template #header="{ titleId, titleClass }">
+            <div class="flex justify-between items-center border-b pb-3">
+                <h4 :id="titleId">{{ '批量操作' }}</h4>
+                <div>
+                    <el-button @click="cancel">取消</el-button>
+                    <el-button type="primary" @click="confirm" v-loading="confirmloading">确认</el-button>
+                </div>
+            </div>
+        </template>
+        <div class="pt-4 pb-2">
+            <template v-if="props.popup == 'dept'">
+                <div class="w-full flex items-center">
+                    <div class="w-[100px] text-right">设置部门:</div>
+                    <div class="flex-1 pl-3">
+                        <el-cascader v-model="bindingVal" :options="props.batchData" class="w-full"
+                            :props="cascaderProps" />
+                    </div>
+                </div>
+            </template>
+            <template v-if="props.popup == 'role'">
+                <div class="w-full flex items-center">
+                    <div class="w-[100px] text-right">设置角色:</div>
+                    <div class="flex-1 pl-3">
+                        <el-select v-model="bindingVal" placeholder="请选择" class="w-full" filterable>
+                            <el-option v-for="item in props.batchData" :key="item.id" :label="item.rolename"
+                                :value="item.id" />
+                        </el-select>
+                    </div>
+                </div>
+            </template>
+        </div>
+    </el-dialog>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+import type { CascaderProps } from 'element-plus'
+import { Props } from './type';
+import { BACTHUPDATEDEPT, BACTHUPDATEROLE } from '../api';
+import { post } from '@/utils/request';
+const props = defineProps<Props>()
+const emits = defineEmits(['close']);
+
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const confirmloading = ref<boolean>(false)
+const cascaderProps = ref<CascaderProps>({
+    value: 'id',
+    expandTrigger: 'hover',
+    checkStrictly: true
+})
+const bindingVal = ref<any>([])
+
+const submitParameters = ref<any>({
+    'dept': {
+        url: BACTHUPDATEDEPT, // 请求地址
+        whether_str: false, // 是否转成字符串
+        filed: 'deptId', // 参数字段
+        param: {}
+    },
+    'role': {
+        url: BACTHUPDATEROLE, // 请求地址
+        whether_str: false, // 是否转成字符串
+        filed: 'roleId', // 参数字段
+        param: {}
+    }
+})
+
+function confirm() {
+    let params = processingParameters()
+    confirmloading.value = true
+    post(params.url, { ...params.param }).then(_res => {
+        globalPopup?.showSuccess('操作成功')
+        cancel()
+    }).catch(err => {
+        globalPopup?.showError(err.msg)
+    }).finally(() => {
+        confirmloading.value = false
+    })
+}
+
+function processingParameters() {
+    let { url, whether_str, filed, param } = submitParameters.value[props.popup]
+    const userIds = props.batchNode.map((item: any) => item.id)
+    let val = bindingVal.value
+    if (Array.isArray(bindingVal.value)) {
+        val = bindingVal.value[bindingVal.value.length - 1]
+    }
+    let rsult = { [filed]: val, userIds: !whether_str ? JSON.stringify(userIds) : userIds.join(',') }
+    return { url, param: { ...param, ...rsult } }
+}
+
+function cancel() {
+    emits('close', 'batchOperationVisible', true)
+}
+</script>
+
+<style lang="scss"></style>

+ 26 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/type.ts

@@ -0,0 +1,26 @@
+export interface Props {
+    /**
+     *  弹窗是否显示
+     */
+    batchOperationVisible: boolean;
+    /**
+     * 弹窗标题
+     */
+    visibleText: String;
+    /**
+     * 弹窗类型
+     */
+    popup: batchOperationType;
+    /**
+     * 数据源
+     */
+    batchData: any;
+    /**
+     * 批量节点
+     */
+    batchNode: any[]
+    /**
+     * 其他配置
+     */
+    otherConfig?: any;
+  }

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/type.d.ts

@@ -0,0 +1 @@
+type batchOperationType = 'dept' | 'role'

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue

@@ -101,7 +101,7 @@
         <div class="flex justify-between items-center border-b pb-3 dialog-header">
           <h4 :id="titleId">{{ allText.editClueText }}</h4>
           <div>
-            <el-button type="primary" :loading="allLoading.clueSaveLoading" @click="saveEditClue(true)">保存并新建</el-button>
+            <el-button type="primary" v-if="!editForm.id" :loading="allLoading.clueSaveLoading" @click="saveEditClue(true)">保存并新建</el-button>
             <el-button type="primary" :loading="allLoading.clueSaveLoading" @click="saveEditClue(false)">保存</el-button>
             <el-button @click="dialogVisible.editClueDialogVisible = false">取消</el-button>
           </div>
@@ -247,7 +247,7 @@ const clueTemplate = ref({
   list: [],
   config: {}
 }) // 线索模板
-const editForm = ref({}) // 编辑表单
+const editForm = ref<any>({}) // 编辑表单
 const taskModalForm = ref({}) // 任务弹窗表单
 const batchTableData = ref([])
 

+ 3 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/dto/TaskDto.java

@@ -24,5 +24,8 @@ public class TaskDto extends Task {
     private String clueName;
     private String phone;
 
+    private Integer departmentId;
+    private String departmentIdByMyselfOrNull;
+
 
 }

+ 25 - 4
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContactsServiceImpl.java

@@ -12,6 +12,7 @@ import com.management.platform.entity.vo.ContactsVo;
 import com.management.platform.mapper.*;
 import com.management.platform.service.ContactsService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.service.SysFunctionService;
 import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
@@ -78,6 +79,9 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
     @Resource
     private ExcelExportServiceImpl excelExportService;
 
+    @Resource
+    private SysFunctionService sysFunctionService;
+
     @Resource
     private StageMapper stageMapper;
 
@@ -137,6 +141,11 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
 
     @Override
     public HttpRespMsg pageContacts(Integer pageIndex, Integer pageSize, Integer customId, String name, String email, String creatorId, String phone, String ownerId, HttpServletRequest request) {
+        String token = String.valueOf(request.getHeader("Token"));
+        User user = userMapper.selectById(token);
+        boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部联系人");
+        boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门联系人");
+
         Map<String, Object> map = new HashMap<>();
         map.put("customId", customId);
         map.put("name", name);
@@ -144,10 +153,21 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
         map.put("ownerId", ownerId);
         map.put("email", email);
         map.put("creatorId", creatorId);
-        String token = String.valueOf(request.getHeader("Token"));
-        User user = userMapper.selectById(token);
         map.put("companyId", user.getCompanyId());
         map.put("isDelete", 0);
+
+
+        if (isAll){
+            System.out.println("do nothing");
+        }else if (isNotAll){
+            Integer departmentId = user.getDepartmentId();//找出对应的部门id
+            map.put("departmentId",departmentId);
+        }else {
+            //查看负责人为自己和null的数据
+            map.put("ownerIdByMyselfAndNull",user.getId());
+
+        }
+
         Page<ContactsVo> pageContacts = contactsMapper.pageContacts(new Page((long) (pageIndex - 1) *pageSize, pageSize), map);
 
         List<ContactsVo> records = pageContacts.getRecords();
@@ -516,7 +536,7 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
                     Method method = contactsClass.getMethod(setter, type);
                     //校验当前列是否为必填
                     if(requiredList.get(i)){
-                        if(StringUtils.isEmpty(cell.getStringCellValue())){
+                        if(cell==null || StringUtils.isEmpty(cell.getStringCellValue())){
                             msg.setError(labelList.get(i)+"值不能为空值");
                             return msg;
                         }
@@ -561,7 +581,7 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
                             }
                         }
                     }else{
-                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                        if(cell!=null && !StringUtils.isEmpty(cell.getStringCellValue())){
                             System.out.println(cell.getStringCellValue());
                             method.invoke(contacts,cell.getStringCellValue());
                         }
@@ -621,6 +641,7 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
         dataList.add(titleList);
 
         Map<String, Object> map = new HashMap<>();
+        map.put("isDelete", 0);
         map.put("customName", customName);
         map.put("name", name);
         map.put("phone", phone);

+ 1 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SysFormServiceImpl.java

@@ -93,7 +93,7 @@ public class SysFormServiceImpl extends ServiceImpl<SysFormMapper, SysForm> impl
         switch (code){
             case "Thread":title = company.getCompanyName()+"_线索导入模板";
             break;
-            case "Custom":title = company.getCompanyName()+"_客户导入模板";
+            case "Customer":title = company.getCompanyName()+"_客户导入模板";
                 break;
             case "Order":title = company.getCompanyName()+"_订单导入模板";
                 break;

+ 89 - 70
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java

@@ -33,6 +33,7 @@ import java.io.*;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.text.SimpleDateFormat;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -61,6 +62,9 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
     @Resource
     private TaskExecutorMapper taskExecutorMapper;
 
+    @Resource
+    private SysFunctionService sysFunctionService;
+
     @Resource
     private TaskRepeatDesignMapper taskRepeatDesignMapper;
 
@@ -175,6 +179,21 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
         List<TaskExecutor> taskExecutorList = taskExecutorMapper.selectList(new LambdaQueryWrapper<TaskExecutor>().eq(TaskExecutor::getCompanyId,user.getCompanyId()));
         List<TaskLog> taskLogList = taskLogMapper.selectList(new LambdaQueryWrapper<TaskLog>().eq(TaskLog::getCompanyId,user.getCompanyId()).orderByDesc(TaskLog::getModTime));
         taskDto.setPageIndex((taskDto.getPageIndex()-1)*taskDto.getPageSize());
+
+        boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部任务");
+        boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门任务");
+
+        if (isAll){
+            System.out.println("do nothing");
+        }else if (isNotAll){
+            Integer departmentId = user.getDepartmentId();//找出对应的部门id
+            taskDto.setDepartmentId(departmentId);
+        }else {
+            //查看负责人为自己和null的数据
+            taskDto.setDepartmentIdByMyselfOrNull(user.getId());
+
+        }
+
         List<TasKVo> taskVoList =taskMapper.getPageListTask(taskDto);
         for (TasKVo tasKVo : taskVoList) {
             if (!taskExecutorList.isEmpty()){
@@ -324,6 +343,37 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
             JSONObject configOb = JSON.parseObject(config);
             JSONArray configObJSONArray = configOb.getJSONArray("list");
 
+            //可能存在栅格布局的情况需要特殊处理
+            List<String> modelNameList=new ArrayList<>();
+            List<String> typeList=new ArrayList<>();
+            List<String> labelList=new ArrayList<>();
+            List<Boolean> requiredList=new ArrayList<>();
+
+            for (int i = 0; i < configObJSONArray.size(); i++) {
+                JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                if(jsonObject.getString("type").equals("grid")){
+                    JSONArray columns = jsonObject.getJSONArray("columns");
+                    for (int i1 = 0; i1 < columns.size(); i1++) {
+                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
+                        JSONArray list = columnsJSONObject.getJSONArray("list");
+                        for (int i2 = 0; i2 < list.size(); i2++) {
+                            JSONObject object = list.getJSONObject(i2);
+                            modelNameList.add(object.getString("model"));
+                            typeList.add(object.getString("type"));
+                            labelList.add(object.getString("label"));
+                            Boolean required = object.getJSONObject("options").getJSONObject("rules").getBoolean("required");
+                            requiredList.add(required);
+                        }
+                    }
+                }else {
+                    modelNameList.add(jsonObject.getString("model"));
+                    typeList.add(jsonObject.getString("type"));
+                    labelList.add(jsonObject.getString("label"));
+                    Boolean required = jsonObject.getJSONObject("options").getJSONObject("rules").getBoolean("required");
+                    requiredList.add(required);
+                }
+            }
+
             List<Task>  importTaskList=new ArrayList<>();
             List<String> userNameList=new ArrayList<>();
             HttpRespMsg respMsg=new HttpRespMsg();
@@ -347,19 +397,8 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                 int cellNum = row.getLastCellNum();
 
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
-                    String modelName = item.getString("model");
+                    String modelName = modelNameList.get(i);
                     XSSFCell cell = row.getCell(i);
-/*                    if(cell!=null&&StringUtils.isNotEmpty(cell.getStringCellValue())){
-                        switch (item.getString("type")){
-                            case "time":cell.setCellType(CellType.NUMERIC);
-                                System.out.println(cell.getNumericCellValue());
-                                break;
-                            case "int":cell.setCellType(CellType.NUMERIC);
-                                break;
-                            default:cell.setCellType(CellType.STRING);
-                        }
-                    }*/
                     if(modelName.equals("executorId")){
                         if(!StringUtils.isEmpty(cell.getStringCellValue())){
                             List<String> executorNames = new ArrayList<>();
@@ -405,19 +444,13 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                 task.setStatus(0);
                 task.setIsDelete(0);
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
-                    String modelName = item.getString("model");
+                    String modelName = modelNameList.get(i);
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
                     String getter="get"+className;
                     String setter="set"+className;
                     XSSFCell cell = row.getCell(i);
                     if(cell!=null&&StringUtils.isNotEmpty(cell.getStringCellValue())){
-                        switch (item.getString("type")){
-                            case "time":cell.setCellType(CellType.NUMERIC);
-                                System.out.println(cell.getNumericCellValue());
-                                break;
-                            case "int":cell.setCellType(CellType.NUMERIC);
-                                break;
+                        switch (typeList.get(i)){
                             default:cell.setCellType(CellType.STRING);
                         }
                     }
@@ -425,25 +458,14 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
 //                    Field field = taskClass.getDeclaredField(modelName);
 //                    Class<?> type = field.getType();
 //                    Method method = taskClass.getMethod(setter, type);
-                    //校验当前列是否为必填
-                    JSONObject options = item.getJSONObject("options");
-                    JSONObject rules = options.getJSONObject("rules");
-                    Boolean required = rules.getBoolean("required");
-                    if(required){
-                        if(StringUtils.isEmpty(cell.getStringCellValue())){
-                            msg.setError(item.getString("label")+"值不能为空值");
+
+                    if(requiredList.get(i)){
+                        if(cell==null||StringUtils.isEmpty(cell.getStringCellValue())){
+                            msg.setError(labelList.get(i)+"值不能为空值");
                             return msg;
                         }
                     }
-                    /*if(modelName.equals("taskCode")){
-                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
-                            //系统中同公司已存在的产品编码 更新
-                            Optional<Task> first = taskList.stream().filter(p ->p.getTaskCode()!=null&& p.getTaskCode().equals(cell.getStringCellValue())).findFirst();
-                            if(first.isPresent()){
-                                task.setId(first.get().getId());
-                            }
-                        }
-                    }*/
+
                     if(modelName.equals("executorId")){
                         if(cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())){
 
@@ -485,12 +507,12 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
 
 
                     }*/
-                    if(modelName.equals("taskName")){
+                   else if(modelName.equals("taskName")){
                         if(!StringUtils.isEmpty(cell.getStringCellValue())){
                             task.setTaskName(cell.getStringCellValue());
                         }
                     }
-                    if(modelName.equals("priority")){
+                   else if(modelName.equals("priority")){
                         if(cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())){
                             switch (cell.getStringCellValue()){
                                 case "低":task.setPriority(0);
@@ -502,42 +524,24 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                             }
                         }
                     }
-                    if(modelName.equals("startDate")){
+                    else if(modelName.equals("startDate")){
                         if(cell != null && cell.getCellTypeEnum() != CellType.BLANK){
-                            if (cell.getCellTypeEnum() == CellType.NUMERIC){
-                                Date dateCellValue = cell.getDateCellValue();
-                                if (dateCellValue.before(new Date(-2208988800L))){
-                                    continue;
-                                }else {
-                                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                                    String string = format.format(dateCellValue);
-                                    System.out.println(string);
-                                    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-                                    LocalDateTime time = LocalDateTime.parse(string, dateTimeFormatter);
-                                    task.setStartDate(time);
-                                }
+                            if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                                task.setStartDate(LocalDateTime.parse(cell.getStringCellValue(),df));
                             }
                         }
                     }
-                    if(modelName.equals("endDate")){
+                    else if(modelName.equals("endDate")){
                         if(cell != null && cell.getCellTypeEnum() != CellType.BLANK){
-                            if (cell.getCellTypeEnum() == CellType.NUMERIC){
-                                Date dateCellValue = cell.getDateCellValue();
-                                if (dateCellValue.before(new Date(-2208988800L))){
-                                    continue;
-                                }else {
-                                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                                    String string = format.format(dateCellValue);
-                                    System.out.println(string);
-                                    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-                                    LocalDateTime time = LocalDateTime.parse(string, dateTimeFormatter);
-                                    task.setEndDate(time);
-                                }
+                            if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                                task.setEndDate(LocalDateTime.parse(cell.getStringCellValue(),df));
                             }
                         }
                     }
 
-                    if(modelName.equals("contactsId")){
+                    else if(modelName.equals("contactsId")){
                         if(cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())){
                             String contactsName = cell.getStringCellValue();
                             List<Contacts> collect = contactsList.stream().filter(contacts -> contacts.getName().equals(contactsName)).collect(Collectors.toList());
@@ -552,7 +556,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                         }
                     }
 
-                    if(modelName.equals("customId")){
+                    else if(modelName.equals("customId")){
                         if(cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())){
                             String customName = cell.getStringCellValue();
                             List<Custom> customs = customList.stream().filter(custom -> customName.equals(custom.getCustomName())).collect(Collectors.toList());
@@ -567,16 +571,18 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                                     }
                                     else {
                                         task.setCustomId(custom.getId());
+                                        task.setTaskType(0);
                                     }
                                 }else {
                                     task.setCustomId(custom.getId());
+                                    task.setTaskType(0);
                                 }
                             }else {
                                 throw new Exception("["+customName+"]对应的客户不存在");
                             }
                         }
                     }
-                    if (modelName.equals("businessOpportunityId")){
+                    else if (modelName.equals("businessOpportunityId")){
                         if(cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())){
                             String businessName = cell.getStringCellValue();
                             List<BusinessOpportunity> collect = opportunityList.stream().filter(o -> businessName.equals(o.getName())).collect(Collectors.toList());
@@ -589,6 +595,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                                         throw new Exception("["+businessName+"]对应的商机没有对应填写的联系人");
                                     }else {
                                         task.setBusinessOpportunityId(businessOpportunity.getId());
+                                        task.setTaskType(1);
                                     }
                                 }
                             }else {
@@ -597,7 +604,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
 
                         }
                     }
-                    if (modelName.equals("orderId")){
+                    else if (modelName.equals("orderId")){
                         if(cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())){
                             String orderName = cell.getStringCellValue();
                             List<SalesOrder> collect = orderList.stream().filter(order -> orderName.equals(order.getOrderName())).collect(Collectors.toList());
@@ -611,6 +618,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                                     }
                                     else {
                                         task.setOrderId(order.getId());
+                                        task.setTaskType(2);
                                     }
                                 }
                             }else {
@@ -619,7 +627,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                         }
                     }
 
-                    if (modelName.equals("clueId")) {
+                    else if (modelName.equals("clueId")) {
                         if (cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())) {
                             String clueName = cell.getStringCellValue();
                             if (task.getContactsId()!=null){
@@ -629,13 +637,14 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                             if (!collect.isEmpty()) {
                                 Clue clue = collect.get(0);
                                 task.setClueId(clue.getId());
+                                task.setTaskType(3);
                             }else {
                                 throw new Exception("["+clueName+"]对应的线索不存在");
                             }
                         }
                     }
 
-                    if (modelName.equals("phone")) {
+                    else if (modelName.equals("phone")) {
                         if (cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())) {
                             String contactsPhone = cell.getStringCellValue();
                             List<Contacts> collect = contactsList.stream().filter(contacts -> contactsPhone.equals(contacts.getPhone())).collect(Collectors.toList());
@@ -654,6 +663,16 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
 
                         }
                     }
+                    else {
+                        if(cell!=null && !StringUtils.isEmpty(cell.getStringCellValue())){
+                            Class<Task> taskClass = Task.class;
+                            Field field = taskClass.getDeclaredField(modelName);
+                            Class<?> type = field.getType();
+                            Method method = taskClass.getMethod(setter, type);
+                            System.out.println(cell.getStringCellValue());
+                            method.invoke(task,cell.getStringCellValue());
+                        }
+                    }
                 }
                 importTaskList.add(task);
             }

+ 7 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ContactsMapper.xml

@@ -56,7 +56,7 @@
                 AND own.id =#{map.ownerId}
             </if>
             <if test="map.creatorId != null and map.creatorId != ''">
-                AND own.id =#{map.creatorId}
+                AND u.id =#{map.creatorId}
             </if>
             <if test="map.phone != null and map.phone != ''">
                 AND c.phone LIKE CONCAT('%', #{map.phone}, '%')
@@ -70,6 +70,12 @@
             <if test="map.companyId != null">
                 AND c.company_id=#{map.companyId}
             </if>
+            <if test="map.departmentId != null">
+                AND own.department_id=#{map.departmentId}
+            </if>
+            <if test="map.ownerIdByMyselfAndNull != null and map.ownerIdByMyselfAndNull != ''">
+                AND ( own.id=#{map.ownerIdByMyselfAndNull} or own.id is null )
+            </if>
         </where>
         order by create_time desc
 

+ 32 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/TaskMapper.xml

@@ -92,7 +92,7 @@
     </resultMap>
 
     <select id="getPageListTask" resultMap="TaskVoMap">
-        select task.* ,
+        select DISTINCT task.* ,
                custom.custom_name,
                business_opportunity.name businessName,
               `sales_order`.order_name ,
@@ -107,7 +107,12 @@
             <if test=" executorName!= null and executorName != '' " >
                 inner join task_executor on task.id=task_executor.task_id
             </if>
-
+            <if test=" departmentId!= null " >
+            inner join task_executor on task.id=task_executor.task_id
+            </if>
+            <if test=" departmentIdByMyselfOrNull!= null and departmentIdByMyselfOrNull != '' " >
+            inner join task_executor on task.id=task_executor.task_id
+            </if>
         <where>
             and 1=1 and task.is_delete=0
 
@@ -150,6 +155,15 @@
             <if test=" companyId!= null ">
                 AND task.company_id = #{companyId}
             </if>
+            <if test=" departmentId!= null " >
+                AND task_executor.task_id in ( SELECT DISTINCT te.task_id FROM task_executor te
+                LEFT JOIN `user` u ON u.id=te.executor_id
+                where u.department_id = #{departmentId} )
+            </if>
+            <if test=" departmentIdByMyselfOrNull!= null and departmentIdByMyselfOrNull != '' " >
+                AND task_executor.task_id in ( SELECT DISTINCT te.task_id FROM task_executor te
+                where te.executor_id= #{departmentIdByMyselfOrNull } or te.executor_id is null )
+            </if>
 
         </where>
         order by task.create_date desc
@@ -163,7 +177,7 @@
 
 
     <select id="getPageListTotalTask" resultMap="TaskVoMap">
-        select task.id
+        select DISTINCT task.id
         from task
         left join  custom on task.custom_id=custom.id
         left join  business_opportunity on task.business_opportunity_id=business_opportunity.id
@@ -173,6 +187,12 @@
         <if test=" executorName!= null and executorName != '' " >
             inner join task_executor on task.id=task_executor.task_id
         </if>
+        <if test=" departmentId!= null " >
+            inner join task_executor on task.id=task_executor.task_id
+        </if>
+        <if test=" departmentIdByMyselfOrNull!= null and departmentIdByMyselfOrNull != '' " >
+            inner join task_executor on task.id=task_executor.task_id
+        </if>
 
 
         <where>
@@ -217,6 +237,15 @@
             <if test=" companyId!= null ">
                 AND task.company_id = #{companyId}
             </if>
+            <if test=" departmentId!= null " >
+                AND  task_executor.task_id in ( SELECT DISTINCT te.task_id FROM task_executor te
+                LEFT JOIN `user` u ON u.id=te.executor_id
+                where u.department_id = #{departmentId} )
+            </if>
+            <if test=" departmentIdByMyselfOrNull!= null and departmentIdByMyselfOrNull != '' " >
+                AND task_executor.task_id in ( SELECT DISTINCT te.task_id FROM task_executor te
+                where te.executor_id= #{departmentIdByMyselfOrNull} or te.executor_id is null )
+            </if>
         </where>
     </select>
     <select id="getListByTaskIds" resultType="com.management.platform.entity.vo.TasKVo">