Prechádzať zdrojové kódy

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

Guo1B0 1 rok pred
rodič
commit
20843559e9
78 zmenil súbory, kde vykonal 2033 pridanie a 711 odobranie
  1. 6 0
      fhKeeper/formulahousekeeper/customerBuler-crm/package-lock.json
  2. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/package.json
  3. 63 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/App.vue
  4. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/defaultCover.png
  5. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/main.ts
  6. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/api.ts
  7. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/index.vue
  8. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/api.ts
  9. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  10. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/api.ts
  11. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/index.vue
  12. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/corpreport/api.ts
  13. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/corpreport/index.vue
  14. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/api.ts
  15. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/index.vue
  16. 144 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/header/header.vue
  17. 89 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home copy.vue
  18. 24 78
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue
  19. 24 28
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  20. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/api.ts
  21. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/index.vue
  22. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/api.ts
  23. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue
  24. 7 24
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/register.vue
  25. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/api.ts
  26. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/dictionary/api.ts
  27. 10 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/dictionary/index.vue
  28. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/index.vue
  29. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/role/api.ts
  30. 12 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/role/index.vue
  31. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/api.ts
  32. 81 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/index.vue
  33. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/api.ts
  34. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/index.vue
  35. 17 5
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue
  36. 34 17
      fhKeeper/formulahousekeeper/customerBuler-crm/src/router/index.ts
  37. 17 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/store/Store.d.ts
  38. 52 20
      fhKeeper/formulahousekeeper/customerBuler-crm/src/store/index.ts
  39. 3 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/styles/global.scss
  40. 6 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/type.d.ts
  41. 25 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ContactsController.java
  42. 13 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Contacts.java
  43. 13 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/vo/ContactsVo.java
  44. 8 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ContactsMapper.java
  45. 7 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ContactsService.java
  46. 68 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContactsServiceImpl.java
  47. 7 7
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  48. 30 1
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ContactsMapper.xml
  49. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  50. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportDeleteController.java
  51. 4 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java
  52. 19 23
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WxCorpInfoController.java
  53. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Department.java
  54. 347 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportDelete.java
  55. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  56. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportDeleteMapper.java
  57. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/TaskMapper.java
  58. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  59. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportDeleteService.java
  60. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/TaskService.java
  61. 5 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  62. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportDeleteServiceImpl.java
  63. 57 29
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  64. 4 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  65. 28 19
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  66. 21 38
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  67. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  68. 66 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportDeleteMapper.xml
  69. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  70. 11 4
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskMapper.xml
  71. 1 0
      fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json
  72. 1 0
      fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json
  73. 3 2
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  74. 509 385
      fhKeeper/formulahousekeeper/timesheet/src/views/project/summary.vue
  75. 1 0
      fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue
  76. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/team/index.vue
  77. 0 2
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/login/index.vue
  78. 6 1
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/task/editask.vue

+ 6 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/package-lock.json

@@ -10,6 +10,7 @@
       "dependencies": {
         "@element-plus/icons-vue": "^2.3.1",
         "@zmjs/form-design": "^0.1.16",
+        "animate.css": "^4.1.1",
         "axios": "^1.6.7",
         "echarts": "^5.5.0",
         "element-plus": "^2.5.6",
@@ -1138,6 +1139,11 @@
       "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.7.tgz",
       "integrity": "sha512-ziv35kaYELFw4suWlotz/Xsl1/1LhWAbwFoD3zIgCgP9gXGECEsAM4GhiB0T0xZdmQjyv6hmAzO280g0+n4vGw=="
     },
+    "node_modules/animate.css": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz",
+      "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ=="
+    },
     "node_modules/ansi-regex": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/package.json

@@ -12,6 +12,7 @@
   "dependencies": {
     "@element-plus/icons-vue": "^2.3.1",
     "@zmjs/form-design": "^0.1.16",
+    "animate.css": "^4.1.1",
     "axios": "^1.6.7",
     "echarts": "^5.5.0",
     "element-plus": "^2.5.6",

+ 63 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/App.vue

@@ -1,14 +1,55 @@
 <template>
-  <router-view></router-view>
+  <!-- <router-view></router-view> -->
+  <router-view v-slot="{ Component }">
+    <transition name="ranimate">
+      <component :is="Component" />
+    </transition>
+  </router-view>
 </template>
 
 <script setup lang="ts">
+import { provide } from 'vue'
 import { useStore } from '@/store/index'
+import { ElNotification, NotificationParamsTyped } from 'element-plus'
 const { setAsyncRoutesMark } = useStore()
 window.addEventListener('beforeunload', () => beforeunloadFn())
 const beforeunloadFn = (() => {
   setAsyncRoutesMark(false)
 })
+
+provide<GlobalPopup>('globalPopup', {
+  showSuccess: (message?: string) => {
+    notificationTiop({
+      message: message || '成功',
+      type: 'success',
+      title: "提示",
+      duration: 2000
+    })
+  }, //!SECTION 成功
+  showError: (message?: string) => notificationTiop({
+    message: message || '失败',
+    type: 'error',
+    title: "提示",
+    duration: 2000
+  }), //!SECTION 失败
+  showWarning: (message: string) => notificationTiop({
+    message,
+    type: 'warning',
+    title: "提示",
+    duration: 2000
+  }), //!SECTION 警告
+  showInfo: (message: string) => notificationTiop({
+    message,
+    type: 'info',
+    title: "提示",
+    duration: 2000
+  }), //!SECTION 文本
+})
+
+const notificationTiop = (options: NotificationParamsTyped) => {
+  ElNotification(options)
+}
+
 </script>
 
 <style>
@@ -18,6 +59,26 @@ body,
 .layouts {
   width: 100%;
   height: 100%;
-  overflow: hidden;
+  /* overflow: hidden; */
+  min-width: 650px;
+}
+* {
+  font-family: '微软雅黑';
+}
+/* home 页面的动画 */
+.router_animate-enter-active {
+    animation: slideInLeft 0.5s;
+}
+.router_animate-leave-active {
+    animation: slideOutLeft 0s;
+}
+
+/* app 路由动画 */
+.ranimate-enter-active {
+  animation: fadeIn 1s;
+}
+ 
+.ranimate-leave-active {
+  animation: fadeIn 0s;
 }
 </style>

BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/defaultCover.png


+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/main.ts

@@ -3,6 +3,7 @@ import { createPinia } from 'pinia'
 import ElementPlus from 'element-plus'
 import "./TailWindCss/index.css";
 import 'element-plus/dist/index.css'
+import 'animate.css/animate.min.css' //引入动画
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
 import App from './App.vue'

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


+ 11 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    analysis
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

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


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

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    business
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

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


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

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    contacts
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

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


+ 11 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/corpreport/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    corpreport
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

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


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

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    customer
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

+ 144 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/header/header.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="trademark mr-8 flex items-center text-white">
+    <img :src="loginLogin" class="w-10 h-10 mr-4" />
+    <div class="text-nowrap">客户管家</div>
+  </div>
+  <div class=" flex flex-row justify-start items-center text-white flex-1 parentDiv" ref="parentDiv">
+    <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" @click="setCurrentRouter(routerItem)" class="text-nowrap">
+        {{ routerItem.name }}
+      </div>
+      <div v-else class="flex justify-center items-center">
+        <el-dropdown>
+          <div class="text-white w-full h-full headerText">
+            {{ routerItem.name }}
+            <el-icon class="el-icon--right">
+              <arrow-down />
+            </el-icon>
+          </div>
+          <template #dropdown>
+            <el-dropdown-menu>
+              <el-dropdown-item v-for="child in routerItem.children" :key="child.path" @click="setCurrentRouter(child)">
+                {{ child.name }}
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </template>
+        </el-dropdown>
+      </div>
+    </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()">
+    </div>
+    <el-icon :size="26" class="ml-4 cursor-pointer">
+      <Grid />
+    </el-icon>
+  </div>
+</template>
+  
+<script lang="ts" setup>
+import { onMounted, ref, watchEffect } from 'vue';
+import { RouteRecordRaw, useRouter } 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 router = useRouter();
+const routerList = ref<RouteRecordRaw[]>([]);
+const activeRouter = ref<RouteRecordRaw>();
+
+const visibleItems = ref<number[]>([]);
+const parentDiv = ref<HTMLElement | null>(null);
+
+const updateVisibleItems = () => {
+  const parentWidth = parentDiv.value?.offsetWidth || 10;
+  const canvas = document.createElement('canvas');
+  const context = canvas.getContext('2d');
+
+  let textWidthList: any = [] // 所有文字的宽度
+  let totalWidth = 0;
+  let temporaryIndex: any = []
+  
+  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) {
+      break;
+    }
+    totalWidth += textWidthList[i];
+    temporaryIndex.push(+i);
+  }
+
+  // 替换最后一个元素
+  let lastIndex = textWidthList.length - 1;
+  temporaryIndex.splice(temporaryIndex.length -1, 1, lastIndex)
+
+  visibleItems.value = temporaryIndex;
+  //console.log(visibleItems.value)
+};
+
+const setCurrentRouter = (item: RouteRecordRaw) => {
+  activeRouter.value = item;
+  if (item.children && item.children.length > 0) {
+    router.push({ path: item.children[0].path });
+    return
+  }
+  router.push({ path: item.path });
+};
+const logout = () => {
+  clearStore();
+  router.push({ path: '/login' });
+};
+onMounted(() => {
+  routerList.value = routers;
+  activeRouter.value = routerList.value.find((item) => item.path === router.currentRoute.value.path);
+  //console.log("routerList", routerList);
+
+  window.addEventListener('resize', updateVisibleItems);
+  setTimeout(() => {
+    updateVisibleItems();
+  }, 500);
+})
+watchEffect(() => {
+  updateVisibleItems();
+});
+</script>
+  
+<style scoped lang="scss">
+.trademark {
+  font-size: 20px;
+}
+.multipleyHeader {
+  height: 96%;
+  display: flex;
+  align-items: center;
+  text-wrap: nowrap;
+
+  .headerText {
+    font-size: 16px;
+  }
+}
+.parentBox {
+  // max-width: 80%;
+  // min-width: 300px;
+  flex: 1;
+  overflow: hidden;
+}
+.header-right {
+  width: 135px;
+}
+.parentDiv {
+  width: 50%;
+}
+</style>

+ 89 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home copy.vue

@@ -0,0 +1,89 @@
+<template>
+  <div class="w-full h-full">
+    <el-container>
+      <el-header class="bg-sky-800 leading-10 flex flex-row justify-between">
+        <div class=" flex flex-row justify-start items-center text-white flex-1">
+          <div v-for="routerItem in routerList"
+            :class="`border-b-2 border-transparent hover:border-white p-2 mr-4 multipleyHeader ${activeRouter?.path === routerItem.path ? 'border-white' : ''}`"
+            :key="routerItem.path">
+            <div v-if="!routerItem.children" @click="setCurrentRouter(routerItem)">
+              {{ routerItem.name }}
+            </div>
+            <div v-else class="flex justify-center items-center">
+              <el-dropdown>
+                <div class="text-white w-full h-full headerText">
+                  {{ routerItem.name }}
+                  <el-icon class="el-icon--right">
+                    <arrow-down />
+                  </el-icon>
+                </div>
+                <template #dropdown>
+                  <el-dropdown-menu>
+                    <el-dropdown-item v-for="child in routerItem.children"
+                      :key="child.path"
+                      @click="setCurrentRouter(child)">
+                      {{ child.name }}
+                    </el-dropdown-item>
+                  </el-dropdown-menu>
+                </template>
+              </el-dropdown>
+            </div>
+          </div>
+        </div>
+        <div class="flex flex-row justify-start items-center text-white">
+          <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()">
+          </div>
+          <el-icon :size="26" class="ml-4 cursor-pointer">
+            <Grid />
+          </el-icon>
+        </div>
+      </el-header>
+      <el-main>
+        <router-view />
+      </el-main>
+    </el-container>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { onMounted, ref } from 'vue';
+import { RouteRecordRaw, useRouter } from 'vue-router';
+import { useStore } from "@/store"
+import defaultCover from "@/assets/defaultCover.png";
+const { getRoutersList } = useStore()
+const router = useRouter();
+const routerList = ref<RouteRecordRaw[]>([]);
+const activeRouter = ref<RouteRecordRaw>();
+const setCurrentRouter = (item: RouteRecordRaw) => {
+  activeRouter.value = item;
+  if (item.children && item.children.length > 0) {
+    router.push({ path: item.children[0].path });
+    return
+  }
+  router.push({ path: item.path });
+};
+const logout = () => {
+  router.push({ path: '/login' });
+};
+onMounted(() => {
+  routerList.value = getRoutersList;
+  activeRouter.value = routerList.value.find((item) => item.path === router.currentRoute.value.path);
+  //console.log("routerList", routerList);
+})
+
+</script>
+
+<style scoped lang="scss">
+.multipleyHeader {
+  height: 96%;
+  display: flex;
+  align-items: center;
+  .headerText {
+    font-size: 16px;
+  }
+}
+</style>

+ 24 - 78
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue

@@ -1,86 +1,32 @@
 <template>
-    <div class="common-layout layouts">
-        <el-container class="flex flex-col layouts">
-            <!-- 头部 -->
-            <el-header></el-header>
-            <!-- 左侧菜单 -->
-            <el-container class="flex-1 layouts">
-                <el-aside class="home-el-aside" width="220px">
-                    <el-menu default-active="1" class="el-menu-vertical-demo">
-                        <el-menu-item :index="(index + 1) + ''" v-for="(item, index) in 10" :key="index">
-                            <div class="relativeElem">
-                                <el-icon>
-                                    <setting />
-                                </el-icon>
-                                <span>第{{ index + 1 }}个</span>
-                            </div>
-                        </el-menu-item>
-
-                        <el-sub-menu index="11">
-                            <template #title>
-                                <el-icon>
-                                    <location />
-                                </el-icon>
-                                <span>第十一个</span>
-                            </template>
-                            <el-menu-item :index="'11'">
-                                <div class="relativeElem">
-                                    <el-icon><icon-menu /></el-icon>
-                                    <span>第11-1个</span>
-                                </div>
-                            </el-menu-item>
-                        </el-sub-menu>
-                    </el-menu>
-                </el-aside>
-                <!-- 主体 -->
-                <el-main>
-                    <router-view></router-view>
-                </el-main>
-            </el-container>
-        </el-container>
-    </div>
+  <div class="w-full h-full">
+    <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" />
+          </transition>
+        </router-view>
+      </el-main>
+    </el-container>
+  </div>
 </template>
+
 <script lang="ts" setup>
+import Header from '@/pages/header/header.vue'
+import { onMounted, ref } from 'vue';
 
 </script>
-<style scoped lang="scss">
-.common-layout {
-    .relativeElem {
-        position: relative;
-        z-index: 2;
-        display: flex;
-        align-items: center;
-    }
-
-    .el-header {
-        background: $darkBlue;
-    }
 
-    .el-menu-vertical-demo {
-        height: 100%;
-        background: $ashen;
-
-        .is-active {
-            position: relative;
-            color: $modena;
-
-            &:before {
-                content: '';
-                position: absolute;
-                right: 0;
-                top: 8px;
-                width: 95%;
-                height: 40px;
-                background: $backColor;
-                border-top-left-radius: 20px;
-                border-bottom-left-radius: 20px;
-            }
-        }
-    }
-
-    .el-main {
-        padding: 0 20px;
-        background: $backColor;
-    }
+<style scoped lang="scss">
+.el-main {
+  padding: 0;
+  flex: 1;
+  overflow: hidden;
+  background: $backColor;
 }
 </style>

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

@@ -40,17 +40,18 @@
 </template>
 
 <script lang="ts" setup>
-import { reactive, ref } from "vue";
+import { reactive, ref, inject } from "vue";
 import { useRouter } from "vue-router";
 import loginLogo from "@/assets/login/login_logo.png";
 import qiyeweixin from "@/assets/login/qiyeweixin.png";
 import { UserFilled, Lock } from '@element-plus/icons-vue'
-import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
+import { type FormInstance, type FormRules } from 'element-plus'
 import { useStore } from '@/store/index'
 import { post } from "@/utils/request";
 import { LOGIN } from "./api";
-const { setRouters } = useStore()
+const { setRouters, setValue } = useStore()
 const router = useRouter();
+const globalPopup = inject<GlobalPopup>('globalPopup')
 const ruleFormRef = ref<FormInstance>();
 const ruleForm = ref({
   username: "",
@@ -72,43 +73,38 @@ const login = (formEl: FormInstance | undefined) => {
       return false;
     }
     loginLoading.value = true;
-    console.log(ruleForm.value);
+    //console.log(ruleForm.value);
     post(LOGIN, { ...ruleForm.value }).then(res => {
-      console.log(res);
+      //console.log(res);
       if(res.code == 'error') {
-        ElMessage.error({
-          message: "登录失败",
-          type: "error",
-          duration: 2000,
-        })
+        globalPopup?.showError(res.msg)
         loginLoading.value = false;
         return
       }
-      ElMessage.success({
-        message: "登录成功",
-        type: "success",
-        duration: 2000,
-      })
+      globalPopup?.showSuccess('登录成功')
+      setValue(res.data, 'userInfo')
+      setValue(res.data?.moduleList, 'routers')
       setTimeout(() => {
         loginLoading.value = false;
+        router.push(res.data?.moduleList[0].path);
       }, 1000)
-      // loginLoading.value = false;
+      loginLoading.value = false;
     }).catch(err => {
-      console.log(err);
+      //console.log(err)
       loginLoading.value = false;
     })
     return
-    let newRouter = [
-      {
-        path: '/thread',
-        name: 'thread'
-      }
-    ]
-    setRouters(newRouter)
-    setTimeout(() => {
-      loginLoading.value = false;
-      router.push(newRouter[0].path);
-    }, 1000);
+    // let newRouter = [
+    //   {
+    //     path: '/thread',
+    //     name: 'thread'
+    //   }
+    // ]
+    // setRouters(newRouter)
+    // setTimeout(() => {
+    //   loginLoading.value = false;
+    //   router.push(newRouter[0].path);
+    // }, 1000);
   })
 
 };

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


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

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    order
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

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


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

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    product
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

+ 7 - 24
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/register.vue

@@ -47,13 +47,14 @@
 </template>
 
 <script lang="ts" setup>
-import { reactive, ref } from "vue";
+import { inject, reactive, ref } from "vue";
 import { useRouter, useRoute } from "vue-router";
 import { HomeFilled, UserFilled, Lock, Iphone, Tickets } from '@element-plus/icons-vue'
 import { ElNotification, ElMessage, type FormInstance, type FormRules } from 'element-plus'
 import { isValueEmpty } from "@/utils/tools";
 import { post } from "@/utils/request";
 import { REGISTER, SENDVCODE } from "./api";
+const globalPopup = inject<GlobalPopup>('globalPopup')
 const router = useRouter();
 const route = useRoute();
 const ruleFormRef = ref<FormInstance>();
@@ -152,35 +153,17 @@ const register = (formEl: FormInstance | undefined) => {
         ...route.query
       }
     }
-    // console.log(params);
     post(REGISTER, params).then(res => {
       if (res.code == "ok") {
-        ElNotification.success({
-          title: "提示",
-          message: "注册成功",
-          type: "success",
-          duration:3000,
-          onClose: () => {
-            registerLoading.value = false;
-            router.back()
-          }
-        })
+        globalPopup?.showSuccess("注册成功")
+        registerLoading.value = false;
+        router.back()
       } else {
-        ElNotification.error({
-          title: "提示",
-          message: res.message || res.msg,
-          type: "success",
-          duration: 3000,
-        })
+        globalPopup?.showError(res.message || res.msg || "注册失败")
         registerLoading.value = false;
       }
     }).catch(err => {
-      ElNotification.error({
-        title: "提示",
-        message: err.message || err.msg,
-        type: "success",
-        duration: 3000,
-      })
+      globalPopup?.showError(err.message || err.msg || "注册失败")
       registerLoading.value = false;
     })
 

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


+ 0 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/dictionary/api.ts


+ 10 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/dictionary/index.vue

@@ -0,0 +1,10 @@
+<template>
+<div>
+  系统字典
+</div>
+</template>
+<script lang="ts" setup>
+
+</script>
+<style lang="scss" scoped>
+</style>

+ 11 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    <router-view></router-view>
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

+ 0 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/role/api.ts


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

@@ -0,0 +1,12 @@
+<template>
+  <div>
+    角色权限
+    <div>左右</div>
+    <div></div>
+  </div>
+</template>
+<script lang="ts" setup>
+
+</script>
+<style lang="scss" scoped>
+</style>

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

@@ -0,0 +1 @@
+export const MDO = "/tasks";

+ 81 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/tasks/index.vue

@@ -0,0 +1,81 @@
+<template>
+  <div class="h-full flex">
+    <div class="p-5 w-80 pr-0">
+      <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col">
+        <div class="flex-1 p-3 overflow-y-auto">
+          <el-form :model="ruleForm">
+            <el-form-item label="任务名称:" label-width="7em" prop="taskName">
+              <el-input v-model="ruleForm.taskName" placeholder="请输入" />
+            </el-form-item>
+            <el-form-item label="客户名称:" label-width="7em" prop="customerName">
+              <el-input v-model="ruleForm.customerName" placeholder="请输入" />
+            </el-form-item>
+            <el-form-item label="联系人电话:" label-width="7em" prop="tel">
+              <el-input v-model="ruleForm.tel" placeholder="请输入" />
+            </el-form-item>
+            <el-form-item label="优先级" label-width="7em" prop="priority">
+              <el-select v-model="ruleForm.priority" placeholder="请选择">
+                <el-option label="全部" value="0" />
+                <el-option label="高" value="1" />
+                <el-option label="中" value="2" />
+                <el-option label="低" value="3" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="任务状态" label-width="7em" prop="status">
+              <el-select v-model="ruleForm.status" placeholder="请选择">
+                <el-option label="全部" value="0" />
+                <el-option label="未开始" value="1" />
+                <el-option label="进行中" value="2" />
+                <el-option label="已完成" value="3" />
+                <el-option label="超时" value="4" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="开始日期" label-width="7em" prop="startDate">
+              <el-date-picker v-model="ruleForm.startDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" />
+            </el-form-item>
+            <el-form-item label="结束日期" label-width="7em" prop="endDate">
+              <el-date-picker v-model="ruleForm.endDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" />
+            </el-form-item>
+          </el-form>
+        </div>
+        <div class="w-full flex p-3 shadow-[0_-3px_5px_0px_rgba(0,0,0,0.2)]">
+          <El-button class="w-full" @click="reset()">重置</El-Button>
+          <El-button type="primary" class="w-full" @click="search()">搜索</El-Button>
+        </div>
+      </div>
+    </div>
+    <div class="flex-1 p-5">
+      <div class="bg-white w-full h-full p-3 shadow-md rounded-md">222</div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { onBeforeMount, onMounted, ref } from 'vue';
+import { useStore } from '@/store';
+import { MDO } from './api';
+const { getFunctionList } = useStore()
+const config = ref<any>([])
+const defaultForm = {
+  taskName: '',
+  customerName: '',
+  tel: '',
+  priority: '0',
+  status: '0',
+  startDate: '',
+  endDate: '',
+}
+const ruleForm = ref<any>()
+const reset = () => {
+  ruleForm.value = defaultForm;
+}
+const search = () => {
+  //console.log("ruleForm", ruleForm.value);
+}
+onBeforeMount(() => {
+  config.value = getFunctionList(MDO);
+  ruleForm.value = defaultForm;
+})
+</script>
+
+<style lang="scss" scoped></style>

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


+ 11 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    团队
+  </div>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped></style>

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

@@ -1,9 +1,21 @@
 <template>
-<div id="" class="h100">
-    线索文件
-</div>
+  <div class="bg-gray-200 h-full flex">
+    <div class="p-5 w-80 pr-0">
+      <div class="bg-white w-full h-full p-3 shadow-md rounded-md">
+        线索管理
+      </div>
+    </div>
+    <div class="flex-1 bg-gray-200 p-5">
+      <div class="bg-white w-full h-full p-3 shadow-md rounded-md">222</div>
+    </div>
+  </div>
 </template>
+
+
 <script setup lang="ts">
+
 </script>
-<style scoped lang="scss">
-</style>
+
+
+<style scoped></style>
+

+ 34 - 17
fhKeeper/formulahousekeeper/customerBuler-crm/src/router/index.ts

@@ -1,4 +1,4 @@
-import { RouteRecordRaw,createRouter, createWebHistory } from "vue-router";
+import { RouteRecordRaw, createRouter, createWebHistory } from "vue-router";
 import { useStore } from "@/store/index";
 export const routes: RouteRecordRaw[] = [
   {
@@ -47,10 +47,11 @@ const router = createRouter({
 router.beforeEach((to, _from, next) => {
   const routerList = useStore().routers;
   const routers = router.getRoutes();
-  console.log(routerList, routers);
-  const { setAsyncRoutesMark, asyncRoutesMark } = useStore();
-  const token = true;
-  const skipPath = ['/login', '/register', '/test', '/testEcharts']
+  //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 {
@@ -58,25 +59,41 @@ router.beforeEach((to, _from, next) => {
       if (asyncRoutesMark) {
         next();
       } else {
-        setAsyncRoutesMark(true)
-        const newRouters: any = routers
-        const addNewRouter = newRouters.find((item: any) => item.name == 'home')
+        setAsyncRoutesMark(true);
+        const newRouters: any = routers;
+        const addNewRouter = newRouters.find(
+          (item: any) => item.path == "/home"
+        );
         routerList.forEach((item: any) => {
-          addNewRouter?.children.push({
-            path: item.path,
-            name: item.name,
-            meta: {},
-            component: () => import(`@/pages/${item.name}/index.vue`),
-          })
-        })
+          let filePath = item.path.split("/")[1];
+          if (item.children && item.children.length > 0) {
+            item.children.forEach((child: any) => {
+              let childFilePath = child.path.split("/")[1];
+              addNewRouter?.children.push({
+                path: child.path,
+                name: child.name,
+                meta: {},
+                component: () =>
+                  import(`@/pages/${filePath}/${childFilePath}/index.vue`),
+              });
+            });
+          } else {
+            addNewRouter?.children.push({
+              path: item.path,
+              name: item.name,
+              meta: {},
+              component: () => import(`@/pages/${filePath}/index.vue`),
+            });
+          }
+        });
         router.addRoute(addNewRouter);
         next({ ...to, replace: true });
       }
     } else {
-      console.log("无登录信息,跳转到登录页");
+      //console.log("无登录信息,跳转到登录页");
       next(`/login`);
     }
   }
-  console.log(routerList);
+  //console.log(routerList);
 });
 export default router;

+ 17 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/store/Store.d.ts

@@ -0,0 +1,17 @@
+type SotreState = {
+  userInfo: any;
+  routers: RouteRecordRaw[];
+  asyncRoutesMark: boolean;
+};
+type SoreGetters = {
+  getRoutersList: () => RouteRecordRaw[];
+  getToken: () => string;
+};
+type SotreActions = {
+  setRouters(arr: any): void;
+  setAsyncRoutesMark(val: boolean): void;
+  setValue(val: any, key: keyof SotreState): void;
+  getRouterConfig(path: string): RouteRecordRaw | any;
+  getFunctionList(path: string): any[];
+  clearStore(): void;
+};

+ 52 - 20
fhKeeper/formulahousekeeper/customerBuler-crm/src/store/index.ts

@@ -1,24 +1,56 @@
 import { defineStore, acceptHMRUpdate } from "pinia";
-export const useStore = defineStore({
-    id: "index",
-    state: () => ({
-        userInfo: {}, // 当前的用户信息
-        routers: [], // 返回的所有路由
-        asyncRoutesMark: false, // 是否添加过路由
-    }),
-    getters: { // 取值
-        
-    },
-    actions: { // 方法
-        setRouters(arr: any) {
-            this.routers = arr;
-        },
-        setAsyncRoutesMark(val: boolean) {
-            this.asyncRoutesMark = val
-        }
-    },
-    persist: true, // 是否持久化
+
+export const useStore = defineStore<
+  string,
+  SotreState,
+  SoreGetters,
+  SotreActions
+>("storeInfo", {
+  state: () => ({
+    userInfo: {}, // 当前的用户信息
+    routers: [], // 返回的所有路由
+    asyncRoutesMark: false, // 是否添加过路由
+  }),
+  getters: {
+    getRoutersList() {
+      // 取值
+      return this.routers;
+    },
+    getToken() {
+      return this.userInfo?.id || "";
+    },
+  },
+  actions: {
+    // 方法
+    setRouters(arr) {
+      this.routers = arr;
+    },
+    setAsyncRoutesMark(val) {
+      this.asyncRoutesMark = val;
+    },
+    setValue(val, key) {
+      this[key] = val;
+    },
+    getRouterConfig(path) {
+      return this.routers.find((item) => item.path === path);
+    },
+    getFunctionList(path) {
+      const config = this.getRouterConfig(path);
+      if (!config) {
+        return [];
+      }
+      return config.functionList || [];
+    },
+    clearStore() {
+      localStorage.clear();
+      sessionStorage.clear();
+      this.userInfo = {};
+      this.routers = [];
+      this.asyncRoutesMark = false;
+    },
+  },
+  persist: true, // 是否持久化
 });
 if (import.meta.hot) {
-    import.meta.hot.accept(acceptHMRUpdate(useStore, import.meta.hot))
+  import.meta.hot.accept(acceptHMRUpdate(useStore, import.meta.hot));
 }

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

@@ -11,4 +11,7 @@ $modena: #6F4AFE;
 }
 .text-black {
     color : $fontBlack
+}
+.back-dark {
+    background-color : $darkBlue
 }

+ 6 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/type.d.ts

@@ -0,0 +1,6 @@
+interface GlobalPopup extends Notify {
+  showSuccess: (message?: string) => void;
+  showError: (message?: string) => void;
+  showWarning: (message: string) => void;
+  showInfo: (message: string) => void;
+}

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

@@ -1,10 +1,19 @@
 package com.management.platform.controller;
 
 
+import com.management.platform.entity.Contacts;
+import com.management.platform.service.ContactsService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * <p>
  *  前端控制器
@@ -17,5 +26,21 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping("/contacts")
 public class ContactsController {
 
+    @Resource
+    private HttpServletRequest request;
+
+    @Autowired
+    private ContactsService contactsService;
+
+    @RequestMapping("/addContacts")
+    public HttpRespMsg addContacts(@RequestBody Contacts contacts){
+        return contactsService.addContacts(contacts, request);
+    }
+
+    @RequestMapping("/pageContacts")
+    public HttpRespMsg pageContacts(@RequestParam Integer pageIndex, @RequestParam Integer pageSize,String customName, String name, String phone, String ownerName){
+        return contactsService.pageContacts(pageIndex,pageSize,customName,name,phone,ownerName,request);
+    }
+
 }
 

+ 13 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Contacts.java

@@ -3,11 +3,15 @@ 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>
@@ -15,7 +19,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2024-02-28
+ * @since 2024-03-05
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -96,6 +100,14 @@ public class Contacts extends Model<Contacts> {
     @TableField("is_delete")
     private Integer isDelete;
 
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
+    private LocalDateTime createTime;
+
 
     @Override
     protected Serializable pkVal() {

+ 13 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/vo/ContactsVo.java

@@ -0,0 +1,13 @@
+package com.management.platform.entity.vo;
+
+import com.management.platform.entity.Contacts;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@Accessors(chain = true)
+public class ContactsVo extends Contacts {
+    private String customName;
+    private String ownerName;
+
+}

+ 8 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ContactsMapper.java

@@ -1,7 +1,13 @@
 package com.management.platform.mapper;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.management.platform.entity.Contacts;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.vo.ContactsVo;
+import com.management.platform.util.HttpRespMsg;
+
+import java.util.Map;
 
 /**
  * <p>
@@ -13,4 +19,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface ContactsMapper extends BaseMapper<Contacts> {
 
+
+    Page<ContactsVo> pageContacts(Page page, Map<String, Object> map);
 }

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

@@ -2,6 +2,10 @@ package com.management.platform.service;
 
 import com.management.platform.entity.Contacts;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.entity.vo.ContactsVo;
+import com.management.platform.util.HttpRespMsg;
+
+import javax.servlet.http.HttpServletRequest;
 
 /**
  * <p>
@@ -13,4 +17,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface ContactsService extends IService<Contacts> {
 
+    HttpRespMsg addContacts(Contacts contacts, HttpServletRequest request);
+
+    HttpRespMsg pageContacts(Integer pageIndex, Integer pageSize, String customName, String name, String phone, String ownerName, HttpServletRequest request);
 }

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

@@ -1,10 +1,28 @@
 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.Contacts;
+import com.management.platform.entity.User;
+import com.management.platform.entity.vo.ContactsVo;
 import com.management.platform.mapper.ContactsMapper;
+import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.ContactsService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.util.HttpRespMsg;
+import org.apache.ibatis.annotations.Mapper;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -16,5 +34,55 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> implements ContactsService {
+    @Resource
+    private ContactsMapper contactsMapper;
+    @Resource
+    private UserMapper userMapper;
+
+
+
+    @Override
+    @Transactional
+    public HttpRespMsg addContacts(Contacts contacts, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String token = String.valueOf(request.getHeader("Token"));
+        User user = userMapper.selectById(token);
+        Integer companyId = user.getCompanyId();
+
+        LambdaQueryWrapper<Contacts> lqw_contacts = new LambdaQueryWrapper<>();
+        lqw_contacts.eq(Contacts::getCustomId,contacts.getCustomId()).eq(Contacts::getName,contacts.getName());
+        Contacts selectedOne = contactsMapper.selectOne(lqw_contacts);
+        if (selectedOne!=null){
+            httpRespMsg.setError("已存在该客户!");
+        }
+        contacts.setCompanyId(companyId)
+                .setOwnerId(user.getId())//添加时默认
+                .setIsDelete(0)
+                .setCreateTime(LocalDateTime.now());
+        int insert = contactsMapper.insert(contacts);
+        if (insert<=0){
+            httpRespMsg.setError("添加失败!");
+        }
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg pageContacts(Integer pageIndex, Integer pageSize, String customName, String name, String phone, String ownerName, HttpServletRequest request) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("customName", customName);
+        map.put("name", name);
+        map.put("phone", phone);
+        map.put("ownerName", ownerName);
+        String token = String.valueOf(request.getHeader("Token"));
+        User user = userMapper.selectById(token);
+        map.put("companyId",user.getCompanyId());
+        Page<ContactsVo> pageContacts = contactsMapper.pageContacts(new Page(pageIndex, pageSize), map);
+        List<ContactsVo> contactsVoList = pageContacts.getRecords();
+
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(contactsVoList);
+        return msg;
+    }
+
 
 }

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

@@ -583,13 +583,13 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         //返回菜单
         List<SysRoleModule> rModules = sysRoleModuleMapper.selectList(new QueryWrapper<SysRoleModule>().eq("role_id", roleId));
         List<Integer> ids = rModules.stream().map(SysRoleModule::getModuleId).collect(Collectors.toList());
-        //项目报告审核模块,如果参与日报的审核,需要自动加上, 或者担任任务分组负责人
-        if (user.isLeader() || user.isHasAuditDept() || (company.getPackageProject() == 1 && taskGroupMapper.selectCount(new QueryWrapper<TaskGroup>().eq("incharger_id", user.getId())) > 0)) {
-            SysModule projectAuditModule = sysModuleMapper.selectOne(new QueryWrapper<SysModule>().eq("name", "项目报告审核"));
-            if (!ids.contains(projectAuditModule.getId())) {
-                ids.add(projectAuditModule.getId());
-            }
-        }
+//        //项目报告审核模块,如果参与日报的审核,需要自动加上, 或者担任任务分组负责人
+//        if (user.isLeader() || user.isHasAuditDept() || (company.getPackageProject() == 1 && taskGroupMapper.selectCount(new QueryWrapper<TaskGroup>().eq("incharger_id", user.getId())) > 0)) {
+//            SysModule projectAuditModule = sysModuleMapper.selectOne(new QueryWrapper<SysModule>().eq("name", "项目报告审核"));
+//            if (!ids.contains(projectAuditModule.getId())) {
+//                ids.add(projectAuditModule.getId());
+//            }
+//        }
 
         List<SysModule> moduleList = sysModuleMapper.selectList(queryWrapper);
 

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

@@ -17,11 +17,40 @@
         <result column="plate4" property="plate4" />
         <result column="plate5" property="plate5" />
         <result column="is_delete" property="isDelete" />
+        <result column="create_time" property="createTime" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, name, custom_id, email, phone, owner_id, plate1, plate2, plate3, plate4, plate5, is_delete
+        id, company_id, name, custom_id, email, phone, owner_id, plate1, plate2, plate3, plate4, plate5, is_delete, create_time
     </sql>
+    <select id="pageContacts" parameterType="java.util.Map"  resultType="com.management.platform.entity.vo.ContactsVo">
+        SELECT c.*, cust.custom_name as customName, own.name as ownerName
+        FROM contacts c
+        LEFT JOIN custom cust ON c.custom_id = cust.id
+        LEFT JOIN user own ON c.owner_id = own.id
+        <where>
+            1=1 and c.is_delete=0
+
+            <if test="map.customName != null and map.customName != ''">
+                AND cust.custom_name LIKE CONCAT('%', #{map.customName}, '%')
+            </if>
+            <if test="map.ownerName != null and map.ownerName != ''">
+                AND own.name LIKE CONCAT('%', #{map.ownerName}, '%')
+            </if>
+            <if test="map.phone != null and map.phone != ''">
+                AND c.phone LIKE CONCAT('%', #{map.phone}, '%')
+            </if>
+            <if test="map.name != null and map.name != ''">
+                AND c.name LIKE CONCAT('%', #{map.name}, '%')
+            </if>
+            <if test="map.companyId != null">
+                AND c.company_id=#{map.companyId}
+            </if>
+        </where>
+        order by create_time desc
+
+    </select>
+
 
 </mapper>

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -1260,8 +1260,8 @@ public class ProjectController {
 
     //FTE报表
     @RequestMapping("/getFTEData")
-    public HttpRespMsg getFTEData(@RequestParam Integer pageIndex, @RequestParam Integer pageSize,String monthStart,String monthEnd,String area,String sortProp, Integer sortOrder,HttpServletRequest request){
-        return projectService.getFTEData(pageIndex,pageSize,monthStart,monthEnd,area,sortProp,sortOrder,request);
+    public HttpRespMsg getFTEData(@RequestParam Integer pageIndex, @RequestParam Integer pageSize,String monthStart,String monthEnd,String area,String userId,String sortProp, Integer sortOrder,HttpServletRequest request){
+        return projectService.getFTEData(pageIndex,pageSize,monthStart,monthEnd,area,userId,sortProp,sortOrder,request);
     }
 
     //导出FTE报表

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportDeleteController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-05
+ */
+@RestController
+@RequestMapping("/report-delete")
+public class ReportDeleteController {
+
+}
+

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

@@ -952,13 +952,13 @@ public class TaskController {
     }
 
     @RequestMapping("/getTaskTimeCompare")
-    public HttpRespMsg getTaskTimeCompare(Integer projectId) {
-        return taskService.getTaskTimeCompare(projectId);
+    public HttpRespMsg getTaskTimeCompare(Integer projectId,Integer deptId) {
+        return taskService.getTaskTimeCompare(projectId,deptId);
     }
 
     @RequestMapping("/exportTaskTimeCompare")
-    public HttpRespMsg exportTaskTimeCompare(Integer projectId) {
-        return taskService.exportTaskTimeCompare(projectId);
+    public HttpRespMsg exportTaskTimeCompare(Integer projectId,Integer deptId) {
+        return taskService.exportTaskTimeCompare(projectId,deptId);
     }
 
     @RequestMapping("exportTask")

+ 19 - 23
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WxCorpInfoController.java

@@ -65,30 +65,26 @@ public class WxCorpInfoController {
 
     @RequestMapping("/testSendTemplateMsg")
     public HttpRespMsg testSendTemplateMsg(String userId) {
-        String corpwxuserIds = "";
-        //多个用户
-        String[] userIds = userId.split("\\|");
-        List<String> ids = Arrays.asList(userIds);
-        List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id",ids));
-        corpwxuserIds = userList.stream().filter(u->!StringUtils.isEmpty(u.getCorpwxUserid())).map(User::getCorpwxUserid).collect(Collectors.joining("|"));
-        if (corpwxuserIds.length() > 0) {
-            int companyId=userList.get(0).getCompanyId();
-            WxCorpInfo corpInfo = wxCorpInfoService.getOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
-            System.out.println("发送给:"+corpwxuserIds);
-            //推送到企业微信
+        int companyId=7;
+        WxCorpInfo corpInfo = wxCorpInfoService.getOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+        String corpwxuserIds = "woy9TkCAAAPD6149u46N_Yi5ARSA4VFw";
+        System.out.println("发送给:"+corpwxuserIds);
+        //推送到企业微信
 //        String corpUid = user.getCorpwxUserid();
-            JSONObject json=new JSONObject();
-            JSONArray dataJson=new JSONArray();
-            JSONObject jsonObj=new JSONObject();
-            jsonObj.put("key", "提示");
-            jsonObj.put("value", "测试提醒消息21:12");
-            dataJson.add(jsonObj);
-            json.put("template_id","tty9TkCAAAYoevY-40ciWD5lDncDfR5w");
-            json.put("url", "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect");
-            json.put("content_item",dataJson);
-            wxCorpInfoService.sendWXCorpTemplateMsg(corpInfo, corpwxuserIds, json);
-
-        }
+        JSONObject json=new JSONObject();
+        JSONArray dataJson=new JSONArray();
+        JSONObject item=new JSONObject();
+        item.put("key","审核人");
+        item.put("value","$userName=woy9TkCAAAPD6149u46N_Yi5ARSA4VFw$");
+        dataJson.add(item);
+        json.put("template_id","tty9TkCAAANpvEtLrkPUGeOEd1-U7W2w");
+        JSONObject item2=new JSONObject();
+        item2.put("key","日期");
+        item2.put("value","2021-07-14");
+        dataJson.add(item2);
+        json.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect");
+        json.put("content_item",dataJson);
+        wxCorpInfoService.sendWXCorpTemplateMsg(corpInfo,corpwxuserIds,json);
         return new HttpRespMsg();
     }
 

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

@@ -58,13 +58,13 @@ public class Department extends Model<Department> {
     /**
      * 部门负责人id
      */
-    @TableField(value = "manager_id", updateStrategy = FieldStrategy.IGNORED)
+    @TableField(value = "manager_id")
     private String managerId;
 
     /**
      * 日报导入审核人
      */
-    @TableField(value = "report_audit_userid", updateStrategy = FieldStrategy.IGNORED)
+    @TableField(value = "report_audit_userid")
     private String reportAuditUserid;
 
 

+ 347 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportDelete.java

@@ -0,0 +1,347 @@
+package com.management.platform.entity;
+
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.time.LocalDate;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ReportDelete extends Model<ReportDelete> {
+
+    private static final long serialVersionUID=1L;
+
+    /**
+     * 主键
+     */
+    @TableId("id")
+    private Integer id;
+
+    /**
+     * user表外键 报告的作者
+     */
+    @TableField("creator_id")
+    private String creatorId;
+
+    /**
+     * project表外键 相关项目
+     */
+    @TableField("project_id")
+    private Integer projectId;
+
+    /**
+     * 日期
+     */
+    @TableField("create_date")
+    private LocalDate createDate;
+
+    /**
+     * 工作时间
+     */
+    @TableField("working_time")
+    private Double workingTime;
+
+    /**
+     * 报告内容; 根据multi_worktime的取值,形式有差别
+     */
+    @TableField("content")
+    private String content;
+
+    /**
+     * 审查状态 0-未审核 1-已通过 2-未通过, -1-导入待审核, 3草稿
+     */
+    @TableField("state")
+    private Integer state;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private LocalDateTime createTime;
+
+    /**
+     * 0-全天, 1-上午,2-下午
+     */
+    @TableField("time_type")
+    private Integer timeType;
+
+    /**
+     * 成本
+     */
+    @TableField("cost")
+    private BigDecimal cost;
+
+    /**
+     * 开始时间
+     */
+    @TableField("start_time")
+    private String startTime;
+
+    /**
+     * 结束时间
+     */
+    @TableField("end_time")
+    private String endTime;
+
+    /**
+     * 员工填写时长类型
+     */
+    @TableField("report_time_type")
+    private Integer reportTimeType;
+
+    /**
+     * 子项目id
+     */
+    @TableField("sub_project_id")
+    private Integer subProjectId;
+
+    /**
+     * 任务id
+     */
+    @TableField("task_id")
+    private Integer taskId;
+
+    /**
+     * 是否是加班
+     */
+    @TableField("is_overtime")
+    private Integer isOvertime;
+
+    /**
+     * 用时占比
+     */
+    @TableField("progress")
+    private Integer progress;
+
+    /**
+     * 部门审核状态: -1 专业未审核,0-部门未审核,1-已通过,2-未通过
+     */
+    @TableField("department_audit_state")
+    private Integer departmentAuditState;
+
+    /**
+     * 阶段/岗位/工序
+     */
+    @TableField("stage")
+    private String stage;
+
+    /**
+     * 图片的数组字符串
+     */
+    @TableField("pic_str")
+    private String picStr;
+
+    /**
+     * 是否是多个时间工作事项
+     */
+    @TableField("multi_worktime")
+    private Integer multiWorktime;
+
+    /**
+     * 驳回原因
+     */
+    @TableField("reject_reason")
+    private String rejectReason;
+
+    /**
+     * 驳回人姓名
+     */
+    @TableField("reject_username")
+    private String rejectUsername;
+
+    /**
+     * 驳回人id
+     */
+    @TableField("reject_userid")
+    private String rejectUserid;
+
+    /**
+     * 选择的自定义维度
+     */
+    @TableField("degree_id")
+    private Integer degreeId;
+
+    /**
+     * 公司id
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+    /**
+     * 代填或者导入的用户id
+     */
+    @TableField("fill_userid")
+    private String fillUserid;
+
+    /**
+     * 审核流程:当前审核的部门id
+     */
+    @TableField("audit_deptid")
+    private Integer auditDeptid;
+
+    /**
+     * 审核流程: 是否是部门审核
+     */
+    @TableField("is_dept_audit")
+    private Integer isDeptAudit;
+
+    /**
+     * 审核流程:当前审核的部门负责人id
+     */
+    @TableField("audit_dept_managerid")
+    private String auditDeptManagerid;
+
+    /**
+     * 是否是最后一步审核
+     */
+    @TableField("is_final_audit")
+    private Integer isFinalAudit;
+
+    /**
+     * 审核流程:审核过程中,项目的审核状态; 0-待审核,1-审核通过
+     */
+    @TableField("project_audit_state")
+    private Integer projectAuditState;
+
+    /**
+     * 任务分组id
+     */
+    @TableField("group_id")
+    private Integer groupId;
+
+    /**
+     * 自定义的数值
+     */
+    @TableField("custom_data")
+    private Double customData;
+
+    /**
+     * 项目审核人id
+     */
+    @TableField("project_auditor_id")
+    private String projectAuditorId;
+
+    /**
+     * 工时日报所属部门id
+     */
+    @TableField("dept_id")
+    private Integer deptId;
+
+    /**
+     * 加班时长
+     */
+    @TableField("overtime_hours")
+    private Double overtimeHours;
+
+    /**
+     * 加班薪资
+     */
+    @TableField("overtime_cost")
+    private BigDecimal overtimeCost;
+
+    /**
+     * 自定义文本信息内容
+     */
+    @TableField("custom_text")
+    private String customText;
+
+    /**
+     * 对应成本项的id
+     */
+    @TableField("basecost_id")
+    private Integer basecostId;
+
+    /**
+     * 项目日报审核时间
+     */
+    @TableField("project_audit_time")
+    private LocalDateTime projectAuditTime;
+
+    /**
+     * 任务分组负责人审核状态: 0-待审核,1-审核通过
+     */
+    @TableField("group_audit_state")
+    private Integer groupAuditState;
+
+    /**
+     * 评价
+     */
+    @TableField("evaluate")
+    private String evaluate;
+
+    /**
+     * 是否属于自动审核通过  0-不属于 1-属于
+     */
+    @TableField("report_auto_approve")
+    private Integer reportAutoApprove;
+
+    /**
+     * 批量填报时的report_batch表id
+     */
+    @TableField("batch_id")
+    private Integer batchId;
+
+    /**
+     * 昱众-角色类型:0-PM,1-CRC
+     */
+    @TableField("extra_field1")
+    private Integer extraField1;
+
+    /**
+     * 昱众-工作职责
+     */
+    @TableField("extra_field2")
+    private Integer extraField2;
+
+    /**
+     * 昱众-工作内容
+     */
+    @TableField("extra_field3")
+    private Integer extraField3;
+
+    /**
+     * SAP项目服务ID
+     */
+    @TableField("sap_service_id")
+    private Integer sapServiceId;
+
+    /**
+     * 多选自定义维度id
+     */
+    @TableField("multi_degr_id")
+    private String multiDegrId;
+
+    /**
+     * 删除的人员id
+     */
+    @TableField("delete_user_id")
+    private String deleteUserId;
+
+    /**
+     * 删除时间
+     */
+    @TableField("delete_time")
+    private LocalDateTime deleteTime;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java

@@ -160,7 +160,7 @@ public interface ProjectMapper extends BaseMapper<Project> {
 
     List<Project> selectNearProject(String userId);
 
-    List<Map<String, Object>> getFTEData(Integer companyId, String startDate, String endDate, Integer start, Integer size, String area,String sortProp, Integer sortOrder, List<Integer> branchDepartment, List<Integer> deptIds);
+    List<Map<String, Object>> getFTEData(Integer companyId, String startDate, String endDate, Integer start, Integer size, String area,String userId,String sortProp, Integer sortOrder, List<Integer> branchDepartment, List<Integer> deptIds);
 
     List<Map<String, Object>> getTimeCostByToken(Integer companyId, String startDate, String endDate);
 

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

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

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/TaskMapper.java

@@ -29,7 +29,7 @@ public interface TaskMapper extends BaseMapper<Task> {
 
     List<Task> nameList(@Param(Constants.WRAPPER) Wrapper wrapper);
 
-    List getTaskTimeCompare(Integer projectId);
+    List getTaskTimeCompare(Integer projectId,Integer deptId);
 
     List<TimeTask> getTaskWithWorktime(Integer projectId, Integer taskType);
 

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java

@@ -243,7 +243,7 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg nearProject(HttpServletRequest request);
 
-    HttpRespMsg getFTEData(Integer pageIndex, Integer pageSize,String monthStart,String monthEnd, String area,String sortProp, Integer sortOrder, HttpServletRequest request);
+    HttpRespMsg getFTEData(Integer pageIndex, Integer pageSize,String monthStart,String monthEnd, String area,String userId,String sortProp, Integer sortOrder, HttpServletRequest request);
 
     HttpRespMsg exportFTEData(String monthStart,String monthEnd, String area, HttpServletRequest request);
 

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

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

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

@@ -32,8 +32,8 @@ public interface TaskService extends IService<Task> {
     List<Task> nameList(Wrapper<Task> queryWrapper);
 
 
-    HttpRespMsg getTaskTimeCompare(Integer projectId);
-    HttpRespMsg exportTaskTimeCompare(Integer projectId);
+    HttpRespMsg getTaskTimeCompare(Integer projectId,Integer deptId);
+    HttpRespMsg exportTaskTimeCompare(Integer projectId,Integer deptId);
 
     HttpRespMsg exportTask(Integer projectId, Integer taskType);
 

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

@@ -11289,7 +11289,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
 
     //获取FTE报表数据
     @Override
-    public HttpRespMsg getFTEData(Integer pageIndex, Integer pageSize,String monthStart,String monthEnd, String area,String sortProp, Integer sortOrder, HttpServletRequest request) {
+    public HttpRespMsg getFTEData(Integer pageIndex, Integer pageSize,String monthStart,String monthEnd, String area,String userId,String sortProp, Integer sortOrder, HttpServletRequest request) {
         HttpRespMsg httpRespMsg =new HttpRespMsg();
         User targetUser = userMapper.selectById(request.getHeader("token"));
         List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "全部部门FTE报表");
@@ -11327,10 +11327,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         if(pageIndex!=null&&pageSize!=null){
             Integer size=pageSize;
             Integer start=(pageIndex-1)*size;
-            resultList=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,start,size,area,sortProp,sortOrder,null,deptIds);
-            total=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,null,null,area,sortProp,sortOrder,null,deptIds).size();
+            resultList=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,start,size,area,userId,sortProp,sortOrder,null,deptIds);
+            total=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,null,null,area,userId,sortProp,sortOrder,null,deptIds).size();
         }else{
-            resultList=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,null,null,area,sortProp,sortOrder,null,deptIds);
+            resultList=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,null,null,area,userId,sortProp,sortOrder,null,deptIds);
         }
         //固定月工时数 163.125
         double regularMonthTime=163.125;
@@ -11366,7 +11366,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         if (userCustoms.size() != 0){
             customName = userCustoms.get(0).getName();
         }
-        HttpRespMsg fteData = getFTEData(null, null, monthStart,monthEnd, area,null,null, request);
+        HttpRespMsg fteData = getFTEData(null, null, monthStart,monthEnd, area,null,null,null, request);
         LocalDate timeStart = LocalDate.parse(monthStart, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
         LocalDate timeEnd = LocalDate.parse(monthEnd, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
         timeStart=timeStart.with(TemporalAdjusters.firstDayOfMonth());

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.ReportDelete;
+import com.management.platform.mapper.ReportDeleteMapper;
+import com.management.platform.service.ReportDeleteService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-05
+ */
+@Service
+public class ReportDeleteServiceImpl extends ServiceImpl<ReportDeleteMapper, ReportDelete> implements ReportDeleteService {
+
+}

+ 57 - 29
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -87,6 +87,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     public String appSecret;
     @Resource
     private TaskGroupMapper taskGroupMapper;
+    @Resource
+    private ReportDeleteService reportDeleteService;
+
     @Resource
     private DepartmentService departmentService;
     @Resource
@@ -1593,6 +1596,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     @Override
     public HttpRespMsg deleteReport(String userId, String date) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String delUserId = request.getHeader("TOKEN");
         Company company = companyMapper.selectById(userMapper.selectById(userId).getCompanyId());
         //某人删除自己某天的全部报告
         QueryWrapper<Report> queryWrapper = new QueryWrapper<Report>().eq("creator_id", userId).eq("create_date", date);
@@ -1610,27 +1614,18 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         } else {
             //删除日报的日志
             reportLogMapper.delete(new QueryWrapper<ReportLog>().eq("creator_id", userId).eq("create_date", date));
+            reportLogDetailMapper.delete(new QueryWrapper<ReportLogDetail>().in("report_id", collect));
+            //存入日报删除表
+            List<ReportDelete> delList = new ArrayList<>();
+            for (Report r : reportList) {
+                //从report对象中复制所有字段到report_delete对象中
+                ReportDelete delLog = new ReportDelete();
+                BeanUtils.copyProperties(r, delLog);
+                delLog.setDeleteUserId(delUserId);
+                delList.add(delLog);
+            }
+            reportDeleteService.saveBatch(delList);
         }
-        //不需要调绎维的删除接口了。工时在我们这边系统内管理控制。
-//        if(company.getId()==862){
-//            String url = "http://183.194.0.98:3202/api/web-server/controlCenter/billRejected";
-//            HttpHeaders headers = new HttpHeaders();
-//            headers.setContentType(MediaType.APPLICATION_JSON);
-//            headers.add("token",getTokenOfYiWei());
-//            JSONObject body=new JSONObject();
-//            body.put("type","EXPENSE");
-//            body.put("billNo","GS"+reportList.get(0).getCreatorId()+reportList.get(0).getCreateDate());
-//            HttpEntity<String> requestEntity = new HttpEntity<String>(body.toJSONString(), headers);
-//            ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
-//                    HttpMethod.POST, requestEntity, String.class);
-//            if (responseEntity.getStatusCode() == HttpStatus.OK) {
-//                String resp = responseEntity.getBody();
-//                JSONObject json = JSONObject.parseObject(resp);
-//                if(json.getIntValue("status")==0){
-//                    JSONArray jsonArray = json.getJSONArray("data");
-//                }
-//            }
-//        }
         return httpRespMsg;
     }
 
@@ -2006,11 +2001,12 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                             User u = first.get();
                             if(u.getCorpwxUserid()!=null){
                                 if(wxCorpInfoList.size()>0){
-                                    JSONObject json=new JSONObject();
+                                    WxCorpInfo wxCorpInfo = wxCorpInfoList.get(0);
+                                    JSONObject json = new JSONObject();
                                     JSONArray dataJson=new JSONArray();
                                     JSONObject item=new JSONObject();
                                     item.put("key","审核人");
-                                    item.put("value",user.getName());
+                                    item.put("value",wxCorpInfo.getSaasSyncContact() == 1?("$userName="+user.getName()+"$"): user.getName());
                                     dataJson.add(item);
                                     if(timeType.getNeedEvaluate()==1){
                                         JSONObject item1=new JSONObject();
@@ -2027,7 +2023,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                                     dataJson.add(item2);
                                     json.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect");
                                     json.put("content_item",dataJson);
-                                    wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfoList.get(0),u.getCorpwxUserid(),json);
+                                    wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo,u.getCorpwxUserid(),json);
                                 }
                             }
                             if(u.getDingdingUserid()!=null){
@@ -2051,6 +2047,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             log.setUserId(user.getId());
             log.setUserName(user.getName());
             log.setProjectName(pNames);
+            if (pNames.length() > 2000) {
+                log.setProjectName(pNames.substring(0, 2000));
+            }
             reportAuditLogMapper.insert(log);
             //员工的日期
             ReportAlogMembdate membdate = new ReportAlogMembdate();
@@ -2550,6 +2549,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             log.setUserId(user.getId());
             log.setUserName(user.getName());
             log.setProjectName(pNames);
+            if (pNames.length() > 2000) {
+                log.setProjectName(pNames.substring(0, 2000));
+            }
             reportAuditLogMapper.insert(log);
             //员工的日期
             ReportAlogMembdate membdate = new ReportAlogMembdate();
@@ -2843,6 +2845,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         log.setUserId(user.getId());
         log.setUserName(user.getName());
         log.setProjectName(pNames);
+        if (pNames.length() > 2000) {
+            log.setProjectName(pNames.substring(0, 2000));
+        }
         reportAuditLogMapper.insert(log);
         //员工的日期
         ReportAlogMembdate membdate = new ReportAlogMembdate();
@@ -3772,6 +3777,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             log.setResult(MessageUtils.message("profession.batchPass"));
             log.setUserId(user.getId());
             log.setUserName(user.getName());
+            if (s.length()>2000) {
+                s = s.substring(0, 2000);
+            }
             log.setProjectName(s);
             reportAuditLogMapper.insert(log);
 
@@ -3886,6 +3894,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         log.setUserId(user.getId());
         log.setUserName(user.getName());
         log.setProjectName(s);
+        if (s.length() > 2000) {
+            s = s.substring(0, 2000);
+        }
         reportAuditLogMapper.insert(log);
         List<Report> allReports = reportMapper.selectList(new QueryWrapper<Report>().in("id", ids));
         saveDenyReportLog(allReports, user.getId(), user.getName(), reason);
@@ -5610,15 +5621,15 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 											if(auditMsg.contains("提交了")){
 												int i = auditMsg.indexOf("提");
 												String substring = auditMsg.substring(0, i);
-												msg = time+" " + auditMsg.replace(substring,"\\$userName="+corpwxUserId+"\\$");
+												msg = time+" " + auditMsg.replace(substring,"\\$userName="+corpwxUserId+"$\\");
 											}else if(auditMsg.contains("审核通过了")){
 												int i = auditMsg.indexOf("审");
 												String substring = auditMsg.substring(0, i);
-												msg = time+" " + auditMsg.replace(substring,"\\$userName="+corpwxUserId+"\\$");
+												msg = time+" " + auditMsg.replace(substring,"\\$userName="+corpwxUserId+"$\\");
 											}else if(auditMsg.contains("驳回了")) {
 												int i = auditMsg.indexOf("驳");
 												String substring = auditMsg.substring(0, i);
-												msg = time+" " + auditMsg.replace(substring,"\\$userName="+corpwxUserId+"\\$");
+												msg = time+" " + auditMsg.replace(substring,"\\$userName="+corpwxUserId+"$\\");
 											}
 										} else {
 											msg = time+" " + auditMsg;
@@ -6080,9 +6091,22 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     public List<Map<String, Object>> getNotFullReportUserList(Integer companyId, LocalDate localStart, LocalDate localEnd) {
         List<Report> reportList  = reportMapper.selectList(new QueryWrapper<Report>().select("id,create_date,creator_id, state").eq("company_id", companyId).between("create_date", localStart, localEnd));
         List<User> allRangeUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId).eq("report_status",0));
-
         List<Map<String, Object>> noReportDataList = new ArrayList<Map<String, Object>>();
         long cnt = localStart.until(localEnd, ChronoUnit.DAYS);
+        //判断用户注册的平台类型
+//        int platform = 0;
+//        if (allRangeUserList.size() > 0) {
+//            User user = allRangeUserList.get(0);
+//            if (user.getCorpwxUserid() != null) {
+//                platform = 1;
+//            } else if (user.getWxOpenid() != null) {
+//                platform = 2;
+//            } else if (user.getDingdingUserid() != null) {
+//                platform = 3;
+//            } else if (user.getFeishuUserid() != null) {
+//                platform = 4;
+//            }
+//        }
         //已驳回的数据
         //按人员过滤
         for (User curUser: allRangeUserList){
@@ -6105,14 +6129,18 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 if (!reportList.stream().anyMatch(item->item.getCreatorId().equals(curUser.getId())&&item.getCreateDate().isEqual(date)&&(item.getState() == 0 || item.getState() == 1))) {
                     HashMap map = new HashMap();
                     map.put("corpwxUserid", curUser.getCorpwxUserid());
+                    map.put("dingdingUserid", curUser.getDingdingUserid());
+                    map.put("wxOpenid", curUser.getWxOpenid());
+                    map.put("feishuUserid", curUser.getFeishuUserid());
+                    map.put("id", curUser.getId());
                     map.put("name", curUser.getName());
                     map.put("days", 1);
                     map.put("daysTxt", date.format(DateTimeFormatter.ofPattern("MM/dd")));
-                    if (!noReportDataList.stream().anyMatch(noItem->noItem.get("corpwxUserid").equals(curUser.getCorpwxUserid()))) {
+                    if (!noReportDataList.stream().anyMatch(noItem->noItem.get("id").equals(curUser.getId()))) {
                         noReportDataList.add(map);
                     } else {
                         //已经添加过了,需要更新天数
-                        Optional<Map<String, Object>> optional = noReportDataList.stream().filter(data -> data.get("corpwxUserid").equals(curUser.getCorpwxUserid())).findFirst();
+                        Optional<Map<String, Object>> optional = noReportDataList.stream().filter(data -> data.get("id").equals(curUser.getId())).findFirst();
                         if (optional.isPresent()) {
                             Map<String, Object> findUser = optional.get();
                             Object days = findUser.get("days");

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

@@ -117,16 +117,16 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
     }
 
     @Override
-    public HttpRespMsg getTaskTimeCompare(Integer projectId) {
+    public HttpRespMsg getTaskTimeCompare(Integer projectId,Integer deptId) {
         HttpRespMsg msg = new HttpRespMsg();
-        msg.data = taskMapper.getTaskTimeCompare(projectId);
+        msg.data = taskMapper.getTaskTimeCompare(projectId,deptId);
         return msg;
     }
 
     @Override
-    public HttpRespMsg exportTaskTimeCompare(Integer projectId) {
+    public HttpRespMsg exportTaskTimeCompare(Integer projectId,Integer deptId) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
-        List<Map> list= taskMapper.getTaskTimeCompare(projectId);
+        List<Map> list= taskMapper.getTaskTimeCompare(projectId,deptId);
         Project project = projectMapper.selectById(projectId);
         try {
             //准备导出

+ 28 - 19
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -1630,27 +1630,36 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                         }
                         //针对赛元微电子,请半天假的情况下。重新校正打卡和工作时长
                         if (corpInfo.getCorpid().equals("wpy9TkCAAAgNp4jvqxKTpXrhvwFvyFHg")) {
-                            if ((morningLeave && afternoonLeave) || isWholeDayLeave) {
-                                ct.setAskLeaveTime(baseMorningWorkTime + baseAfternoonWorkTime);
+                            if (dtf.format(ct.getCreateDate()).equals("2024-02-09") ) {
+                                //硬编码,这天由于特殊情况,考勤有数据但是他们没有上班,需要修正为0
                                 ct.setWorkHours(0.0);
                                 ct.setCardTime(0.0);
-                                ct.setStartTime(baseMorningStart);
-                                ct.setEndTime(baseAfternoonEnd);
-                                if (showLog) System.out.println("再次校正,全天请假");
-                            } else if (morningLeave){
-                                ct.setAskLeaveTime(baseMorningWorkTime);
-                                ct.setWorkHours(baseAfternoonWorkTime);
-                                ct.setCardTime(baseAfternoonWorkTime);
-                                ct.setStartTime(baseAfternoonStart);
-                                ct.setEndTime(baseAfternoonEnd);
-                                if (showLog) System.out.println("再次校正,上午请假");
-                            } else if (afternoonLeave) {
-                                ct.setAskLeaveTime(baseAfternoonWorkTime);
-                                ct.setWorkHours(baseMorningWorkTime);
-                                ct.setCardTime(baseMorningWorkTime);
-                                ct.setStartTime(baseMorningStart);
-                                ct.setEndTime(baseMorningEnd);
-                                if (showLog) System.out.println("再次校正,下午请假");
+                                ct.setStartTime("00:00");
+                                ct.setEndTime("00:00");
+                                ct.setAskLeaveTime(0.0);
+                            } else {
+                                if ((morningLeave && afternoonLeave) || isWholeDayLeave) {
+                                    ct.setAskLeaveTime(baseMorningWorkTime + baseAfternoonWorkTime);
+                                    ct.setWorkHours(0.0);
+                                    ct.setCardTime(0.0);
+                                    ct.setStartTime(baseMorningStart);
+                                    ct.setEndTime(baseAfternoonEnd);
+                                    if (showLog) System.out.println("再次校正,全天请假");
+                                } else if (morningLeave){
+                                    ct.setAskLeaveTime(baseMorningWorkTime);
+                                    ct.setWorkHours(baseAfternoonWorkTime);
+                                    ct.setCardTime(baseAfternoonWorkTime);
+                                    ct.setStartTime(baseAfternoonStart);
+                                    ct.setEndTime(baseAfternoonEnd);
+                                    if (showLog) System.out.println("再次校正,上午请假");
+                                } else if (afternoonLeave) {
+                                    ct.setAskLeaveTime(baseAfternoonWorkTime);
+                                    ct.setWorkHours(baseMorningWorkTime);
+                                    ct.setCardTime(baseMorningWorkTime);
+                                    ct.setStartTime(baseMorningStart);
+                                    ct.setEndTime(baseMorningEnd);
+                                    if (showLog) System.out.println("再次校正,下午请假");
+                                }
                             }
                         }
                     }

+ 21 - 38
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -1400,47 +1400,16 @@ public class TimingTask {
                         LocalDate endDate = localDate.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                         userList = reportService.getNotFullReportUserList(company.getId(), startDate, endDate);
                     }
+                } else if (t.getAlertType() == 4) {
+                    //4--每周提醒上周漏填
+                    LocalDate lastSunday = localDate.with(DayOfWeek.SUNDAY).minusWeeks(1);
+                    LocalDate lastMonday = lastSunday.minusDays(6);
+                    userList = reportService.getNotFullReportUserList(company.getId(), lastMonday, lastSunday);
+                    System.out.println("用户数量="+userList.size());
+                    lastWeekNotFill = true;
                 }
                 List<WxCorpInfo> cpList = wxCorpInfoMapper.selectList(new QueryWrapper<WxCorpInfo>().eq("company_id", t.getCompanyId()));
                 final boolean finalLastWeekNotFill = lastWeekNotFill;
-//                userList.forEach(u->{
-//                    if (u.get("corpwxUserid") != null){
-//                        //推送到企业微信
-//                        String corpUid = (String) u.get("corpwxUserid");
-//                        JSONObject json=new JSONObject();
-//                        JSONArray dataJson = new JSONArray();
-//                        JSONObject jsonObj = new JSONObject();
-//                        jsonObj.put("key", "提示");
-//                        if (t.getAlertType() == 3) {
-//                            //每月提醒上个月的
-//                            if ((Integer)u.get("days") > 3) {
-//                                jsonObj.put("value", "您上个月有"+u.get("daysTxt")+"...共"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
-//                            } else {
-//                                jsonObj.put("value", "您上个月有"+u.get("daysTxt")+"共"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
-//                            }
-//                        } else {
-//                            if (finalLastWeekNotFill) {
-//                                jsonObj.put("value", "您上周有"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
-//                            } else {
-//                                jsonObj.put("value", StringUtils.isEmpty(t.getAlertMsg())?"":t.getAlertMsg());
-//                            }
-//                        }
-//                        dataJson.add(jsonObj);
-//                        if(isPrivateDeploy){
-//                            json.put("content",StringUtils.isEmpty(t.getAlertMsg())?"":t.getAlertMsg()+"\\n<a href=\\\"https://open.weixin.qq.com/connect/oauth2/authorize?appid="+suitId+"&redirect_uri="+pcUrl+"/api/corpInsideWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect\\\">去填写</a>");
-//                        }else {
-//                            json.put("template_id","tty9TkCAAAYoevY-40ciWD5lDncDfR5w");
-//                            json.put("url", "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect");
-//                            json.put("content_item",dataJson);
-//                        }
-//                        if (cpList.size() > 0) {
-////                            System.out.println("发送企业微信漏填提醒:" + LocalDateTime.now().toString() + ", corpUid=" + corpUid + ", json=" + json.toJSONString());
-//                            wxCorpInfoService.sendWXCorpTemplateMsg(cpList.get(0), corpUid, json);
-//                        }
-//                    } else if (u.get("wxOpenid") != null) {
-//                        push(u, t.getAlertMsg());
-//                    }
-//                });
                 //今天或者明天统一提醒,提醒内容大家都一样
                 if (t.getAlertType() == 0 || t.getAlertType() == 1) {
                     //判断是企业微信用户还是微信用户
@@ -1514,6 +1483,13 @@ public class TimingTask {
                             push(u, t.getAlertMsg());
                         }
                     });
+                    //针对钉钉发送提醒
+                    if (userList.size() > 0 && userList.get(0).get("dingdingUserid") != null) {
+                        CompanyDingding compDingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", t.getCompanyId()));
+                        String idStr = userList.stream().map(u -> (String) u.get("dingdingUserid")).collect(Collectors.joining(","));
+                        //TODO: 批量发送,最大支持1000个用户Id. 多的话需要分批发送; 目前尚无这么大的数据量
+                        companyDingdingService.sendFillReportAlertMsg(t.getCompanyId(), compDingding.getAgentId(), t.getAlertMsg(), idStr);
+                    }
                 }
 
             }
@@ -1521,6 +1497,7 @@ public class TimingTask {
         if (isDev) {
             return;
         }
+        //针对钉钉提醒类型是0或者1的情况,发送提醒。(当天提醒或者今天提醒昨天漏填)
         List<Map<String, Object>> dingdingUserList = userMapper.getPushDingdingUserList(str, date);
         //钉钉平台的用批量发送, 每分钟5000个
         int minuteSize = 5000;
@@ -2047,4 +2024,10 @@ public class TimingTask {
         }
     }
 
+
+
+    @Scheduled(cron = "1 1 1 1 1 ?")
+    public void cleanUselessData(){
+        //TODO: 日报删除表report_delete,需要定期清理
+    }
 }

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml

@@ -1744,6 +1744,9 @@
         <if test="area!=null and area != '' ">
             and u.plate1 = #{area}
         </if>
+        <if test="userId!=null and userId != '' ">
+            and u.id = #{userId}
+        </if>
         <if test="branchDepartment!=null and branchDepartment.size()>0">
             and u.department_id in
             <foreach collection="branchDepartment" open="(" close=")" separator="," item="item">

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 66 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportDeleteMapper.xml


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

@@ -75,7 +75,7 @@
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN project_separate AS ps on b.id=ps.id
         LEFT JOIN user AS c ON a.creator_id=c.id
-        LEFT JOIN user_with_beisen AS uwb ON c.job_number=c.job_number
+        LEFT JOIN user_with_beisen AS uwb ON uwb.job_number=c.job_number
         left join sub_project as d on d.id = a.sub_project_id
         left join task on task.id = a.task_id
         left join report_extra_degree on report_extra_degree.id = a.degree_id
@@ -132,7 +132,7 @@
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN project_separate AS ps on b.id=ps.id
         LEFT JOIN user AS c ON a.creator_id=c.id
-        LEFT JOIN user_with_beisen AS uwb ON c.job_number=c.job_number
+        LEFT JOIN user_with_beisen AS uwb ON uwb.job_number=c.job_number
         left join sub_project as d on d.id = a.sub_project_id
         left join task on task.id = a.task_id
         left join report_extra_degree on report_extra_degree.id = a.degree_id

+ 11 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskMapper.xml

@@ -150,10 +150,17 @@
 
     <!-- 查询任务实际工时和计划工时对比,仅查询有实际工时的数据 -->
     <select id="getTaskTimeCompare" resultType="java.util.Map">
-        SELECT task.id , task.name AS name, task.plan_hours as planHours, IFNULL(SUM(report.`working_time`),0) AS workHours FROM report
-                                                                                                                                     LEFT JOIN task ON report.`task_id` = task.id AND report.state = 1
-        WHERE task.project_id = #{projectId}
-        GROUP BY task.id
+        SELECT t.id , t.name AS name ,IFNULL(SUM(te.plan_hours),0) AS planHours, IFNULL(SUM(r.`working_time`),0) AS workHours FROM
+        task_executor te
+        LEFT JOIN USER u ON te.executor_id=u.id
+        LEFT JOIN task t ON t.id=te.task_id
+        LEFT JOIN report r ON r.task_id=t.id AND r.state=1
+        LEFT JOIN project p ON p.id=t.project_id
+        WHERE p.id= #{projectId}
+        <if test="deptId!=null and deptId">
+            and u.department_id=#{deptId}
+        </if>
+        GROUP BY t.id
     </select>
 
     <!--查询任务,带实际工时-->

+ 1 - 0
fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json

@@ -935,6 +935,7 @@
   "missingfill": "Daily reminder missed filling on the day",
   "missingfills": "Daily reminder missed yesterday",
   "lastDayOfWeek": "Remind on the last day of current week",
+  "alertLastWeek": "Remind last week's missing report",
   "monthAlert": "Remind last month's missed report on fixed day",
   "morningtime": "morning time",
   "owntimeframe": "Choose your own time frame",

+ 1 - 0
fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json

@@ -945,6 +945,7 @@
   "missingfill": "每日提醒当天漏填",
   "missingfills": "每日提醒昨天漏填",
   "lastDayOfWeek": "每周最后一个工作日",
+  "alertLastWeek": "每周提醒上周漏填",
   "monthAlert": "每月固定日期提醒上个月",
   "remindertext": "提醒文本",
   "personneltoset": "不提醒人员设置",

+ 3 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -82,9 +82,9 @@
         <!-- 时间段筛选 ins == 6 || ins == 8 || ins == 9 || ins == 10 || ins == 11 || ins == 12 || ins == 5 || ins == 16 || ins == 17 || ins == 18 || ins == 20 || ins == 21 || ins == 22 -->
         <template v-if="screeningCondition.timePeriod.includes(ins)">
           <span>
-            <span class="demonstration" style="color:#999;padding:0 10px">
+            <!-- <span class="demonstration" style="color:#999;padding:0 10px">
               {{ ins == 15 ? $t('xiang-mu-chuang-jian-shi-jian-duan') : $t('message.period') }}
-            </span>
+            </span> -->
             <el-date-picker v-model="rangeDatas" type="daterange" value-format="yyyy-MM-dd" :placeholder="$t('selectstartdate')" @change="picks()" :range-separator="$t('other.to')" :start-placeholder="$t('time.startDate')" :end-placeholder="$t('time.endDate')" style="width:300px" :clearable="ins == 15" size="small"> </el-date-picker>
           </span>
         </template>
@@ -2495,6 +2495,7 @@ export default {
         monthStart: this.monthRange[0]+"-01",
         monthEnd: this.monthRange[1]+"-01",
         area: this.areaName || null,
+        userId:this.userId,
         pageIndex: this.page,
         pageSize: this.size
       }

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 509 - 385
fhKeeper/formulahousekeeper/timesheet/src/views/project/summary.vue


+ 1 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

@@ -217,6 +217,7 @@
                             <el-option :label="$t('missingfills')" :value="1"></el-option>
                             <el-option :label="$t('lastDayOfWeek')" :value="2"></el-option>
                             <el-option :label="$t('monthAlert')" :value="3"></el-option>
+                            <el-option :label="$t('alertLastWeek')" :value="4"></el-option>
                         </el-select>
                         <span v-if="timeType.alertType == 3" style="color:#606266;">(每月
                         <el-select v-model="timeType.alertDay" style="width:80px;">

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/team/index.vue

@@ -3764,7 +3764,7 @@ export default {
 
 <style scoped>
 .deteee{
-  font-size: 25px;
+  font-size: 18px;
   margin-bottom: 20px;
 }
 .deteeeAce {

+ 0 - 2
fhKeeper/formulahousekeeper/timesheet_h5/src/views/login/index.vue

@@ -108,7 +108,6 @@
                         console.log('urlRight=' + urlRight);
                         urlRight = urlRight.substring(0, urlRight.indexOf('#/'));
                         // window.location = urlLeft + "#/home" + urlRight;//拼接跳转
-                        alert(url);
                         //获取code
                         var code = urlRight.substring('?code='.length,urlRight.indexOf('&state='));
                         var passUserId = urlRight.substring(urlRight.indexOf('&state=')+'&state='.length);
@@ -303,7 +302,6 @@
                                 }else{
                                     corpId = url.substring(url.indexOf(key)+key.length,url.indexOf('#'));
                                 }
-                                alert('钉钉登录==='+corpId);
                                 this.isDingding = true
                                 dd.ready(function() {
                                     dd.runtime.permission.requestAuthCode({

+ 6 - 1
fhKeeper/formulahousekeeper/timesheet_h5/src/views/task/editask.vue

@@ -151,6 +151,9 @@
                         <div class="popupSearch" v-if="user.userNameNeedTranslate != '1'">
                             <van-search v-model="executor.searchText" placeholder="输入员工姓名搜索" @search="onSearch" shape="round" background="#F4F4F4"></van-search>
                         </div>
+                        <div class="popupSearch" v-if="user.userNameNeedTranslate == '1'">
+                            <van-search v-model="executor.searchText" placeholder="输入员工姓名搜索" @search="getOnSearch(executor.searchText)" shape="round" background="#F4F4F4"></van-search>
+                        </div>
 
                         <div class="popupCon conBorder">
                             <van-radio-group v-model="executor.item" class="popupItem marginNone borderNone">
@@ -421,7 +424,9 @@ export default {
             this.finishDateShow = false
         },
         
-        executorChange(item,index){           // 选择执行人
+        executorChange(item,index){  // 选择执行人
+            this.executor.searchText = ''
+            this.getOnSearch('')
             this.executor.show = true
             this.executor.index = index
             this.executor.searchList.forEach(u=>{if (u.id == item.executorId) {