Kaynağa Gözat

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

zhouyy 2 ay önce
ebeveyn
işleme
facd62f46d
76 değiştirilmiş dosya ile 3562 ekleme ve 511 silme
  1. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/index.html
  2. 7 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/my/index.vue
  3. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/build.bat
  4. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/node_modules.zip
  5. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login_logo.png
  6. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/index.vue
  7. 89 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/header/header.vue
  8. 4 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  9. 1 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/index.vue
  10. 3 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/AddPersonnelModal.vue
  11. 106 0
      fhKeeper/formulahousekeeper/inva_4_tivo/appMarket.html
  12. 138 0
      fhKeeper/formulahousekeeper/inva_4_tivo/css/appMarket.css
  13. 161 0
      fhKeeper/formulahousekeeper/inva_4_tivo/css/appMarket.less
  14. BIN
      fhKeeper/formulahousekeeper/inva_4_tivo/image/customerNew/login_logo.png
  15. BIN
      fhKeeper/formulahousekeeper/inva_4_tivo/image/followup/suifangaas.png
  16. BIN
      fhKeeper/formulahousekeeper/inva_4_tivo/image/ions/youjiantos.png
  17. 1 0
      fhKeeper/formulahousekeeper/inva_4_tivo/moduleView/header.html
  18. 40 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  19. 41 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  20. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/constant/Constant.java
  21. 47 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/EquipmentOwnerController.java
  22. 3 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  23. 15 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java
  24. 45 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/EquipmentOwner.java
  25. 12 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ExpenseSheet.java
  26. 8 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/User.java
  27. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/EquipmentOwnerMapper.java
  28. 24 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/EquipmentOwnerService.java
  29. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserService.java
  30. 112 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/EquipmentOwnerServiceImpl.java
  31. 143 31
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseSheetServiceImpl.java
  32. 6 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  33. 66 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  34. 8 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  35. 28 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  36. 4 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/ExcelUtil.java
  37. 17 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/EquipmentOwnerMapper.xml
  38. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ExpenseItemMapper.xml
  39. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml
  40. 88 88
      fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/package-lock.json
  41. 16 9
      fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/planView/component/planComponent.vue
  42. 61 13
      fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/planView/todayPlan/distribution.vue
  43. 1 1
      fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/statisticsView/statisticsDetail.vue
  44. 1 1
      fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/statisticsView/statisticsView.vue
  45. 28 7
      fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/workView/fillReport.vue
  46. 2 1
      fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/workView/workView.vue
  47. 104 2
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/plan/orderInsert.vue
  48. 109 11
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/plan/planComponent.vue
  49. 5 0
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/plan/planComponentDetil.vue
  50. 69 4
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/product/list.vue
  51. 4 0
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/settings/settings.vue
  52. 158 23
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/statistic/index.vue
  53. 0 3
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/team/index.vue
  54. 43 14
      fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/workReport/daily.vue
  55. 12 0
      fhKeeper/formulahousekeeper/timesheet/build-private.bat
  56. 5 23
      fhKeeper/formulahousekeeper/timesheet/index.html
  57. 156 0
      fhKeeper/formulahousekeeper/timesheet/setIndex/indexOne.html
  58. 127 0
      fhKeeper/formulahousekeeper/timesheet/setIndex/indexTwo.html
  59. 8 0
      fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue
  60. 282 53
      fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue
  61. 111 3
      fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue
  62. 5 0
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/my/children/center.vue
  63. 106 0
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/appMarket.html
  64. 138 0
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/css/appMarket.css
  65. 161 0
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/css/appMarket.less
  66. 196 196
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/customerNew.html
  67. BIN
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/image/customerNew/login_logo.png
  68. BIN
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/image/followup/suifangaas.png
  69. BIN
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/image/ions/youjiantos.png
  70. 106 0
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/appMarket.html
  71. 138 0
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/css/appMarket.css
  72. 161 0
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/css/appMarket.less
  73. 3 3
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/customerNew.html
  74. BIN
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/image/customerNew/login_logo.png
  75. BIN
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/image/followup/suifangaas.png
  76. BIN
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/image/ions/youjiantos.png

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/index.html

@@ -7,7 +7,7 @@
     <title>客户管家</title>
     <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" referrerpolicy="origin"></script>
     <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" referrerpolicy="origin"></script>
-    <script src="https://s.url.cn/qqun/qun/qqweb/m/qun/confession/js/vconsole.min.js "></script>
+    <!-- <script src="https://s.url.cn/qqun/qun/qqweb/m/qun/confession/js/vconsole.min.js "></script> -->
   </head>
   <body>
     <div id="app"></div>

+ 7 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/my/index.vue

@@ -12,6 +12,8 @@
           <div class="flex flex-col justify-center text-[#5D5D5D] leading-6">
             <div class="text-center">公司: {{ userInfo.userInfo?.company?.companyName }}</div>
             <div class="text-center">角色: {{ userInfo.userInfo?.roleName }}</div>
+
+            <div class="text-center text-[#075985] mt-2" @click="applicationMarket()">应用市场</div>
           </div>
         </div>
         
@@ -54,6 +56,11 @@ function judgingTheEnvironment() {
   isCorpWX.value = currentEnvironment.indexOf("wxwork") > 0 ? true : false
 }
 
+const applicationMarket = () => {
+  window.location.href = 'https://www.ttkuaiban.com/appMarket.html'
+  // window.open('https://www.ttkuaiban.com/appMarket.html', '_blank'); 
+}
+
 useLifecycle({
   load: () => {
     judgingTheEnvironment()

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/build.bat

@@ -0,0 +1 @@
+npm run build

BIN
fhKeeper/formulahousekeeper/customerBuler-crm/node_modules.zip


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


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

@@ -316,7 +316,7 @@ async function importBusiness(param: UploadRequestOptions) {
     allLoading.importLoading = false
   })
   if (res.code == 'ok') {
-    globalPopup?.showSuccess('导入成功' || '')
+    globalPopup?.showSuccess('导入成功')
     getCustomerTable()
     return
   }

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

@@ -47,6 +47,12 @@
     </div>
   </div>
   <div class="flex flex-row justify-start items-center text-white header-right">
+    <div class="cursor-pointer flex items-center">
+      <el-icon :size="24" @click="applicationMarket()">
+        <Menu />
+      </el-icon>
+      <div class="ml-2">应用市场</div>
+    </div>
     <el-badge :value="numberOfLogos" :max="99" class="ml-4 cursor-pointer h-[26px]" :show-zero="false">
       <el-icon :size="26" @click="newsDrawer = true">
         <Bell />
@@ -74,6 +80,7 @@
         </div>
         <div class="text-center leading-none text-slate-50 pb-3">角色:{{ userInfo.roleName }}</div>
         <div class="text-center leading-none text-slate-50 pb-3">公司:{{ userInfo.companyName }}</div>
+        <div class="text-center leading-none text-slate-50 pb-3"><el-link type="warning" @click="changePasswordClick()">修改密码</el-link></div>
         <div class="w-full drawerVisBtn" v-if="userInfo.userNameNeedTranslate != 1">
           <div @click="logout()">退出</div>
         </div>
@@ -124,18 +131,39 @@
       </div>
     </div>
   </el-drawer>
+
+  <!-- 修改密码 -->
+  <el-dialog v-model="changePasswordVlsable" title="修改密码" width="500">
+    <el-form ref="ruleFormRef" :model="changePasswordForm" class="mt-4" :rules="changePasswordRules" status-icon>
+      <el-form-item label="原密码" label-width="90px">
+        <el-input v-model.trim="changePasswordForm.originPassword" prop="originPassword" />
+      </el-form-item>
+      <el-form-item label="新密码" label-width="90px">
+        <el-input v-model.trim="changePasswordForm.newPassword" prop="newPassword" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="changePasswordVlsable = false">取消</el-button>
+        <el-button type="primary" @click="changePassword(ruleFormRef)">
+          确定
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
 </template>
 
 <!-- /information/list -->
 
 <script lang="ts" setup>
-import { onMounted, ref, watchEffect, watch } from 'vue';
+import { onMounted, ref, watchEffect, watch, reactive, inject } from 'vue';
 import { RouteRecordRaw, useRouter, useRoute } from 'vue-router';
 import { useStore } from "../../store/index"
 import { post, uploadFile } from "@/utils/request";
 import defaultCover from "../../assets/defaultCover.png";
 import { formatDate } from '@/utils/times'
 import loginLogin from '../../assets/login/login_logo.png'
+import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
 const { routers, clearStore, userInfo } = useStore()
 const router = useRouter();
 const route = useRoute()
@@ -153,6 +181,65 @@ const newsDrawer = ref(false)
 const newsDrawerLoading = ref(false)
 const numberOfLogos = ref(0)
 
+const changePasswordVlsable = ref(false)
+const changePasswordForm = ref({
+  originPassword: '',
+  newPassword: '',
+})
+
+interface RuleForm {
+  originPassword: string
+  newPassword: string
+}
+
+const changePasswordRules = reactive<FormRules<RuleForm>>({
+  originPassword: [
+    { required: true, message: '请输入原密码', trigger: 'blur' },
+  ],
+  newPassword: [
+    { required: true, message: '请输入新密码', trigger: 'blur' },
+  ],
+})
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const ruleFormRef = ref<FormInstance>()
+
+const applicationMarket = () => {
+  window.location.href = 'https://www.ttkuaiban.com/appMarket.html'
+  // window.open('https://www.ttkuaiban.com/appMarket.html', '_blank'); 
+}
+
+const changePassword = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  if(!changePasswordForm.value.originPassword) {
+    globalPopup?.showWarning('请填写原密码')
+    return
+  }
+  if(!changePasswordForm.value.newPassword) {
+    globalPopup?.showWarning('请填写新密码')
+    return
+  }
+  const fomrVal = {
+    ...changePasswordForm.value,
+    id: userInfo.id
+  }
+  post(`/user/editPassword`, { ...fomrVal }).then(_res => {
+    globalPopup?.showSuccess('修改成功')
+    setTimeout(() => {
+      logout()
+    }, 500)
+  }).catch(err => {
+    globalPopup?.showError(err.msg)
+  })
+}
+
+const changePasswordClick = () => {
+  changePasswordForm.value = {
+    originPassword: '',
+    newPassword: '',
+  }
+  changePasswordVlsable.value = true
+}
+
 const updateVisibleItems = () => {
   const parentWidth = (parentDiv.value?.offsetWidth && parentDiv.value?.offsetWidth - 150) || 10;
   const canvas = document.createElement('canvas');
@@ -348,7 +435,7 @@ watchEffect(() => {
 }
 
 .header-right {
-  width: 135px;
+  width: 220px;
 }
 
 .parentDiv {

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

@@ -66,10 +66,10 @@ const router = useRouter();
 const globalPopup = inject<GlobalPopup>('globalPopup')
 const ruleFormRef = ref<FormInstance>();
 const ruleForm = ref({
-  username: "18122222222",
-  password: "000000",
-  // username: "",
-  // password: "",
+  // username: "18122222222",
+  // password: "000000",
+  username: "",
+  password: "",
 });
 const loginLoading = ref(false);
 const rules = reactive<FormRules<typeof ruleForm>>({

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

@@ -366,7 +366,7 @@ async function importUser(param: UploadRequestOptions) {
   })
   loadingFrom.importLoading = false
   if (res.code == 'ok') {
-    globalPopup?.showSuccess('导入成功' || '')
+    globalPopup?.showSuccess('导入成功')
     closeModal('importVisible')
     getTableData()
     return
@@ -437,7 +437,6 @@ function changeBatch(flag: boolean = true) {
 }
 
 function addPersone(item: any) {
-  console.log(item)
   if (!item) {
     personnelFromData.value = {}
     dialogFrom.addPersonnelDialogVisible = true

+ 3 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/module/AddPersonnelModal.vue

@@ -33,7 +33,7 @@
                     <!-- <el-cascader v-model="personnelFrom.departmentId" :options="data.deptList" placeholder="请选择部门" :props="{ checkStrictly: true }" clearable style="width: 100%" /> -->
                     <tree-select v-model="personnelFrom.departmentId" :size="''" checkStrictly placeholder="请选择部门" :key="personnelFrom.departmentId"></tree-select>
                 </el-form-item>
-                <el-form-item label="角色">
+                <el-form-item label="角色" prop="roleId">
                     <el-select v-model="personnelFrom.roleId" placeholder="请选择角色" size="large">
                         <el-option v-for="item in data.roleList" :key="item.id" :label="item.rolename"
                             :value="item.id" />
@@ -99,7 +99,8 @@ const props = defineProps<Props>();
 
 // 定义校验规则
 const personnelRules = reactive<FormRules<typeof personnelFrom>>({ // 部门表单校验规则
-    name: [{ required: true, trigger: 'blur', message: '请输入姓名' }]
+    name: [{ required: true, trigger: 'blur', message: '请输入姓名' }],
+    roleId: [{ required: true, trigger: 'change', message: '请选择角色' }]
 })
 
 // 定义方法

+ 106 - 0
fhKeeper/formulahousekeeper/inva_4_tivo/appMarket.html

@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>应用市场</title>
+  <link rel="stylesheet" href="./css/reset.css">
+  <link rel="stylesheet" href="./css/appMarket.css">
+</head>
+
+<body>
+  <div class="applicationMarket">
+    <div class="applicationMarket-title">
+      <div class="ourServices">
+        我们的服务
+      </div>
+      <div class="applicationEncyclopedia">
+        权威认证--火石智能引擎,一站式攻克管理难题
+      </div>
+    </div>
+    <div class="topicContent">
+
+      <div class="bigCircle">
+        <a href="./index.html">
+          <div class="bigCircle-icon">
+            <img src="./image/gsgj.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              工时管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              工时管家基础版提供核心的工时填报、审核和统计功能,专业版增加了项目管理模块,包含立项、任务协同进度追踪、费用成本管控等功能。旗舰版涵盖了客户管理、合同管理、请假和出差管理模块,满足全面数字化办公需求。
+            </div>
+          </div>
+        </a>
+      </div>
+
+
+
+      <div class="bigCircle">
+        <a href="./customerNew.html">
+          <div class="bigCircle-icon">
+            <img src="./image/customerNew/login_logo.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              智能客户管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              客户管家是一款专为企业设计的客户关系管理系统(CRM),旨在通过智能化、高效化的管理手段,帮助企业节约营销成本、降低客户流失率,并提升客户追踪与数据处理的效率。主要用于企业的客户关系管理,通过整合客户信息、线索管理、商机挖掘、销售流程优化等功能,帮助企业更好地理解和服务客户,提升客户满意度和忠诚度,进而促进业务增长。
+            </div>
+          </div>
+        </a>
+      </div>
+
+      <div class="bigCircle">
+        <a href="./workshop.html">
+          <div class="bigCircle-icon">
+            <img src="./image/workshopimage/logo.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              生产车间管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              生产车间管家是一款专为解决生产管理、员工报工、数据统计等企业痛点的综合性管理软件。它不仅能够帮助企业实现生产流程的智能化管理,还能优化产品管理、排产计划、员工填报以及数据统计等多个环节,从而提升企业的整体运营效率和管理水平。
+            </div>
+          </div>
+        </a>
+      </div>
+
+
+      <div class="bigCircle">
+        <a href="./followup.html">
+          <div class="bigCircle-icon">
+            <img src="./image/followup/suifangaas.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              随访管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              随访管家是一款集患者资料收集整理、随访计划执行、和数据统计分析功能于一体的医患服务系统,帮助医院规范随访工作,提高随访效率,提升医疗水平,提高患者依从度。
+            </div>
+          </div>
+        </a>
+      </div>
+    </div>
+  </div>
+</body>
+
+</html>

+ 138 - 0
fhKeeper/formulahousekeeper/inva_4_tivo/css/appMarket.css

@@ -0,0 +1,138 @@
+html,
+body {
+  width: 100%;
+  height: 100%;
+  background-color: #f6f7fb;
+}
+div {
+  box-sizing: border-box;
+}
+.applicationMarket {
+  height: 100%;
+}
+.applicationMarket .applicationMarket-title {
+  width: 100%;
+  padding: 80px 0 60px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.applicationMarket .applicationMarket-title .ourServices {
+  width: 160px;
+  text-align: center;
+  font-size: 14px;
+  padding: 8px 0;
+  color: #63aefb;
+  border: 1px solid #63aefb;
+  border-radius: 6px;
+  background-color: rgba(99, 174, 251, 0.2);
+  margin: auto;
+  margin-bottom: 20px;
+}
+.applicationMarket .applicationMarket-title .applicationEncyclopedia {
+  text-align: center;
+  font-size: 28px;
+  font-weight: bold;
+  color: #000000;
+  margin-bottom: 0px;
+}
+.applicationMarket .topicContent {
+  width: 70%;
+  margin: auto;
+  display: flex;
+  justify-content: space-between;
+  flex-wrap: wrap;
+  margin-bottom: 60px;
+}
+.applicationMarket .topicContent .bigCircle {
+  width: 49.3%;
+  background-color: #fff;
+  border-radius: 6px;
+  height: 320px;
+  padding: 25px;
+  cursor: pointer;
+  border: 1px solid #fff;
+  margin-bottom: 20px;
+}
+.applicationMarket .topicContent .bigCircle a {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  box-sizing: border-box;
+}
+.applicationMarket .topicContent .bigCircle .bigCircle-icon {
+  width: 20%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding-right: 25px;
+}
+.applicationMarket .topicContent .bigCircle .textTitle {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title {
+  font-size: 24px;
+  color: #000000;
+  font-weight: bold;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title .textTitle-title-icon {
+  width: 30px;
+  height: 30px;
+  border-radius: 50%;
+  background-color: rgba(99, 174, 251, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title .textTitle-title-icon img {
+  width: 50%;
+  height: 50%;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-text {
+  font-size: 16px;
+  color: #999999;
+  margin-top: 15px;
+  line-height: 1.4;
+}
+.applicationMarket .topicContent .bigCircle:hover {
+  border: 1px solid #86bffb;
+  background-color: rgba(99, 174, 251, 0.2);
+}
+.applicationMarket .topicContent .bigCircle:hover .textTitle-title-icon {
+  background-color: #fff !important;
+}
+.applicationMarket img {
+  width: 100%;
+}
+@media only screen and (max-width: 768px) {
+  .applicationMarket .applicationMarket-title {
+    padding-bottom: 30px !important;
+  }
+  .applicationMarket .applicationMarket-title .applicationEncyclopedia {
+    font-size: 22px !important;
+  }
+  .applicationMarket .topicContent {
+    width: 85% !important;
+  }
+  .applicationMarket .bigCircle-icon {
+    width: 0 !important;
+    overflow: hidden !important;
+    padding: 0 !important;
+  }
+  .applicationMarket .topicContent {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
+  .applicationMarket .topicContent .bigCircle {
+    width: 100%;
+  }
+}

+ 161 - 0
fhKeeper/formulahousekeeper/inva_4_tivo/css/appMarket.less

@@ -0,0 +1,161 @@
+html,
+body {
+  width: 100%;
+  height: 100%;
+  background-color: #f6f7fb;
+}
+
+div {
+  box-sizing: border-box;
+}
+
+.applicationMarket {
+  height: 100%;
+  .applicationMarket-title {
+    width: 100%;
+    padding: 80px 0 60px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+
+    .ourServices {
+      width: 160px;
+      text-align: center;
+      font-size: 14px;
+      padding: 8px 0;
+      color: #63aefb;
+      border: 1px solid #63aefb;
+      border-radius: 6px;
+      background-color: rgba(99, 174, 251, 0.2);
+      margin: auto;
+      margin-bottom: 20px;
+    }
+    .applicationEncyclopedia {
+      text-align: center;
+      font-size: 28px;
+      font-weight: bold;
+      color: #000000;
+      margin-bottom: 0px;
+    }
+  }
+
+  .topicContent {
+    width: 70%;
+    margin: auto;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    margin-bottom: 60px;
+
+    .bigCircle {
+      width: 49.3%;
+      background-color: #fff;
+      border-radius: 6px;
+      height: 320px;
+      padding: 25px;
+      cursor: pointer;
+      border: 1px solid #fff;
+
+      a {
+        width: 100%;
+        height: 100%;
+        display: flex;
+        flex-direction: row;
+        box-sizing: border-box;
+        box-sizing: border-box;
+      }
+
+      .bigCircle-icon {
+        width: 20%;
+        height: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding-right: 25px;
+      }
+
+      .textTitle {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+
+        .textTitle-title {
+          font-size: 24px;
+          color: #000000;
+          font-weight: bold;
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+
+          .textTitle-title-icon {
+            width: 30px;
+            height: 30px;
+            border-radius: 50%;
+            background-color: rgba(99, 174, 251, 0.2);
+            display: flex;
+            justify-content: center;
+            align-items: center;
+
+            img {
+              width: 50%;
+              height: 50%;
+            }
+          }
+        }
+
+        .textTitle-text {
+          font-size: 16px;
+          color: #999999;
+          margin-top: 15px;
+          line-height: 1.4;
+        }
+      }
+
+      &:hover {
+        border: 1px solid #86bffb;
+        background-color: rgba(99, 174, 251, 0.2);
+
+        .textTitle-title-icon {
+          background-color: #fff !important;
+        }
+      }
+
+      &{
+        margin-bottom: 20px;
+      }
+    }
+  }
+
+  img {
+    width: 100%;
+  }
+}
+
+// 媒体查询
+@media only screen and (max-width: 768px) {
+  .applicationMarket {
+    .applicationMarket-title {
+      padding-bottom: 30px !important;
+      .applicationEncyclopedia {
+        font-size: 22px !important;
+      }
+    }
+    .topicContent {
+      width: 85% !important;
+    }
+    .bigCircle-icon {
+      width: 0 !important;
+      overflow: hidden !important;
+      padding: 0 !important;
+    }
+    .topicContent {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      .bigCircle {
+        width: 100%;
+      }
+    }
+  }
+}

BIN
fhKeeper/formulahousekeeper/inva_4_tivo/image/customerNew/login_logo.png


BIN
fhKeeper/formulahousekeeper/inva_4_tivo/image/followup/suifangaas.png


BIN
fhKeeper/formulahousekeeper/inva_4_tivo/image/ions/youjiantos.png


+ 1 - 0
fhKeeper/formulahousekeeper/inva_4_tivo/moduleView/header.html

@@ -69,6 +69,7 @@
             { label: '关于我们', value: '../about.html', class: 'header-item' },
             { label: '企业动态', value: '../dynamic.html', class: 'header-item' },
             { label: '知识园地', value: '/articleTemplate/pageList?pageIndex=1&pageSize=10', class: 'header-item' },
+            { label: '应用市场', value: '../appMarket.html', class: 'header-item' },
           ],
           otherList: [
             { label: '工时管家', path: '../index.html', icon: './image/icon/workHour.png', hoverIcon: './image/icon/workHourHover.png' },

+ 40 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -1429,6 +1429,46 @@ public class WeiXinCorpController {
                         originalDictList.add(remindDict1);originalDictList.add(remindDict2);originalDictList.add(remindDict3);
                         originalDictList.add(remindDict4);originalDictList.add(remindDict5);originalDictList.add(remindDict6);
                         originalDictList.add(remindDict7);originalDictList.add(remindDict8);
+
+                        String[] ClueSources = {"广告", "推销电话", "员工介绍", "外部介绍", "在线商场", "X(Twitter)", "Facebook", "合作伙伴", "公开媒介", "销售邮件", "合作伙伴研讨会", "研讨会内部", "交易会", "Web下载", "Web调研", "聊天", "其他"};
+                        for (int i = 0; i < ClueSources.length; i++) {
+                            originalDictList.add(new SysDict("ClueSources", ClueSources[i], i + 1, company.getId()));
+                        }
+
+                        String[] CustomLevel={"已获得", "活跃", "市场失败", "项目取消", "关闭"};
+                        for (int i = 0; i < CustomLevel.length; i++) {
+                            originalDictList.add(new SysDict("CustomLevel", CustomLevel[i], i + 1, company.getId()));
+                        }
+
+                        String[] CustomIndustry = {"ASP(应用服务提供商)", "数据/电信/OEM", "ERP(企业资源规划)", "政府/军队", "大企业", "管理软件提供商", "MSP(管理服务提供商)", "网络设备(企业)", "非管理ISV", "光网络", "服务提供商", "中小企业", "存储设备", "存储服务提供商", "系统集成", "无线企业", "咨询", "科技", "金融服务", "教育", "制造业", "通信", "房地产", "其他"};
+                        for (int i = 0; i < CustomIndustry.length; i++) {
+                            originalDictList.add(new SysDict("CustomIndustry", CustomIndustry[i], i + 1, company.getId()));
+                        }
+
+                        String[] CustomSources = {"广告", "推销电话", "员工介绍", "外部介绍", "在线商场", "X(Twitter)", "Facebook", "合作伙伴", "公开媒介", "销售邮件", "合作伙伴研讨会", "研讨会内部", "交易会", "Web下载", "Web调研", "聊天", "其他"};
+                        for (int i = 0; i < CustomSources.length; i++) {
+                            originalDictList.add(new SysDict("CustomSources", CustomSources[i], i + 1, company.getId()));
+                        }
+
+                        String[] ProductType = {"软件", "硬件", "服务", "咨询", "信息产品", "电子产品", "家用电器", "医疗设备", "化学品与材料", "能源产品", "其他"};
+                        for (int i = 0; i < ProductType.length; i++) {
+                            originalDictList.add(new SysDict("ProductType", ProductType[i], i + 1, company.getId()));
+                        }
+
+                        String[] ProductUnit = {"个", "件", "只", "条", "台", "套", "张", "千克", "吨", "克", "毫克"};
+                        for (int i = 0; i < ProductUnit.length; i++) {
+                            originalDictList.add(new SysDict("ProductUnit", ProductUnit[i], i + 1, company.getId()));
+                        }
+
+                        String[] OrderType = {"在线订购", "线下购买", "定制开发服务", "续约", "试用版", "教育培训课程", "捐赠购买", "其他"};
+                        for (int i = 0; i < OrderType.length; i++) {
+                            originalDictList.add(new SysDict("OrderType", OrderType[i], i + 1, company.getId()));
+                        }
+
+                        String[] ContractType = {"服务协议", "供应商合同", "联合合作协议", "知识产权授权", "咨询服务协议", "采购合同"};
+                        for (int i = 0; i < ContractType.length; i++) {
+                            originalDictList.add(new SysDict("ContractType", ContractType[i], i + 1, company.getId()));
+                        }
                         sysDictService.saveBatch(originalDictList);
 
                         //设置默认表单配置

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

@@ -1215,6 +1215,47 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             originalDictList.add(remindDict4);originalDictList.add(remindDict5);originalDictList.add(remindDict6);
             originalDictList.add(remindDict7);originalDictList.add(remindDict8);
 
+
+            String[] ClueSources = {"广告", "推销电话", "员工介绍", "外部介绍", "在线商场", "X(Twitter)", "Facebook", "合作伙伴", "公开媒介", "销售邮件", "合作伙伴研讨会", "研讨会内部", "交易会", "Web下载", "Web调研", "聊天", "其他"};
+            for (int i = 0; i < ClueSources.length; i++) {
+                originalDictList.add(new SysDict("ClueSources", ClueSources[i], i + 1, company.getId()));
+            }
+
+            String[] CustomLevel={"已获得", "活跃", "市场失败", "项目取消", "关闭"};
+            for (int i = 0; i < CustomLevel.length; i++) {
+                originalDictList.add(new SysDict("CustomLevel", CustomLevel[i], i + 1, company.getId()));
+            }
+
+            String[] CustomIndustry = {"ASP(应用服务提供商)", "数据/电信/OEM", "ERP(企业资源规划)", "政府/军队", "大企业", "管理软件提供商", "MSP(管理服务提供商)", "网络设备(企业)", "非管理ISV", "光网络", "服务提供商", "中小企业", "存储设备", "存储服务提供商", "系统集成", "无线企业", "咨询", "科技", "金融服务", "教育", "制造业", "通信", "房地产", "其他"};
+            for (int i = 0; i < CustomIndustry.length; i++) {
+                originalDictList.add(new SysDict("CustomIndustry", CustomIndustry[i], i + 1, company.getId()));
+            }
+
+            String[] CustomSources = {"广告", "推销电话", "员工介绍", "外部介绍", "在线商场", "X(Twitter)", "Facebook", "合作伙伴", "公开媒介", "销售邮件", "合作伙伴研讨会", "研讨会内部", "交易会", "Web下载", "Web调研", "聊天", "其他"};
+            for (int i = 0; i < CustomSources.length; i++) {
+                originalDictList.add(new SysDict("CustomSources", CustomSources[i], i + 1, company.getId()));
+            }
+
+            String[] ProductType = {"软件", "硬件", "服务", "咨询", "信息产品", "电子产品", "家用电器", "医疗设备", "化学品与材料", "能源产品", "其他"};
+            for (int i = 0; i < ProductType.length; i++) {
+                originalDictList.add(new SysDict("ProductType", ProductType[i], i + 1, company.getId()));
+            }
+
+            String[] ProductUnit = {"个", "件", "只", "条", "台", "套", "张", "千克", "吨", "克", "毫克"};
+            for (int i = 0; i < ProductUnit.length; i++) {
+                originalDictList.add(new SysDict("ProductUnit", ProductUnit[i], i + 1, company.getId()));
+            }
+
+            String[] OrderType = {"在线订购", "线下购买", "定制开发服务", "续约", "试用版", "教育培训课程", "捐赠购买", "其他"};
+            for (int i = 0; i < OrderType.length; i++) {
+                originalDictList.add(new SysDict("OrderType", OrderType[i], i + 1, company.getId()));
+            }
+
+            String[] ContractType = {"服务协议", "供应商合同", "联合合作协议", "知识产权授权", "咨询服务协议", "采购合同"};
+            for (int i = 0; i < ContractType.length; i++) {
+                originalDictList.add(new SysDict("ContractType", ContractType[i], i + 1, company.getId()));
+            }
+
 //            sysDictMapper.batchInsertDict(originalDictList);
             sysDictService.saveBatch(originalDictList);
 

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/constant/Constant.java

@@ -58,4 +58,6 @@ public class Constant {
     public static final String[] LEAVE_WAIT_CHECK= {"请假人","请假类型","请假时间","备注"};
     //请假审核通知
     public static final String[] LEAVE_CHECK= {"审核结果","审核人","请假时间","备注"};
+    
+    public static final int ZHE_ZHONG_COMPANY_ID=4811;
 }

+ 47 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/EquipmentOwnerController.java

@@ -0,0 +1,47 @@
+package com.management.platform.controller;
+
+
+import com.management.platform.entity.EquipmentOwner;
+import com.management.platform.service.EquipmentOwnerService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-02-21
+ */
+@RestController
+@RequestMapping("/equipment-owner")
+public class EquipmentOwnerController {
+
+    @Resource
+    private EquipmentOwnerService equipmentOwnerService;
+
+    @Resource
+    private HttpServletRequest request;
+    @RequestMapping("/addOrUpdate")
+    public HttpRespMsg addOrUpdate(EquipmentOwner equipmentOwner){
+        return equipmentOwnerService.addOrUpdate(equipmentOwner, request);
+    }
+
+    @RequestMapping("/getList")
+    public HttpRespMsg getList(){
+        return equipmentOwnerService.getList(request);
+    }
+
+    @RequestMapping("/removeEquipmentOwner")
+    public HttpRespMsg removeEquipmentOwner(Integer id){
+        return equipmentOwnerService.removeEquipmentOwner(id,request);
+    }
+
+}
+

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

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.pagehelper.util.StringUtil;
 import com.management.platform.config.LimitRequest;
+import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.MonthWorkingTimeVO;
 import com.management.platform.entity.vo.SysRichFunction;
@@ -1505,7 +1506,7 @@ public class ReportController {
                     //httpRespMsg.setError("每日工作时长不得超过"+comTimeType.getAllday()+"小时");
                     httpRespMsg.setError("每日工作时长不得少于" + comTimeType.getMinReportTime() + "小时");
                     return httpRespMsg;
-                } else if (company.getId() != 4811 && dailyWorktime > comTimeType.getMaxReportTime()) {//陕西柘中不做上限校验
+                } else if (company.getId() != Constant.ZHE_ZHONG_COMPANY_ID && dailyWorktime > comTimeType.getMaxReportTime()) {//陕西柘中不做上限校验
                     HttpRespMsg httpRespMsg = new HttpRespMsg();
                     //httpRespMsg.setError("每日工作时长不得超过"+comTimeType.getAllday()+"小时");
                     httpRespMsg.setError("每日工作时长不得超过" + comTimeType.getMaxReportTime() + "小时");
@@ -1515,7 +1516,7 @@ public class ReportController {
         }
 
         //校验填报工时
-        if (company.getId() != 4811) {
+        if (company.getId() != Constant.ZHE_ZHONG_COMPANY_ID) {
             List<Report> checkedUserDayList = new ArrayList<>();
             for (Report report : reportList) {
                 String creatorId = report.getCreatorId();

+ 15 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -1027,5 +1027,20 @@ public class UserController {
         return userService.unbindCorpWX(userId, request);
     }
 
+
+    @RequestMapping("/addUserIsMachine")
+    public HttpRespMsg addUsersIsMachine(String ids){
+        return userService.addUserIsMachine(ids, request);
+    }
+
+    @RequestMapping("/removeUserIsMachine")
+    public HttpRespMsg removeUserIsMachine(String id){
+        return userService.removeUserIsMachine(id, request);
+    }
+
+    @RequestMapping("/getUserIsMachineList")
+    public HttpRespMsg getUserIsMachineList(){
+        return userService.getUserIsMachineList(request);
+    }
 }
 

+ 45 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/EquipmentOwner.java

@@ -0,0 +1,45 @@
+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 com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-02-21
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class EquipmentOwner extends Model<EquipmentOwner> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("company_id")
+    private Integer companyId;
+
+    /**
+     * 设备归属人名称
+     */
+    @TableField("equipment_owner")
+    private String equipmentOwner;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 12 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ExpenseSheet.java

@@ -154,6 +154,18 @@ public class ExpenseSheet extends Model<ExpenseSheet> {
     @TableField("pay_way_name")
     private String payWayName;
 
+    @TableField("equipment_owner_id")
+    private Integer equipmentOwnerId;
+
+    @TableField(exist = false)
+    private String equipmentOwnerName;
+
+    /**
+     * 工程名称
+     */
+    @TableField(exist = false)
+    private String engineeringName;
+
 
     @Override
     protected Serializable pkVal() {

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

@@ -22,7 +22,7 @@ import org.springframework.format.annotation.DateTimeFormat;
  * </p>
  *
  * @author Seyason
- * @since 2023-08-16
+ * @since 2025-02-21
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -279,6 +279,7 @@ public class User extends Model<User> {
      */
     @TableField("feishu_userid")
     private String feishuUserid;
+
     /**
      * 飞书部门id
      */
@@ -304,10 +305,15 @@ public class User extends Model<User> {
     @TableField("user_group_id")
     private Integer userGroupId;
 
+    /**
+     * 1-否 2-是 是否属于机械费用下方人员
+     */
+    @TableField("is_machine_cost")
+    private Integer isMachineCost;
+
     @TableField(exist = false)
     private List<Department> userReportDeptList;
 
-
     @Override
     protected Serializable pkVal() {
         return this.id;

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

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.EquipmentOwner;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-02-21
+ */
+public interface EquipmentOwnerMapper extends BaseMapper<EquipmentOwner> {
+
+}

+ 24 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/EquipmentOwnerService.java

@@ -0,0 +1,24 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.EquipmentOwner;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.util.HttpRespMsg;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-02-21
+ */
+public interface EquipmentOwnerService extends IService<EquipmentOwner> {
+
+    HttpRespMsg addOrUpdate(EquipmentOwner equipmentOwner, HttpServletRequest request);
+
+    HttpRespMsg getList(HttpServletRequest request);
+
+    HttpRespMsg removeEquipmentOwner(Integer id, HttpServletRequest request);
+}

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

@@ -108,4 +108,10 @@ public interface UserService extends IService<User> {
     HttpRespMsg getSimpleActiveUserListPage(Integer pageIndex, Integer pageSize, Integer departmentId, HttpServletRequest request, String keyword, String cursor, String userIds) throws Exception;
 
     HttpRespMsg unbindCorpWX(String userId, HttpServletRequest request);
+
+    HttpRespMsg addUserIsMachine(String ids, HttpServletRequest request);
+
+    HttpRespMsg removeUserIsMachine(String id, HttpServletRequest request);
+
+    HttpRespMsg getUserIsMachineList(HttpServletRequest request);
 }

+ 112 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/EquipmentOwnerServiceImpl.java

@@ -0,0 +1,112 @@
+package com.management.platform.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.constant.Constant;
+import com.management.platform.entity.EquipmentOwner;
+import com.management.platform.entity.ExpenseSheet;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.EquipmentOwnerMapper;
+import com.management.platform.mapper.ExpenseSheetMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.EquipmentOwnerService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-02-21
+ */
+@Service
+public class EquipmentOwnerServiceImpl extends ServiceImpl<EquipmentOwnerMapper, EquipmentOwner> implements EquipmentOwnerService {
+
+    @Resource
+    private UserMapper  userMapper;
+    @Resource
+    private EquipmentOwnerMapper equipmentOwnerMapper;
+
+    @Resource
+    private ExpenseSheetMapper expenseSheetMapper;
+
+    @Override
+    public HttpRespMsg addOrUpdate(EquipmentOwner equipmentOwner, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        if (user.getCompanyId()!= Constant.ZHE_ZHONG_COMPANY_ID){
+            msg.setError("该公司无需操作设备归属人");
+            return msg;
+        }
+        if (equipmentOwner.getId()==null){
+            Integer count = equipmentOwnerMapper.selectCount(new QueryWrapper<EquipmentOwner>()
+                    .eq("equipment_owner", equipmentOwner.getEquipmentOwner())
+                    .eq("company_id", user.getCompanyId()));
+            if (count>0){
+                msg.setError("归属人名称:"+equipmentOwner.getEquipmentOwner()+",已存在");
+            }else {
+                equipmentOwner.setCompanyId(user.getCompanyId());
+                int insert = equipmentOwnerMapper.insert(equipmentOwner);
+                if (insert>0){
+                    return msg;
+                }else {
+                    msg.setError("添加失败");
+                    return msg;
+                }
+            }
+        }
+        else {
+            Integer count = equipmentOwnerMapper.selectCount(new QueryWrapper<EquipmentOwner>()
+                    .eq("equipment_owner", equipmentOwner.getEquipmentOwner())
+                    .ne("id", equipmentOwner.getId())
+                    .eq("company_id", user.getCompanyId()));
+            if (count>0){
+                msg.setError("归属人名称:"+equipmentOwner.getEquipmentOwner()+",已存在");
+            }else {
+                int update = equipmentOwnerMapper.updateById(equipmentOwner);
+                if (update>0){
+                    return msg;
+                }else {
+                    msg.setError("修改失败");
+                    return msg;
+                }
+            }
+        }
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg getList(HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        if (user.getCompanyId()!=Constant.ZHE_ZHONG_COMPANY_ID){
+            msg.setData(new ArrayList<EquipmentOwner>());
+        }else {
+            List<EquipmentOwner> selectedList = equipmentOwnerMapper.selectList(new QueryWrapper<EquipmentOwner>()
+                    .eq("company_id", user.getCompanyId()).orderByDesc("id"));
+            msg.setData(selectedList);
+        }
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg removeEquipmentOwner(Integer id, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        Integer count = expenseSheetMapper.selectCount(new QueryWrapper<ExpenseSheet>().eq("equipment_owner_id", id));
+        if (count>0){
+            msg.setError("存在报销单绑定该设备审核人,删除失败");
+        }else {
+            equipmentOwnerMapper.deleteById(id);
+        }
+        return msg;
+    }
+}

+ 143 - 31
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseSheetServiceImpl.java

@@ -18,6 +18,7 @@ import com.management.platform.service.*;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.EncryptedDocumentException;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.CellType;
@@ -54,6 +55,7 @@ import java.util.stream.Collectors;
  */
 @Service
 @Transactional
+@Slf4j
 public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, ExpenseSheet> implements ExpenseSheetService {
     @Value(value = "${upload.path}")
     private String path;
@@ -101,6 +103,9 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
     @Resource
     private CompanyDingdingService companyDingdingService;
 
+    @Resource
+    private EquipmentOwnerMapper equipmentOwnerMapper;
+
 
     @Override
     public HttpRespMsg add(ExpenseSheet sheet, String items, String userId) {
@@ -115,8 +120,16 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
         boolean isAuditor = functionDeptList.size() > 0;
         boolean isNew = false;
         if (sheet.getId() == null) {
+            if (((sheet.getTotalAmount()==null||sheet.getTotalAmount()==0)) &&expenseMainType!=null&&!sheet.getType().equals(expenseMainType.getId())){
+                msg.setError("费用金额不能为空或等于0");
+                return msg;
+            }
             //柘中公司
-            if (user.getCompanyId()==4811&&expenseMainType!=null&&sheet.getType().equals(expenseMainType.getId())){
+            if (user.getCompanyId()==Constant.ZHE_ZHONG_COMPANY_ID&&expenseMainType!=null&&sheet.getType().equals(expenseMainType.getId())){
+                if (sheet.getOwnerId().equals(userId)){
+                    msg.setError("机械费用不能自己给自己下发");
+                    return msg;
+                }
                 sheet.setStatus(4);//未填写
                 sheet.setReviewProcess(3);//未提交
             }else {
@@ -145,10 +158,23 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                 msg.setError(MessageUtils.message("other.billNoExist"));
                 return msg;
             }
-        } else {
-            if(user.getCompanyId()==4811&&user.getId().equals(sheet.getOwnerId())&&expenseMainType!=null&&sheet.getType().equals(expenseMainType.getId())){
+        }
+        else {
+            if (sheet.getStatus()!=2&&sheet.getStatus()!=3&&sheet.getStatus()!=4) {
+                msg.setError("报销单已提交,不能修改");
+                return msg;
+            }
+            if(user.getCompanyId()==Constant.ZHE_ZHONG_COMPANY_ID&&user.getId().equals(sheet.getOwnerId())&&expenseMainType!=null&&sheet.getType().equals(expenseMainType.getId())){
+                if (org.apache.commons.lang3.StringUtils.isEmpty(sheet.getFirstCheckerId())||org.apache.commons.lang3.StringUtils.isEmpty(sheet.getSecondCheckerId())){
+                    msg.setError("请选择第一审核人,第二审核人");
+                    return msg;
+                }
                 //柘中公司
-                if (sheet.getTotalAmount() > 0) {
+                if (sheet.getTotalAmount()==null||sheet.getTotalAmount()==0){
+                    msg.setError("费用金额不能为空或等于0");
+                    return msg;
+                }
+                if (sheet.getTotalAmount() >0) {
                     sheet.setStatus(1);//待审核
                     sheet.setReviewProcess(0);//待第一审核人审核
                 }
@@ -159,14 +185,19 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                         //默认系统中设置的有审核权限的人审核
                         if (isAuditor) {
                             sheet.setStatus(0);
+                            sheet.setReviewProcess(2);
                         } else {
                             sheet.setStatus(1);
+                            sheet.setReviewProcess(0);
                         }
+
                     } else if (auditSetting.getAuditType() == 1) {
                         //项目经理审核,默认为待审核状态
                         sheet.setStatus(1);
+                        sheet.setReviewProcess(0);
                     } else if (auditSetting.getAuditType() == 2) {
                         sheet.setStatus(1);//修改为待审核状态
+                        sheet.setReviewProcess(0);
                     }
                 }
             }
@@ -209,7 +240,7 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                     msg.setError("项目【"+p.getProjectName()+"】没有下拨"+settingName+"的预算");
                     return msg;
                 }
-                if (user.getCompanyId()!=4811){
+                if (user.getCompanyId()!=Constant.ZHE_ZHONG_COMPANY_ID){
                     //计算该项目当前已经填报的费用报销的金额
                     Double sumAmount = expenseItemMapper.selectSumAmountByProjectAndType(projectId, type);
                     if (amount + sumAmount > pCurCost.getBaseAmount()) {
@@ -296,12 +327,14 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
             if (auditSetting==null||auditSetting.getAuditType() == null || auditSetting.getAuditType() == 0) {
                 expenseItemService.remove(new QueryWrapper<ExpenseItem>().eq("expense_id", sheet.getId()));
                 expenseItemService.saveBatch(itemList);
-            } else {
+            }
+            else {
                 if (isAuditor) {
                     //有审核权限的人修改,直接修改
                     expenseItemService.remove(new QueryWrapper<ExpenseItem>().eq("expense_id", sheet.getId()));
                     expenseItemService.saveBatch(itemList);
-                } else {
+                }
+                else {
                     //已通过不能删除
                     QueryWrapper<ExpenseItem> queryWrapper = new QueryWrapper<ExpenseItem>().eq("expense_id", sheet.getId());
                     queryWrapper.eq("status", 0);
@@ -323,7 +356,7 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
             expenseItemService.saveBatch(itemList);
         }
 
-        if (isNew && auditSetting != null && auditSetting.getAuditType() == 1) {
+        if (isNew && auditSetting != null && auditSetting.getAuditType() == 1&& org.apache.commons.lang3.StringUtils.isNotEmpty(sheet.getFirstCheckerId())) {
             //发送给项目经理审核
             List<Integer> collect = itemList.stream().map(ExpenseItem::getProjectId).collect(Collectors.toList());
             if (collect.size() > 0) {
@@ -378,7 +411,8 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                     informationService.saveBatch(informationList);
                 }
             }
-        }else if (isNew && auditSetting != null && auditSetting.getAuditType() == 2) {
+        }
+        else if (isNew && auditSetting != null && auditSetting.getAuditType() == 2&&org.apache.commons.lang3.StringUtils.isNotEmpty(sheet.getFirstCheckerId())) {
             //发送给第一审核人审核
             List<User> targetUserList = new ArrayList<>();
             User firstChecker = userMapper.selectById(sheet.getFirstCheckerId());
@@ -429,6 +463,42 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
             }
             informationService.saveBatch(informationList);
         }
+        //柘中下发报销单 给报销人发送信息提醒
+        else if (isNew && auditSetting != null && auditSetting.getAuditType() == 2&&org.apache.commons.lang3.StringUtils.isEmpty(sheet.getFirstCheckerId())) {
+            //给报销人发送信息提醒
+            log.info("柘中给报销人下发报销单");
+            List<User> targetUserList = new ArrayList<>();
+            User owner = userMapper.selectById(sheet.getOwnerId());
+            targetUserList.add(owner);
+            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+            if (wxCorpInfo != null) {
+                //推送到企业微信
+                StringBuilder stringBuilder = new StringBuilder();
+                stringBuilder.append("$userName="+owner.getCorpwxUserid()+"$")
+                        .append(":有票据类型为机械费用的报销单待填写");
+                wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,owner.getCorpwxUserid(), stringBuilder.toString(), "expense",
+                        WxCorpInfoServiceImpl.TEXT_CARD_MSG_EXPENSE_UN);
+            }
+        }
+        //柘中报销人填写报销单信息,完善填报金额,第一审核人,第二审核人信息,给第一审核人发送信息
+        if (!isNew&& auditSetting != null && auditSetting.getAuditType() == 2&&sheet.getReviewProcess()==0){
+            log.info("柘中报销人填写报销单信息,完善填报金额,第一审核人,第二审核人信息,给第一审核人发送信息");
+            //发送给第一审核人审核
+            List<User> targetUserList = new ArrayList<>();
+            User firstChecker = userMapper.selectById(sheet.getFirstCheckerId());
+            targetUserList.add(firstChecker);
+            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+            if (wxCorpInfo != null) {
+                User targetUser = userMapper.selectById(sheet.getOwnerId());
+                //推送到企业微信
+                StringBuilder stringBuilder = new StringBuilder();
+                stringBuilder.append("报销人:").append("$userName="+targetUser.getCorpwxUserid()+"$")
+                        .append(",填写了机械费用报销单的信息,请及时审核");
+
+                wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,firstChecker.getCorpwxUserid(), stringBuilder.toString(), "expense",
+                        WxCorpInfoServiceImpl.TEXT_CARD_MSG_EXPENSE_NEED);
+            }
+        }
         return msg;
     }
 
@@ -444,10 +514,12 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
         QueryWrapper<ExpenseSheet> queryWrapper = new QueryWrapper<ExpenseSheet>();
         //当前用户
         String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         queryWrapper.eq("company_id", sheet.getCompanyId()).orderByDesc("id");
         ExpenseAuditSetting expenseAuditSetting = expenseAuditSettingMapper.selectById(sheet.getCompanyId());
-
+        List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", user.getCompanyId()));
+        List<EquipmentOwner> equipmentOwnerList = equipmentOwnerMapper.selectList(new QueryWrapper<EquipmentOwner>().eq("company_id", user.getCompanyId()));
         if (!StringUtils.isEmpty(sheet.getCode())) {
             queryWrapper.eq("code", sheet.getCode());
         }
@@ -462,7 +534,6 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
         if (expenseAuditSetting == null || expenseAuditSetting.getAuditType() == 0) {
             if (sheet.getStatus() != null &&  sheet.getStatus() == 1) {
                 //待审核列表,检查是否有权限
-                User user = userMapper.selectById(token);
                 List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "费用审核");
                 if (functionList.size() == 0) {
                     //无权查看待审核
@@ -535,13 +606,16 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                 IPage<ExpenseSheet> listIPager = expenseSheetMapper.selectPage(new Page<>(pageIndex, pageSize),
                         queryWrapper);
                 List<ExpenseSheet> records = listIPager.getRecords();
-
+                List<Integer> expenseSheetIds = records.stream().map(ExpenseSheet::getId).collect(Collectors.toList());
+                List<ExpenseItem> expenseItemList = expenseItemMapper.selectList(new QueryWrapper<ExpenseItem>().in(!expenseSheetIds.isEmpty(),"expense_id",expenseSheetIds));
                 List<ExpenseMainType> expenseMainTypes = expenseMainTypeService.list(new QueryWrapper<ExpenseMainType>().eq("company_id", sheet.getCompanyId()).or().eq("is_system",1));
                 records.forEach(re->{
                     Optional<ExpenseMainType> first = expenseMainTypes.stream().filter(et -> et.getId().equals(re.getType())).findFirst();
                     if(first.isPresent()){
                         re.setExpenseMainTypeName(first.get().getName());
                     }
+                    Optional<EquipmentOwner> equipmentOwnerOptional = equipmentOwnerList.stream().filter(eo -> re.getEquipmentOwnerId() != null && eo.getId().equals(re.getEquipmentOwnerId())).findFirst();
+                    equipmentOwnerOptional.ifPresent(equipmentOwner -> re.setEquipmentOwnerName(equipmentOwner.getEquipmentOwner()));
                 });
                 if (records.size()>0){
                     records.forEach(r->{
@@ -549,8 +623,17 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                                 .filter(e -> e.getExpenseId().equals(r.getId())&&e.getProjectId().equals(projectId)).collect(Collectors.toList());
                         double amount = items.stream().mapToDouble(item -> Optional.ofNullable(item.getAmount()).orElse(0.0)).sum();
                         r.setTotalAmount(amount);
+
+                        List<Integer> projectIds = expenseItemList.stream().filter(e -> e.getExpenseId().equals(r.getId())).map(ExpenseItem::getProjectId).distinct().collect(Collectors.toList());
+                        StringJoiner stringJoiner = new StringJoiner(",");
+                        for (Integer id : projectIds) {
+                            Optional<Project> optional = projectList.stream().filter(p -> p.getId().equals(id)).findFirst();
+                            optional.ifPresent(p->stringJoiner.add(p.getProjectName()));
+                        }
+                        r.setEngineeringName(stringJoiner.toString());
                     });
                 }
+
                 Long total = listIPager.getTotal();
                 Map<String, Object> map = new HashMap<>();
                 map.put("records", records);
@@ -559,16 +642,31 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                 return httpRespMsg;
             }
         }else {
+            if (user.getCompanyId()==Constant.ZHE_ZHONG_COMPANY_ID&& org.apache.commons.lang3.StringUtils.isNotEmpty(user.getRoleName())&&user.getRoleName().equals("费用管理员")){
+                queryWrapper.eq("operator_id",user.getId());
+            }
             IPage<ExpenseSheet> listIPager = expenseSheetMapper.selectPage(new Page<>(pageIndex, pageSize),
                     queryWrapper);
             List<ExpenseSheet> records = listIPager.getRecords();
-
+            List<Integer> expenseSheetIds = records.stream().map(ExpenseSheet::getId).collect(Collectors.toList());
+            List<ExpenseItem> expenseItemList = expenseItemMapper.selectList(new QueryWrapper<ExpenseItem>().in(!expenseSheetIds.isEmpty(),"expense_id",expenseSheetIds));
             List<ExpenseMainType> expenseMainTypes = expenseMainTypeService.list(new QueryWrapper<ExpenseMainType>().eq("company_id", sheet.getCompanyId()).or().eq("is_system",1));
             records.forEach(re->{
                 Optional<ExpenseMainType> first = expenseMainTypes.stream().filter(et -> et.getId().equals(re.getType())).findFirst();
                 if(first.isPresent()){
                     re.setExpenseMainTypeName(first.get().getName());
                 }
+                Optional<EquipmentOwner> equipmentOwnerOptional = equipmentOwnerList.stream().filter(eo -> re.getEquipmentOwnerId() != null && eo.getId().equals(re.getEquipmentOwnerId())).findFirst();
+                equipmentOwnerOptional.ifPresent(equipmentOwner -> re.setEquipmentOwnerName(equipmentOwner.getEquipmentOwner()));
+
+
+                List<Integer> projectIds = expenseItemList.stream().filter(e -> e.getExpenseId().equals(re.getId())).map(ExpenseItem::getProjectId).distinct().collect(Collectors.toList());
+                StringJoiner stringJoiner = new StringJoiner(",");
+                for (Integer id : projectIds) {
+                    Optional<Project> optional = projectList.stream().filter(p -> p.getId().equals(id)).findFirst();
+                    optional.ifPresent(p->stringJoiner.add(p.getProjectName()));
+                }
+                re.setEngineeringName(stringJoiner.toString());
             });
             Long total = listIPager.getTotal();
             Map<String, Object> map = new HashMap<>();
@@ -604,7 +702,9 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
     @Override
     public HttpRespMsg getDetail(Integer id,Integer projectId) {
         String token = request.getHeader("TOKEN");
+        User selectUser = userMapper.selectById(token);
         ExpenseSheet expenseSheet = expenseSheetMapper.selectById(id);
+        List<EquipmentOwner> equipmentOwnerList = equipmentOwnerMapper.selectList(new QueryWrapper<EquipmentOwner>().eq("company_id", selectUser.getCompanyId()));
         if(!StringUtils.isEmpty(expenseSheet.getFirstCheckerId())){
             User user = userMapper.selectById(expenseSheet.getFirstCheckerId());
             expenseSheet.setFirstCheckerName(user.getName());
@@ -648,6 +748,8 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
         double amount = list.stream().mapToDouble(item -> Optional.ofNullable(item.getAmount()).orElse(0.0)).sum();
         expenseSheet.setTotalAmount(amount);
         HttpRespMsg msg = new HttpRespMsg();
+        Optional<EquipmentOwner> equipmentOwnerOptional = equipmentOwnerList.stream().filter(eo -> expenseSheet.getEquipmentOwnerId() != null && eo.getId().equals(expenseSheet.getEquipmentOwnerId())).findFirst();
+        equipmentOwnerOptional.ifPresent(equipmentOwner -> expenseSheet.setEquipmentOwnerName(equipmentOwner.getEquipmentOwner()));
         msg.data = expenseSheet;
         return msg;
     }
@@ -667,7 +769,7 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                 User secondChecker = userMapper.selectById(sheet.getSecondCheckerId());
                 targetUserList.add(secondChecker);
                 WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
-                if (wxCorpInfo != null) {
+                if (wxCorpInfo != null&&user.getCompanyId()!=Constant.ZHE_ZHONG_COMPANY_ID) {
                     String corpUserString = targetUserList.stream().map(tl -> tl.getCorpwxUserid()).collect(Collectors.joining("|"));
                     User targetUser = userMapper.selectById(sheet.getOwnerId());
                     ExpenseMainType mainType = expenseMainTypeService.getById(sheet.getType());
@@ -698,23 +800,30 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
                     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=expense#wechat_redirect");
                     json.put("content_item",dataJson);
                     wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo,corpUserString, json);
-                }
 
-                List<Information> informationList=new ArrayList<>();
-                for (User item : targetUserList) {
-                    Information information=new Information();
-                    information.setUserId(item.getId());
-                    information.setTime(LocalDateTime.now());
-                    information.setMsg("费用报销待审核");
-                    information.setType(3);
-                    information.setContent(sheet.getCreateDate()+"");
-                    informationList.add(information);
+                    List<Information> informationList=new ArrayList<>();
+                    for (User item : targetUserList) {
+                        Information information=new Information();
+                        information.setUserId(item.getId());
+                        information.setTime(LocalDateTime.now());
+                        information.setMsg("费用报销待审核");
+                        information.setType(3);
+                        information.setContent(sheet.getCreateDate()+"");
+                        informationList.add(information);
+                    }
+                    informationService.saveBatch(informationList);
+                }{
+                    User targetUser = userMapper.selectById(sheet.getOwnerId());
+                    //推送到企业微信
+                    StringBuilder stringBuilder = new StringBuilder();
+                    stringBuilder.append("报销人:").append("$userName="+targetUser.getCorpwxUserid()+"$")
+                            .append(",填写了机械费用报销单的信息,请及时审核");
+
+                    wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,secondChecker.getCorpwxUserid(), stringBuilder.toString(), "expense",
+                            WxCorpInfoServiceImpl.TEXT_CARD_MSG_EXPENSE_NEED);
                 }
-                informationService.saveBatch(informationList);
-            }else if(sheet.getReviewProcess()!=null&&sheet.getReviewProcess()==1){
-                sheet.setReviewProcess(2);
-                sheet.setStatus(0);
-            }else if(sheet.getReviewProcess()!=null&&sheet.getReviewProcess()==0&&user.getCompanyId()==4811){
+            }
+            else if(sheet.getReviewProcess()!=null&&sheet.getReviewProcess()==1){
                 sheet.setReviewProcess(2);
                 sheet.setStatus(0);
             }
@@ -780,8 +889,11 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
         }
         stringBuilder.append("的费用报销申请。");
         if (sheet.getStatus() == 2) {
-            //驳回加原因
-            stringBuilder.append("原因: ").append(denyReason);
+            if (org.apache.commons.lang3.StringUtils.isNotEmpty(denyReason))
+            {
+                //驳回加原因
+                stringBuilder.append("原因: ").append(denyReason);
+            }
         }
 
         String ownerId = sheet.getOwnerId();

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

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.ImmutableMap;
+import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.*;
 import com.management.platform.mapper.*;
@@ -1694,7 +1695,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
         Company company = companyMapper.selectById(companyId);
         boolean isNew = true;
-        if (companyId==4811&&projectMainId==null){
+        if (companyId== Constant.ZHE_ZHONG_COMPANY_ID&&projectMainId==null){
             httpRespMsg.setError("请选择主项目");
             return httpRespMsg;
         }
@@ -3871,7 +3872,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         String[] statusNames = {"-",MessageUtils.message("excel.onGoing"),MessageUtils.message("excel.complete"),MessageUtils.message("excel.revoke"),MessageUtils.message("excel.pause")};
         List<List<String>> exportList = new ArrayList<>();
         List<ProjectMain> projectMainList=new ArrayList<>();
-        if (user.getCompanyId()==4811){
+        if (user.getCompanyId()==Constant.ZHE_ZHONG_COMPANY_ID){
             String[] titles = {MessageUtils.message("entry.projectId"),"主项目", MessageUtils.message("entry.projectName"),
                     MessageUtils.message("excel.charge"), MessageUtils.message("excel.projectAmount")+"(元)", MessageUtils.message("leave.status")
                     ,MessageUtils.message("excel.planStart"), MessageUtils.message("excel.planEnd"),
@@ -3891,7 +3892,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         for (Project project : projectList) {
             List<String> data = new ArrayList<>();
             data.add(project.getProjectCode() == null?"":project.getProjectCode());
-            if (user.getCompanyId()==4811){
+            if (user.getCompanyId()==Constant.ZHE_ZHONG_COMPANY_ID){
                 Optional<ProjectMain> first = projectMainList.stream().filter(pm -> project.getProjectMainId() != null && pm.getId().equals(project.getProjectMainId())).findFirst();
                 if (first.isPresent()){
                     data.add(org.apache.commons.lang3.StringUtils.isEmpty(first.get().getName())?"":first.get().getName());
@@ -4465,7 +4466,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         //获取表头
         List<ExpenseMainType> mainTypeList = expenseMainTypeMapper.selectList(new QueryWrapper<ExpenseMainType>().eq("company_id", companyId));
         List<Project> projectList=new ArrayList<>();
-        if (user.getCompanyId()==4811){
+        if (user.getCompanyId()==Constant.ZHE_ZHONG_COMPANY_ID){
             projectList = projectMapper.getProjectInAndOut(companyId, null, null, projectId,inchagerIds,projectMainId);
         }else {
             projectList = projectMapper.getProjectInAndOut(companyId, null, null, null,inchagerIds,null);
@@ -4481,7 +4482,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         }
 
         List<List<String>> exportList = new ArrayList<>();
-        if (user.getCompanyId()==4811){
+        if (user.getCompanyId()==Constant.ZHE_ZHONG_COMPANY_ID){
             String[] titles = {"项目编号","主项目","项目名称","合同金额(元)","总费用","利润","利润率","","人工成本"};
             ArrayList<String> strings = Lists.newArrayList(titles);
 

+ 66 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -6,6 +6,7 @@ import com.aliyun.dingtalkcontact_1_0.models.SearchUserResponse;
 import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -2698,6 +2699,71 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         return respMsg;
     }
 
+    @Override
+    public HttpRespMsg addUserIsMachine(String ids, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        if (user.getCompanyId()!=Constant.ZHE_ZHONG_COMPANY_ID){
+            msg.setError("该公司无需添加机械费用下发人员");
+            return msg;
+        }else {
+            if (StringUtils.isEmpty(ids)){
+                msg.setError("请选择机械费用下发人员");
+                return msg;
+            }else {
+                String[] idArray = ids.split(",");
+                List<String> idList = Arrays.stream(idArray).map(String::trim).collect(Collectors.toList());
+                int update = userMapper.update(null, new UpdateWrapper<User>().set("is_machine_cost", 2).in("id", idList));
+                if (update>0){
+                    return msg;
+                }else {
+                    msg.setError("修改失败");
+                    return msg;
+                }
+            }
+        }
+    }
+
+    @Override
+    public HttpRespMsg removeUserIsMachine(String id, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        if (user.getCompanyId()!=Constant.ZHE_ZHONG_COMPANY_ID){
+            msg.setError("该公司无需删除机械费用下发人员");
+            return msg;
+        }else {
+            if (StringUtils.isEmpty(id)){
+                msg.setError("请选择机械费用下发人员");
+                return msg;
+            }else {
+                int update = userMapper.update(null, new UpdateWrapper<User>().set("is_machine_cost", 1).eq("id", id));
+                if (update>0){
+                    return msg;
+                }else {
+                    msg.setError("修改失败");
+                    return msg;
+                }
+            }
+        }
+    }
+
+    @Override
+    public HttpRespMsg getUserIsMachineList(HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        if (user.getCompanyId()!=Constant.ZHE_ZHONG_COMPANY_ID){
+            msg.setData(new ArrayList<User>());
+            return msg;
+        }else {
+            List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", user.getCompanyId()).eq("is_machine_cost", 2));
+            msg.setData(userList);
+            return msg;
+        }
+    }
+
     @Override
     public HttpRespMsg getUserListByRole(HttpServletRequest request,String tableName) {
         HttpRespMsg httpRespMsg=new HttpRespMsg();

+ 8 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -115,6 +115,9 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     public static final int TEXT_CARD_MSG_TASK_FILE_UPDATE = 24;//任务文件更新
     public static final int TEXT_CARD_MSG_TASK_FILE_REJECT = 25;//任务文件驳回
 
+    public static final int TEXT_CARD_MSG_EXPENSE_NEED = 26;//费用报销待审核
+    public static final int TEXT_CARD_MSG_EXPENSE_UN = 27;//费用报销待填写
+
     private static Object userLock = new Object();
 
     @Value("${suitId}")
@@ -333,7 +336,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         try {
             log.info("发送企业微信消息===" + corpUserid);
             System.out.println("发送企业微信消息===" + corpUserid);
-            if (isDev) return;
+//            if (isDev) return;
             String accessToken = getCorpAccessToken(corpInfo);
             String url = URL_SEND_WXCORP_MSG.replaceAll("ACCESS_TOKEN", accessToken);
             HttpHeaders headers = new HttpHeaders();
@@ -387,6 +390,10 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                         title = "费用报销审核通过";
                     } else if (msgType.equals(TEXT_CARD_MSG_EXPENSE_DENY)) {
                         title = "费用报销审核驳回";
+                    } else if (msgType.equals(TEXT_CARD_MSG_EXPENSE_NEED)) {
+                        title = "费用报销待审核";
+                    }else if (msgType.equals(TEXT_CARD_MSG_EXPENSE_UN)) {
+                        title = "费用报销待填写";
                     }
                 }
                 else if ("task".equals(pageRouter)) {

+ 28 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
@@ -178,6 +179,15 @@ public class TimingTask {
     @Resource
     private TaskFilesMapper taskFilesMapper;
 
+    @Resource
+    private ExpenseSheetMapper expenseSheetMapper;
+
+    @Resource
+    private InformationService informationService;
+
+    @Resource
+    private ExpenseMainTypeService expenseMainTypeService;
+
 
     private static final List<Integer> VALID_TOKEN_CHARS = new ArrayList<>();
     static {
@@ -1187,6 +1197,24 @@ public class TimingTask {
         });
     }
 
+
+    //每天9点35分 自动检查柘中报销人填写报销单信息
+    @Scheduled(cron = "0 35 9 ? * *")
+    private void autoCheckZheZhongExpense() {
+        if (isDev) return;
+        List<ExpenseSheet> expenseSheetList = expenseSheetMapper.selectList(new QueryWrapper<ExpenseSheet>().eq("status", 4).eq("company_id", Constant.ZHE_ZHONG_COMPANY_ID));
+        if (!expenseSheetList.isEmpty()) {
+            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", Constant.ZHE_ZHONG_COMPANY_ID));
+            for (ExpenseSheet sheet : expenseSheetList) {
+                User owner = userMapper.selectById(sheet.getOwnerId());
+                StringBuilder stringBuilder = new StringBuilder();
+                stringBuilder.append("$userName="+owner.getCorpwxUserid()+"$")
+                        .append(":有票据类型为机械费用的报销单待填写");
+                wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,owner.getCorpwxUserid(), stringBuilder.toString(), "expense",
+                        WxCorpInfoServiceImpl.TEXT_CARD_MSG_EXPENSE_UN);
+            }
+        }
+    }
     //每天2点10分 自动审核超过指定天数的日报
     @Scheduled(cron = "0 10 2 ? * *")
     private void autoApprove() {

+ 4 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/ExcelUtil.java

@@ -588,8 +588,10 @@ public class ExcelUtil {
                 }
                 //合并单元格
                 CellRangeAddress cellRangeAddress = new CellRangeAddress(1,list.size()-1,7, 7);
-                //加入合并单元格对象
-                sheet.addMergedRegion(cellRangeAddress);
+                if (list.size()>=3) {
+                    //加入合并单元格对象
+                    sheet.addMergedRegion(cellRangeAddress);
+                }
 
 //                for(List<String> rowList : list) {
 //                    Row row = sheet.createRow(start);

+ 17 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/EquipmentOwnerMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.EquipmentOwnerMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.EquipmentOwner">
+        <id column="id" property="id" />
+        <result column="company_id" property="companyId" />
+        <result column="equipment_owner" property="equipmentOwner" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, company_id, equipment_owner
+    </sql>
+
+</mapper>

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ExpenseItemMapper.xml

@@ -49,7 +49,7 @@
         left join expense_sheet b on a.expense_id = b.id
         left join user on user.id = b.owner_id
         left join department on department.department_id = user.department_id
-        where a.project_id = #{projectId} order by a.happen_date desc
+        where a.project_id = #{projectId}  and b.status=0  order by a.happen_date desc
     </select>
 
     <select id="selectExpenseByProject" resultType="java.lang.Double">

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml

@@ -47,6 +47,7 @@
         <result column="feishu_deptid" property="feishuDeptid" />
         <result column="only_audit_once" property="onlyAuditOnce" />
         <result column="user_group_id" property="userGroupId" />
+        <result column="is_machine_cost" property="isMachineCost" />
     </resultMap>
     <resultMap id="BaseResultMap2" type="com.management.platform.entity.User">
         <id column="id" property="id" />

+ 88 - 88
fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/package-lock.json

@@ -1817,6 +1817,59 @@
           "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
           "dev": true
         },
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true,
+          "optional": true
+        },
+        "emojis-list": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+          "dev": true,
+          "optional": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
         "minimist": {
           "version": "1.2.5",
           "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz",
@@ -1846,6 +1899,41 @@
           "requires": {
             "ansi-regex": "^5.0.0"
           }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
+        "vue-loader-v16": {
+          "version": "npm:vue-loader@16.8.3",
+          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
+          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chalk": "^4.1.0",
+            "hash-sum": "^2.0.0",
+            "loader-utils": "^2.0.0"
+          },
+          "dependencies": {
+            "chalk": {
+              "version": "4.1.2",
+              "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+              "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+              }
+            }
+          }
         }
       }
     },
@@ -12112,94 +12200,6 @@
         }
       }
     },
-    "vue-loader-v16": {
-      "version": "npm:vue-loader@16.8.3",
-      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
-      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "chalk": "^4.1.0",
-        "hash-sum": "^2.0.0",
-        "loader-utils": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
-          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-          "dev": true,
-          "optional": true
-        },
-        "emojis-list": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz",
-          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
-          "dev": true,
-          "optional": true
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
-          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        }
-      }
-    },
     "vue-router": {
       "version": "3.5.1",
       "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.5.1.tgz?cache=0&sync_timestamp=1617697843139&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.5.1.tgz",

+ 16 - 9
fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/planView/component/planComponent.vue

@@ -20,6 +20,9 @@
                 <div class="PlanItem">
                   <div>项目代码:</div><span>{{ item.product.code }}</span>
                 </div>
+                <div class="PlanItem">
+                  <div>项目名称:</div><span>{{ item.product.projectName }}</span>
+                </div>
                 <div class="PlanItem">
                   <div>计划总工价:</div><span class="textBeyondHiding">{{item.totalMoney}}</span>
                 </div>
@@ -44,6 +47,9 @@
                 <div class="PlanItem">
                   <div>每辆数量:</div><span class="textBeyondHiding">{{ item.product.vehicleNumber }}</span>
                 </div>
+                <div class="PlanItem">
+                  <div>列序号:</div><span class="textBeyondHiding">{{ item.columnNumStart }}-{{ item.columnNumEnd }}</span>
+                </div>
                 <div class="PlanItemBtn">
                   <span class="text" @click="hidePlan(item.id,item.hideState)">
                     {{ jisuanDate(item.startDate)>30 ? '隐藏' : ''}}
@@ -284,26 +290,27 @@ export default {
         flex-wrap: wrap;
 
         .PlanItem {
-          width: 50%;
+          // width: 50%;
           display: flex;
           padding-top: 8px;
 
-          &:first-child {
-            width: 100%;
+          // &:first-child {
+          //   width: 100%;
 
-            span {
-              width: 200px;
-              word-break: break-all;
-            }
-          }
+          //   span {
+          //     width: 200px;
+          //     word-break: break-all;
+          //   }
+          // }
 
           div {
-            width: 100px;
+            width: 110px;
             text-align: right;
             color: #666;
           }
 
           span {
+            flex: 1;
             display: inline-block;
             color: #333;
           }

+ 61 - 13
fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/planView/todayPlan/distribution.vue

@@ -2,18 +2,22 @@
 <div>
   <div class="distribution">
     <van-nav-bar :title="titleText" left-text="返回" :right-text="!todayAndTomorrow ? '下发计划' : ''" @click-left="back" @click-right="placeAnOrder" fixed left-arrow/>
-    <div class="distribution_header">
-      <div>{{ productName }}</div>
-      <div>{{ productSchedulingNum }}</div>
-      <div>{{ dates }}</div>
+    <div style="display: flex;justify-content: space-between;">
+      <div class="distribution_header">
+        <div>{{ productName }}</div>
+        <div>{{ productSchedulingNum }}</div>
+        <div>{{ dates }}</div>
+      </div>
+      <van-button @click="batchUnReceive()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量拒收</van-button>
     </div>
+    
     <div class="distribution_con contentRoll">
       <div class="distribution_box" v-for="item,index in distributionList" :key="index">
         <div class="distribution_ItemBom">
-          <van-checkbox v-if="todayAndTomorrow" :disabled="item.checkboxDisabled"  v-model="item.prodProcedure.isSelected"  @click="itemChecked" shape="square">
+          <van-checkbox v-if="todayAndTomorrow" :disabled="item.checkboxDisabled  || (item.teamNames&&item.teamNames.indexOf(user.name) == -1)"  v-model="item.prodProcedure.isSelected"  @click="itemChecked" shape="square">
           </van-checkbox>
           <div class="PlanItem">
-            <span>{{ item.prodProcedure.name }}</span>
+            <span>{{item.prodProcedure.seq}}. {{ item.prodProcedure.name }}</span>
           </div>
           <div class="PlanItem">
             <div>单件工价:</div><span class="textBeyondHiding">{{ item.prodProcedure.unitPrice }}</span>
@@ -55,7 +59,7 @@
                             <span class="" v-if="second_item.status==0&&beDeptList" @click="deletePeople(second_item.id)"  style="color: #1989fa;">删除</span>
                       </div>
                       <p style="margin-top:20px;">
-                        <span class="" v-if="beDeptList" @click="distributionProp(item,index,'add')"  style="color: #1989fa;">新增</span>
+                        <span class="" v-if="beDeptList && item.totalProgress<100" @click="distributionProp(item,index,'add')"  style="color: #1989fa;">新增</span>
                       </p>
                     </div>
                 </div>
@@ -72,8 +76,8 @@
   <div class="formBatch" v-if="todayAndTomorrow">
         <van-checkbox v-model="isAllChecked" :disabled="distributionList.length == 0" @click="allChecked" shape="square" style="padding-left:3vw"></van-checkbox>
         <div style="padding:1vh 2vw">
-        <van-button @click="batchReceive()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量接收</van-button>
-        <!-- <van-button @click="cancellationReceiveBatch()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量取消接收</van-button> -->
+        <van-button style="margin-right: 10px;" @click="batchReceive()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量接收</van-button>
+        <van-button @click="cancellationReceiveBatch()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量取消接收</van-button>
         <!-- <van-button @click="batchAgree(false)" :disabled="!isCanAgree || distributionList.length == 0" type="danger" size="small" style="margin-left:2vw">批量驳回</van-button> -->
         </div>
   </div>
@@ -118,6 +122,7 @@ export default {
       ChooseSomeoneKey: 1,
 
       peopleListIdObj: null, // 杯换人的所有信息
+
     };
   },
   computed: {},
@@ -148,7 +153,7 @@ export default {
         let resArr=  this.distributionList.map(item=>{
           if(item.prodProcedure.isSelected){
             if(item.prodProcedureTeamList.filter(i=>i.userId==this.user.id).length>0){
-               return item.prodProcedureTeamList.filter(i=>i.userId==this.user.id)[0].planProcedureId
+               return item.prodProcedureTeamList.filter(i=>i.userId==this.user.id)[0].id
             }else{
               return "-1"
             }
@@ -176,18 +181,27 @@ export default {
     },
     // 批量操作
     allChecked(){
+        let status=false
         if(this.isAllChecked){
             for(let i in this.distributionList){
-                this.distributionList[i].prodProcedure.isSelected = true
-                console.log('===============');
+                if(this.distributionList[i].teamNames&&this.distributionList[i].teamNames.indexOf(this.user.name) != -1){
+                  this.distributionList[i].prodProcedure.isSelected = true
+                  status=true
+                }
             }
             this.isCanAgree = true
+            if(!status){
+              this.$toast.success('当前不存在可以接受/拒收工序');
+              this.isCanAgree = false
+              this.isAllChecked=false
+            }
         }else{
             for(let i in this.distributionList){
                 this.distributionList[i].prodProcedure.isSelected = false
             }
             this.isCanAgree = false
         }
+        console.log(this.distributionList)
         this.$forceUpdate();
     },
     itemChecked(){
@@ -237,6 +251,40 @@ export default {
             }).catch(err => { this.$toast.clear(); })
         }
     },
+    batchUnReceive(bol){
+        let ids = ''
+        console.log(this.user)
+        let resArr=  this.distributionList.map(item=>{
+          if(item.prodProcedure.isSelected){
+            if(item.prodProcedureTeamList.filter(i=>i.userId==this.user.id).length>0){
+               return item.prodProcedureTeamList.filter(i=>i.userId==this.user.id)[0].id
+            }else{
+              return "-1"
+            }
+          }
+         })
+         console.log('res===============',resArr)
+         ids = resArr.join(",").trim()
+        if(resArr.length > 0){
+            this.$axios.post(
+              "/plan/unReceivePlan",
+              {
+                ids:ids
+              }
+            ).then(res => {
+              if (res.code === "ok") {
+                this.isAllChecked=false
+                this.isCanAgree=false
+                this.getDistributionList()
+                this.$toast.success('拒收成功');
+              } else {
+                this.$toast.clear();
+                console.log("bbb")
+                this.$toast.fail(res.msg);
+              }
+            }).catch(err => { this.$toast.clear(); })
+        }
+    },
     workShowHide(index) {
       this.distributionList[index].flg = !this.distributionList[index].flg;
       console.log('=========>',this.distributionList[index].flg)
@@ -309,7 +357,7 @@ export default {
           for(var i in arr) {
             arr[i].checkboxDisabled = true
             if(arr[i].prodProcedureTeamList&&arr[i].prodProcedureTeamList.length > 0) {
-              let arrList = arr[i].prodProcedureTeamList.filter(item => item.status == 0 && item.userId==this.user.id)
+              let arrList = arr[i].prodProcedureTeamList.filter(item => (item.status == 0||item.status == 1) && item.userId==this.user.id)
               console.log(arrList, 'arrList')
               if(arrList.length > 0) {
                 arr[i].checkboxDisabled = false

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/statisticsView/statisticsDetail.vue

@@ -84,7 +84,7 @@ export default {
         detailStatus:0,
         userId:this.userId,
       };
-      this.$axios.post("/report/getPersonWorkHoursWagesDetail", postData)
+      this.$axios.post("/report/getPersonWorkHoursWagesDetailForMob", postData)
         .then(res => {
           this.saving = false;
             if(res.code == "ok") {

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/statisticsView/statisticsView.vue

@@ -102,7 +102,7 @@ export default {
         endDate:this.endDate,
         checkStatus:this.checkStatus
       };
-      this.$axios.post("/report/getPersonWorkHoursWagesDetail", postData)
+      this.$axios.post("/report/getPersonWorkHoursWagesDetailForMob", postData)
         .then(res => {
           this.saving = false;
             if(res.code == "ok") {

+ 28 - 7
fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/workView/fillReport.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="distribution">
     <van-nav-bar title="报工" left-text="返回" @click-left="back" fixed left-arrow />
-    <van-cell title="报工日期" :value="reportDate" @click="reportDateShow = true" is-link>
+    <van-cell title="报工日期" :value="reportDate" @click="showReportDate" is-link>
     </van-cell>
     <van-cell title="产品名称" :value="reportForm.product_name"></van-cell>
     <van-cell :title="reportForm.plan_type == 0?'排产工单号':'任务变更通知号'" :value="reportForm.plan_type == 0 ? reportForm.product_scheduling_num : reportForm.task_change_notice_num"></van-cell>
@@ -37,13 +37,13 @@
               <van-stepper v-model="reportForm.finishNum" step="0.1" :min="0" :max="reportForm.num" :decimal-length="2" @change="onFinishNumChange"/>
             </template>
           </van-cell>
-          <van-cell title="完成全部工作" >
+          <!-- <van-cell title="完成全部工作" >
             <template>
               <div style="float:right;">
                 <van-checkbox v-model="reportForm.isFinish" />
               </div>
             </template>
-          </van-cell>
+          </van-cell> -->
           <van-cell title="中止工作" v-if="!reportForm.isFinish">
             <template>
               <div style="float:right;">
@@ -57,7 +57,7 @@
           </van-cell>
         </van-cell-group>
         <div style="margin: 16px;">
-          <van-button round block type="primary" native-type="submit" :loading="saving">
+          <van-button round block type="primary" native-type="submit" v-if="supplementaryReportFlag || dateOfTheDay == reportDate" :loading="saving">
             提交
           </van-button>
           <p v-if="reportForm.canBeDeleted" @click="deleteReport" style="margin:16px;text-align:center;color:#666;">删除</p>
@@ -101,7 +101,9 @@ export default {
         progress: 10,
       },
       inputSteelNum:null,
-      oldPlanSteelStampNumberList:[]
+      oldPlanSteelStampNumberList:[],
+      supplementaryReportFlag: true, // 是否补报
+      dateOfTheDay: this.getDateOfTheDay(), // 当天日期
     };
   },
   computed: {},
@@ -116,8 +118,24 @@ export default {
     this.reportId = this.$route.query.otherId;
 
     this.getMyPlanProcedureList();
+    const { functionList = [] } = this.user
+    this.supplementaryReportFlag = functionList.filter(item => item.name == '补报').length > 0
   },
   methods: {
+    // 获取当天的日期 YYYY-MM-DD
+    getDateOfTheDay() {
+      const date = new Date();
+      const year = date.getFullYear();
+      const month = date.getMonth() + 1;
+      const day = date.getDate();
+      return `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`;
+    },
+    showReportDate() {
+      if(!this.supplementaryReportFlag) {
+        return
+      }
+      this.reportDateShow = true
+    },
     formatDate(date) {
       // 中国标准时间转成 YYYY-MM-DD
       const year = date.getFullYear();
@@ -156,7 +174,9 @@ export default {
       //件数发生改变时,检测如果和计划总件数一样,则算完成
       if (this.reportForm.finishNum == this.reportForm.num) {
           this.$set(this.reportForm, 'isFinish',true);
-      } 
+      } else {
+         this.$set(this.reportForm, 'isFinish',false);
+      }
     },
     back() {
       this.$router.go(-1);
@@ -226,8 +246,9 @@ export default {
         .then(res => {
           this.saving = false;
           if (res.code == "ok") {
+            this.$toast.success('提交成功')
           } else {
-            this.$toast.fail(res.msg);
+            this.$toast.fail({ message: res.msg, duration: 5000});
           }
         }).catch(err => { this.$toast.clear(); });
     },

+ 2 - 1
fhKeeper/formulahousekeeper/timesheet-workshop-h5-stand/src/views/workView/workView.vue

@@ -47,7 +47,7 @@
             <div v-if="reportBoolean" class="marginBtnPro">{{ item.productSchedulingNum }}</div>
             <div>
               <van-row>
-                <van-col span="19">{{ prod.plan_type == 0 ? item.procedure_name : prod.task_change_notice_num }}</van-col>
+                <van-col span="19">{{item.seq}}. {{ prod.plan_type == 0 ? item.procedure_name : prod.task_change_notice_num }}</van-col>
                 <van-col span="5" style="text-align:right;"><span style="color:goldenrod;font-size:16px;">{{ item.work_time
                 }}</span> <span style="font-size:12px;">分钟</span></van-col>
               </van-row>
@@ -257,6 +257,7 @@ export default {
             job_of_money: item.jobOfMoney,
             plan_check_type: item.planCheckType,
             procedure_name: item.procedureName,
+            seq: item.seq,
             progress: item.progress,
             work_time: item.workingTime,
             finishNum: item.finishNum,

+ 104 - 2
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/plan/orderInsert.vue

@@ -15,6 +15,8 @@
           </div>
         </div>
         <div class="OutSide_right">
+          <el-link type="primary" :underline="false" @click="showReportingDialog()">{{ "同步临时报工"
+          }}</el-link>
           <el-link type="primary" :underline="false" @click="(taskTypeDialog = true)">{{ "任务类型管理"
           }}</el-link>
           <el-link type="primary" :underline="false" @click="addPlan()">{{
@@ -131,9 +133,10 @@
           </el-form-item>
           <el-form-item label="计划工时" prop="planWorkHour">
             <div style="display: flex;">
-              <el-input v-model="todayPlanForm.planWorkHour" type="number" placeholder="请输入" style="flex: 1;"
+              <el-input v-model="todayPlanForm.planWorkHour" type="number" placeholder="请输入" style="width: 100px"
                 maxlength="5"></el-input>
               <div style="margin-left: 10px;">分钟</div>
+              <div style="margin-left: 10px;">{{ hourNum }} 小时</div>
             </div>
           </el-form-item>
           <el-form-item label="单价" prop="moneyOfJob">
@@ -167,6 +170,9 @@
               value-format="yyyy-MM-dd">
             </el-date-picker>
           </el-form-item>
+          <el-form-item label="结算总额(元)" prop="settlementAmount">
+            <el-input v-model="todayPlanForm.settlementAmount"></el-input>
+          </el-form-item>
           <el-form-item label="描述" style="width: 100%">
             <el-input type="textarea" :rows="6" placeholder="请输入描述" v-model="todayPlanForm.describtion" maxlength="200">
             </el-input>
@@ -218,6 +224,29 @@
       </span>
     </el-dialog>
 
+    <!-- 同步临时报工 -->
+    <el-dialog title="同步临时报工" :visible.sync="synchronousReportingDialog" width="600px" :before-close="handleClose">
+      <div class="tongbu">
+        <div :style="`color: ${reportWorkDayDisable ? 'red' : '#999'}`">选择的日期在三十天内</div>
+        <el-date-picker
+          v-model="reportWorkDay"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          :clearable="false"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="handleDateChange">
+        </el-date-picker>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="
+          (synchronousReportingDialog = false)
+          ">取 消</el-button>
+        <el-button type="primary" :loading="reportWorkLoading" :disabled="reportWorkDayDisable" @click="reportWorkCli()">确定</el-button>
+      </span>
+    </el-dialog>
+
     <!-- 任务类型新增 -->
     <el-dialog title="新增任务类型" :visible.sync="taskTypeAddDialog" width="800" :before-close="handleClose">
       <div>
@@ -286,6 +315,10 @@ export default {
   },
   data() {
     return {
+      synchronousReportingDialog: false, 
+      reportWorkDay: [],
+      reportWorkDayDisable: false,
+      reportWorkLoading: false,
       steelStampNumber: "",
       todayDate: this.dayjs().format('YYYY-MM-DD'),
       planDate: this.dayjs().format('YYYY-MM-DD'),
@@ -370,7 +403,13 @@ export default {
       }
     };
   },
-  computed: {},
+  computed: {
+    hourNum() {
+      let hour = Math.floor((this.todayPlanForm.planWorkHour || 0) / 60);
+      let xiaos = (this.todayPlanForm.planWorkHour || 0) % 60
+      return `${hour}.${xiaos}`
+    }
+  },
   watch: {},
   mounted() {
     this.getDepartmentList(),
@@ -380,6 +419,55 @@ export default {
       this.getTaskTypeList();
   },
   methods: {
+    reportWorkCli() {
+      this.reportWorkLoading = true;
+      this.http.post(
+        "/wx-corp-info/testSyncTemporaryJobApplication",
+        { startDate: this.reportWorkDay[0], endDate: this.reportWorkDay[1] },
+        (res) => {
+          this.reportWorkLoading = false;
+          if (res.code == "ok") {
+            this.synchronousReportingDialog = false
+            this.$message({
+              message: '同步成功',
+              type: "success",
+            });
+            this.getTableData()
+          } else {
+            this.$message({
+              message: res.msg,
+              type: "error",
+            });
+          }
+        },
+        (error) => {
+          this.reportWorkLoading = false;
+          this.$message({
+            message: error,
+            type: "error",
+          });
+        }
+      );
+    },
+    // 显示临时报工
+    showReportingDialog() {
+      this.reportWorkDay = [this.dayjs().format('YYYY-MM-DD'), this.dayjs().format('YYYY-MM-DD')]
+      this.synchronousReportingDialog = true
+    },
+    handleDateChange(value) {
+      const startDate = value[0];
+      const endDate = value[1];
+      const d1 = this.dayjs(startDate);
+      const d2 = this.dayjs(endDate);
+      const diffDays = Math.abs(d1.diff(d2, 'day'));
+      if (diffDays > 30) {
+        this.reportWorkDayDisable = true
+        console.log('日期相隔超过三十天');
+      } else {
+        console.log('日期相隔不超过三十天');
+        this.reportWorkDayDisable = false
+      }
+    },
     // 初始化 Form
     initTodayPlanForm() {
       this.todayPlanForm = {
@@ -1048,6 +1136,20 @@ export default {
 };
 </script>
 <style scoped lang='scss'>
+
+.tongbu {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  &>div {
+    margin-bottom: 15px;
+    color: #999;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
 .colorText {
   color: #02a7f0;
   cursor: pointer;

+ 109 - 11
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/plan/planComponent.vue

@@ -18,6 +18,17 @@
             <span class="demonstration">{{ "钢印号" }}</span><el-input v-model="steelStampNumber" size="small"
               @change="getTableData(hasChooseDept)" placeholder="请输入内容" clearable="true"></el-input>
           </div>
+          <div class="OutSide" style="padding-bottom: 0;">
+              <el-input placeholder="请输入内容"  v-model="searchValue" class="input-with-select" size="small">
+              <el-select v-model="searchType" slot="prepend" placeholder="请选择">
+                <el-option label="排产工单号" value="1"></el-option>
+                <el-option label="项目名称" value="2"></el-option>
+                <el-option label="产品名称" value="3"></el-option>
+                <el-option label="订单号" value="4"></el-option>
+              </el-select>
+              <el-button slot="append" icon="el-icon-search" @click="getTableData()"></el-button>
+            </el-input>
+          </div>
         </div>
         <div class="OutSide_right">
           <!-- <el-link type="primary" :underline="false" @click="(deptSetDialog = true), getPlanDeptSet()">{{ "部门设置"
@@ -84,6 +95,10 @@
               </div>
             </template>
           </el-table-column>
+          <el-table-column prop="productOrderNum" label="生产订单号" width="180">
+          </el-table-column>
+          <el-table-column prop="projectName" label="项目名称" width="180">
+          </el-table-column>
           <el-table-column prop="productName" label="产品名称" width="180">
           </el-table-column>
           <el-table-column prop="projectCode" label="项目代码" width="180">
@@ -133,16 +148,25 @@
           <el-form-item label="排产工单号" style="width: 100%" prop="productSchedulingNum">
             <el-input v-model="todayPlanForm.productSchedulingNum" maxlength="50"></el-input>
           </el-form-item>
+          <el-form-item label="生产订单号" style="width: 100%" prop="productOrderNum">
+            <el-input v-model="todayPlanForm.productOrderNum" maxlength="50"></el-input>
+          </el-form-item>
+          <el-form-item label="项目名称" style="width: 100%" prop="projectName">
+            <!-- <el-input :disabled="todayPlanForm.id==null?false:true"  v-model="todayPlanForm.projectName" maxlength="50" @blur="filterProductList(todayPlanForm.projectName)"></el-input> -->
+            <el-select :disabled="todayPlanForm.id==null?false:true" filterable remote reserve-keyword :remote-method="getProjectNames" @change="filterProductList(todayPlanForm.projectName)" v-model="todayPlanForm.projectName" placeholder="请输入项目名称" class="w100">
+              <el-option v-for="item in projectNameList" :key="item.label" :label="item.value" :value="item.value">
+              </el-option>
+            </el-select> 
+          </el-form-item>
           <el-form-item label="产品名称" style="width: 100%" prop="productId">
             <el-select :disabled="todayPlanForm.id==null?false:true" v-model="todayPlanForm.productId" placeholder="请选择" class="w100" @change="setProductCode" filterable>
               <el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id">
               </el-option>
-            </el-select>
+            </el-select>  
           </el-form-item>
           <el-form-item label="项目代码" style="width: 100%" prop="projectCode">
             <el-input :disabled="todayPlanForm.id==null?false:true" v-model="todayPlanForm.projectCode" maxlength="50" readonly></el-input>
           </el-form-item>
-
           <div v-for="(item, index) in todayPlanForm.steelStampNumberList" style="width: 100%;margin-bottom: 10px;">
             <el-form-item label="钢印号" :key="index" style="width: 100%" prop="steelStampNumberStart">
               <el-input class="w45" v-model="item.steelStampNumberStart" maxlength="20"></el-input>
@@ -167,6 +191,11 @@
           <!-- <el-form-item label="进度"  :style="this.titleName==='编辑今日计划'?'':'width: 100%'" prop="progress">
             <el-input v-model="todayPlanForm.progress" maxlength="20"></el-input>
           </el-form-item> -->
+          <el-form-item label="列序号" style="width: 100%" prop="columnNumStart">
+            <el-input-number class="w45" v-model="todayPlanForm.columnNumStart" maxlength="20"></el-input-number>
+            {{ "-" }}
+            <el-input-number class="w45" v-model="todayPlanForm.columnNumEnd" maxlength="20"></el-input-number>
+          </el-form-item>
           <el-form-item label="车辆序号" style="width: 100%" prop="steelStampNumberStart">
             <el-input-number class="w45" v-model="todayPlanForm.vehicleNumStart" maxlength="20"></el-input-number>
             {{ "-" }}
@@ -395,8 +424,12 @@ export default {
         productSchedulingNum: [
           { required: true, message: "排产工单号", trigger: "blur" },
         ],
+        productOrderNum: [
+          { required: true, message: "生产订单号", trigger: "blur" },
+        ],
         productId: [{ required: true, message: "产品名称", trigger: "blur" }],
         projectCode: [{ required: true, message: "项目代码", trigger: "blur" }],
+        projectName: [{ required: true, message: "项目名称", trigger: "blur" }],
         // steelStampNumberStart: [
         //   { required: true, message: "钢印号", trigger: "blur" },
         // ],
@@ -412,6 +445,9 @@ export default {
       },
       exportDialog: false,
       exportParam: { productId: null, rangeDatas: this.getCurrentRangeTime() },
+      searchType:'1',
+      searchValue:'',
+      projectNameList:[]
     };
   },
   computed: {},
@@ -427,13 +463,13 @@ export default {
     addInput() {
       console.log('===========', this.todayPlanForm.steelStampNumberList)
       console.log('===========', this.todayPlanForm)
-      if (this.todayPlanForm.steelStampNumberList.length >= 9) {
-        this.$message({
-          message: '超过最大条数(9)',
-          type: "error",
-        });
-        return
-      }
+      // if (this.todayPlanForm.steelStampNumberList.length >= 9) {
+      //   this.$message({
+      //     message: '超过最大条数(9)',
+      //     type: "error",
+      //   });
+      //   return
+      // }
       this.todayPlanForm.steelStampNumberList.push({
         id: null,
         steelStampNumberStart: '',
@@ -442,6 +478,34 @@ export default {
         ruleIndexEnd: '',
       });   // 在数组中添加一个空对象
     },
+    filterProductList(value){
+      this.todayPlanForm.productId=null,
+      this.todayPlanForm.projectCode=null,
+      this.http.post(
+          "/product/getProductPage",
+          {
+            pageIndex: null,
+            pageSize: null,
+            projectName:value
+          },
+          (res) => {
+            if (res.code == "ok") {
+              this.productList = res.data.records;
+            } else {
+              this.$message({
+                message: res.msg,
+                type: "error",
+              });
+            }
+          },
+          (error) => {
+            this.$message({
+              message: error,
+              type: "error",
+            });
+          }
+        );
+    },
     deleteInput(index) {
       this.todayPlanForm.steelStampNumberList.splice(index, 1)
     },
@@ -471,8 +535,12 @@ export default {
     setProductCode() {
       let arrList = this.productList.filter(item => item.id == this.todayPlanForm.productId)
       console.log('====>', arrList)
-      this.todayPlanForm.projectCode = arrList[0].code
-      this.todayPlanForm.productName = arrList[0].name
+      // this.todayPlanForm.projectCode = arrList[0].code
+      // this.todayPlanForm.projectName = arrList[0].projectName
+      // this.todayPlanForm.productName = arrList[0].name
+      this.$set(this.todayPlanForm, "projectCode", arrList[0].code)
+      // this.$set(this.todayPlanForm, "projectName", arrList[0].projectName)
+      this.$set(this.todayPlanForm, "productName", arrList[0].name)
     },
     today() {
       let date = new Date();
@@ -675,6 +743,34 @@ export default {
       this.hasChooseDept = item.departmentId;
       this.getTableData(item.departmentId);
     },
+    getProjectNames(value){
+      if(value != '') {
+        this.http.post(
+          "/product/getProductProjectNames",
+          {
+            value:value,
+          },
+          (res) => {
+            if (res.code == "ok") {
+              this.projectNameList = res.data;
+            } else {
+              this.$message({
+                message: res.msg,
+                type: "error",
+              });
+            }
+          },
+          (error) => {
+            this.$message({
+              message: error,
+              type: "error",
+            });
+          }
+        );
+      } else {
+        this.projectNameList = []
+      }
+    },
     // 获取车间数据
     getTableData(departmentId) {
       console.log(this.planDate, departmentId);
@@ -688,6 +784,8 @@ export default {
           steelStampNumber: this.steelStampNumber,
           pageIndex: this.pageIndex,
           pageSize: this.pageSize,
+          searchValue:this.searchValue,
+          searchType:this.searchType
         },
         (res) => {
           this.tableDataLoading = false;

+ 5 - 0
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/plan/planComponentDetil.vue

@@ -29,6 +29,11 @@
           :height="tableHight"
           v-if="TabIndex == 0" v-loading="tableDataLoading"
         >
+        <el-table-column label="序号" width="60">
+            <template slot-scope="scope">{{
+              scope.row.prodProcedure.seq
+            }}</template>
+          </el-table-column>
           <el-table-column label="工序名称" width="400">
             <template slot-scope="scope">
                 <div class="disFlexscope">

+ 69 - 4
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/product/list.vue

@@ -14,6 +14,16 @@
                     <el-input v-model="code" placeholder="请输入" clearable="true" size="small">
                     </el-input>
                 </el-form-item>
+                <el-form-item label="产品状态">
+                    <el-select v-model="status" placeholder="请选择">
+                        <el-option
+                        v-for="item in productStatus"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                        </el-option>
+                    </el-select>
+                </el-form-item>
                 <el-form-item>
                     <el-button @click="getList" size="small">查询</el-button>
                 </el-form-item>
@@ -60,6 +70,7 @@
                             </el-form-item>
                             <el-form-item>
                                 <el-table :data="props.row.tableProdProcedure.procedureList" border style="width: 100%">
+                                    <el-table-column prop="seq" label="序号" width="60"></el-table-column>
                                     <el-table-column prop="name" label="工序名称" width="180">
                                     </el-table-column>
                                     <el-table-column prop="workingTime" label="单件工时" width="180">
@@ -114,16 +125,18 @@
             <el-table-column type="selection" width="55">
             </el-table-column>
             <el-table-column prop="name" label="产品名称"  width="300"></el-table-column>
+            <el-table-column prop="projectName" label="项目名称" width="200"></el-table-column>
             <el-table-column prop="code" label="项目代码" width="200"></el-table-column>
             <el-table-column prop="orderNumber" label="订单数量" width="100"></el-table-column>
             <el-table-column prop="unit" label="单位" width="100"></el-table-column>
             <el-table-column prop="groupNumber" label="编组"></el-table-column>
             <el-table-column prop="columnNumber" label="每列数量"></el-table-column>
             <el-table-column prop="vehicleNumber" label="每辆数量"></el-table-column>
-            <el-table-column label="操作" width="200" fixed="right">
+            <el-table-column label="操作" width="250" fixed="right">
                 <template slot-scope="scope">
                     <el-button size="mini" @click="handleAdd(scope.$index, scope.row)">编辑</el-button>
                     <el-button size="mini" @click="copyProduct(scope.row)">复制</el-button>
+                    <el-button size="mini" @click="deactivate(scope.row)">{{scope.row.status==0?'停用':'启用'}}</el-button>
                 </template>
             </el-table-column>
         </el-table>
@@ -176,6 +189,10 @@
                         <el-input v-model="addForm.name" :placeholder="$t('peaseenterthe')" clearable maxlength="50"
                             show-word-limit="true"></el-input>
                     </el-form-item>
+                    <el-form-item label="项目名称" prop="projectName">
+                        <el-input v-model="addForm.projectName" :placeholder="$t('peaseenterthe')" clearable maxlength="50"
+                            show-word-limit="true"></el-input>
+                    </el-form-item>
                     <el-form-item label="项目代码" prop="code">
                         <!-- <el-input v-model="addForm.code" :disabled="!permissions.projectManagement && addForm.creatorId != user.id" placeholder="请输入项目编号" clearable></el-input> -->
                         <el-input v-model="addForm.code" :placeholder="$t('peaseenterthe')" clearable maxlength="50"
@@ -223,7 +240,7 @@
                  <!--此处是录入工序的模块-->
 
 
-                <el-input placeholder="请输入工序版本号" v-model="procedureVersion" clearable maxlength="50" class="input-pM"></el-input>
+                <el-input placeholder="请输入工序版本号" v-model="procedureVersion" clearable maxlength="50" class="input-pM" @change="getProdProcedureListWithVersion(productId,procedureVersion)"></el-input>
                 <el-table :data="procedureLit" style="width: 100%">
                     <el-table-column prop="name" label="工序名称"  width="350">
                         <template slot-scope="scope">
@@ -788,6 +805,7 @@ export default {
             rules: {
                 name: [{ required: true, message: this.$t('pleaseentername'), trigger: "blur" }],
                 code: [{ required: true, message: "请输入项目代码", trigger: "blur" }],
+                projectName: [{ required: true, message: "请输入项目名称", trigger: "blur" }],
                 orderNumber: [{ required: true, message:' 请输入订单数量', trigger: "blur" }],
                 unit: [{ required: true, message: '请输入单位', trigger: "blur" }],
                 groupNumber: [{ required: true, message: '请输入编组', trigger: "blur" }],
@@ -885,7 +903,17 @@ export default {
             dataListBf: [],
             imgUrlLists: '',
             imgUrlListFlg: false,
-            estimatedWorkTime: ''
+            estimatedWorkTime: '',
+            productStatus:[
+                {
+                value: '0',
+                label: '启用'
+                }, {
+                value: '1',
+                label: '停用'
+                }
+            ],
+            status:'0'
         };
     },
     // 过滤器
@@ -1193,6 +1221,15 @@ export default {
                     })
             }
 
+        },
+        getProdProcedureListWithVersion(id,version) {
+            if (version != null && version != '') {
+                this.http.post("/prod-procedure/getInfo", { version: version, productId: id },
+                    res => {
+                        this.procedureLit=res.data
+                    })
+            }
+
         },
         getProdMaterialVersion(id, index) {
             if (this.prodMaterialVersion != null && this.prodMaterialVersion != '') {
@@ -1586,6 +1623,33 @@ export default {
                     });
                 });
         },
+        deactivate(item){
+            var value
+            item.status==0?value=1:value=0
+            this.http.post('/product/deactivate', {
+                id:item.id,value:value
+            },
+            res => {
+                if (res.code == "ok") {
+                    this.$message({
+                        message: item.status==0?'停用成功':'启用成功',
+                        type: "success"
+                    });
+                } else {
+                    this.$message({
+                        message: res.msg,
+                        type: "error"
+                    });
+                }
+                this.getList()
+            },
+            error => {
+                this.$message({
+                    message: error,
+                    type: "error"
+                });
+            });
+        },
         addProjectLevel(row) {
             this.addProjectLevelDialog = true
             if (!row) {
@@ -3007,7 +3071,8 @@ export default {
                 pageSize: this.size,
                 name: this.name,
                 code: this.code,
-                cateId: this.cateId
+                cateId: this.cateId,
+                status:this.status
             }
 
             this.http.post('/product/getProductPage', parameter,

+ 4 - 0
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/settings/settings.vue

@@ -34,6 +34,10 @@
         <div style="width:400px;margin:0 auto;padding:20px;">
             <h3>系统部署</h3>
             <el-form style="padding:35px;">
+                <el-form-item label="系统日志" >
+                    <span>{{ param.h5Url }}</span>
+                    <el-button type="primary" size="small" style="margin-left: 32px;"><a style="text-decoration:none; color:#fff" href="/api/common/downLoadLog">下载日志</a></el-button>
+                </el-form-item>
                 <el-form-item label="前端H5安装包" >
                     <span>{{ param.h5Url }}</span>
                     <el-upload ref="upload" action="#" :limit="1" :http-request="importH5" :show-file-list="false">

+ 158 - 23
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/statistic/index.vue

@@ -39,7 +39,7 @@
       <div class="headScreen" :style="'width:72%'">
           <!-- 部门筛选 -->
           <el-cascader v-if="ins!=5 && !isViewUser" v-model="departmentIdArray" :options="departmentList" :placeholder="$t('qing-xuan-ze-bu-men')"
-            :props="{ checkStrictly: true,expandTrigger: 'hover' }" collapse-tags :show-all-levels="false" clearable
+            :props="{ multiple: true, checkStrictly: true,expandTrigger: 'hover' }" collapse-tags :show-all-levels="false" clearable
             @change="selcts()" size="small" style="margin-bottom: 10px;width:180px"
           ></el-cascader>
 
@@ -88,17 +88,28 @@
                 <el-table-column align="center" prop="name" label="人员" min-width="100" fixed="left"></el-table-column>
                 <el-table-column v-for="(item, index) in personWorkHoursWagesHead" :key="index" :label="item" align="center" min-width="150">
                     <template slot-scope="scope">
-                        <div v-for="(items, indexs) in scope.row.personWorkHoursWages" :key="indexs" @click="showReportDetail(scope.row,item,0)" :class="`${scope.row.departmentCascade== '小计' ? '' : 'colorText'}`">
-                            <div v-if="items.crateDate == item">
-                               <div> {{items.workTime}}分钟 </div> 
-                               <div>{{items.cost}}元</div>
+                        <div v-for="(items, indexs) in scope.row.personWorkHoursWages" :key="indexs" :class="`${scope.row.departmentCascade== '小计' ? '' : 'colorText'}`">
+                            <div v-if="items.crateDate == item" @click.stop="showReportDetail(scope.row,item,0)">
+                              <div  style="color: black;" v-if="items.planWorkTime">平均 {{items.planWorkTime}}分钟  {{items.planCost}}元</div>
+                              <!-- <div @click.stop="showReportDetail(scope.row,item,0)" v-if="items.workTime>0">已填 {{items.workTime}}分钟  {{items.cost}}元 </div>{{items.leave}}
+                              <div style="color: green;" @click.stop="showTempReportDetail(scope.row,item,0)" v-if="items.tempWorkTime>0||items.tempCost>0">临时报工 {{items.tempWorkTime}}分钟  {{items.tempCost}}元</div> -->
+                              <div  v-if="items.workTime>0">已填 {{items.workTime}}分钟  {{items.cost}}元 </div>{{items.leave}}
+                              <div style="color: green;" v-if="items.tempWorkTime>0||items.tempCost>0">临时报工 {{items.tempWorkTime}}分钟  {{items.tempCost}}元</div>
+                              <div style="color: red;" v-if="items.surplusTime">剩余 {{items.surplusTime}}分钟  {{items.surplusCost}}元</div>
                             </div>
                         </div>
                     </template>
                 </el-table-column>
-                <el-table-column align="center" prop="totalResult" label="合计" min-width="150">
+                <el-table-column align="center" prop="totalResult" label="合计" min-width="180">
                    <template slot-scope="scope" >
-                    <span :class="`${'colorText'}`" @click="showReportDetail(scope.row,item,1)">{{scope.row.totalResult}}</span>
+                    <div @click="showReportDetail(scope.row,item,1)">
+                      <div style="color: black;">{{scope.row.totalPlanResult | formatStr('平均') }}</div>
+                      <!-- <div style="color: #02a7f0;"  @click="showReportDetail(scope.row,item,1)"> {{scope.row.totalResult | formatStr('已填')}}</div> 
+                      <div style="color: green;"  @click="showTempReportDetail(scope.row,item,1)">{{scope.row.totalTempResult | formatStr('临时报工')}}</div>  -->
+                      <div style="color: #02a7f0;" > {{scope.row.totalResult | formatStr('已填')}}</div> 
+                      <div style="color: green;" >{{scope.row.totalTempResult | formatStr('临时报工')}}</div> 
+                      <div style="color: red;">{{scope.row.totalSurplusResult | formatStr('剩余') }}</div>
+                    </div>
                   </template>
                 </el-table-column>
             </el-table>
@@ -154,6 +165,9 @@
                 <el-table-column align="center" prop="productName" label="产品名称" min-width="150">
                   <template slot-scope="scope">{{scope.row.productName}}</template>
                 </el-table-column>
+                <el-table-column align="center" prop="projectName" label="项目名称" min-width="150">
+                  <template slot-scope="scope">{{scope.row.projectName}}</template>
+                </el-table-column>
                 <el-table-column align="center" prop="startDate" label="开始日期" width="150">
                   <template slot-scope="scope">{{scope.row.startDate}}</template>
                 </el-table-column>
@@ -352,7 +366,10 @@
           <div>
             <el-table
               :data="personWorkHoursWagesDetail"
-              style="width: 100%">
+              style="width: 100%"
+              :row-class-name="tableRowClassName"
+              height="500"
+              >
               <el-table-column
                 prop="date"
                 label="计划(开始-结束日期)"
@@ -364,17 +381,19 @@
               <el-table-column prop="productName" label="产品名称" width="180"></el-table-column>
               <el-table-column prop="product_scheduling_num" label="排产工单号" width="180"></el-table-column>
               <el-table-column prop="procedureName" label="工序名称" width="180"></el-table-column>
+              <el-table-column prop="taskName" label="任务名称" width="250"></el-table-column>
+              <el-table-column prop="task_type_name" label="任务类型" width="180"></el-table-column>
               <el-table-column prop="finishNum" label="完成件数" width="80">
                 <template slot-scope="scope">
-                  {{scope.row.finishNum?scope.row.finishNum:0}}
+                  {{scope.row.finishNum?scope.row.finishNum:''}}
                 </template>
               </el-table-column>
               <el-table-column prop="cost" label="工钱" width="80"></el-table-column>
               <el-table-column prop="checkType" label="质检方式" width="80"></el-table-column>
               <el-table-column prop="checkerName" label="质检人" width="180"></el-table-column>
               <el-table-column prop="working_time" label="工作时长" width="180">
-                <template slot-scope="scope">
-                  {{scope.row.working_time}}分钟
+                <template slot-scope="scope" v-if="scope.row.working_time">
+                  {{scope.row.working_time}}{{'分钟'}}
                 </template>
               </el-table-column>
             </el-table>
@@ -734,6 +753,13 @@ export default {
       personWorkHoursWorkTime(value) {
         let val = +((value ? value : 0) * 60).toFixed(2) + 0
         return val
+      },
+      formatStr(val, str) {
+        if(!val) {
+          return ''
+        }
+        let relut = val.replace(/\b0\.\d+\S*\s*/g, '')
+        return`${relut ? str : ''} ${relut}`
       }
   },
   methods: {
@@ -756,6 +782,15 @@ export default {
       this.detailUserId=row.id
       this.getPersonWorkHoursWagesDetail(item,viewAll)
     },
+    showTempReportDetail(row,item,viewAll){
+      if(row.departmentCascade=='小计'){
+          return
+      }
+      console.log(item)
+      this.reportDetailDialog=true
+      this.detailUserId=row.id
+      this.getPersonWorkHoursWagesDetailForTemp(item,viewAll)
+    },
     authorityToJudge() {
     //   if(this.permissions.reportProject || this.permissions.reportAllProject) {this.ssl(0);this.defaultActive = '1-1';return} else
     //   if(this.permissions.reportTask || this.permissions.reportAllTask) {this.ssl(1);this.defaultActive = '1-2';return} else
@@ -817,6 +852,17 @@ export default {
           });
       });
     },
+    //处理列类别
+    tableRowClassName({row}) {
+      if (row.colorType == "blue") {
+        return 'blue-row';
+      } else if (row.colorType == "black") {
+        return 'black-row';
+      }else if(row.colorType == "green"){
+        return 'green-row';
+      }
+      return '';
+    },
     getUserList(e) {
       let param={}
       if(e){
@@ -889,13 +935,18 @@ export default {
     },
     //人员工时工价表数据
     getPersonWorkHoursWagesList(){
+        let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.listLoading=true
         this.http.post( "/report/getPersonWorkHoursWagesList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId
         },
         res => {
@@ -959,15 +1010,59 @@ export default {
         });
       });
     },
+    getPersonWorkHoursWagesDetailForTemp(item,viewAll){
+      this.listLoading=true
+      let param={
+        userId:this.detailUserId
+      }
+      if(viewAll==1){
+        this.simpleDateChoose=''
+        param={
+          ...param,
+          startDate:this.rangeDatas[0],
+          endDate:this.rangeDatas[1]
+        }
+      }else{
+        this.simpleDateChoose=item
+        param={
+          ...param,
+          date: this.simpleDateChoose.substring(0,4)+"-"+this.simpleDateChoose.substring(4,6)+"-"+this.simpleDateChoose.substring(6,this.simpleDateChoose.length),
+        }
+      }
+      this.http.post( "/report/getPersonWorkHoursWagesDetailForTemp", param,
+      res => {
+        if (res.code == "ok") {
+          this.personWorkHoursWagesDetail=res.data.record
+          this.totalCost=res.data.totalCost
+          this.totalWorkingTime=res.data.totalWorkingTime
+        } else {
+          this.$message({
+            message: res.msg,
+            type: "error"
+          });
+        }
+        this.listLoading=false
+      },error => {
+        this.$message({
+          message: error,
+          type: "error"
+        });
+      });
+    },
     //工序实际工时表
     getProcedureRealTimeProgressList(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/getProcedureRealTimeProgressList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId
         },
         res => {
@@ -991,12 +1086,17 @@ export default {
     //部门生产统计表
     getDpetStatisticsProgressList(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/getDpetStatisticsProgressList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
         },
         res => {
           if (res.code == "ok") {
@@ -1019,12 +1119,17 @@ export default {
     //计划实际工时表
     getPlanRealTimeProgressList(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/getPlanRealTimeProgressList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId
         },
         res => {
@@ -1048,12 +1153,17 @@ export default {
     //人员工时工价表数据
     getWorkReportQuery(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/workReportQuery", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId,
             productId:this.productId,
             vehicleNum:this.vehicleNum,
@@ -1107,12 +1217,17 @@ export default {
     },
     //车间工位计划表
     getPlanDataWithStation(deptId){
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
       let param={
         startDate:this.rangeDatas[0],
         endDate:this.rangeDatas[1],
         pageIndex: this.page,
         pageSize: this.size,
-        stationId:this.departmentIdArray[this.departmentIdArray.length - 1],
+        stationIds:deptArr.join(','),
       }
       if(deptId){
         this.exportDeptId=deptId
@@ -1327,26 +1442,31 @@ export default {
     var url = "/report";
     var fName = "";
     var sl = {}
+    let deptArr = []
+    for(var i in this.departmentIdArray){
+      let itemList = this.departmentIdArray[i] 
+      deptArr.push(itemList[itemList.length - 1])
+    }
     if (this.ins == 0) {  
         fName = '人员工时工价表_' + '.xlsx';
         url += "/exportPersonWorkHoursWorkTime";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
     } else if (this.ins == 1) {
         fName = '工序实时进度表_' + '.xlsx';
         url += "/exportProcedureRealTimeProgressList";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
     }else if (this.ins == 2) {
         fName = '报工详情表_' + '.xlsx';
         url += "/exportWorkReportQuery";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
         sl.vehicleNum=this.vehicleNum;
         sl.steelNum=this.steelNum;
@@ -1356,14 +1476,14 @@ export default {
         url += "/exportPlanRealTimeProgressList";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
     } else if (this.ins == 4) {
         fName = '部门生产统计表_' + '.xlsx';
         url += "/exportDpetStatisticsProgressList";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
     }
     else if (this.ins == 5) {
         fName = '月度生产件数表_' + '.xlsx';
@@ -1378,7 +1498,7 @@ export default {
         sl.endDate=this.rangeDatas[1];
         if(!this.personnelFlag){
           url += "/exportPlanDataWithStation";
-          sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+          sl.deptIds=deptArr.join(',');
           if(this.exportDeptId){
           sl.filterDeptId=this.exportDeptId;
           sl.isFilterDept=1
@@ -1492,6 +1612,8 @@ export default {
     }else{
       this.getUserList()
     }
+    this.page=1
+    this.size=20
     console.log(this.userId,'==============')
     this.getList(true)
     },
@@ -1756,3 +1878,16 @@ export default {
 }
 
 </style>
+<style>
+.el-table .blue-row {
+  color: #02a7f0;
+}
+
+.el-table .black-row {
+  color: black;
+}
+
+.el-table .green-row {
+  color: green;
+}
+</style>

+ 0 - 3
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/team/index.vue

@@ -109,9 +109,6 @@
                      <el-form-item style="float:right;" v-if="permissions.structureExport">
                           <el-link type="primary" :underline="false" @click="showWorkTypeDialog">自定义工种</el-link>
                       </el-form-item>
-                      <el-form-item style="float:right;" >
-                        <el-link type="primary" :underline="false" @click="openInsertDialog(null)">添加人员</el-link>
-                      </el-form-item>
                     
                     <el-form-item style="float:right;">
                         <span style="color: #666666">{{ $t('jiao-se') }}</span>

+ 43 - 14
fhKeeper/formulahousekeeper/timesheet-workshop-stand/src/views/workReport/daily.vue

@@ -669,11 +669,13 @@
                         <el-option v-for="item in allPlanList"  :key="item.id" :label="item.productName" :value="item.id"></el-option>
                     </el-select>
                 </el-form-item> -->
-                <el-form-item prop="departmentId" :label="'选择工位'" v-if="permissions.reportsCompany">
+                <el-form-item :label="'选择工位'" v-if="permissions.reportsCompany">
 
-                    <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.departmentId" :placeholder="$t('other.allDepartments')" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 350px;"></el-cascader>
-
-                    <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
+                    <!-- 部门筛选 -->
+                    <el-cascader  v-model="departmentIdArray" :options="departmentList" :placeholder="$t('qing-xuan-ze-bu-men')"
+                        :props="{ multiple: true, checkStrictly: true,expandTrigger: 'hover' }" collapse-tags :show-all-levels="false" clearable
+                        size="small" style="margin-bottom: 10px;width:180px"
+                    ></el-cascader>
 
                 </el-form-item>
                 <el-form-item prop="projectId" :label="$t('time.dateRange')">
@@ -1379,7 +1381,7 @@
         },
         data() {
             return {
-                
+                props:{ multiple: true },
                 checkTypeTxt:['自检','互检','专检'],
                 modItemDataId: null,
                 modImportTime: null,
@@ -1465,7 +1467,7 @@
                 weekDay : [this.$t('weekDay.sunday'), this.$t('weekDay.monday'), this.$t('weekDay.tuesday'), this.$t('weekDay.wednesday'), this.$t('weekDay.thursday'), this.$t('weekDay.friday'), this.$t('weekDay.saturday')],
                 statusStyle:["waiting", "filledReportStyle", "RejectStyle", "waitSubmitStyle"],
                 fillStatusList: [],
-                exportParam:{projectId: null, dateRange:[], departmentId: null},
+                exportParam:{projectId: null, dateRange:[], deptIds: null},
                 exportDialog:false,
                 timeFields:['timeType', 'workingTime', 'startTime', 'progress'],
                 subProjectList:[],
@@ -1653,6 +1655,7 @@
                 totalReportHours: 0, // 合计的工时
 
                 allPlanList: [], // 所有计划
+                departmentIdArray:[],
             };
         },
         watch: {
@@ -1697,7 +1700,7 @@
             this.exportParam.dateRange = [startStr,t];
             this.getAllDate(1);
             this.getReportList();
-            
+            this.getDepartmentList()
             // this.getFillProjectList();
             // this.getTimeType();
             this.getDepartment();
@@ -3856,7 +3859,25 @@
                         });
                 }
             },
-            
+            getDepartmentList() {
+            this.http.post( this.port.manage.depList, {},
+                res => {
+                if (res.code == "ok") {
+                    let dptlist = JSON.parse(JSON.stringify(res.data));
+                    this.departmentList = this.changeArr(dptlist);
+                } else {
+                    this.$message({
+                    message: res.msg,
+                    type: "error"
+                    });
+                }
+                },error => {
+                this.$message({
+                    message: error,
+                    type: "error"
+                });
+                });
+            },
             // 获取部门列表
             getDepartment() {
                 let day = (this.choseDay+1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
@@ -3871,7 +3892,7 @@
                             // })
                             return
                         }
-                        this.departmentList = JSON.parse(JSON.stringify(res.data))
+                        // this.departmentList = JSON.parse(JSON.stringify(res.data))
                         var list = res.data , list1 = JSON.parse(JSON.stringify(res.data));
                         // let noAllData = JSON.parse(JSON.stringify(res.data));
                         // if (this.user.role > 0) {
@@ -4127,7 +4148,7 @@
                 let day = (this.choseDay +1)> 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
                 sessionStorage.msg = this.date + day,
                 this.getReportList();
-                this.getDepartment();
+                // this.getDepartment();
                 this.curDate = item.date;
             },
             canClick(i, item){
@@ -4311,20 +4332,28 @@
             //导出日报
             exportReport() {
                 this.listLoading = true;
+                var fName ='日报统计表_' + '.xlsx';
                 var param = {};
                 const { dateRange, departmentId } = this.exportParam
                 param.startDate = dateRange[0]
                 param.endDate = dateRange[1]
-                console.log(departmentId)
-                if(departmentId && departmentId.length > 0) {
-                    param.departmentId = departmentId[departmentId.length - 1]
+                let deptArr = []
+                for(var i in this.departmentIdArray){
+                let itemList = this.departmentIdArray[i] 
+                deptArr.push(itemList[itemList.length - 1])
                 }
+                param.deptIds = deptArr.join(',')
                 this.http.post('/report/exportReport', param,
                 res => {
                     this.listLoading = false;
                     if (res.code == "ok") {
-                        location.href = res.data;
+                        var filePath = res.data;
                         this.exportDialog = false;
+                        const a = document.createElement('a'); // 创建a标签
+                        a.setAttribute('download', fName);// download属性
+                        a.setAttribute('href', filePath);// href链接
+                        a.click(); //自执行点击事件
+                        a.remove();
                     } else {
                         this.$message({
                             message: res.msg,

+ 12 - 0
fhKeeper/formulahousekeeper/timesheet/build-private.bat

@@ -0,0 +1,12 @@
+@echo off
+
+copy /Y setIndex\indexTwo.html index.html
+
+start /B npm run build
+
+timeout /t 35 /nobreak
+
+copy /Y setIndex\indexOne.html index.html
+
+echo Done!
+pause

+ 5 - 23
fhKeeper/formulahousekeeper/timesheet/index.html

@@ -14,12 +14,9 @@
     <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
     <link href="./static/css/public.css" rel="stylesheet" type="text/css" />
     <!-- <script async defer src="http://47.101.180.183:9999/api/application/embed?protocol=http&host=47.101.180.183:9999&token=56c5bbad807f9a14"></script> -->
-    <script async defer src="https://chatai.ttkuaiban.com/api/application/embed?protocol=https&host=chatai.ttkuaiban.com&token=56c5bbad807f9a14"></script>
+    <script async defer src="https://chatai.ttkuaiban.com/api/application/embed?protocol=https&host=chatai.ttkuaiban.com&token=8aa88c0a6d804a57"></script>
     <!-- 引入样式 -->
-    <!-- <link
-      href="https://cdn.staticfile.org/element-ui/2.13.0/theme-chalk/index.css"
-      rel="stylesheet"
-    /> -->
+    <!-- <link href="https://cdn.staticfile.org/element-ui/2.13.0/theme-chalk/index.css" rel="stylesheet"/> -->
     <!-- <link rel="stylesheet" href="./static/js/element-uiCss.css"> -->
     <!-- 接入JQ  -->
     <!-- <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> -->
@@ -118,18 +115,9 @@
         }
       }
     </style>
-    <!-- <meta name="wpk-bid" content="dta_2_71020"> <script>var isDingtalk = navigator && /DingTalk/.test(navigator.userAgent);var isProductEnv = window &&window.location &&window.location.host 
-            && window.location.host.indexOf('//127.0.0.1')===-1
-            && window.location.host.indexOf('//localhost')===-1
-            && window.location.host.indexOf('//192.168.')===-1
-            // 如果有其它测试域名,请一起排掉,减少测试环境对生产环境监控的干扰
-        if (isProductEnv) {    !(function(c,i,e,b){var h=i.createElement("script");var f=i.getElementsByTagName("script")[0];h.type="text/javascript";h.crossorigin=true;h.onload=function(){c[b]||(c[b]=new c.wpkReporter({bid:"dta_2_71020"}));c[b].installAll()};f.parentNode.insertBefore(h,f);h.src=e})(window,document,"https://g.alicdn.com/woodpeckerx/jssdk??wpkReporter.js","__wpk"); }</script> -->
   </head>
   <!-- 接入飞书 -->
-  <script
-    type="text/javascript"
-    src="https://lf1-cdn-tos.bytegoofy.com/goofy/lark/op/h5-js-sdk-1.5.16.js"
-  ></script>
+  <script type="text/javascript" src="https://lf1-cdn-tos.bytegoofy.com/goofy/lark/op/h5-js-sdk-1.5.16.js"></script>
   <!-- <script src="./static/js/goofy.js"></script> -->
   <!-- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
     <script>
@@ -159,14 +147,8 @@
     <!-- <script src="https://cdn.staticfile.org/echarts/3.8.5/echarts.min.js"></script> -->
     <script src="./static/js/echarts.min.js"></script>
     <!-- 引入企业微信js -->
-    <script
-      src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"
-      referrerpolicy="origin"
-    ></script>
-    <script
-      src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"
-      referrerpolicy="origin"
-    ></script>
+    <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" referrerpolicy="origin"></script>
+    <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" referrerpolicy="origin"></script>
     
     <!-- <script src="./static/js/jweixin-1.2.0.js"></script>
         <script src="./static/js/jwxwork-1.0.0.js"></script> -->

+ 156 - 0
fhKeeper/formulahousekeeper/timesheet/setIndex/indexOne.html

@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> -->
+    <!-- 尝试清除打包缓存 -->
+    <!-- <meta http-equiv="pragram" content="no-cache">
+        <meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
+        <meta http-equiv="expires" content="0"> -->
+    <!-- 尝试清除打包缓存 -->
+    <title>工时管家</title>
+    <!--接入钉钉前端组件,进行通讯录组件展示-->
+    <script src="https://auth.dingtalk.com/opendata-1.1.0.js"></script>
+    <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
+    <link href="./static/css/public.css" rel="stylesheet" type="text/css" />
+    <!-- <script async defer src="http://47.101.180.183:9999/api/application/embed?protocol=http&host=47.101.180.183:9999&token=56c5bbad807f9a14"></script> -->
+    <script async defer src="https://chatai.ttkuaiban.com/api/application/embed?protocol=https&host=chatai.ttkuaiban.com&token=56c5bbad807f9a14"></script>
+    <!-- 引入样式 -->
+    <!-- <link href="https://cdn.staticfile.org/element-ui/2.13.0/theme-chalk/index.css" rel="stylesheet"/> -->
+    <!-- <link rel="stylesheet" href="./static/js/element-uiCss.css"> -->
+    <!-- 接入JQ  -->
+    <!-- <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> -->
+    <script src="./static/js/jquery.min.js"></script>
+    <style>
+      /* 滚动条样式修改 */
+      /*滚动条凹槽的颜色,还可以设置边框属性 */
+      ::-webkit-scrollbar-track-piece {
+        background-color: #f8f8f8;
+        -webkit-border-radius: 2em;
+        -moz-border-radius: 2em;
+        border-radius: 2em;
+      }
+      /*滚动条的宽度*/
+      ::-webkit-scrollbar {
+        width: 9px;
+        height: 9px;
+      }
+      /*滚动条的设置*/
+      ::-webkit-scrollbar-thumb {
+        background-color: #dddddd;
+        background-clip: padding-box;
+        -webkit-border-radius: 2em;
+        -moz-border-radius: 2em;
+        border-radius: 2em;
+      }
+
+      /*滚动条鼠标移上去*/
+      ::-webkit-scrollbar-thumb:hover {
+        background-color: #bbb;
+      }
+
+      /*取消消息列表弹出框的内边距*/
+      .popover-self {
+        padding: 0 !important;
+      }
+
+      /*自定义颜色*/
+      #nprogress .bar {
+        background: #f58220 !important;
+      }
+
+      .selectworktime .el-dialog__header {
+        padding-top: 0;
+        padding-bottom: 0;
+      }
+      .selectworktime .el-dialog__body {
+        padding-top: 15px;
+      }
+      .el-dialog__headerbtn {
+        z-index: 2002;
+      }
+      .selecteorktime_datapick_popper {
+        left: 12vh !important;
+      }
+      .customsalary .el-input__inner {
+        height: 35px;
+        line-height: 35px;
+      }
+      .projectSelectPopperClass {
+        max-width: 1000px;
+      }
+      .projectSelectPopperClass li {
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(1) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 350px;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(2) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 650px;
+
+        text-align: right;
+      }
+
+      /* 清除浮动 */
+      .clearfix:after {
+        content: "";
+        display: block;
+        height: 0;
+        clear: both;
+        visibility: hidden;
+      }
+      .clearfix {
+        /* 触发 hasLayout */
+        zoom: 1;
+      }
+      .fillWeekCustom {
+        .el-dialog__body {
+          padding: 10px 20px !important;
+        }
+      }
+    </style>
+  </head>
+  <!-- 接入飞书 -->
+  <script type="text/javascript" src="https://lf1-cdn-tos.bytegoofy.com/goofy/lark/op/h5-js-sdk-1.5.16.js"></script>
+  <!-- <script src="./static/js/goofy.js"></script> -->
+  <!-- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
+    <script>
+        var vConsole = new window.VConsole();
+    </script> -->
+  <body>
+    <div id="app"></div>
+    <script>
+      document.body.ondrop = function (event) {
+        event.preventDefault();
+        event.stopPropagation();
+      };
+    </script>
+    <!-- 引入Vue.js -->
+    <!-- <script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js"></script> -->
+    <script src="./static/js/vue.min.js"></script>
+    <!-- 引入vuex.js -->
+    <!-- <script src="https://cdn.staticfile.org/vuex/3.0.0/vuex.min.js"></script> -->
+    <script src="./static/js/vuex.min.js"></script>
+    <!-- 引入vue-router -->
+    <!-- <script src="https://cdn.staticfile.org/vue-router/3.0.0/vue-router.min.js"></script> -->
+    <script src="./static/js/vue-router.min.js"></script>
+    <!-- 引入组件库 -->
+    <!-- <script src="https://cdn.staticfile.org/element-ui/2.13.0/index.js"></script> -->
+    <script src="./static/js/element-ui.js"></script>
+    <!-- 引入echarts -->
+    <!-- <script src="https://cdn.staticfile.org/echarts/3.8.5/echarts.min.js"></script> -->
+    <script src="./static/js/echarts.min.js"></script>
+    <!-- 引入企业微信js -->
+    <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" referrerpolicy="origin"></script>
+    <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" referrerpolicy="origin"></script>
+    
+    <!-- <script src="./static/js/jweixin-1.2.0.js"></script>
+        <script src="./static/js/jwxwork-1.0.0.js"></script> -->
+  </body>
+</html>

+ 127 - 0
fhKeeper/formulahousekeeper/timesheet/setIndex/indexTwo.html

@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>工时管家</title>
+    <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
+    <link href="./static/css/public.css" rel="stylesheet" type="text/css" />
+    <script src="./static/js/jquery.min.js"></script>
+    <style>
+      /* 滚动条样式修改 */
+      /*滚动条凹槽的颜色,还可以设置边框属性 */
+      ::-webkit-scrollbar-track-piece {
+        background-color: #f8f8f8;
+        -webkit-border-radius: 2em;
+        -moz-border-radius: 2em;
+        border-radius: 2em;
+      }
+      /*滚动条的宽度*/
+      ::-webkit-scrollbar {
+        width: 9px;
+        height: 9px;
+      }
+      /*滚动条的设置*/
+      ::-webkit-scrollbar-thumb {
+        background-color: #dddddd;
+        background-clip: padding-box;
+        -webkit-border-radius: 2em;
+        -moz-border-radius: 2em;
+        border-radius: 2em;
+      }
+
+      /*滚动条鼠标移上去*/
+      ::-webkit-scrollbar-thumb:hover {
+        background-color: #bbb;
+      }
+
+      /*取消消息列表弹出框的内边距*/
+      .popover-self {
+        padding: 0 !important;
+      }
+
+      /*自定义颜色*/
+      #nprogress .bar {
+        background: #f58220 !important;
+      }
+
+      .selectworktime .el-dialog__header {
+        padding-top: 0;
+        padding-bottom: 0;
+      }
+      .selectworktime .el-dialog__body {
+        padding-top: 15px;
+      }
+      .el-dialog__headerbtn {
+        z-index: 2002;
+      }
+      .selecteorktime_datapick_popper {
+        left: 12vh !important;
+      }
+      .customsalary .el-input__inner {
+        height: 35px;
+        line-height: 35px;
+      }
+      .projectSelectPopperClass {
+        max-width: 1000px;
+      }
+      .projectSelectPopperClass li {
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(1) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 350px;
+      }
+      .projectSelectPopperClass .el-select-dropdown__item span:nth-child(2) {
+        font-size: 13px;
+        height: 34px;
+        max-width: 650px;
+
+        text-align: right;
+      }
+
+      /* 清除浮动 */
+      .clearfix:after {
+        content: "";
+        display: block;
+        height: 0;
+        clear: both;
+        visibility: hidden;
+      }
+      .clearfix {
+        /* 触发 hasLayout */
+        zoom: 1;
+      }
+      .fillWeekCustom {
+        .el-dialog__body {
+          padding: 10px 20px !important;
+        }
+      }
+    </style>
+  </head>
+  <!-- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
+    <script>
+        var vConsole = new window.VConsole();
+    </script> -->
+  <body>
+    <div id="app"></div>
+    <script>
+      document.body.ondrop = function (event) {
+        event.preventDefault();
+        event.stopPropagation();
+      };
+    </script>
+    <!-- 引入Vue.js -->
+    <script src="./static/js/vue.min.js"></script>
+    <!-- 引入vuex.js -->
+    <script src="./static/js/vuex.min.js"></script>
+    <!-- 引入vue-router -->
+    <script src="./static/js/vue-router.min.js"></script>
+    <!-- 引入组件库 -->
+    <script src="./static/js/element-ui.js"></script>
+    <!-- 引入echarts -->
+    <script src="./static/js/echarts.min.js"></script>
+  </body>
+</html>

+ 8 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue

@@ -33,6 +33,10 @@
                         <el-dropdown-item divided  command="en">English</el-dropdown-item>
                     </el-dropdown-menu> 
                 </el-dropdown> -->
+                <div style="margin-right: 10px;cursor: pointer;" @click="applicationMarket">
+                    <i class="el-icon-menu" style="font-size:18px" ></i>
+                    应用市场
+                </div>
                 <el-dropdown trigger="hover" style="margin-right:30px;">
                     <span class="el-dropdown-link userinfo-inner">
                         <i class="el-icon-user" style="font-size:18px" ></i>
@@ -433,6 +437,10 @@
             console.log(localStorage.getItem('firstTourFalse'))
         },
         methods: {
+            applicationMarket() {
+                window.location.href = 'https://www.ttkuaiban.com/appMarket.html'
+                // window.open('https://www.ttkuaiban.com/appMarket.html', '_blank'); 
+            },
             getSkipGuidance() {
                 this.http.post('/user/skipGuidance', {},
                 res => {

+ 282 - 53
fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue

@@ -59,6 +59,8 @@
             v-if="permissions.costAll">{{ $t('expensetypemanagement') }}</el-button></p>
         <p style="float: right;margin-right: 25px;"><el-button type="primary" @click="expenseTypeOp" size="mini"
             v-if="permissions.costAll">{{ $t('feiYongZhuLeiXingGuanLi') }}</el-button></p>
+        <p style="float: right;margin-right: 25px;"><el-button type="primary" @click="equipmentOwner" size="mini"
+            v-if="user.isMachineCost == 2">设备归属人管理</el-button></p>
       </div>
       <!-- 上面部分 -->
       <div ref="staff" style="margin: 20px 20px 0 220px; width: 81.5%">
@@ -71,7 +73,7 @@
               <el-form-item :label="$t('peopleconcerned')" prop="ownerId">
                 <!--普通员工只能自己填报自己的 -->
                 <el-select v-if="user.userNameNeedTranslate != '1'" v-model="addForm.ownerId"
-                  :placeholder="$t('pleaseselecttheapplicant')" style="width: 150px" :disabled="!permissions.costAudit"
+                  :placeholder="$t('pleaseselecttheapplicant')" style="width: 150px" :disabled="!permissions.costAudit && expenseMainTypeValue != 14454"
                   filterable="true">
                   <span v-for="(item, index) in users" :key="index">
                     <el-option :label="item.name" :value="item.id"></el-option>
@@ -91,7 +93,7 @@
                 </el-col>
               </el-form-item>
               <!-- 发票张数 -->
-              <el-form-item :label="$t('invoicenumber')" v-if="this.user.timeType.easyExpense == 0">
+              <el-form-item :label="$t('invoicenumber')" v-if="this.user.timeType.easyExpense == 0 && (expenseMainTypeValue != 14454)">
                 <el-input v-model="addForm.ticketNum" style="width: 150px"></el-input>
               </el-form-item>
               <!-- 费用主类型 -->
@@ -116,36 +118,35 @@
                   @selectCal="selectCal"></selectCat>
               </el-form-item>
               <!-- 第二审核人 -->
-              <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2 && user.companyId != 4811">
+              <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2">
                 <el-select v-if="user.userNameNeedTranslate != '1'" v-model="addForm.secondCheckerId"
                   :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px"
-                  filterable="true">
+                  filterable="true" :disabled="expenseMainTypeValue == 14454">
                   <span v-for="(item, index) in usersNoInfo" :key="index">
                     <el-option :label="item.name" :value="item.id"></el-option>
                   </span>
                 </el-select>
 
-                <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'150'" :distinction="'5'"
+                <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'150'" :distinction="'5'" :disabled="expenseMainTypeValue == 14454"
                   :subject="usersNoInfo" :subjectId="addForm.secondCheckerId" ref="selectCat" 
                   @selectCal="selectCal"></selectCat>
               </el-form-item>
-              <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2 && user.companyId == 4811 && expenseMainTypeValue != 14454">
-                <el-select v-if="user.userNameNeedTranslate != '1'" v-model="addForm.secondCheckerId"
-                  :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px"
+
+              <!-- 设备归属人 -->
+              <el-form-item label="设备归属人" v-if="expenseMainTypeValue == 14454">
+                <el-select v-model="addForm.equipmentOwnerId"
+                  placeholder="请选择设备归属人" style="width: 150px"
                   filterable="true">
-                  <span v-for="(item, index) in usersNoInfo" :key="index">
-                    <el-option :label="item.name" :value="item.id"></el-option>
+                  <span v-for="(item, index) in equipmentOwnerList" :key="index">
+                    <el-option :label="item.equipmentOwner" :value="item.id"></el-option>
                   </span>
                 </el-select>
-
-                <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'150'" :distinction="'5'"
-                  :subject="usersNoInfo" :subjectId="addForm.secondCheckerId" ref="selectCat" 
-                  @selectCal="selectCal"></selectCat>
               </el-form-item>
+
               <!-- 备注 -->
               <el-form-item :label="$t('bei-zhu')" style="display: block; width: 70%">
                 <el-input type="textarea" v-model="addForm.remark" :autosize="{ minRows: 2, maxRows: 2 }"
-                  maxlength="100"></el-input>
+                  maxlength="100" :disabled="expenseMainTypeValue == 14454"></el-input>
               </el-form-item>
               <!-- 总费用 -->
               <!-- <div style="float: left; line-height: 55px;margin-left:20px">总费用 <el-link disabled v-model="addForm.totalAmount">{{addForm.totalAmount}}</el-link> 元</div> -->
@@ -187,7 +188,7 @@
               <el-table-column :label="$t('invoices')" width="175px" v-if="this.user.timeType.easyExpense == 0">
                 <template slot-scope="scope">
                   <el-select size="small" v-model="scope.row.invoiceType" :placeholder="$t('pleaseselectthetypeoffee')"
-                    style="width: 150px;">
+                    style="width: 150px;" :disabled="user.companyId == 4811 && user.id != addForm.ownerId && expenseMainTypeValue == 14454">
                     <el-option :label="$t('vATspecialinvoice')" value="0"></el-option>
                     <el-option :label="$t('vATgeneralinvoice')" value="1"></el-option>
                   </el-select>
@@ -211,13 +212,13 @@
               <el-table-column prop="invoiceNo" :label="$t('invoiceno')" width="135px"
                 v-if="this.user.timeType.easyExpense == 0">
                 <template slot-scope="scope">
-                  <el-input size="small" v-model.number="scope.row.invoiceNo"></el-input>
+                  <el-input size="small" v-model.number="scope.row.invoiceNo" :disabled="user.companyId == 4811 && user.id != addForm.ownerId && expenseMainTypeValue == 14454"></el-input>
                 </template>
               </el-table-column>
               <el-table-column :label="$t('shui-shuai')" width="135px" v-if="this.user.timeType.easyExpense == 0">
                 <template slot-scope="scope">
                   <el-input size="small" type="number" v-model="scope.row.taxPercent"
-                    @input="zhi(scope.$index)"></el-input>
+                    @input="zhi(scope.$index)" :disabled="user.companyId == 4811 && user.id != addForm.ownerId && expenseMainTypeValue == 14454"></el-input>
                 </template>
               </el-table-column>
               <el-table-column :label="$t('taxs')" width="135px" v-if="this.user.timeType.easyExpense == 0">
@@ -374,36 +375,96 @@
             v-loading="listLoading" :height="tableHeight - currentClickNum" style="width: 100%;"
             :summary-method="getSummaries" show-summary>
             <el-table-column type="selection" width="55"></el-table-column>
-            <el-table-column prop="code" :label="$t('ticketnumber')" width="120"></el-table-column>
+            <el-table-column prop="code" :label="$t('ticketnumber')" width="120">
+              <template slot-scope="scope">
+                <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                  <span style="color: red">{{ scope.row.code }}</span>
+                </template>
+                <template v-else>{{ scope.row.code }}</template>
+              </template>
+            </el-table-column>
+            <el-table-column prop="engineeringName" label="工程名称" width="200" v-if="user.companyId == 4811">
+              <template slot-scope="scope">
+                <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                  <span style="color: red">{{ scope.row.engineeringName }}</span>
+                </template>
+                <template v-else>{{ scope.row.engineeringName }}</template>
+              </template>
+            </el-table-column>
             <el-table-column prop="totalAmount" :label="$t('amountof') + '(' + $t('yuan') + ')'" align="center" width="120">
               <template slot-scope="scope">
-                <span style="float:right;margin-right:20px">{{ scope.row.totalAmount ? scope.row.totalAmount.toFixed(2) :
-                  '0' }}</span>
+                <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                  <span style="color: red">
+                    <span style="float:right;margin-right:20px">{{ scope.row.totalAmount ? scope.row.totalAmount.toFixed(2) : '0' }}</span>
+                  </span>
+                </template>
+                <template v-else>
+                  <span style="float:right;margin-right:20px">{{ scope.row.totalAmount ? scope.row.totalAmount.toFixed(2) : '0' }}</span>
+                </template>
               </template>
             </el-table-column>
             <el-table-column prop="ownerName" :label="$t('peopleconcerned')">
               <template slot-scope="scope">
                 <div>
-                  <span v-if="user.userNameNeedTranslate != 1">
-                    {{ scope.row.ownerName }}
-                  </span>
-                  <span v-if="user.userNameNeedTranslate == 1">
-                    <TranslationOpenDataText type='userName' :openid='scope.row.ownerName'></TranslationOpenDataText>
-                  </span>
+                  <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                    <span style="color: red">
+                      <span v-if="user.userNameNeedTranslate != 1">
+                        {{ scope.row.ownerName }}
+                      </span>
+                      <span v-if="user.userNameNeedTranslate == 1">
+                        <TranslationOpenDataText type='userName' :openid='scope.row.ownerName'></TranslationOpenDataText>
+                      </span>
+                    </span>
+                  </template>
+                  <template v-else>
+                    <span v-if="user.userNameNeedTranslate != 1">
+                      {{ scope.row.ownerName }}
+                    </span>
+                    <span v-if="user.userNameNeedTranslate == 1">
+                      <TranslationOpenDataText type='userName' :openid='scope.row.ownerName'></TranslationOpenDataText>
+                    </span>
+                  </template>
                 </div>
               </template>
             </el-table-column>
-            <el-table-column prop="createDate" :label="$t('fillinthedate')" width="100"></el-table-column>
+            <el-table-column prop="createDate" :label="$t('fillinthedate')" width="100">
+              <template slot-scope="scope">
+                <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                  <span style="color: red">{{ scope.row.createDate }}</span>
+                </template>
+                <template v-else>{{ scope.row.createDate }}</template>
+              </template>
+            </el-table-column>
             <el-table-column prop="ticketNum" :label="$t('invoicenumber')"
-              v-if="this.user.timeType.easyExpense == 0"></el-table-column>
+              v-if="this.user.timeType.easyExpense == 0 && user.companyId != 4811"></el-table-column>
             <el-table-column prop="type" :label="$t('ppertype')" v-if="this.user.timeType.easyExpense == 0">
               <template slot-scope="scope">
-                {{ scope.row.expenseMainTypeName }}
+                <template slot-scope="scope">
+                  <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                    <span style="color: red">{{ scope.row.expenseMainTypeName }}</span>
+                  </template>
+                  <template v-else>{{ scope.row.expenseMainTypeName }}</template>
+                </template>
+              </template>
+            </el-table-column>
+            <el-table-column prop="equipmentOwnerName" label="设备归属人" v-if="user.companyId == 4811" width="150">
+              <template slot-scope="scope">
+                <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                  <span style="color: red">{{ scope.row.equipmentOwnerName }}</span>
+                </template>
+                <template v-else>{{ scope.row.equipmentOwnerName }}</template>
               </template>
             </el-table-column>
             <el-table-column prop="remark" :label="$t('bei-zhu')" width="180">
               <template slot-scope="scope">
-                <span style="font-size:12px;">{{ scope.row.remark }}</span>
+                  <template v-if="user.companyId == 4811 && scope.row.status == 4">
+                    <span style="color: red">
+                      <span style="font-size:12px;">{{ scope.row.remark }}</span>
+                    </span>
+                  </template>
+                  <template v-else>
+                    <span style="font-size:12px;">{{ scope.row.remark }}</span>
+                  </template>
               </template>
             </el-table-column>
             <el-table-column prop="status" :label="$t('state.states')" width="80">
@@ -442,8 +503,8 @@
                   <el-button icon="el-icon-view" circle size="mini"
                     @click.stop.native="downloadByA(scope.row)"></el-button>
                   <el-button icon="el-icon-edit" circle size="mini" style="margin-left:10px;"
-                    @click.stop.native="showEditName(scope.row)"
-                    v-show="permissions.costAudit || scope.row.status == 1 || scope.row.status == 2"></el-button>
+                  @click.stop.native="showEditName(scope.row)"
+                  v-show="(scope.row.status == 1 || scope.row.status == 2 || scope.row.status == 4) && ((user.id == scope.row.ownerId && user.companyId == (4811)) || permissions.costAudit)"></el-button>
                   <el-button icon="el-icon-delete" circle size="mini" style="margin-left:10px;"
                     @click.stop.native="deleteItem(scope.row)"
                     v-show="permissions.costAudit || scope.row.status == 1 || scope.row.status == 2"></el-button>
@@ -496,7 +557,7 @@
 
           </el-form-item>
           <!-- 第一审核人 -->
-          <el-form-item :label="$t('di-yi-shen-he-ren')" v-if="auditTypeItem.auditType == 2">
+          <el-form-item :label="$t('di-yi-shen-he-ren')" v-if="auditTypeItem.auditType == 2 && user.companyId != 4811">
             <el-select v-if="user.userNameNeedTranslate != '1'" v-model="ParticularsList.firstCheckerId"
               :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px" :disabled="ParticularsList.reviewProcess > 0 || (flg || ParticularsList.ownerId == ParticularsList.operatorId)"
               filterable="true">
@@ -509,8 +570,22 @@
               :subject="users" :subjectId="ParticularsList.firstCheckerId" ref="selectCat" :disabled="ParticularsList.reviewProcess > 0 || (flg || ParticularsList.ownerId == ParticularsList.operatorId)"
               @selectCal="selectCal"></selectCat>
           </el-form-item>
+
+          <el-form-item :label="$t('di-yi-shen-he-ren')" v-if="auditTypeItem.auditType == 2 && user.companyId == 4811">
+            <el-select v-if="user.userNameNeedTranslate != '1'" v-model="ParticularsList.firstCheckerId"
+              :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px" :disabled="user.id != ParticularsList.ownerId"
+              filterable="true">
+              <span v-for="(item, index) in users" :key="index">
+                <el-option :label="item.name" :value="item.id"></el-option>
+              </span>
+            </el-select>
+
+            <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'150'" :distinction="'6'"
+              :subject="users" :subjectId="ParticularsList.firstCheckerId" ref="selectCat" :disabled="user.id != ParticularsList.ownerId"
+              @selectCal="selectCal"></selectCat>
+          </el-form-item>
           <!-- 第二审核人 -->
-          <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2">
+          <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2 && user.companyId != 4811">
             <el-select v-if="user.userNameNeedTranslate != '1'" v-model="ParticularsList.secondCheckerId"
               :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px" :disabled="ParticularsList.reviewProcess > 1 || (flg || ParticularsList.ownerId == ParticularsList.operatorId)"
               filterable="true">
@@ -524,18 +599,47 @@
               @selectCal="selectCal"></selectCat>
           </el-form-item>
 
+          <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2 && user.companyId == 4811">
+            <el-select v-if="user.userNameNeedTranslate != '1'" v-model="ParticularsList.secondCheckerId"
+              :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px" :disabled="user.id != ParticularsList.ownerId"
+              filterable="true">
+              <span v-for="(item, index) in users" :key="index">
+                <el-option :label="item.name" :value="item.id"></el-option>
+              </span>
+            </el-select>
+
+            <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'150'" :distinction="'7'"
+              :subject="users" :subjectId="ParticularsList.secondCheckerId" ref="selectCat" :disabled="user.id != ParticularsList.ownerId"
+              @selectCal="selectCal"></selectCat>
+          </el-form-item>
+
+          <el-form-item label="设备归属人" v-if="ParticularsList.type == 14454">
+            <el-select v-model="ParticularsList.equipmentOwnerId"
+              placeholder="请选择设备归属人" style="width: 150px"
+              filterable="true" :disabled="(ParticularsList.type == 14454 && user.companyId == 4811)">
+              <span v-for="(item, index) in equipmentOwnerList" :key="index">
+                <el-option :label="item.equipmentOwner" :value="item.id"></el-option>
+              </span>
+            </el-select>
+          </el-form-item>
+
           <el-form-item :label="$t('fillinthedate')">
             <!-- <el-input v-model="ParticularsList.createDate" :disabled="flg"></el-input> -->
-            <el-date-picker type="date" :disabled="flg" :placeholder="$t('optiondate')"
+            <el-date-picker type="date" :disabled="flg || (ParticularsList.type == 14454 && user.companyId == 4811)" :placeholder="$t('optiondate')"
               v-model="ParticularsList.createDate" value-format="yyyy-MM-dd" style="width: 200px;"></el-date-picker>
           </el-form-item>
-          <el-form-item :label="$t('invoicenumber')">
+          <el-form-item :label="$t('invoicenumber')" v-if="user.companyId == 4811 && ParticularsList.type != 14454">
             <el-input v-enter-number v-model="ParticularsList.ticketNum" :disabled="flg"></el-input>
           </el-form-item>
           <el-form-item :label="$t('costtype')" style="width: 270px">
-            <el-select size="small" v-model="ParticularsList.type" style="width: 150px" :disabled="flg">
-              <el-option v-for="item in expenseMainTypes" :key="item.id" :label="item.name" :value="item.id"></el-option>
-            </el-select>
+            <template v-if="user.companyId == 4811 && ParticularsList.type == 14454">
+              机械费用
+            </template>
+            <template v-else>
+              <el-select size="small" v-model="ParticularsList.type" style="width: 150px" :disabled="flg || (ParticularsList.type == 14454 && user.companyId == 4811)">
+                <el-option v-for="item in expenseMainTypes" :key="item.id" :label="item.name" :value="item.id"></el-option>
+              </el-select>
+            </template>
           </el-form-item>
           <el-form-item :label="$t('bei-zhu')" style="width: 280px">
             <el-input v-model="ParticularsList.remark" :disabled="flg" maxlength="100"></el-input>
@@ -567,7 +671,7 @@
           <el-table-column prop="projectId" :label="$t('other.project')" width="155">
             <template slot-scope="scope">
               <el-select size="small" v-if="!flg" v-model="scope.row.projectId" :placeholder="$t('other.project')"
-                style="width: 130px">
+                style="width: 130px" :disabled="(ParticularsList.type == 14454 && user.companyId == 4811)">
                 <el-option v-for="(item, index) in projectList" :key="index" :label="item.projectName + item.projectCode"
                   :value="item.id" @click="ok(item)">
                   <span style="float: left;color: #8492a6; font-size: 13px">{{ item.projectCode }}</span>
@@ -582,7 +686,7 @@
           <el-table-column prop="happenDate" :label="$t('forthedate')" width="172">
             <template slot-scope="scope">
               <el-date-picker size="small" v-if="!flg" v-model="scope.row.happenDate" type="date" style=" width: 145px"
-                value-format="yyyy-MM-dd" :placeholder="$t('optiondate')">
+                value-format="yyyy-MM-dd" :placeholder="$t('optiondate')" :disabled="(ParticularsList.type == 14454 && user.companyId == 4811)">
               </el-date-picker>
               <span v-else>{{ scope.row.happenDate }}</span>
             </template>
@@ -601,7 +705,7 @@
           <el-table-column prop="invoiceType" :label="$t('costtype')" width="172">
             <template slot-scope="scope">
               <el-select v-if="!flg" size="small" v-model="scope.row.expenseType"
-                :placeholder="$t('pleaseselectthetypeoffee')" style="width: 150px">
+                :placeholder="$t('pleaseselectthetypeoffee')" style="width: 150px" :disabled="(ParticularsList.type == 14454 && user.companyId == 4811)">
                 <el-option v-for="(item, index) in expenseTypeList" :key="index" :label="item.typeName"
                   :value="item.typeName"></el-option>
               </el-select>
@@ -854,7 +958,7 @@
             <span class="detail-item-title"><span class="printBox">{{ $t('tianBaoShiJian') }}</span></span>
             <span class="detail-item-content">{{ ParticularsList.createDate }}</span>
           </div>
-          <div class="detail-item">
+          <div class="detail-item" v-if="ParticularsList.type != 14454">
             <span class="detail-item-title"><span class="printBox">{{ $t('invoicenumber') }}</span></span>
             <span class="detail-item-content">{{ ParticularsList.ticketNum }} {{ $t('zhang') }}</span>
           </div>
@@ -862,6 +966,10 @@
             <span class="detail-item-title"><span class="printBox">{{ $t('feiYongLeiXing') }}</span></span>
             <span class="detail-item-content">{{ detaExpenseMainTypeName }}</span>
           </div>
+          <div class="detail-item" v-if="ParticularsList.type == 14454">
+            <span class="detail-item-title"><span class="printBox">设备归属人</span></span>
+            <span class="detail-item-content">{{ ParticularsList.equipmentOwnerName }}</span>
+          </div>
           <div class="detail-item">
             <span class="detail-item-title"><span class="printBox">{{ $t('totalcostos') }}</span></span>
             <span class="detail-item-content">¥ {{ ParticularsList.totalAmount | numberToCurrency }}</span>
@@ -1099,6 +1207,36 @@
         <el-button type="primary" @click="callingInterface(1, releaseData.data)">{{ $t('queDing') }}</el-button>
       </span>
     </el-dialog>
+
+    <!-- 设备归属人管理 -->
+    <el-dialog title="设备归属人管理" :visible.sync="equipmentOwnerVisable" width="600" :before-close="handleClose">
+      <el-table :data="equipmentOwnerList" style="width: 100%" height="40vh">
+        <el-table-column label="序号" width="180">
+          <template slot-scope="scope">
+            {{ scope.$index + 1 }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="equipmentOwner" label="姓名"></el-table-column>
+        <el-table-column label="操作" width="240">
+          <template slot-scope="scope">
+            <el-button type="primary" size="small" @click="updateOwner(scope.row)">编辑</el-button>
+            <el-button type="danger" size="small" @click="deleteOwner(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="equipmentOwnerVisable = false">取 消</el-button>
+        <el-button type="primary" @click="updateOwner()">新增归属人</el-button>
+      </span>
+    </el-dialog>
+
+    <el-dialog :title="`${equipmentOwnerValue.id ? '编辑' : '新增'}归属人`" :visible.sync="equipmentOwnertextVisable" width="600" :before-close="handleClose">
+      <el-input v-model.trim="equipmentOwnerValue.equipmentOwner" placeholder="请输入归属人名称" clearable></el-input>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="equipmentOwnertextVisable = false">取 消</el-button>
+        <el-button type="primary" @click="addEditorOwner()" :disabled="!equipmentOwnerValue.equipmentOwner">确 定</el-button>
+      </span>
+    </el-dialog>
   </section>
 </template>
 
@@ -1129,6 +1267,7 @@ export default {
         reason: '',
         id: null
       },
+      copyUsers: [],
       basecostSettingList: [],
       exportingData:false,
       fileList: [],
@@ -1223,6 +1362,11 @@ export default {
       dialogVisibleRelease: false, // 发放弹出框
 
       selectProject: null, // 项目选择
+
+      equipmentOwnerVisable: false,
+      equipmentOwnerList: [],
+      equipmentOwnertextVisable: false,
+      equipmentOwnerValue: { equipmentOwner: '' }
     };
   },
   computed: {
@@ -1256,6 +1400,9 @@ export default {
     this.getBasecostItemList();
     this.getAuditType();
     this.getSendStateList();
+    if(this.user.companyId == 4811) {
+      this.getEquipmentOwnerList()
+    }
   },
   filters: {
     numberToCurrency(value) {
@@ -1274,6 +1421,66 @@ export default {
     }
   },
   methods: {
+    updateOwner(row) {
+      if(!row) {
+        this.equipmentOwnerValue = { equipmentOwner: '' }
+      } else {
+        this.equipmentOwnerValue = { equipmentOwner: row.equipmentOwner, id: row.id }
+      }
+      this.equipmentOwnertextVisable = true
+    },
+    equipmentOwner() {
+      this.equipmentOwnerVisable = true
+    }, 
+    deleteOwner(row) {
+      this.$confirm(`此操作将删除【${row.equipmentOwner}】设备归属人, 是否继续?`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.http.post('/equipment-owner/removeEquipmentOwner', {
+          id: row.id
+        },
+        res => {
+          if (res.code == 'ok') {
+            this.$message({ message: '删除成功', type: 'success' })
+            this.getEquipmentOwnerList()
+          } else {
+            this.$message({ message: res.msg, type: 'error'})
+          }
+        }, err => {
+          this.$message({ message: err, type: 'error' })
+        })
+      })
+    },
+    addEditorOwner() {
+      this.http.post('/equipment-owner/addOrUpdate', {
+        ...this.equipmentOwnerValue
+      },
+      res => {
+        if (res.code == 'ok') {
+          this.$message({ message: '添加成功', type: 'success' })
+          this.equipmentOwnertextVisable = false
+          this.getEquipmentOwnerList()
+        } else {
+          this.$message({ message: res.msg, type: 'error'})
+        }
+      }, err => {
+        this.$message({ message: err, type: 'error' })
+      })
+    },
+    getEquipmentOwnerList() {
+      this.http.post('/equipment-owner/getList', {},
+      res => {
+        if (res.code == 'ok') {
+          this.equipmentOwnerList = res.data || [];
+        } else {
+          this.$message({ message: res.msg, type: 'error'})
+        }
+      }, err => {
+        this.$message({ message: err, type: 'error' })
+      })
+    },
     getBasecostItemList() {
       this.http.post('/project-basecost-setting/list', {},
         res => {
@@ -1645,8 +1852,18 @@ export default {
         });
     },
     costMainTypeSwitching() {
-      if(this.user.companyId == 4811 && this.expenseMainTypeValue == 14454) {
-        this.addForm.firstCheckerId = this.user.id
+      if(this.user.companyId == 4811) {
+        if(this.expenseMainTypeValue == 14454) {
+          this.users = JSON.parse(JSON.stringify(this.copyUsers)).filter(item => item.id != this.user.id)
+          this.addForm.firstCheckerId = ''
+          this.addForm.secondCheckerId = ''
+          if(this.addForm.ownerId == this.user.id) {
+            this.addForm.ownerId = ''
+          }
+        } else {
+          this.addForm.ownerId = this.user.id
+          this.users = JSON.parse(JSON.stringify(this.copyUsers))
+        }
       }
       this.getExpList()
     },
@@ -1689,10 +1906,11 @@ export default {
       },
         res => {
           if (res.code == "ok") {
-            if(this.user.roleName == '费用管理员') {
-              this.expenseMainTypes = res.data
-            } else {
+            if(this.user.isMachineCost != 2) {
               this.expenseMainTypes = res.data.filter(item => item.id != 14454)
+              // this.addForm.firstCheckerId = this.user.id
+            } else {
+              this.expenseMainTypes = res.data
             }
             this.expenseMainTypeValue = this.expenseMainTypes[0].id
           } else {
@@ -1747,6 +1965,16 @@ export default {
       this.displayTable = true;
     },
     present() {
+      if(this.user.companyId == 4811) {
+        if(!this.ParticularsList.firstCheckerId || !this.ParticularsList.secondCheckerId) {
+          this.$message({
+            message: !this.ParticularsList.firstCheckerId ? this.$t('qingXuanZeDiYiShenHeRen') : this.$t('qingXuanZeDiErShenHeRen'),
+            type: "error"
+          });
+          return;
+        }
+      }
+
       this.adds();
     },
     // 删除操作
@@ -1819,8 +2047,9 @@ export default {
             // this.users = res.data.records;
             const { id } = JSON.parse(sessionStorage.getItem('user'))
             this.users = res.data;
-            // this.usersNoInfo = res.data.filter(item => item.id != id)
-            this.usersNoInfo = res.data
+            this.usersNoInfo = res.data.filter(item => item.id != id)
+            this.copyUsers = JSON.parse(JSON.stringify(res.data))
+            // this.usersNoInfo = res.data
             if (!this.permissions.costAudit) {
               this.addForm.ownerId = this.user.id;
               this.addForm.status = 1;
@@ -1845,7 +2074,7 @@ export default {
       this.$refs.mainAddForm.validate(valid => {
         if (valid) {
           if(this.auditTypeItem.auditType == 2 && (!this.addForm.firstCheckerId || !this.addForm.secondCheckerId)) {
-            if(this.user.id != 4811 && this.expenseMainTypeValue != 14454) {
+            if(this.user.companyId != 4811 && this.expenseMainTypeValue != 14454) {
               this.$message({
                 message: !this.addForm.firstCheckerId ? this.$t('qingXuanZeDiYiShenHeRen') : this.$t('qingXuanZeDiErShenHeRen'),
                 type: "error"
@@ -2047,7 +2276,7 @@ export default {
             });
             this.addForm = {
               code: null,
-              ownerId: this.user.id,
+              ownerId: this.expenseMainTypeValue == 14454 ? '' : this.user.id,
               createDate: null,
               type: this.expenseMainTypeValue,
               ticketNum: 1, remark: null, totalAmount: 0,

+ 111 - 3
fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

@@ -246,7 +246,7 @@
                     <div class="underpanel">
                         <div class="whiteList_head">
                             <span style="float:left;color:#999">{{ $t('personneltoset') }}</span>
-                            <el-link type="primary" style="float:left;margin-left:15px" :underline="false" @click="addWhite">{{ $t('addTian') }}</el-link>
+                            <el-link type="primary" style="float:left;margin-left:15px" :underline="false" @click="addWhite('personnel')">{{ $t('addTian') }}</el-link>
                         </div>
                         <div class="whiteList_content">
                             <el-tag style="margin:10px 0 0 10px" v-for="item in whiteList" :key="item.id" closable @close="whiteDelete(item)">
@@ -284,6 +284,30 @@
                 </div>
             </el-col>
         </el-row>
+
+        <!-- 机械费用下发设置 -->
+        <template v-if="user.companyId == 4811">
+            <p style="margin-left:10px;color:#666;">机械费用下发设置</p>
+            <el-row :gutter="20" style="padding-top:10px;width:100%;margin:0 auto;padding-left:10px;padding-right:10px;">
+                <el-col :span="24" >
+                    <div class="panel" >
+                        <div class="underpanel">
+                            <div class="whiteList_head">
+                                <span style="float:left;color:#999">机械费用下发人员</span>
+                                <el-link type="primary" style="float:left;margin-left:15px" :underline="false" @click="addWhite('mechanics')">{{ $t('addTian') }}</el-link>
+                            </div>
+                            <div class="whiteList_content">
+                                <el-tag style="margin:10px 0 0 10px" v-for="item in mechanicalPersonnelList" :key="item.id" closable @close="mechanicsDeleteItem(item)">
+                                    <span v-if="user.userNameNeedTranslate != '1'">{{item.name}}</span>
+                                    <span v-if="user.userNameNeedTranslate == '1'"><TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText></span>
+                                </el-tag>
+                            </div>
+                        </div>
+                    </div>
+                </el-col>
+            </el-row>
+        </template>
+
 <!-- 设置员工可补填的时间 -->
         <p style="margin-left:10px;color:#666;">{{ $t('timesetting') }}</p>
         <el-row :gutter="20" style="padding-top:10px;width:100%;margin:0 auto;padding-left:10px;padding-right:10px;">
@@ -734,7 +758,8 @@
             <!-- <div>已选中&nbsp;{{chosenMembCount}}&nbsp;人</div>         :default-checked-keys="alreadyPartArray"  @check-change="onTreeItemChange" -->
             <div slot="footer" class="dialog-footer">
                 <el-button  @click="whiteListDialog = false, resetechartDepartment()">{{ $t('btn.cancel') }}</el-button>
-                <el-button type="primary" @click="setWhiteList()">{{ $t('btn.determine') }}</el-button>
+                <!-- <el-button type="primary" @click="setWhiteList()">{{ $t('btn.determine') }}</el-button> -->
+                <el-button type="primary" @click="personnelDetermination()">{{ $t('btn.determine') }}</el-button>
             </div>
         </el-dialog>
 
@@ -951,6 +976,8 @@
                         return false;
                     }
                 },
+                mechanicalPersonnelList: [],
+                selectPersonnelType: 'personnel',
             };
         },
         watch: {
@@ -988,6 +1015,9 @@
             setTimeout(() => {
                 // thats.$tours['myTour'].start()
             }, 1000)
+            if(this.user.companyId == 4811) {
+                this.getMechanicalPersonnelList()
+            }
         },
          methods: {
             startSynchronizing() {
@@ -1701,12 +1731,35 @@
             //     var list = chosenList.filter(item=>item.isUser == 1);
             //     // this.chosenMembCount = list.length;
             // },
-            addWhite(){
+            addWhite(type = 'personnel'){
                 this.specialHolidays = 0
                 this.whiteListDialog = true
                 this.filterText = ''
+                this.selectPersonnelType = type
                 this.getWhiteListAll()
             },
+            mechanicsDeleteItem(item) {
+                const id = item.id
+                this.http.post('/user/removeUserIsMachine',{ id },res => {
+                    if(res.code == 'ok'){
+                        this.$message({
+                            message: this.$t('message.successfullyDeleted'),
+                            type: 'success'
+                        })
+                        this.getMechanicalPersonnelList()
+                    }else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                },err => {
+                    this.$message({
+                        message: err,
+                        type: 'error'
+                    })
+                })
+            },  
             whiteDelete(item){
                 
                 this.whiteList.splice(this.whiteList.indexOf(item),1)
@@ -1732,6 +1785,44 @@
                     })
                 })
             },
+            personnelDetermination() {
+                if(this.selectPersonnelType == 'mechanics') {
+                    this.setUpMechanicalPersonnel()
+                } else {
+                    this.setWhiteList()
+                }
+            },
+            setUpMechanicalPersonnel() {
+                let chosenList = this.$refs.whiteListTree.getCheckedNodes();
+                let chose2 = chosenList.filter(item=>item.isUser == 1)
+                let chose3 = ''
+                for(let i=0;i<chose2.length;i++){chose3 += chose2[i].id + ','}
+                chose3 = chose3.substring(0,chose3.length - 1)
+
+                this.http.post('/user/addUserIsMachine',{
+                    ids: chose3
+                },res => {
+                    if(res.code == 'ok'){
+                        this.$message({
+                            message: this.$t('addsuccessful'),
+                            type: 'success'
+                        })
+                        this.getMechanicalPersonnelList()
+                        this.resetechartDepartment()
+                        this.whiteListDialog = false
+                    }else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                },error => {
+                    this.$message({
+                        message: error,
+                        type: 'error'
+                    })
+                })
+            },
             setWhiteList(){
                 let chosenList = this.$refs.whiteListTree.getCheckedNodes();
                 let chose2 = chosenList.filter(item=>item.isUser == 1)
@@ -2060,6 +2151,23 @@
                 this.searchPersonnelFlg = false
                 this.getWhiteListAll()
             },
+            getMechanicalPersonnelList() {
+                this.http.post('/user/getUserIsMachineList', {}, res => {
+                    if(res.code == 'ok'){
+                        this.mechanicalPersonnelList = res.data || []
+                    }else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                },error => {
+                    this.$message({
+                        message: error,
+                        type: 'error'
+                    })
+                })
+            },
             // 重置企业微信选人搜索
             resetechartDepartment() {
                 this.wxFilterText = ''

+ 5 - 0
fhKeeper/formulahousekeeper/timesheet_h5/src/views/my/children/center.vue

@@ -33,6 +33,7 @@
                 <van-cell title="使用说明" :title-style="'flex: 1;'" is-link @click="instructions()"></van-cell>
                 <van-cell title="在线客服" :title-style="'flex: 1;'" is-link @click="tokefu()"></van-cell>
                 <van-cell title="添加员工" :title-style="'flex: 1;'" is-link @click="addEmployee()" v-if="wxManager"></van-cell>
+                <van-cell title="应用市场" :title-style="'flex: 1;'" is-link @click="applicationMarket()"></van-cell>
                 <!-- </div> -->
                 <!-- <van-cell title="修改密码" isLink to="/my/set"></van-cell> -->
             </div>
@@ -78,6 +79,10 @@
         },
 
         methods: {
+            applicationMarket() {
+                window.location.href = 'https://www.ttkuaiban.com/appMarket.html'
+                // window.open('https://www.ttkuaiban.com/appMarket.html', '_blank'); 
+            },
             logout() {
                 this.$store.commit("updateLogin", false);
                 localStorage.removeItem("userInfo");

+ 106 - 0
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/appMarket.html

@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>应用市场</title>
+  <link rel="stylesheet" href="./css/reset.css">
+  <link rel="stylesheet" href="./css/appMarket.css">
+</head>
+
+<body>
+  <div class="applicationMarket">
+    <div class="applicationMarket-title">
+      <div class="ourServices">
+        应用市场
+      </div>
+      <div class="applicationEncyclopedia">
+        为您提供全面的数字化解决方案
+      </div>
+    </div>
+    <div class="topicContent">
+
+      <div class="bigCircle">
+        <a href="./index.html">
+          <div class="bigCircle-icon">
+            <img src="./image/gsgj.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              工时管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              工时管家基础版提供核心的工时填报、审核和统计功能,专业版增加了项目管理模块,包含立项、任务协同进度追踪、费用成本管控等功能。旗舰版涵盖了客户管理、合同管理、请假和出差管理模块,满足全面数字化办公需求。
+            </div>
+          </div>
+        </a>
+      </div>
+
+
+
+      <div class="bigCircle">
+        <a href="./customerNew.html">
+          <div class="bigCircle-icon">
+            <img src="./image/customerNew/login_logo.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              智能客户管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              客户管家是一款专为企业设计的客户关系管理系统(CRM),旨在通过智能化、高效化的管理手段,帮助企业节约营销成本、降低客户流失率,并提升客户追踪与数据处理的效率。主要用于企业的客户关系管理,通过整合客户信息、线索管理、商机挖掘、销售流程优化等功能,帮助企业更好地理解和服务客户,提升客户满意度和忠诚度,进而促进业务增长。
+            </div>
+          </div>
+        </a>
+      </div>
+
+      <div class="bigCircle">
+        <a href="./workshop.html">
+          <div class="bigCircle-icon">
+            <img src="./image/workshopimage/logo.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              生产车间管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              生产车间管家是一款专为解决生产管理、员工报工、数据统计等企业痛点的综合性管理软件。它不仅能够帮助企业实现生产流程的智能化管理,还能优化产品管理、排产计划、员工填报以及数据统计等多个环节,从而提升企业的整体运营效率和管理水平。
+            </div>
+          </div>
+        </a>
+      </div>
+
+
+      <div class="bigCircle">
+        <a href="./followup.html">
+          <div class="bigCircle-icon">
+            <img src="./image/followup/suifangaas.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              随访管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              随访管家是一款集患者资料收集整理、随访计划执行、和数据统计分析功能于一体的医患服务系统,帮助医院规范随访工作,提高随访效率,提升医疗水平,提高患者依从度。
+            </div>
+          </div>
+        </a>
+      </div>
+    </div>
+  </div>
+</body>
+
+</html>

+ 138 - 0
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/css/appMarket.css

@@ -0,0 +1,138 @@
+html,
+body {
+  width: 100%;
+  height: 100%;
+  background-color: #f6f7fb;
+}
+div {
+  box-sizing: border-box;
+}
+.applicationMarket {
+  height: 100%;
+}
+.applicationMarket .applicationMarket-title {
+  width: 100%;
+  padding: 80px 0 60px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.applicationMarket .applicationMarket-title .ourServices {
+  width: 160px;
+  text-align: center;
+  font-size: 14px;
+  padding: 8px 0;
+  color: #63aefb;
+  border: 1px solid #63aefb;
+  border-radius: 6px;
+  background-color: rgba(99, 174, 251, 0.2);
+  margin: auto;
+  margin-bottom: 20px;
+}
+.applicationMarket .applicationMarket-title .applicationEncyclopedia {
+  text-align: center;
+  font-size: 28px;
+  font-weight: bold;
+  color: #000000;
+  margin-bottom: 0px;
+}
+.applicationMarket .topicContent {
+  width: 70%;
+  margin: auto;
+  display: flex;
+  justify-content: space-between;
+  flex-wrap: wrap;
+  margin-bottom: 60px;
+}
+.applicationMarket .topicContent .bigCircle {
+  width: 49.3%;
+  background-color: #fff;
+  border-radius: 6px;
+  height: 320px;
+  padding: 25px;
+  cursor: pointer;
+  border: 1px solid #fff;
+  margin-bottom: 20px;
+}
+.applicationMarket .topicContent .bigCircle a {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  box-sizing: border-box;
+}
+.applicationMarket .topicContent .bigCircle .bigCircle-icon {
+  width: 20%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding-right: 25px;
+}
+.applicationMarket .topicContent .bigCircle .textTitle {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title {
+  font-size: 24px;
+  color: #000000;
+  font-weight: bold;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title .textTitle-title-icon {
+  width: 30px;
+  height: 30px;
+  border-radius: 50%;
+  background-color: rgba(99, 174, 251, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title .textTitle-title-icon img {
+  width: 50%;
+  height: 50%;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-text {
+  font-size: 16px;
+  color: #999999;
+  margin-top: 15px;
+  line-height: 1.4;
+}
+.applicationMarket .topicContent .bigCircle:hover {
+  border: 1px solid #86bffb;
+  background-color: rgba(99, 174, 251, 0.2);
+}
+.applicationMarket .topicContent .bigCircle:hover .textTitle-title-icon {
+  background-color: #fff !important;
+}
+.applicationMarket img {
+  width: 100%;
+}
+@media only screen and (max-width: 768px) {
+  .applicationMarket .applicationMarket-title {
+    padding-bottom: 30px !important;
+  }
+  .applicationMarket .applicationMarket-title .applicationEncyclopedia {
+    font-size: 22px !important;
+  }
+  .applicationMarket .topicContent {
+    width: 85% !important;
+  }
+  .applicationMarket .bigCircle-icon {
+    width: 0 !important;
+    overflow: hidden !important;
+    padding: 0 !important;
+  }
+  .applicationMarket .topicContent {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
+  .applicationMarket .topicContent .bigCircle {
+    width: 100%;
+  }
+}

+ 161 - 0
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/css/appMarket.less

@@ -0,0 +1,161 @@
+html,
+body {
+  width: 100%;
+  height: 100%;
+  background-color: #f6f7fb;
+}
+
+div {
+  box-sizing: border-box;
+}
+
+.applicationMarket {
+  height: 100%;
+  .applicationMarket-title {
+    width: 100%;
+    padding: 80px 0 60px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+
+    .ourServices {
+      width: 160px;
+      text-align: center;
+      font-size: 14px;
+      padding: 8px 0;
+      color: #63aefb;
+      border: 1px solid #63aefb;
+      border-radius: 6px;
+      background-color: rgba(99, 174, 251, 0.2);
+      margin: auto;
+      margin-bottom: 20px;
+    }
+    .applicationEncyclopedia {
+      text-align: center;
+      font-size: 28px;
+      font-weight: bold;
+      color: #000000;
+      margin-bottom: 0px;
+    }
+  }
+
+  .topicContent {
+    width: 70%;
+    margin: auto;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    margin-bottom: 60px;
+
+    .bigCircle {
+      width: 49.3%;
+      background-color: #fff;
+      border-radius: 6px;
+      height: 320px;
+      padding: 25px;
+      cursor: pointer;
+      border: 1px solid #fff;
+
+      a {
+        width: 100%;
+        height: 100%;
+        display: flex;
+        flex-direction: row;
+        box-sizing: border-box;
+        box-sizing: border-box;
+      }
+
+      .bigCircle-icon {
+        width: 20%;
+        height: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding-right: 25px;
+      }
+
+      .textTitle {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+
+        .textTitle-title {
+          font-size: 24px;
+          color: #000000;
+          font-weight: bold;
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+
+          .textTitle-title-icon {
+            width: 30px;
+            height: 30px;
+            border-radius: 50%;
+            background-color: rgba(99, 174, 251, 0.2);
+            display: flex;
+            justify-content: center;
+            align-items: center;
+
+            img {
+              width: 50%;
+              height: 50%;
+            }
+          }
+        }
+
+        .textTitle-text {
+          font-size: 16px;
+          color: #999999;
+          margin-top: 15px;
+          line-height: 1.4;
+        }
+      }
+
+      &:hover {
+        border: 1px solid #86bffb;
+        background-color: rgba(99, 174, 251, 0.2);
+
+        .textTitle-title-icon {
+          background-color: #fff !important;
+        }
+      }
+
+      &{
+        margin-bottom: 20px;
+      }
+    }
+  }
+
+  img {
+    width: 100%;
+  }
+}
+
+// 媒体查询
+@media only screen and (max-width: 768px) {
+  .applicationMarket {
+    .applicationMarket-title {
+      padding-bottom: 30px !important;
+      .applicationEncyclopedia {
+        font-size: 22px !important;
+      }
+    }
+    .topicContent {
+      width: 85% !important;
+    }
+    .bigCircle-icon {
+      width: 0 !important;
+      overflow: hidden !important;
+      padding: 0 !important;
+    }
+    .topicContent {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      .bigCircle {
+        width: 100%;
+      }
+    }
+  }
+}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 196 - 196
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/customerNew.html


BIN
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/image/customerNew/login_logo.png


BIN
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/image/followup/suifangaas.png


BIN
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/image/ions/youjiantos.png


+ 106 - 0
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/appMarket.html

@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>应用市场</title>
+  <link rel="stylesheet" href="./css/reset.css">
+  <link rel="stylesheet" href="./css/appMarket.css">
+</head>
+
+<body>
+  <div class="applicationMarket">
+    <div class="applicationMarket-title">
+      <div class="ourServices">
+        应用市场
+      </div>
+      <div class="applicationEncyclopedia">
+        为您提供全面的数字化解决方案
+      </div>
+    </div>
+    <div class="topicContent">
+
+      <div class="bigCircle">
+        <a href="./index.html">
+          <div class="bigCircle-icon">
+            <img src="./image/gsgj.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              工时管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              工时管家基础版提供核心的工时填报、审核和统计功能,专业版增加了项目管理模块,包含立项、任务协同进度追踪、费用成本管控等功能。旗舰版涵盖了客户管理、合同管理、请假和出差管理模块,满足全面数字化办公需求。
+            </div>
+          </div>
+        </a>
+      </div>
+
+
+
+      <div class="bigCircle">
+        <a href="./customerNew.html">
+          <div class="bigCircle-icon">
+            <img src="./image/customerNew/login_logo.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              智能客户管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              客户管家是一款专为企业设计的客户关系管理系统(CRM),旨在通过智能化、高效化的管理手段,帮助企业节约营销成本、降低客户流失率,并提升客户追踪与数据处理的效率。主要用于企业的客户关系管理,通过整合客户信息、线索管理、商机挖掘、销售流程优化等功能,帮助企业更好地理解和服务客户,提升客户满意度和忠诚度,进而促进业务增长。
+            </div>
+          </div>
+        </a>
+      </div>
+
+      <div class="bigCircle">
+        <a href="./workshop.html">
+          <div class="bigCircle-icon">
+            <img src="./image/workshopimage/logo.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              生产车间管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              生产车间管家是一款专为解决生产管理、员工报工、数据统计等企业痛点的综合性管理软件。它不仅能够帮助企业实现生产流程的智能化管理,还能优化产品管理、排产计划、员工填报以及数据统计等多个环节,从而提升企业的整体运营效率和管理水平。
+            </div>
+          </div>
+        </a>
+      </div>
+
+
+      <div class="bigCircle">
+        <a href="./followup.html">
+          <div class="bigCircle-icon">
+            <img src="./image/followup/suifangaas.png">
+          </div>
+          <div class="textTitle">
+            <div class="textTitle-title">
+              随访管家
+              <div class="textTitle-title-icon">
+                <img src="./image/ions/youjiantos.png" />
+              </div>
+            </div>
+            <div class="textTitle-text">
+              随访管家是一款集患者资料收集整理、随访计划执行、和数据统计分析功能于一体的医患服务系统,帮助医院规范随访工作,提高随访效率,提升医疗水平,提高患者依从度。
+            </div>
+          </div>
+        </a>
+      </div>
+    </div>
+  </div>
+</body>
+
+</html>

+ 138 - 0
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/css/appMarket.css

@@ -0,0 +1,138 @@
+html,
+body {
+  width: 100%;
+  height: 100%;
+  background-color: #f6f7fb;
+}
+div {
+  box-sizing: border-box;
+}
+.applicationMarket {
+  height: 100%;
+}
+.applicationMarket .applicationMarket-title {
+  width: 100%;
+  padding: 80px 0 60px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.applicationMarket .applicationMarket-title .ourServices {
+  width: 160px;
+  text-align: center;
+  font-size: 14px;
+  padding: 8px 0;
+  color: #63aefb;
+  border: 1px solid #63aefb;
+  border-radius: 6px;
+  background-color: rgba(99, 174, 251, 0.2);
+  margin: auto;
+  margin-bottom: 20px;
+}
+.applicationMarket .applicationMarket-title .applicationEncyclopedia {
+  text-align: center;
+  font-size: 28px;
+  font-weight: bold;
+  color: #000000;
+  margin-bottom: 0px;
+}
+.applicationMarket .topicContent {
+  width: 70%;
+  margin: auto;
+  display: flex;
+  justify-content: space-between;
+  flex-wrap: wrap;
+  margin-bottom: 60px;
+}
+.applicationMarket .topicContent .bigCircle {
+  width: 49.3%;
+  background-color: #fff;
+  border-radius: 6px;
+  height: 320px;
+  padding: 25px;
+  cursor: pointer;
+  border: 1px solid #fff;
+  margin-bottom: 20px;
+}
+.applicationMarket .topicContent .bigCircle a {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  box-sizing: border-box;
+}
+.applicationMarket .topicContent .bigCircle .bigCircle-icon {
+  width: 20%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding-right: 25px;
+}
+.applicationMarket .topicContent .bigCircle .textTitle {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title {
+  font-size: 24px;
+  color: #000000;
+  font-weight: bold;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title .textTitle-title-icon {
+  width: 30px;
+  height: 30px;
+  border-radius: 50%;
+  background-color: rgba(99, 174, 251, 0.2);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-title .textTitle-title-icon img {
+  width: 50%;
+  height: 50%;
+}
+.applicationMarket .topicContent .bigCircle .textTitle .textTitle-text {
+  font-size: 16px;
+  color: #999999;
+  margin-top: 15px;
+  line-height: 1.4;
+}
+.applicationMarket .topicContent .bigCircle:hover {
+  border: 1px solid #86bffb;
+  background-color: rgba(99, 174, 251, 0.2);
+}
+.applicationMarket .topicContent .bigCircle:hover .textTitle-title-icon {
+  background-color: #fff !important;
+}
+.applicationMarket img {
+  width: 100%;
+}
+@media only screen and (max-width: 768px) {
+  .applicationMarket .applicationMarket-title {
+    padding-bottom: 30px !important;
+  }
+  .applicationMarket .applicationMarket-title .applicationEncyclopedia {
+    font-size: 22px !important;
+  }
+  .applicationMarket .topicContent {
+    width: 85% !important;
+  }
+  .applicationMarket .bigCircle-icon {
+    width: 0 !important;
+    overflow: hidden !important;
+    padding: 0 !important;
+  }
+  .applicationMarket .topicContent {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
+  .applicationMarket .topicContent .bigCircle {
+    width: 100%;
+  }
+}

+ 161 - 0
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/css/appMarket.less

@@ -0,0 +1,161 @@
+html,
+body {
+  width: 100%;
+  height: 100%;
+  background-color: #f6f7fb;
+}
+
+div {
+  box-sizing: border-box;
+}
+
+.applicationMarket {
+  height: 100%;
+  .applicationMarket-title {
+    width: 100%;
+    padding: 80px 0 60px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+
+    .ourServices {
+      width: 160px;
+      text-align: center;
+      font-size: 14px;
+      padding: 8px 0;
+      color: #63aefb;
+      border: 1px solid #63aefb;
+      border-radius: 6px;
+      background-color: rgba(99, 174, 251, 0.2);
+      margin: auto;
+      margin-bottom: 20px;
+    }
+    .applicationEncyclopedia {
+      text-align: center;
+      font-size: 28px;
+      font-weight: bold;
+      color: #000000;
+      margin-bottom: 0px;
+    }
+  }
+
+  .topicContent {
+    width: 70%;
+    margin: auto;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    margin-bottom: 60px;
+
+    .bigCircle {
+      width: 49.3%;
+      background-color: #fff;
+      border-radius: 6px;
+      height: 320px;
+      padding: 25px;
+      cursor: pointer;
+      border: 1px solid #fff;
+
+      a {
+        width: 100%;
+        height: 100%;
+        display: flex;
+        flex-direction: row;
+        box-sizing: border-box;
+        box-sizing: border-box;
+      }
+
+      .bigCircle-icon {
+        width: 20%;
+        height: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding-right: 25px;
+      }
+
+      .textTitle {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+
+        .textTitle-title {
+          font-size: 24px;
+          color: #000000;
+          font-weight: bold;
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+
+          .textTitle-title-icon {
+            width: 30px;
+            height: 30px;
+            border-radius: 50%;
+            background-color: rgba(99, 174, 251, 0.2);
+            display: flex;
+            justify-content: center;
+            align-items: center;
+
+            img {
+              width: 50%;
+              height: 50%;
+            }
+          }
+        }
+
+        .textTitle-text {
+          font-size: 16px;
+          color: #999999;
+          margin-top: 15px;
+          line-height: 1.4;
+        }
+      }
+
+      &:hover {
+        border: 1px solid #86bffb;
+        background-color: rgba(99, 174, 251, 0.2);
+
+        .textTitle-title-icon {
+          background-color: #fff !important;
+        }
+      }
+
+      &{
+        margin-bottom: 20px;
+      }
+    }
+  }
+
+  img {
+    width: 100%;
+  }
+}
+
+// 媒体查询
+@media only screen and (max-width: 768px) {
+  .applicationMarket {
+    .applicationMarket-title {
+      padding-bottom: 30px !important;
+      .applicationEncyclopedia {
+        font-size: 22px !important;
+      }
+    }
+    .topicContent {
+      width: 85% !important;
+    }
+    .bigCircle-icon {
+      width: 0 !important;
+      overflow: hidden !important;
+      padding: 0 !important;
+    }
+    .topicContent {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      .bigCircle {
+        width: 100%;
+      }
+    }
+  }
+}

+ 3 - 3
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/customerNew.html

@@ -6,7 +6,7 @@
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
   <meta name="keywords" content="客户关系管理系统,CRM系统,销售订单管理,随访任务,线索,商机,联系人,产品,智能客户关系管理" />
   <meta name="description"
-    content="智能客户管家是一款结合了AI人工智能技术的客户关系管理系统(CRM),帮助企业全面管理客户和订单信息,降低客户流失率,促进成单。可以有效降低企业的营销管理成本。" />
+    content="智能客户管家是一款结合了人工智能技术的客户关系管理系统(CRM),使用DeepSeek大模型能力帮助企业全面管理客户和订单信息,降低客户流失率,促进成单。可以有效降低企业的营销管理成本。" />
   <title>AI智能客户管家|客户关系管理系统|CRM系统|-客户管家是强大易用的客户关系管理系统。销售订单|客户管理|线索|商机|联系人|产品|报表分析|智能BI</title>
   <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
   <link href="css/styles.css" rel="stylesheet">
@@ -47,7 +47,7 @@
       <img src="./image/customerNew/banner.gif" alt="" />
       <div class="bannar_text">
         <div class="bannar_text_title">AI智能客户管家</div>
-        <div class="bannar_text_item">· 节约企业营销成本<br />· 降低客户流失率<br />· 高效的客户追踪和智能数据处理系统</div>
+        <div class="bannar_text_item">· 节约企业营销成本<br />· 降低客户流失率<br />· ChatBI+DeepSeek智能数据处理系统</div>
       </div>
       
       <div class="bannar_text_btn">
@@ -61,7 +61,7 @@
         <div class="integrationImg">
           <img src="./image/customerNew/integrationImg.png" alt="">
         </div>
-        <div class="integrationText">· 客户管家,独创AI一体化智能管理</div>
+        <div class="integrationText">· 客户管家,独创AI一体化智能管理+DeepSeek</div>
       </div>
     </div>
 

BIN
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/image/customerNew/login_logo.png


BIN
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/image/followup/suifangaas.png


BIN
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/templates/image/ions/youjiantos.png