Kaynağa Gözat

Merge remote-tracking branch 'origin/master'

yusm 1 yıl önce
ebeveyn
işleme
c68d605a97
100 değiştirilmiş dosya ile 4465 ekleme ve 1286 silme
  1. 7 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/App.vue
  2. 48 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/404.vue
  3. 18 13
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/relatedProducts.vue
  4. 34 6
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  5. 121 20
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/header/header.vue
  6. 7 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue
  7. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  8. 16 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/api.ts
  9. 127 45
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue
  10. 199 23
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/information.vue
  11. 21 33
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/operationRecord.vue
  12. 17 47
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/products.vue
  13. 20 44
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedBusiness.vue
  14. 78 39
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/detail/index.vue
  15. 168 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/deteleTables.vue
  16. 101 40
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue
  17. 4 95
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/index.vue
  18. 1 6
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/attachment.vue
  19. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue
  20. 5 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/router/index.ts
  21. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/styles/global.scss
  22. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/request.ts
  23. 10 12
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts
  24. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/vite.config.ts
  25. 176 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/AttachmentCenterController.java
  26. 39 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/AuditLogCenterController.java
  27. 35 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java
  28. 4 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ContactsController.java
  29. 4 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java
  30. 0 110
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/OrderController.java
  31. 218 19
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ProductController.java
  32. 186 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SalesOrderController.java
  33. 99 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/AttachmentCenter.java
  34. 78 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/AuditLogCenter.java
  35. 11 8
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessOpportunity.java
  36. 9 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Product.java
  37. 7 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Order.java
  38. 5 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/UploadFile.java
  39. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/AttachmentCenterMapper.java
  40. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/AuditLogCenterMapper.java
  41. 4 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessOpportunityMapper.java
  42. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ProductAuditLogMapper.java
  43. 3 3
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/OrderMapper.java
  44. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/AttachmentCenterService.java
  45. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/AuditLogCenterService.java
  46. 5 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessOpportunityService.java
  47. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ContactsService.java
  48. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/CustomService.java
  49. 6 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ProductService.java
  50. 7 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/OrderService.java
  51. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/AttachmentCenterServiceImpl.java
  52. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/AuditLogCenterServiceImpl.java
  53. 31 7
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java
  54. 5 5
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java
  55. 8 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContactsServiceImpl.java
  56. 18 5
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java
  57. 0 141
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/OrderServiceImpl.java
  58. 63 3
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java
  59. 374 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java
  60. 4 14
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  61. 26 0
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/AttachmentCenterMapper.xml
  62. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/AuditLogCenterMapper.xml
  63. 2 2
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessItemProductMapper.xml
  64. 12 2
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml
  65. 2 1
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ProductMapper.xml
  66. 2 2
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/OrderMapper.xml
  67. 5 0
      fhKeeper/formulahousekeeper/management-platform/pom.xml
  68. 151 118
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FeishuInfoController.java
  69. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/HolidaySettingController.java
  70. 80 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  71. 106 12
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java
  72. 7 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/CompanyDingding.java
  73. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/UserMonthWork.java
  74. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java
  75. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java
  76. 95 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  77. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java
  78. 1 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseSheetServiceImpl.java
  79. 3 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FeishuInfoServiceImpl.java
  80. 83 30
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  81. 163 251
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  82. 14 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  83. 63 11
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  84. 66 9
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/BeiSenUtils.java
  85. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml
  86. 2 14
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/CompanyDingdingMapper.xml
  87. 64 28
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  88. 1 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/Department.java
  89. 12 3
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  90. 0 25
      fhKeeper/formulahousekeeper/plugIn/form-design-master/src/components.d.ts
  91. 25 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/components/CodeEditor.vue.d.ts
  92. 22 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/components/ComponentGroup.vue.d.ts
  93. 680 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/config/index.d.ts
  94. 79 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/DesignForm.vue.d.ts
  95. 16 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/FormConfig.vue.d.ts
  96. 20 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/WidgetConfig.vue.d.ts
  97. 22 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/WidgetForm.vue.d.ts
  98. 25 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/WidgetFormItem.vue.d.ts
  99. 43 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateForm.vue.d.ts
  100. 0 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateFormItem.vue.d.ts

+ 7 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/App.vue

@@ -52,7 +52,7 @@ const notificationTiop = (options: NotificationParamsTyped) => {
 
 </script>
 
-<style>
+<style lang="scss">
 html,
 body,
 #app,
@@ -81,4 +81,10 @@ body,
 .ranimate-leave-active {
   animation: fadeIn 0s;
 }
+
+.drawerVisClass {
+  .el-drawer__body {
+    padding: 0 !important;
+  }
+}
 </style>

+ 48 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/404.vue

@@ -1,11 +1,56 @@
 <template>
   <div>
-    404
+    <div class="page-img">
+      <img src="../assets/404.png" />
+    </div>
+    <p class="page-container"><b>Error</b> 非常抱歉你访问的页面不存在!!!</p>
+    <div class="page-button">
+      <el-button type="primary" round @click="back" icon="el-icon-s-promotion">返回首页</el-button>
+    </div>
   </div>
 </template>
 
 <script lang="ts" setup>
-
+import { useRouter } from "vue-router";
+import { useStore } from "@/store/index"
+const router = useRouter();
+const { clearStore } = useStore()
+function back() {
+  clearStore();
+  router.replace('/login');
+}
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.page-img {
+  text-align: center;
+  display: flex;
+  justify-content: center;
+  padding: 100px 0 0 0;
+
+  img {
+    width: 600px;
+  }
+}
+
+.page-container {
+  font-size: 20px;
+  text-align: center;
+  color: rgb(192, 204, 218);
+
+  b {
+    margin-right: 30px;
+    font-size: 26px;
+  }
+}
+
+.page-button {
+  text-align: center;
+  margin-top: 40px;
+
+  .el-button.is-round {
+    width: 150px;
+    margin-right: 80px;
+  }
+}
+</style>

+ 18 - 13
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/relatedProducts.vue

@@ -2,25 +2,25 @@
     <div>
         <el-table ref="productTableRef" :data="productTable" border :row-class-name="tableRowClassName"
             @row-click="tableRowItem" style="width: 100%;height: 200px">
-            <el-table-column label="序号" width="80">
+            <el-table-column label="序号" width="60" align="center">
                 <template #default="scope">
                     <span>{{ scope.$index + 1 }}</span>
                 </template>
             </el-table-column>
             <el-table-column prop="productName" label="产品名称" width="180">
                 <template #default="scope">
-                    <el-select v-model="productTable[scope.$index].productName" placeholder="请选择"
+                    <el-select v-model="productTable[scope.$index].productId" placeholder="请选择"
                         v-if="productTableIndex == scope.$index" clearable @clear="clearTableItem(scope.$index)"
                         @change="selectChange(scope.$index, productTable[scope.$index].productName)">
-                        <el-option v-for="item in productArrar" :key="item.id" :label="item.productName" :value="item.id" />
+                        <el-option v-for="item in productArrar" :key="item.productId" :label="item.productName" :value="item.productId" />
                     </el-select>
                     <span v-else>{{ productTable[scope.$index].productName }}</span>
                 </template>
             </el-table-column>
-            <el-table-column prop="productType" label="产品类型" width="180"></el-table-column>
-            <el-table-column prop="unit" label="单位" width="80"></el-table-column>
+            <el-table-column prop="typeName" label="产品类型" width="180"></el-table-column>
+            <el-table-column prop="unitName" label="单位" width="120"></el-table-column>
             <el-table-column prop="price" label="标准价格" width="120"></el-table-column>
-            <el-table-column prop="stock" label="库存" width="80"></el-table-column>
+            <el-table-column prop="inventory" label="库存" width="80"></el-table-column>
             <el-table-column prop="sellingPrice" label="售价" width="180">
                 <template #default="scope">
                     <el-input-number v-model="productTable[scope.$index].sellingPrice" class="mx-4" :min="0" :max="100000000" controls-position="right" v-if="productTableIndex == scope.$index" />
@@ -39,7 +39,7 @@
                     <span v-else>{{ productTable[scope.$index].discount }}</span>
                 </template>
             </el-table-column>
-            <el-table-column prop="total" label="合计" width="180"></el-table-column>
+            <el-table-column prop="totalPrice" label="合计" width="180"></el-table-column>
             <el-table-column label="操作" fixed="right" width="120">
                 <template #default="scope">
                     <el-button link type="primary" size="large" @click.stop="addTableItem(scope.$index)">添加</el-button>
@@ -52,18 +52,18 @@
 </template>
   
 <script lang="ts" setup>
-import { ref, reactive, onMounted, inject } from "vue";
+import { ref, reactive, onMounted, inject, watchEffect } from "vue";
+
+const props = defineProps<{
+    productTableList: any,
+}>()
 
 const productTable: any = ref([{}])
 const productTableIndex = ref(0) // 可以编辑索引
-const productArrar = ref([
-    { id: 1, productName: '产品1', productType: '类别1', unit: '台', price: '1122', stock: '100', sellingPrice: 0, quantity: 0, discount: 0, total: '' },
-    { id: 2, productName: '产品2', productType: '类别2', unit: '台', price: '2211', stock: '300', sellingPrice: 0, quantity: 0, discount: 0, total: '' },
-])
+const productArrar: any = ref([])
 
 function selectChange(index: number, val: number | string) {
     let newObj = productArrar.value.find((item: any) => item.id == val)
-    console.log(newObj)
     productTable.value.splice(index, 1, newObj)
 }
 
@@ -87,6 +87,11 @@ function clearTableItem(index: number) {
 function deteleTableItem(index: number) {
     productTable.value.splice(index, 1)
 }
+
+watchEffect(() => {
+    const { productTableList } = props
+    productArrar.value = productTableList || []
+});
 </script>
   
 <style lang="scss" scoped></style>

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

@@ -109,9 +109,9 @@
         </div>
       </template>
       <div class="h-[60vh] overflow-y-auto scroll-bar">
-        <GenerateForm ref="generateForm" :data="generateFormData" />
+        <!-- <GenerateForm ref="generateForm" :data="generateFormData" /> -->
         <div>相关产品</div>
-        <RelatedProducts />
+        <RelatedProducts :productTableList="productTableList" />
       </div>
     </el-dialog>
   </div>
@@ -122,6 +122,7 @@ import { ref, reactive, onMounted, inject } from "vue";
 import type { FormInstance, FormRules } from 'element-plus'
 import { useRouter, useRoute } from "vue-router";
 import { GETSYSFILED, MOD, GETPERSONNEL, GETGENERATEFOEM } from './api'
+import { GETTABLELIST } from '@/pages/product/api'
 import { post, get } from "@/utils/request";
 import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, getLastDayOfMonth, formatDate } from '@/utils/tools'
 import { GenerateForm } from '@zmjs/form-design';
@@ -166,13 +167,14 @@ const fixedData = reactive({
   BusinessStage: [] as fixedDataInterface[],
   Personnel: [] as personnelInterface[]
 })
+const productTableList = ref([])
 
 
 function editBusiness() {
   generateForm.value?.getData().then((res: any) => {
     console.log('正确')
     console.log(res)
-  }).catch( (_err: any) => {
+  }).catch((_err: any) => {
     globalPopup?.showError('请填写完整')
   })
 }
@@ -214,14 +216,40 @@ async function getSystemField() {
 
 function toBusinessTableDetail(row: any) {
   console.log('点击跳转详情')
-  router.push({ 
-    path: `${MOD}/detail`, 
-    query: { id: row.id } 
+  router.push({
+    path: `${MOD}/detail`,
+    query: { id: row.id }
+  })
+}
+
+function getProductTableList() {
+  post(GETTABLELIST, { pageIndex: -1, pageSize: -1 }).then((res) => {
+    if (res.code == 'ok') {
+      const { record, total } = res.data
+      productTableList.value = record.map((item: any) => {
+        const { id, productName, productCode, unit, unitName, typeName, type, price, inventory } = item
+        return {
+          productId: id,
+          productName,
+          productCode,
+          unit,
+          unitName,
+          price,
+          type,
+          typeName,
+          inventory,
+          quantity: '',
+          discount: '',
+          totalPrice: ''
+        }
+      })
+    }
   })
 }
 
 onMounted(() => {
   getSystemField()
+  getProductTableList()
 })
 </script>
 

+ 121 - 20
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/header/header.vue

@@ -7,7 +7,8 @@
     <div v-for="(routerItem, routerItemIdex) in routerList"
       :class="`border-b-2 border-transparent hover:border-white p-2 mr-4 cursor-pointer multipleyHeader ${activeRouter?.path === routerItem.path ? 'border-white' : ''}`"
       :key="routerItem.path" ref="childDivs" v-show="visibleItems.includes(routerItemIdex)">
-      <div v-if="routerItem.children && routerItem.children.length <= 0 && routerItem?.isMenu" @click="setCurrentRouter(routerItem)" class="text-nowrap">
+      <div v-if="routerItem.children && routerItem.children.length <= 0 && routerItem?.isMenu"
+        @click="setCurrentRouter(routerItem)" class="text-nowrap">
         {{ routerItem.name }}
       </div>
       <div v-if="routerItem.children && routerItem.children.length > 0" class="flex justify-center items-center">
@@ -28,18 +29,54 @@
         </el-dropdown>
       </div>
     </div>
+    <div v-if="moreRoutes.length > 0" class="flex justify-center items-center">
+      <el-dropdown trigger="click">
+        <span class="text-white w-full h-full headerText">
+          <el-icon>
+            <MoreFilled />
+          </el-icon>
+        </span>
+        <template #dropdown>
+          <el-dropdown-menu>
+            <el-dropdown-item v-for="(child, childIndex) in moreRoutes" :key="child.path"
+              @click="moreSetCurrentRouter(child, childIndex)">
+              {{ child.name }}
+            </el-dropdown-item>
+          </el-dropdown-menu>
+        </template>
+      </el-dropdown>
+    </div>
   </div>
   <div class="flex flex-row justify-start items-center text-white header-right">
     <el-icon :size="26" class="ml-4 cursor-pointer">
       <Bell />
     </el-icon>
     <div>
-      <img class="w-8 h-8 rounded-full ml-4 cursor-pointer" :src="defaultCover" alt="" @click="logout()">
+      <img class="w- h-8 rounded-full ml-4 cursor-pointer" :src="defaultCover" alt="" @click="drawerVis = true">
     </div>
     <el-icon :size="26" class="ml-4 cursor-pointer">
       <Grid />
     </el-icon>
   </div>
+
+  <!-- 左侧 -->
+  <el-drawer v-model="drawerVis" modal-class="drawerVisClass" :with-header="false">
+    <div class="w-full h-full">
+      <div class="bg-[#075985]">
+        <div class="p-8">
+          <div class="w-[100px] h-[100px] p-2 border-[1px] border-[#999] rounded-full m-auto">
+            <img class="w-full h-full" :src="defaultCover">
+          </div>
+        </div>
+        <div class="text-center text-[20px] leading-none text-white pb-3">{{ userInfo.name }}</div>
+        <div class="text-center leading-none text-slate-50 pb-3">角色:{{ userInfo.roleName }}</div>
+        <div class="text-center leading-none text-slate-50 pb-3">公司:{{ userInfo.companyName }}</div>
+        <div class="w-full drawerVisBtn">
+          <div @click="logout()">退出</div>
+        </div>
+      </div>
+    </div>
+  </el-drawer>
 </template>
   
 <script lang="ts" setup>
@@ -48,7 +85,7 @@ import { RouteRecordRaw, useRouter, useRoute } from 'vue-router';
 import { useStore } from "../../store/index"
 import defaultCover from "../../assets/defaultCover.png";
 import loginLogin from '../../assets/login/login_logo.png'
-const { routers, clearStore } = useStore()
+const { routers, clearStore, userInfo } = useStore()
 const router = useRouter();
 const route = useRoute()
 // const routerList = ref<RouteRecordRaw[]>([]);
@@ -57,25 +94,28 @@ const activeRouter = ref<RouteRecordRaw>();
 
 const visibleItems = ref<number[]>([]);
 const parentDiv = ref<HTMLElement | null>(null);
+const itemLastIndex = ref(0)
+const moreRoutes = ref<any[]>([])
+const drawerVis = ref(false)
 
 const updateVisibleItems = () => {
-  const parentWidth = parentDiv.value?.offsetWidth || 10;
+  const parentWidth = (parentDiv.value?.offsetWidth && parentDiv.value?.offsetWidth - 150) || 10;
   const canvas = document.createElement('canvas');
   const context = canvas.getContext('2d');
 
   let textWidthList: any = [] // 所有文字的宽度
   let totalWidth = 0;
   let temporaryIndex: any = []
-  
-  if(context) {
+
+  if (context) {
     context.font = '16px 微软雅黑';
     textWidthList = routerList.value.map((item: any) => {
       const metrics = context.measureText(item.name);
       return Math.ceil(metrics.width) + 32; // 32是padding和margin的宽度
     })
   }
-  for(let i in textWidthList) {
-    if(totalWidth + textWidthList[i] > parentWidth) {
+  for (let i in textWidthList) {
+    if (totalWidth + textWidthList[i] > parentWidth) {
       break;
     }
     totalWidth += textWidthList[i];
@@ -83,13 +123,41 @@ const updateVisibleItems = () => {
   }
 
   // 替换最后一个元素
-  let lastIndex = textWidthList.length - 1;
-  temporaryIndex.splice(temporaryIndex.length -1, 1, lastIndex)
-
+  const lastIndex = routerList.value.findIndex(obj => obj.name === '系统设置');
+  itemLastIndex.value = lastIndex
+  temporaryIndex.splice(temporaryIndex.length - 1, 1, lastIndex)
   visibleItems.value = temporaryIndex;
-  //console.log(visibleItems.value)
+
+  // 过滤出隐藏的元素
+  let interceptIndex = Object.values(visibleItems.value).findIndex(v => +v == lastIndex)
+  let newVisibleItems = JSON.parse(JSON.stringify(temporaryIndex)).splice(0, interceptIndex + 1)
+  let missingIndex = findMissingNumbers(newVisibleItems)
+  let routerLists = []
+  for (var i in missingIndex) {
+    routerLists.push(routerList.value[missingIndex[i]])
+  }
+  moreRoutes.value = routerLists
+
+  // 判断当前的索引是否在隐藏元素中
+  let currentIndex = moreRoutes.value.findIndex(obj => obj.name === activeRouter.value?.name);
+  if (currentIndex >= 0) {
+    replaceData(activeRouter.value, currentIndex)
+  }
 };
 
+const findMissingNumbers = (arr: any) => {
+  let missingNumbers = [];
+  arr.sort((a: any, b: any) => a - b); // 对数组进行排序
+
+  for (let i = arr[0]; i < arr[arr.length - 1]; i++) {
+    if (!arr.includes(i)) { // 如果数组中不包含当前数字
+      missingNumbers.push(i); // 将缺失的数字添加到结果数组中
+    }
+  }
+
+  return missingNumbers;
+}
+
 const setCurrentRouter = (item: RouteRecordRaw) => {
   activeRouter.value = item;
   if (item.children && item.children.length > 0) {
@@ -98,6 +166,20 @@ const setCurrentRouter = (item: RouteRecordRaw) => {
   }
   router.push({ path: item.path });
 };
+
+const moreSetCurrentRouter = (item: RouteRecordRaw, index: any) => {
+  activeRouter.value = item;
+  router.push({ path: item.path });
+  replaceData(item, index)
+};
+
+const replaceData = (item: any, index: any) => {
+  let itemIndex = routerList.value.findIndex(v => v.name == item.name)
+  let lastItem = routerList.value[visibleItems.value[visibleItems.value.length - 2]]
+  visibleItems.value.splice(visibleItems.value.length - 2, 1, itemIndex),
+    moreRoutes.value.splice(index, 1, lastItem)
+}
+
 const logout = () => {
   clearStore();
   router.push({ path: '/login' });
@@ -112,13 +194,12 @@ onMounted(() => {
   }, 500);
 })
 watchEffect(() => {
-  updateVisibleItems();
-  watch(() => route.path, (newPath, _oldPath) => {  
-      activeRouter.value = routerList.value.find((item) => item.path === newPath);
-    }, { 
-      immediate: false 
-    }
-  );  
+  watch(() => route.path, (newPath, _oldPath) => {
+    activeRouter.value = routerList.value.find((item) => item.path === newPath);
+  }, {
+    immediate: false
+  }
+  );
 });
 </script>
   
@@ -126,6 +207,7 @@ watchEffect(() => {
 .trademark {
   font-size: 20px;
 }
+
 .multipleyHeader {
   height: 96%;
   display: flex;
@@ -136,16 +218,35 @@ watchEffect(() => {
     font-size: 16px;
   }
 }
+
 .parentBox {
   // max-width: 80%;
   // min-width: 300px;
   flex: 1;
   overflow: hidden;
 }
+
 .header-right {
   width: 135px;
 }
+
 .parentDiv {
-  width: 50%;
+  width: 10%;
+}
+
+.drawerVisClass {
+  .drawerVisBtn {
+    margin-top: 10px;
+    border-top: 1px solid #999;
+    div {
+      text-align: center;
+      line-height: 40px;
+      color: #fff;
+      cursor: pointer;
+      &:hover {
+        background: #086597;
+      }
+    }
+  }
 }
 </style>

+ 7 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue

@@ -1,11 +1,10 @@
 <template>
-  <div class="w-full h-full">
+  <div class="w-full h-full" v-loading="isLoading">
     <el-container class="flex flex-row h-full">
       <el-header class="bg-sky-800 leading-10 flex flex-row justify-between">
         <Header></Header>
       </el-header>
       <el-main>
-        <!-- <router-view /> -->
         <router-view v-slot="{ Component }">
           <transition name="router_animate">
             <component :is="Component" />
@@ -18,8 +17,13 @@
 
 <script lang="ts" setup>
 import Header from '@/pages/header/header.vue'
-import { onMounted, ref } from 'vue';
+import { nextTick, onMounted, ref } from 'vue';
+const isLoading = ref(true);
 
+onMounted(async () => {
+  await nextTick();
+  isLoading.value = false;
+});
 </script>
 
 <style scoped lang="scss">

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

@@ -54,8 +54,8 @@ const router = useRouter();
 const globalPopup = inject<GlobalPopup>('globalPopup')
 const ruleFormRef = ref<FormInstance>();
 const ruleForm = ref({
-  username: "",
-  password: "",
+  username: "18122222222",
+  password: "000000",
 });
 const loginLoading = ref(false);
 const rules = reactive<FormRules<typeof ruleForm>>({
@@ -88,7 +88,7 @@ const login = (formEl: FormInstance | undefined) => {
       setTimeout(() => {
         loginLoading.value = false;
         router.push(res.data?.moduleList[0].path);
-      }, 1000)
+      }, 100)
     }).catch(_err => {
       loginLoading.value = false;
     })

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

@@ -1,8 +1,23 @@
 export const MOD = '/product'
+export const MODUCODE = 'Product'
 export const prefix = '/product'
+export const GETDOEMCODE = '/sys-form/getListByCode'
 export const GETSYSFILED = '/sys-dict/getListByCode'
 export const GETPERSONNEL = '/user/getSimpleActiveUserList'
 export const GETTEMPLATE = `/sys-form/getListByCode${MOD}`
 export const GETTABLELIST = `${prefix}/list`
 export const ADDPRODUCT = `${prefix}/addOrUpdate`
-export const ALLDETELE = `${prefix}/delete`
+export const ALLDETELE = `${prefix}/delete`
+export const UPLOADFILE = `${prefix}/importData`
+export const RECYCLELIST = `${prefix}/recycleList`
+export const DETERDETELE = `${prefix}/batchDeleteProduct`
+export const ROLLBACK = `${prefix}/batchRecoveryProduct`
+export const GETDETAIL = `${prefix}/detail`
+export const GETINCHARGER = `${prefix}/transferIncharger`
+export const GETBUSINESS = `${prefix}/businessListWithProduct`
+export const GETORDER = `${prefix}/orderWithProduct`
+export const UPLOADATTACHMENT = `/attachment/uploadAttachment`
+export const GETCENTERLIST = `/audit-log-center/list`
+export const GETATTACHMENT = `/attachment/attachmentList`
+export const FILEDETELE = `/attachment/delete`
+export const FILERENAME = `/attachment/rename`

+ 127 - 45
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue

@@ -3,67 +3,149 @@
         <div class="flex justify-between">
             <div class="title">附件</div>
             <div>
-                <el-button type="primary">上传</el-button>
+                <el-upload ref="uploadRef" :http-request="httpUploadFile" :limit="1" :show-file-list="false"
+                    element-loading-text="正在上传">
+                    <template #trigger>
+                        <el-button type="primary" :loading="allLoading.uploadLoading">上传</el-button>
+                    </template>
+                </el-upload>
             </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
             <el-table :data="attachmenttable" border style="width: 100%;height: 200px;">
-                <el-table-column prop="fileName" label="附件名称" width="180" />
-                <el-table-column prop="fileSize" label="附件大小" width="120" />
-                <el-table-column prop="uploader" label="上传人" width="120" />
-                <el-table-column prop="uploadTime" label="上传时间" width="180" />
+                <el-table-column prop="attachmentName" label="附件名称" width="180" />
+                <el-table-column prop="size" label="附件大小" width="120" />
+                <el-table-column prop="creatorName" label="上传人" width="120" />
+                <el-table-column prop="indate" label="上传时间" width="180" />
                 <el-table-column label="操作" width="180" fixed="right">
                     <template #default="scope">
-                        <el-button link type="primary" size="large">下载</el-button>
-                        <el-button link type="primary" size="large">重命名</el-button>
-                        <el-button link type="danger" size="large">删除</el-button>
+                        <el-button link type="primary" size="large" @click="fileDownload(scope.row)">下载</el-button>
+                        <el-button link type="primary" size="large" @click="showVisible(scope.row)">重命名</el-button>
+                        <el-button link type="danger" size="large" @click="deteleFile(scope.row)">删除</el-button>
                     </template>
                 </el-table-column>
             </el-table>
         </div>
+
+        <!-- 弹窗 -->
+        <el-dialog v-model="allVisible.renameVisible" width="800" :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>
+                        <el-button type="primary" :loading="allLoading.renameLoading" :disabled="!renameVal"
+                            @click="saveEditClue()">保存</el-button>
+                        <el-button @click="allVisible.renameVisible = false">取消</el-button>
+                    </div>
+                </div>
+            </template>
+            <div class="pt-3">
+                <el-input v-model.trim="renameVal" style="width: 100%" class="pb-3" clearable />
+            </div>
+        </el-dialog>
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { get, post, uploadFile } from '@/utils/request';
+import { UploadRequestOptions } from 'element-plus';
+import { ref, reactive, onMounted, onUnmounted, defineEmits, inject, watchEffect } from 'vue'
+import { FILEDETELE, FILERENAME, MODUCODE, UPLOADATTACHMENT } from '../api';
+import { confirmAction, downloadFile } from '@/utils/tools';
+
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const emits = defineEmits(['getFileList']);
+
+const attachmenttable = ref([])
+const information: any = ref({})
+const renameItem: any = ref({})
+const renameVal = ref('')
+const allLoading = reactive({
+    uploadLoading: false,
+    renameLoading: false,
+})
+const allVisible = reactive({
+    renameVisible: false
+})
+
+const props = defineProps<{
+    data: any,
+    information: any
+}>()
+
+// 下载文件
+function fileDownload(item: any) {
+    downloadFile(item.url, `${item.attachmentName}${item.attachmentSuffix}`)
+}
+
+// 保存重命名
+function saveEditClue() {
+    const id = renameItem.value.id
+    allLoading.renameLoading = true
+    post(FILERENAME, { name: renameVal.value, id }).then((res) => {
+        if (res.code == 'ok') {
+            allVisible.renameVisible = false
+            globalPopup?.showSuccess(res.msg || '')
+            emits('getFileList')
+        }
+    }).catch((err) => {
+        globalPopup?.showError(err.msg || '')
+    }).finally(() => {
+        allLoading.renameLoading = false
+    })
+}
+
+// 删除文件
+function deteleFile(item: any) {
+    const id = item.id
+    confirmAction(`确定删除【${item.attachmentName}】文件吗?`).then(() => {
+        post(FILEDETELE, { id }).then((_res) => {
+            globalPopup?.showSuccess('删除成功')
+            emits('getFileList')
+        }).catch((err) => {
+            globalPopup?.showError(err.msg || '')
+        })
+    })
+}
+
+// 显示弹窗
+function showVisible(item: any) {
+    renameItem.value = JSON.parse(JSON.stringify(item))
+    renameVal.value = renameItem.value.attachmentName
+    allVisible.renameVisible = true
+}
+
+// 上传附件
+async function httpUploadFile(param: UploadRequestOptions) {
+    allLoading.uploadLoading = true
+    const id = information.value.id
+    const formData = new FormData();
+    formData.append('file', param.file)
+    formData.append('moduleId', id)
+    formData.append('moduleCode', MODUCODE)
+    const res = await uploadFile(UPLOADATTACHMENT, formData)
+    allLoading.uploadLoading = false
+    if (res.code == 'ok') {
+        globalPopup?.showSuccess('上传成功')
+        emits('getFileList');
+        return
+    }
+    globalPopup?.showError(res.msg || '')
+    return res
+}
+
+// 接收参数赋值
+function receiveAssignment(item: any) {
+    attachmenttable.value = item.data
+    information.value = item.information
+}
+
+watchEffect(() => {
+    receiveAssignment(props)
+});
 
-const attachmenttable = ref([{
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}])
 // 生命周期钩子
 onMounted(() => {
+    receiveAssignment(props)
 });
 </script>
 <style scoped lang="scss">

Dosya farkı çok büyük olduğundan ihmal edildi
+ 199 - 23
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/information.vue


+ 21 - 33
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/operationRecord.vue

@@ -5,47 +5,35 @@
         </div>
         <div class="flex-1 overflow-auto pt-5">
             <el-table :data="operationRecordtable" border style="width: 100%;height: 278px;">
-                <el-table-column prop="operatingTime" label="操作时间" width="140" />
-                <el-table-column prop="operator" label="操作人" width="120" />
-                <el-table-column prop="operationContent" label="操作内容" />
+                <el-table-column prop="auditTime" label="操作时间" width="140" />
+                <el-table-column prop="auditorName" label="操作人" width="120" />
+                <el-table-column prop="auditorContent" label="操作内容" />
             </el-table>
         </div>
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+
+const operationRecordtable = ref([])
+const information: any = ref({})
+
+const props = defineProps<{
+    data: any,
+}>()
+
+// 接收参数赋值
+function receiveAssignment(item: any) {
+    operationRecordtable.value = item.data
+}
+
+watchEffect(() => {
+    receiveAssignment(props)
+});
 
-const operationRecordtable = ref([{
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-},])
 // 生命周期钩子
 onMounted(() => {
+    receiveAssignment(props)
 });
 </script>
 <style scoped lang="scss">

+ 17 - 47
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/products.vue

@@ -2,9 +2,6 @@
     <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>
-                <el-button type="primary">编辑产品</el-button>
-            </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
             <el-table :data="relatedTaskstable" border style="width: 100%;height: 300px;">
@@ -34,53 +31,26 @@
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+
+const relatedTaskstable = ref([])
+
+const props = defineProps<{
+    data: any
+}>()
+
+// 接收参数赋值
+function receiveAssignment(item: any) {
+    relatedTaskstable.value = item.data
+}
+
+watchEffect(() => {
+    receiveAssignment(props)
+});
 
-const relatedTaskstable = ref([{
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}])
 // 生命周期钩子
 onMounted(() => {
+    receiveAssignment(props)
 });
 </script>
 <style scoped lang="scss">

+ 20 - 44
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedBusiness.vue

@@ -22,53 +22,29 @@
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+
+const relatedTaskstable = ref([])
+const information: any = ref({})
+
+const props = defineProps<{
+    data: any,
+    information: any
+}>()
+
+// 接收参数赋值
+function receiveAssignment(item: any) {
+    relatedTaskstable.value = item.data
+    information.value = item.information
+}
+
+watchEffect(() => {
+    receiveAssignment(props)
+});
 
-const relatedTaskstable = ref([{
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}])
 // 生命周期钩子
 onMounted(() => {
+    receiveAssignment(props)
 });
 </script>
 <style scoped lang="scss">

+ 78 - 39
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/detail/index.vue

@@ -7,34 +7,34 @@
         </el-link>
       </div>
       <div class="mr-8">
-        <el-select v-model="value" placeholder="请选择" style="width: 150px">
-          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+        <el-select v-model="value" placeholder="请选择" style="width: 150px" @change="getDetail(false)">
+          <el-option v-for="item in options" :key="item.id" :label="item.productName" :value="item.id" />
         </el-select>
       </div>
     </div>
     <!-- 内容 -->
-    <div class="flex-1 flex flex-col overflow-y-auto overflow-x-hidden scroll-bar">
+    <div class="flex-1 flex flex-col overflow-y-auto overflow-x-hidden scroll-bar" v-loading="pageLoading">
       <div class="w-full h-auto flex justify-between">
         <div class="bg-white shadow-md rounded-md" style="width: 46%;">
-          <Information />
+          <Information :data="information" @getInformationData="getInformationData" />
         </div>
         <div class="bg-white ml-2 shadow-md rounded-md flex-1">
-          <Attachment />
+          <Attachment :data="attachment" :information="information" @getFileList="getFileList" />
         </div>
       </div>
 
       <div class="w-full h-auto flex justify-between mt-2">
         <div class="bg-white shadow-md rounded-md" style="width: 65%;">
-          <RelatedBusiness />
+          <RelatedBusiness :data="relatedBusiness" :information="information" />
         </div>
         <div class="bg-white ml-2 shadow-md rounded-md flex-1">
-          <OperationRecord />
+          <OperationRecord :data="operationRecord" />
         </div>
       </div>
 
       <div class="w-full h-auto flex justify-between mt-2">
         <div class="bg-white shadow-md rounded-md w-full">
-          <Products />
+          <Products :data="products" />
         </div>
       </div>
     </div>
@@ -45,6 +45,7 @@
 import { ref, reactive, onMounted, inject } from "vue";
 import type { FormInstance, FormRules } from 'element-plus'
 import { Edit, ArrowLeft as IconView } from '@element-plus/icons-vue'
+import { useRoute } from "vue-router";
 import { backPath } from '../../../utils/tools'
 
 import Information from '../component/information.vue'
@@ -52,40 +53,78 @@ 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 { GETBUSINESS, GETDETAIL, GETCENTERLIST, GETORDER, MODUCODE, GETATTACHMENT, GETTABLELIST } from "../api";
+import { post } from "@/utils/request";
+
+const route = useRoute()
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const addressParameters: any = ref(0) // 地址上的参数
+const information = ref({}) // 基本信息
+const attachment = ref([]) // 附件
+const relatedBusiness = ref([]) // 相关商机
+const operationRecord = ref([]) // 操作记录
+const products = ref([]) // 相关产品
+
+const pageLoading = ref(false)
 
 const value = ref('')
-const stageStatusVal = ref('')
-const options = [
-  {
-    value: 'Option1',
-    label: 'Option1',
-  },
-  {
-    value: 'Option2',
-    label: 'Option2',
-  },
-  {
-    value: 'Option3',
-    label: 'Option3',
-  },
-  {
-    value: 'Option4',
-    label: 'Option4',
-  },
-  {
-    value: 'Option5',
-    label: 'Option5',
-  },
-]
-
-
-function handleScroll(event: any) { // 滚表横向滚动
-  if (event.deltaY) {
-    event.preventDefault();
-    const element = event.currentTarget;
-    element.scrollLeft += event.deltaY;
+const options: any = ref([])
+
+function getInformationData(val: any = false) {
+  const id = val ? val : addressParameters.value
+  post(GETDETAIL, { id }).then((res) => {
+    information.value = res.data
+  })
+}
+
+function getFileList(val: any = false) {
+  const id = val ? val : addressParameters.value
+  post(GETATTACHMENT, { moduleId: id, moduleCode: MODUCODE }).then((res) => {
+    attachment.value = res.data
+  })
+}
+
+async function getDetail(flag: boolean) {
+  try {
+    const id = flag ? addressParameters.value : value.value
+    pageLoading.value = true
+
+    await Promise.all([
+      getInformationData(id),
+      getFileList(id),
+      post(GETCENTERLIST, { id, moduleCode: MODUCODE }).then((res) => {
+        operationRecord.value = res.datag
+      }),
+      post(GETORDER, { id }).then((res) => {
+        products.value = res.data
+      }),
+      post(GETBUSINESS, { id }).then((res) => {
+        relatedBusiness.value = res.data
+      })
+    ])
+
+    pageLoading.value = false
+  } catch (error) {
+    pageLoading.value = false
+    console.log(error, '<==== 加载错误')
   }
 }
+
+function getProductList() {
+  post(GETTABLELIST, { pageIndex: -1, pageSize: -1 }).then((res) => {
+    const { record } = res.data
+    options.value = record
+  }).catch(() => {
+    globalPopup?.showError('产品列表获取失败')
+  })
+}
+
+onMounted(() => {
+  const { id } = route.query
+  addressParameters.value = id
+  getProductList()
+  getDetail(true)
+})
 </script>
   
 <style lang="scss" scoped>
@@ -144,7 +183,7 @@ function handleScroll(event: any) { // 滚表横向滚动
     padding-bottom: 4px;
   }
 
-  .selectClas >>> .el-select__wrapper {
+  .selectClas>>>.el-select__wrapper {
     background-color: none !important;
     box-shadow: none !important;
   }

+ 168 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/deteleTables.vue

@@ -0,0 +1,168 @@
+<template>
+    <el-dialog v-model="deteleClueDialogVisible" width="1000" :before-close="beForeCancel" :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>
+                    <el-button type="primary" @click="batchRestore()"
+                        v-loading="allLoading.batchRecoveryLoading">批量恢复</el-button>
+                    <el-button type="primary" @click="batchDeletes()"
+                        v-loading="allLoading.batchDeteleLoading">批量删除</el-button>
+                    <el-button @click="cancel()">取消</el-button>
+                </div>
+            </div>
+        </template>
+        <div class="h-[60vh] flex flex-col">
+            <div class="flex-1 w-full overflow-hidden">
+                <el-table ref="clueTableRef" :data="deteleClueTable" border v-loading="allLoading.tableLoading"
+                    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"></el-table-column>
+                    <el-table-column prop="typeName" label="产品类别" width="180"></el-table-column>
+                    <el-table-column prop="unitName" label="单位" width="180"></el-table-column>
+                    <el-table-column prop="price" label="标准价格(元)" width="180"></el-table-column>
+                    <el-table-column prop="inventory" label="库存" width="180"></el-table-column>
+                    <el-table-column prop="status" label="状态" width="180"></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="createTime" label="创建时间" width="180"></el-table-column>
+                    <el-table-column label="操作" fixed="right" width="120">
+                        <template #default="scope">
+                            <el-button link type="primary" size="large" @click="restoreItemRow([scope.row])">恢复</el-button>
+                            <el-button link type="danger" size="large" @click="deteItemRow([scope.row])">删除</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+            <div class="flex justify-end pt-3">
+                <el-pagination layout="total, prev, pager, next, sizes" :page-size="tableForm.pageSize"
+                    @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="clueTotalTable"
+                    :hide-on-single-page="true" />
+            </div>
+        </div>
+    </el-dialog>
+</template>
+<script lang="ts" setup>
+import { post } from '@/utils/request';
+import { ref, reactive, onMounted, watchEffect, watch, inject } from 'vue'
+import { DETERDETELE, RECYCLELIST, ROLLBACK } from './api';
+import { ElTable } from 'element-plus';
+import { confirmAction } from '@/utils/tools';
+
+const emits = defineEmits(['showDeteleProduct']);
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const deteleClueTable = ref([])
+const deteleClueDialogVisible = ref(false)
+const clueTotalTable = ref(0)
+const allLoading = reactive({
+    batchRecoveryLoading: false,
+    batchDeteleLoading: false,
+    tableLoading: false
+})
+
+const tableForm = reactive({
+    pageIndex: 1,
+    pageSize: 10
+})
+
+const clueTableRef = ref<InstanceType<typeof ElTable>>() // 产品table dom
+
+const props = defineProps<{
+    visibles: boolean
+}>()
+
+watch(() => props.visibles, (newVal) => {
+    deteleClueDialogVisible.value = newVal
+    if (newVal) {
+        getTableList()
+    }
+})
+
+function batchRestore() {
+    const data = clueTableRef.value && clueTableRef.value.getSelectionRows()
+    if (!data.length) {
+        globalPopup?.showWarning('请选择需要恢复的数据')
+        return
+    }
+    restoreItemRow(data)
+}
+
+function batchDeletes() {
+    const data = clueTableRef.value && clueTableRef.value.getSelectionRows()
+    if (!data.length) {
+        globalPopup?.showWarning('请选择需要删除的数据')
+        return
+    }
+    deteItemRow(data)
+}
+
+function deteItemRow(items: any[]) {
+    const ids = items.map((item: any) => item.id).join(',')
+    const str = items.map((item: any) => item.productName).join(',')
+    confirmAction(`确定${items.length > 1 ? '批量删除这些' : '删除'}【${str}】产品吗?`, '', 'warning').then(() => {
+        post(DETERDETELE, { ids }).then(res => {
+            if (res.code != 'ok') {
+                globalPopup?.showError(res.msg)
+                return
+            }
+            globalPopup?.showSuccess('删除成功')
+            getTableList()
+        })
+    })
+}
+
+function restoreItemRow(items: any[]) {
+    const ids = items.map((item: any) => item.id).join(',')
+    const str = items.map((item: any) => item.productName).join(',')
+    confirmAction(`确定${items.length > 1 ? '批量恢复这些' : '恢复'}【${str}】产品吗?`, '', 'warning').then(() => {
+        post(ROLLBACK, { ids }).then(res => {
+            if (res.code != 'ok') {
+                globalPopup?.showError(res.msg)
+                return
+            }
+            globalPopup?.showSuccess('恢复成功')
+            getTableList()
+        })
+    })
+}
+
+function getTableList() {
+    allLoading.tableLoading = true
+    post(RECYCLELIST, { ...tableForm }).then((res) => {
+        if (res.code == 'ok') {
+            const { record, total } = res.data
+            deteleClueTable.value = record
+            clueTotalTable.value = total
+        }
+    }).finally(() => {
+        allLoading.tableLoading = false
+    })
+}
+
+function handleSizeChange(val: number) {
+    tableForm.pageIndex = 1
+    tableForm.pageSize = val
+    getTableList()
+}
+
+function handleCurrentChange(val: number) {
+    tableForm.pageIndex = val
+    getTableList()
+}
+
+function cancel() {
+    emits('showDeteleProduct', false)
+}
+
+function beForeCancel(done: () => void) {
+    emits('showDeteleProduct', false)
+    done()
+}
+
+onMounted(() => {
+
+})
+
+</script>
+<style lang="scss" scoped></style>

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

@@ -39,10 +39,10 @@
     <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(true)">新建产品</el-button>
-          <el-button type="primary">批量删除</el-button>
-          <el-button type="primary">回收站</el-button>
-          <el-button type="primary">导入</el-button>
+          <el-button type="primary" @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">导出</el-button>
         </div>
         <div class="flex-1 w-full overflow-hidden">
@@ -57,17 +57,21 @@
                 }}</el-button>
               </template>
             </el-table-column>
-            <el-table-column prop="type" label="产品类别" width="180"></el-table-column>
-            <el-table-column prop="unit" label="单位" width="180"></el-table-column>
-            <el-table-column prop="price" label="标准价格" width="180"></el-table-column>
+            <el-table-column prop="typeName" label="产品类别" width="180"></el-table-column>
+            <el-table-column prop="unitName" label="单位" width="180"></el-table-column>
+            <el-table-column prop="price" label="标准价格(元)" width="180"></el-table-column>
             <el-table-column prop="inventory" label="库存" width="180"></el-table-column>
-            <el-table-column prop="status" label="状态" width="180"></el-table-column>
-            <el-table-column prop="inchargerId" label="负责人" width="190"></el-table-column>
-            <el-table-column prop="creatorId" label="创建人" width="180"></el-table-column>
+            <el-table-column prop="status" label="状态" width="180">
+              <template #default="scope">
+                {{ scope.row.status == 1 ? '上架' : '下架' }}
+              </template>
+            </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="createTime" label="创建时间" width="180"></el-table-column>
             <el-table-column label="操作" fixed="right" width="200">
               <template #default="scope">
-                <el-button link type="primary" size="large">编辑</el-button>
+                <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>
               </template>
             </el-table-column>
@@ -75,7 +79,8 @@
         </div>
         <div class="flex justify-end pt-3">
           <el-pagination layout="total, prev, pager, next, sizes" :page-size="filterProductForm.pageSize"
-            @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="productTableTotal" :hide-on-single-page="true" />
+            @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="productTableTotal"
+            :hide-on-single-page="true" />
         </div>
       </div>
     </div>
@@ -86,8 +91,8 @@
         <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)" v-loading="allLoading.saveLoading">保存并新建</el-button>
-            <el-button type="primary" @click="saveProductRow(false)" v-loading="allLoading.saveLoading">保存</el-button>
+            <el-button type="primary" @click="saveProductRow(true)" :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>
         </div>
@@ -99,17 +104,40 @@
       </div>
     </el-dialog>
 
+    <el-dialog v-model="dialogVisible.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-upload class="upload-demo mr-3" :limit="1" :show-file-list="false" accept=".xlsx" :http-request="importProducts">
+              <el-button type="primary" :loading="allLoading.importLoading">导入</el-button>
+            </el-upload>
+            <el-button @click="dialogVisible.importVisible = false">取消</el-button>
+          </div>
+        </div>
+      </template>
+      <div class="p-8">
+        <div class="ml-4 mr-4">
+          <div class="flex items-center">1、点击下载 <el-link type="primary">产品导入模板.xlsx</el-link></div>
+          <div class="mt-4">2、填写excel文件、产品编号、产品名称、产品类别、标准价格、库存、状态必填</div>
+        </div>
+      </div>
+    </el-dialog>
+
+    <DeteleTables :visibles="dialogVisible.deteleProductDialogVisible" @showDeteleProduct="showDeteleProduct" />
+
   </div>
 </template>
 
 <script lang="ts" setup>
 import { ref, reactive, onMounted, inject } from "vue";
-import { GETSYSFILED, MOD, GETPERSONNEL, GETTEMPLATE, GETTABLELIST, ADDPRODUCT, ALLDETELE } from './api'
+import { GETSYSFILED, MOD, GETPERSONNEL, GETTEMPLATE, GETTABLELIST, ADDPRODUCT, ALLDETELE, UPLOADFILE } from './api'
 import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, getLastDayOfMonth, formatDate, createTaskFromType, confirmAction } from '@/utils/tools'
-import { FormInstance, FormRules, ElMessageBox, ElTable } from 'element-plus'
-import { post, get } from "@/utils/request";
+import { FormInstance, FormRules, ElMessageBox, ElTable, UploadRequestOptions } from 'element-plus'
+import { post, get, uploadFile } from "@/utils/request";
 import { useRouter, useRoute } from "vue-router";
 import { GenerateForm } from '@zmjs/form-design';
+import DeteleTables from "./deteleTables.vue";
 
 const router = useRouter()
 const globalPopup = inject<GlobalPopup>('globalPopup')
@@ -128,12 +156,15 @@ const allLoading = reactive({
   productTableLading: false,
   generateFormLading: false,
   saveLoading: false,
+  importLoading: false
 })
 const dialogVisible = reactive({
   editProductVisible: false,
   taskModalVisible: false,
   clueDialogVisible: false,
-  deteleClueDialogVisible: false
+  deteleClueDialogVisible: false,
+  importVisible: false,
+  deteleProductDialogVisible: false
 })
 const allText = reactive({
   editClueText: '新建产品',
@@ -154,17 +185,31 @@ const genereditForm = ref({}) // 编辑表单
 const generateFormKey = ref(1)
 
 // 方法定义
+function batchDelete() {
+  const data = productTableRef.value && productTableRef.value.getSelectionRows()
+  if (!data.length) {
+    globalPopup?.showWarning('请选择数据')
+    return
+  }
+  deteleRow(data)
+}
+
+function showDeteleProduct(flag: boolean) {
+  if(!flag) {
+    getProductTableList()
+  }
+  dialogVisible.deteleProductDialogVisible = flag
+}
+
 function deteleRow(items: any[]) {
   let ids = items.map(item => item.id).join(',')
   let str = items.map(item => item.productName).join(',')
-  confirmAction(`确定${items.length > 1 ? '批量删除' : '删除'}【${str}】线索吗?`).then(() => {
-    post(ALLDETELE, { ids: ids }).then(res => {
-      if (res.code != 'ok') {
-        globalPopup?.showError(res.msg)
-        return
-      }
+  confirmAction(`确定${items.length > 1 ? '批量删除' : '删除'}【${str}】产品吗?`).then(() => {
+    post(ALLDETELE, { ids: ids }).then((_res) => {
       globalPopup?.showSuccess('删除成功')
       getProductTableList()
+    }).catch((err) => {
+      globalPopup?.showError(err.msg)
     })
   })
 }
@@ -172,42 +217,45 @@ function deteleRow(items: any[]) {
 async function saveProductRow(flag: boolean) {
   const data = await generateForm.value.getData()
   let newData = { ...genereditForm.value, ...data }
+  delete newData.createTime
   allLoading.saveLoading = true
-  post(ADDPRODUCT, { ...newData }).then((res) => {
-    console.log(res)
-    if(res.code != 'ok') {
-      globalPopup?.showError(res.msg)
-      return
-    }
+  post(ADDPRODUCT, { ...newData }).then(() => {
     globalPopup?.showSuccess('保存成功')
-    if (!flag) {
+    if (flag) {
       genereditForm.value = {}
       generateForm.value && generateForm.value.reset()
-      generateFormKey.value++
     }
+    getProductTableList()
     dialogVisible.editProductVisible = flag
-  }).catch(() => {
-    dialogVisible.editProductVisible = flag
+  }).catch((err) => {
+    globalPopup?.showError(err.msg)
   }).finally(() => {
     allLoading.saveLoading = false
   })
 }
 
-function editProduct(_flag: boolean) {
+function editProduct(item: any) {
   dialogVisible.editProductVisible = true
   allLoading.generateFormLading = true
+  if (item) {
+    genereditForm.value = item
+    allText.editClueText = '编辑产品'
+  }
+  if (!item) {
+    genereditForm.value = {}
+  }
   setTimeout(() => {
     generateForm.value && generateForm.value.reset()
     generateFormKey.value++
     allLoading.generateFormLading = false
-  }, 1000)
+  }, 500)
 }
 
 function getProductTableList() {
   allLoading.productTableLading = true
   let valueForm = getFromValue(filterProductForm)
   post(GETTABLELIST, { ...valueForm }).then((res) => {
-    if(res.code == 'ok') {
+    if (res.code == 'ok') {
       const { record, total } = res.data
       productTableList.value = record
       productTableTotal.value = total
@@ -217,6 +265,19 @@ function getProductTableList() {
   })
 }
 
+async function importProducts(param: UploadRequestOptions) {
+  allLoading.importLoading = true
+  const formData = new FormData();
+  formData.append('multipartFile', param.file)
+  const res = await uploadFile(UPLOADFILE, formData)
+  allLoading.importLoading = false
+  if (res.code == 'ok') {
+    globalPopup?.showSuccess(res.msg || '')
+    return
+  }
+  globalPopup?.showError(res.msg || '')
+}
+
 function handleSizeChange(val: number) {
   filterProductForm.pageIndex = 1
   filterProductForm.pageSize = val
@@ -235,9 +296,9 @@ function resetFilter() {
 }
 
 function toProductDetail(row: any) {
-  router.push({ 
-    path: `${MOD}/detail`, 
-    query: { id: row.id } 
+  router.push({
+    path: `${MOD}/detail`,
+    query: { id: row.id }
   })
 }
 

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

@@ -117,8 +117,8 @@
         </div>
       </div>
     </div>
-    <TaskModal :visible="taskModalVisible" :title="taskForm?'编辑任务':'新建任务'" :save-loading="taskLoading"
-      :edit-form="taskForm" @close="closeTaskModal" @submit="submitForm" :disabled-list="[]"/>
+    <TaskModal :visible="taskModalVisible" :title="taskForm ? '编辑任务' : '新建任务'" :save-loading="taskLoading"
+      :edit-form="taskForm" @close="closeTaskModal" @submit="submitForm" />
     <ImportModal :visible="importVisible" :save-loading="importLoading" @close="closeImportModal"
       @submit="importExcel" />
     <ExportModal :visible="exportVisible" :save-loading="exportLoading" @close="closeExportModal"
@@ -171,105 +171,14 @@ const searchForm = ref<any>();
 const tableRef = ref<InstanceType<typeof ElTable>>();
 const loading = ref<boolean>(false);
 const totalCount = ref<number>(0);
-const tableData = ref<any[]>([
-  {
-    taskName: '任务1111111111111111111111111',
-    contactsTel: "15100111111",
-    contactsName: "水水水水",
-    customerName: '李四',
-    status: 0,
-    priority: 0,
-    executorId: [1, 2], //执行人id
-    startDate: dayjs().format('YYYY-MM-DD'),
-    endDate: dayjs().format('YYYY-MM-DD'),
-    repeat:1,
-    taskType: 1,
-    endType: 1,
-    taskDesc: "任务秒数",
-    repeatType:4,
-    repeatDesignDay: "1,4,3,4",
-    taskLogs: [
-      {
-        id: 3,
-        modTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
-        userName: '张三',
-        content: '删除任务'
-      },
-      {
-        id: 2,
-        modTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
-        operateType: '2',
-        userName: '张三',
-        content: '修改任务'
-      }, {
-        id: 1,
-        modTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
-        operateType: '1',
-        userName: '张三',
-        content: '创建任务'
-      }
-    ]
-  },
-  {
-    taskName: '任务222',
-    customerName: '张三',
-    status: '1',
-    priority: '1',
-    startDate: dayjs().format('YYYY-MM-DD'),
-    endDate: dayjs().format('YYYY-MM-DD'),
-    taskType: '2'
-  },
-  {
-    taskName: '任务333',
-    customerName: '王五',
-    status: '2',
-    priority: '2',
-    startDate: dayjs().format('YYYY-MM-DD'),
-    endDate: dayjs().format('YYYY-MM-DD'),
-    taskType: '0'
-  },
-  {
-    taskName: '任务444',
-    customerName: '赵六',
-    status: '3',
-    priority: '1',
-    startDate: dayjs().format('YYYY-MM-DD'),
-    endDate: dayjs().format('YYYY-MM-DD'),
-    taskType: '3'
-  },
-  {
-    taskName: '任务555',
-    customerName: '马六',
-    status: '1',
-    priority: '2',
-    startDate: dayjs().format('YYYY-MM-DD'),
-    endDate: dayjs().format('YYYY-MM-DD'),
-  },
-  {
-    taskName: '任务666',
-    customerName: '吴七',
-    status: '3',
-    priority: '0',
-    startDate: dayjs().format('YYYY-MM-DD'),
-    endDate: dayjs().format('YYYY-MM-DD'),
-  },
-  {
-    taskName: '任务777',
-    customerName: '钱八',
-    status: '0',
-    priority: '1',
-    startDate: dayjs().format('YYYY-MM-DD'),
-    endDate: dayjs().format('YYYY-MM-DD'),
-  }
-])
+const tableData = ref<any[]>([])
 function search() {
-  return
   loading.value = true;
   post(PAGE_LIST, getFromValue(searchForm.value)).then(({ data }) => {
     loading.value = false;
     const { total, record } = data;
     totalCount.value = total;
-    // tableData.value = record;
+    tableData.value = record;
   }).catch(err => {
     console.log("err", err);
     loading.value = false;

+ 1 - 6
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/attachment.vue

@@ -64,12 +64,7 @@ const props = defineProps<{
 
 // 下载文件
 function fileDownload(item: any) {
-    const id = item.id
-    post(DOWNFILE, { id }).then((res) => {
-        downloadFile(res, item.name)
-    }).catch((err) => {
-        downloadFile(err, item.name)
-    })
+    downloadFile(`${item.path}`, item.name)
 }
 
 // 删除文件

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

@@ -139,7 +139,7 @@
     <DeteleTables :visibles="dialogVisible.deteleClueDialogVisible" @showDeteleClue="showDeteleClue" />
 
     <TaskModal :visible="dialogVisible.taskModalVisible" :edit-form="createTaskFromType(3)" :save-loading="'1'"
-      @close="closeTaskModal" @submit="submitForm" />
+      @close="closeTaskModal" @submit="submitForm" :title="'新建任务'" :disabled-list="['taskType', 'clueId']" />
   </div>
 </template>
 

+ 5 - 4
fhKeeper/formulahousekeeper/customerBuler-crm/src/router/index.ts

@@ -47,11 +47,9 @@ const router = createRouter({
 router.beforeEach((to, _from, next) => {
   const routerList = useStore().routers;
   const routers = router.getRoutes();
-  //console.log(routerList, routers);
   const { setAsyncRoutesMark, asyncRoutesMark, getToken } = useStore();
   const token = getToken;
   const skipPath = ["/login", "/register", "/test", "/testEcharts"];
-  //console.log(token, '<==== token')
   if (skipPath.includes(to.path)) {
     next();
   } else {
@@ -80,7 +78,6 @@ router.beforeEach((to, _from, next) => {
               });
             });
           } else {
-            console.log(`/src/pages/${filePath}/index.vue`)
             addNewRouter?.children.push({
               path: item.path,
               name: item.name,
@@ -90,6 +87,11 @@ router.beforeEach((to, _from, next) => {
           }
         });
         router.addRoute(addNewRouter);
+        router.addRoute({
+          path: '/:catchAll(.*)',
+          name: 'NotFound',
+          component: () => import("../pages/404.vue"),
+        })
         next({ ...to, replace: true });
       }
     } else {
@@ -97,6 +99,5 @@ router.beforeEach((to, _from, next) => {
       next(`/login`);
     }
   }
-  console.log(routerList);
 });
 export default router;

+ 3 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/styles/global.scss

@@ -47,7 +47,7 @@ $modena: #6f4afe;
   height: 0px;
 }
 
-.el-dialog__header,.el-dialog__body{
-  margin: 0;
-  padding: 0;
+.el-dialog__header, .el-dialog__body{
+  margin: 0 !important;
+  padding: 0 !important;
 }

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/request.ts

@@ -45,13 +45,13 @@ instance.interceptors.response.use(
 );
 
 // 封装GET请求
-export async function get(url: string, params?: any): Promise<any> {
+export async function get(url: string, params?: any, file: boolean = false): Promise<any> {
   return new Promise((resolve, reject) => {
     instance
       .get(url, { params })
       .then(({ data }: any) => {
         const { code } = data;
-        if (code === "ok") {
+        if (code === "ok" || file) {
           resolve(data);
           return;
         }

+ 10 - 12
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts

@@ -1,5 +1,6 @@
 import { defalutModalForm } from '@/components/TaskModal/api'
 import { ElMessageBox } from 'element-plus';
+import { get } from './request';
 /**
  * 判断值是否为空
  * @param value 值
@@ -155,20 +156,17 @@ export function createTaskFromType(taskType: TASK_VALUE_TYPE) {
 
 /**
  * 下载文件
- * @param dataFile 接口返回的数据
+ * @param fileData 接口返回的数据 或 文件地址
  * @param fileName 文件名称
  */
-export function downloadFile(dataFile: any, fileName: string) {
-  const data = dataFile;
-  const blob = new Blob([data]);
-  const url = window.URL.createObjectURL(blob);
-  const a = document.createElement('a');
-  a.href = url;
-  a.download = fileName;
-  document.body.appendChild(a);
-  a.click();
-  window.URL.revokeObjectURL(url);
-  document.body.removeChild(a);
+export async function downloadFile(fileData: any, fileName: string) {
+  const url=fileData;
+  const link = document.createElement('a');
+  link.href = url;
+  link.setAttribute('download', fileName);
+  document.body.appendChild(link);
+  link.click();
+  document.body.removeChild(link);
 };
 
 /**

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/vite.config.ts

@@ -4,7 +4,7 @@ import vue from "@vitejs/plugin-vue";
 import { resolve } from "path";
 
 // const target = "http://192.168.2.8:10010";
-const target = "http://192.168.2.93:10010";
+const target = "http://192.168.2.178:10010";
 // const target = "http://47.101.180.183:10010";
 
 export default defineConfig({

+ 176 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/AttachmentCenterController.java

@@ -0,0 +1,176 @@
+package com.management.platform.controller;
+
+
+import com.management.platform.entity.AttachmentCenter;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.*;
+import com.management.platform.service.ProductService;
+import com.management.platform.task.SFTPAsyncUploader;
+import com.management.platform.util.DocumentTypeUtil;
+import com.management.platform.util.FileUtil;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MessageUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+@RestController
+@RequestMapping("/attachment")
+public class AttachmentCenterController {
+    @Resource
+    private ProductService productService;
+    @Resource
+    private HttpServletRequest request;
+
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private AttachmentCenterMapper attachmentCenterMapper;
+    @Value("${upload.path}")
+    private String uploadPath;
+
+    @Autowired
+    public SFTPAsyncUploader sftpAsyncUploader;
+
+    /**
+     * 上传文件
+     * @param files 上传的文件
+     * @param response
+     * @return
+     * @throws Exception
+     */
+    @RequestMapping(value="uploadAttachment")
+    public HttpRespMsg uploadAttachment(
+            @RequestParam Integer moduleId,
+            @RequestParam String moduleCode,
+            @RequestParam("file") MultipartFile[] files,
+            HttpServletResponse response) throws Exception {
+        HttpRespMsg msg = new HttpRespMsg();
+        User user = (User) userMapper.selectById(request.getHeader("Token"));
+
+        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
+        for (MultipartFile file : files) {
+            AttachmentCenter record = new AttachmentCenter();
+            record.setCreatorId(user.getId());
+            record.setCreatorName(user.getName());
+            record.setAttachmentName(file.getOriginalFilename());
+            record.setModuleId(moduleId);
+            record.setModuleCode(moduleCode);
+            if (file != null && !file.isEmpty()) {
+                //截取文件后缀
+                String fileSuffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
+                record.setAttachmentType(DocumentTypeUtil.DocumentType(fileSuffix));
+                record.setAttachmentSuffix(fileSuffix);
+                //处理文件
+                File dir = new File(uploadPath);
+                if (!dir.exists()) {
+                    dir.mkdir();
+                }
+                String fileName= "";
+                if (file!=null && !file.isEmpty()) {
+                    fileName = file.getOriginalFilename();
+
+                    int pos = fileName.lastIndexOf(".");
+                    String suffix = fileName.substring(pos).toLowerCase();
+                    //用uuid替换原始的文件名
+                    String purFName = UUID.randomUUID().toString().replaceAll("-", "");
+                    fileName = purFName + suffix;
+                    File saveFile = new File(dir, fileName);
+                    try {
+                        saveFile.createNewFile();
+                        file.transferTo(saveFile);
+                        //异步上传到备份服务器
+                        sftpAsyncUploader.uploadFileAsync(saveFile);
+
+                        //计算文件大小
+                        long fileSize = saveFile.length();
+                        String fileLength = FileUtil.getReadableFileSize(fileSize);
+                        record.setServerName(uploadPath + fileName);
+
+                        record.setSize(fileLength);
+                        String pathPrefix = "/upload/";
+                        record.setUrl(pathPrefix + fileName);
+                        attachmentCenterMapper.insert(record);
+                        String path = uploadPath;
+                        //生成原文件名称与服务器文件名称对应
+                        msg.data = record;
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                        fileName = null;
+                        msg.setError(e.getMessage()+", path="+dir.getAbsolutePath());
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        fileName = null;
+                        msg.setError(e.getMessage()+", path="+dir.getAbsolutePath());
+                    }
+                } else {
+                    msg.setError(MessageUtils.message("file.nonExistentError"));
+                }
+            }
+        }
+        return msg;
+    }
+
+    @RequestMapping("/rename")
+    public HttpRespMsg rename(Integer id,String name){
+        HttpRespMsg msg=new HttpRespMsg();
+        AttachmentCenter attachmentCenter = attachmentCenterMapper.selectById(id);
+        File file = new File(attachmentCenter.getServerName());
+        if(file.exists()){
+            attachmentCenter.setAttachmentName(name);
+            String pathPrefix = "/upload/";
+            attachmentCenterMapper.updateById(attachmentCenter);
+            msg.setMsg("文件重命名成功");
+        }else {
+            msg.setError("文件不存在");
+        }
+        return msg;
+    }
+
+    @RequestMapping("/delete")
+    public HttpRespMsg delete(Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        AttachmentCenter attachmentCenter = attachmentCenterMapper.selectById(id);
+        File file = new File(attachmentCenter.getServerName());
+        if(file.exists()){
+            boolean delete = file.delete();
+            if(delete){
+                attachmentCenterMapper.deleteById(id);
+                msg.setMsg("文件删除成功");
+            }else {
+                msg.setError("文件删除失败");
+            }
+        }else {
+            msg.setError("文件不存在");
+        }
+        return msg;
+    }
+
+    @RequestMapping("/attachmentList")
+    public HttpRespMsg attachmentList(Integer moduleId, String moduleCode){
+        // 根据 moduleId 和 moduleCode 查询 attachment_center 表
+        return productService.attachmentList(moduleId, moduleCode);
+    }
+}
+

+ 39 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/AuditLogCenterController.java

@@ -0,0 +1,39 @@
+package com.management.platform.controller;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.management.platform.entity.AuditLogCenter;
+import com.management.platform.service.AuditLogCenterService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+@RestController
+@RequestMapping("/audit-log-center")
+public class AuditLogCenterController {
+
+    @Resource
+    private AuditLogCenterService auditLogCenterService;
+
+    @RequestMapping("/list")
+    public HttpRespMsg list(String moduleCode,Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        List<AuditLogCenter> list = auditLogCenterService.list(new LambdaQueryWrapper<AuditLogCenter>().eq(AuditLogCenter::getModuleCode, moduleCode).eq(AuditLogCenter::getModuleId,id));
+        msg.setData(list);
+        return msg;
+    }
+
+}
+

+ 35 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java

@@ -52,6 +52,40 @@ public class BusinessOpportunityController {
         return bOservice.exportData(bo,request);
     }
 
+    // 批量放入回收站
+    @RequestMapping("delete")
+    public Object delete(BusinessOpportunity bo) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String ids1 = bo.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            bOservice.isDelete(ids);
+            msg.setMsg("操作成功");
+        } else {
+            msg.setError("请选择线索");
+
+        }
+        return msg;
+    } @RequestMapping("rollBack")
+    public Object rollBack(BusinessOpportunity bo) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String ids1 = bo.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            bOservice.isRollBack(ids);
+            msg.setMsg("操作成功");
+        } else {
+            msg.setError("请选择线索");
+
+        }
+        return msg;
+    }
     @RequestMapping("insertAndUpdate")
     public HttpRespMsg insertAndUpdate( BusinessOpportunity bo, HttpServletRequest request) {
         User user = userMapper.selectById(request.getHeader("Token"));
@@ -181,7 +215,7 @@ public class BusinessOpportunityController {
 
     // 上传
     @RequestMapping("uploadFile")
-    public Object uploadFile(BusinessItemCustom bo, HttpServletRequest request, MultipartFile file) throws Exception {
+    public Object uploadFile(BusinessOpportunity bo, HttpServletRequest request, MultipartFile file) throws Exception {
         return bOservice.uploadFile(bo, request, file);
     }
 

+ 4 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ContactsController.java

@@ -44,6 +44,10 @@ public class ContactsController {
     public HttpRespMsg addContacts(Contacts contacts){
         return contactsService.addContacts(contacts, request);
     }
+    @RequestMapping("/getAllContacts")
+    public HttpRespMsg getAllContacts(HttpServletRequest request){
+        return contactsService.getAllContacts(request);
+    }
 
     /**
      * 分页查询联系人

+ 4 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java

@@ -42,6 +42,10 @@ public class CustomController {
     public HttpRespMsg list(Custom custom , HttpServletRequest request){
         return customService.getList(custom,request);
     }
+    @RequestMapping("getAllCustom")
+    public HttpRespMsg getAllCustom( HttpServletRequest request){
+        return customService.getAllCustom(request);
+    }
     @RequestMapping("deleteList")
     public HttpRespMsg deleteList(Custom custom , HttpServletRequest request){
         return customService.getDeleteList(custom,request);

+ 0 - 110
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/OrderController.java

@@ -1,110 +0,0 @@
-package com.management.platform.controller;
-
-
-import com.alibaba.fastjson.JSONArray;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.management.platform.entity.Order;
-import com.management.platform.entity.OrderProductDetail;
-import com.management.platform.entity.Product;
-import com.management.platform.entity.Task;
-import com.management.platform.mapper.UserMapper;
-import com.management.platform.service.OrderProductDetailService;
-import com.management.platform.service.OrderService;
-import com.management.platform.service.ProductService;
-import com.management.platform.service.TaskService;
-import com.management.platform.util.HttpRespMsg;
-import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
-import java.util.List;
-
-/**
- * <p>
- *  前端控制器
- * </p>
- *
- * @author Seyason
- * @since 2024-02-28
- */
-@RestController
-@RequestMapping("/order")
-public class OrderController {
-    @Resource
-    private OrderService orderService;
-    @Resource
-    private UserMapper userMapper;
-    @Resource
-    private HttpServletRequest request;
-    @Resource
-    private OrderProductDetailService orderProductDetailService;
-
-    @RequestMapping("/list")
-    public HttpRespMsg list(String userId, String orderName,String orderCode, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete){
-        return orderService.getList(userId,orderName,orderCode,productCode,pageIndex,pageSize,isDelete);
-    }
-
-    @RequestMapping("/addOrUpdate")
-    public HttpRespMsg addOrUpdate(Order order){
-        HttpRespMsg msg=new HttpRespMsg();
-        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
-        order.setCompanyId(companyId);
-        int count;
-        if(order.getId()==null){
-            count = orderService.count(new LambdaQueryWrapper<Order>().eq(Order::getCompanyId, companyId).eq(Order::getOrderCode, order.getOrderCode()));
-        }else {
-            count = orderService.count(new LambdaQueryWrapper<Order>().eq(Order::getCompanyId, companyId).ne(Order::getId,order.getId()).eq(Order::getOrderCode,order.getOrderCode()));
-        }
-        if(count>0){
-            msg.setError("订单编号为["+order.getOrderCode()+"]的订单已存在");
-            return msg;
-        }
-        if(!orderService.saveOrUpdate(order)){
-            msg.setError("验证失败");
-            return msg;
-        }
-        //处理订单下的产品数据
-        if(!StringUtils.isEmpty(order.getOrderProductDetailString())){
-            String orderProductDetailString = order.getOrderProductDetailString();
-            List<OrderProductDetail> orderProductDetails = JSONArray.parseArray(orderProductDetailString, OrderProductDetail.class);
-            if(orderProductDetails.size()>0){
-                orderProductDetails.forEach(o->{
-                    o.setOrderId(order.getId());
-                });
-                orderProductDetailService.saveOrUpdateBatch(orderProductDetails);
-            }
-        }
-        return msg;
-    }
-
-    @RequestMapping("/delete")
-    public HttpRespMsg delete(Integer id){
-        HttpRespMsg msg=new HttpRespMsg();
-        Order order = orderService.getById(id);
-        order.setIsDelete(1);
-        if(!orderService.updateById(order)){
-            msg.setError("验证失败");
-            return msg;
-        }
-        return msg;
-    }
-
-    @RequestMapping("/recover")
-    public HttpRespMsg recover(Integer id){
-        HttpRespMsg msg=new HttpRespMsg();
-        Order order = orderService.getById(id);
-        order.setIsDelete(0);
-        if(!orderService.updateById(order)){
-            msg.setError("验证失败");
-            return msg;
-        }
-        return msg;
-    }
-
-}
-

+ 218 - 19
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ProductController.java

@@ -2,16 +2,12 @@ package com.management.platform.controller;
 
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.UserMapper;
-import com.management.platform.service.ProductService;
-import com.management.platform.service.TaskService;
+import com.management.platform.service.*;
+import com.management.platform.util.BeanChangeUtil;
 import com.management.platform.util.HttpRespMsg;
-import com.management.platform.util.MessageUtils;
-import org.apache.poi.hssf.usermodel.*;
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddressList;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
@@ -19,10 +15,10 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
-import java.io.File;
-import java.io.FileOutputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
@@ -44,6 +40,20 @@ public class ProductController {
     private HttpServletRequest request;
     @Resource
     private TaskService taskService;
+    @Resource
+    private AuditLogCenterService auditLogCenterService;
+    @Resource
+    private BusinessOpportunityService businessOpportunityService;
+    @Resource
+    private BusinessItemProductService businessItemProductService;
+    @Resource
+    private CustomService customService;
+    @Resource
+    private OrderProductDetailService orderProductDetailService;
+    @Resource
+    private SalesOrderService salesOrderService;
+    @Resource
+    private SysDictService sysDictService;
 
     @RequestMapping("/list")
     public HttpRespMsg list(String userId,String productName,String productCode,Integer pageIndex,Integer pageSize){
@@ -54,8 +64,10 @@ public class ProductController {
     @RequestMapping("/addOrUpdate")
     public HttpRespMsg addOrUpdate(Product product){
         HttpRespMsg msg=new HttpRespMsg();
-        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        User user = userMapper.selectById(request.getHeader("token"));
+        Integer companyId = user.getCompanyId();
         product.setCompanyId(companyId);
+        product.setCreatorId(user.getId());
         int count;
         if(product.getId()==null){
             count = productService.count(new LambdaQueryWrapper<Product>().eq(Product::getCompanyId, companyId).eq(Product::getProductCode, product.getProductCode()));
@@ -66,25 +78,79 @@ public class ProductController {
             msg.setError("产品编码为["+product.getProductCode()+"]的产品已存在");
             return msg;
         }
+        //todo:生成操作记录
+        AuditLogCenter auditLogCenter =new AuditLogCenter();
+        auditLogCenter.setAuditorId(user.getId());
+        auditLogCenter.setAuditorName(user.getName());
+        boolean isNew=true;
+        if(product.getId()==null){
+            auditLogCenter.setAuditorContent("创建了产品");
+        }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);
+            }
+
+        }
         if(!productService.saveOrUpdate(product)){
             msg.setError("验证失败");
             return msg;
         }
+        if(isNew){
+            auditLogCenter.setModuleId(product.getId());
+            auditLogCenter.setModuleCode("Product");
+            auditLogCenterService.save(auditLogCenter);
+        }
         return msg;
     }
 
 
     @RequestMapping("/delete")
-    public HttpRespMsg delete(Integer id){
+    public HttpRespMsg delete(String ids){
         HttpRespMsg msg=new HttpRespMsg();
-        int count = taskService.count(new LambdaQueryWrapper<Task>().eq(Task::getProductId, id));
-        if(count>0){
-            msg.setError("当前产品已绑定到相关任务,删除失败");
-            return msg;
-        }
-        if(!productService.removeById(id)){
-            msg.setError("验证失败");
-            return msg;
+        User user = userMapper.selectById(request.getHeader("token"));
+        if(!StringUtils.isEmpty(ids)){
+            String[] split = ids.split(",");
+            List<String> splitList = Arrays.asList(split);
+            List<Integer> idList = splitList.stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
+            int count = taskService.count(new LambdaQueryWrapper<Task>().in(Task::getProductId, idList));
+            if(count>0){
+                msg.setError("当前产品已绑定到相关任务,删除失败");
+                return msg;
+            }
+            if(idList.size()>0){
+                List<Product> productList = productService.list(new LambdaQueryWrapper<Product>().in(Product::getId, idList));
+                productList.forEach(p->{
+                    p.setIsDelete(1);
+                });
+                if(!productService.updateBatchById(productList)){
+                    msg.setError("验证失败");
+                    return msg;
+                }
+            }
+            List<AuditLogCenter> auditLogCenters =new ArrayList<>();
+            if(idList.size()>0){
+                idList.forEach(i->{
+                    //todo: 生成操作记录
+                    AuditLogCenter auditLogCenter =new AuditLogCenter();
+                    auditLogCenter.setAuditorContent("删除了产品");
+                    auditLogCenter.setAuditorId(user.getId());
+                    auditLogCenter.setAuditorName(user.getName());
+                    auditLogCenter.setModuleId(Integer.valueOf(i));
+                    auditLogCenter.setModuleCode("Product");
+                    auditLogCenters.add(auditLogCenter);
+                });
+            }
+            if(auditLogCenters.size()>0){
+                auditLogCenterService.saveBatch(auditLogCenters);
+            }
         }
         return msg;
     }
@@ -99,5 +165,138 @@ public class ProductController {
         return productService.exportData(userId,productName,productCode);
     }
 
+    @RequestMapping("/detail")
+    public HttpRespMsg detail(Integer id){
+        return productService.getDetail(id);
+    }
+
+    @RequestMapping("/transferIncharger")
+    public HttpRespMsg transferIncharger(Integer id,String userId){
+        HttpRespMsg msg=new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        Product byId = productService.getById(id);
+        if(!StringUtils.isEmpty(userId)){
+            byId.setInchargerId(userId);
+        }
+        if(!productService.updateById(byId)){
+            msg.setError("验证失败");
+        }
+        //todo:生成操作记录
+        AuditLogCenter auditLogCenter =new AuditLogCenter();
+        if(!StringUtils.isEmpty(byId.getInchargerId())){
+            if(!byId.getInchargerId().equals(userId)){
+                auditLogCenter.setModuleId(byId.getId())
+                        .setModuleCode("Product")
+                        .setAuditorId(user.getId())
+                        .setAuditorName(user.getName())
+                        .setAuditorContent("转移了产品");
+                auditLogCenterService.save(auditLogCenter);
+            }
+        }
+        return msg;
+    }
+
+    @RequestMapping("/businessListWithProduct")
+    public HttpRespMsg businessListWithProduct(Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<BusinessItemProduct> businessItemProducts = businessItemProductService.list(new LambdaQueryWrapper<BusinessItemProduct>().eq(BusinessItemProduct::getProductId, id));
+        List<Integer> businessIds = businessItemProducts.stream().map(BusinessItemProduct::getBusinessId).distinct().collect(Collectors.toList());
+        businessIds.add(-1);
+        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"));
+        opportunityList.forEach(c->{
+            Optional<Custom> custom = customList.stream().filter(ct -> ct.getId().equals(c.getCustomerId())).findFirst();
+            if(custom.isPresent()){
+                c.setCustomerName(custom.get().getCustomName());
+            }
+            Optional<User> user = userList.stream().filter(u -> u.getId().equals(c.getCreatorId())).findFirst();
+            if(user.isPresent()){
+                c.setCreatorName(user.get().getName());
+            }
+            Optional<User> incharger = userList.stream().filter(u -> u.getId().equals(c.getInchargerId())).findFirst();
+            if(incharger.isPresent()){
+                c.setInchargerName(incharger.get().getName());
+            }
+            Optional<SysDict> businessStage = businessStageList.stream().filter(b -> b.getId().equals(c.getStageId())).findFirst();
+            if(businessStage.isPresent()){
+                c.setStageValue(businessStage.get().getName());
+            }
+        });
+        msg.setData(opportunityList);
+        return msg;
+    }
+
+    @RequestMapping("/orderWithProduct")
+    public HttpRespMsg orderWithProduct(Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<OrderProductDetail> productDetailList = orderProductDetailService.list(new LambdaQueryWrapper<OrderProductDetail>().eq(OrderProductDetail::getProductId, id));
+        List<Integer> orderIds = productDetailList.stream().map(OrderProductDetail::getOrderId).distinct().collect(Collectors.toList());
+        List<Custom> customList = customService.list(new LambdaQueryWrapper<Custom>().eq(Custom::getCompanyId, companyId));
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
+        orderIds.add(-1);
+        List<SalesOrder> orderList = salesOrderService.list(new LambdaQueryWrapper<SalesOrder>().in(SalesOrder::getId, orderIds));
+        List<SysDict> orderTypeList = sysDictService.list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, "OrderType"));
+        orderList.forEach(o->{
+            Optional<Custom> custom = customList.stream().filter(ct -> ct.getId().equals(o.getCustomId())).findFirst();
+            if(custom.isPresent()){
+                o.setCustomName(custom.get().getCustomName());
+            }
+            Optional<User> user = userList.stream().filter(u -> u.getId().equals(o.getCreatorId())).findFirst();
+            if(user.isPresent()){
+                o.setCreatorName(user.get().getName());
+            }
+            Optional<User> incharger = userList.stream().filter(u -> u.getId().equals(o.getInchargerId())).findFirst();
+            if(incharger.isPresent()){
+                o.setInchargerName(incharger.get().getName());
+            }
+            Optional<SysDict> orderType = orderTypeList.stream().filter(ot -> ot.getId().equals(o.getType())).findFirst();
+            if(orderType.isPresent()){
+                o.setTypeName(orderType.get().getName());
+            }
+        });
+        msg.setData(orderList);
+        return msg;
+    }
+
+    @RequestMapping("/recycleList")
+    public HttpRespMsg recycleList(Integer pageIndex,Integer pageSize){
+        return productService.recycleList(pageIndex,pageSize);
+    }
+
+    @RequestMapping("/batchRecoveryProduct")
+    public HttpRespMsg recovery(String ids){
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!StringUtils.isEmpty(ids)){
+            String[] idsSplit = ids.split(",");
+            List<String> splitList = Arrays.asList(idsSplit);
+            List<Integer> idList = splitList.stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
+            idList.add(-1);
+            List<Product> productList = productService.list(new LambdaQueryWrapper<Product>().in(Product::getId, idList));
+            if(productList.size()>0){
+                productList.forEach(p->{
+                    p.setIsDelete(0);
+                });
+                productService.updateBatchById(productList);
+            }
+        }
+        return msg;
+    }
+
+    @RequestMapping("/batchDeleteProduct")
+    public HttpRespMsg batchDeleteProduct(String ids){
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!StringUtils.isEmpty(ids)){
+            String[] idsSplit = ids.split(",");
+            List<String> splitList = Arrays.asList(idsSplit);
+            List<Integer> idList = splitList.stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
+            idList.add(-1);
+            productService.removeByIds(idList);
+        }
+        return msg;
+    }
 }
 

+ 186 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SalesOrderController.java

@@ -0,0 +1,186 @@
+package com.management.platform.controller;
+
+
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.ProductMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.*;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-02-28
+ */
+@RestController
+@RequestMapping("/order")
+public class SalesOrderController {
+    @Resource
+    private SalesOrderService salesOrderService;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private OrderProductDetailService orderProductDetailService;
+    @Resource
+    private ProductMapper productMapper;
+    @Resource
+    private SysDictService sysDictService;
+    @Resource
+    private TaskService taskService;
+
+    @RequestMapping("/list")
+    public HttpRespMsg list(String userId, String orderName,String orderCode, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete){
+        return salesOrderService.getList(userId,orderName,orderCode,productCode,pageIndex,pageSize,isDelete);
+    }
+
+    @RequestMapping("/addOrUpdate")
+    public HttpRespMsg addOrUpdate(SalesOrder order){
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        order.setCompanyId(companyId);
+        int count;
+        if(order.getId()==null){
+            count = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).eq(SalesOrder::getOrderCode, order.getOrderCode()));
+        }else {
+            count = salesOrderService.count(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId).ne(SalesOrder::getId,order.getId()).eq(SalesOrder::getOrderCode,order.getOrderCode()));
+        }
+        if(count>0){
+            msg.setError("订单编号为["+order.getOrderCode()+"]的订单已存在");
+            return msg;
+        }
+        if(!salesOrderService.saveOrUpdate(order)){
+            msg.setError("验证失败");
+            return msg;
+        }
+        //处理订单下的产品数据
+        if(!StringUtils.isEmpty(order.getOrderProductDetailString())){
+            String orderProductDetailString = order.getOrderProductDetailString();
+            List<OrderProductDetail> orderProductDetails = JSONArray.parseArray(orderProductDetailString, OrderProductDetail.class);
+            if(orderProductDetails.size()>0){
+                orderProductDetails.forEach(o->{
+                    o.setOrderId(order.getId());
+                });
+                orderProductDetailService.saveOrUpdateBatch(orderProductDetails);
+            }
+        }
+        return msg;
+    }
+
+    @RequestMapping("/delete")
+    public HttpRespMsg delete(String ids){
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!StringUtils.isEmpty(ids)){
+            String[] idSplit = ids.split(",");
+            List<String> splitList = Arrays.asList(idSplit);
+            List<Integer> idList = splitList.stream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
+            List<SalesOrder> orderList = salesOrderService.list(new LambdaQueryWrapper<SalesOrder>().in(SalesOrder::getId, idList));
+            orderList.forEach(o->{
+                o.setIsDelete(1);
+            });
+            if(!salesOrderService.updateBatchById(orderList)){
+                msg.setError("验证失败");
+                return msg;
+            }
+        }
+        return msg;
+    }
+
+    @RequestMapping("/recover")
+    public HttpRespMsg recover(String ids){
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!StringUtils.isEmpty(ids)){
+            String[] idSplit = ids.split(",");
+            List<String> splitList = Arrays.asList(idSplit);
+            List<Integer> idList = splitList.stream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
+            List<SalesOrder> orderList = salesOrderService.list(new LambdaQueryWrapper<SalesOrder>().in(SalesOrder::getId, idList));
+            orderList.forEach(o->{
+                o.setIsDelete(0);
+            });
+            if(!salesOrderService.updateBatchById(orderList)){
+                msg.setError("验证失败");
+                return msg;
+            }
+        }
+        return msg;
+    }
+
+    @RequestMapping("/importData")
+    public HttpRespMsg importData(MultipartFile multipartFile){
+        return salesOrderService.importData(multipartFile);
+    }
+
+    @RequestMapping("/exportData")
+    public HttpRespMsg exportData(String userId, String orderName,String orderCode, String productCode) throws Exception {
+        return salesOrderService.exportData(userId,orderName,orderCode,productCode);
+    }
+
+    @RequestMapping("/productWithOrder")
+    public HttpRespMsg productWithOrder(Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
+        List<SysDict> sysDictOfProductUnit = sysDictService.list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, "ProductUnit"));
+        List<SysDict> sysDictOfProductType = sysDictService.list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, "ProductType"));
+        List<OrderProductDetail> orderProductDetails = orderProductDetailService.list(new LambdaQueryWrapper<OrderProductDetail>().eq(OrderProductDetail::getOrderId, id));
+        List<Integer> productIds = orderProductDetails.stream().map(OrderProductDetail::getProductId).collect(Collectors.toList());
+        productIds.add(-1);
+        List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>().in(Product::getId, productIds));
+        productList.forEach(p->{
+            Optional<User> user = userList.stream().filter(u -> u.getId().equals(p.getInchargerId())).findFirst();
+            if(user.isPresent()){
+                p.setInchargerName(user.get().getName());
+            }
+            Optional<User> creator = userList.stream().filter(u -> u.getId().equals(p.getCreatorId())).findFirst();
+            if(creator.isPresent()){
+                p.setCreatorName(creator.get().getName());
+            }
+            Optional<SysDict> unit = sysDictOfProductUnit.stream().filter(u -> u.getId().equals(p.getUnit())).findFirst();
+            if(unit.isPresent()){
+                p.setUnitName(unit.get().getName());
+            }
+            Optional<SysDict> type = sysDictOfProductType.stream().filter(u -> u.getId().equals(p.getType())).findFirst();
+            if(type.isPresent()){
+                p.setTypeName(type.get().getName());
+            }
+        });
+        msg.setData(productList);
+        return msg;
+    }
+
+    @RequestMapping("/taskWithOrder")
+    public HttpRespMsg taskWithOrder(Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
+        List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getOrderId, id));
+        taskList.forEach(p->{
+            Optional<User> user = userList.stream().filter(u -> u.getId().equals(p.getExecutorId())).findFirst();
+            if(user.isPresent()){
+                p.setExecutorName(user.get().getName());
+            }
+        });
+        msg.setData(taskList);
+        return msg;
+    }
+
+}
+

+ 99 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/AttachmentCenter.java

@@ -0,0 +1,99 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class AttachmentCenter extends Model<AttachmentCenter> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 附件名称
+     */
+    @TableField("attachment_name")
+    private String attachmentName;
+
+    /**
+     * 服务器生成的附件
+     */
+    @TableField("server_name")
+    private String serverName;
+
+    /**
+     * 对外访问地址
+     */
+    @TableField("url")
+    private String url;
+
+    @TableField("creator_id")
+    private String creatorId;
+
+    @TableField("creator_name")
+    private String creatorName;
+
+    @TableField("indate")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime indate;
+
+    /**
+     * 模块id
+     */
+    @TableField("module_id")
+    private Integer moduleId;
+
+    /**
+     * 模块代码
+     */
+    @TableField("module_code")
+    private String moduleCode;
+
+    /**
+     * 文件大小
+     */
+    @TableField("size")
+    private String size;
+
+    /**
+     * 文件类型
+     */
+    @TableField("attachment_type")
+    private Integer attachmentType;
+
+    /**
+     * 文件后缀
+     */
+    @TableField("attachment_suffix")
+    private String attachmentSuffix;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 78 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/AuditLogCenter.java

@@ -0,0 +1,78 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class AuditLogCenter extends Model<AuditLogCenter> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 模块id
+     */
+    @TableField("module_id")
+    private Integer moduleId;
+
+    /**
+     * 模块编码
+     */
+    @TableField("module_code")
+    private String moduleCode;
+
+    /**
+     * 操作时间
+     */
+    @TableField("audit_time")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime auditTime;
+
+    /**
+     * 操作人id
+     */
+    @TableField("auditor_id")
+    private String auditorId;
+
+    /**
+     * 操作人
+     */
+    @TableField("auditor_name")
+    private String auditorName;
+
+    /**
+     * 操作内容
+     */
+    @TableField("auditor_content")
+    private String auditorContent;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 11 - 8
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessOpportunity.java

@@ -11,9 +11,11 @@ import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -51,7 +53,7 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
     @TableField("contacts_id")
     private Integer contactsId;
     @TableField(exist = false)
-    private Integer contactsName;
+    private String contactsName;
 
     /**
      * 客户id
@@ -60,11 +62,7 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
     private Integer customerId;
     @TableField(exist = false)
     private String customerName;
-    /**
-     * 产品id
-     */
-    @TableField("product_id")
-    private Integer productId;
+
 
     /**
      * 商机金额
@@ -76,13 +74,16 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
      * 预计成交日期
      */
     @TableField("expected_transaction_date")
-    private LocalDateTime expectedTransactionDate;
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date expectedTransactionDate;
 
     /**
-     * 商机阶段 0-验证客户 1-需求分析 2-方案报价 3-赢单
+     * 商机阶段
      */
     @TableField("stage_id")
     private Integer stageId;
+
     @TableField(exist = false)
     private String stageValue;
     @TableField(exist = false)
@@ -92,6 +93,8 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
      * 创建时间
      */
     @TableField("create_time")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
     private Date createTime;
     @TableField(exist = false)
     private String startTime;

+ 9 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Product.java

@@ -133,9 +133,18 @@ public class Product extends Model<Product> {
     @TableField("descs")
     private String descs;
 
+    /**
+     * 回收站 0-否 1-是
+     */
+    @TableField("is_delete")
+    private Integer isDelete;
+
     @TableField(exist = false)
     private String inchargerName;
 
+    @TableField(exist = false)
+    private String creatorName;
+
     @TableField(exist = false)
     private String typeName;
 

+ 7 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Order.java

@@ -27,7 +27,7 @@ import org.springframework.format.annotation.DateTimeFormat;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
-public class Order extends Model<Order> {
+public class SalesOrder extends Model<SalesOrder> {
 
     private static final long serialVersionUID=1L;
 
@@ -202,6 +202,12 @@ public class Order extends Model<Order> {
     @TableField(exist = false)
     private String inchargerName;
 
+    @TableField(exist = false)
+    private String customName;
+
+    @TableField(exist = false)
+    private String creatorName;
+
 
     @Override
     protected Serializable pkVal() {

+ 5 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/UploadFile.java

@@ -68,6 +68,11 @@ public class UploadFile extends Model<UploadFile> {
      */
     @TableField("create_id")
     private String createId;
+    /**
+     * 创建人id
+     */
+    @TableField("file_type")
+    private String fileType;
 
     /**
      * 模块码clue线索 business商户 custom客户

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/AttachmentCenterMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.AttachmentCenter;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+public interface AttachmentCenterMapper extends BaseMapper<AttachmentCenter> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/AuditLogCenterMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.AuditLogCenter;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+public interface AuditLogCenterMapper extends BaseMapper<AuditLogCenter> {
+
+}

+ 4 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessOpportunityMapper.java

@@ -25,4 +25,8 @@ public interface BusinessOpportunityMapper extends BaseMapper<BusinessOpportunit
     int getTotal(BusinessOpportunity bo);
     int getTotal1(@Param("bo") BusinessOpportunity bo,@Param("userId") String userId);
     int getTotal2(@Param("bo") BusinessOpportunity bo,@Param("userId") String userId);
+
+    BusinessOpportunity selectByIdToInfo(Integer id);
+
+    void updateBatchById(List<Integer> ids);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ProductAuditLogMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.AuditLogCenter;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+public interface ProductAuditLogMapper extends BaseMapper<AuditLogCenter> {
+
+}

+ 3 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/OrderMapper.java

@@ -1,6 +1,6 @@
 package com.management.platform.mapper;
 
-import com.management.platform.entity.Order;
+import com.management.platform.entity.SalesOrder;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.management.platform.entity.User;
 import org.apache.ibatis.annotations.Select;
@@ -15,8 +15,8 @@ import java.util.List;
  * @author Seyason
  * @since 2024-02-28
  */
-public interface OrderMapper extends BaseMapper<Order> {
+public interface SalesOrderMapper extends BaseMapper<SalesOrder> {
 
     @Select("select * from `order` WHERE company_id = #{companyId} AND is_delete = 0 ")
-    List<Order> getList(User user);
+    List<SalesOrder> getList(User user);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/AttachmentCenterService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.AttachmentCenter;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+public interface AttachmentCenterService extends IService<AttachmentCenter> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/AuditLogCenterService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.AuditLogCenter;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+public interface AuditLogCenterService extends IService<AuditLogCenter> {
+
+}

+ 5 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessOpportunityService.java

@@ -41,11 +41,15 @@ public interface BusinessOpportunityService extends IService<BusinessOpportunity
 
     HttpRespMsg saveProduct(BusinessOpportunity bo, User user);
 
-    Object uploadFile(BusinessItemCustom bo, HttpServletRequest request, MultipartFile file);
+    Object uploadFile(BusinessOpportunity bo, HttpServletRequest request, MultipartFile file);
 
     Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response);
 
     Object deleteFile(UploadFile file, HttpServletRequest request);
 
     Object reFileName(UploadFile uploadFile, HttpServletRequest request);
+
+    void isDelete(List<Integer> ids);
+
+    void isRollBack(List<Integer> ids);
 }

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

@@ -40,4 +40,6 @@ public interface ContactsService extends IService<Contacts> {
     HttpRespMsg importData(MultipartFile multipartFile, HttpServletRequest request);
 
     HttpRespMsg exportData(String customName, String name, String email, String creatorName, String phone, String ownerName, HttpServletRequest request) throws Exception;
+
+    HttpRespMsg getAllContacts(HttpServletRequest request);
 }

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

@@ -46,4 +46,6 @@ public interface CustomService extends IService<Custom> {
     Object deleteFile(UploadFile file, HttpServletRequest request);
 
     Object reFileName(UploadFile uploadFile, HttpServletRequest request);
+
+    HttpRespMsg getAllCustom(HttpServletRequest request);
 }

+ 6 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ProductService.java

@@ -22,4 +22,10 @@ public interface ProductService extends IService<Product> {
     HttpRespMsg importData(MultipartFile multipartFile);
 
     HttpRespMsg exportData(String userId, String productName, String productCode) throws Exception;
+
+    HttpRespMsg getDetail(Integer id);
+
+    HttpRespMsg recycleList(Integer pageIndex, Integer pageSize);
+
+    HttpRespMsg attachmentList(Integer moduleId, String moduleCode);
 }

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

@@ -1,8 +1,9 @@
 package com.management.platform.service;
 
-import com.management.platform.entity.Order;
+import com.management.platform.entity.SalesOrder;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * <p>
@@ -12,7 +13,11 @@ import com.management.platform.util.HttpRespMsg;
  * @author Seyason
  * @since 2024-02-28
  */
-public interface OrderService extends IService<Order> {
+public interface SalesOrderService extends IService<SalesOrder> {
 
     HttpRespMsg getList(String userId, String orderName,String orderCode, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete);
+
+    HttpRespMsg importData(MultipartFile multipartFile);
+
+    HttpRespMsg exportData(String userId, String orderName, String orderCode, String productCode) throws Exception;
 }

+ 20 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/AttachmentCenterServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.AttachmentCenter;
+import com.management.platform.mapper.AttachmentCenterMapper;
+import com.management.platform.service.AttachmentCenterService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+@Service
+public class AttachmentCenterServiceImpl extends ServiceImpl<AttachmentCenterMapper, AttachmentCenter> implements AttachmentCenterService {
+
+}

+ 20 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/AuditLogCenterServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.AuditLogCenter;
+import com.management.platform.mapper.AuditLogCenterMapper;
+import com.management.platform.service.AuditLogCenterService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-15
+ */
+@Service
+public class AuditLogCenterServiceImpl extends ServiceImpl<AuditLogCenterMapper, AuditLogCenter> implements AuditLogCenterService {
+
+}

+ 31 - 7
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java

@@ -75,7 +75,7 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
 
     @Override
     public BusinessOpportunity getInfo(BusinessOpportunity bo, User user) {
-        BusinessOpportunity businessOpportunity = bOMapper.selectById(bo.getId());
+        BusinessOpportunity businessOpportunity = bOMapper.selectByIdToInfo(bo.getId());
         businessOpportunity.setActionLogList(actionLogMapper.selectList(new QueryWrapper<ActionLog>().eq("item_id", bo.getId()).eq("code", "business")));
         businessOpportunity.setUploadFilePList(uploadFileMapper.selectByInfoList("business",bo.getId()));
         businessOpportunity.setTaskList(taskMapper.selectList(new QueryWrapper<Task>().eq("business_opportunity_id",bo.getId())));
@@ -93,7 +93,7 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
                 // 折后价格
                 discountedPrice = discountedPrice.add(price.multiply(divide));
             }
-            BigDecimal divide = discountedPrice.divide(finalPrice);
+            BigDecimal divide = discountedPrice.divide(finalPrice,2,BigDecimal.ROUND_UP);
             // 整单折扣率
             businessOpportunity.setFinalPrice(divide.multiply(new BigDecimal(100)));
         }
@@ -236,7 +236,7 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
     @Value(value = "${upload.file}")
     private String filePath;
     @Override
-    public Object uploadFile(BusinessItemCustom bo, HttpServletRequest request, MultipartFile file) {
+    public Object uploadFile(BusinessOpportunity bo, HttpServletRequest request, MultipartFile file) {
         User user = userMapper.selectById(request.getHeader("token"));
         if (!file.isEmpty()) { // 检查上传的文件是否为空
             try {
@@ -257,10 +257,14 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
                 //用uuid替换原始的文件名
                 String purFName = UUID.randomUUID().toString().replaceAll("-", "");
                 realName = purFName + suffix;
-
-
-                uf.setPath(filePath + realName);
+                long size = file.getSize();
+                double v = (double) size / (1024 * 1024);
+                String format = String.format("%.2f MB", v);
+                uf.setPath("/file/" + realName);
                 uf.setCode("business");
+                System.out.println(format);
+                uf.setSize(format);
+                uf.setFileType(suffix);
                 uf.setItemId(bo.getId());
                 uf.setRealName(realName);
                 uf.setCreateTime(new Date());
@@ -291,7 +295,8 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
             HttpRespMsg msg = new HttpRespMsg();
             msg.setError("请选择上传文件");
             return msg;
-        }    }
+        }
+    }
 
     @Override
     public Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response) {
@@ -340,6 +345,25 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
         return uploadFileMapper.update(null, new UpdateWrapper<UploadFile>().eq("id", uploadFile.getId()).set("name", uploadFile.getName()));
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void isDelete(List<Integer> ids) {
+        UpdateWrapper<BusinessOpportunity> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.in("id", ids);
+        BusinessOpportunity bo = new BusinessOpportunity();
+        bo.setIsDelete(1);
+        bOMapper.update(bo, updateWrapper);
+    }
+
+    @Override
+    public void isRollBack(List<Integer> ids) {
+        UpdateWrapper<BusinessOpportunity> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.in("id", ids);
+        BusinessOpportunity bo = new BusinessOpportunity();
+        bo.setIsDelete(0);
+        bOMapper.update(bo, updateWrapper);
+    }
+
     private BusinessOpportunity setNull(BusinessOpportunity bo) {
         if (bo.getPlate1() == "") {
             bo.setPlate1(null);

+ 5 - 5
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java

@@ -304,14 +304,14 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                 //用uuid替换原始的文件名
                 String purFName = UUID.randomUUID().toString().replaceAll("-", "");
                 realName = purFName + suffix;
-
                 long size = file.getSize();
-                String s = "MB";
-                double  l = size / 1024.00 / 1024.00;
-                System.out.println(size);
+                double v = (double) size / (1024 * 1024);
+                String format = String.format("%.2f MB", v);
                 uf.setPath("/file/" + realName);
                 uf.setCode("clue");
-                uf.setSize(l+s);
+                System.out.println(format);
+                uf.setSize(format);
+                uf.setFileType(suffix);
                 uf.setItemId(clue.getId());
                 uf.setRealName(realName);
                 uf.setCreateTime(new Date());

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

@@ -575,5 +575,13 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
         return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName,dataList,path);
     }
 
+    @Override
+    public HttpRespMsg getAllContacts(HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("token"));
+        HttpRespMsg mgs = new HttpRespMsg();
+        mgs.setData(contactsMapper.selectList(new QueryWrapper<Contacts>().eq("company_id",user.getCompanyId())));
+        return mgs;
+    }
+
 
 }

+ 18 - 5
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java

@@ -211,11 +211,11 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
         boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门客户");
         List<Custom> list = new ArrayList<>();
         int i = 0;
-        if (!isAll) {
+        if (isAll) {
             //查看全部线索
             list = customMapper.getList(custom);
             i = customMapper.getTotal(custom);
-        } else if (!isNotAll) {
+        } else if (isNotAll) {
             //查看负责部门线索 找出所处部门下所有的负责人
             list = customMapper.getList1(custom);
             i = customMapper.getTotal1(custom);
@@ -290,10 +290,14 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
                 //用uuid替换原始的文件名
                 String purFName = UUID.randomUUID().toString().replaceAll("-", "");
                 realName = purFName + suffix;
-
-
-                uf.setPath(filePath + realName);
+                long size = file.getSize();
+                double v = (double) size / (1024 * 1024);
+                String format = String.format("%.2f MB", v);
+                uf.setPath("/file/" + realName);
                 uf.setCode("custom");
+                System.out.println(format);
+                uf.setSize(format);
+                uf.setFileType(suffix);
                 uf.setItemId(custom.getId());
                 uf.setRealName(realName);
                 uf.setCreateTime(new Date());
@@ -372,6 +376,15 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
         return uploadFileMapper.update(null, new UpdateWrapper<UploadFile>().eq("id", uploadFile.getId()).set("name", uploadFile.getName()));
     }
 
+    @Override
+    public HttpRespMsg getAllCustom(HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("token"));
+        Integer companyId = user.getCompanyId();
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(customMapper.selectList(new QueryWrapper<Custom>().eq("company_id",companyId)));
+        return msg;
+    }
+
 
     private Custom setNull(Custom clue) {
         if (clue.getPlate1() == "") {

+ 0 - 141
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/OrderServiceImpl.java

@@ -1,141 +0,0 @@
-package com.management.platform.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.management.platform.entity.*;
-import com.management.platform.mapper.*;
-import com.management.platform.service.DepartmentService;
-import com.management.platform.service.OrderService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.management.platform.service.SysFunctionService;
-import com.management.platform.util.HttpRespMsg;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * <p>
- *  服务实现类
- * </p>
- *
- * @author Seyason
- * @since 2024-02-28
- */
-@Service
-public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
-
-    @Resource
-    private OrderMapper orderMapper;
-    @Resource
-    private HttpServletRequest request;
-    @Resource
-    private UserMapper userMapper;
-    @Resource
-    private SysFunctionService sysFunctionService;
-    @Resource
-    private DepartmentMapper departmentMapper;
-    @Resource
-    private DepartmentOtherManagerMapper departmentOtherManagerMapper;
-    @Resource
-    private SysDictMapper sysDictMapper;
-
-    @Override
-    public HttpRespMsg getList(String userId, String orderName,String orderCode, 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()));
-        boolean viewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部订单");
-        boolean viewDept = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门订单");
-        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, user.getCompanyId()));
-        List<SysDict> sysDictOfOrderType = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, user.getCompanyId()).eq(SysDict::getCode, "OrderType"));
-        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        orderLambdaQueryWrapper.eq(Order::getCompanyId,user.getCompanyId());
-        if(isDelete!=null){
-            orderLambdaQueryWrapper.eq(Order::getIsDelete,isDelete);
-        }else {
-            orderLambdaQueryWrapper.eq(Order::getIsDelete,0);
-        }
-        orderLambdaQueryWrapper.eq(Order::getStatus,1);
-        //判断查看全部的权限
-        if(!viewAll){
-            //判断查看负责部门的权限
-            if(!viewDept){
-                //都没有就只能看自己创建的
-                orderLambdaQueryWrapper.eq(Order::getCreatorId,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()));
-                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());
-                orderLambdaQueryWrapper.in(Order::getCreatorId,userIds);
-            }
-        }
-        if(!StringUtils.isEmpty(orderName)){
-            orderLambdaQueryWrapper.like(Order::getOrderName,orderName);
-        }
-        if(!StringUtils.isEmpty(orderCode)){
-            orderLambdaQueryWrapper.like(Order::getOrderCode,orderCode);
-        }
-        if(!StringUtils.isEmpty(productCode)){
-            orderLambdaQueryWrapper.inSql(Order::getId,
-                    "select o.order_id from order_product_detail o left join product p on o.product_id=p.id " +
-                            "where p.company_id="+user.getCompanyId()+" and p.product_code like '%"+productCode+"%'");
-        }
-        if(pageIndex==null||pageSize==null){
-            pageIndex=-1;
-            pageSize=-1;
-        }
-        IPage<Order> orderIPage = orderMapper.selectPage(new Page<>(pageIndex, pageSize), orderLambdaQueryWrapper);
-        List<Order> records = orderIPage.getRecords();
-        records.forEach(r->{
-            Optional<User> item = userList.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
-            if(item.isPresent()){
-                r.setInchargerName(item.get().getName());
-            }
-            Optional<SysDict> type = sysDictOfOrderType.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
-            if(type.isPresent()){
-                r.setTypeName(type.get().getName());
-            }
-        });
-        Map map=new HashMap();
-        map.put("record",records);
-        map.put("total",orderIPage.getTotal());
-        msg.setData(map);
-        return msg;
-    }
-
-    //递归获取子部门
-    public List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
-        List<Integer> list = new ArrayList<>();
-        list.add(departmentId);
-        //搜到子部门进行添加
-        for (Department department : departmentList) {
-            if (departmentId.equals(department.getSuperiorId())) {
-                list.addAll(getBranchDepartment(department.getDepartmentId(), departmentList));
-            }
-        }
-        return list;
-    }
-}

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

@@ -71,6 +71,8 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
     private DepartmentMapper departmentMapper;
     @Resource
     private DepartmentOtherManagerMapper departmentOtherManagerMapper;
+    @Resource
+    private AttachmentCenterMapper attachmentCenterMapper;
 
     @Override
     public HttpRespMsg getList(Integer companyId,String userId, String productName, String productCode, Integer pageIndex, Integer pageSize) {
@@ -79,6 +81,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
         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,0);
         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"));
@@ -128,18 +131,22 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
             pageIndex=-1;
             pageSize=-1;
         }
-        IPage<Product> productIPage = productMapper.selectPage(new Page<>(pageIndex, pageSize), queryWrapper);
+        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.getCreatorId())).findFirst();
+            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.getCreatorId())).findFirst();
+            Optional<SysDict> type = sysDictOfProductType.stream().filter(u -> u.getId().equals(r.getType())).findFirst();
             if(type.isPresent()){
                 r.setTypeName(type.get().getName());
             }
@@ -403,6 +410,49 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
         return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName,dataList,path);
     }
 
+    @Override
+    public HttpRespMsg getDetail(Integer id) {
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        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"));
+        Product product = productMapper.selectById(id);
+        Optional<User> user = userList.stream().filter(u -> u.getId().equals(product.getInchargerId())).findFirst();
+        if(user.isPresent()){
+            product.setInchargerName(user.get().getName());
+        }
+        Optional<User> creator = userList.stream().filter(u -> u.getId().equals(product.getCreatorId())).findFirst();
+        if(creator.isPresent()){
+            product.setCreatorName(creator.get().getName());
+        }
+        Optional<SysDict> unit = sysDictOfProductUnit.stream().filter(u -> u.getId().equals(product.getUnit())).findFirst();
+        if(unit.isPresent()){
+            product.setUnitName(unit.get().getName());
+        }
+        Optional<SysDict> type = sysDictOfProductType.stream().filter(u -> u.getId().equals(product.getType())).findFirst();
+        if(type.isPresent()){
+            product.setTypeName(type.get().getName());
+        }
+        msg.setData(product);
+        return msg;
+    }
+
+    @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());
+        map.put("total",productIPage.getTotal());
+        msg.setData(map);
+        return msg;
+    }
+
     //递归获取子部门
     public List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
         List<Integer> list = new ArrayList<>();
@@ -416,4 +466,14 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
         return list;
     }
 
+    @Override
+    public HttpRespMsg attachmentList(Integer moduleId, String moduleCode) {
+        HttpRespMsg msg=new HttpRespMsg();
+        // 获取 attachment_center 表里所有的数据
+        List<AttachmentCenter> attachmentCenterList = attachmentCenterMapper.selectList(new LambdaQueryWrapper<AttachmentCenter>()
+                .eq(AttachmentCenter::getModuleId, moduleId)
+                .eq(AttachmentCenter::getModuleCode, moduleCode));
+        msg.setData(attachmentCenterList);
+        return msg;
+    }
 }

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

@@ -0,0 +1,374 @@
+package com.management.platform.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.*;
+import com.management.platform.service.*;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.util.ExcelUtil;
+import com.management.platform.util.HttpRespMsg;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-02-28
+ */
+@Service
+public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOrder> implements SalesOrderService {
+
+    @Resource
+    private SalesOrderMapper salesOrderMapper;
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private SysFunctionService sysFunctionService;
+    @Resource
+    private DepartmentMapper departmentMapper;
+    @Resource
+    private DepartmentOtherManagerMapper departmentOtherManagerMapper;
+    @Resource
+    private SysDictMapper sysDictMapper;
+    @Resource
+    private ExcelExportService excelExportService;
+    @Resource
+    private SysFormMapper sysFormMapper;
+    @Resource
+    private WxCorpInfoService wxCorpInfoService;
+    @Value(value = "${upload.path}")
+    private String path;
+
+    @Override
+    public HttpRespMsg getList(String userId, String orderName,String orderCode, 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()));
+        boolean viewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部订单");
+        boolean viewDept = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门订单");
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, user.getCompanyId()));
+        List<SysDict> sysDictOfOrderType = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, user.getCompanyId()).eq(SysDict::getCode, "OrderType"));
+        LambdaQueryWrapper<SalesOrder> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        orderLambdaQueryWrapper.eq(SalesOrder::getCompanyId,user.getCompanyId());
+        if(isDelete!=null){
+            orderLambdaQueryWrapper.eq(SalesOrder::getIsDelete,isDelete);
+        }else {
+            orderLambdaQueryWrapper.eq(SalesOrder::getIsDelete,0);
+        }
+        orderLambdaQueryWrapper.eq(SalesOrder::getStatus,1);
+        //判断查看全部的权限
+        if(!viewAll){
+            //判断查看负责部门的权限
+            if(!viewDept){
+                //都没有就只能看自己创建的
+                orderLambdaQueryWrapper.eq(SalesOrder::getCreatorId,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()));
+                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());
+                orderLambdaQueryWrapper.in(SalesOrder::getCreatorId,userIds);
+            }
+        }
+        if(!StringUtils.isEmpty(orderName)){
+            orderLambdaQueryWrapper.like(SalesOrder::getOrderName,orderName);
+        }
+        if(!StringUtils.isEmpty(orderCode)){
+            orderLambdaQueryWrapper.like(SalesOrder::getOrderCode,orderCode);
+        }
+        if(!StringUtils.isEmpty(productCode)){
+            orderLambdaQueryWrapper.inSql(SalesOrder::getId,
+                    "select o.order_id from order_product_detail o left join product p on o.product_id=p.id " +
+                            "where p.company_id="+user.getCompanyId()+" and p.product_code like '%"+productCode+"%'");
+        }
+        if(pageIndex==null||pageSize==null){
+            pageIndex=-1;
+            pageSize=-1;
+        }
+        IPage<SalesOrder> orderIPage = salesOrderMapper.selectPage(new Page<>(pageIndex, pageSize), orderLambdaQueryWrapper);
+        List<SalesOrder> records = orderIPage.getRecords();
+        records.forEach(r->{
+            Optional<User> item = userList.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
+            if(item.isPresent()){
+                r.setInchargerName(item.get().getName());
+            }
+            Optional<SysDict> type = sysDictOfOrderType.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
+            if(type.isPresent()){
+                r.setTypeName(type.get().getName());
+            }
+        });
+        Map map=new HashMap();
+        map.put("record",records);
+        map.put("total",orderIPage.getTotal());
+        msg.setData(map);
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg importData(MultipartFile multipartFile) {
+        HttpRespMsg msg=new HttpRespMsg();
+        String fileName = multipartFile.getOriginalFilename();
+        File file = new File(fileName == null ? "file" : fileName);
+        User user = userMapper.selectById(request.getHeader("token"));
+        Integer companyId = user.getCompanyId();
+        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
+        List<SalesOrder> orderList = salesOrderMapper.selectList(new LambdaQueryWrapper<SalesOrder>().eq(SalesOrder::getCompanyId, companyId));
+        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"));
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        try {
+            inputStream = multipartFile.getInputStream();
+            outputStream = new FileOutputStream(file);
+            byte[] buffer = new byte[4096];
+            int temp = 0;
+            while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
+                outputStream.write(buffer, 0, temp);
+            }
+            inputStream.close();
+            outputStream.close();
+            //解析表格
+            HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(file));
+            //我们只需要第一个sheet
+            HSSFSheet sheet = workbook.getSheetAt(0);
+            //由于第一行需要指明列对应的标题
+            int rowNum = sheet.getLastRowNum();
+            //获取当前表单模板 校验规则
+            SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCode, "Product").eq(SysForm::getCompanyId, companyId).eq(SysForm::getIsCurrent, 1));
+            if(sysForm==null){
+                msg.setError("当前模块未配置自定义模板,需先完成配置");
+                return msg;
+            }
+            String config = sysForm.getConfig();
+            JSONObject configOb = JSON.parseObject(config);
+            JSONArray configObJSONArray = configOb.getJSONArray("list");
+            List<SalesOrder>  importOrderList=new ArrayList<>();
+            List<String> userNameList=new ArrayList<>();
+            HttpRespMsg respMsg=new HttpRespMsg();
+            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+                HSSFRow row = sheet.getRow(rowIndex);
+                if (row == null) {
+                    continue;
+                }
+                //跳过空行
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
+                //获取到当前行的列数据
+                int cellNum = row.getLastCellNum();
+                for (int i = 0; i < cellNum; i++) {
+                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    String modelName = item.getString("model");
+                    HSSFCell cell = row.getCell(i);
+                    if(cell!=null){
+                        switch (item.getString("type")){
+                            case "time":cell.setCellType(CellType.NUMERIC);
+                                break;
+                            default:cell.setCellType(CellType.STRING);
+                        }
+                    }
+                    if(modelName.equals("inchargerId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            userNameList.add(cell.getStringCellValue());
+                        }
+                    }
+
+                }
+            }
+            System.out.println("参与搜素的人员列表"+userNameList + userNameList.size());
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1&&userNameList.size()>0){
+                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList,null);
+                if(respMsg.code.equals("0")){
+                    msg.setError("姓名为["+String.valueOf(respMsg.data)+"]的人员存在重复,请使用工号!");
+                    return msg;
+                }
+            }
+            List<User> targetUserList= (List<User>) respMsg.data;
+            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+                HSSFRow row = sheet.getRow(rowIndex);
+                if (row == null) {
+                    continue;
+                }
+                //跳过空行
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
+                //获取到当前行的列数据
+                int cellNum = row.getLastCellNum();
+                SalesOrder order=new SalesOrder();
+                order.setCompanyId(companyId);
+                order.setCreatorId(user.getId());
+                for (int i = 0; i < cellNum; i++) {
+                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    String modelName = item.getString("model");
+                    String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
+                    String getter="get"+className;
+                    String setter="set"+className;
+                    HSSFCell cell = row.getCell(i);
+                    if(cell!=null){
+                        switch (item.getString("type")){
+                            case "time":cell.setCellType(CellType.NUMERIC);
+                                break;
+                            default:cell.setCellType(CellType.STRING);
+                        }
+                    }
+//                    Class<?> productClass = Class.forName("com.management.platform.entity.Product");
+                    Class<Product> productClass = Product.class;
+                    Method method = productClass.getMethod(setter, String.class);
+                    //校验当前列是否为必填
+                    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")+"值不能为空值");
+                            return msg;
+                        }
+                    }
+                    if(modelName.equals("orderCode")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            //系统中同公司已存在的产品编码 更新
+                            Optional<SalesOrder> first = orderList.stream().filter(p ->p.getOrderCode()!=null&& p.getOrderCode().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                order.setId(first.get().getId());
+                            }
+                        }
+                    }
+                    if(modelName.equals("inchargerId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            String userName = cell.getStringCellValue();
+                            Optional<User> first;
+                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                                Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(userName)).findFirst();
+                                first= userList.stream().filter(u ->(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))||(optional.isPresent()&&u.getCorpwxUserid()!=null&&u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
+                            }else {
+                                first= userList.stream().filter(u -> u.getName().equals(userName)||(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))).findFirst();
+                            }
+                            if (first.isPresent()) {
+                                order.setInchargerId(first.get().getId());
+                            } else {
+                                throw new Exception("["+userName+"]在系统中不存在");
+                            }
+                        }
+                    }
+                    if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                        method.invoke(order,cell.getStringCellValue());
+                    }
+                }
+                importOrderList.add(order);
+            }
+            if(importOrderList.size()>0){
+                if(!saveOrUpdateBatch(importOrderList)){
+                    msg.setError("验证失败");
+                    return msg;
+                }
+            }
+        } catch (IOException | NoSuchMethodException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        } catch (InvocationTargetException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg exportData(String userId, String orderName, String orderCode, String productCode) throws Exception {
+        User user = userMapper.selectById(request.getHeader("token"));
+        SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCompanyId, user.getCompanyId()).eq(SysForm::getCode, "Product").eq(SysForm::getIsCurrent, 1));
+        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
+        String config = sysForm.getConfig();
+        JSONObject configOb = JSON.parseObject(config);
+        JSONArray configObJSONArray = configOb.getJSONArray("list");
+        List<List<String>> dataList=new ArrayList<>();
+        List<String> titleList=new ArrayList<>();
+        for (int i = 0; i < configObJSONArray.size(); i++) {
+            JSONObject item = configObJSONArray.getJSONObject(i);
+            titleList.add(item.getString("label"));
+        }
+        dataList.add(titleList);
+        HttpRespMsg respMsg = getList( userId, orderName,orderCode, productCode, null, null,0);
+        Map<String, Object> msgData = (Map<String, Object>) respMsg.getData();
+        List<Product> productList = (List<Product>) msgData.get("record");
+        for (Product product : productList) {
+            List<String> item=new ArrayList<>();
+            for (int i = 0; i < configObJSONArray.size(); i++) {
+                JSONObject target = configObJSONArray.getJSONObject(i);
+                String model = target.getString("model");
+                String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
+                Class<? extends Product> aClass = product.getClass();
+                String value = String.valueOf(aClass.getMethod("get" + targetName).invoke(product)==null?"":aClass.getMethod("get" + targetName).invoke(product));
+                if(model.equals("inchargerId")){
+                    if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                        value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(product))+"$";
+                    }else {
+                        value = String.valueOf(aClass.getMethod("getInchargerName").invoke(product));
+                    }
+                }
+                item.add(value);
+            }
+            dataList.add(item);
+        }
+        String fileName="销售表导出_"+ System.currentTimeMillis();
+        return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName,dataList,path);
+    }
+
+    //递归获取子部门
+    public List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
+        List<Integer> list = new ArrayList<>();
+        list.add(departmentId);
+        //搜到子部门进行添加
+        for (Department department : departmentList) {
+            if (departmentId.equals(department.getSuperiorId())) {
+                list.addAll(getBranchDepartment(department.getDepartmentId(), departmentList));
+            }
+        }
+        return list;
+    }
+}

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

@@ -10,19 +10,13 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.entity.*;
 import com.management.platform.entity.dto.TaskDto;
 import com.management.platform.entity.vo.TasKVo;
-import com.management.platform.entity.vo.TasKVo;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
-import com.management.platform.util.MessageUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.*;
 import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -35,14 +29,10 @@ 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.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * <p>
@@ -93,7 +83,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
     private BusinessOpportunityMapper businessOpportunityMapper;
 
     @Resource
-    private OrderMapper orderMapper;
+    private SalesOrderMapper salesOrderMapper;
 
     @Resource
     private ClueMapper clueMapper;
@@ -328,7 +318,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
             List<Custom> customList=customMapper.selectList(new LambdaQueryWrapper<Custom>().eq(Custom::getCompanyId, user.getCompanyId()).eq(Custom::getIsDelete,0));
             List<BusinessOpportunity> opportunityList = businessOpportunityMapper.selectList(new LambdaQueryWrapper<BusinessOpportunity>()
                     .eq(BusinessOpportunity::getCompanyId, user.getCompanyId()).eq(BusinessOpportunity::getIsDelete, 0));
-            List<Order> orderList = orderMapper.getList(user);
+            List<SalesOrder> orderList = salesOrderMapper.getList(user);
              List<Clue> clueList = clueMapper.selectList(new LambdaQueryWrapper<Clue>().eq(Clue::getCompanyId, user.getCompanyId()).eq(Clue::getIsDelete, 0).orderByDesc(Clue::getCreateTime));
             for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 HSSFRow row = sheet.getRow(rowIndex);
@@ -594,11 +584,11 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                     if (modelName.equals("orderId")){
                         if(cell!=null&&!StringUtils.isEmpty(cell.getStringCellValue())){
                             String orderName = cell.getStringCellValue();
-                            List<Order> collect = orderList.stream().filter(order -> orderName.equals(order.getOrderName())).collect(Collectors.toList());
+                            List<SalesOrder> collect = orderList.stream().filter(order -> orderName.equals(order.getOrderName())).collect(Collectors.toList());
                             if (collect.size()>1){
                                 throw new Exception("["+orderName+"]对应的销售订单存在多个");
                             }else if (collect.size()==1) {
-                                Order order=collect.get(0);
+                                SalesOrder order=collect.get(0);
                                 if (task.getContactsId()!=null){
                                     if (!order.getContactsId().equals(task.getContactsId())){
                                         throw new Exception("["+orderName+"]对应的销售订单没有对应填写的联系人");

+ 26 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/AttachmentCenterMapper.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.AttachmentCenterMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.AttachmentCenter">
+        <id column="id" property="id" />
+        <result column="attachment_name" property="attachmentName" />
+        <result column="server_name" property="serverName" />
+        <result column="url" property="url" />
+        <result column="creator_id" property="creatorId" />
+        <result column="creator_name" property="creatorName" />
+        <result column="indate" property="indate" />
+        <result column="module_id" property="moduleId" />
+        <result column="module_code" property="moduleCode" />
+        <result column="size" property="size" />
+        <result column="attachment_type" property="attachmentType" />
+        <result column="attachment_suffix" property="attachmentSuffix" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, attachment_name, server_name, url, creator_id, creator_name, indate, module_id, module_code, size, attachment_type, attachment_suffix
+    </sql>
+
+</mapper>

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/AuditLogCenterMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.AuditLogCenterMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.AuditLogCenter">
+        <id column="id" property="id" />
+        <result column="module_id" property="moduleId" />
+        <result column="module_code" property="moduleCode" />
+        <result column="audit_time" property="auditTime" />
+        <result column="auditor_id" property="auditorId" />
+        <result column="auditor_name" property="auditorName" />
+        <result column="auditor_content" property="auditorContent" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, module_id, module_code, audit_time, auditor_id, auditor_name, auditor_content
+    </sql>
+
+</mapper>

+ 2 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessItemProductMapper.xml

@@ -25,11 +25,11 @@
                p.price price,
                (select `name` from sys_dict where id = p.unit and code = 'ProductUnit') unit,
                (select `name` from sys_dict where id = p.type and code = 'ProductType') productType,
-               p.inventory inventory,
+               p.inventory inventory
         from business_item_product i
                  left join product p on i.product_id = p.id
 --         left join sys_dict d on
-        where business_id = #{id}
+        where i.business_id = #{id}
     </select>
 
 </mapper>

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

@@ -28,7 +28,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, name, contacts_id, customer_id, product_id, amount_of_money, expected_transaction_date, stage, create_time, edit_time, creator_id, incharger_id, remark, is_delete, plate1, plate2, plate3, plate4, plate5
+        id, company_id, name, contacts_id, customer_id, product_id, amount_of_money, expected_transaction_date, stage_id, create_time, edit_time, creator_id, incharger_id, remark, is_delete, plate1, plate2, plate3, plate4, plate5
     </sql>
     <select id="selectAllList" resultType="com.management.platform.entity.BusinessOpportunity">
         select
@@ -230,7 +230,17 @@
             and id in (select business_id from business_product where product_id = #{productId})
         </if>
     </select>
-
+    <select id="selectByIdToInfo" resultType="com.management.platform.entity.BusinessOpportunity">
+        SELECT *,
+               (select `name` from stage where id = stage_id)          stageValue,
+               (select custom_name from custom where id = customer_id) customerName,
+               (select `name` from contacts where id = contacts_id)    contactsName,
+               (select `name` from `user` where id = contacts_id)      inchargerName,
+               (select `name` from `user` where id = creator_id)       creatorName,
+               (SELECT sum(total) from business_product WHERE business_id = id)
+        from business_opportunity
+        where id = #{id}
+    </select>
 
 
 </mapper>

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

@@ -22,11 +22,12 @@
         <result column="plate4" property="plate4" />
         <result column="plate5" property="plate5" />
         <result column="descs" property="descs" />
+        <result column="is_delete" property="isDelete" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, product_name, product_code, type, unit, price, inventory, status, incharger_id, create_time, creator_id, plate1, plate2, plate3, plate4, plate5, descs
+        id, company_id, product_name, product_code, type, unit, price, inventory, status, incharger_id, create_time, creator_id, plate1, plate2, plate3, plate4, plate5, descs, is_delete
     </sql>
 
 </mapper>

+ 2 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/OrderMapper.xml

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.management.platform.mapper.OrderMapper">
+<mapper namespace="com.management.platform.mapper.SalesOrderMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.management.platform.entity.Order">
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.SalesOrder">
         <id column="id" property="id" />
         <result column="company_id" property="companyId" />
         <result column="order_name" property="orderName" />

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/pom.xml

@@ -108,6 +108,11 @@
             <artifactId>dingtalk</artifactId>
             <version>1.1.50</version>
         </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dingtalk</artifactId>
+            <version>2.1.14</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>

+ 151 - 118
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FeishuInfoController.java

@@ -11,10 +11,7 @@ import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.UserVO;
 import com.management.platform.mapper.*;
-import com.management.platform.service.DepartmentOtherManagerService;
-import com.management.platform.service.FeishuInfoService;
-import com.management.platform.service.SysRoleService;
-import com.management.platform.service.UserService;
+import com.management.platform.service.*;
 import com.management.platform.service.impl.FeishuInfoServiceImpl;
 import com.management.platform.util.*;
 import com.taobao.api.ApiException;
@@ -22,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.*;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
@@ -67,8 +65,12 @@ public class FeishuInfoController {
     @Resource
     private DepartmentFeishuMapper departmentFeishuMapper;
     @Resource
+    private DepartmentFeishuService departmentFeishuService;
+    @Resource
     private DepartmentMapper departmentMapper;
     @Resource
+    private DepartmentService departmentService;
+    @Resource
     private SysRoleMapper sysRoleMapper;
     @Resource
     private UserService userService;
@@ -644,6 +646,7 @@ public class FeishuInfoController {
         if(feishuInfoList.size()>0){
             FeishuInfo feishuInfo = feishuInfoList.get(0);
             List<User> allUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", feishuInfo.getCompanyId()));
+            List<Department> allDepartmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, feishuInfo.getCompanyId()));
             SysRole role = sysRoleMapper.selectOne(new QueryWrapper<SysRole>().eq("company_id",feishuInfo.getCompanyId()).eq("rolename","普通员工"));
             //通讯录权限范围变更
             //todo:新增的
@@ -655,9 +658,11 @@ public class FeishuInfoController {
                 allNeedTodo.addAll(departmentArray);
                 for (int i = 0; i < departmentArray.size(); i++) {
                     JSONObject ob = departmentArray.getJSONObject(i);
-                    JSONArray jsonArray = getSubDepartmentList(feishuInfo, ob.getString("open_department_id"));
-                    if(jsonArray!=null&&jsonArray.size()>0){
-                        allNeedTodo.addAll(jsonArray);
+                    if(ob.getString("open_department_id")!=null){
+                        JSONArray jsonArray = getSubDepartmentList(feishuInfo, ob.getString("open_department_id"));
+                        if(jsonArray!=null&&jsonArray.size()>0){
+                            allNeedTodo.addAll(jsonArray);
+                        }
                     }
                 }
                 List<Department> departmentList=new ArrayList<>();
@@ -670,8 +675,7 @@ public class FeishuInfoController {
                     String openDepartmentId = String.valueOf(ob.getString("open_department_id"));
                     String departmentParentId =String.valueOf(ob.getString("parent_department_id"));
                     JSONArray leaders = ob.getJSONArray("leaders");
-                    Integer cut = departmentFeishuMapper.selectCount(new QueryWrapper<DepartmentFeishu>().eq("corpid",feishuInfo.getCorpid()).eq("feishu_deptid",departmentId));
-                    if(cut==0&&!departmentId.equals("0")){
+                    if(!departmentId.equals("0")){
                         System.out.println("join===========");
                         DepartmentFeishu departmentFeishu=new DepartmentFeishu();
                         departmentFeishu.setCorpid(feishuInfo.getCorpid())
@@ -683,7 +687,11 @@ public class FeishuInfoController {
                         department.setCompanyId(feishuInfo.getCompanyId());
                         department.setDepartmentName(departmentName);
                         department.setFeishuDeptid(openDepartmentId);
-                        departmentMapper.insert(department);
+                        Optional<Department> optional = allDepartmentList.stream().filter(a -> a.getFeishuDeptid().equals(openDepartmentId)).findFirst();
+                        if(optional.isPresent()){
+                            department.setDepartmentId(optional.get().getDepartmentId());
+                        }
+                        departmentService.saveOrUpdate(department);
                         List<DepartmentOtherManager> odList=new ArrayList<>();
                         if(leaders!=null&&leaders.size()>0){
                             //todo:处理主要负责人
@@ -741,65 +749,70 @@ public class FeishuInfoController {
                         JSONObject userJson = userInfoWithDepartment.getJSONObject(m);
                         String curUserid = userJson.getString("user_id");
                         String openUserid = userJson.getString("open_id");
-                        if(!userJson.getJSONObject("status").getBoolean("is_activated")){
-                            continue;
-                        }
                         List<String> departments = (List<String>) userJson.get("department_ids");
                         System.out.println("user info======:"+userJson.toString());
-                        boolean b = allUserList.stream().anyMatch(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(userJson.getString("open_id")));
-                        if(!b){
-                            //不存在的人员, 进行插入
-                            User user = new User();
-                            //在当前部门下的员工
+                        Optional<User> optional = allUserList.stream().filter(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(userJson.getString("open_id"))).findFirst();
+                        //不存在的人员, 进行插入
+                        User user = new User();
+                        //在当前部门下的员工
+                        if(optional.isPresent()){
+                            user.setId(optional.get().getId());
+                        }else {
                             user.setId(SnowFlake.nextId()+"")
-                                    .setRoleId(role.getId())//默认普通员工
-                                    .setRoleName(role.getRolename())
-                                    .setCompanyId(feishuInfo.getCompanyId())
-                                    .setName(userJson.getString("name"))
-                                    .setFeishuUserid(openUserid)
-                                    .setColor(ColorUtil.randomColor())
-                                    .setJobNumber(curUserid)
-                                    .setPassword(MD5Util.getPassword("000000"))
-                                    .setFeishuDeptid(departmentFeishu.getFeishuDeptid());
-                            String max = departments.get(0);
-                            Optional<DepartmentFeishu> dpFs = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(max)).findFirst();
-                            if(dpFs.isPresent()){
-                                Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(dpFs.get().getSysDeptid())).findFirst();
-                                if(dp.isPresent()){
-                                    user.setDepartmentName(dp.get().getDepartmentName());
-                                    user.setDepartmentId(dp.get().getDepartmentId());
-                                    user.setDepartmentCascade(convertDepartmentIdToCascade(dp.get().getDepartmentId(),departmentList));
-                                }
-                            }
-                            boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
-                            if(!c){
-                                newUserList.add(user);
+                                .setRoleId(role.getId())//默认普通员工
+                                .setRoleName(role.getRolename());
+                        }
+                        user.setCompanyId(feishuInfo.getCompanyId())
+                                .setName(userJson.getString("name"))
+                                .setFeishuUserid(openUserid)
+                                .setColor(ColorUtil.randomColor())
+                                .setJobNumber(curUserid)
+                                .setPassword(MD5Util.getPassword("000000"))
+                                .setFeishuDeptid(departmentFeishu.getFeishuDeptid())
+                                .setIsActive(userJson.getJSONObject("status").getBoolean("is_activated")?1:0);
+                        String max = departments.get(0);
+                        Optional<DepartmentFeishu> dpFs = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(max)).findFirst();
+                        if(dpFs.isPresent()){
+                            Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(dpFs.get().getSysDeptid())).findFirst();
+                            if(dp.isPresent()){
+                                user.setDepartmentName(dp.get().getDepartmentName());
+                                user.setDepartmentId(dp.get().getDepartmentId());
+                                user.setDepartmentCascade(convertDepartmentIdToCascade(dp.get().getDepartmentId(),departmentList));
                             }
                         }
+                        boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
+                        if(!c){
+                            newUserList.add(user);
+                        }
                     }
                 }
                 //todo:处理人员
                 JSONArray userArrays = addedOb.getJSONArray("users");
                 if(userArrays!=null&&userArrays.size()>0){
                     for (int i = 0; i < userArrays.size(); i++) {
-                        JSONObject userOb = userArrays.getJSONObject(i);
-                        boolean b = allUserList.stream().anyMatch(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(userOb.getString("open_id")));
-                        if(!b){
-                            //不存在的人员, 进行插入
-                            User user = new User();
-                            user.setId(SnowFlake.nextId()+"")
-                                    .setRoleId(role.getId())//默认普通员工
-                                    .setRoleName(role.getRolename())
-                                    .setCompanyId(feishuInfo.getCompanyId())
-                                    .setName(userOb.getString("name"))
-                                    .setFeishuUserid(userOb.getString("open_id"))
-                                    .setColor(ColorUtil.randomColor())
-                                    .setJobNumber(userOb.getString("user_id"))
-                                    .setPassword(MD5Util.getPassword("000000"));
-                            boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
-                            if(!c){
-                                newUserList.add(user);
-                            }
+                        String uid = userArrays.getString(i);
+                        Optional<User> optional = allUserList.stream().filter(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(uid)).findFirst();
+                        //不存在的人员, 进行插入
+                        User user = new User();
+                        //在当前部门下的员工
+                        if(optional.isPresent()){
+                            user.setId(optional.get().getId());
+                        }else {
+                            user.setId(SnowFlake.nextId()+"");
+                        }
+                        JSONObject userOb = feishuInfoService.getUserInfo(feishuInfo, uid);
+                        user.setRoleId(role.getId())
+                                .setRoleId(role.getId())//默认普通员工
+                                .setRoleName(role.getRolename())
+                                .setCompanyId(feishuInfo.getCompanyId())
+                                .setName(userOb.getString("name"))
+                                .setFeishuUserid(userOb.getString("open_id"))
+                                .setColor(ColorUtil.randomColor())
+                                .setJobNumber(userOb.getString("user_id"))
+                                .setPassword(MD5Util.getPassword("000000"));
+                        boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
+                        if(!c){
+                            newUserList.add(user);
                         }
                     }
                 }
@@ -815,10 +828,12 @@ public class FeishuInfoController {
     }
 
     @RequestMapping("/getFeishuMembsFromPlatform")
+    @Transactional(rollbackFor = Exception.class)
     public HttpRespMsg getFeishuMembsFromPlatform(HttpServletRequest request){
         HttpRespMsg msg=new HttpRespMsg();
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         FeishuInfo feishuInfo = feishuInfoMapper.selectOne(new LambdaQueryWrapper<FeishuInfo>().eq(FeishuInfo::getCompanyId, companyId));
+        List<Department> allDepartmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
         List<User> allUserList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
         String corpId = feishuInfo.getCorpid();
         if(feishuInfo==null){
@@ -845,13 +860,16 @@ public class FeishuInfoController {
         JSONArray departmentArray = departmentInfoArrays;
         JSONArray allNeedTodo=new JSONArray();
         allNeedTodo.addAll(departmentArray);
-        for (int i = 0; i < departmentArray.size(); i++) {
-            JSONObject ob = departmentArray.getJSONObject(i);
-            JSONArray jsonArray = getSubDepartmentList(feishuInfo, ob.getString("open_department_id"));
-            if(jsonArray!=null&&jsonArray.size()>0){
-                allNeedTodo.addAll(jsonArray);
-            }
-        }
+//        for (int i = 0; i < departmentArray.size(); i++) {
+//            JSONObject ob = departmentArray.getJSONObject(i);
+//            System.out.println("ob对象数据"+ob.toJSONString());
+//            if(ob.getString("open_department_id")!=null){
+//                JSONArray jsonArray = getSubDepartmentList(feishuInfo, ob.getString("open_department_id"));
+//                if(jsonArray!=null&&jsonArray.size()>0){
+//                    allNeedTodo.addAll(jsonArray);
+//                }
+//            }
+//        }
         List<Department> departmentList=new ArrayList<>();
         List<DepartmentFeishu> departmentFeishuList=new ArrayList<>();
         for (int j = 0; j < allNeedTodo.size(); j++) {
@@ -862,8 +880,7 @@ public class FeishuInfoController {
             String openDepartmentId = String.valueOf(ob.getString("open_department_id"));
             String departmentParentId =String.valueOf(ob.getString("parent_department_id"));
             JSONArray leaders = ob.getJSONArray("leaders");
-            Integer cut = departmentFeishuMapper.selectCount(new QueryWrapper<DepartmentFeishu>().eq("corpid",feishuInfo.getCorpid()).eq("feishu_deptid",departmentId));
-            if(cut==0&&!departmentId.equals("0")){
+            if(!departmentId.equals("0")){
                 System.out.println("join===========");
                 DepartmentFeishu departmentFeishu=new DepartmentFeishu();
                 departmentFeishu.setCorpid(feishuInfo.getCorpid())
@@ -875,7 +892,11 @@ public class FeishuInfoController {
                 department.setCompanyId(feishuInfo.getCompanyId());
                 department.setDepartmentName(departmentName);
                 department.setFeishuDeptid(openDepartmentId);
-                departmentMapper.insert(department);
+                Optional<Department> optional = allDepartmentList.stream().filter(a ->a.getFeishuDeptid()!=null&& a.getFeishuDeptid().equals(openDepartmentId)).findFirst();
+                if(optional.isPresent()){
+                    department.setDepartmentId(optional.get().getDepartmentId());
+                }
+                departmentService.saveOrUpdate(department);
                 List<DepartmentOtherManager> odList=new ArrayList<>();
                 if(leaders!=null&&leaders.size()>0){
                     //todo:处理主要负责人
@@ -908,12 +929,17 @@ public class FeishuInfoController {
                 departmentMapper.updateById(department);
                 departmentList.add(department);
                 departmentFeishu.setSysDeptid(department.getDepartmentId());
-                departmentFeishuMapper.insert(departmentFeishu);
+                DepartmentFeishu feishu = departmentFeishuMapper.selectOne(new LambdaQueryWrapper<DepartmentFeishu>().eq(DepartmentFeishu::getFeishuOpenDeptid, departmentFeishu.getFeishuOpenDeptid()));
+                if(feishu!=null){
+                    departmentFeishu.setId(feishu.getId());
+                }
+                departmentFeishuService.saveOrUpdate(departmentFeishu);
                 departmentFeishuList.add(departmentFeishu);
                 departmentOtherManagerService.saveBatch(odList);
             }
         }
         List<User> newUserList=new ArrayList<>();
+        System.out.println("departmentFeishuList========"+departmentFeishuList.toString());
         for (DepartmentFeishu departmentFeishu : departmentFeishuList) {
             Optional<Department> first = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(departmentFeishu.getSysDeptid())).findFirst();
             //获取到当前部门的上级部门
@@ -929,45 +955,48 @@ public class FeishuInfoController {
             }
             //处理部门下的人员
             JSONArray userInfoWithDepartment=feishuInfoService.getUserInfoWithDepartment(feishuInfo,departmentFeishu.getFeishuOpenDeptid(),null);
+            System.out.println("userInfoWithDepartment=========="+userInfoWithDepartment.toJSONString());
             for (int m=0;m<userInfoWithDepartment.size(); m++) {
                 JSONObject userJson = userInfoWithDepartment.getJSONObject(m);
                 String curUserid = userJson.getString("user_id");
                 String openUserid = userJson.getString("open_id");
-                if(!userJson.getJSONObject("status").getBoolean("is_activated")){
-                    continue;
-                }
                 List<String> departments = (List<String>) userJson.get("department_ids");
                 System.out.println("user info======:"+userJson.toString());
-                boolean b = allUserList.stream().anyMatch(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(userJson.getString("open_id")));
-                if(!b){
-                    //不存在的人员, 进行插入
-                    User user = new User();
-                    //在当前部门下的员工
+                Optional<User> optional = allUserList.stream().filter(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(userJson.getString("open_id"))).findFirst();
+                //不存在的人员, 进行插入
+                User user = new User();
+                //在当前部门下的员工
+                if(optional.isPresent()){
+                    user.setId(optional.get().getId());
+                }else {
                     user.setId(SnowFlake.nextId()+"")
-                            .setRoleId(role.getId())//默认普通员工
-                            .setRoleName(role.getRolename())
-                            .setCompanyId(feishuInfo.getCompanyId())
-                            .setName(userJson.getString("name"))
-                            .setFeishuUserid(openUserid)
-                            .setColor(ColorUtil.randomColor())
-                            .setJobNumber(curUserid)
-                            .setPassword(MD5Util.getPassword("000000"))
-                            .setFeishuDeptid(departmentFeishu.getFeishuDeptid());
-                    String max = departments.get(0);
-                    Optional<DepartmentFeishu> dpFs = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(max)).findFirst();
-                    if(dpFs.isPresent()){
-                        Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(dpFs.get().getSysDeptid())).findFirst();
-                        if(dp.isPresent()){
-                            user.setDepartmentName(dp.get().getDepartmentName());
-                            user.setDepartmentId(dp.get().getDepartmentId());
-                            user.setDepartmentCascade(convertDepartmentIdToCascade(dp.get().getDepartmentId(),departmentList));
-                        }
-                    }
-                    boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
-                    if(!c){
-                        newUserList.add(user);
+                        .setRoleId(role.getId())//默认普通员工
+                        .setRoleName(role.getRolename());
+                }
+                user.setCompanyId(feishuInfo.getCompanyId())
+                        .setName(userJson.getString("name"))
+                        .setFeishuUserid(openUserid)
+                        .setColor(ColorUtil.randomColor())
+                        .setJobNumber(curUserid)
+                        .setPassword(MD5Util.getPassword("000000"))
+                        .setFeishuDeptid(departmentFeishu.getFeishuDeptid())
+                        .setIsActive(userJson.getJSONObject("status").getBoolean("is_activated")?1:0);
+                String max = departments.get(0);
+                System.out.println("maxDept====="+max);
+                Optional<DepartmentFeishu> dpFs = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(max)).findFirst();
+                if(dpFs.isPresent()){
+                    Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(dpFs.get().getSysDeptid())).findFirst();
+                    if(dp.isPresent()){
+                        System.out.println("Set Dept");
+                        user.setDepartmentName(dp.get().getDepartmentName());
+                        user.setDepartmentId(dp.get().getDepartmentId());
+                        user.setDepartmentCascade(convertDepartmentIdToCascade(dp.get().getDepartmentId(),departmentList));
                     }
                 }
+                boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
+                if(!c){
+                    newUserList.add(user);
+                }
             }
         }
         //todo:处理人员
@@ -977,29 +1006,33 @@ public class FeishuInfoController {
         if(userArrays!=null&&userArrays.size()>0){
             for (int i = 0; i < userArrays.size(); i++) {
                 String uid = userArrays.getString(i);
-                boolean b = allUserList.stream().anyMatch(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(uid));
-                if(!b){
-                    //不存在的人员, 进行插入
-                    User user = new User();
-                    JSONObject userOb = feishuInfoService.getUserInfo(feishuInfo, uid);
-                    user.setId(SnowFlake.nextId()+"")
-                            .setRoleId(role.getId())//默认普通员工
-                            .setRoleName(role.getRolename())
-                            .setCompanyId(feishuInfo.getCompanyId())
-                            .setName(userOb.getString("name"))
-                            .setFeishuUserid(userOb.getString("open_id"))
-                            .setColor(ColorUtil.randomColor())
-                            .setJobNumber(userOb.getString("user_id"))
-                            .setPassword(MD5Util.getPassword("000000"));
-                    boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
-                    if(!c){
-                        newUserList.add(user);
-                    }
+                Optional<User> optional = allUserList.stream().filter(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(uid)).findFirst();
+                //不存在的人员, 进行插入
+                User user = new User();
+                //在当前部门下的员工
+                if(optional.isPresent()){
+                    user.setId(optional.get().getId());
+                }else {
+                    user.setId(SnowFlake.nextId()+"");
+                }
+                JSONObject userOb = feishuInfoService.getUserInfo(feishuInfo, uid);
+                user.setRoleId(role.getId())
+                        .setRoleId(role.getId())//默认普通员工
+                        .setRoleName(role.getRolename())
+                        .setCompanyId(feishuInfo.getCompanyId())
+                        .setName(userOb.getString("name"))
+                        .setFeishuUserid(userOb.getString("open_id"))
+                        .setColor(ColorUtil.randomColor())
+                        .setJobNumber(userOb.getString("user_id"))
+                        .setPassword(MD5Util.getPassword("000000"));
+                boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
+                if(!c){
+                    newUserList.add(user);
                 }
             }
         }
         if(newUserList.size()>0){
-            userService.saveBatch(newUserList);
+            userService.saveOrUpdateBatch(newUserList);
         }
         return msg;
     }

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/HolidaySettingController.java

@@ -61,6 +61,10 @@ public class HolidaySettingController {
             return msg;
         }
         holidaySetting.setCompanyId(companyId);
+        if(holidaySetting.getRangeType()==0){
+            holidaySetting.setTargetUsers("");
+            holidaySetting.setTargetDepts("");
+        }
         if(!holidaySettingService.saveOrUpdate(holidaySetting)){
             msg.setError("验证失败");
         }

+ 80 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -30,6 +30,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.DecimalFormat;
@@ -105,6 +106,10 @@ public class ReportController {
     private LeaveSheetService leaveSheetService;
     @Resource
     private EstimateTimeSettingMapper estimateTimeSettingMapper;
+    @Resource
+    private UserFvTimeMapper userFvTimeMapper;
+    @Resource
+    private UserCustomMapper userCustomMapper;
 
     //获取任务相关的日报列表
     @RequestMapping("/getTaskReportList")
@@ -1723,6 +1728,81 @@ public class ReportController {
         return httpRespMsg;
     }
 
+    @RequestMapping("/checkBeiSengCardTime")
+    public HttpRespMsg checkBeiSengCardTime(String userId, String dateWorkingTime) throws Exception {
+        HttpRespMsg msg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        JSONArray array = JSONArray.parseArray(dateWorkingTime);
+        List<UserCustom> userCustomList = userCustomMapper.selectList(new LambdaQueryWrapper<UserCustom>().eq(UserCustom::getCompanyId, user.getCompanyId()));
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, user.getCompanyId()));
+        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        List<LocalDate> dateList = new ArrayList<>();
+        for (int i = 0; i < array.size(); i++) {
+            JSONObject jsonObject = array.getJSONObject(i);
+            LocalDate date = LocalDate.parse(jsonObject.getString("date"), df);
+            dateList.add(date);
+        }
+        Optional<LocalDate> max = dateList.stream().max(LocalDate::compareTo);
+        Optional<LocalDate> min = dateList.stream().min(LocalDate::compareTo);
+        //获取景昱的考勤和加班时长,进行比对,如果有不一致的,返回错误
+        //错误信息格式:有加班工资的情况下,返回 异常:2024-04-18日填报工时(6h)不等于考勤总时长(8h);无加班工资情况下,返回 异常:2024-04-18日填报工时(8h)少于考勤工时(10h)
+        List<UserFvTime> userFvTimeList = userFvTimeMapper.selectList(new LambdaQueryWrapper<UserFvTime>().between(UserFvTime::getWorkDate, df.format(min.get()), df.format(max.get())));
+        StringBuilder warningMsg = new StringBuilder();
+        for (int i = 0; i < array.size(); i++) {
+            JSONObject jsonObject = array.getJSONObject(i);
+            LocalDate date = LocalDate.parse(jsonObject.getString("date"), df);
+            double workingTime = jsonObject.getDouble("workingTime");
+            Optional<UserFvTime> first = userFvTimeList.stream().filter(u -> u.getWorkDate().isEqual(date) && u.getUserId().equals(userId)).findFirst();
+            if(first.isPresent()){
+                if(first.get().getWorkHours()!=null){
+                    Optional<User> optional = userList.stream().filter(u -> u.getId().equals(userId)).findFirst();
+                    User targetUser = optional.get();
+                    List<String> customList = userCustomList.stream().map(UserCustom::getName).collect(Collectors.toList());
+                    if(customList.size()>0&&customList.contains("是否有加班费")){
+                        int index = customList.indexOf("是否有加班费");
+                        targetUser.getPlate1();
+                        String getter="getPlate"+(index+1);
+                        Class<User> aClass = User.class;
+                        Method method = aClass.getMethod(getter);
+                        String invoke = (String) method.invoke(targetUser);
+                        if(StringUtils.isEmpty(invoke)){
+                            msg.setError("人员未设置薪资类型,请联系管理人员");
+                            return msg;
+                        }
+                        if(invoke==null||invoke.equals("有加班费")){
+                            if(!(Double.valueOf(String.valueOf(workingTime)).equals(Double.valueOf(first.get().getWorkHours())))){
+                                if(warningMsg.length()>0){
+                                    warningMsg.append(",");
+                                }
+                                warningMsg.append(df.format(date)+"日填报工时("+workingTime+"h)不等于考勤总时长("+first.get().getWorkHours()+"h)");
+                            }
+                        }else{
+                            if((Double.valueOf(String.valueOf(workingTime))<first.get().getWorkHours())){
+                                if(warningMsg.length()>0){
+                                    warningMsg.append(",");
+                                }
+                                warningMsg.append(df.format(date)+"日填报工时("+workingTime+"h)少于考勤工时("+first.get().getWorkHours()+"h)");
+                            }
+                        }
+                    }
+                }
+            }else {
+                if(warningMsg.length()>0){
+                    warningMsg.append(",");
+                }
+                warningMsg.append(df.format(date)+"未查询到考勤信息");
+            }
+        }
+        String warningMsgStr = warningMsg.toString();
+        if (!StringUtils.isEmpty(warningMsgStr)) {
+            if(warningMsgStr.length()>100){
+                warningMsgStr = warningMsgStr.substring(0, 100)+"...";
+            }
+            msg.setError(warningMsgStr);
+        }
+        return msg;
+    }
+
     private void fillReportHours(Report report, BigDecimal hourCost, Double workingTime, Integer timeType, String startTime, String endTime, SimpleDateFormat sdf, TimeType comTimeType, List<TimeAutoExclude> excludeTimeList) {
         if (report.getMultiWorktime() == 0) {
             //普通工时成本计算

+ 106 - 12
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java

@@ -11,6 +11,7 @@ import com.management.platform.mapper.TimeTypeMapper;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.mapper.UserWithBeisenMapper;
 import com.management.platform.service.UserFvTimeService;
+import com.management.platform.service.UserService;
 import com.management.platform.service.UserWithBeisenService;
 import com.management.platform.util.BeiSenUtils;
 import com.management.platform.util.HttpRespMsg;
@@ -23,6 +24,8 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -59,11 +62,14 @@ public class UserWithBeisenController {
     private UserFvTimeService userFvTimeService;
     @Resource
     private TimeTypeMapper timeTypeMapper;
+    @Resource
+    private UserService userService;
 
     @RequestMapping("/getByTimeWindow")
     public HttpRespMsg getByTimeWindow(String startTime,String stopTime){
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
         BeisenConfig beisenConfig = beisenConfigMapper.selectById(companyId);
         if(beisenConfig==null){
             httpRespMsg.setError("北森基础数据配置未完成,请联系服务商完成配置");
@@ -71,6 +77,8 @@ public class UserWithBeisenController {
         }
         List<UserWithBeisen> allBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, companyId));
         List<UserWithBeisen> userWithBeisenList=new ArrayList<>();
+        //更新电话到工时
+        List<User> needUpdateUsers=new ArrayList<>();
         List<JSONArray> byTimeWindow = BeiSenUtils.getByTimeWindow("",startTime,stopTime,companyId,beisenConfig.getAppKey(),beisenConfig.getAppSecret());
         for (JSONArray array : byTimeWindow) {
             for (int i = 0; i < array.size(); i++) {
@@ -95,6 +103,14 @@ public class UserWithBeisenController {
                     continue;
                 }
                 userWithBeisenList.add(userWithBeisen);
+                Optional<User> user = userList.stream().filter(u ->u.getJobNumber()!=null&&u.getJobNumber().equals(userWithBeisen.getJobNumber())).findFirst();
+                if(user.isPresent()){
+                    User u=new User();
+                    u.setId(user.get().getId());
+                    u.setPhone(userWithBeisen.getMobilePhone());
+                    u.setJobNumber(userWithBeisen.getJobNumber());
+                    needUpdateUsers.add(u);
+                }
             }
         }
         if(userWithBeisenList.size()>0){
@@ -103,6 +119,9 @@ public class UserWithBeisenController {
                 return httpRespMsg;
             }
         }
+        if(needUpdateUsers.size()>0){
+            userService.updateBatchById(needUpdateUsers);
+        }
         return httpRespMsg;
     }
 
@@ -130,6 +149,7 @@ public class UserWithBeisenController {
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
         DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
+        DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         TimeType timeType = timeTypeMapper.selectById(companyId);
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
@@ -144,12 +164,15 @@ public class UserWithBeisenController {
         //todo 获取到指定日期的加班数据
         List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
         JSONArray allOverTimeList=new JSONArray();
+        JSONArray allVacationList=new JSONArray();
         List<UserFvTime> userFvTimeList=new ArrayList<>();
         for (LocalDate localDate : workDaysListInRange) {
             JSONArray statisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
             JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
             allOverTimeList.addAll(overTimeList);
             attendanceStatistics.addAll(statisticList);
+            allVacationList.addAll(vacationList);
         }
         for (LocalDate localDate : workDaysListInRange) {
             Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
@@ -166,27 +189,68 @@ public class UserWithBeisenController {
                 //获取最早上班打卡时间
                 List<LocalTime> minLocalTimeList = timeStream.filter(t -> t.getIntValue("Type") == 1).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
                 Optional<LocalTime> min = minLocalTimeList.stream().min(LocalTime::compareTo);
-                //获取最早上班打卡时间
+                //获取最晚下班时间
                 List<LocalTime> maxLocalTimeList = timeStream1.filter(t -> t.getIntValue("Type") == 9).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
                 Optional<LocalTime> max = maxLocalTimeList.stream().max(LocalTime::compareTo);
-                //获取最晚下班时间
                 if(first.isPresent()){
                     boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
                     //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Double workTime=8.0;
+                    Duration between = Duration.between(min.get(), max.get());
+                    Double workTime;
+                    if(between.toHours()>8){
+                        workTime=8.0;
+                    }else if(between.toHours()<0){
+                        workTime=0.0;
+                    }else {
+                        BigDecimal decimal = new BigDecimal(between.toMinutes());
+                        decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                        workTime=decimal.doubleValue();
+                    }
                     Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
+                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
                     Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
                     if(beisen.isPresent()){
+                        //审核通过以及审批中都算
                         List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-                                && a.getIntValue("ApproveStatus") == 2).collect(Collectors.toList());
+                                && (a.getIntValue("ApproveStatus") == 1||a.getIntValue("ApproveStatus") == 2)
+                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
                         if(overTimeList.size()>0){
-                            double actualOverTimeDuration = overTimeList.stream().mapToDouble(i -> i.getDouble("ActualOverTimeDuration")).sum();
+                            double actualOverTimeDuration = overTimeList.stream().mapToDouble(i -> i.getDouble("OverTimeDuration")).sum();
                             if(workDay){
                                 workTime= workTime+actualOverTimeDuration;
                             }else {
                                 workTime= actualOverTimeDuration;
                             }
                         }
+                        //处理修改
+                        List<JSONObject> vacationList = vacationStream.filter(a ->{
+                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
+                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
+                            boolean b=false;
+                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
+                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
+                                b=true;
+                            }
+                            if(a.getString("StaffId").equals(beisen.get().getUserId())
+                                    && b
+                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
+                                return true;
+                            }
+                            return false;
+                        }).collect(Collectors.toList());
+                        if(vacationList.size()>0){
+                            double vacationDuration = vacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
+                            BigDecimal decimal = new BigDecimal(vacationDuration);
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            //考勤打卡区间大于8小时 但是存在休假数据
+                            if(between.toHours()>8){
+                                if(decimal.doubleValue()>8){
+                                    workTime= workTime-8;
+                                }else {
+                                    workTime= workTime-decimal.doubleValue();
+                                }
+                            }
+                        }
                     }
                     UserFvTime userFvTime=new UserFvTime();
                     userFvTime.setWorkDate(localDate);
@@ -218,6 +282,7 @@ public class UserWithBeisenController {
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
         DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
+        DateTimeFormatter df3=DateTimeFormatter.ofPattern("HH:mm:ss");
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
         TimeType timeType = timeTypeMapper.selectById(companyId);
@@ -228,15 +293,17 @@ public class UserWithBeisenController {
             msg.setError("北森基础数据配置未完成,请联系服务商完成配置");
             return msg;
         }
-        //todo 获取到指定日期的考勤数据
-        //todo 获取到指定日期的加班数据
         Optional<UserWithBeisen> withBeisen = userWithBeisenList.stream().filter(u ->u.getJobNumber()!=null&& u.getJobNumber().equals(user.getJobNumber())).findFirst();
         if(!withBeisen.isPresent()){
             msg.setError("当前员工在北森系统中不存在,请完成录入员工信息");
             return msg;
         }
+        //todo 获取到指定日期的考勤数据
         JSONObject item = BeiSenUtils.getAttendanceStatisticWithUser(createDate,withBeisen.get().getUserId(), beisenConfig.getAppKey(), beisenConfig.getAppSecret());
+        //todo 获取到指定日期的加班数据
         JSONArray allOverTimeList = BeiSenUtils.getOverTimeList(createDate,beisenConfig.getAppKey(),beisenConfig.getAppSecret(),1,100);
+        //todo 获取到指定日期的休假数据
+        JSONArray vacationList = BeiSenUtils.getVacationList(createDate, beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
         //获取当前数据下的人员工号对应到工时管家
         Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(withBeisen.get().getJobNumber())).findFirst();
         System.out.println("考勤数据:"+item.toString());
@@ -247,25 +314,52 @@ public class UserWithBeisenController {
         if(first.isPresent()){
             boolean workDay = WorkDayCalculateUtils.isWorkDay(LocalDate.parse(createDate,df));
             //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-            Double workTime=8.0;
+            Double workTime;
+            Duration between = Duration.between(LocalTime.parse(firstCard, df3), LocalTime.parse(lastCard, df3));
+            if(between.toHours()>8){
+                workTime=8.0;
+            }else if(between.toHours()<0) {
+                workTime=0.0;
+            }else {
+                BigDecimal decimal = new BigDecimal(between.toMinutes());
+                decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                workTime=decimal.doubleValue();
+            }
             Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
+            Stream<JSONObject> vacationStream = vacationList.stream().map(elment -> (JSONObject) elment);
             Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
             if(beisen.isPresent()){
                 List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-                        && a.getIntValue("ApproveStatus") == 2).collect(Collectors.toList());
+                        && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
                 if(overTimeList.size()>0){
-                    double actualOverTimeDuration = overTimeList.stream().mapToDouble(i -> i.getDouble("ActualOverTimeDuration")).sum();
+                    double actualOverTimeDuration = overTimeList.stream().mapToDouble(i -> i.getDouble("OverTimeDuration")).sum();
                     if(workDay){
                         workTime= workTime+actualOverTimeDuration;
                     }else {
                         workTime= actualOverTimeDuration;
                     }
                 }
+                //计算休假
+                List<JSONObject> targetVacation = vacationStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
+                        && (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))).collect(Collectors.toList());
+                if(targetVacation.size()>0){
+                    double vacationDuration = targetVacation.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
+                    BigDecimal decimal = new BigDecimal(vacationDuration);
+                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                    //考勤打卡区间大于8小时 但是存在休假数据
+                    if(between.toHours()>8){
+                        if(decimal.doubleValue()>8){
+                            workTime= workTime-8;
+                        }else {
+                            workTime= workTime-decimal.doubleValue();
+                        }
+                    }
+                }
             }
             UserFvTime userFvTime=new UserFvTime();
             userFvTime.setWorkDate(LocalDate.parse(createDate,df));
-            userFvTime.setStartTime(!StringUtils.isEmpty(firstCard)?firstCard:"08:30");
-            userFvTime.setEndTime(!StringUtils.isEmpty(lastCard)?lastCard:"17:30");
+            userFvTime.setStartTime(!StringUtils.isEmpty(firstCard)?firstCard:"08:30:00");
+            userFvTime.setEndTime(!StringUtils.isEmpty(lastCard)?lastCard:"17:30:00");
             userFvTime.setUserId(first.get().getId());
             userFvTime.setCompanyId(companyId);
             userFvTime.setWorkHours(workTime.floatValue());

+ 7 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/CompanyDingding.java

@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2023-05-26
+ * @since 2024-04-20
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -108,6 +108,12 @@ public class CompanyDingding extends Model<CompanyDingding> {
     @TableField("sync_contact")
     private Integer syncContact;
 
+    /**
+     * 通讯录是否需要转译
+     */
+    @TableField("contact_need_translate")
+    private Integer contactNeedTranslate;
+
 
     @Override
     protected Serializable pkVal() {

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/UserMonthWork.java

@@ -7,6 +7,7 @@ public class UserMonthWork {
     public String userId;
     public String name;
     public String departmentName;
+    public String deptId;
     public String inactiveDate;
     public String corpwxUserId;
     public String corpwxDeptId;

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java

@@ -92,12 +92,12 @@ public interface ReportMapper extends BaseMapper<Report> {
     List<Map<String, Object>> getReportNameByDateAndDept(@Param("date") String date,
                                                          @Param("deptIds") List<Integer> deptIds,
                                                          @Param("userId") String userId,
-                                                         @Param("companyId") Integer companyId, Integer pageStart, Integer pageSize);
+                                                         @Param("companyId") Integer companyId, String viewUserId, Integer pageStart, Integer pageSize);
 
     Integer getReportNameByDateAndDeptCount(@Param("date") String date,
                                                          @Param("deptIds") List<Integer> deptIds,
                                                          @Param("userId") String userId,
-                                                         @Param("companyId") Integer companyId);
+                                                         @Param("companyId") Integer companyId, String viewUserId);
     List<Map<String, Object>> getDetailByStateInMyProfession(@Param("state") Integer state,
                                                @Param("companyId") Integer companyId,
                                                @Param("leaderId") String leaderId);

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java

@@ -52,4 +52,10 @@ public interface DingDingService {
     String inactiveUserNotInAuthRange(String corpid);
 
     HttpRespMsg fixAttendance(Integer companyId);
+
+    String getTranslationMediaId(String fileName,CompanyDingding dingding) throws Exception;
+
+    String syncTranslation(String mediaId,String fileName,String unionId,CompanyDingding dingding) throws Exception;
+
+    String getSyncTranslationResult(String jobId,CompanyDingding dingding) throws Exception;
 }

+ 95 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java

@@ -3,8 +3,11 @@ package com.management.platform.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.aliyun.dingtalkcontact_1_0.Client;
 import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
+import com.aliyun.tea.TeaConverter;
 import com.aliyun.tea.TeaException;
+import com.aliyun.tea.TeaPair;
 import com.aliyun.teaopenapi.models.Config;
 import com.aliyun.teautil.models.RuntimeOptions;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -19,7 +22,9 @@ import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.*;
 import com.taobao.api.ApiException;
+import com.taobao.api.FileItem;
 import com.taobao.api.internal.util.StringUtils;
+import com.taobao.api.internal.util.WebUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
@@ -38,6 +43,13 @@ import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.aliyun.tea.*;
+import com.aliyun.teautil.*;
+import com.aliyun.teautil.models.*;
+import com.aliyun.dingtalkcontact_1_0.*;
+import com.aliyun.dingtalkcontact_1_0.models.*;
+import com.aliyun.teaopenapi.*;
+import com.aliyun.teaopenapi.models.*;
 
 //import com.management.platform.entity.vo.LeaveQuotaNum;
 
@@ -152,6 +164,9 @@ public class DingDingServiceImpl implements DingDingService {
     @Value("${configEnv.isDev}")
     private boolean isDev;//是否是本地开发环境
 
+    @Value("${upload.path}")
+    private String path;//是否是本地开发环境
+
     public static final HashMap<String, Long> syncLog = new HashMap();
 
     @Override
@@ -377,8 +392,6 @@ public class DingDingServiceImpl implements DingDingService {
                     .setExpirationDate(LocalDateTime.now().plusDays(15));
             company.setPackageProject(1);
             company.setPackageExpense(1);
-            company.setPackageCustomer(1);
-            company.setPackageOa(1);
             //设置来源
             company.setRegFrom("钉钉");
             companyMapper.insert(company);
@@ -483,6 +496,7 @@ public class DingDingServiceImpl implements DingDingService {
         dingding.setAgentId(agentId);
         dingding.setAuthUserId(authUserId);
         dingding.setSyncContact(1);
+        dingding.setContactNeedTranslate(1);//上架到钉钉应用市场,通讯录为加密模式,需要转译
 
         if (oldD == null) {
             //第一次,查询对方企业的accessToken
@@ -1148,6 +1162,7 @@ public class DingDingServiceImpl implements DingDingService {
                         num = auditWorkflowTimeSettingMapper.selectCount(new QueryWrapper<AuditWorkflowTimeSetting>().in("audit_dept_id", deptIds));
                     }
                     userVO.setHasAuditDept(num>0);
+                    userVO.setUserNameNeedTranslate(companyDingding.getContactNeedTranslate());
                     userService.setUserRoleMenu(userVO);
                     httpRespMsg.data = userVO;
                 }
@@ -2529,6 +2544,84 @@ public class DingDingServiceImpl implements DingDingService {
         return SUITE_ACCESS_TOKEN;
     }
 
+    //上传文件获取media_id
+    @Override
+    public String getTranslationMediaId(String fileName,CompanyDingding dingding) throws Exception {
+        OapiFileUploadSingleRequest request = new OapiFileUploadSingleRequest();
+        request.setFileSize(45L);
+        request.setAgentId(String.valueOf(dingding.getAgentId()));
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/file/upload/single?"+ WebUtils.buildQuery(request.getTextParams(),"utf-8"));
+        // 必须重新new一个请求
+        String media_id;
+        request = new OapiFileUploadSingleRequest();
+        request.setFile(new FileItem(path+fileName));
+        OapiFileUploadSingleResponse response = client.execute(request,getCorpAccessToken(dingding));
+        System.out.println(response.getBody());
+        JSONObject obj = JSONObject.parseObject(response.getBody());
+        if (obj.getIntValue("errcode") == 0) {
+            media_id = obj.getString("media_id");
+            return media_id;
+        }
+        return null;
+    }
+
+
+    @Override
+    public String syncTranslation(String mediaId, String fileName, String unionId,CompanyDingding dingding) throws Exception {
+        com.aliyun.dingtalkcontact_1_0.Client client = createClient();
+        TranslateFileHeaders translateFileHeaders = new TranslateFileHeaders();
+        translateFileHeaders.xAcsDingtalkAccessToken =getCorpAccessToken(dingding);
+        if(mediaId!=null){
+            java.util.Map<String, String> medias = TeaConverter.buildMap(
+                    new TeaPair(mediaId,fileName)
+            );
+            TranslateFileRequest translateFileRequest = new TranslateFileRequest()
+                    .setMedias(medias)
+                    .setUnionId(unionId);
+            try {
+                TranslateFileResponse translateFileResponse = client.translateFileWithOptions(translateFileRequest, translateFileHeaders, new RuntimeOptions());
+                TranslateFileResponseBody body = translateFileResponse.body;
+                return body.jobId;
+            } catch (TeaException err) {
+                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                    // err 中含有 code 和 message 属性,可帮助开发定位问题
+                }
+            } catch (Exception _err) {
+                TeaException err = new TeaException(_err.getMessage(), _err);
+                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                    // err 中含有 code 和 message 属性,可帮助开发定位问题
+                }
+
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getSyncTranslationResult(String jobId,CompanyDingding dingding) throws Exception {
+        if(jobId!=null){
+            com.aliyun.dingtalkcontact_1_0.Client client = createClient();
+            GetTranslateFileJobResultHeaders getTranslateFileJobResultHeaders = new GetTranslateFileJobResultHeaders();
+            getTranslateFileJobResultHeaders.xAcsDingtalkAccessToken = getCorpAccessToken(dingding);
+            GetTranslateFileJobResultRequest getTranslateFileJobResultRequest = new GetTranslateFileJobResultRequest()
+                    .setJobId(jobId);
+            try {
+                GetTranslateFileJobResultResponse translateFileJobResultWithOptions = client.getTranslateFileJobResultWithOptions(getTranslateFileJobResultRequest, getTranslateFileJobResultHeaders, new RuntimeOptions());
+                GetTranslateFileJobResultResponseBody body = translateFileJobResultWithOptions.body;
+                return body.url;
+            } catch (TeaException err) {
+                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                    // err 中含有 code 和 message 属性,可帮助开发定位问题
+                }
+            } catch (Exception _err) {
+                TeaException err = new TeaException(_err.getMessage(), _err);
+                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                    // err 中含有 code 和 message 属性,可帮助开发定位问题
+                }
+            }
+        }
+        return null;
+    }
 
     private boolean judgeIsLeader(String userId) {
         int cnt = projectAuditorMapper.selectCount(new QueryWrapper<ProjectAuditor>().eq("auditor_id", userId));

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java

@@ -13,6 +13,7 @@ import org.apache.poi.ss.usermodel.BorderStyle;
 import org.apache.poi.ss.usermodel.CellStyle;
 import org.apache.poi.ss.usermodel.FillPatternType;
 import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
@@ -34,6 +35,8 @@ public class ExcelExportServiceImpl implements ExcelExportService {
 
     @Resource
     private CorpwxJobResultMapper corpwxJobResultMapper;
+    @Value("${upload.path}")
+    private String path;
 
     @Transactional(isolation = Isolation.READ_COMMITTED)
     public void testRead(String jobId) {

+ 1 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseSheetServiceImpl.java

@@ -146,9 +146,7 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                     //项目经理审核,默认为待审核状态
                     sheet.setStatus(1);
                 }else if (auditSetting.getAuditType() == 2) {
-                    if (sheet.getStatus() == null) {
-                        sheet.setStatus(1);//默认提交时为待审核状态
-                    }
+                    sheet.setStatus(1);//修改为待审核状态
                 }
             }
         }

+ 3 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FeishuInfoServiceImpl.java

@@ -178,7 +178,7 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
                 Map resultMap=new HashMap();
                 JSONArray departmentResult=new JSONArray();
                 JSONArray userResult=new JSONArray();
-                String url = GET_AVAILABLE_RANGE;
+                String url = GET_AVAILABLE_RANGE+"?page_size={page_size}";
                 HttpHeaders headers = new HttpHeaders();
                 RestTemplate restTemplate = new RestTemplate();
                 MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
@@ -191,8 +191,9 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
                 map.put("page_token",null);
                 if(pageToken!=null){
                         map.put("page_token",pageToken);
+                        url+="&page_token={page_token}";
                 }
-                ResponseEntity<String> ResponseEntity = restTemplate.exchange(url+"?page_size={page_size}&page_token={page_token}",HttpMethod.GET,httpEntity,String.class,map);
+                ResponseEntity<String> ResponseEntity = restTemplate.exchange(url,HttpMethod.GET,httpEntity,String.class,map);
                 if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
                         String resp = ResponseEntity.getBody();
                         JSONObject respJson = JSONObject.parseObject(resp);

+ 83 - 30
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -8,7 +8,6 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.github.pagehelper.util.StringUtil;
 import com.management.platform.entity.*;
 import com.management.platform.entity.Task;
 import com.management.platform.entity.vo.*;
@@ -16,8 +15,6 @@ import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.*;
 import com.management.platform.webservice.po.*;
-import com.sun.star.bridge.oleautomation.Decimal;
-import javafx.stage.Stage;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpPost;
@@ -25,7 +22,6 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
-import org.apache.ibatis.annotations.Select;
 import org.apache.poi.EncryptedDocumentException;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFRow;
@@ -45,7 +41,6 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -55,21 +50,17 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.sql.Array;
 import java.sql.Timestamp;
 import java.text.*;
 import java.time.*;
 import java.time.chrono.ChronoLocalDate;
 import java.time.format.DateTimeFormatter;
-import java.time.temporal.TemporalAdjuster;
 import java.time.temporal.TemporalAdjusters;
 import java.util.*;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
-import java.util.function.Function;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 
 /**
@@ -247,6 +238,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     private StagesService stagesService;
     @Resource
     private SapProjectServiceService sapProjectServiceService;
+    @Resource
+    private HolidaySettingService holidaySettingService;
 
     @Value(value = "${upload.path}")
     private String path;
@@ -8114,6 +8107,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         Integer timeliness = timeType.getTimeliness();
         List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "全公司填报及时率");
         List<SysRichFunction> functionDeptList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "负责部门填报及时率");
+        //获取到公司设置的特殊节假日设置
+        List<HolidaySetting> holidaySettingList = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, targetUser.getCompanyId()).isNotNull(HolidaySetting::getHolidayDate));
         List<Integer> deptIds=new ArrayList<>();
         List<Department> allDepartmentList=departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id",targetUser.getCompanyId()));
         List<Department> userDepartmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", targetUser.getId()).eq("company_id",targetUser.getCompanyId()));
@@ -8161,9 +8156,14 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         }
         List<Map<String,Object>> reportList=reportMapper.getUserReportTimelinessRate(targetUser.getCompanyId(),startDate,endDate,userId,deptIds);
         Map<Object, List<Map<String, Object>>> listMap = reportList.stream().filter(item->!StringUtils.isEmpty(item.get("userName"))).collect(Collectors.groupingBy(rp -> rp.get("userName")));
-        //获取请假数据
-        List<LeaveSheet> leaveSheetList = leaveSheetMapper.selectList(new QueryWrapper<LeaveSheet>().eq("company_id", targetUser.getCompanyId()));
+        //获取请假数据 todo:待优化 这里需要过滤日期(防止获取数据太慢)
+        List<LeaveSheet> leaveSheetList = leaveSheetMapper.selectList(new LambdaQueryWrapper<LeaveSheet>()
+                .eq(LeaveSheet::getCompanyId, targetUser.getCompanyId()).le(LeaveSheet::getStartDate,endDate).ge(LeaveSheet::getEndDate,startDate));
         List<TimelinessRateVO> resultList=new ArrayList<>();
+        //针对美莱德 去除2024-02-09
+        //针对人员已经特殊节假日设置去除相对应的日期
+        List<HolidaySetting> allUsersSetting = holidaySettingList.stream().filter(h -> h.getRangeType() == 0).collect(Collectors.toList());
+        List<HolidaySetting> targetUserOrDeptSetting = holidaySettingList.stream().filter(h -> h.getRangeType() == 1).collect(Collectors.toList());
         for (User user : userList){
             LocalDateTime sDate;
             LocalDateTime eDate = LocalDate.parse(endDate).atTime(LocalTime.MIN);
@@ -8176,13 +8176,35 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     sDate = inductionDate.atTime(LocalTime.MIN);
                 }
             }else  sDate = LocalDate.parse(startDate).atTime(LocalTime.MIN);
-            List<LocalDateTime> dateTimeList=getDays(sDate, eDate);
-            //针对美莱德 去除2024-02-09
-            if(user.getCompanyId()==876){
-                dateTimeList=dateTimeList.stream().filter(d->!d.isEqual(LocalDate.parse("2024-02-09").atTime(LocalTime.MIN))).collect(Collectors.toList());
+            AtomicReference<List<LocalDateTime>> dateTimeList= new AtomicReference<>(getDays(sDate, eDate));
+            if(allUsersSetting.size()>0){
+                List<LocalDateTime> holidayDateList = allUsersSetting.stream().map(h->h.getHolidayDate().atTime(LocalTime.MIN)).collect(Collectors.toList());
+                dateTimeList.set(dateTimeList.get().stream().filter(d -> !holidayDateList.contains(d)).collect(Collectors.toList()));
+            }
+            if(targetUserOrDeptSetting.size()>0){
+                targetUserOrDeptSetting.forEach(t->{
+                    LocalDateTime holidayDate = t.getHolidayDate().atTime(LocalTime.MIN);
+                    if(!StringUtils.isEmpty(t.getTargetUsers())&&!t.getTargetUsers().equals("")){
+                        String[] userSplit = t.getTargetUsers().split(",");
+                        List<String> userAsList = Arrays.asList(userSplit);
+                        if(userAsList.contains(user.getId())){
+                            dateTimeList.set(dateTimeList.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                        }
+                    }
+                    if(!StringUtils.isEmpty(t.getTargetDepts())&&!t.getTargetDepts().equals("")){
+                        String[] deptSplit = t.getTargetDepts().split(",");
+                        List<String> deptAsList = Arrays.asList(deptSplit);
+                        for (String deptId : deptAsList) {
+                            List<Integer> subDeptIds = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                            if(deptId.equals(user.getDepartmentId())||subDeptIds.contains(user.getDepartmentId())){
+                                dateTimeList.set(dateTimeList.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                            }
+                        }
+                    }
+                });
             }
             List<Map<String,Object>> dataList=new ArrayList<>();
-            long days =dateTimeList.size();
+            long days = dateTimeList.get().size();
             List<LeaveSheet> leaveSheets = leaveSheetList.stream().filter(ls -> ls.getOwnerId().equals(user.getId())
                     &&((ls.getStartDate().isBefore(ChronoLocalDate.from(eDate))||ls.getStartDate().isEqual(ChronoLocalDate.from(eDate))))
                     &&((ls.getEndDate().isAfter(ChronoLocalDate.from(sDate))||ls.getEndDate().isEqual(ChronoLocalDate.from(sDate))))).collect(Collectors.toList());
@@ -8204,7 +8226,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             }
             List<Map<String, Object>> mapList = listMap.get(user.getName());
             //去掉填非工作日
-            for (LocalDateTime localDateTime : dateTimeList) {
+            for (LocalDateTime localDateTime : dateTimeList.get()) {
                 if(mapList!=null){
                     //在非工作日下 填报了的情况下 及时填报了就算作及时率计算的基数
                     if(!WorkDayCalculateUtils.isWorkDay(localDateTime.toLocalDate())&&!mapList.stream().anyMatch(ml->{
@@ -8226,22 +8248,51 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             long daysWithLeave =days;
             if(leaveSheets.size()>0){
                 for (LeaveSheet leaveSheet : leaveSheets) {
-                    List<LocalDateTime> leaveDateList = getDays(leaveSheet.getStartDate().atTime(LocalTime.MIN), leaveSheet.getEndDate().atTime(LocalTime.MIN));
-                    //针对美莱德 去除2024-02-09
-                    if(user.getCompanyId()==876){
-                        leaveDateList=leaveDateList.stream().filter(d->!d.isEqual(LocalDate.parse("2024-02-09").atTime(LocalTime.MIN))).collect(Collectors.toList());
-                    }
-                    List<LocalDateTime> list = getDays(leaveSheet.getStartDate().atTime(LocalTime.now()), leaveSheet.getEndDate().atTime(LocalTime.now()));
-                    //针对美莱德 去除2024-02-09
-                    if(user.getCompanyId()==876){
-                        list=list.stream().filter(d->!d.isEqual(LocalDate.parse("2024-02-09").atTime(LocalTime.MIN))).collect(Collectors.toList());
+                    AtomicReference<List<LocalDateTime>> leaveDateList = new AtomicReference<>(getDays(leaveSheet.getStartDate().atTime(LocalTime.MIN), leaveSheet.getEndDate().atTime(LocalTime.MIN)));
+//                    //针对美莱德 去除2024-02-09
+//                    if(user.getCompanyId()==876){
+//                        leaveDateList=leaveDateList.stream().filter(d->!d.isEqual(LocalDate.parse("2024-02-09").atTime(LocalTime.MIN))).collect(Collectors.toList());
+//                    }
+                    AtomicReference<List<LocalDateTime>> list = new AtomicReference<>(getDays(leaveSheet.getStartDate().atTime(LocalTime.MIN), leaveSheet.getEndDate().atTime(LocalTime.MIN)));
+//                    //针对美莱德 去除2024-02-09
+//                    if(user.getCompanyId()==876){
+//                        list=list.stream().filter(d->!d.isEqual(LocalDate.parse("2024-02-09").atTime(LocalTime.MIN))).collect(Collectors.toList());
+//                    }
+                    if(allUsersSetting.size()>0){
+                        List<LocalDateTime> holidayDateList = allUsersSetting.stream().map(h->h.getHolidayDate().atTime(LocalTime.MIN)).collect(Collectors.toList());
+                        leaveDateList.set(leaveDateList.get().stream().filter(d -> !holidayDateList.contains(d)).collect(Collectors.toList()));
+                        list.set(list.get().stream().filter(d -> !holidayDateList.contains(d)).collect(Collectors.toList()));
+                    }
+                    if(targetUserOrDeptSetting.size()>0){
+                        targetUserOrDeptSetting.forEach(t->{
+                            LocalDateTime holidayDate = t.getHolidayDate().atTime(LocalTime.MIN);
+                            if(!StringUtils.isEmpty(t.getTargetUsers())&&!t.getTargetUsers().equals("")){
+                                String[] userSplit = t.getTargetUsers().split(",");
+                                List<String> userAsList = Arrays.asList(userSplit);
+                                if(userAsList.contains(user.getId())){
+                                    leaveDateList.set(leaveDateList.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                    list.set(list.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                }
+                            }
+                            if(!StringUtils.isEmpty(t.getTargetDepts())&&!t.getTargetDepts().equals("")){
+                                String[] deptSplit = t.getTargetDepts().split(",");
+                                List<String> deptAsList = Arrays.asList(deptSplit);
+                                for (String deptId : deptAsList) {
+                                    List<Integer> subDeptIds = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                                    if(deptId.equals(user.getDepartmentId())||subDeptIds.contains(user.getDepartmentId())){
+                                        leaveDateList.set(leaveDateList.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                        list.set(list.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                    }
+                                }
+                            }
+                        });
                     }
-                    if(list.size()>1){
-                        days-=list.size();
+                    if(list.get().size()>1){
+                        days-= list.get().size();
                     }else {
                         days-=1;
                     }
-                    for (LocalDateTime localDateTime : leaveDateList) {
+                    for (LocalDateTime localDateTime : leaveDateList.get()) {
                         //todo: 请假区间当中有非工作日在之前被当作 不需填报 所以要加上 保证基数正确
                         if(!WorkDayCalculateUtils.isWorkDay(localDateTime.toLocalDate())){
                             days+=1;
@@ -11772,6 +11823,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         break;
                     case "Z10":categoryName="运维项目";
                         break;
+                    case "Z11":categoryName="数字化服务项目";
+                        break;
                     default:categoryName="未知";
                 }
                 String finalCategoryName = categoryName;

+ 163 - 251
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -204,6 +204,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     private ExcelExportService excelExportService;
     @Resource
     private ProjectMainMapper projectMainMapper;
+    @Resource
+    private HolidaySettingService holidaySettingService;
     @Autowired
     RestTemplate restTemplate;
 
@@ -237,206 +239,39 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             //首先根据日期获取当天所有提交过日志的人
             String userId = request.getHeader("Token");
             User user = userMapper.selectById(userId);
-            TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+            String viewUserId = user.getId();
+            Integer companyId = user.getCompanyId();
+            TimeType timeType = timeTypeMapper.selectById(companyId);
             List<Map<String, Object>> nameList = new ArrayList<>();
             List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全公司工时");
             Integer totalMembCount = 0;
             if (functionList.size() == 0) {
-                String leaderId = user.getId();
-                //不是项目经理,只看自己的报告
                 List<Map<String, Object>> list = new ArrayList<>();
-                //没有指定员工或者指定的就是自己
-                if (targetUid == null || targetUid.equals(user.getId())) {
-                    //查看自己的日报
-                    if (pageIndex != null && pageIndex == 0) {
-                        //仅第一页显示自己的
-                        Map<String, Object> map = new HashMap<>();
-                        map.put("id", user.getId());
-                        map.put("name", user.getName());
-                        List<String> uids = new ArrayList<>();
-                        uids.add(user.getId());
-                        list = reportMapper.getUserReportByDateOrId(date, uids, null);
-                        if (list.size() > 0) {
-                            //个人日报
-                            nameList.add(map);
-                            map.put("data", list);
-                            double reportTime = 0;
-                            BigDecimal total = new BigDecimal(0);
-                            int state = (int)list.get(0).get("state");
-                            boolean hasDeny = false;
-                            boolean hasWaiting = false;
-                            for (Map<String, Object> m : list) {
-                                double t = (double) m.get("time");
-                                reportTime += t;
-                                total = total.add((BigDecimal)m.get("cost"));
-                                int curState = (int)m.get("state");
-                                if (curState == 2) {
-                                    hasDeny = true;
-                                }
-                                if (curState == 0) {
-                                    hasWaiting = true;
-                                }
-                            }
-                            if(hasDeny) {
-                                state = 2;
-                            } else if (hasWaiting) {
-                                state = 0;
-                            }
-                            DecimalFormat df = new DecimalFormat("0.00");
-                            map.put("reportTime", df.format(reportTime));
-                            map.put("cost", total);
-                            map.put("state", state);
-                        }
+                List<Integer> allVisibleDeptIdList = null;
+                if (deptId != null) {
+                    //指定了部门进行查看
+                    allVisibleDeptIdList = new ArrayList<>();
+                    allVisibleDeptIdList.add(deptId);
+                    //找到该部门的所有子部门
+                    List<Department> allDepts = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+                    Optional<Department> first = allDepts.stream().filter(d -> d.getDepartmentId().equals(deptId)).findFirst();
+                    if (first.isPresent()) {
+                        Department department = first.get();
+                        //递归获取全部子部门
+                        List<Department> deptList = getSubDepts(department, allDepts);
+                        deptList.add(department);
+                        List<Integer> ids = deptList.stream().map(Department::getDepartmentId).collect(Collectors.toList());
+                        allVisibleDeptIdList.addAll(ids);
                     }
+                } else {
+                    allVisibleDeptIdList = getAllVisibleDeptIdList(user, null);
                 }
-
-                List<Integer> allVisibleDeptIdList = getAllVisibleDeptIdList(user, null);
                 //需要看可见部门(部门主要负责人和其他负责人以及查看本部门工时权限)所有人员的日报
-                if (allVisibleDeptIdList.size() > 0) {
-                    if (nameList.size() > 0) {
-                        //自己填写的日报
-                        List<Map<String, Object>> deptNameList = reportMapper.getReportNameByDateAndDept(date,
-                                allVisibleDeptIdList, targetUid, null, pageStart, pageSize);
-                        totalMembCount = reportMapper.getReportNameByDateAndDeptCount(date, allVisibleDeptIdList, targetUid, null);
-                        for (Map<String, Object> deptNameItem : deptNameList) {
-                            if (!deptNameItem.get("id").equals(user.getId())) {
-                                nameList.add(deptNameItem);
-                            }
-                        }
-                    } else {
-                        nameList = reportMapper.getReportNameByDateAndDept(date,
-                                allVisibleDeptIdList, targetUid, null, pageStart, pageSize);
-                        totalMembCount = reportMapper.getReportNameByDateAndDeptCount(date, allVisibleDeptIdList, targetUid, null);
-                    }
-                    if (nameList.size() > 0) {
-                        List<String> userIds = new ArrayList<>();
-                        nameList.forEach(n->{
-                            String id = (String) n.get("id");
-                            userIds.add(id);
-                        });
-                        List<Map<String, Object>> reportList = reportMapper.getUserReportByDateOrId(date, userIds, null);
-                        for (Map<String, Object> memb : nameList) {
-                            //再根据人分别获取当天的报告
-                            List<Map<String, Object>> rList = new ArrayList<Map<String, Object>>();
-                            BigDecimal total = new BigDecimal(0);
-                            for (Map<String, Object> report : reportList) {
-                                if (((String)report.get("creatorId")).equals((String)memb.get("id"))) {
-                                    rList.add(report);
-                                    total = total.add((BigDecimal) report.get("cost"));
-                                }
-                            }
-                            memb.put("data", rList);
-                            memb.put("cost", total);
-                            double reportTime = 0;
-                            if (rList.size() > 0) {
-                                int state = 1;
-                                for (Map<String, Object> m : rList) {
-                                    double t = (double) m.get("time");
-                                    reportTime += t;
-
-                                    //取最低的状态
-                                    if (state == 2) {
-                                        continue;
-                                    }
-                                    if (state == 0) {
-                                        if ((int)m.get("state") == 2) {
-                                            state = 2;
-                                        } else {
-                                            continue;
-                                        }
-                                    } else {
-                                        state = (int)m.get("state");
-                                    }
-                                }
-                                memb.put("state", state);
-                            }
-                            DecimalFormat df = new DecimalFormat("0.00");
-                            memb.put("reportTime", df.format(reportTime));
-                        }
-                    }
-                }
-                if(deptId==null&&targetUid==null){
-                    //担任项目经理或者日报审核人,查找相关的人员的日报
-                    List<Map<String, Object>> puserNames = reportMapper.getReportNameByDate(date, user.getCompanyId(), leaderId);
-                    List<Map<String, Object>> inchargeReportList= reportMapper.getInchargeReportByDate(date, leaderId, null);
-
-                    if ((timeType.getReportAuditType() == 5 || timeType.getReportAuditType() == 6)&& timeType.getReportCc() == 1) {
-                        //存在抄送人的设置,需要把抄送人的项目相关日报也加上
-                        List<Map<String, Object>> viewUserNames = reportMapper.getCcReportNameByDate(date, user.getCompanyId(),leaderId);
-                        for (Map<String, Object> viewItem : viewUserNames) {
-                            boolean exists = false;
-                            for (Map<String, Object> u : puserNames) {
-                                if (u.get("id").equals(viewItem.get("id"))) {
-                                    exists = true;
-                                    break;
-                                }
-                            }
-                            if (!exists) {
-                                puserNames.add(viewItem);
-                            }
-                        }
-
-                        List<Map<String, Object>> viewReportList = reportMapper.getCcReportByDate(date, leaderId, null);
-                        for (Map<String, Object> viewItem : viewReportList) {
-                            boolean exists = false;
-                            for (Map<String, Object> u : inchargeReportList) {
-                                if (u.get("id").equals(viewItem.get("id"))) {
-                                    exists = true;
-                                    break;
-                                }
-                            }
-                            if (!exists) {
-                                inchargeReportList.add(viewItem);
-                            }
-                        }
-                    }
-                    for (Map<String, Object> map2 : puserNames) {
-
-                        if (nameList.size() > 0) {
-                            String myUserId = (String)nameList.get(0).get("id");
-                            if (myUserId.equals(map2.get("id"))) {
-                                //自己的报告,之前已经添加过了,排重
-                                continue;
-                            }
-                        }
-                        List<Object> collect = nameList.stream().map(nl -> nl.get("")).collect(Collectors.toList());
-                        if(!collect.contains(map2.get("id"))){
-                            nameList.add(map2);
-                        }
-                        //再根据人分别获取当天的报告
-                        List<Map<String, Object>> list2 =
-                                inchargeReportList.stream().filter(i->i.get("creatorId").equals(map2.get("id"))).collect(Collectors.toList());
-                        map2.put("data", list2);
-
-                        double reportTime = 0;
-                        BigDecimal total = new BigDecimal(0);
-                        int state = 1;
-                        for (Map<String, Object> m : list2) {
-                            double t = (double) m.get("time");
-                            reportTime += t;
-                            total = total.add((BigDecimal)m.get("cost"));
-                            //取最低的状态
-                            if (state == 2) {
-                                continue;
-                            }
-                            if (state == 0) {
-                                if ((int)m.get("state") == 2) {
-                                    state = 2;
-                                } else {
-                                    continue;
-                                }
-                            } else {
-                                state = (int)m.get("state");
-                            }
-                        }
-                        DecimalFormat df = new DecimalFormat("0.00");
-                        map2.put("reportTime", df.format(reportTime));
-                        map2.put("cost", total);
-                        map2.put("state", state);
-                    }
-                }
+                nameList = reportMapper.getReportNameByDateAndDept(date,
+                        allVisibleDeptIdList.size() > 0?allVisibleDeptIdList:null, targetUid, companyId, (deptId == null?viewUserId:null), pageStart, pageSize);
+                totalMembCount = reportMapper.getReportNameByDateAndDeptCount(date, allVisibleDeptIdList.size() > 0?allVisibleDeptIdList:null, targetUid, companyId, (deptId == null?viewUserId:null));
             } else {
-                Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
+                //查看全公司的数据
                 List<Integer> ids = null;
                 if (deptId != null) {
                     if (deptId == 0) {
@@ -457,53 +292,53 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 }
                 nameList = reportMapper.getReportNameByDateAndDept(date,
-                        ids, targetUid, companyId, pageStart, pageSize);
-                totalMembCount = reportMapper.getReportNameByDateAndDeptCount(date, ids, targetUid, companyId);
-                if (nameList.size() > 0) {
-                    List<String> userIds = new ArrayList<>();
-                    nameList.forEach(n->{
-                        String id = (String) n.get("id");
-                        userIds.add(id);
-                    });
-                    List<Map<String, Object>> reportList = reportMapper.getUserReportByDateOrId(date, userIds, null);
-                    for (Map<String, Object> map : nameList) {
-                        //再根据人分别获取当天的报告
-                        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
-                        BigDecimal total = new BigDecimal(0);
-                        for (Map<String, Object> report : reportList) {
-                            if (((String)report.get("creatorId")).equals((String)map.get("id"))) {
-                                list.add(report);
-                                total = total.add((BigDecimal) report.get("cost"));
-                            }
-
+                        ids, targetUid, companyId, null, pageStart, pageSize);
+                totalMembCount = reportMapper.getReportNameByDateAndDeptCount(date, ids, targetUid, companyId, null);
+            }
+            if (nameList.size() > 0) {
+                List<String> userIds = new ArrayList<>();
+                nameList.forEach(n->{
+                    String id = (String) n.get("id");
+                    userIds.add(id);
+                });
+                List<Map<String, Object>> reportList = reportMapper.getUserReportByDateOrId(date, userIds, null);
+                for (Map<String, Object> memb : nameList) {
+                    //再根据人分别获取当天的报告
+                    List<Map<String, Object>> rList = new ArrayList<Map<String, Object>>();
+                    BigDecimal total = new BigDecimal(0);
+                    for (Map<String, Object> report : reportList) {
+                        if (((String)report.get("creatorId")).equals((String)memb.get("id"))) {
+                            rList.add(report);
+                            total = total.add((BigDecimal) report.get("cost"));
                         }
-                        map.put("data", list);
-                        map.put("cost", total);
-                        double reportTime = 0;
-                        if (list.size() > 0) {
-                            int state = 1;
-                            for (Map<String, Object> m : list) {
-                                double t = (double) m.get("time");
-                                reportTime += t;
-                                //取最低的状态
-                                if (state == 2) {
-                                    continue;
-                                }
-                                if (state == 0) {
-                                    if ((int)m.get("state") == 2) {
-                                        state = 2;
-                                    } else {
-                                        continue;
-                                    }
+                    }
+                    memb.put("data", rList);
+                    memb.put("cost", total);
+                    double reportTime = 0;
+                    if (rList.size() > 0) {
+                        int state = 1;
+                        for (Map<String, Object> m : rList) {
+                            double t = (double) m.get("time");
+                            reportTime += t;
+
+                            //取最低的状态
+                            if (state == 2) {
+                                continue;
+                            }
+                            if (state == 0) {
+                                if ((int)m.get("state") == 2) {
+                                    state = 2;
                                 } else {
-                                    state = (int)m.get("state");
+                                    continue;
                                 }
+                            } else {
+                                state = (int)m.get("state");
                             }
-                            map.put("state", state);
                         }
-                        DecimalFormat df = new DecimalFormat("0.00");
-                        map.put("reportTime", df.format(reportTime));
+                        memb.put("state", state);
                     }
+                    DecimalFormat df = new DecimalFormat("0.00");
+                    memb.put("reportTime", df.format(reportTime));
                 }
             }
 
@@ -4152,11 +3987,11 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                             Class<User> aClass = User.class;
                             Method method = aClass.getMethod(getter);
                             String invoke = (String) method.invoke(targetUser);
-                            if(invoke.equals("有加班费")){
+                            if(invoke==null||invoke.equals("有加班费")){
                                 if(!(Double.valueOf(String.valueOf(map.get("workingTime"))).equals(Double.valueOf(first.get().getWorkHours())))){
                                     map.put("exceedCardTime",1);
                                 }
-                            }else if(invoke.equals("无加班费")){
+                            }else{
                                 if((Double.valueOf(String.valueOf(map.get("workingTime")))<first.get().getWorkHours())){
                                     map.put("exceedCardTime",1);
                                 }
@@ -4376,8 +4211,35 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         User user = userMapper.selectById(token);
         Integer companyId = user.getCompanyId();
         Company company = companyMapper.selectById(companyId);
+        //准备部门数据
+        List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
         List<UserFvTime> userFvTimeList = userFvTimeMapper.selectList(new LambdaQueryWrapper<UserFvTime>().between(UserFvTime::getWorkDate, startDate, endDate));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, company.getId()));
+        //处理特殊节假日设置
+        //特殊节假日配置
+        List<HolidaySetting> holidaySettingList = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, companyId));
+        //针对全员生效的日期
+        List<LocalDate> holidayForAllUser = holidaySettingList.stream().filter(h -> h.getRangeType() == 0).collect(Collectors.toList()).stream().map(HolidaySetting::getHolidayDate).distinct().collect(Collectors.toList());
+        //针对指定人员的日期
+        List<LocalDate> holidayForTarget = holidaySettingList.stream().filter(h -> h.getRangeType() == 1).collect(Collectors.toList()).stream().map(HolidaySetting::getHolidayDate).distinct().collect(Collectors.toList());
+        //针对指定人员的人员已经部门
+        String userIdStr = holidaySettingList.stream().filter(f -> f.getRangeType() == 1).collect(Collectors.toList()).stream().map(HolidaySetting::getTargetUsers).collect(Collectors.joining(","));
+        String deptIdStr = holidaySettingList.stream().filter(f -> f.getRangeType() == 1).collect(Collectors.toList()).stream().map(HolidaySetting::getTargetDepts).collect(Collectors.joining(","));
+        List<Integer> targetDeptIds=new ArrayList<>();
+        if(!StringUtils.isEmpty(deptIdStr)&&!deptIdStr.equals("")){
+            String[] deptSplit = deptIdStr.split(",");
+            List<String> deptArray = Arrays.asList(deptSplit);
+            for (String deptId : deptArray) {
+                List<Integer> subDeptIds = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                targetDeptIds.add(Integer.valueOf(deptId));
+                targetDeptIds.addAll(subDeptIds);
+            }
+        }
+        List<String> targetUserIds=new ArrayList<>();
+        if(!StringUtils.isEmpty(userIdStr)&&!userIdStr.equals("")){
+            String[] userSplit = userIdStr.split(",");
+            targetUserIds = Arrays.asList(userSplit);
+        }
         List<UserCustom> userCustomList = userCustomMapper.selectList(new LambdaQueryWrapper<UserCustom>().eq(UserCustom::getCompanyId, companyId));
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
         //String[] weekDayCHN = {"周一","周二","周三","周四","周五","周六","周日"};
@@ -4422,8 +4284,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             }
         }
         List<UserMonthWork> userMonthWorks = new ArrayList<UserMonthWork>();
-        //准备部门数据
-        List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
         //获取所有同步的企业微信数据
         List<Map> userCorpwxTimeMapList = userCorpwxTimeMapper.selectByAsk(companyId,startDate,endDate);
         String lastUserId = null;
@@ -4432,6 +4292,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             String id = (String)data.get("id");
             String name = (String)data.get("name");
             String departmentName = (String) data.get("departmentName");
+            String deptId = String.valueOf(data.get("deptId"));
             String corpwxUserId = (String) data.get("corpwxUserId");
             Integer corpwxDeptId = (Integer) data.get("corpwxDeptId");
             Map<String, Object> map = new HashMap<>();
@@ -4455,11 +4316,11 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                             Class<User> aClass = User.class;
                             Method method = aClass.getMethod(getter);
                             String invoke = (String) method.invoke(targetUser);
-                            if(invoke.equals("有加班费")){
+                            if(invoke==null||invoke.equals("有加班费")){
                                 if(!(Double.valueOf(String.valueOf(data.get("workingTime"))).equals(Double.valueOf(first.get().getWorkHours())))){
                                     map.put("exceedCardTime",1);
                                 }
-                            }else if(invoke.equals("无加班费")){
+                            }else{
                                 if((Double.valueOf(String.valueOf(data.get("workingTime")))<first.get().getWorkHours())){
                                     map.put("exceedCardTime",1);
                                 }
@@ -4477,6 +4338,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 lastUserData.userId = id;
                 lastUserData.name = name;
                 lastUserData.departmentName = departmentName;
+                lastUserData.deptId = deptId;
                 lastUserData.corpwxUserId = corpwxUserId;
                 lastUserData.corpwxDeptId = String.valueOf(corpwxDeptId);
                 lastUserData.worktimeList = new ArrayList<>();
@@ -4587,6 +4449,26 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 });
             }
+            if(worktimeList!=null&&worktimeList.size()>0){
+                Iterator<Map<String, Object>> iterator = worktimeList.iterator();
+                while (iterator.hasNext()){
+                    Map<String, Object> w = iterator.next();
+                    if(holidayForAllUser.size()>0){
+                        boolean match = holidayForAllUser.stream().anyMatch(h -> h.isEqual(LocalDate.parse(String.valueOf(w.get("createDate")), df)));
+                        if(match){
+                            iterator.remove();
+                        }
+                    }
+                    if(holidayForTarget.size()>0){
+                        boolean dayMatch = holidayForTarget.stream().anyMatch(h -> h.isEqual(LocalDate.parse(String.valueOf(w.get("createDate")), df)));
+                        if(dayMatch){
+                            if((userMonthWork.deptId!=null&&targetDeptIds.contains(Integer.valueOf(userMonthWork.deptId)))||targetUserIds.contains(userMonthWork.userId)){
+                                iterator.remove();
+                            };
+                        }
+                    }
+                }
+            }
         }
         HashMap map = new HashMap();
         List<HashMap> days = new ArrayList<HashMap>();
@@ -7067,6 +6949,36 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         if (defaultDegree!=null && "-1".equals(defaultDegree.get("id").toString())){
             defaultDegree = null;
         }
+        //如果该项目已经没有绑定该维度,则取消
+        if (defaultDegree != null) {
+            Integer degreeId = (Integer) defaultDegree.get("id");
+            Integer companyId = user.getCompanyId();
+            TimeType timeType = timeTypeMapper.selectById(companyId);
+            List<ReportExtraDegree> extraDegreeList = reportExtraDegreeMapper.selectList(new QueryWrapper<ReportExtraDegree>().eq("company_id", companyId));
+            String associateDegrees = "";
+            List<String> associateDegreeList = new ArrayList<>();
+            if(timeType.getCustomDegreeWithPro()==0){
+                associateDegrees=extraDegreeList.stream().map(a->String.valueOf(a.getId())).collect(Collectors.joining(","));
+            }else {
+                Project project = projectMapper.selectById(projectId);
+                associateDegrees = project.getAssociateDegrees();
+            }
+            boolean find = false;
+            if (!StringUtils.isEmpty(associateDegrees)) {
+                String[] id = associateDegrees.split("\\,");
+                for (int i=0;i<id.length; i++) {
+                    if (id[i].equals(degreeId.toString())) {
+                        find = true;
+                        break;
+                    }
+                }
+            }
+            if (!find) {
+                //该维度已不存在,或者从项目上解绑了
+                defaultDegree = null;
+            }
+        }
+
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         httpRespMsg.data = defaultDegree;
         return httpRespMsg;
@@ -9066,19 +8978,19 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     ww.put("workingTime",0);
                     worktimeList.add(ww);
                 }
-                if(worktimeList.size()>0){
-                    worktimeList.forEach(w->{
-                        Optional<UserFvTime> first = userFvTimeList.stream().filter(u -> u.getWorkDate().isEqual(date) && u.getUserId().equals(m.userId)).findFirst();
-                        if(first.isPresent()){
-                            w.put("cardTime",first.get().getWorkHours());
-                        }
-                        w.put("name",m.name);
-                        w.put("corpwxDeptId",m.corpwxDeptId);
-                        w.put("corpwxUserId",m.corpwxUserId);
-                        w.put("departmentName",m.departmentName);
-                        w.put("userId",m.userId);
-                    });
-                }
+            }
+            if(worktimeList.size()>0){
+                worktimeList.forEach(w->{
+                    Optional<UserFvTime> first = userFvTimeList.stream().filter(u -> u.getWorkDate().isEqual(LocalDate.parse(String.valueOf(w.get("createDate")),df)) && u.getUserId().equals(m.userId)).findFirst();
+                    if(first.isPresent()){
+                        w.put("cardTime",first.get().getWorkHours());
+                    }
+                    w.put("name",m.name);
+                    w.put("corpwxDeptId",m.corpwxDeptId);
+                    w.put("corpwxUserId",m.corpwxUserId);
+                    w.put("departmentName",m.departmentName);
+                    w.put("userId",m.userId);
+                });
             }
             result.addAll(worktimeList);
         });

+ 14 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -264,6 +264,13 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 if (info != null) {
                     userList.get(0).setUserNameNeedTranslate(info.getSaasSyncContact());
                 }
+                //检测钉钉用户,是否需要转译
+                else {
+                    CompanyDingding companyDingding = companyDingdingService.getOne(new QueryWrapper<CompanyDingding>().eq("company_id", company.getId()));
+                    if (companyDingding != null) {
+                        userList.get(0).setUserNameNeedTranslate(companyDingding.getContactNeedTranslate());
+                    }
+                }
                 BeanUtils.copyProperties(userList.get(0), userVO);
                 if (userVO.getRoleId() == null || userVO.getRoleId() == 0) {
                     httpRespMsg.setError(MessageUtils.message("user.noRole"));
@@ -2614,7 +2621,13 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         if (info != null) {
             user.setUserNameNeedTranslate(info.getSaasSyncContact());
         }
-
+        //检测钉钉用户,是否需要转译
+        else {
+            CompanyDingding companyDingding = companyDingdingService.getOne(new QueryWrapper<CompanyDingding>().eq("company_id", company.getId()));
+            if (companyDingding != null) {
+                user.setUserNameNeedTranslate(companyDingding.getContactNeedTranslate());
+            }
+        }
         UserVO userVO = new UserVO().setCompanyName(company.getCompanyName());
         userVO.setCompany(company);
         BeanUtils.copyProperties(user, userVO);

+ 63 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -38,6 +38,7 @@ import javax.annotation.Resource;
 import java.io.File;
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.security.SecureRandom;
 import java.sql.Time;
 import java.sql.Timestamp;
@@ -1786,6 +1787,10 @@ public class TimingTask {
                             break;
                         case "Z09":categoryName="售后工程项目";
                             break;
+                        case "Z10":categoryName="运维项目";
+                            break;
+                        case "Z11":categoryName="数字化服务项目";
+                            break;
                         default:categoryName="未知";
                     }
                     String finalCategoryName = categoryName;
@@ -2001,7 +2006,6 @@ public class TimingTask {
         if(isDev){
             return;
         }
-        List<UserWithBeisen> allBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, 936));
         List<UserWithBeisen> userWithBeisenList=new ArrayList<>();
         LocalDate now=LocalDate.now();
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
@@ -2016,6 +2020,7 @@ public class TimingTask {
             if(beisenConfig!=null){
                 List<JSONArray> byTimeWindow = BeiSenUtils.getByTimeWindow("",startTime,endTime,beisenConfig.getCompanyId(),beisenConfig.getAppKey(),beisenConfig.getAppSecret());
                 List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, beisenConfig.getCompanyId()));
+                List<UserWithBeisen> allBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, beisenConfig.getCompanyId()));
                 if(byTimeWindow.size()>0){
                     for (JSONArray array : byTimeWindow) {
                         for (int i = 0; i < array.size(); i++) {
@@ -2033,7 +2038,7 @@ public class TimingTask {
                                 userWithBeisen.setId(first.get().getId());
                             }
                             userWithBeisenList.add(userWithBeisen);
-                            Optional<User> user = userList.stream().filter(u -> u.getJobNumber().equals(userWithBeisen.getJobNumber())).findFirst();
+                            Optional<User> user = userList.stream().filter(u ->u.getJobNumber()!=null&&u.getJobNumber().equals(userWithBeisen.getJobNumber())).findFirst();
                             if(user.isPresent()){
                                 User u=new User();
                                 u.setId(user.get().getId());
@@ -2057,7 +2062,7 @@ public class TimingTask {
     /**
      * 每天凌晨2:50同步前一天的北森考勤数据 暂时固定公司id(5978)针对景昱
      * */
-    @Scheduled(cron ="0 50 2 ? * *")
+    @Scheduled(cron ="0 38 16 ? * *")
     public void syncAttendanceFromBeisen(){
         if(isDev){
             return;
@@ -2065,7 +2070,8 @@ public class TimingTask {
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
         DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
-        String startDate=LocalDate.now().plusDays(1).format(df);
+        DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+        String startDate=LocalDate.now().minusDays(1).format(df);
         String endDate=LocalDate.now().plusDays(1).format(df);
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, 5978));
         List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, 5978));
@@ -2073,15 +2079,21 @@ public class TimingTask {
         if(beisenConfig==null){
             return;
         }
-        //todo 获取到指定日期的考勤数据
-        JSONArray attendanceStatistics = BeiSenUtils.getAttendanceStatistics(startDate, endDate, beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+
         //todo 获取到指定日期的加班数据
         List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
         JSONArray allOverTimeList=new JSONArray();
+        JSONArray attendanceStatistics=new JSONArray();
+        JSONArray allVacationList=new JSONArray();
         List<UserFvTime> userFvTimeList=new ArrayList<>();
         for (LocalDate localDate : workDaysListInRange) {
             JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+            //todo 获取到指定日期的考勤数据
+            JSONArray attendanceStatisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
             allOverTimeList.addAll(overTimeList);
+            attendanceStatistics.addAll(attendanceStatisticList);
+            allVacationList.addAll(vacationList);
         }
         for (LocalDate localDate : workDaysListInRange) {
             Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
@@ -2105,25 +2117,65 @@ public class TimingTask {
                 if(first.isPresent()){
                     boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
                     //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Double workTime=8.0;
+                    Duration between = Duration.between(min.get(), max.get());
+                    Double workTime;
+                    if(between.toHours()>8){
+                        workTime=8.0;
+                    }else if(between.toHours()<0){
+                        workTime=0.0;
+                    }else {
+                        BigDecimal decimal = new BigDecimal(between.toMinutes());
+                        decimal=decimal.divide(new BigDecimal(60),1, RoundingMode.HALF_UP);
+                        workTime=decimal.doubleValue();
+                    }
                     Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
+                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
                     Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
                     if(beisen.isPresent()){
                         List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-                                && a.getIntValue("ApproveStatus") == 2).collect(Collectors.toList());
+                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)
+                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
                         if(overTimeList.size()>0){
-                            double actualOverTimeDuration = overTimeList.stream().mapToDouble(i -> i.getDouble("ActualOverTimeDuration")).sum();
+                            double actualOverTimeDuration = overTimeList.stream().mapToDouble(i -> i.getDouble("OverTimeDuration")).sum();
                             if(workDay){
                                 workTime= workTime+actualOverTimeDuration;
                             }else {
                                 workTime= actualOverTimeDuration;
                             }
                         }
+                        List<JSONObject> vacationList = vacationStream.filter(a ->{
+                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
+                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
+                            boolean b=false;
+                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
+                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
+                                b=true;
+                            }
+                            if(a.getString("StaffId").equals(beisen.get().getUserId())
+                                    && b
+                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
+                                return true;
+                            }
+                            return false;
+                        }).collect(Collectors.toList());
+                        if(vacationList.size()>0){
+                            double vacationDuration = vacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
+                            BigDecimal decimal = new BigDecimal(vacationDuration);
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            //考勤打卡区间大于8小时 但是存在休假数据
+                            if(between.toHours()>8){
+                                if(decimal.doubleValue()>8){
+                                    workTime= workTime-8;
+                                }else {
+                                    workTime= workTime-decimal.doubleValue();
+                                }
+                            }
+                        }
                     }
                     UserFvTime userFvTime=new UserFvTime();
                     userFvTime.setWorkDate(localDate);
-                    userFvTime.setStartTime(min.isPresent()?df2.format(min.get()):"08:30");
-                    userFvTime.setEndTime(max.isPresent()?df2.format(max.get()):"17:30");
+                    userFvTime.setStartTime(min.isPresent()?df2.format(min.get()):"08:30:00");
+                    userFvTime.setEndTime(max.isPresent()?df2.format(max.get()):"17:30:00");
                     userFvTime.setUserId(first.get().getId());
                     userFvTime.setCompanyId(5978);
                     userFvTime.setWorkHours(workTime.floatValue());

+ 66 - 9
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/BeiSenUtils.java

@@ -97,16 +97,35 @@ public class BeiSenUtils {
         requestMap.put("timeWindowQueryType",1);
         requestMap.put("startTime",startTime+"T00:00:00");
         requestMap.put("stopTime",stopTime+"T23:59:59");
-        List<String> columns=new ArrayList<>();
-        columns.add("JobNumber");
-        columns.add("MobilePhone");
-        columns.add("Name");
-        columns.add("StaffID");
-        columns.add("UserID");
-        columns.add("extOTWagetype_110324_985711501");
-        if(companyId!=null && companyId==5978){
-            requestMap.put("columns",columns);
+        //针对景昱的参数
+        {
+            List<String> columns=new ArrayList<>();
+            columns.add("JobNumber");
+            columns.add("MobilePhone");
+            columns.add("Name");
+            columns.add("StaffID");
+            columns.add("UserID");
+            columns.add("extOTWagetype_110324_985711501");
+            if(companyId!=null && companyId==5978){
+                requestMap.put("columns",columns);
+            }
         }
+        List<Integer> serviceType=new ArrayList<>();
+        serviceType.add(0);
+        serviceType.add(1);
+        List<String> employType=new ArrayList<>();
+        employType.add("0");
+        employType.add("2");
+        List<Integer> empStatus=new ArrayList<>();
+        empStatus.add(2);
+        empStatus.add(3);
+        empStatus.add(6);
+        empStatus.add(8);
+        requestMap.put("serviceType",serviceType);
+        requestMap.put("employType",employType);
+        requestMap.put("empStatus",empStatus);
+        requestMap.put("isWithDeleted",true);
+        requestMap.put("enableTranslate",true);
         System.out.println("--------headers请求头数据-------"+headers);
         if(!StringUtils.isEmpty(scrollId)){
             requestMap.put("scrollId",scrollId);
@@ -307,4 +326,42 @@ public class BeiSenUtils {
         return data;
     }
 
+    /**
+     * 获取人员休假数据
+     * */
+    public static JSONArray getVacationList(String day,String appkey,String appSecret,Integer pageIndex,Integer pageSize){
+        String url = "https://openapi.italent.cn/AttendanceOpen/api/v1/Vacation/GetList";
+        HttpHeaders headers = new HttpHeaders();
+        RestTemplate restTemplate = new RestTemplate();
+        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
+        headers.setContentType(type);
+        String accessToken = getToken(appkey,appSecret);
+        System.out.println("--------Bearer TOKEN--------"+accessToken);
+        headers.add("Authorization","Bearer "+accessToken);
+        JSONObject requestMap = new JSONObject();
+        requestMap.put("Day",day);
+        requestMap.put("PageIndex",pageIndex);
+        requestMap.put("PageSize",pageSize);
+        System.out.println("--------headers请求头数据-------"+headers);
+        System.out.println("--------requestMap请求参数-------"+requestMap);
+        HttpEntity<JSONObject> entity = new HttpEntity<>(requestMap, headers);
+        ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
+        JSONArray lastJSONArray=new JSONArray();
+        if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
+            String resp= ResponseEntity.getBody();
+            JSONObject respJson = JSONObject.parseObject(resp);
+            if(respJson.getIntValue("Code")==200){
+                JSONObject data = respJson.getJSONObject("Data");
+                JSONArray target = data.getJSONArray("VacationList");
+                lastJSONArray.addAll(target);
+                if (target.size()>0){
+                    pageIndex++;
+                    JSONArray overTimeList = getVacationList(day, appkey, appSecret, pageIndex, pageSize);
+                    lastJSONArray.addAll(overTimeList);
+                }
+            }
+        }
+        return lastJSONArray;
+    }
+
 }

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml

@@ -15,7 +15,7 @@ spring:
       location: C:/upload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://47.101.180.183:17089/man_dev?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
+    url: jdbc:mysql://47.101.180.183:17089/man_hour_manager?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
     username: root
     password: P011430@Huoshi*
 

+ 2 - 14
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/CompanyDingdingMapper.xml

@@ -20,24 +20,12 @@
         <result column="pc_web_url" property="pcWebUrl" />
         <result column="oa_manager_dingid" property="oaManagerDingid" />
         <result column="sync_contact" property="syncContact" />
+        <result column="contact_need_translate" property="contactNeedTranslate" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        corpid, corp_name, auth_user_id, indate, company_id, access_token, expire_time, agent_id, inner_appkey, inner_appsecret, inner_token, inner_expire_time, web_url, pc_web_url, oa_manager_dingid, sync_contact
+        corpid, corp_name, auth_user_id, indate, company_id, access_token, expire_time, agent_id, inner_appkey, inner_appsecret, inner_token, inner_expire_time, web_url, pc_web_url, oa_manager_dingid, sync_contact, contact_need_translate
     </sql>
 
-    <select id="getDingdingCompanyList" resultType="com.management.platform.entity.CompanyDingding">
-        select *
-        from company_dingding
-        left join company
-        ON company_dingding.company_id = company.id
-        where company.expiration_date >= now()
-        <if test="companyIds.size()>0">
-            and company.id in
-            <foreach collection="companyIds" item="item" separator="," open="(" close=")">
-                #{item}
-            </foreach>
-        </if>
-    </select>
 </mapper>

+ 64 - 28
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml

@@ -670,22 +670,40 @@
         SELECT DISTINCT b.id, b.name ,a.evaluate as evaluate
         FROM report AS a
         JOIN user AS b ON a.creator_id=b.id
+        left join project on project.id = a.project_id
+        LEFT JOIN project_ccuser ON a.project_id = project_ccuser.project_id
         WHERE 1=1
         <if test="date != null and date != ''">
             AND a.create_date=#{date}
         </if>
-        <if test="deptIds != null">
-            AND b.department_id in
-            <foreach item="item" collection="deptIds" separator="," open="(" close=")" index="">
-                #{item, jdbcType=INTEGER}
-            </foreach>
-        </if>
-        <if test="companyId != null">
-            AND b.company_id = #{companyId}
-        </if>
-        <if test="userId != null">
-            AND b.id=#{userId}
-        </if>
+        <choose>
+            <when test="userId != null">
+                AND b.id=#{userId}
+            </when>
+            <otherwise>
+                <!--自己,担任项目经理,日报审核人,抄送人,或者自己部门的人填的日报 -->
+                <if test="viewUserId != null">
+                    and (a.creator_id = #{viewUserId} or a.project_auditor_id = #{viewUserId} or project.incharger_id = #{viewUserId}
+                    or project_ccuser.`user_id` = #{viewUserId}
+                    <if test="deptIds != null">
+                        or b.department_id in
+                        <foreach item="item" collection="deptIds" separator="," open="(" close=")" index="">
+                            #{item, jdbcType=INTEGER}
+                        </foreach>
+                    </if>
+                    )
+                </if>
+                <if test="viewUserId == null">
+                    <if test="deptIds != null">
+                        and b.department_id in
+                        <foreach item="item" collection="deptIds" separator="," open="(" close=")" index="">
+                            #{item, jdbcType=INTEGER}
+                        </foreach>
+                    </if>
+                </if>
+            </otherwise>
+        </choose>
+        AND b.company_id = #{companyId}
         <if test="pageStart != null">
             limit #{pageStart}, #{pageSize}
         </if>
@@ -695,22 +713,40 @@
         SELECT count(DISTINCT b.id) as count
         FROM report AS a
         JOIN user AS b ON a.creator_id=b.id
+        left join project on project.id = a.project_id
+        LEFT JOIN project_ccuser ON a.project_id = project_ccuser.project_id
         WHERE 1=1
         <if test="date != null and date != ''">
             AND a.create_date=#{date}
         </if>
-        <if test="deptIds != null">
-            AND b.department_id in
-            <foreach item="item" collection="deptIds" separator="," open="(" close=")" index="">
-                #{item, jdbcType=INTEGER}
-            </foreach>
-        </if>
-        <if test="companyId != null">
-            AND b.company_id = #{companyId}
-        </if>
-        <if test="userId != null">
-            AND b.id=#{userId}
-        </if>
+        <choose>
+            <when test="userId != null">
+                AND b.id=#{userId}
+            </when>
+            <otherwise>
+                <!--自己,担任项目经理,日报审核人,抄送人,或者自己部门的人填的日报 -->
+                <if test="viewUserId != null">
+                    and (a.creator_id = #{viewUserId} or a.project_auditor_id = #{viewUserId} or project.incharger_id = #{viewUserId}
+                    or project_ccuser.`user_id` = #{viewUserId}
+                    <if test="deptIds != null">
+                        or b.department_id in
+                        <foreach item="item" collection="deptIds" separator="," open="(" close=")" index="">
+                            #{item, jdbcType=INTEGER}
+                        </foreach>
+                    </if>
+                    )
+                </if>
+                <if test="viewUserId == null">
+                    <if test="deptIds != null">
+                        and b.department_id in
+                        <foreach item="item" collection="deptIds" separator="," open="(" close=")" index="">
+                            #{item, jdbcType=INTEGER}
+                        </foreach>
+                    </if>
+                </if>
+            </otherwise>
+        </choose>
+        AND b.company_id = #{companyId}
     </select>
 
     <!--专业待审核的报告列表-->
@@ -843,7 +879,7 @@
         WHERE r.create_date BETWEEN #{startDate} AND #{endDate} AND r.creator_id = #{userId} GROUP BY r.create_date
     </select>
     <select id="getUserDailyWorkTime" resultType="java.util.Map">
-        SELECT user.id, user.name,department.department_name as departmentName,department.corpwx_deptid as corpwxDeptId, report.create_date as createDate, sum(working_time) as workingTime,user.inactive_date as inactiveDate,user.corpwx_userid as corpwxUserId
+        SELECT user.id, user.name,department.department_name as departmentName,department.department_id as deptId,department.corpwx_deptid as corpwxDeptId, report.create_date as createDate, sum(working_time) as workingTime,user.inactive_date as inactiveDate,user.corpwx_userid as corpwxUserId
         FROM user
         left join report on user.id = report.creator_id
         left join department on department.department_id = user.department_id
@@ -1190,7 +1226,7 @@
         WHERE b.state = 1
         AND b.company_id =#{companyId}
         <if test="startDate!=null and endDate!=null">
-        AND b.create_date BETWEEN #{startDate} AND #{endDate}
+            AND b.create_date BETWEEN #{startDate} AND #{endDate}
         </if>
         GROUP BY b.project_id,b.`create_date`
         HAVING IFNULL(SUM(b.custom_data),0) > 0
@@ -1200,8 +1236,8 @@
         SELECT p.id as projectId, SUM(IFNULL(r.working_time, 0)) AS total_working_time
         FROM report r LEFT JOIN project p ON r.project_id = p.id
         WHERE p.company_id = #{companyId}
-              AND p.status in(1,2)
-              AND (p.finish_date IS NULL OR p.finish_date >= '2023-11-08')
+        AND p.status in(1,2)
+        AND (p.finish_date IS NULL OR p.finish_date >= '2023-11-08')
         <if test="projectId!=null">
             and p.id=#{projectId}
         </if>

+ 1 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/Department.java

@@ -58,7 +58,7 @@ public class Department extends Model<Department> {
     /**
      * 部门负责人id
      */
-    @TableField(value = "manager_id", updateStrategy = FieldStrategy.IGNORED)
+    @TableField(value = "manager_id")
     private String managerId;
 
     /**

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

@@ -134,6 +134,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     @Value(value = "${upload.path}")
     private String path;
 
+
+    public static final Object locker = new Object();
+    public static int times = 0;
+
     @Override
     public synchronized HttpRespMsg submitReport(Report report, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
@@ -162,6 +166,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 
         //检查当天该员工的该工序是否已经有报工
         Report todayReport = reportMapper.selectOne(new QueryWrapper<Report>().eq("creator_id", token).eq("user_procedure_team_id", report.getUserProcedureTeamId()).eq("create_date", targetDate));
+        System.out.println(LocalDateTime.now().toString()+", 读取Report 是否为Null = "+todayReport == null);
         //计算工作时长
         ProdProcedureTeam prodProcedureTeam = prodProcedureTeamMapper.selectById(report.getUserProcedureTeamId());
         //总计划任务的工序中有总工时和总工价
@@ -214,6 +219,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 
         if (todayReport == null) {
             reportMapper.insert(report);
+            log.debug("插入Report, ===id=="+report.getId()+"=="+report.getCreatorId()+" "+report.getCreateDate());
+            System.out.println(LocalDateTime.now().toString()+" 插入Report, ===id=="+report.getId()+"=="+report.getCreatorId()+" "+report.getCreateDate());
             //处理钢印号
             if (!StringUtils.isEmpty(report.getSteelNumArray())) {
                 JSONArray array = JSONArray.parseArray(report.getSteelNumArray());
@@ -248,7 +255,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             workingTime = 0.0;
         }
         planProcedureTotal.setTotalFillTime(workingTime);
-        planProcedureTotal.setTotalProgress((int)(workingTime / planProcedureTotal.getTotalWorkingHours()) * 100);
+        planProcedureTotal.setTotalProgress((int)((workingTime / planProcedureTotal.getTotalWorkingHours()) * 100));
         planProcedureTotalMapper.updateById(planProcedureTotal);
         //检查该计划下的所有工序是否都已经完成
         List<PlanProcedureTotal> planProcedureTotalList = planProcedureTotalMapper.selectList(new QueryWrapper<PlanProcedureTotal>().eq("plan_id", planProcedureTotal.getPlanId()));
@@ -4771,7 +4778,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 workingTime = curReportSumItem.getWorkingTime();
             }
             planProcedureTotal.setTotalFillTime(workingTime);
-            planProcedureTotal.setTotalProgress((int)(workingTime / planProcedureTotal.getTotalWorkingHours()) * 100);
+            planProcedureTotal.setTotalProgress((int)((workingTime / planProcedureTotal.getTotalWorkingHours()) * 100));
+            System.out.println("planProcedureTotal.getId()=="+planProcedureTotal.getId()+"--进度 2 workingTime:"+workingTime+" totalWorkingHours:"+planProcedureTotal.getTotalWorkingHours()+" totalProgress:"+planProcedureTotal.getTotalProgress());
             planProcedureTotalMapper.updateById(planProcedureTotal);
             return new HttpRespMsg();
         }
@@ -4817,7 +4825,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     workingTime = curReportSumItem.getWorkingTime();
                 }
                 planProcedureTotal.setTotalFillTime(workingTime);
-                planProcedureTotal.setTotalProgress((int)(workingTime / planProcedureTotal.getTotalWorkingHours()) * 100);
+                planProcedureTotal.setTotalProgress((int)((workingTime / planProcedureTotal.getTotalWorkingHours()) * 100));
+                System.out.println("planProcedureTotal.getId()=="+planProcedureTotal.getId()+"--进度 3 workingTime:"+workingTime+" totalWorkingHours:"+planProcedureTotal.getTotalWorkingHours()+" totalProgress:"+planProcedureTotal.getTotalProgress());
                 planProcedureTotalMapper.updateById(planProcedureTotal);
             }
         }

+ 0 - 25
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/components.d.ts

@@ -6,31 +6,6 @@ declare module 'vue' {
   export interface GlobalComponents {
     CodeEditor: typeof import('./components/CodeEditor.vue')['default']
     ComponentGroup: typeof import('./components/ComponentGroup.vue')['default']
-    ElButton: typeof import('element-plus/es')['ElButton']
-    ElCascader: typeof import('element-plus/es')['ElCascader']
-    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
-    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
-    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
-    ElDialog: typeof import('element-plus/es')['ElDialog']
-    ElDivider: typeof import('element-plus/es')['ElDivider']
-    ElForm: typeof import('element-plus/es')['ElForm']
-    ElFormItem: typeof import('element-plus/es')['ElFormItem']
-    ElImage: typeof import('element-plus/es')['ElImage']
-    ElInput: typeof import('element-plus/es')['ElInput']
-    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
-    ElOption: typeof import('element-plus/es')['ElOption']
-    ElRadio: typeof import('element-plus/es')['ElRadio']
-    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
-    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
-    ElRate: typeof import('element-plus/es')['ElRate']
-    ElSelect: typeof import('element-plus/es')['ElSelect']
-    ElSlider: typeof import('element-plus/es')['ElSlider']
-    ElSpace: typeof import('element-plus/es')['ElSpace']
-    ElSwitch: typeof import('element-plus/es')['ElSwitch']
-    ElTable: typeof import('element-plus/es')['ElTable']
-    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
-    ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
-    ElUpload: typeof import('element-plus/es')['ElUpload']
   }
 }
 

+ 25 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/components/CodeEditor.vue.d.ts

@@ -0,0 +1,25 @@
+import 'vue-prism-editor/dist/prismeditor.min.css';
+import 'prismjs/components/prism-clike';
+import 'prismjs/components/prism-json';
+import 'prismjs/themes/prism-tomorrow.css';
+declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
+    modelValue: string;
+    language?: string | undefined;
+    readonly?: boolean | undefined;
+}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
+    modelValue: string;
+    language?: string | undefined;
+    readonly?: boolean | undefined;
+}>>> & {
+    "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
+}, {}>;
+export default _default;
+declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
+declare type __VLS_TypePropsToRuntimeProps<T> = {
+    [K in keyof T]-?: {} extends Pick<T, K> ? {
+        type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
+    } : {
+        type: import('vue').PropType<T[K]>;
+        required: true;
+    };
+};

+ 22 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/components/ComponentGroup.vue.d.ts

@@ -0,0 +1,22 @@
+export declare function cloneWidget(params: any): any;
+declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
+    fields: any[];
+    title: string;
+    list: any[];
+    allList: any;
+}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
+    fields: any[];
+    title: string;
+    list: any[];
+    allList: any;
+}>>>, {}>;
+export default _default;
+declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
+declare type __VLS_TypePropsToRuntimeProps<T> = {
+    [K in keyof T]-?: {} extends Pick<T, K> ? {
+        type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
+    } : {
+        type: import('vue').PropType<T[K]>;
+        required: true;
+    };
+};

+ 680 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/config/index.d.ts

@@ -0,0 +1,680 @@
+export interface Rules {
+    trigger: string;
+    enum: string;
+    len?: number;
+    max?: number;
+    message: string;
+    min?: number;
+    pattern: string;
+    required: boolean;
+    type: string;
+}
+export interface WidgetForm {
+    list: any[];
+    config: {
+        size: '' | 'default' | 'small' | 'large';
+        hideRequiredAsterisk: boolean;
+        labelWidth: number;
+        labelPosition: string;
+    };
+}
+export declare const getWidgetForm: () => WidgetForm;
+export declare const basicComponents: ({
+    label: string;
+    type: "input";
+    options: {
+        width: string;
+        defaultValue: string;
+        placeholder: string;
+        maxlength: null;
+        prefix: string;
+        suffix: string;
+        prepend: string;
+        append: string;
+        disabled: boolean;
+        clearable: boolean;
+        readonly: boolean;
+        rules: Rules;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "password";
+    options: {
+        width: string;
+        defaultValue: string;
+        placeholder: string;
+        maxlength: null;
+        prefix: string;
+        suffix: string;
+        prepend: string;
+        append: string;
+        showPassword: boolean;
+        disabled: boolean;
+        clearable: boolean;
+        readonly: boolean;
+        rules: Rules;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "textarea";
+    options: {
+        width: string;
+        defaultValue: string;
+        placeholder: string;
+        maxlength: null;
+        rows: number;
+        autosize: boolean;
+        showWordLimit: boolean;
+        disabled: boolean;
+        clearable: boolean;
+        readonly: boolean;
+        rules: Rules;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        showPassword?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "number";
+    options: {
+        width: string;
+        defaultValue: number;
+        min: number;
+        max: number;
+        step: number;
+        disabled: boolean;
+        rules: Rules;
+        placeholder?: undefined;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        clearable?: undefined;
+        readonly?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "radio";
+    options: {
+        defaultValue: string;
+        width: string;
+        inline: boolean;
+        remote: boolean;
+        showLabel: boolean;
+        remoteFunc: string;
+        options: {
+            value: string;
+            label: string;
+        }[];
+        remoteOptions: never[];
+        props: {
+            value: string;
+            label: string;
+        };
+        disabled: boolean;
+        rules: Rules;
+        placeholder?: undefined;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        clearable?: undefined;
+        readonly?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "checkbox";
+    options: {
+        defaultValue: never[];
+        width: string;
+        inline: boolean;
+        remote: boolean;
+        showLabel: boolean;
+        remoteFunc: string;
+        options: {
+            label: string;
+            value: string;
+        }[];
+        remoteOptions: never[];
+        props: {
+            value: string;
+            label: string;
+        };
+        disabled: boolean;
+        rules: Rules;
+        placeholder?: undefined;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        clearable?: undefined;
+        readonly?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "time";
+    options: {
+        defaultValue: string;
+        width: string;
+        placeholder: string;
+        format: string;
+        valueFormat: string;
+        readonly: boolean;
+        editable: boolean;
+        clearable: boolean;
+        disabled: boolean;
+        rules: Rules;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "date";
+    options: {
+        defaultValue: string;
+        width: string;
+        placeholder: string;
+        format: string;
+        readonly: boolean;
+        editable: boolean;
+        clearable: boolean;
+        disabled: boolean;
+        rules: Rules;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        valueFormat?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "rate";
+    options: {
+        defaultValue: number;
+        max: number;
+        allowHalf: boolean;
+        disabled: boolean;
+        rules: Rules;
+        width?: undefined;
+        placeholder?: undefined;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        clearable?: undefined;
+        readonly?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "select";
+    options: {
+        defaultValue: string;
+        width: string;
+        multiple: boolean;
+        placeholder: string;
+        remote: boolean;
+        showLabel: boolean;
+        filterable: boolean;
+        clearable: boolean;
+        disabled: boolean;
+        props: {
+            label: string;
+            value: string;
+        };
+        options: {
+            label: string;
+            value: string;
+        }[];
+        remoteOptions: never[];
+        remoteFunc: string;
+        rules: Rules;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        readonly?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "switch";
+    options: {
+        defaultValue: boolean;
+        disabled: boolean;
+        activeText: string;
+        inactiveText: string;
+        rules: Rules;
+        width?: undefined;
+        placeholder?: undefined;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        clearable?: undefined;
+        readonly?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        range?: undefined;
+    };
+} | {
+    label: string;
+    type: "slider";
+    options: {
+        defaultValue: number;
+        width: string;
+        min: number;
+        max: number;
+        step: number;
+        disabled: boolean;
+        range: boolean;
+        rules: Rules;
+        placeholder?: undefined;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        clearable?: undefined;
+        readonly?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+    };
+} | {
+    label: string;
+    type: "text";
+    options: {
+        defaultValue: string;
+        width?: undefined;
+        placeholder?: undefined;
+        maxlength?: undefined;
+        prefix?: undefined;
+        suffix?: undefined;
+        prepend?: undefined;
+        append?: undefined;
+        disabled?: undefined;
+        clearable?: undefined;
+        readonly?: undefined;
+        rules?: undefined;
+        showPassword?: undefined;
+        rows?: undefined;
+        autosize?: undefined;
+        showWordLimit?: undefined;
+        min?: undefined;
+        max?: undefined;
+        step?: undefined;
+        inline?: undefined;
+        remote?: undefined;
+        showLabel?: undefined;
+        remoteFunc?: undefined;
+        options?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        format?: undefined;
+        valueFormat?: undefined;
+        editable?: undefined;
+        allowHalf?: undefined;
+        multiple?: undefined;
+        filterable?: undefined;
+        activeText?: undefined;
+        inactiveText?: undefined;
+        range?: undefined;
+    };
+})[];
+export declare const basicFields: ("number" | "input" | "select" | "textarea" | "time" | "switch" | "text" | "password" | "radio" | "checkbox" | "date" | "rate" | "slider")[];
+export declare const advanceComponents: ({
+    label: string;
+    type: "img-upload";
+    options: {
+        defaultValue: never[];
+        name: string;
+        action: string;
+        method: string;
+        listType: string;
+        accept: string;
+        limit: number;
+        multiple: boolean;
+        disabled: boolean;
+        rules: Rules;
+        width?: undefined;
+        placeholder?: undefined;
+        clearable?: undefined;
+        filterable?: undefined;
+        remote?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        remoteFunc?: undefined;
+    };
+    labelWidth?: undefined;
+} | {
+    label: string;
+    type: "download";
+    labelWidth: string;
+    options: {
+        defaultValue: string;
+        name: string;
+        action?: undefined;
+        method?: undefined;
+        listType?: undefined;
+        accept?: undefined;
+        limit?: undefined;
+        multiple?: undefined;
+        disabled?: undefined;
+        rules?: undefined;
+        width?: undefined;
+        placeholder?: undefined;
+        clearable?: undefined;
+        filterable?: undefined;
+        remote?: undefined;
+        remoteOptions?: undefined;
+        props?: undefined;
+        remoteFunc?: undefined;
+    };
+} | {
+    label: string;
+    type: "cascader";
+    options: {
+        defaultValue: never[];
+        width: string;
+        placeholder: string;
+        disabled: boolean;
+        clearable: boolean;
+        filterable: boolean;
+        remote: boolean;
+        remoteOptions: never[];
+        props: {
+            label: string;
+            value: string;
+            children: string;
+        };
+        remoteFunc: string;
+        rules: Rules;
+        name?: undefined;
+        action?: undefined;
+        method?: undefined;
+        listType?: undefined;
+        accept?: undefined;
+        limit?: undefined;
+        multiple?: undefined;
+    };
+    labelWidth?: undefined;
+})[];
+export declare const advanceFields: ("img-upload" | "download" | "cascader")[];
+export declare const layoutComponents: ({
+    label: string;
+    type: string;
+    columns: {
+        span: number;
+        list: never[];
+    }[];
+    options: {
+        gutter: number;
+        align: string;
+        defaultValue?: undefined;
+        disabled?: undefined;
+        size?: undefined;
+    };
+} | {
+    label: string;
+    type: string;
+    columns: {
+        label: string;
+        prop: string;
+    }[];
+    options: {
+        defaultValue: never[];
+        disabled: boolean;
+        size: string;
+        align: string;
+        gutter?: undefined;
+    };
+} | {
+    label: string;
+    type: string;
+    options: {
+        gutter?: undefined;
+        align?: undefined;
+        defaultValue?: undefined;
+        disabled?: undefined;
+        size?: undefined;
+    };
+    columns?: undefined;
+})[];
+export declare const layoutFields: string[];

+ 79 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/DesignForm.vue.d.ts

@@ -0,0 +1,79 @@
+import type { PropType } from 'vue';
+import type { WidgetForm } from '@/config';
+declare const _default: import("vue").DefineComponent<{
+    preview: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    generateJson: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    clearable: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    basicFieldsList: {
+        type: PropType<("number" | "input" | "select" | "textarea" | "time" | "switch" | "text" | "password" | "radio" | "checkbox" | "date" | "rate" | "slider")[]>;
+        default: () => ("number" | "input" | "select" | "textarea" | "time" | "switch" | "text" | "password" | "radio" | "checkbox" | "date" | "rate" | "slider")[];
+    };
+    advanceFieldsList: {
+        type: PropType<("img-upload" | "download" | "cascader")[]>;
+        default: () => ("img-upload" | "download" | "cascader")[];
+    };
+    layoutFieldsList: {
+        type: PropType<string[]>;
+        default: () => string[];
+    };
+    request: {
+        type: FunctionConstructor;
+    };
+}, {
+    getJson: () => {
+        list: any[];
+        config: {
+            size: "" | "small" | "default" | "large";
+            hideRequiredAsterisk: boolean;
+            labelWidth: number;
+            labelPosition: string;
+        };
+    };
+    setJson: (json: WidgetForm) => void;
+    clear: () => void;
+}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
+    preview: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    generateJson: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    clearable: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    basicFieldsList: {
+        type: PropType<("number" | "input" | "select" | "textarea" | "time" | "switch" | "text" | "password" | "radio" | "checkbox" | "date" | "rate" | "slider")[]>;
+        default: () => ("number" | "input" | "select" | "textarea" | "time" | "switch" | "text" | "password" | "radio" | "checkbox" | "date" | "rate" | "slider")[];
+    };
+    advanceFieldsList: {
+        type: PropType<("img-upload" | "download" | "cascader")[]>;
+        default: () => ("img-upload" | "download" | "cascader")[];
+    };
+    layoutFieldsList: {
+        type: PropType<string[]>;
+        default: () => string[];
+    };
+    request: {
+        type: FunctionConstructor;
+    };
+}>>, {
+    preview: boolean;
+    generateJson: boolean;
+    clearable: boolean;
+    basicFieldsList: ("number" | "input" | "select" | "textarea" | "time" | "switch" | "text" | "password" | "radio" | "checkbox" | "date" | "rate" | "slider")[];
+    advanceFieldsList: ("img-upload" | "download" | "cascader")[];
+    layoutFieldsList: string[];
+}>;
+export default _default;

+ 16 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/FormConfig.vue.d.ts

@@ -0,0 +1,16 @@
+import type { WidgetForm } from '@/config';
+declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
+    config: WidgetForm['config'];
+}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
+    config: WidgetForm['config'];
+}>>>, {}>;
+export default _default;
+declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
+declare type __VLS_TypePropsToRuntimeProps<T> = {
+    [K in keyof T]-?: {} extends Pick<T, K> ? {
+        type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
+    } : {
+        type: import('vue').PropType<T[K]>;
+        required: true;
+    };
+};

+ 20 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/WidgetConfig.vue.d.ts

@@ -0,0 +1,20 @@
+declare const _default: import("vue").DefineComponent<{
+    select: {
+        type: ObjectConstructor;
+    };
+}, {
+    data: any;
+    hasKey: (key: string) => boolean;
+    handleInsertColumn: () => void;
+    handleInsertOption: () => void;
+    handleOptionsRemove: (index: number) => void;
+    handleSliderModeChange: (checked: string | number | boolean) => void;
+    handleSelectModeChange: (val: string | number | boolean) => void;
+}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:select"[], "update:select", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
+    select: {
+        type: ObjectConstructor;
+    };
+}>> & {
+    "onUpdate:select"?: ((...args: any[]) => any) | undefined;
+}, {}>;
+export default _default;

+ 22 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/WidgetForm.vue.d.ts

@@ -0,0 +1,22 @@
+import type { WidgetForm } from '@/config';
+declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
+    list: any;
+    config: WidgetForm['config'];
+    selectWidget: any;
+}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:selectWidget"[], "update:selectWidget", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
+    list: any;
+    config: WidgetForm['config'];
+    selectWidget: any;
+}>>> & {
+    "onUpdate:selectWidget"?: ((...args: any[]) => any) | undefined;
+}, {}>;
+export default _default;
+declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
+declare type __VLS_TypePropsToRuntimeProps<T> = {
+    [K in keyof T]-?: {} extends Pick<T, K> ? {
+        type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
+    } : {
+        type: import('vue').PropType<T[K]>;
+        required: true;
+    };
+};

+ 25 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/design/WidgetFormItem.vue.d.ts

@@ -0,0 +1,25 @@
+declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimeProps<{
+    list: any;
+    element: any;
+    index: number;
+    selectWidget: any;
+}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("itemClick" | "delete" | "update:selectWidget")[], "itemClick" | "delete" | "update:selectWidget", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
+    list: any;
+    element: any;
+    index: number;
+    selectWidget: any;
+}>>> & {
+    onItemClick?: ((...args: any[]) => any) | undefined;
+    onDelete?: ((...args: any[]) => any) | undefined;
+    "onUpdate:selectWidget"?: ((...args: any[]) => any) | undefined;
+}, {}>;
+export default _default;
+declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
+declare type __VLS_TypePropsToRuntimeProps<T> = {
+    [K in keyof T]-?: {} extends Pick<T, K> ? {
+        type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
+    } : {
+        type: import('vue').PropType<T[K]>;
+        required: true;
+    };
+};

+ 43 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateForm.vue.d.ts

@@ -0,0 +1,43 @@
+declare const _default: import("vue").DefineComponent<{
+    data: {
+        type: ObjectConstructor;
+        default: import("@/config").WidgetForm;
+    };
+    value: {
+        type: ObjectConstructor;
+    };
+    disabled: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    request: {
+        type: FunctionConstructor;
+    };
+}, {
+    getData: () => Promise<unknown>;
+    reset: () => void;
+    generateForm: import("vue").Ref<any>;
+    model: import("vue").Ref<any>;
+    updatedModel: import("vue").Ref<any>;
+    rules: import("vue").Ref<any>;
+    widgetForm: import("vue").Ref<any>;
+}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
+    data: {
+        type: ObjectConstructor;
+        default: import("@/config").WidgetForm;
+    };
+    value: {
+        type: ObjectConstructor;
+    };
+    disabled: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    request: {
+        type: FunctionConstructor;
+    };
+}>>, {
+    data: Record<string, any>;
+    disabled: boolean;
+}>;
+export default _default;

+ 0 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateFormItem.vue.d.ts


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor