Pārlūkot izejas kodu

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

douhl 11 mēneši atpakaļ
vecāks
revīzija
2716c07393
62 mainītis faili ar 12032 papildinājumiem un 38317 dzēšanām
  1. 19 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/components/TaskModal/index.vue
  2. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/components/TaskModal/taskFunction.ts
  3. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/deteleTables.vue
  4. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  5. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/api.ts
  6. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/deteleTables.vue
  7. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/information.vue
  8. 2 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedBusiness.vue
  9. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/detail/index.vue
  10. 12 11
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/index.vue
  11. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/api.ts
  12. 9 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/attachment.vue
  13. 4 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/deteleTables.vue
  14. 22 12
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/information.vue
  15. 9 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/operationRecord.vue
  16. 13 14
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedBusiness.vue
  17. 11 11
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedContacts.vue
  18. 17 16
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedOrders.vue
  19. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/detail/index.vue
  20. 41 19
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/index.vue
  21. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  22. 7 7
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/api.ts
  23. 18 12
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/deteleTables.vue
  24. 33 23
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/information.vue
  25. 2 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/products.vue
  26. 7 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/rebate.vue
  27. 3 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/detail/index.vue
  28. 23 14
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/index.vue
  29. 12 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue
  30. 23 6
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/information.vue
  31. 23 10
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedBusiness.vue
  32. 24 15
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/products.vue
  33. 5 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/detail/index.vue
  34. 18 16
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue
  35. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/type.d.ts
  36. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/register.vue
  37. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/role/index.vue
  38. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/api.ts
  39. 39 17
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/index.vue
  40. 8 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/api.ts
  41. 276 48
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/index.vue
  42. 18 15
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/AddPersonnelModal.vue
  43. 100 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/BatchOperation.vue
  44. 26 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/type.ts
  45. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/type.d.ts
  46. 7 7
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue
  47. 10821 37852
      fhKeeper/formulahousekeeper/management-crm/crm.log
  48. 10 11
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ProductController.java
  49. 40 11
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SalesOrderController.java
  50. 3 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/dto/TaskDto.java
  51. 2 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/SalesOrderService.java
  52. 25 4
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContactsServiceImpl.java
  53. 68 8
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java
  54. 13 11
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java
  55. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SysFormServiceImpl.java
  56. 89 70
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  57. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml
  58. 7 1
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ContactsMapper.xml
  59. 32 3
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/TaskMapper.xml
  60. 20 6
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  61. 43 12
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml
  62. 5 4
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue

+ 19 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/components/TaskModal/index.vue

@@ -33,7 +33,7 @@
           </template>
           <template v-for="item in TASK_TYPE_FIELD">
             <el-select v-model="form[item.field]" v-if="form.taskType == item.type" placeholder="请选择" clearable
-              filterable :disabled="disabledList && disabledList.includes(item.field)">
+              filterable :disabled="disabledList && disabledList.includes(item.field)" @change="(e: any) => {taskFormChange(e, item.field)}">
               <el-option v-for="v in taskTypeValueData" :key="v.id" :value="v[item.valueIndex]"
                 :label="v[item.labelIndex]" />
             </el-select>
@@ -41,7 +41,7 @@
         </el-form-item>
         <el-form-item label="联系人:" v-if="TASK_TYPE.find(v => v.value == (form.taskType || '1'))?.show">
           <el-select v-model="form.contactsId" placeholder="请选择" clearable filterable
-            :disabled="disabledList && disabledList.includes('contactsId')">
+            :disabled="(disabledList && disabledList.includes('contactsId'))">
             <el-option v-for="item in contactValueData" :key="item.id" :value="item.id" :label="item.name" />
           </el-select>
         </el-form-item>
@@ -135,6 +135,7 @@ import { Delete, Plus } from "@element-plus/icons-vue"
 import { FormInstance, dayjs } from 'element-plus';
 import { getFromValue } from '@/utils/tools';
 import { Props, Emits } from './type';
+import { URL_GETALL } from '@/pages/contacts/api';
 const props = defineProps<Props>()
 const emits = defineEmits<Emits>();
 watch(() => props.saveLoading, (val) => {
@@ -214,6 +215,22 @@ const form = ref<any>({});
 const formRef = ref<FormInstance>();
 const generateFormRef = ref<InstanceType<typeof GenerateForm>>();
 const generateFormData = ref<any>({ ...defaultGenerateFormData });
+function taskFormChange(e: any, field: 'customId' | 'businessOpportunityId' | 'orderId' | 'clueId') {
+  const fieldMap = {
+    'customId': 'customerId',
+    'businessOpportunityId': 'businessId',
+    'orderId': 'salesId',
+    'clueId': ''
+  };
+  let fieldStr = fieldMap[field] || '';
+  updateContactPerson(e, fieldStr)
+}
+function updateContactPerson(val: any, field: string) {
+  let formVal = field ? { [field]: val } : {}
+  get(URL_GETALL, { ...formVal }).then(({ data }) => {
+    contactValueData.value = data;//联系人
+  })
+}
 function closeVisible() {
   formRef.value?.resetFields();
   generateFormData.value = { ...defaultGenerateFormData };

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/components/TaskModal/taskFunction.ts

@@ -24,7 +24,7 @@ export async function createTask(submitData: any, isClose: boolean) : Promise<Ta
         post(ADD_TASK, getFromValue(params)).then(() => {
             resolve({ saveLoading: '3', isClose })
         }).catch((err) => {
-            reject({ saveLoading: '4', isClose, message: err.message })
+            reject({ saveLoading: '4', isClose, message: err.msg })
         })
     })
 }

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/deteleTables.vue

@@ -100,7 +100,7 @@ function businessOperationItem(value: string | number, label: string, type: oper
             getTableList()
             changeBatch(false)
         }).catch((err) => {
-            globalPopup?.showError(err.message)
+            globalPopup?.showError(err.msg)
         })
     })
 }

+ 3 - 3
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: {},
@@ -356,7 +356,7 @@ function businessDeteleItem(value: string | number, label: string, batch: boolea
       changeBatch(false)
       getBusinessTableList()
     }).catch((err) => {
-      globalPopup?.showError(err.message)
+      globalPopup?.showError(err.msg)
     })
   })
 }

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/api.ts

@@ -29,7 +29,7 @@ export const actionButtons: any[] = [
 ]
 
 export const tableColumns: TableColumn[] = [
-    { prop: 'name', label: '联系人', event: 'toDetali', width: '150' },
+    { prop: 'name', label: '联系人姓名', event: 'toDetali', width: '150' },
     { prop: 'customName', label: '客户名称', width: '150' },
     { prop: 'phone', label: '电话号码', width: '200' },
     { prop: 'email', label: '邮箱', width: '200' },

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

@@ -89,7 +89,7 @@ function batchOperation(type: operationType) {
 }
 
 function businessOperationItem(value: string | number, label: string, type: operationType, batch: boolean = false) {
-    confirmAction(`确定${batch ? '批量' : ''}${type}【${label}】商机吗?`).then(() => {
+    confirmAction(`确定${batch ? '批量' : ''}${type}【${label}】联系人吗?`).then(() => {
         let url = type == '恢复' ? URL_RESTORE : URL_DETELEITEM
         post(url, { ids: value }).then(res => {
             if (res.code != 'ok') {
@@ -100,7 +100,7 @@ function businessOperationItem(value: string | number, label: string, type: oper
             getTableList()
             changeBatch(false)
         }).catch((err) => {
-            globalPopup?.showError(err.message)
+            globalPopup?.showError(err.msg)
         })
     })
 }

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

@@ -5,13 +5,13 @@
             <div>
                 <el-button type="primary" v-if="!info.ownerId">认领</el-button>
                 <el-button type="primary" v-else @click="operationCli(false)">转移</el-button>
-                <el-button type="primary" @click="editInfo(info)">编辑</el-button>
+                <el-button type="primary" v-permission="['contactsEdit']" @click="editInfo(info)">编辑</el-button>
             </div>
         </div>
         <div class="form flex flex-wrap justify-between">
             <div v-for="item in formItems" :key="item.label" class="formItem flex pt-2 pb-1" :style="{ width: item.width }">
                 <div :class="item.labelClass">{{ item.label }}:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ item.value }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{ item.value }}</div>
             </div>
         </div>
 

+ 2 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedBusiness.vue

@@ -2,7 +2,7 @@
     <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
             <div class="title">相关商机</div>
-            <div>
+            <div v-permission="['businessAddAnEdit']">
                 <el-button type="primary" @click="addBusiness()">新建商机</el-button>
             </div>
         </div>
@@ -15,14 +15,13 @@
                         }}</el-button>
                     </template>
                 </el-table-column>
-                <el-table-column prop="customerName" label="客户名称" width="130" />
+                <el-table-column prop="customerName" label="客户名称" width="140" />
                 <el-table-column prop="inchargerName" label="负责人" width="130" />
                 <el-table-column prop="amountOfMoney" label="商机金额" width="130" />
                 <el-table-column prop="expectedTransactionDate" label="预计成交时间" width="170" />
                 <el-table-column prop="stageValue" label="商机阶段" width="130" />
                 <el-table-column prop="creatorName" label="创建人" width="130" />
                 <el-table-column prop="createTime" label="创建时间" width="130" />
-                <el-table-column prop="modifyTime" label="修改时间" width="130" />
             </el-table>
         </div>
 

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

@@ -81,7 +81,7 @@ function getAllContacts() {
     post(URL_GETALL, {}).then(({ data }) => {
         options.value = (data || []).map((item: any) => ({ value: item.id, label: item.name }))
     }).catch((err) => {
-        globalPopup?.showError(err.message)
+        globalPopup?.showError(err.msg)
     })
 }
 

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

@@ -26,11 +26,11 @@
         <div class="flex justify-end pb-3">
           <!-- 操作按钮 -->
           <!-- <el-button v-for="(button, index) in actionButtons" :key="index" type="primary">{{ button.text }}</el-button> -->
-          <el-button type="primary" @click="editContacts(false)">新建联系人</el-button>
+          <el-button type="primary" v-permission="['contactsAdd']" @click="editContacts(false)">新建联系人</el-button>
           <el-button type="primary" @click="batchDeteleItem" :disabled="batchTableData.length <= 0">批量删除</el-button>
           <el-button type="primary" @click="showVisible('deteleContactsVisible')">回收站</el-button>
-          <el-button type="primary" @click="showVisible('importVisible')">导入</el-button>
-          <el-button type="primary" @click="exportCustomerTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
+          <el-button type="primary" v-permission="['contactsImport']" @click="showVisible('importVisible')">导入</el-button>
+          <el-button type="primary" v-permission="['contactsExport']" @click="exportCustomerTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
         </div>
         <div class="flex-1 w-full overflow-hidden">
           <!-- 表格 -->
@@ -49,11 +49,11 @@
                 </template>
               </template>
             </el-table-column>
-            <el-table-column :label="'操作'" :width="'200px'" fixed="right">
+            <el-table-column :label="'操作'" :width="'200px'" fixed="right" v-permission="['contactsEdit', 'tasksAdd']">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click="editContacts(scope.row)">编辑</el-button>
-                <el-button link type="primary" size="large" @click="newTask(scope.row)">新建任务</el-button>
-                <el-button link type="danger" size="large"
+                <el-button link type="primary" size="large" v-permission="['contactsEdit']" @click="editContacts(scope.row)">编辑</el-button>
+                <el-button link type="primary" size="large" v-permission="['tasksAdd']" @click="newTask(scope.row)">新建任务</el-button>
+                <el-button link type="danger" size="large" v-permission="['contactsEdit']"
                   @click="contactsDeteleItem(scope.row.id, scope.row.customName)">删除</el-button>
               </template>
             </el-table-column>
@@ -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>>()
@@ -250,8 +250,9 @@ function batchDeteleItem() {
 }
 
 function contactsDeteleItem(value: string | number, label: string, batch: boolean = false) {
-  confirmAction(`确定${batch ? '批量' : ''}删除【${label}】客户吗?`).then(() => {
-    let url = batch ? URL_BATCHDETELE : URL_DETELERECYCLE
+  confirmAction(`确定${batch ? '批量' : ''}删除【${label}】联系人吗?`).then(() => {
+    // let url = batch ? URL_BATCHDETELE : URL_DETELERECYCLE
+    let url = URL_DETELERECYCLE
     post(url, { ids: value }).then(res => {
       if (res.code != 'ok') {
         globalPopup?.showError(res.msg)

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/api.ts

@@ -1,5 +1,5 @@
 export const MOD = '/customer'
-export const IMPORTMOD = 'Custom'
+export const IMPORTMOD = 'Customer'
 export const PREFIX = '/custom'
 export const GETSYSFILED = '/sys-dict/getListByCode'
 export const GETPERSONNEL = '/user/getSimpleActiveUserList'

+ 9 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/attachment.vue

@@ -2,7 +2,7 @@
     <div class="attachment pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
             <div class="title">附件</div>
-            <div>
+            <div v-permission="['customerEdit']">
                 <el-upload ref="uploadRef" :http-request="httpUploadFile" :limit="1" :show-file-list="false"
                     element-loading-text="正在上传">
                     <template #trigger>
@@ -16,7 +16,7 @@
                 <el-table-column prop="name" label="附件名称" width="180" />
                 <el-table-column prop="size" label="附件大小" width="120" />
                 <el-table-column prop="userName" label="上传人" width="120" />
-                <el-table-column prop="createTime" label="上传时间" width="180" />
+                <el-table-column prop="createTime" label="上传时间" width="180" sortable />
                 <el-table-column label="操作" width="180" fixed="right">
                     <template #default="scope">
                         <el-button link type="primary" size="large" @click="fileDownload(scope.row)">下载</el-button>
@@ -50,6 +50,7 @@ import { UploadRequestOptions } from 'element-plus';
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
 import { URL_DETELEFILE, URL_REFFILENAME, URL_UPLOADFILE } from '../api';
 import { confirmAction, downloadFile } from '@/utils/tools';
+import { formatDate } from '@/utils/times';
 
 const emits = defineEmits(['refreshData']);
 const globalPopup = inject<GlobalPopup>('globalPopup')
@@ -118,7 +119,12 @@ function showVisible(item: any) {
 
 watchEffect(() => {
     information.value = props.data
-    attachmenttable.value = (props.data.files || [])
+    attachmenttable.value = (props.data.files || []).map((item: any) => {
+        return {
+            ...item,
+            createTime: formatDate(new Date(item.createTime))
+        }
+    })
 });
 
 // 生命周期钩子

+ 4 - 4
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/deteleTables.vue

@@ -30,9 +30,9 @@
                     <el-table-column label="操作" fixed="right" width="120">
                         <template #default="scope">
                             <el-button link type="primary" size="large"
-                                @click="operationItem(scope.row.id, scope.row.name, '恢复')">恢复</el-button>
+                                @click="operationItem(scope.row.id, scope.row.customName, '恢复')">恢复</el-button>
                             <el-button link type="danger" size="large"
-                                @click="operationItem(scope.row.id, scope.row.name, '删除')">删除</el-button>
+                                @click="operationItem(scope.row.id, scope.row.customName, '删除')">删除</el-button>
                         </template>
                     </el-table-column>
                 </el-table>
@@ -87,7 +87,7 @@ watch(() => props.visibles, (newVal) => {
 
 function batchOperation(type: operationType) {
     const value = batchTableData.value.map((item: any) => item.id).join(',')
-    const label = batchTableData.value.map((item: any) => item.name).join(',')
+    const label = batchTableData.value.map((item: any) => item.customName).join(',')
     operationItem(value, label, type, true)
 }
 
@@ -103,7 +103,7 @@ function operationItem(value: string | number, label: string, type: operationTyp
             getTableList()
             changeBatch(false)
         }).catch((err) => {
-            globalPopup?.showError(err.message)
+            globalPopup?.showError(err.msg)
         })
     })
 }

+ 22 - 12
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/information.vue

@@ -5,27 +5,31 @@
             <div>
                 <el-button type="primary" @click="claimCustomer()" v-if="!information.inchargerName">认领</el-button>
                 <el-button type="primary" @click="transferCli()">转移</el-button>
-                <el-button type="primary" @click="editCustomer()">编辑</el-button>
+                <el-button type="primary" v-permission="['customerEdit']" @click="editCustomer()">编辑</el-button>
             </div>
         </div>
         <div class="form flex flex-wrap justify-between">
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-20 text-right text-gray-500">客户名称:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.customName }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.customName }}</div>
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">客户来源:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.customSourceValue }}
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{
+                    information.customSourceValue }}
                 </div>
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">电话号码:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.companyPhone }}
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.companyPhone }}
                 </div>
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">邮箱:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.email }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.email }}</div>
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">客户行业:</div>
@@ -34,7 +38,8 @@
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">客户级别:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.customerLevelValue
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{
+                    information.customerLevelValue
                 }}</div>
             </div>
             <div class="formItem flex pt-2 pb-1">
@@ -48,7 +53,8 @@
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">创建人:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.creatorName }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.creatorName }}
+                </div>
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">创建时间:</div>
@@ -57,7 +63,7 @@
             </div>
             <div class="formItem flex pt-2 pb-1" style="width: 100%;">
                 <div class="w-22 text-right text-gray-500">备注:</div>
-                <div class="flex-1 ml-1 text ">
+                <div class="flex-1 ml-1 text " v-ellipsis-tooltip>
                     {{ information.customDesc }}
                 </div>
             </div>
@@ -91,7 +97,8 @@
                 <div class="flex justify-between items-center border-b pb-3 dialog-header">
                     <h4 :id="titleId">{{ '编辑客户' }}</h4>
                     <div>
-                        <el-button type="primary" @click="saveCustomer()" :loading="allLoading.saveLading">保存</el-button>
+                        <el-button type="primary" @click="saveCustomer()"
+                            :loading="allLoading.saveLading">保存</el-button>
                         <el-button @click="closeVisible('editCustomerVisible')">取消</el-button>
                     </div>
                 </div>
@@ -144,7 +151,9 @@ const allVisible = reactive({
 function saveCustomer() {
     generateForm.value?.getData().then((res: any) => {
         allLoading.saveLading = true
-        post(URL_EDITSAVE, { ...generateFormValue.value, ...res }).then((_res) => {
+        let formVal = { ...generateFormValue.value, ...res }
+        delete formVal.createTime
+        post(URL_EDITSAVE, { ...formVal }).then((_res) => {
             globalPopup?.showSuccess('操作成功')
             closeVisible('editCustomerVisible')
             emits('refreshData')
@@ -188,11 +197,12 @@ function claimCustomer() {
 }
 
 function editCustomer() {
-    const { id, companyPhone, customName, inchargerId, createTime, customSourceId, customerIndustryId, customerLevelId, email, telPhone } = information.value
+    const { id, companyPhone, customName, inchargerId, createTime, customSourceId, customerIndustryId, customerLevelId, email, telPhone, customDesc } = information.value
     const formVal = {
         id, customName, inchargerId, customerIndustryId, customerLevelId, email, customSourceId,
         createTime: formatDate(new Date(createTime)),
-        telPhone, companyPhone
+        telPhone, companyPhone,
+        customDesc
     }
     generateFormValue.value = formVal
     allLoading.generateFormDataLoading = true

+ 9 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/operationRecord.vue

@@ -5,14 +5,15 @@
         </div>
         <div class="flex-1 overflow-auto pt-5">
             <el-table :data="operationRecordtable" border style="width: 100%;height: 278px;">
-                <el-table-column prop="creaTime" label="操作时间" width="140" />
-                <el-table-column prop="username" label="操作人" width="120" />
+                <el-table-column prop="creatTime" label="操作时间" width="140" />
+                <el-table-column prop="userName" label="操作人" width="120" />
                 <el-table-column prop="name" label="操作内容" />
             </el-table>
         </div>
     </div>
 </template>
 <script lang="ts" setup>
+import { formatDate } from '@/utils/times';
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
 
 const operationRecordtable = ref([])
@@ -25,7 +26,12 @@ const props = defineProps<{
 watchEffect(() => {
     const { data } = props
     information.value = data
-    operationRecordtable.value = data.actionLogs || []
+    operationRecordtable.value = (data.actionLogs || []).map((item: any) => {
+        return {
+            ...item,
+            creatTime: formatDate(new Date(item.creatTime))
+        }
+    })
 })
 
 // 生命周期钩子

+ 13 - 14
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedBusiness.vue

@@ -2,27 +2,26 @@
     <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
             <div class="title">相关商机</div>
-            <div>
+            <div v-permission="['businessAddAnEdit']">
                 <el-button type="primary" @click="editNewBusiness()">新建商机</el-button>
             </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
             <el-table :data="relatedTaskstable" border style="width: 100%;height: 300px;">
-                <el-table-column prop="taskName" label="商机名称">
+                <el-table-column prop="taskName" label="name">
                     <template #default="scope">
                         <el-button link type="primary" size="large">{{
-                            scope.row.taskName
-                        }}</el-button>
+                            scope.row.name
+                            }}</el-button>
                     </template>
                 </el-table-column>
-                <el-table-column prop="priority" label="客户名称" width="130" />
-                <el-table-column prop="status" label="负责人" width="130" />
-                <el-table-column prop="executor" label="商机金额" width="130" />
-                <el-table-column prop="startTime" label="预计成交时间" width="130" />
-                <el-table-column prop="endTime" label="商机阶段" width="130" />
-                <el-table-column prop="endTime" label="创建人" width="130" />
-                <el-table-column prop="endTime" label="创建时间" width="130" />
-                <el-table-column prop="endTime" label="修改时间" width="130" />
+                <el-table-column prop="customerName" label="客户名称" width="130" />
+                <el-table-column prop="inchargerName" label="负责人" width="130" />
+                <el-table-column prop="amountOfMoney" label="商机金额" width="130" />
+                <el-table-column prop="expectedTransactionDate" label="预计成交时间" width="200" />
+                <el-table-column prop="stageValue" label="商机阶段" width="140" />
+                <el-table-column prop="creatorName" label="创建人" width="130" />
+                <el-table-column prop="createTime" label="创建时间" width="130" />
             </el-table>
         </div>
 
@@ -87,7 +86,7 @@ const allLoading = reactive({
 function editBusiness(visibles: boolean) {
     businessTemplateRef.value?.getData().then((res: any) => {
         let productTableListData = relatedProductsRef?.value?.returnData()
-        if(!productTableListData || judgmentaAmounteEqual({ ...businessTemplateValue.value, ...res }, productTableListData)) {
+        if (!productTableListData || judgmentaAmounteEqual({ ...businessTemplateValue.value, ...res }, productTableListData)) {
             return
         }
         productTableListData.forEach((item: any) => {
@@ -168,7 +167,7 @@ function getProductTableList() {
 watchEffect(() => {
     const { data } = props
     information.value = data
-    relatedTaskstable.value = []
+    relatedTaskstable.value = (data.businessOpportunitys || [])
 })
 
 // 生命周期钩子

+ 11 - 11
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedContacts.vue

@@ -2,7 +2,7 @@
     <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
             <div class="title">相关联系人</div>
-            <div>
+            <div v-permission="['contactsAdd']">
                 <el-button type="primary" @click="editContacts(information)">新建联系人</el-button>
             </div>
         </div>
@@ -13,20 +13,20 @@
                         {{ scope.$index + 1 }}
                     </template>
                 </el-table-column>
-                <el-table-column prop="taskName" label="联系人姓名">
+                <el-table-column prop="name" label="联系人姓名">
                     <template #default="scope">
                         <el-button link type="primary" size="large">{{
-                            scope.row.taskName
+                            scope.row.name
                         }}</el-button>
                     </template>
                 </el-table-column>
-                <el-table-column prop="priority" label="电话号码" width="130" />
-                <el-table-column prop="status" label="邮箱" width="130" />
-                <el-table-column prop="executor" label="职务" width="130" />
-                <el-table-column prop="startTime" label="性别" width="130" />
-                <el-table-column prop="endTime" label="负责人" width="130" />
-                <el-table-column prop="endTime" label="创建人" width="130" />
-                <el-table-column prop="endTime" label="创建时间" width="130" />
+                <el-table-column prop="phone" label="电话号码" width="130" />
+                <el-table-column prop="email" label="邮箱" width="130" />
+                <el-table-column prop="position" label="职务" width="130" />
+                <el-table-column prop="sexValue" label="性别" width="130" />
+                <el-table-column prop="ownerName" label="负责人" width="130" />
+                <el-table-column prop="creatorName" label="创建人" width="130" />
+                <el-table-column prop="createTime" label="创建时间" width="130" />
             </el-table>
         </div>
 
@@ -116,7 +116,7 @@ const allVisible = reactive({
 watchEffect(() => {
     const { data } = props
     information.value = data
-    relatedCustomertable.value = []
+    relatedCustomertable.value = (data.contacts || [])
 })
 
 async function getSystemField() {

+ 17 - 16
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedOrders.vue

@@ -2,29 +2,29 @@
     <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
             <div class="title">相关销售订单</div>
-            <div>
+            <div v-permission="['orderAdd']">
                 <el-button type="primary" @click="editOrder()">新建销售订单</el-button>
             </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
             <el-table :data="relatedOrders" border style="width: 100%;height: 300px;">
-                <el-table-column prop="priority" label="订单编号" width="130" />
-                <el-table-column prop="taskName" label="订单名称">
+                <el-table-column prop="orderCode" label="订单编号" width="130" />
+                <el-table-column prop="orderName" label="订单名称" min-width="200">
                     <template #default="scope">
                         <el-button link type="primary" size="large">{{
-                            scope.row.taskName
-                        }}</el-button>
+                            scope.row.orderName
+                            }}</el-button>
                     </template>
                 </el-table-column>
-                <el-table-column prop="priority" label="客户名称" width="130" />
-                <el-table-column prop="status" label="订单金额" width="130" />
-                <el-table-column prop="executor" label="已回款" width="130" />
-                <el-table-column prop="startTime" label="未回款" width="130" />
-                <el-table-column prop="endTime" label="订单类型" width="130" />
-                <el-table-column prop="endTime" label="下单时间" width="130" />
-                <el-table-column prop="endTime" label="负责人" width="130" />
-                <el-table-column prop="endTime" label="创建人" width="130" />
-                <el-table-column prop="endTime" label="创建时间" width="130" />
+                <el-table-column prop="customName" label="客户名称" width="130" />
+                <el-table-column prop="price" label="订单金额(¥)" width="130" />
+                <el-table-column prop="receivedPayment" label="已回款(¥)" width="130" />
+                <el-table-column prop="unReceivedPayment" label="未回款(¥)" width="130" />
+                <el-table-column prop="typeName" label="订单类型" width="130" />
+                <el-table-column prop="placeTime" label="下单时间" width="200" />
+                <el-table-column prop="inchargerName" label="负责人" width="130" />
+                <el-table-column prop="creatorName" label="创建人" width="130" />
+                <el-table-column prop="createTime" label="创建时间" width="200" />
             </el-table>
         </div>
 
@@ -103,6 +103,7 @@ function saveOrder(flag: boolean) {
             ...res,
             orderEndDate: res.orderEndDate ? formatDate(res.orderEndDate) : '',
             orderStartDate: res.orderStartDate ? formatDate(res.orderStartDate) : '',
+            placeTime: res.placeTime ? formatDate(res.placeTime) : '',
             orderProductDetailString: produt
         }).then((_res) => {
             allVisible.editOrderVisible = flag
@@ -122,7 +123,7 @@ function saveOrder(flag: boolean) {
 function editOrder() {
     showVisible('editOrderVisible')
     allLoading.orderTemplateLoadinng = true
-    
+
     orderTemplateValue.value = { customId: information.value.id }
     productTableListValue.value = []
     setTimeout(() => {
@@ -176,7 +177,7 @@ function getProductTableList() {
 watchEffect(() => {
     const { data } = props
     information.value = data
-    relatedOrders.value = []
+    relatedOrders.value = (data.salesOrders || [])
 })
 
 // 生命周期钩子

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

@@ -7,7 +7,7 @@
         </el-link>
       </div>
       <div class="mr-8">
-        <el-select v-model="values" placeholder="请选择" style="width: 150px" @change="getDetail()">
+        <el-select v-model="values" placeholder="请选择" style="width: 250px" @change="getDetail()">
           <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
       </div>

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

@@ -12,7 +12,7 @@
                 <el-option v-for="item in fixedData.ClueSources" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
-            <el-form-item label="电话号码">
+            <el-form-item label="公司号码">
               <el-input v-model="customerCriteriaForm.telPhone" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="邮箱">
@@ -20,7 +20,8 @@
             </el-form-item>
             <el-form-item label="客户行业">
               <el-select v-model="customerCriteriaForm.customerIndustryId" placeholder="请选择" clearable>
-                <el-option v-for="item in fixedData.CustomIndustry" :key="item.id" :label="item.name" :value="item.id" />
+                <el-option v-for="item in fixedData.CustomIndustry" :key="item.id" :label="item.name"
+                  :value="item.id" />
               </el-select>
             </el-form-item>
             <el-form-item label="客户级别">
@@ -52,46 +53,48 @@
     <div class="flex-1 p-5 overflow-auto">
       <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
         <div class="flex justify-end pb-3">
-          <el-button type="primary" @click="editCustomer(false)">新建客户</el-button>
+          <el-button type="primary" v-permission="['customerAdd']" @click="editCustomer(false)">新建客户</el-button>
           <el-button type="primary" @click="showVisible('batchTransferVisible')"
             :disabled="batchTableData.length <= 0">批量转移</el-button>
           <el-button type="primary" @click="batchDeteleItem()" :disabled="batchTableData.length <= 0">批量删除</el-button>
           <el-button type="primary" @click="showVisible('deteleCustomerVisible')">回收站</el-button>
-          <el-button type="primary" @click="showVisible('importVisible')">导入</el-button>
-          <el-button type="primary" @click="exportCustomerTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
+          <el-button type="primary" v-permission="['customerImport']" @click="showVisible('importVisible')">导入</el-button>
+          <el-button type="primary" v-permission="['customerExport']" @click="exportCustomerTableList()"
+            :loading="allLoading.exoprtLoading">导出</el-button>
         </div>
         <div class="flex-1 w-full overflow-hidden">
-          <el-table ref="customerTableRef" :data="customerTable" border v-loading="allLoading.customerTableLading"
-            style="width: 100%;height: 100%;" @selection-change="changeBatch">
+          <el-table ref="customerTableRef" :show-overflow-tooltip="tableShowOverflowTooltip" :data="customerTable" border v-loading="allLoading.customerTableLading"
+            style="width: 100%;height: 100%;" @selection-change="changeBatch" @sort-change="sortChange">
             <el-table-column type="selection" width="55" />
             <el-table-column prop="customName" label="客户名称" width="180">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click.prevent="toCustomerTableDetail(scope.row)">{{
+                <!-- <el-button link type="primary" size="large" @click.prevent="toCustomerTableDetail(scope.row)">{{
                   scope.row.customName
-                }}</el-button>
+                }}</el-button> -->
+                <div class="table-text-textnowrap" @click.prevent="toCustomerTableDetail(scope.row)">{{ scope.row.customName }}</div>
               </template>
             </el-table-column>
             <el-table-column prop="customSourceValue" label="客户来源" width="180"></el-table-column>
             <el-table-column prop="companyPhone" label="公司电话" width="180"></el-table-column>
             <el-table-column prop="email" label="邮箱" width="200"></el-table-column>
             <el-table-column prop="customerIndustryValue" label="客户行业" width="180"></el-table-column>
-            <el-table-column prop="customerLevelValue" label="客户级别" width="180"></el-table-column>
+            <el-table-column prop="customerLevelValue" label="客户级别" width="180" sortable="custom"></el-table-column>
             <el-table-column prop="inchargerName" label="负责人" width="190"></el-table-column>
             <el-table-column prop="creatorName" label="创建人" width="180"></el-table-column>
             <el-table-column prop="newCreateTime" label="创建时间" width="180"></el-table-column>
-            <el-table-column label="操作" fixed="right" width="200">
+            <el-table-column label="操作" fixed="right" width="200" v-permission="['customerEdit', 'tasksAdd', 'customerEdit']">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click="editCustomer(scope.row)">编辑</el-button>
-                <el-button link type="primary" size="large" @click="newTask(scope.row)">新建任务</el-button>
-                <el-button link type="danger" size="large"
+                <el-button link type="primary" size="large" v-permission="['customerEdit']" @click="editCustomer(scope.row)">编辑</el-button>
+                <el-button link type="primary" size="large" v-permission="['tasksAdd']" @click="newTask(scope.row)">新建任务</el-button>
+                <el-button link type="danger" size="large" v-permission="['customerEdit']"
                   @click="customerDeteleItem(scope.row.id, scope.row.customName)">删除</el-button>
               </template>
             </el-table-column>
           </el-table>
         </div>
         <div class="flex justify-end pt-3">
-          <el-pagination layout="total, prev, pager, next, sizes" :total="customerTotalTable" :hide-on-single-page="true"
-            @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+          <el-pagination layout="total, prev, pager, next, sizes" :total="customerTotalTable"
+            :hide-on-single-page="true" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
         </div>
       </div>
     </div>
@@ -102,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>
@@ -181,6 +184,7 @@ import { useRouter, useRoute } from "vue-router";
 import { GenerateForm } from '@zmjs/form-design';
 import { createTask } from "@/components/TaskModal/taskFunction";
 import { ElTable, UploadRequestOptions } from "element-plus";
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
 
 import TaskModal from '@/components/TaskModal/index.vue'
 import DeteleBusiness from './component/deteleTables.vue'
@@ -209,6 +213,7 @@ interface customerCriteriaFormType { // 线索筛选条件类型
   customerIndustryId: string | number,
   customerLevelId: string | number,
   inchargerId: string | number,
+  isDesc?: string | number,
   startTime: string | number,
   endTime: string | number,
   pageIndex: string | number,
@@ -226,6 +231,7 @@ const customerCriteriaForm = reactive<customerCriteriaFormType>({ // 筛选条
   customerIndustryId: '',
   customerLevelId: '',
   inchargerId: '',
+  isDesc: '',
   startTime: getFirstDayOfMonth(new Date()),
   endTime: formatDate(new Date()),
   pageIndex: 1,
@@ -266,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')
@@ -276,6 +282,21 @@ const transferPersonnel = ref('')
 
 
 // 定义方法
+function sortChange(data: any) {
+  customerCriteriaForm.pageIndex = 1
+  switch (data.order) {
+    case 'ascending':
+      customerCriteriaForm.isDesc = 1
+      break
+    case 'descending':
+      customerCriteriaForm.isDesc = 0
+      break
+    default:
+      customerCriteriaForm.isDesc = ''
+  }
+  getCustomerTable()
+}
+
 async function importBusiness(param: UploadRequestOptions) {
   allLoading.importLoading = true
   const formData = new FormData();
@@ -331,7 +352,7 @@ function customerDeteleItem(value: string | number, label: string, batch: boolea
       changeBatch(false)
       getCustomerTable()
     }).catch((err) => {
-      globalPopup?.showError(err.message)
+      globalPopup?.showError(err.msg)
     })
   })
 }
@@ -364,6 +385,7 @@ function editCustomerSave(flag: boolean) {
       ...customerTemplateValue.value,
       ...res
     }
+    delete formVal.createTime
     post(URL_EDITSAVE, { ...formVal }).then((_res) => {
       allVisible.editCustomerVisible = flag
       globalPopup?.showSuccess('保存成功')

+ 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">

+ 7 - 7
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/api.ts

@@ -27,16 +27,16 @@ export const tableColumns: TableColumn[] = [
     { prop: 'orderName', label: '订单名称', width: '150' },
     { prop: 'customName', label: '客户名称', width: '200' },
     { prop: 'businessOpportunityName', label: '商机名称', width: '200' },
-    { prop: 'price', label: '订单金额', width: '100' },
-    { prop: 'receivedPayment', label: '已回款', width: '100' },
-    { prop: 'unReceivedPayment', label: '未回款', width: '100' },
-    { prop: 'status', label: '回放状态', width: '100' },
+    { prop: 'price', label: '订单金额(¥)', width: '120' },
+    { prop: 'receivedPayment', label: '已回款(¥)', width: '100' },
+    { prop: 'unReceivedPayment', label: '未回款(¥)', width: '100' },
+    { prop: 'statusValue', label: '回款状态', width: '100' },
     { prop: 'typeName', label: '订单类型', width: '200' },
     { prop: 'placeTime', label: '下单时间', width: '200' },
     { prop: 'orderStartDate', label: '订单开始时间', width: '200' },
-    { prop: 'orderEndDate', label: '订单结束时间', width: '200' },
-    { prop: 'customSigner', label: '客户签的人', width: '200' },
-    { prop: 'companySigner', label: '公司签的人', width: '200' },
+    { prop: 'orderEndDate', label: '订单结束时间', width: '140' },
+    { prop: 'customSignerName', label: '客户签的人', width: '140' },
+    { prop: 'companySignerName', label: '公司签的人', width: '200' },
     { prop: 'inchargerName', label: '负责人', width: '200' },
     { prop: 'creatorName', label: '创建人', width: '200' },
     { prop: 'createTime', label: '创建时间', width: '200' },

+ 18 - 12
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/deteleTables.vue

@@ -5,10 +5,10 @@
             <div class="flex justify-between items-center border-b pb-3 dialog-header">
                 <h4 :id="titleId">销售订单回收站</h4>
                 <div>
-                    <el-button type="primary" v-loading="allLoading.batchRecoveryLoading" :disabled="batchTableData.length == 0"
-                        @click="batchOperation('恢复')">批量恢复</el-button>
-                    <el-button type="primary" v-loading="allLoading.batchDeteleLoading" :disabled="batchTableData.length == 0"
-                        @click="batchOperation('删除')">批量删除</el-button>
+                    <el-button type="primary" v-loading="allLoading.batchRecoveryLoading"
+                        :disabled="batchTableData.length == 0" @click="batchOperation('恢复')">批量恢复</el-button>
+                    <el-button type="primary" v-loading="allLoading.batchDeteleLoading"
+                        :disabled="batchTableData.length == 0" @click="batchOperation('删除')">批量删除</el-button>
                     <el-button @click="cancel()">取消</el-button>
                 </div>
             </div>
@@ -18,8 +18,8 @@
                 <el-table ref="busiessTableRef" :data="deteleBusinessTable" border v-loading="allLoading.tableLoading"
                     @selection-change="changeBatch" style="width: 100%;height: 100%;">
                     <el-table-column type="selection" width="55" />
-                    <el-table-column v-for="(item, index) in tableColumns" :prop="item.prop" :label="item.label" :key="index"
-                        :width="item.width">
+                    <el-table-column v-for="(item, index) in tableColumns" :prop="item.prop" :label="item.label"
+                        :key="index" :width="item.width">
                         <template #default="scope">
                             <span>{{ scope.row[item.prop] }}</span>
                         </template>
@@ -27,9 +27,9 @@
                     <el-table-column label="操作" fixed="right" width="120">
                         <template #default="scope">
                             <el-button link type="primary" size="large"
-                                @click="businessOperationItem(scope.row.id, scope.row.name, '恢复')">恢复</el-button>
+                                @click="businessOperationItem(scope.row.id, scope.row.orderName, '恢复')">恢复</el-button>
                             <el-button link type="danger" size="large"
-                                @click="businessOperationItem(scope.row.id, scope.row.name, '删除')">删除</el-button>
+                                @click="businessOperationItem(scope.row.id, scope.row.orderName, '删除')">删除</el-button>
                         </template>
                     </el-table-column>
                 </el-table>
@@ -45,7 +45,7 @@
 <script lang="ts" setup>
 import { post } from '@/utils/request';
 import { ref, reactive, onMounted, watchEffect, watch, inject } from 'vue'
-import { GETTABLELIST, tableColumns, URL_BATCHDELETE, URL_RECOVER } from '../api';
+import { GETTABLELIST, paymentStatus, tableColumns, URL_BATCHDELETE, URL_RECOVER } from '../api';
 import { ElTable } from 'element-plus';
 import { confirmAction } from '@/utils/tools';
 import { formatDate } from '@/utils/times';
@@ -84,7 +84,7 @@ watch(() => props.visibles, (newVal) => {
 
 function batchOperation(type: operationType) {
     const value = batchTableData.value.map((item: any) => item.id).join(',')
-    const label = batchTableData.value.map((item: any) => item.name).join(',')
+    const label = batchTableData.value.map((item: any) => item.orderName).join(',')
     businessOperationItem(value, label, type, true)
 }
 
@@ -101,7 +101,7 @@ function businessOperationItem(value: string | number, label: string, type: oper
             getTableList()
             changeBatch(false)
         }).catch((err) => {
-            globalPopup?.showError(err.message)
+            globalPopup?.showError(err.msg)
         })
     })
 }
@@ -120,7 +120,13 @@ function getTableList() {
     post(GETTABLELIST, { ...tableForm, isDelete: 1 }).then((res) => {
         if (res.code == 'ok') {
             const { record, total } = res.data
-            deteleBusinessTable.value = record
+            deteleBusinessTable.value = (record || []).map((item: any) => {
+                let val = paymentStatus.find((items: any) => items.value == item.status)
+                return {
+                    ...item,
+                    statusValue: val ? val.label : ''
+                }
+            })
             businessTotalTable.value = total
         }
     }).finally(() => {

+ 33 - 23
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/information.vue

@@ -4,13 +4,14 @@
             <div class="title">基本信息</div>
             <div>
                 <el-button type="primary" @click="transferCli()">转移</el-button>
-                <el-button type="primary" @click="editInfo(info)">编辑</el-button>
+                <el-button type="primary" v-permission="['orderEdit']" @click="editInfo(info)">编辑</el-button>
             </div>
         </div>
         <div class="form flex flex-wrap justify-between">
-            <div v-for="item in formItems" :key="item.label" class="formItem flex" :style="{ width: item.width }">
+            <div v-for="item in formItems" :key="item.label" class="formItem flex" :style="`width: ${item.width}`">
                 <div :class="item.labelClass">{{ item.label }}:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ item.value }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    item.value }}</div>
             </div>
         </div>
 
@@ -62,7 +63,7 @@ import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffec
 import { GenerateForm } from '@zmjs/form-design';
 import { getFromValue, getTemplateKey } from '@/utils/tools';
 import { get, post } from '@/utils/request';
-import { GETGENERATEFOEM, GETPERSONNEL, URL_OEDERUPDATE, URL_PRODUTWITHORDER, URL_TRANSFER } from '../api';
+import { GETGENERATEFOEM, GETPERSONNEL, URL_OEDERUPDATE, URL_PRODUTWITHORDER, URL_TRANSFER, paymentStatus } from '../api';
 import { formatDate } from '@/utils/times';
 
 const globalPopup = inject<GlobalPopup>('globalPopup')
@@ -102,6 +103,7 @@ function editOrderSave() {
             ...res,
             orderEndDate: res.orderEndDate ? formatDate(res.orderEndDate) : '',
             orderStartDate: res.orderStartDate ? formatDate(res.orderStartDate) : '',
+            placeTime: res.placeTime ? formatDate(res.placeTime) : '',
             orderProductDetailString: JSON.stringify(productTableListValue.value || [])
         }).then((_res) => {
             closeVisible('editOrderVisible')
@@ -178,32 +180,38 @@ function closeVisible(type: keyof typeof allVisible) {
 }
 
 const formItems = reactive([
-    { label: '订单编号', key: 'orderCode', value: '', labelClass: 'w-20 text-right text-gray-500', width: '48%' },
-    { label: '订单名称', key: 'orderName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '客户名称', key: 'customName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '商机名称', key: 'businessOpportunityName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '订单金额', key: 'price', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '回款状态', key: 'receivedStatus', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '已回款金额', key: 'receivedPayment', value: '', labelClass: 'w-24 text-right text-gray-500', width: '48%' },
-    { label: '未回款', key: 'unReceivedPayment', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '订单类型', key: 'type', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '下单时间', key: 'placeTime', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '订单开始时间', key: 'orderStartDate', value: '', labelClass: 'w-30 text-right text-gray-500', width: '48%' },
-    { label: '订单结束时间', key: 'orderEndDate', value: '', labelClass: 'w-30 text-right text-gray-500', width: '48%' },
-    { label: '负责人', key: 'inchargerName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '创建人', key: 'createName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '创建时间', key: 'createTime', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '客户签约人', key: 'customSigner', value: '', labelClass: 'w-24 text-right text-gray-500', width: '48%' },
-    { label: '公司签约人', key: 'companySigner', value: '', labelClass: 'w-24 text-right text-gray-500', width: '48%' },
-    { label: '备注', key: 'remark', value: '', labelClass: 'w-22 text-right text-gray-500', width: '100%' },
+    { label: '订单编号', key: 'orderCode', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '订单名称', key: 'orderName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '客户名称', key: 'customName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '商机名称', key: 'businessOpportunityName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '订单金额', key: 'price', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '回款状态', key: 'statusValue', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '已回款金额', key: 'receivedPayment', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '未回款', key: 'unReceivedPayment', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '订单类型', key: 'type', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '下单时间', key: 'placeTime', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '订单开始时间', key: 'orderStartDate', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '订单结束时间', key: 'orderEndDate', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '负责人', key: 'inchargerName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '创建人', key: 'creatorName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '创建时间', key: 'createTime', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '客户签约人', key: 'customSigner', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '公司签约人', key: 'companySigner', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '备注', key: 'remark', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '100%' },
 ])
 
 watchEffect(() => {
     const { data } = props
     info.value = data
     formItems.forEach(item => {
-        item.value = info.value[item.key] || '';
+        if (item.key === 'statusValue') {
+            const status = info.value['status'];
+            item.value = status !== '' && status !== null ? (paymentStatus.find(p => p.value === status)?.label || '') : '';
+        } else {
+            item.value = info.value[item.key] || '';
+        }
     });
+
 })
 
 async function getSystemField() {
@@ -234,6 +242,8 @@ onMounted(async () => {
 
     .form {
         .formItem {
+            width: 48%;
+
             .text {
                 display: -webkit-box;
                 /* Safari */

+ 2 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/products.vue

@@ -2,7 +2,7 @@
     <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
             <div class="title">相关产品</div>
-            <div class="flex">
+            <div class="flex" v-permission="['productEdit']">
                 <el-button type="primary" @click="productClick()">编辑产品</el-button>
             </div>
         </div>
@@ -97,6 +97,7 @@ function saveOrder() {
         ...items,
         orderEndDate: items.orderEndDate ? items.orderEndDate : '',
         orderStartDate: items.orderStartDate ? items.orderStartDate : '',
+        placeTime: items.placeTime ? formatDate(items.placeTime) : '',
         orderProductDetailString: produt
     }).then(() => {
         globalPopup?.showSuccess('操作成功')

+ 7 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/rebate.vue

@@ -2,7 +2,7 @@
     <div class="operationRecord pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
             <div class="title">回款</div>
-            <div class="flex">
+            <div class="flex" v-permission="['orderEdit']">
                 <el-button type="primary" @click="editRebate(false)">新增回款</el-button>
             </div>
         </div>
@@ -98,8 +98,12 @@ function editRebate(item: any) {
 }
 
 function saveRebate() {
-    if (!mony.value || mony.value == '.') {
-        globalPopup?.showWarning('请输入金额')
+    if (!mony.value || mony.value == '.' || Number(mony.value as string) < 0) {
+        globalPopup?.showWarning(Number(mony.value as string) < 0 ? '请不要输入负数' : '请输入金额')
+        return
+    }
+    if(Number(mony.value as string) > info.value.unReceivedPayment) {
+        globalPopup?.showWarning('回款金额超过了未回款金额')
         return
     }
     allLoading.rebateLoading = true

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

@@ -94,7 +94,7 @@ function getAllContacts() {
         options.value = (data.record || []).map((item: any) => ({ value: item.id, label: item.orderName }))
         values.value = rowId.value
     }).catch((err) => {
-        globalPopup?.showError(err.message)
+        globalPopup?.showError(err.msg)
     })
 }
 
@@ -157,12 +157,13 @@ async function getAll(event: allTypeStr) {
         } else if (event == 'getFileList') {
             await getFileList()
         } else if (event == 'getRelatedTasks') {
-            await getFileList()
+            await getRelatedTasks()
         } else if (event == 'getOperationRecord') {
             await getOperationRecord()
         } else if (event == 'getRelatedProducts') {
             await getRelatedProducts()
         } else if (event == 'getPaymentCollectionList') {
+            await getDetail()
             await getPaymentCollectionList()
         }
 

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

@@ -36,31 +36,32 @@
       <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
         <div class="flex justify-end pb-3">
           <!-- 操作按钮 -->
-          <el-button type="primary" @click="editOrder(false)">新建订单</el-button>
+          <el-button type="primary" v-permission="['orderAdd']" @click="editOrder(false)">新建订单</el-button>
           <el-button type="primary" :disabled="batchTableData.length <= 0">批量转移</el-button>
           <el-button type="primary" @click="batchDeteleItem()" :disabled="batchTableData.length <= 0">批量删除</el-button>
           <el-button type="primary" @click="showVisible('deteleOrderVisible')">回收站</el-button>
-          <el-button type="primary" @click="showVisible('importVisible')">导入</el-button>
-          <el-button type="primary" @click="exportOrderTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
+          <el-button type="primary" v-permission="['orderImport']" @click="showVisible('importVisible')">导入</el-button>
+          <el-button type="primary" v-permission="['orderExport']" @click="exportOrderTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
         </div>
         <div class="flex-1 w-full overflow-hidden">
           <!-- 表格 -->
-          <el-table ref="otherTableRef" :data="formTable" border v-loading="allLoading.formTableLading"
+          <el-table ref="otherTableRef" :data="formTable" :show-overflow-tooltip="tableShowOverflowTooltip" border v-loading="allLoading.formTableLading"
             style="width: 100%;height: 100%;" @selection-change="changeBatch">
             <el-table-column type="selection" width="55" />
             <el-table-column v-for="(column, index) in tableColumns" :key="index" :prop="column.prop"
               :label="column.label" :width="column.width">
               <template #default="scope">
                 <template v-if="column.event === 'toDetali'">
-                  <el-button link type="primary" size="large" @click="toDetali(scope.row)">{{ scope.row[column.prop]
-                  }}</el-button>
+                  <!-- <el-button link type="primary" size="large" @click="toDetali(scope.row)">{{ scope.row[column.prop]
+                  }}</el-button> -->
+                  <div class="table-text-textnowrap" @click.prevent="toDetali(scope.row)">{{ scope.row[column.prop] }}</div>
                 </template>
               </template>
             </el-table-column>
-            <el-table-column :label="'操作'" :width="'200px'" fixed="right">
+            <el-table-column :label="'操作'" :width="'200px'" fixed="right" v-permission="['orderEdit']">
               <template #default="scope">
                 <el-button link type="primary" size="large" @click="editOrder(scope.row)">编辑</el-button>
-                <el-button link type="primary" size="large" @click="newTask(scope.row)">新建任务</el-button>
+                <el-button link type="primary" size="large" v-permission="['tasksEdit']" @click="newTask(scope.row)">新建任务</el-button>
                 <el-button link type="danger" size="large"
                   @click="orderDeteleItem(scope.row.id, scope.row.orderName)">删除</el-button>
               </template>
@@ -81,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>
@@ -132,12 +133,13 @@
 import { ref, reactive, onMounted, inject, defineExpose } from "vue";
 import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, getLastDayOfMonth, formatDate, getTemplateKey, createTaskFromType, confirmAction, downloadFile, downloadTemplate } from '@/utils/tools'
 import { post, get, uploadFile } from "@/utils/request";
-import { tableColumns, GETSYSFILED, GETPERSONNEL, GETGENERATEFOEM, MOD, GETTABLELIST, GETALLPRODUCT, GETTABLELISTPRODUCT, URL_OEDERUPDATE, URL_PRODUTWITHORDER, URL_DETELEITEM, EXPORTTIME, IMPORTMOD, IMPORITEM } from "./api";
+import { tableColumns, GETSYSFILED, GETPERSONNEL, GETGENERATEFOEM, MOD, GETTABLELIST, GETALLPRODUCT, GETTABLELISTPRODUCT, URL_OEDERUPDATE, URL_PRODUTWITHORDER, URL_DETELEITEM, EXPORTTIME, IMPORTMOD, IMPORITEM, paymentStatus } from "./api";
 import { useRouter, useRoute } from "vue-router";
 import { GenerateForm } from '@zmjs/form-design';
 import { formatDateTime } from "@/utils/times";
 import { ElTable, UploadRequestOptions } from "element-plus";
 import { createTask } from "@/components/TaskModal/taskFunction";
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
 import { URL_FETALL } from "../customer/api";
 
 import RelatedProducts from '@/components/relatedProducts/relatedProducts.vue'
@@ -200,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>()
@@ -244,7 +246,7 @@ function batchDeteleItem() {
 }
 
 function orderDeteleItem(value: string | number, label: string, batch: boolean = false) {
-  confirmAction(`确定${batch ? '批量' : ''}删除【${label}】客户吗?`).then(() => {
+  confirmAction(`确定${batch ? '批量' : ''}删除【${label}】销售订单吗?`).then(() => {
     post(URL_DETELEITEM, { ids: value }).then(res => {
       if (res.code != 'ok') {
         globalPopup?.showError(res.msg)
@@ -254,7 +256,7 @@ function orderDeteleItem(value: string | number, label: string, batch: boolean =
       changeBatch(false)
       getTableList()
     }).catch((err) => {
-      globalPopup?.showError(err.message)
+      globalPopup?.showError(err.msg)
     })
   })
 }
@@ -295,6 +297,7 @@ function saveOrder(flag: boolean) {
       ...res,
       orderEndDate: res.orderEndDate ? formatDate(res.orderEndDate) : '',
       orderStartDate: res.orderStartDate ? formatDate(res.orderStartDate) : '',
+      placeTime: res.placeTime ? formatDate(res.placeTime) : '',
       orderProductDetailString: produt
     }).then((_res) => {
       allVisible.editOrderVisible = flag
@@ -351,7 +354,13 @@ function getTableList() {
   allLoading.formTableLading = true
   post(GETTABLELIST, { ...formValue, ...formPaging }).then(res => {
     const { total, record } = res.data
-    formTable.value = record
+    formTable.value = (record || []).map((item: any) => {
+      let val = paymentStatus.find((items: any) => items.value == item.status)
+      return {
+        ...item,
+        statusValue: val ? val.label : ''
+      }
+    })
     formTablePaging.total = total
   }).finally(() => {
     allLoading.formTableLading = false

+ 12 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue

@@ -71,10 +71,18 @@ const props = defineProps<{
     data: any,
     information: any
 }>()
+const uploadRef = ref()
 
 // 下载文件
 function fileDownload(item: any) {
-    downloadFile(item.url, `${item.attachmentName}${item.attachmentSuffix}`)
+    downloadFile(item.url, `${removeSuffix(item.attachmentName, item.attachmentSuffix)}${item.attachmentSuffix}`)
+}
+
+function removeSuffix(str: string, suffix: string) {
+    if (str.endsWith(suffix)) {
+        return str.slice(0, -suffix.length);
+    }
+    return str;
 }
 
 // 保存重命名
@@ -122,7 +130,9 @@ async function httpUploadFile(param: UploadRequestOptions) {
     formData.append('file', param.file)
     formData.append('moduleId', id)
     formData.append('moduleCode', MODUCODE)
-    const res = await uploadFile(UPLOADATTACHMENT, formData)
+    const res = await uploadFile(UPLOADATTACHMENT, formData).finally(() => {
+        uploadRef.value.clearFiles()
+    })
     allLoading.uploadLoading = false
     if (res.code == 'ok') {
         globalPopup?.showSuccess('上传成功')

+ 23 - 6
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/information.vue

@@ -3,18 +3,19 @@
         <div class="flex justify-between">
             <div class="title">基本信息</div>
             <div>
-                <el-button type="primary" @click="showVisible('proudDialogVisible')">转移</el-button>
-                <el-button type="primary" @click="editProduct(info)">编辑</el-button>
+                <el-button type="primary" @click="claimProduct()" v-loading="allLoading.claimLoading" v-if="!info.inchargerName">认领</el-button>
+                <el-button type="primary" @click="showVisible('proudDialogVisible')" v-if="info.inchargerName">转移</el-button>
+                <el-button type="primary" v-permission="['productEdit']" @click="editProduct(info)">编辑</el-button>
             </div>
         </div>
         <div class="form flex flex-wrap justify-between">
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-20 text-right text-gray-500">产品编号:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ info.productCode }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{ info.productCode }}</div>
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">产品名称:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ info.productName }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{ info.productName }}</div>
             </div>
             <div class="formItem flex pt-2 pb-1">
                 <div class="w-22 text-right text-gray-500">产品类别:</div>
@@ -50,7 +51,7 @@
             </div>
             <div class="formItem flex pt-2 pb-1" style="width: 100%;">
                 <div class="w-22 text-right text-gray-500">备注:</div>
-                <div class="flex-1 ml-1 text ">
+                <div class="flex-1 ml-1 text " v-ellipsis-tooltip>
                     {{ info.descs }}
                 </div>
             </div>
@@ -129,7 +130,8 @@ const dialogVisible = reactive({
 const allLoading = reactive({
     productLoading: false,
     generateFormLading: false,
-    saveBtnLoading: false
+    saveBtnLoading: false,
+    claimLoading: false
 })
 const allText = reactive({
     productText: '转移产品'
@@ -185,6 +187,21 @@ function transferProduct() {
     })
 }
 
+function claimProduct() {
+    const ids = info.value?.id
+    const inchargerId = userInfo.id
+    allLoading.claimLoading = true
+    post(GETINCHARGER, { id: ids, userId: inchargerId }).then((res) => {
+        if (res.code == 'ok') {
+            globalPopup?.showSuccess('操作成功')
+            dialogVisible.proudDialogVisible = false
+            emits('getInformationData')
+        }
+    }).finally(() => {
+        allLoading.claimLoading = false
+    })
+}
+
 // 显示弹窗
 function showVisible(filed: keyof typeof dialogVisible) {
     if (filed == 'proudDialogVisible') {

+ 23 - 10
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedBusiness.vue

@@ -4,25 +4,25 @@
             <div class="title">相关商机</div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
-            <el-table :data="relatedTaskstable" border style="width: 100%;height: 100%;">
-                <el-table-column prop="taskName" label="任务名称">
+            <el-table :data="relatedTaskstable" :show-overflow-tooltip="tableShowOverflowTooltip" border
+                style="width: 100%;height: 100%;">
+                <el-table-column v-for="(item, index) in tableColumn" :prop="item.prop" :label="item.label" :key="index"
+                    :width="item.width">
                     <template #default="scope">
-                        <el-button link type="primary" size="large">{{
-                            scope.row.taskName
-                        }}</el-button>
+                        <div class="table-text-textnowrap" v-if="item.eventName"
+                            @click="dealWithTableColumn(scope.row, item.eventName)">{{ scope.row[item.prop] }}</div>
+                        <template v-else>{{ scope.row[item.prop] }}</template>
                     </template>
                 </el-table-column>
-                <el-table-column prop="priority" label="优先级" width="130" />
-                <el-table-column prop="status" label="状态" width="130" />
-                <el-table-column prop="executor" label="执行人" width="130" />
-                <el-table-column prop="startTime" label="开始时间" width="130" />
-                <el-table-column prop="endTime" label="截至时间" width="130" />
             </el-table>
         </div>
     </div>
 </template>
 <script lang="ts" setup>
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+import { tableColumn, MOD } from '@/pages/business/api'
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
+import router from '@/router';
 
 const relatedTaskstable = ref([])
 const information: any = ref({})
@@ -38,6 +38,19 @@ function receiveAssignment(item: any) {
     information.value = item.information
 }
 
+function dealWithTableColumn(row: any, eventName: string) {
+  if (eventName == 'toClueTableDetail') {
+    toBusinessTableDetail(row)
+  }
+}
+
+function toBusinessTableDetail(row: any) {
+  router.push({
+    path: `${MOD}/detail`,
+    query: { id: row.id }
+  })
+}
+
 watchEffect(() => {
     receiveAssignment(props)
 });

+ 24 - 15
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/products.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
         <div class="flex justify-between">
-            <div class="title">相关产品</div>
+            <div class="title">相关销售订单</div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
             <el-table :data="relatedTaskstable" border style="width: 100%;height: 300px;">
@@ -10,28 +10,24 @@
                         {{ scope.$index + 1 }}
                     </template>
                 </el-table-column>
-                <el-table-column prop="taskName" label="产品名称">
+                <el-table-column v-for="(column, index) in tableColumns" :key="index" :prop="column.prop"
+                    :label="column.label" :width="column.width">
                     <template #default="scope">
-                        <el-button link type="primary" size="large">{{
-                            scope.row.taskName
-                        }}</el-button>
+                        <template v-if="column.event === 'toDetali'">
+                            <el-button link type="primary" size="large" @click="toDetali(scope.row)">{{
+                                scope.row[column.prop]
+                                }}</el-button>
+                        </template>
                     </template>
                 </el-table-column>
-                <el-table-column prop="priority" label="产品类别" width="130" />
-                <el-table-column prop="status" label="产品类型" width="130" />
-                <el-table-column prop="executor" label="单位" width="130" />
-                <el-table-column prop="startTime" label="标准价格" width="130" />
-                <el-table-column prop="endTime" label="库存" width="130" />
-                <el-table-column prop="endTime" label="售价" width="130" />
-                <el-table-column prop="endTime" label="数量" width="130" />
-                <el-table-column prop="endTime" label="折扣(%)" width="130" />
-                <el-table-column prop="endTime" label="合计" width="130" />
             </el-table>
         </div>
     </div>
 </template>
 <script lang="ts" setup>
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+import { tableColumns, MOD, paymentStatus } from '@/pages/order/api'
+import router from '@/router';
 
 const relatedTaskstable = ref([])
 
@@ -41,7 +37,20 @@ const props = defineProps<{
 
 // 接收参数赋值
 function receiveAssignment(item: any) {
-    relatedTaskstable.value = item.data
+    relatedTaskstable.value = (item.data || []).map((item: any) => {
+      let val = paymentStatus.find((items: any) => items.value == item.status)
+      return {
+        ...item,
+        statusValue: val ? val.label : ''
+      }
+    })
+}
+
+function toDetali(row: any) {
+  router.push({
+    path: `${MOD}/detail`,
+    query: { id: row.id }
+  })
 }
 
 watchEffect(() => {

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

@@ -7,7 +7,7 @@
         </el-link>
       </div>
       <div class="mr-8">
-        <el-select v-model="value" placeholder="请选择" style="width: 150px" @change="getDetail(false)">
+        <el-select v-model="addressParameters" placeholder="请选择" style="width: 250px" @change="getDetail(false)">
           <el-option v-for="item in options" :key="item.id" :label="item.productName" :value="item.id" />
         </el-select>
       </div>
@@ -34,7 +34,7 @@
 
       <div class="w-full h-auto flex justify-between mt-2">
         <div class="bg-white shadow-md rounded-md w-full">
-          <Products :data="products" />
+          <RelatedSalesOrder :data="products" />
         </div>
       </div>
     </div>
@@ -52,9 +52,10 @@ import Information from '../component/information.vue'
 import Attachment from '../component/attachment.vue'
 import RelatedBusiness from '../component/relatedBusiness.vue';
 import OperationRecord from '../component/operationRecord.vue';
-import Products from '../component/products.vue';
+import RelatedSalesOrder from '../component/relatedSalesOrder.vue';
 import { GETBUSINESS, GETDETAIL, GETCENTERLIST, GETORDER, MODUCODE, GETATTACHMENT, GETTABLELIST } from "../api";
 import { post } from "@/utils/request";
+import { number } from "echarts";
 
 const route = useRoute()
 const globalPopup = inject<GlobalPopup>('globalPopup')
@@ -121,7 +122,7 @@ function getProductList() {
 
 onMounted(() => {
   const { id } = route.query
-  addressParameters.value = id
+  addressParameters.value = (id || '') ? Number(id) : ''
   getProductList()
   getDetail(true)
 })

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

@@ -11,17 +11,17 @@
               <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>
+              <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>
             <el-form-item label="状态">
-              <el-select v-model="filterProductForm.status" placeholder="请选择">
-                <el-option v-for="item in fixedData.Personnel" :key="item.id" :label="item.name" :value="item.id" />
+              <el-select v-model="filterProductForm.status" placeholder="请选择" filterable clearable>
+                <el-option v-for="item in SELECTSTATUS" :key="item.value" :label="item.label" :value="item.value" />
               </el-select>
             </el-form-item>
             <el-form-item label="负责人">
-              <el-select v-model="filterProductForm.userId" placeholder="请选择">
+              <el-select v-model="filterProductForm.userId" placeholder="请选择" filterable clearable>
                 <el-option v-for="item in fixedData.Personnel" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
@@ -44,22 +44,23 @@
     <div class="flex-1 p-5 overflow-auto">
       <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
         <div class="flex justify-end pb-3">
-          <el-button type="primary" @click="editProduct(false)">新建产品</el-button>
+          <el-button type="primary" v-permission="['productAdd']" @click="editProduct(false)">新建产品</el-button>
           <el-button type="primary" @click="batchDelete()">批量删除</el-button>
           <el-button type="primary" @click="showDeteleProduct(true)">回收站</el-button>
-          <el-button type="primary" @click="dialogVisible.importVisible = true">导入</el-button>
-          <el-button type="primary" @click="exportProductTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
+          <el-button type="primary" v-permission="['productImport']" @click="dialogVisible.importVisible = true">导入</el-button>
+          <el-button type="primary" v-permission="['productExport']" @click="exportProductTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
         </div>
         <div class="flex-1 w-full overflow-hidden">
-          <el-table ref="productTableRef" :data="productTableList" border v-loading="allLoading.productTableLading"
+          <el-table ref="productTableRef" :show-overflow-tooltip="tableShowOverflowTooltip" :data="productTableList" border v-loading="allLoading.productTableLading"
             style="width: 100%;height: 100%;">
             <el-table-column type="selection" width="55" />
             <el-table-column prop="productCode" label="产品编号" width="180"></el-table-column>
             <el-table-column prop="productName" label="产品名称" width="180">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click="toProductDetail(scope.row)">{{
+                <!-- <el-button link type="primary" size="large" @click="toProductDetail(scope.row)">{{
                   scope.row.productName
-                }}</el-button>
+                }}</el-button> -->
+                <div class="table-text-textnowrap" @click.prevent="toProductDetail(scope.row)">{{ scope.row.productName }}</div>
               </template>
             </el-table-column>
             <el-table-column prop="typeName" label="产品类别" width="180"></el-table-column>
@@ -74,7 +75,7 @@
             <el-table-column prop="inchargerName" label="负责人" width="190"></el-table-column>
             <el-table-column prop="creatorName" label="创建人" width="180"></el-table-column>
             <el-table-column prop="createTime" label="创建时间" width="180"></el-table-column>
-            <el-table-column label="操作" fixed="right" width="200">
+            <el-table-column label="操作" fixed="right" width="200" v-permission="['productEdit']">
               <template #default="scope">
                 <el-button link type="primary" size="large" @click.stop="editProduct(scope.row)">编辑</el-button>
                 <el-button link type="danger" size="large" @click.stop="deteleRow([scope.row])">删除</el-button>
@@ -96,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>
@@ -136,9 +137,10 @@
 
 <script lang="ts" setup>
 import { ref, reactive, onMounted, inject } from "vue";
-import { GETSYSFILED, MOD, MODUCODE, GETPERSONNEL, GETTEMPLATE, GETTABLELIST, ADDPRODUCT, ALLDETELE, UPLOADFILE, EXPORTTIME } from './api'
+import { GETSYSFILED, MOD, MODUCODE, GETPERSONNEL, GETTEMPLATE, GETTABLELIST, ADDPRODUCT, ALLDETELE, UPLOADFILE, EXPORTTIME, SELECTSTATUS } from './api'
 import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, downloadFile, formatDate, createTaskFromType, confirmAction, downloadTemplate } from '@/utils/tools'
 import { FormInstance, FormRules, ElMessageBox, ElTable, UploadRequestOptions } from 'element-plus'
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
 import { post, get, uploadFile } from "@/utils/request";
 import { useRouter, useRoute } from "vue-router";
 import { GenerateForm } from '@zmjs/form-design';
@@ -155,7 +157,7 @@ const filterProductForm = reactive<filterProductFormType>({ // 筛选条件form
   pageIndex: 1,
   pageSize: 10,
   id: '',
-  type: '',
+  productType: '',
   status: '',
 })
 const allLoading = reactive({
@@ -188,7 +190,7 @@ const productTemplate = ref({
   list: [],
   config: {}
 }) // 产品模板
-const genereditForm = ref({}) // 编辑表单
+const genereditForm = ref<any>({}) // 编辑表单
 const generateFormKey = ref(1)
 
 // 方法定义
@@ -311,7 +313,7 @@ function handleCurrentChange(val: number) {
 }
 
 function resetFilter() {
-  let newResetForm = resetFromValue(filterProductForm, { startTime: getFirstDayOfMonth(new Date()), endTime: formatDate(new Date()), pageIndex: 1, pageFrom: 10 })
+  let newResetForm = resetFromValue(filterProductForm, { startTime: getFirstDayOfMonth(new Date()), endTime: formatDate(new Date()), pageIndex: 1, pageSize: 10 })
   Object.assign(filterProductForm, newResetForm)
   getProductTableList()
 }

+ 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/register.vue

@@ -163,7 +163,7 @@ const register = (formEl: FormInstance | undefined) => {
         registerLoading.value = false;
       }
     }).catch(err => {
-      globalPopup?.showError(err.message || err.msg || "注册失败")
+      globalPopup?.showError(err.msg || err.msg || "注册失败")
       registerLoading.value = false;
     })
 

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

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/api.ts

@@ -30,9 +30,9 @@ export const defaultSearchForm = {
 };
 export const PRIORITY = [
   //优先级
-  { label: "", value: 2 },
+  { label: "", value: 2 },
   { label: "中", value: 1 },
-  { label: "", value: 0 },
+  { label: "", value: 0 },
 ];
 export const STATUS: StatusType[] = [
   //任务状态

+ 39 - 17
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/index.vue

@@ -15,7 +15,7 @@
             <el-form-item label="客户名称:" label-width="7em" prop="customName">
               <el-input v-model="searchForm.customName" placeholder="请输入" />
             </el-form-item>
-            <el-form-item label="联系人:" label-width="7em" prop="contactsName">
+            <el-form-item label="联系人号码:" label-width="7em" prop="contactsName">
               <el-input v-model="searchForm.contactsName" placeholder="请输入" />
             </el-form-item>
             <el-form-item label="执行人:" label-width="7em" prop="executorName">
@@ -52,13 +52,14 @@
     <div class="flex-1 p-5 overflow-auto">
       <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
         <div class="ml-auto p-3">
-          <el-button type="primary" @click="createTasks()">创建任务</el-Button>
+          <el-button type="primary" v-permission="['tasksAdd']" @click="createTasks()">创建任务</el-Button>
           <el-button type="primary" :disabled="len == 0" :loading="btnLoading" @click="deleteTasks()">批量删除</el-Button>
-          <el-button type="primary" @click="openImportModal()">导入</el-Button>
-          <el-button type="primary" :loading="btnLoading" @click="exportTasks()">导出</el-Button>
+          <el-button type="primary" v-permission="['tasksImport']" @click="openImportModal()">导入</el-Button>
+          <!-- <el-button type="primary" :loading="btnLoading" @click="exportTasks()">导出</el-Button> -->
+          <el-button type="primary" v-permission="['tasksExport']" :loading="btnLoading" @click="newExportTasks()">导出</el-Button>
         </div>
         <div class="flex-1 overflow-y-auto">
-          <el-table :data="tableData" style="width: 100%;height: 100%;" ref="tableRef" v-loading="loading">
+          <el-table :data="tableData" :show-overflow-tooltip="tableShowOverflowTooltip" style="width: 100%;height: 100%;" ref="tableRef" v-loading="loading">
             <el-table-column type="selection" width="55" />
             <el-table-column prop="taskName" label="任务名称" header-align="center" align="center" show-overflow-tooltip
               width="200" />
@@ -75,19 +76,11 @@
                 </el-text>
               </template>
             </el-table-column>
-            <el-table-column prop="customName" label="执行人" width="120" header-align="center" align="center" />
+            <el-table-column prop="executorNames" label="执行人" width="120" header-align="center" align="center" />
             <el-table-column prop="startDate" label="开始时间" width="200" :sortable="true" header-align="center"
               align="center" value-format="YYYY-MM-DD" />
             <el-table-column prop="endDate" label="截止时间" width="200" :sortable="true" header-align="center"
               align="center" value-format="YYYY-MM-DD" />
-            <el-table-column prop="contactsName" label="联系人" header-align="center" align="center" width="120">
-              <template #default="scope">
-                <el-link :underline="false" type="primary" @click="goDetail(scope.row, 'contacts', 'contactsId')">
-                  {{ scope.row.contactsName }}
-                </el-link>
-              </template>
-            </el-table-column>
-            <el-table-column prop="contactsTel" label="联系人号码" header-align="center" align="center" width="140" />
             <el-table-column prop="customName" label="客户名称" header-align="center" align="center" width="120">
               <template #default="scope">
                 <el-link :underline="false" type="primary" @click="goDetail(scope.row, 'customer', 'customId')">
@@ -117,8 +110,16 @@
                 </el-link>
               </template>
             </el-table-column>
+            <el-table-column prop="contactsName" label="联系人名称" header-align="center" align="center" width="120">
+              <template #default="scope">
+                <el-link :underline="false" type="primary" @click="goDetail(scope.row, 'contacts', 'contactsId')">
+                  {{ scope.row.contactsName }}
+                </el-link>
+              </template>
+            </el-table-column>
+            <el-table-column prop="contactsTel" label="联系人号码" header-align="center" align="center" width="140" />
 
-            <el-table-column fixed="right" label="操作" header-align="center" align="center" width="150">
+            <el-table-column fixed="right" label="操作" header-align="center" align="center" width="160" v-permission="['tasksEdit']">
 
               <template #default="scope">
                 <el-button link type="primary" @click.prevent="editRow(scope.row)">
@@ -165,6 +166,7 @@ import ImportModal from './ImportModal.vue';
 import ExportModal from './ExportModal.vue';
 import { post, uploadFile } from '@/utils/request';
 import { getFromValue, confirmAction, downloadFile } from '@/utils/tools';
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
 import { pushMap } from './type';
 const router = useRouter()
 const { getFunctionList } = useStore()
@@ -206,7 +208,7 @@ function submitForm(data: any, isClose: boolean) {
     search();
   }).catch(err => {
     taskLoading.value = "4"
-    globalPopup?.showError(err.message)
+    globalPopup?.showError(err.msg)
   })
 
 }
@@ -216,6 +218,23 @@ const tableRef = ref<InstanceType<typeof ElTable>>();
 const loading = ref<boolean>(false);
 const totalCount = ref<number>(0);
 const tableData = ref<any[]>([])
+
+function newExportTasks() {
+  btnLoading.value = true
+  const { startDate, endDate } = searchForm.value;
+  let params = {
+    ...searchForm.value,
+    startDate: startDate && dayjs(startDate).format('YYYY-MM-DD 00:00:00'),
+    endDate: endDate && dayjs(endDate).format('YYYY-MM-DD 23:59:59')
+  }
+  post(EXPORT_DATA_BY_TASK_ID, {...getFromValue(params)}).then((res) => {
+    globalPopup?.showSuccess("导出成功")
+    downloadFile(res.data, "任务列表.xlsx");
+  }).finally(() => {
+    btnLoading.value = false
+  })
+}
+
 function search() {
   loading.value = true;
   const { startDate, endDate } = searchForm.value;
@@ -228,7 +247,10 @@ function search() {
     loading.value = false;
     const { total, record } = data;
     totalCount.value = total;
-    tableData.value = record;
+    tableData.value = record.map((item: any) => ({
+      ...item,
+      executorNames: item.taskExecutors?.join(',') ?? ''
+    }));
   }).catch(err => {
     globalPopup?.showError(err);
     loading.value = false;

+ 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'

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

@@ -8,7 +8,7 @@
               <el-input v-model="filterCriteriaForm.clueName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="线索来源">
-              <el-select v-model="filterCriteriaForm.clueSourceId" placeholder="请选择" clearable>
+              <el-select v-model="filterCriteriaForm.clueSourceId" placeholder="请选择" clearable filterable>
                 <el-option v-for="item in fixedData.ClueSources" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
@@ -19,17 +19,17 @@
               <el-input v-model="filterCriteriaForm.email" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="客户行业">
-              <el-select v-model="filterCriteriaForm.customerIndustryId" placeholder="请选择">
+              <el-select v-model="filterCriteriaForm.customerIndustryId" placeholder="请选择" filterable clearable>
                 <el-option v-for="item in fixedData.CustomIndustry" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
             <el-form-item label="客户级别">
-              <el-select v-model="filterCriteriaForm.customerLevelId" placeholder="请选择">
+              <el-select v-model="filterCriteriaForm.customerLevelId" placeholder="请选择" filterable clearable>
                 <el-option v-for="item in fixedData.CustomLevel" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
             <el-form-item label="负责人">
-              <el-select v-model="filterCriteriaForm.inchargerId" placeholder="请选择">
+              <el-select v-model="filterCriteriaForm.inchargerId" placeholder="请选择" filterable clearable>
                 <el-option v-for="item in fixedData.Personnel" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
@@ -72,7 +72,7 @@
             <el-table-column prop="phone" label="电话号码" width="180"></el-table-column>
             <el-table-column prop="email" label="邮箱" width="180"></el-table-column>
             <el-table-column prop="customerIndustryValue" label="客户行业" width="180"></el-table-column>
-            <el-table-column prop="customerLevelValue" label="客户级别" width="180" sortable></el-table-column>
+            <el-table-column prop="customerLevelValue" label="客户级别" width="180" sortable="custom"></el-table-column>
             <el-table-column prop="inchargerName" label="负责人" width="190"></el-table-column>
             <el-table-column prop="createName" label="创建人" width="180"></el-table-column>
             <el-table-column prop="createTime" label="创建时间" width="180"></el-table-column>
@@ -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([])
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 10821 - 37852
fhKeeper/formulahousekeeper/management-crm/crm.log


+ 10 - 11
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ProductController.java

@@ -7,6 +7,7 @@ import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.*;
 import com.management.platform.util.BeanChangeUtil;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -54,6 +55,8 @@ public class ProductController {
     private SalesOrderService salesOrderService;
     @Resource
     private SysDictService sysDictService;
+    @Resource
+    private StageService stageService;
 
 
     /**
@@ -77,6 +80,7 @@ public class ProductController {
     * @Date: 2024/5/21
     */
     @RequestMapping("/addOrUpdate")
+    @Transactional
     public HttpRespMsg addOrUpdate(Product product){
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
@@ -97,18 +101,17 @@ public class ProductController {
         AuditLogCenter auditLogCenter =new AuditLogCenter();
         auditLogCenter.setAuditorId(user.getId());
         auditLogCenter.setAuditorName(user.getName());
-        boolean isNew=true;
+        auditLogCenter.setModuleId(product.getId());
+        auditLogCenter.setModuleCode("Product");
         if(product.getId()==null){
             auditLogCenter.setAuditorContent("创建了产品");
+            auditLogCenterService.save(auditLogCenter);
         }else {
             Product oldProduct = productService.getById(product.getId());
             BeanChangeUtil<Product> beanChangeUtil = new BeanChangeUtil();
             String content = beanChangeUtil.contrastObj(oldProduct, product);
             //发生变化才生成记录
             if(!StringUtils.isEmpty(content.trim())){
-                isNew=false;
-                auditLogCenter.setModuleId(product.getId());
-                auditLogCenter.setModuleCode("Product");
                 auditLogCenter.setAuditorContent("编辑了产品");
                 auditLogCenterService.save(auditLogCenter);
             }
@@ -118,11 +121,6 @@ public class ProductController {
             msg.setError("验证失败");
             return msg;
         }
-        if(isNew){
-            auditLogCenter.setModuleId(product.getId());
-            auditLogCenter.setModuleCode("Product");
-            auditLogCenterService.save(auditLogCenter);
-        }
         return msg;
     }
 
@@ -268,7 +266,8 @@ public class ProductController {
         List<BusinessOpportunity> opportunityList = businessOpportunityService.list(new LambdaQueryWrapper<BusinessOpportunity>().in(BusinessOpportunity::getId, businessIds));
         List<Custom> customList = customService.list(new LambdaQueryWrapper<Custom>().eq(Custom::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<SysDict> businessStageList = sysDictService.list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, "BusinessStage"));
+//        List<SysDict> businessStageList = sysDictService.list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, "BusinessStage"));
+        List<Stage> businessStageList = stageService.list(new LambdaQueryWrapper<Stage>().eq(Stage::getCompanyId, companyId));
         opportunityList.forEach(c->{
             Optional<Custom> custom = customList.stream().filter(ct -> ct.getId().equals(c.getCustomerId())).findFirst();
             if(custom.isPresent()){
@@ -282,7 +281,7 @@ public class ProductController {
             if(incharger.isPresent()){
                 c.setInchargerName(incharger.get().getName());
             }
-            Optional<SysDict> businessStage = businessStageList.stream().filter(b -> b.getId().equals(c.getStageId())).findFirst();
+            Optional<Stage> businessStage = businessStageList.stream().filter(b -> b.getId().equals(c.getStageId())).findFirst();
             if(businessStage.isPresent()){
                 c.setStageValue(businessStage.get().getName());
             }

+ 40 - 11
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SalesOrderController.java

@@ -9,6 +9,7 @@ import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.*;
 import com.management.platform.util.BeanChangeUtil;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -50,6 +51,8 @@ public class SalesOrderController {
     private AuditLogCenterService auditLogCenterService;
     @Resource
     private SalesOrderPaymentService salesOrderPaymentService;
+    @Resource
+    private ProductService productService;
 
 
     /**
@@ -58,8 +61,8 @@ public class SalesOrderController {
     @RequestMapping("/list")
     public HttpRespMsg list(String inchargerId,Integer orderType, String orderName,
                             String orderCode,Integer customId,String businessName,
-                            Integer receivedStatus,String startDate,String endDate, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete){
-        return salesOrderService.getList(inchargerId,orderType,orderName,orderCode,customId,businessName,receivedStatus,startDate,endDate,productCode,pageIndex,pageSize,isDelete);
+                            Integer receivedStatus,String startTime,String endTime, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete){
+        return salesOrderService.getList(inchargerId,orderType,orderName,orderCode,customId,businessName,receivedStatus,startTime,endTime,productCode,pageIndex,pageSize,isDelete);
     }
 
     /**
@@ -79,6 +82,7 @@ public class SalesOrderController {
      * 新增编辑订单数据
      * */
     @RequestMapping("/addOrUpdate")
+    @Transactional
     public HttpRespMsg addOrUpdate(SalesOrder order){
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
@@ -88,16 +92,23 @@ public class SalesOrderController {
         if(order.getPrice()!=null){
             order.setUnReceivedPayment(order.getPrice());
         }
-        int count;
+        int countCode;
+        int countName;
         if(order.getId()==null){
-            count = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).eq(SalesOrder::getOrderCode, order.getOrderCode()));
+            countCode = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).eq(SalesOrder::getOrderCode, order.getOrderCode()));
+            countName = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).eq(SalesOrder::getOrderName, order.getOrderName()));
         }else {
-            count = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).ne(SalesOrder::getId,order.getId()).eq(SalesOrder::getOrderCode,order.getOrderCode()));
+            countCode = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).ne(SalesOrder::getId,order.getId()).eq(SalesOrder::getOrderCode,order.getOrderCode()));
+            countName = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).ne(SalesOrder::getId,order.getId()).eq(SalesOrder::getOrderName,order.getOrderName()));
         }
-        if(count>0){
+        if(countCode>0){
             msg.setError("订单编号为["+order.getOrderCode()+"]的订单已存在");
             return msg;
         }
+        if(countName>0){
+            msg.setError("订单名称为["+order.getOrderCode()+"]的订单已存在");
+            return msg;
+        }
         //todo:生成操作记录
         AuditLogCenter auditLogCenter =new AuditLogCenter();
         auditLogCenter.setAuditorId(user.getId());
@@ -125,10 +136,24 @@ public class SalesOrderController {
         if(!StringUtils.isEmpty(order.getOrderProductDetailString())){
             String orderProductDetailString = order.getOrderProductDetailString();
             List<OrderProductDetail> orderProductDetails = JSONArray.parseArray(orderProductDetailString, OrderProductDetail.class);
+            List<Integer> productIds = orderProductDetails.stream().map(OrderProductDetail::getProductId).distinct().collect(Collectors.toList());
+            productIds.add(-1);
+            List<Product> productList = productService.list(new LambdaQueryWrapper<Product>().in(Product::getId, productIds));
             if(orderProductDetails.size()>0){
-                orderProductDetails.forEach(o->{
-                    o.setOrderId(order.getId());
-                });
+                for (OrderProductDetail orderProductDetail : orderProductDetails) {
+                    orderProductDetail.setOrderId(order.getId());
+                    Optional<Product> first = productList.stream().filter(p -> p.getId().equals(orderProductDetail.getProductId())).findFirst();
+                    if(first.isPresent()){
+                        if(orderProductDetail.getNum().intValue()>first.get().getInventory()){
+                            try {
+                                throw new Exception("相关产品["+first.get().getProductName()+"]库存数量不足");
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                                msg.setError(e.getMessage());
+                            }
+                        }
+                    }
+                }
                 orderProductDetailService.saveOrUpdateBatch(orderProductDetails);
             }
         }
@@ -285,8 +310,8 @@ public class SalesOrderController {
     * @Date: 2024/5/14
     */
     @RequestMapping("/exportData")
-    public HttpRespMsg exportData(String userId, String orderName,String orderCode, String productCode) throws Exception {
-        return salesOrderService.exportData(userId,orderName,orderCode,productCode);
+    public HttpRespMsg exportData(String userId, String orderName,String orderCode, String productCode,String startTime,String endTime) throws Exception {
+        return salesOrderService.exportData(userId,orderName,orderCode,productCode,startTime,endTime);
     }
 
 
@@ -364,6 +389,10 @@ public class SalesOrderController {
         SalesOrderPayment salesOrderPayment=new SalesOrderPayment();
         salesOrderPayment.setMoney(new BigDecimal(money));
         salesOrderPayment.setOrderId(orderId);
+        if(money>salesOrder.getUnReceivedPayment().doubleValue()){
+            msg.setError("回款金额不能大于当前未回款金额");
+            return msg;
+        }
         //订单已回款金额
         BigDecimal receivedPayment = salesOrder.getReceivedPayment();
         //订单未回款金额

+ 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;
+
 
 }

+ 2 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/SalesOrderService.java

@@ -17,11 +17,11 @@ public interface SalesOrderService extends IService<SalesOrder> {
 
     HttpRespMsg getList(String inchargerId,Integer orderType, String orderName,
                         String orderCode,Integer customId,String businessName,
-                        Integer receivedStatus,String startDate,String endDate, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete);
+                        Integer receivedStatus,String startTime,String endTime, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete);
 
     HttpRespMsg importData(MultipartFile multipartFile);
 
-    HttpRespMsg exportData(String userId, String orderName, String orderCode, String productCode) throws Exception;
+    HttpRespMsg exportData(String userId, String orderName, String orderCode, String productCode,String startTime,String endTime) throws Exception;
 
     HttpRespMsg salesKit(Integer queryType,Integer dateType, String startDate, String endDate);
 

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

+ 68 - 8
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java

@@ -122,11 +122,12 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
                 deptIds=deptIds.stream().distinct().collect(Collectors.toList());
                 List<Integer> finalDeptIds2 = deptIds;
                 List<String> userIds = userList.stream().filter(u -> finalDeptIds2.contains(u.getDepartmentId())).map(User::getId).collect(Collectors.toList());
+                userIds.add("-1");
                 queryWrapper.in(Product::getCreatorId,userIds);
             }
         }
         if(!StringUtils.isEmpty(userId)){
-            queryWrapper.eq(Product::getCreatorId,userId);
+            queryWrapper.eq(Product::getInchargerId,userId);
         }
         if(!StringUtils.isEmpty(productName)){
             queryWrapper.like(Product::getProductName,productName);
@@ -150,6 +151,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
             pageIndex=-1;
             pageSize=-1;
         }
+        queryWrapper.orderByDesc(Product::getCreateTime);
         IPage<Product> productIPage = productMapper.selectPage(new Page<>(pageIndex, pageSize,true), queryWrapper);
         List<Product> records = productIPage.getRecords();
         records.forEach(r->{
@@ -514,13 +516,71 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
     @Override
     public HttpRespMsg recycleList(Integer pageIndex, Integer pageSize) {
         HttpRespMsg msg=new HttpRespMsg();
-        User user = userMapper.selectById(request.getHeader("token"));
-        LambdaQueryWrapper<Product> productLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        productLambdaQueryWrapper.eq(Product::getCompanyId,user.getCompanyId());
-        productLambdaQueryWrapper.eq(Product::getIsDelete,1);
-        IPage<Product> productIPage = productMapper.selectPage(new Page<>(pageIndex, pageSize), productLambdaQueryWrapper);
-        Map<String,Object> map=new HashMap<>();
-        map.put("record",productIPage.getRecords());
+        User targetUsr = userMapper.selectById(request.getHeader("token"));
+        Integer companyId=targetUsr.getCompanyId();
+        List<Department> departments = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
+        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(Product::getCompanyId,companyId);
+        queryWrapper.eq(Product::getIsDelete,1);
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
+        List<SysDict> sysDictOfProductType = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ProductType"));
+        List<SysDict> sysDictOfProductUnit = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ProductUnit"));
+        boolean hasPriviledgeAll = sysFunctionService.hasPriviledge(targetUsr.getRoleId(), "查看全部产品数据");
+        boolean hasPriviledgeDept = sysFunctionService.hasPriviledge(targetUsr.getRoleId(), "查看负责部门产品数据");
+        //判断查看全部的权限
+        if(!hasPriviledgeAll){
+            //判断查看负责部门的权限
+            if(!hasPriviledgeDept){
+                //都没有就只能看自己创建的
+                queryWrapper.eq(Product::getCreatorId,targetUsr.getId());
+            }else {
+                List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getManagerId, targetUsr.getId()));
+                List<DepartmentOtherManager> otherManagerList = departmentOtherManagerMapper.selectList(new LambdaQueryWrapper<DepartmentOtherManager>().eq(DepartmentOtherManager::getOtherManagerId, targetUsr.getId()));
+                List<Integer> deptIds=new ArrayList<>();
+                deptIds.add(-1);
+                List<Integer> managerDeptIds = departmentList.stream().map(Department::getDepartmentId).distinct().collect(Collectors.toList());
+                List<Integer> otherManagerDeptIds = otherManagerList.stream().map(DepartmentOtherManager::getDepartmentId).distinct().collect(Collectors.toList());
+                deptIds.addAll(managerDeptIds);
+                List<Integer> finalDeptIds1 = deptIds;
+                managerDeptIds.forEach(m->{
+                    List<Integer> branchDepartment = getBranchDepartment(m, departments);
+                    finalDeptIds1.addAll(branchDepartment);
+                });
+                deptIds.addAll(otherManagerDeptIds);
+                List<Integer> finalDeptIds = deptIds;
+                otherManagerDeptIds.forEach(o->{
+                    List<Integer> branchDepartment = getBranchDepartment(o, departments);
+                    finalDeptIds.addAll(branchDepartment);
+                });
+                deptIds=deptIds.stream().distinct().collect(Collectors.toList());
+                List<Integer> finalDeptIds2 = deptIds;
+                List<String> userIds = userList.stream().filter(u -> finalDeptIds2.contains(u.getDepartmentId())).map(User::getId).collect(Collectors.toList());
+                userIds.add("-1");
+                queryWrapper.in(Product::getCreatorId,userIds);
+            }
+        }
+        IPage<Product> productIPage = productMapper.selectPage(new Page<>(pageIndex, pageSize,true), queryWrapper);
+        List<Product> records = productIPage.getRecords();
+        records.forEach(r->{
+            Optional<User> user = userList.stream().filter(u -> u.getId().equals(r.getInchargerId())).findFirst();
+            if(user.isPresent()){
+                r.setInchargerName(user.get().getName());
+            }
+            Optional<User> creator = userList.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
+            if(creator.isPresent()){
+                r.setCreatorName(creator.get().getName());
+            }
+            Optional<SysDict> unit = sysDictOfProductUnit.stream().filter(u -> u.getId().equals(r.getUnit())).findFirst();
+            if(unit.isPresent()){
+                r.setUnitName(unit.get().getName());
+            }
+            Optional<SysDict> type = sysDictOfProductType.stream().filter(u -> u.getId().equals(r.getType())).findFirst();
+            if(type.isPresent()){
+                r.setTypeName(type.get().getName());
+            }
+        });
+        Map map=new HashMap();
+        map.put("record",records);
         map.put("total",productIPage.getTotal());
         msg.setData(map);
         return msg;

+ 13 - 11
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java

@@ -94,7 +94,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
     @Override
     public HttpRespMsg getList(String inchargerId,Integer orderType, String orderName,
                                String orderCode,Integer customId,String businessName,
-                               Integer receivedStatus,String startDate,String endDate, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete) {
+                               Integer receivedStatus,String startTime,String endTime, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete) {
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         List<Department> departments = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, user.getCompanyId()));
@@ -116,8 +116,8 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
         if(!viewAll){
             //判断查看负责部门的权限
             if(!viewDept){
-                //都没有就只能看自己创建的
-                orderLambdaQueryWrapper.eq(SalesOrder::getCreatorId,user.getId());
+                //都没有就只能看自己创建的或者负责的
+                orderLambdaQueryWrapper.and(wrapper->wrapper.eq(SalesOrder::getCreatorId,user.getId()).or().eq(SalesOrder::getInchargerId,user.getId()));
             }else {
                 List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getManagerId, user.getId()));
                 List<DepartmentOtherManager> otherManagerList = departmentOtherManagerMapper.selectList(new LambdaQueryWrapper<DepartmentOtherManager>().eq(DepartmentOtherManager::getOtherManagerId, user.getId()));
@@ -140,7 +140,8 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
                 deptIds=deptIds.stream().distinct().collect(Collectors.toList());
                 List<Integer> finalDeptIds2 = deptIds;
                 List<String> userIds = userList.stream().filter(u -> finalDeptIds2.contains(u.getDepartmentId())).map(User::getId).collect(Collectors.toList());
-                orderLambdaQueryWrapper.in(SalesOrder::getCreatorId,userIds);
+                userIds.add("-1");
+                orderLambdaQueryWrapper.and(wrapper->wrapper.in(SalesOrder::getCreatorId,userIds).or().in(SalesOrder::getInchargerId,userIds));
             }
         }
         if (!StringUtils.isEmpty(inchargerId)){
@@ -164,8 +165,8 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
                 orderLambdaQueryWrapper.and(wrapper->wrapper.isNull(SalesOrder::getReceivedPayment).or().eq(SalesOrder::getReceivedPayment,0));
             }
         }
-        if(!StringUtils.isEmpty(startDate)&&!StringUtils.isEmpty(endDate)){
-            orderLambdaQueryWrapper.lt(SalesOrder::getOrderStartDate,endDate).gt(SalesOrder::getOrderEndDate,startDate);
+        if(!StringUtils.isEmpty(startTime)&&!StringUtils.isEmpty(endTime)){
+            orderLambdaQueryWrapper.lt(SalesOrder::getOrderStartDate,endTime).gt(SalesOrder::getOrderEndDate,startTime);
         }
         if(!StringUtils.isEmpty(orderName)){
             orderLambdaQueryWrapper.like(SalesOrder::getOrderName,orderName);
@@ -182,6 +183,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
             pageIndex=-1;
             pageSize=-1;
         }
+        orderLambdaQueryWrapper.orderByDesc(SalesOrder::getCreateTime);
         IPage<SalesOrder> orderIPage = salesOrderMapper.selectPage(new Page<>(pageIndex, pageSize), orderLambdaQueryWrapper);
         List<SalesOrder> records = orderIPage.getRecords();
         List<Integer> orderIds = records.stream().map(SalesOrder::getId).distinct().collect(Collectors.toList());
@@ -560,7 +562,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
     }
 
     @Override
-    public HttpRespMsg exportData(String userId, String orderName, String orderCode, String productCode) throws Exception {
+    public HttpRespMsg exportData(String userId, String orderName, String orderCode, String productCode,String startTime,String endTime) throws Exception {
         User user = userMapper.selectById(request.getHeader("token"));
         SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCompanyId, user.getCompanyId()).eq(SysForm::getCode, "Order").eq(SysForm::getIsCurrent, 1));
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
@@ -586,7 +588,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
             }
         }
         dataList.add(titleList);
-        HttpRespMsg respMsg = getList( userId,null, orderName,orderCode,null,null,null,null,null,productCode, null,null,0);
+        HttpRespMsg respMsg = getList( userId,null, orderName,orderCode,null,null,null,startTime,endTime,productCode, null,null,0);
         Map<String, Object> msgData = (Map<String, Object>) respMsg.getData();
         List<SalesOrder> salesOrderList = (List<SalesOrder>) msgData.get("record");
         for (SalesOrder salesOrder : salesOrderList) {
@@ -794,7 +796,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
         double businessOpportunityPrice = businessOpportunityList.stream().filter(b->!StringUtils.isEmpty(b.getAmountOfMoney())).mapToDouble(b ->Double.valueOf(b.getAmountOfMoney())).sum();
         Integer salesOrderCount = salesOrderMapper.selectCount(salesOrderLambdaQueryWrapper);
         List<SalesOrder> salesOrders = salesOrderMapper.selectList(salesOrderLambdaQueryWrapper);
-        double salesOrdersPrice = salesOrders.stream().mapToDouble(s -> s.getPrice().doubleValue()).sum();
+        double salesOrdersPrice = salesOrders.stream().filter(i->i.getPrice()!=null).mapToDouble(s -> s.getPrice().doubleValue()).sum();
         Integer clueCount = clueMapper.selectCount(clueLambdaQueryWrapper);
 
         int customCount1 = customService.count(customLambdaQueryWrapper1);
@@ -804,7 +806,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
         double businessOpportunityPrice1 = businessOpportunityList1.stream().filter(b->!StringUtils.isEmpty(b.getAmountOfMoney())).mapToDouble(b -> Double.valueOf(b.getAmountOfMoney())).sum();
         Integer salesOrderCount1 = salesOrderMapper.selectCount(salesOrderLambdaQueryWrapper1);
         List<SalesOrder> salesOrders1 = salesOrderMapper.selectList(salesOrderLambdaQueryWrapper1);
-        double salesOrdersPrice1 = salesOrders1.stream().mapToDouble(s -> s.getPrice().doubleValue()).sum();
+        double salesOrdersPrice1 = salesOrders1.stream().filter(s->s.getPrice()!=null).mapToDouble(s ->s.getPrice().doubleValue()).sum();
         Integer clueCount1 = clueMapper.selectCount(clueLambdaQueryWrapper1);
         Map<String,Object> customMap=new HashMap<>();
         customMap.put("customCount",customCount);
@@ -819,7 +821,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
         businessOpportunityMap.put("businessOpportunityPromote",getPromote(businessOpportunityCount,businessOpportunityCount1));
         resultMap.put("businessOpportunity",businessOpportunityMap);
         Map<String,Object> businessOpportunityPriceMap=new HashMap<>();
-        businessOpportunityPriceMap.put("businessOpportunityPrice",businessOpportunityPrice);
+        businessOpportunityPriceMap.put("businessOpportunityPrice",String.format("%.2f",businessOpportunityPrice));
         businessOpportunityPriceMap.put("businessOpportunityPromote",getPromote((int)businessOpportunityPrice,(int)businessOpportunityPrice1));
         resultMap.put("businessOpportunityPrice",businessOpportunityPriceMap);
         Map<String,Object> salesOrderMap=new HashMap<>();

+ 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);
             }

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

@@ -245,7 +245,7 @@
     <select id="getDataSummary" resultType="java.util.Map">
         SELECT COUNT(*) newNum,SUM(bo.amount_of_money) AS allAmountOfMoney,SUM(s.name='赢单') winning,SUM(s.name='输单') losting  FROM business_opportunity bo
         LEFT JOIN stage s ON bo.stage_id=s.id
-        WHERE company_id=#{companyId} and is_delete=0
+        WHERE bo.company_id=#{companyId} and is_delete=0
         <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''">
             and DATE_FORMAT(bo.create_time,'%Y-%m-%d') BETWEEN #{startDate} AND #{endDate}
         </if>

+ 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">

+ 20 - 6
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -131,6 +131,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     private ProductMapper productMapper;
     @Resource
     private ProdProcedureMapper prodProcedureMapper;
+    @Resource
+    private LeaveSheetService leaveSheetService;
 
     @Value(value = "${upload.path}")
     private String path;
@@ -4114,6 +4116,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         personWorkHoursWagesList.addAll(totalList);
         //日期范围内所有分配数据
         List<ProdProcedureTeam> allProcedureTeamList = prodProcedureTeamMapper.selectList(new LambdaQueryWrapper<ProdProcedureTeam>().between(ProdProcedureTeam::getDistributeDate, startDate, endDate));
+        //日期范围内所有请假数据
+        List<LeaveSheet> leaveSheetList = leaveSheetService.list(new LambdaQueryWrapper<LeaveSheet>().le(LeaveSheet::getStartDate, endDate).ge(LeaveSheet::getEndDate, startDate));
         //日期范围内所有派工数据
         List<Integer> ids = allProcedureTeamList.stream().map(ProdProcedureTeam::getPlanProcedureId).distinct().collect(Collectors.toList());
         List<PlanProcedureTotal> planProcedureTotalList = planProcedureTotalMapper.selectList(new LambdaQueryWrapper<PlanProcedureTotal>().in(PlanProcedureTotal::getId, ids));
@@ -4168,6 +4172,14 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 } else {
                     Map map = new HashMap();
+                    //不存在报工数据显示请假详情数据
+                    boolean match = leaveSheetList.stream().anyMatch(l ->
+                            (l.getStartDate().isBefore(LocalDate.parse(date, dtf1)) || l.getStartDate().isEqual(LocalDate.parse(date, dtf1)))
+                                    &&
+                                    (l.getEndDate().isAfter(LocalDate.parse(date, dtf1)) || l.getEndDate().isEqual(LocalDate.parse(date, dtf1))) && l.getOwnerId().equals(u.getId()));
+                    if(match){
+                        map.put("leave","当天请假");
+                    }
                     map.put("crateDate", date);
                     map.put("cost", 0);
                     map.put("workTime", 0);
@@ -4285,12 +4297,14 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         List<Integer> deptIds = departmentList.stream().map(Department::getDepartmentId).distinct().collect(Collectors.toList());
         List<Integer> otherDeptIds = departmentOtherManagers.stream().map(DepartmentOtherManager::getDepartmentId).distinct().collect(Collectors.toList());
         deptIds.addAll(otherDeptIds);
+        //日期范围内所有请假数据
+        List<LeaveSheet> leaveSheetList = leaveSheetService.list(new LambdaQueryWrapper<LeaveSheet>().le(LeaveSheet::getStartDate, endDate).ge(LeaveSheet::getEndDate, startDate).eq(LeaveSheet::getOwnerId,userId));
         List<Map<String,Object>> mapList=reportMapper.getPersonWorkHoursWagesDetail(date,userId,user.getCompanyId(),startDate,endDate,checkStatus,detailStatus);
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         HashMap map=new HashMap();
         map.put("record",mapList);
-        map.put("totalWorkingTime",mapList.stream().mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
-        map.put("totalCost",mapList.stream().mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
+        map.put("totalWorkingTime",mapList.stream().filter(i->i.get("working_time")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
+        map.put("totalCost",mapList.stream().filter(i->i.get("cost")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
         if(checkStatus!=null && detailStatus==null){
             mapList=reportMapper.getPersonWorkHoursWagesDetail(date,user.getId(),user.getCompanyId(),startDate,endDate,checkStatus,detailStatus);
             DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy-MM-dd");
@@ -4359,13 +4373,13 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 }
                 item.put("subDataList",theData);
-                item.put("working_time",list.stream().mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
-                item.put("cost",list.stream().mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
+                item.put("working_time",list.stream().filter(i->i.get("working_time")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
+                item.put("cost",list.stream().filter(i->i.get("cost")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
                 resultList.add(item);
             }
             map.put("record",resultList);
-            map.put("totalWorkingTime",resultList.stream().mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
-            map.put("totalCost",resultList.stream().mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
+            map.put("totalWorkingTime",resultList.stream().filter(i->i.get("working_time")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
+            map.put("totalCost",resultList.stream().filter(i->i.get("cost")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
         }
         httpRespMsg.setData(map);
         return httpRespMsg;

+ 43 - 12
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml

@@ -154,20 +154,51 @@
         </if>
         group by b.id, a.create_date
     </select>
+<!--修改前 人员工时工价表详情数据-->
+<!--    <select id="getPersonWorkHoursWagesDetail" resultType="java.util.Map">-->
+<!--        select r.cost,r.working_time,r.finish_num, r.creator_id,ppt.total_progress as progress,DATE_FORMAT(r.create_date,'%Y%m%d') as createDate,pp.name as procedureName,(case  when pp.check_type=0 then '自检' when pp.check_type=1 then '互检' else '专检' end) as checkType,-->
+<!--        p.name as productName,DATE_FORMAT(plan.start_date,'%Y%m%d') as planStartDate,DATE_FORMAT(plan.end_date,'%Y%m%d') as planEndDate ,-->
+<!--        plan.task_change_notice_num as taskName,plan.plan_type as planType,u.name as checkerName,u2.name as creatorName,plan.product_scheduling_num,r.finish_num as finishNum-->
+<!--        from report r-->
+<!--        left join prod_procedure_team ppt2 on r.user_procedure_team_id=ppt2.id-->
+<!--        left join prod_procedure pp on r.prod_procedure_id=pp.id-->
+<!--        left join plan_procedure_total ppt on ppt.id=ppt2.plan_procedure_id-->
+<!--        left join product p on p.id=r.product_id-->
+<!--        left join plan on plan.id=r.plan_id-->
+<!--        left join user u on r.checker_id=u.id-->
+<!--        left join user u2 on r.creator_id=u2.id-->
+<!--        where r.company_id=#{companyId}  and r.finish_num &gt; 0-->
+<!--        <if test="date!=null and date!=''">-->
+<!--            and r.create_date=#{date}-->
+<!--        </if>-->
+<!--        <if test="userId!=null and userId!=''">-->
+<!--            <choose>-->
+<!--                <when test="checkStatus!=null and checkStatus==1 and detailStatus==null">-->
+<!--                    and plan.foreman_id=#{userId}-->
+<!--                </when>-->
+<!--                <otherwise>-->
+<!--                    and r.creator_id=#{userId}-->
+<!--                </otherwise>-->
+<!--            </choose>-->
+<!--        </if>-->
+<!--        <if test="startDate!=null and endDate!=null">-->
+<!--            and r.create_date between #{startDate} and #{endDate}-->
+<!--        </if>-->
+<!--    </select>-->
 
     <select id="getPersonWorkHoursWagesDetail" resultType="java.util.Map">
-        select r.cost,r.working_time,r.finish_num, r.creator_id,ppt.total_progress as progress,DATE_FORMAT(r.create_date,'%Y%m%d') as createDate,pp.name as procedureName,(case  when pp.check_type=0 then '自检' when pp.check_type=1 then '互检' else '专检' end) as checkType,
+        select r.cost,r.working_time,r.finish_num as finish_num, r.creator_id,ppt.total_progress as progress,DATE_FORMAT(r.create_date,'%Y%m%d') as createDate,pp.name as procedureName,(case  when pp.check_type=0 then '自检' when pp.check_type=1 then '互检' else '专检' end) as checkType,
         p.name as productName,DATE_FORMAT(plan.start_date,'%Y%m%d') as planStartDate,DATE_FORMAT(plan.end_date,'%Y%m%d') as planEndDate ,
         plan.task_change_notice_num as taskName,plan.plan_type as planType,u.name as checkerName,u2.name as creatorName,plan.product_scheduling_num,r.finish_num as finishNum
-        from report r
-        left join prod_procedure_team ppt2 on r.user_procedure_team_id=ppt2.id
-        left join prod_procedure pp on r.prod_procedure_id=pp.id
-        left join plan_procedure_total ppt on ppt.id=ppt2.plan_procedure_id
-        left join product p on p.id=r.product_id
-        left join plan on plan.id=r.plan_id
-        left join user u on r.checker_id=u.id
-        left join user u2 on r.creator_id=u2.id
-        where r.company_id=#{companyId}  and r.finish_num &gt; 0
+        FROM prod_procedure_team ppt2
+        LEFT JOIN plan_procedure_total ppt ON ppt.id=ppt2.plan_procedure_id
+        LEFT JOIN plan ON plan.id=ppt.plan_id
+        LEFT JOIN report r ON r.user_procedure_team_id=ppt2.id
+        LEFT JOIN prod_procedure pp ON ppt.prod_procedure_id=pp.id
+        LEFT JOIN product p ON p.id=plan.product_id
+        LEFT JOIN USER u ON r.checker_id=u.id
+        LEFT JOIN USER u2 ON r.creator_id=u2.id
+        WHERE ppt2.company_id=#{companyId}
         <if test="date!=null and date!=''">
             and r.create_date=#{date}
         </if>
@@ -177,12 +208,12 @@
                     and plan.foreman_id=#{userId}
                 </when>
                 <otherwise>
-                    and r.creator_id=#{userId}
+                    and ppt2.user_id=#{userId}
                 </otherwise>
             </choose>
         </if>
         <if test="startDate!=null and endDate!=null">
-            and r.create_date between #{startDate} and #{endDate}
+            and ppt2.distribute_date between #{startDate} and #{endDate}
         </if>
     </select>
 

+ 5 - 4
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue

@@ -91,8 +91,9 @@
                         <div v-for="(items, indexs) in scope.row.personWorkHoursWages" :key="indexs" @click="showReportDetail(scope.row,item,0)" :class="`${scope.row.departmentCascade== '小计' ? '' : 'colorText'}`">
                             <div v-if="items.crateDate == item">
                               <div  style="color: black;" v-if="items.planWorkTime">平均 {{items.planWorkTime}}分钟  {{items.planCost}}元</div>
-                               <div>已填 {{items.workTime}}分钟  {{items.cost}}元</div> 
-                               <div style="color: red;" v-if="items.surplusTime">剩余 {{items.surplusTime}}分钟  {{items.surplusCost}}元</div>
+                              <div v-if="items.leave">{{items.leave}}</div>
+                              <div v-else>已填 {{items.workTime}}分钟  {{items.cost}}元</div> 
+                              <div style="color: red;" v-if="items.surplusTime">剩余 {{items.surplusTime}}分钟  {{items.surplusCost}}元</div>
                             </div>
                         </div>
                     </template>
@@ -371,14 +372,14 @@
               <el-table-column prop="procedureName" label="工序名称" width="180"></el-table-column>
               <el-table-column prop="finishNum" label="完成件数" width="80">
                 <template slot-scope="scope">
-                  {{scope.row.finishNum?scope.row.finishNum:0}}
+                  {{scope.row.finishNum?scope.row.finishNum:''}}
                 </template>
               </el-table-column>
               <el-table-column prop="cost" label="工钱" width="80"></el-table-column>
               <el-table-column prop="checkType" label="质检方式" width="80"></el-table-column>
               <el-table-column prop="checkerName" label="质检人" width="180"></el-table-column>
               <el-table-column prop="working_time" label="工作时长" width="180">
-                <template slot-scope="scope">
+                <template slot-scope="scope" v-if="scope.row.working_time">
                   {{scope.row.working_time}}分钟
                 </template>
               </el-table-column>