Procházet zdrojové kódy

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

zhouyy před 5 měsíci
rodič
revize
7f626e1254
36 změnil soubory, kde provedl 744 přidání a 104 odebrání
  1. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/formForm/formItem.vue
  2. 2 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/formForm/formView.vue
  3. 5 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js
  4. 12 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleList/moduleList.vue
  5. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contacts/contactsInfo.vue
  6. 163 18
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contract/detail.vue
  7. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/customerInfo.vue
  8. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/addEditor.vue
  9. 18 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/detail.vue
  10. 122 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/orderInfo.vue
  11. 18 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/detail.vue
  12. 2 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/newAndModifiedRelatedProducts.vue
  13. 139 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/productInfo.vue
  14. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/threadInfo.vue
  15. 7 7
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/salesBriefings.vue
  16. 4 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/workbench.vue
  17. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/news/index.vue
  18. 7 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/addEditorVisitor.vue
  19. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/visitorDetails.vue
  20. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/utility/generalVariables.js
  21. 7 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ContractController.java
  22. 5 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/TaskController.java
  23. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ContractService.java
  24. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/TaskService.java
  25. 17 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java
  26. 52 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  27. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  28. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  29. 47 11
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  30. 2 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  31. 5 5
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  32. 39 5
      fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue
  33. 5 1
      fhKeeper/formulahousekeeper/timesheet/src/views/task/list.vue
  34. 39 26
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  35. 3 3
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/project/index.vue
  36. 6 0
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/task/editask.vue

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/formForm/formItem.vue

@@ -163,6 +163,7 @@
     :style="{ height: '80%' }"
   >
     <PullDownSelector
+      :showElement="showSelect"
       :options="element.options.options"
       :multipleChoice="element.options.multiple"
       :doYouNeedTranslation="distinguishComponents"

+ 2 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/formForm/formView.vue

@@ -77,13 +77,14 @@ async function cascadeProcessing(relatedField) {
       const { data } = await requestData(list.value[i].options.remoteFunc, {
         ...formVal,
       });
-      list.value[i].options.options = data.map((item) => {
+      const newList = data.map((item) => {
         const { props: setProps } = list.value[i].options;
         return {
           label: item[setProps.label || "label"],
           value: item[setProps.value || "value"],
         };
       });
+      list.value[i].options.options = newList.length > 0 ? newList : [{ }];
     }
   }
 }

+ 5 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js

@@ -32,12 +32,14 @@ export const DELETE_PRODUCT = '/product/delete' // 删除产品
 export const DELETE_CONTRACT = '/contract/deleteContract' // 删除合同
 export const DELETE_ORDER = '/order/delete' // 删除订单
 export const DELETE_VISITOR_PLAN = `/visitPlan/delVisitPlan` // 删除访客计划
+export const TRANSFER_SALES_ORDERS = `/order/transfer` // 转移销售订单
 
 export const BUSINESS_OPPORTUNITY_TRANSFER = '/business-opportunity/claim' // 转移商机
 export const TRANSFER_CLUES = '/clue/claim' // 转移线索
 export const TRANSFER_CUSTOMERS = '/custom/claim' // 转移客户
 export const TRANSFER_CONTACT_PERSON = `/contacts/transferContacts` // 转移联系人
 export const NEW_BUSINESS_OPPORTUNITY_EDITING = `/business-opportunity/insertAndUpdate` // 商机新增编辑
+export const TRANSFER_PRODUCTS = `/product/transferIncharger` // 转移产品
 export const NEW_CLUE_EDITING = `/clue/insertAndUpdate` // 线索新增编辑
 export const CUSTOMER_ADDED_EDITOR = `/custom/insertAndUpdate` // 客户新增编辑
 export const CONTACT_PERSON_ADDITION_EDITOR = `/contacts/addContacts` // 联系人新增编辑
@@ -50,6 +52,7 @@ export const PLAN_TO_ADD_EDITORS = `/visitPlan/addOrUpdateVisitPlan` // 计划
 
 export const GET_BUSINESS_OPPORTUNITY_DETAILS = `/business-opportunity/getInfo` // 商机详情
 export const GET_CLUE_DETAILS = `/clue/getDetail` // 线索详情
+export const SALES_ORDER_DETAILS = `/order/getDetail` // 销售订单详情
 export const OBTAIN_CUSTOMER_DETAILS = `/custom/getInfo` // 获取客户想
 export const GET_CONTACT_DETAILS = `/contacts/getContactsDetail` // 获取联系人详情
 export const OBTAIN_PRODUCT_RELATED_BUSINESS_OPPORTUNITIES = `/product/businessListWithProduct` // 获取产品关联商机
@@ -57,6 +60,7 @@ export const OBTAIN_SALES_ORDERS_RELATED_TO_THE_PRODUCT = `/product/orderWithPro
 export const GET_ORDER_RELATED_TASKS = `/order/taskWithOrder` // 获取销售订单关联任务
 export const OBTAIN_ORDER_RELATED_PRODUCTS = `/order/productWithOrder` // 获取销售订单关联产品
 export const OBTAIN_DETAILS_OF_THE_VISIT_PLAN = `/visitPlan/getVisitPlanDetail` // 获取访客计划详情
+export const GET_PRODUCT_DETAILS = `/product/detail` // 获取产品详情
 
 export const SELL_AND_OBTAIN_RELATED_PRODUCTS = `/product/orderWithProduct` // 销售订单关联产品
 
@@ -94,6 +98,7 @@ export const CANCEL_THE_TOP_PLACEMENT_OF_THE_PRODUCT = `/product/undoPin` // 取
 export const TOP_DATA_OF_PRODUCT_LIST = `/product/pageProductByPin` // 产品列表顶置数据
 
 export const TOP_OF_THE_CONTRACT = `/contract/pinContract` // 合同顶置
+export const CONTRACT_APPROVED = `/contract/processContract` // 合同审批
 export const CONTRACT_CANCELLATION_WITH_TOP_PLACEMENT = `/contract/undoPin` // 取消顶置
 export const TOP_DATA_OF_CONTRACT_LIST = `/contract/pageContractByPin` // 合同列表顶置数据
 

+ 12 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleList/moduleList.vue

@@ -156,13 +156,13 @@
                       <div class="flex items-center h-full bg-white">
                         <template v-if="!item.inchargerName">
                           <div class="buttonCircle rounded-full" @click="claimAndClaim(item)" v-if="['business', 'thread',
-                            'customer'].includes(queryParameters?.key)">
+                            'customer', 'product'].includes(queryParameters?.key)">
                             <img src="/src/assets/image/claimAndClaim.png" class="w-full h-full">
                           </div>
                         </template>
                         <template v-if="item.inchargerName || item.ownerName">
                           <div class="buttonCircle rounded-full" @click="transfer(item)" v-if="['business', 'thread',
-                            'customer', 'contacts'].includes(queryParameters?.key)">
+                            'customer', 'contacts', 'product', 'order'].includes(queryParameters?.key)">
                             <img src="/src/assets/image/transfer.png" class="w-full h-full">
                           </div>
                         </template>
@@ -323,6 +323,8 @@ function confirmTransfer() {
   let formVal = {}
   if(queryParameters?.value.key == 'contacts') {
     formVal = { id, inchargerId: value, ownerId: value }
+  } else if(queryParameters?.value.key == 'product' || queryParameters?.value.key == 'order') {
+    formVal = { id, userId: value }
   } else {
     formVal = { ids: id, inchargerId: value, }
   }
@@ -335,13 +337,18 @@ function confirmTransfer() {
 
 // 认领
 function claimAndClaim(item) {
-  const { id, name, clueName, customName } = item
+  const { id, name, clueName, customName, productName } = item
+  const { key } = queryParameters.value
   const userId = userInfo.userInfo.id
+  const formVal = {
+    [key == 'product' ? 'id' : 'ids']: id,
+    [key == 'product' ? 'userId' : 'inchargerId']: userId
+  }
   showConfirmDialog({
     title: `认领${queryParameters.value.name}`,
-    message: `确定认领【${name || clueName || customName}】${queryParameters.value.name}吗?`,
+    message: `确定认领【${name || clueName || customName || productName}】${queryParameters.value.name}吗?`,
   }).then(() => {
-    requests.post(queryParameters?.value.transferInterface, { ids: id, inchargerId: userId }).then((res) => {
+    requests.post(queryParameters?.value.transferInterface, { ...formVal }).then((res) => {
       toastSuccess('认领成功')
       onRefresh(true)
     })

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contacts/contactsInfo.vue

@@ -135,6 +135,7 @@ function selectChange(value, label) {
 }
 
 function showDialogCli() {
+  dialogSelection.value = {}
   showDialog.value = true
 }
 

+ 163 - 18
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contract/detail.vue

@@ -1,50 +1,81 @@
 <template>
   <div class="flex flex-col h-full">
     <div class="bg-white info flex-1 overflow-y-auto cellnormall">
-      <van-cell title="合同编号" :value="info.number" />
-      <van-cell title="合同名称" :value="info.name" />
-      <van-cell title="合同金额" :value="info.amounts">
+      <van-cell title="合同编号" :value="infoData.number" />
+      <van-cell title="合同名称" :value="infoData.name" />
+      <van-cell title="合同金额" :value="infoData.amounts">
         <template #default>
-          <span class="text-[#FF8B32]" v-if="info.amounts">¥ {{ info.amounts }}</span>
+          <span class="text-[#FF8B32]" v-if="infoData.amounts">¥ {{ infoData.amounts }}</span>
         </template>
       </van-cell>
-      <van-cell title="已回款金额" :value="info.payment">
+      <van-cell title="已回款金额" :value="infoData.payment">
         <template #default>
-          <span class="text-[#FF8B32]" v-if="info.payment">¥ {{ info.payment }}</span>
+          <span class="text-[#FF8B32]" v-if="infoData.payment">¥ {{ infoData.payment }}</span>
         </template>
       </van-cell>
-      <van-cell title="已回款进度" :value="info.payment">
+      <van-cell title="已回款进度" :value="infoData.payment">
         <template #default>
-          {{ info.payment ? (100 * info.payment / info.amounts).toFixed(1) + '%' : '0%' }}
+          {{ infoData.payment ? (100 * infoData.payment / infoData.amounts).toFixed(1) + '%' : '0%' }}
         </template>
       </van-cell>
-      <van-cell title="下笔回款日期" :value="info.nextPaymentDate">
+      <van-cell title="下笔回款日期" :value="infoData.nextPaymentDate">
         <template #default>
-          {{ info.nextPaymentDate ? info.nextPaymentDate : '-' }}
+          {{ infoData.nextPaymentDate ? infoData.nextPaymentDate : '-' }}
         </template>
       </van-cell>
-      <van-cell title="下笔回款金额" :value="info.payment">
+      <van-cell title="下笔回款金额" :value="infoData.payment">
         <template #default>
-          <span class="text-[#FF8B32]" v-if="info.payment">¥ {{ info.payment.toFixed(2) }}</span>
+          <span class="text-[#FF8B32]" v-if="infoData.payment">¥ {{ infoData.payment.toFixed(2) }}</span>
         </template>
       </van-cell>
-      <van-cell title="合同类型" :value="info.typeName" />
-      <van-cell title="状态" :value="info.status">
+      <van-cell title="合同类型" :value="infoData.typeName" />
+      <van-cell title="状态" :value="infoData.status">
         <template #default>
-          <span :style="fixedFieldStatusArray[info.status].color">
-            {{ fixedFieldStatusArray[info.status].label }}
+          <span :style="fixedFieldStatusArray[infoData.status].color">
+            {{ fixedFieldStatusArray[infoData.status].label }}
           </span>
         </template>
       </van-cell>
     </div>
+    <div class="bottomButton">
+      <template v-if="infoData.status == 1">
+        <van-button type="success" class="w-full block" @click="adoptOperation">通过合同</van-button>
+        <van-button type="danger" class="w-full block" @click="rejectOperation">驳回合同</van-button>
+      </template>
+      <van-button type="default" class="w-full block" v-permission="[routingInformation.jurisdiction.edit]"
+        @click="jumpEdit()">编辑合同</van-button>
+      <van-button type="danger" class="w-full block" v-permission="[routingInformation.jurisdiction.delete]"
+        @click="deleteRow()">删除合同</van-button>
+    </div>
+
+    <!-- 驳回弹窗 -->
+    <van-dialog v-model:show="showDialog" :title="`转移线索`" show-cancel-button @confirm="confirmTransfer"
+      :before-close="dialogCloseBefo">
+      <template #default>
+        <van-field v-model.trim="dialogSelection" type="textarea" rows="3" label="驳回原因" placeholder="请输入驳回原因" />
+      </template>
+    </van-dialog>
   </div>
 </template>
 
 <script setup>
-import { ref } from 'vue';
+import { ref, watch } from 'vue';
+import requests from "@common/requests";
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { fixedFieldStatusArray } from '@/utility/defaultData.js';
+import { CONTRACT_APPROVED } from '@hooks/useApi'
+import useShowToast from '@hooks/useToast'
+import useInfoStore from '@store/useInfoStore'
+import useRouterStore from "@store/useRouterStore.js";
+import { routingInfos } from "@utility/generalVariables"
+import { resetListData, getListFieldKey } from '@components/common/formForm/formCorrespondenceProcessing'
+import useFixedData from "@store/useFixedData.js"
 
+const fixedData = useFixedData()
+const router = useRouterStore()
+const userInfo = useInfoStore()
+const { toastSuccess, toastFail, toastText } = useShowToast()
 const props = defineProps({
   info: {
     type: Object,
@@ -53,9 +84,123 @@ const props = defineProps({
   }
 })
 
+const routingInformation = routingInfos['contract']
+const showDialog = ref(false);
+const showSelect = ref(false);
+const dialogSelection = ref({});
+
+watch(() => props.info, (newValue) => {
+  processingData(newValue.id)
+})
+
+const infoData = ref(props.info);
+const timeout = ref(null);
+
+function adoptOperation() {
+  const { name = '', id } = infoData.value
+  showConfirmDialog({
+    title: `合同通过`,
+    message: `确认审核通过吗?,通过后合同基本信息无法修改`,
+  }).then(() => {
+    requests.post(CONTRACT_APPROVED, { id, status: 0 }).then((res) => {
+      toastSuccess('操作成功')
+      processingData(id)
+    }).catch((err) => {
+      toastFail(err.msg ? err.msg : '操作失败')
+    })
+  })
+}
+
+function rejectOperation() {
+  dialogSelection.value = ''
+  showDialog.value = true
+}
+
+function confirmTransfer() {
+  const { name = '', id } = infoData.value
+  if (!dialogSelection.value) {
+    return toastText('请输入驳回原因')
+  }
+
+  showConfirmDialog({
+    title: `合同驳回`,
+    message: `确认驳回吗?,驳回后合同基本信息无法修改`,
+  }).then(() => {
+    requests.post(CONTRACT_APPROVED, { id, status: 0, msg: dialogSelection.value }).then((res) => {
+      toastSuccess('操作成功')
+      showDialog.value = false
+      processingData(id)
+    })
+  })
+}
+
+function dialogCloseBefo(val) {
+  if (val == 'confirm' && showDialog.value) {
+    return false
+  }
+
+  return true
+}
+
+function deleteRow() {
+  const { name = '', searchFiled = {}, deteleFiled = '' } = routingInformation
+  const row = props.info
+  const foemVal = { [routingInformation.key == 'tasks' ? 'taskIds' : 'ids']: row.id }
+  showConfirmDialog({
+    title: `删除${name}`,
+    message: `确定删除【${row[searchFiled?.search]}】${name}吗?`,
+  }).then(() => {
+    requests.post(deteleFiled, { ...foemVal }).then((res) => {
+      toastSuccess('删除成功')
+      router.navigateBack({
+        success: () => {
+          router.emit('moduleListDetailParameter', {
+            row: JSON.stringify(routingInformation)
+          })
+        }
+      })
+    }).catch((err) => {
+      toastFail(err.msg ? err.msg : '删除失败')
+    })
+  })
+}
+
+function jumpEdit() {
+  const formJson = fixedData.formJson[routingInformation.key] || []
+  const formList = resetListData(formJson?.list)
+  const filedObj = getListFieldKey(formList, props.info)
+  const formVal = { ...filedObj, id: props.info.id }
+
+  router.navigateTo({
+    pathName: 'addEditor',
+    success: () => {
+      router.emit('addEditorParameter', {
+        routerInfo: JSON.stringify(routingInformation),
+        filedValue: JSON.stringify(formVal)
+      })
+    }
+  })
+}
+
+function getDetails(id) {
+  // 获取合同详情
+}
+function processingData(id) {
+  clearTimeout(timeout.value);
+  timeout.value = setTimeout(() => {
+    getDetails(id)
+  }, 100);
+}
+
 useLifecycle({
+  init: () => {
+    processingData(props.info.id)
+  },
   load: () => {
-    // 添加加载逻辑
+    processingData(props.info.id)
+  },
+  unload: () => {
+    clearTimeout(timeout.value)
   }
 });
 </script>

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/customerInfo.vue

@@ -156,6 +156,7 @@ function selectChange(value, label) {
 }
 
 function showDialogCli() {
+  dialogSelection.value = {}
   showDialog.value = true
 }
 

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/addEditor.vue

@@ -38,7 +38,7 @@
 <script setup>
 import { ref, onActivated } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
-import { SELL_AND_OBTAIN_RELATED_PRODUCTS, ORDER_ADDITION_EDITING } from "@hooks/useApi"
+import { OBTAIN_ORDER_RELATED_PRODUCTS, ORDER_ADDITION_EDITING } from "@hooks/useApi"
 import { defaultRelatedProductDataFields } from "@utility/defaultData"
 import dayjs from 'dayjs';
 import requests from "@common/requests";
@@ -123,7 +123,7 @@ function getBusinessOpportunityDetails(row) {
     businessItemProductList.value = [{ ...defaultRelatedProductDataFields }]
     return
   }
-  requests.post(SELL_AND_OBTAIN_RELATED_PRODUCTS, { id }).then(({ data }) => {
+  requests.post(OBTAIN_ORDER_RELATED_PRODUCTS, { id }).then(({ data }) => {
     if ((data || []).length === 0) {
       businessItemProductList.value = [{ ...defaultRelatedProductDataFields }]
       return

+ 18 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/detail.vue

@@ -2,7 +2,7 @@
   <div class="w-full h-full">
     <van-tabs v-model:active="tabActive">
       <van-tab title="销售订单信息" name="销售订单信息">
-        <OrderInfo :info="info" />
+        <OrderInfo :info="infoData" />
       </van-tab>
       <van-tab title="相关任务" name="相关任务">
         <RelatedTasks :infoList="relatedTasksList"  />
@@ -17,7 +17,7 @@
 <script setup>
 import { ref, onActivated, watch } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
-import { GET_ORDER_RELATED_TASKS, OBTAIN_ORDER_RELATED_PRODUCTS } from "@hooks/useApi"
+import { GET_ORDER_RELATED_TASKS, OBTAIN_ORDER_RELATED_PRODUCTS, SALES_ORDER_DETAILS } from "@hooks/useApi"
 import requests from "@common/requests";
 import OrderInfo from './orderInfo.vue';
 import RelatedTasks from '../tasks/relatedTasks.vue';
@@ -33,6 +33,8 @@ const props = defineProps({
 const tabActive = ref('销售订单信息');
 const relatedTasksList = ref([]);
 const relatedProductsList = ref([]);
+const infoData = ref(props.info);
+const timeout = ref(null);
 
 watch(() => props.info, (newValue) => {
   tabActive.value = '销售订单信息';
@@ -40,6 +42,9 @@ watch(() => props.info, (newValue) => {
 })
 
 function getDetailedData(id) {
+  requests.post(SALES_ORDER_DETAILS, { id }).then(({ data }) => {
+    infoData.value = data || []
+  })
   requests.post(GET_ORDER_RELATED_TASKS, { id }).then(({ data }) => {
     relatedTasksList.value = data || []
   })
@@ -60,13 +65,23 @@ function getDetailedData(id) {
 }
 
 function processingData(id) {
-  getDetailedData(id)
+  clearTimeout(timeout.value);
+  timeout.value = setTimeout(() => {
+    getDetailedData(id)
+  }, 100);
 }
 
 useLifecycle({
   init: () => {
     tabActive.value = '销售订单信息';
     processingData(props.info.id)
+  },
+  load: () => {
+    tabActive.value = '销售订单信息';
+    processingData(props.info.id)
+  },
+  unload: () => {
+    clearTimeout(timeout.value)
   }
 });
 </script>

+ 122 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/orderInfo.vue

@@ -46,14 +46,49 @@
       </van-cell>
       <van-cell title="备注" :value="info.remark" />
     </div>
+    <div class="bottomButton">
+      <van-button type="warning" class="w-full block" v-if="info.inchargerName"  @click="showDialogCli()">转移销售订单</van-button>
+      <van-button type="default" class="w-full block" v-permission="[routingInformation.jurisdiction.edit]" @click="jumpEdit()">编辑销售订单</van-button>
+      <van-button type="danger" class="w-full block" v-permission="[routingInformation.jurisdiction.delete]" @click="deleteRow()">删除销售订单</van-button>
+    </div>
+
+    <!-- 转移弹窗 -->
+    <van-dialog v-model:show="showDialog" :title="`转移线索`" show-cancel-button
+      @confirm="confirmTransfer" :before-close="dialogCloseBefo">
+      <van-cell title="转移至" is-link @click="showSelect = true">
+        <template #value>
+          {{ dialogSelection.label }}
+        </template>
+      </van-cell>
+      <div class="themeTextColor text-size-small pl-4 pt-2 pb-2">转移后,将看不到此线索了</div>
+    </van-dialog>
+
+    <!-- select 选择器 -->
+    <van-popup v-model:show="showSelect" destroy-on-close position="bottom" :style="{ height: '80%' }">
+      <PullDownSelector @change="selectChange" />
+    </van-popup>
   </div>
 </template>
 
 <script setup>
 import { ref } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { fixedFieldPaymentStatus } from "@utility/defaultData" 
+import { TRANSFER_CLUES } from '@hooks/useApi'
+import requests from "@common/requests";
+import useShowToast from '@hooks/useToast'
+import useInfoStore from '@store/useInfoStore'
+import useRouterStore from "@store/useRouterStore.js";
+import { routingInfos } from "@utility/generalVariables"
+import { resetListData, getListFieldKey } from '@components/common/formForm/formCorrespondenceProcessing'
+import useFixedData from "@store/useFixedData.js"
+
 
+const fixedData = useFixedData()
+const router = useRouterStore()
+const userInfo = useInfoStore()
+const { toastSuccess, toastFail, toastText } = useShowToast()
 const props = defineProps({
   info: {
     type: Object,
@@ -62,6 +97,93 @@ const props = defineProps({
   }
 })
 
+const routingInformation = routingInfos['order']
+const showDialog = ref(false);
+const showSelect = ref(false);
+const dialogSelection = ref({});
+
+function deleteRow() {
+  const { name = '', searchFiled = {}, deteleFiled = '' } = routingInformation
+  const row = props.info
+  const foemVal = { [routingInformation.key == 'tasks' ? 'taskIds' : 'ids']: row.id }
+  showConfirmDialog({
+    title: `删除${name}`,
+    message: `确定删除【${row[searchFiled?.search]}】${name}吗?`,
+  }).then(() => {
+    requests.post(deteleFiled, { ...foemVal }).then((res) => {
+      toastSuccess('删除成功')
+      router.navigateBack({
+        success: () => {
+          router.emit('moduleListDetailParameter', {
+            row: JSON.stringify(routingInformation)
+          })
+        }
+      })
+    }).catch((err) => {
+      toastFail(err.msg ? err.msg : '删除失败')
+    })
+  })
+}
+
+function jumpEdit() {
+  const formJson = fixedData.formJson[routingInformation.key] || []
+  const formList = resetListData(formJson?.list)
+  const filedObj = getListFieldKey(formList, props.info)
+  const formVal = { ...filedObj, id: props.info.id }
+
+  router.navigateTo({
+    pathName: 'addEditor',
+    success: () => {
+      router.emit('addEditorParameter', {
+        routerInfo: JSON.stringify(routingInformation),
+        filedValue: JSON.stringify(formVal)
+      })
+    }
+  })
+}
+
+function listReloadData() {
+  router.navigateBack({
+    success: () => {
+      router.eventEmit('moduleListRefreshData', {})
+    }
+  })
+}
+function confirmTransfer() {
+  if(!dialogSelection.value.label) {
+    return toastText('请选择要转移的人员')
+  }
+
+  requests.post(TRANSFER_CLUES, { ids: props.info.id, inchargerId: dialogSelection.value.value }).then((res) => {
+    toastSuccess('转移成功')
+    showDialog.value = false
+    setTimeout(() => {
+      listReloadData()
+    }, 2000)
+  })
+}
+
+function selectChange(value, label) {
+  dialogSelection.value = {
+    value, label
+  }
+  showSelect.value = false
+}
+
+function showDialogCli() {
+  dialogSelection.value = {}
+  showDialog.value = true
+}
+
+function dialogCloseBefo(val) {
+  if(val == 'confirm' && showDialog.value) {
+    return false
+  }
+
+  return true
+}
+
+
 useLifecycle({
   load: () => {
     // 添加加载逻辑

+ 18 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/detail.vue

@@ -2,7 +2,7 @@
   <div class="w-full h-full">
     <van-tabs v-model:active="tabActive">
       <van-tab title="产品信息" name="产品信息">
-        <ProductInfo :info="info" />
+        <ProductInfo :info="infoData" />
       </van-tab>
       <van-tab title="相关商机" name="相关商机">
         <RelatedBusinessOpportunities :infoList="relatedBusinessOpportunitiesList"  />
@@ -17,7 +17,7 @@
 <script setup>
 import { ref, onActivated, watch } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
-import { OBTAIN_PRODUCT_RELATED_BUSINESS_OPPORTUNITIES, OBTAIN_SALES_ORDERS_RELATED_TO_THE_PRODUCT } from "@hooks/useApi"
+import { OBTAIN_PRODUCT_RELATED_BUSINESS_OPPORTUNITIES, OBTAIN_SALES_ORDERS_RELATED_TO_THE_PRODUCT, GET_PRODUCT_DETAILS } from "@hooks/useApi"
 import requests from "@common/requests";
 import ProductInfo from './productInfo.vue';
 import RelatedSalesOrders from '../order/relatedSalesOrders.vue';
@@ -33,6 +33,8 @@ const props = defineProps({
 const tabActive = ref('产品信息');
 const relatedBusinessOpportunitiesList = ref([]);
 const relatedSalesOrdersList = ref([]);
+const infoData = ref(props.info);
+const timeout = ref(null);
 
 watch(() => props.info, (newValue) => {
   tabActive.value = '产品信息';
@@ -40,6 +42,9 @@ watch(() => props.info, (newValue) => {
 })
 
 function getDetailedData(id) {
+  requests.post(GET_PRODUCT_DETAILS, { id }).then(({ data }) => {
+    infoData.value = data || {}
+  })
   requests.post(OBTAIN_PRODUCT_RELATED_BUSINESS_OPPORTUNITIES, { id }).then(({ data }) => {
     relatedBusinessOpportunitiesList.value = data || []
   })
@@ -49,13 +54,23 @@ function getDetailedData(id) {
 }
 
 function processingData(id) {
-  getDetailedData(id)
+  clearTimeout(timeout.value);
+  timeout.value = setTimeout(() => {
+    getDetailedData(id)
+  }, 100);
 }
 
 useLifecycle({
   init: () => {
     tabActive.value = '产品信息';
     processingData(props.info.id)
+  },
+  load: () => {
+    tabActive.value = '产品信息';
+    processingData(props.info.id)
+  },
+  unload: () => {
+    clearTimeout(timeout.value)
   }
 });
 </script>

+ 2 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/newAndModifiedRelatedProducts.vue

@@ -69,6 +69,8 @@
       name="quantity"
       label="数量"
       placeholder="请输入"
+      :max="form.inventory ? +form.inventory : 0"
+      :min="0"
       @input="inputNumberChange('quantity')"
     ></van-field>
     <van-field

+ 139 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/productInfo.vue

@@ -19,13 +19,52 @@
       </van-cell>
       <van-cell title="备注" :value="info.descs" />
     </div>
+    <div class="bottomButton">
+      <van-button type="warning" class="w-full block" v-if="info.inchargerName"
+        @click="showDialogCli()">转移产品</van-button>
+      <van-button type="primary" class="w-full block" v-if="!info.inchargerName"
+        @click="claimAndClaim()">认领产品</van-button>
+      <van-button type="default" class="w-full block" v-permission="[routingInformation.jurisdiction.edit]"
+        @click="jumpEdit()">编辑产品</van-button>
+      <van-button type="danger" class="w-full block" v-permission="[routingInformation.jurisdiction.delete]"
+        @click="deleteRow()">删除产品</van-button>
+    </div>
+
+    <!-- 转移弹窗 -->
+    <van-dialog v-model:show="showDialog" :title="`转移产品`" show-cancel-button @confirm="confirmTransfer"
+      :before-close="dialogCloseBefo">
+      <van-cell title="转移至" is-link @click="showSelect = true">
+        <template #value>
+          {{ dialogSelection.label }}
+        </template>
+      </van-cell>
+      <div class="themeTextColor text-size-small pl-4 pt-2 pb-2">转移后,将看不到此产品了</div>
+    </van-dialog>
+
+    <!-- select 选择器 -->
+    <van-popup v-model:show="showSelect" destroy-on-close position="bottom" :style="{ height: '80%' }">
+      <PullDownSelector @change="selectChange" />
+    </van-popup>
   </div>
 </template>
 
 <script setup>
 import { ref } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
+import { TRANSFER_PRODUCTS } from '@hooks/useApi'
+import requests from "@common/requests";
+import useShowToast from '@hooks/useToast'
+import useInfoStore from '@store/useInfoStore'
+import useRouterStore from "@store/useRouterStore.js";
+import { routingInfos } from "@utility/generalVariables"
+import { resetListData, getListFieldKey } from '@components/common/formForm/formCorrespondenceProcessing'
+import useFixedData from "@store/useFixedData.js"
 
+const fixedData = useFixedData()
+const router = useRouterStore()
+const userInfo = useInfoStore()
+const { toastSuccess, toastFail, toastText } = useShowToast()
 const props = defineProps({
   info: {
     type: Object,
@@ -34,6 +73,106 @@ const props = defineProps({
   }
 })
 
+const routingInformation = routingInfos['product']
+const showDialog = ref(false);
+const showSelect = ref(false);
+const dialogSelection = ref({});
+
+function deleteRow() {
+  const { name = '', searchFiled = {}, deteleFiled = '' } = routingInformation
+  const row = props.info
+  const foemVal = { [routingInformation.key == 'tasks' ? 'taskIds' : 'ids']: row.id }
+  showConfirmDialog({
+    title: `删除${name}`,
+    message: `确定删除【${row[searchFiled?.search]}】${name}吗?`,
+  }).then(() => {
+    requests.post(deteleFiled, { ...foemVal }).then((res) => {
+      toastSuccess('删除成功')
+      router.navigateBack({
+        success: () => {
+          router.emit('moduleListDetailParameter', {
+            row: JSON.stringify(routingInformation)
+          })
+        }
+      })
+    }).catch((err) => {
+      toastFail(err.msg ? err.msg : '删除失败')
+    })
+  })
+}
+
+function jumpEdit() {
+  const formJson = fixedData.formJson[routingInformation.key] || []
+  const formList = resetListData(formJson?.list)
+  const filedObj = getListFieldKey(formList, props.info)
+  const formVal = { ...filedObj, id: props.info.id }
+
+  router.navigateTo({
+    pathName: 'addEditor',
+    success: () => {
+      router.emit('addEditorParameter', {
+        routerInfo: JSON.stringify(routingInformation),
+        filedValue: JSON.stringify(formVal)
+      })
+    }
+  })
+}
+
+function listReloadData() {
+  router.navigateBack({
+    success: () => {
+      router.eventEmit('moduleListRefreshData', {})
+    }
+  })
+}
+function confirmTransfer() {
+  if (!dialogSelection.value.label) {
+    return toastText('请选择要转移的人员')
+  }
+
+  requests.post(TRANSFER_PRODUCTS, { id: props.info.id, userId: dialogSelection.value.value }).then((res) => {
+    toastSuccess('转移成功')
+    showDialog.value = false
+    setTimeout(() => {
+      listReloadData()
+    }, 2000)
+  })
+}
+
+function claimAndClaim() {
+  showConfirmDialog({
+    title: '认领线索',
+    message: `确定认领【${props.info.clueName}】线索吗?`,
+  }).then(() => {
+    requests.post(TRANSFER_PRODUCTS, { id: props.info.id, userId: userInfo.userInfo.id }).then((res) => {
+      toastSuccess('认领成功')
+      listReloadData()
+      props.info.inchargerName = userInfo.userInfo.clueName
+      showDialog.value = false
+    })
+  })
+}
+
+function selectChange(value, label) {
+  dialogSelection.value = {
+    value, label
+  }
+  showSelect.value = false
+}
+
+function showDialogCli() {
+  dialogSelection.value = {}
+  showDialog.value = true
+}
+
+function dialogCloseBefo(val) {
+  if (val == 'confirm' && showDialog.value) {
+    return false
+  }
+
+  return true
+}
+
 useLifecycle({
   load: () => {
     // 添加加载逻辑

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/threadInfo.vue

@@ -153,6 +153,7 @@ function selectChange(value, label) {
 }
 
 function showDialogCli() {
+  dialogSelection.value = {}
   showDialog.value = true
 }
 

+ 7 - 7
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/salesBriefings.vue

@@ -43,7 +43,7 @@
             <div class="flex items-end">
               <span class="text-[#F3893C] text-size-in font-bold mr-1">
                 {{ salesBriefings?.businessOpportunity?.businessOpportunityCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
@@ -54,7 +54,7 @@
             <div class="flex items-end">
               <span class="text-[#A66AFF] text-size-in font-bold mr-1">
                 {{ salesBriefings?.salesOrder?.salesOrderCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
@@ -67,8 +67,8 @@
             <div>销售订单金额</div>
             <div class="flex items-end">
               <span class="text-[#67DF2A] text-size-in font-bold mr-1">
-                {{ salesBriefings?.salesOrdersPrice?.salesOrdersPriceCount || 0 }}
-              </span>
+                {{ salesBriefings?.salesOrdersPrice?.salesOrdersPrice || 0 }}
+              </span>
             </div>
           </div>
         </div>
@@ -78,8 +78,8 @@
             <div>商机金额</div>
             <div class="flex items-end">
               <span class="text-[#EED116] text-size-in font-bold mr-1">
-                {{ salesBriefings?.businessOpportunityPrice?.businessOpportunityPriceCount || 0 }}
-              </span>
+                {{ salesBriefings?.businessOpportunityPrice?.businessOpportunityCount || 0 }}
+              </span>
             </div>
           </div>
         </div>
@@ -93,7 +93,7 @@
             <div class="flex items-end">
               <span class="text-[#F44873] text-size-in font-bold mr-1">
                 {{ salesBriefings?.clue?.clueCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>

+ 4 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/workbench.vue

@@ -189,6 +189,9 @@ const displayFrequentlyUsedContacts = ref(false)
 function calendarPanelChangeSet(data) {
   dateConditions.value = dayjs(data.date).format('YYYY-MM-DD')
   getVisitorPlan()
+  setTimeout(() => {
+    getPlanCalendarList()
+  }, 1)
 }
 
 function jumpToAdd(rows) {
@@ -350,10 +353,10 @@ function getAllData() {
   displayFrequentlyUsedContacts.value = useInfo.modularList.filter(item => item.path === '/contacts').length
   areYouRequesting.value = true
   Promise.all([
+    getPlanCalendarList(),
     getVisitorPlan(),
     getCommonlyUsedModules(),
     getFrequentlyUsedContacts(),
-    getPlanCalendarList()
   ]).finally(() => {
     areYouRequesting.value = false
   })

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/news/index.vue

@@ -32,7 +32,7 @@
 <script setup>
 import { ref } from "vue";
 import { useLifecycle } from "@hooks/useCommon.js";
-import { GET_MESSAGE_LIST, READ_MESSAGE } from "@hooks/useApi";
+import { GET_MESSAGE_LIST, READ_MESSAGE, ONE_CLICK_READ } from "@hooks/useApi";
 import useShowToast from "@hooks/useToast";
 import useRouterStore from "@store/useRouterStore.js";
 import useInfoStore from "@store/useInfoStore.js";

+ 7 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/addEditorVisitor.vue

@@ -180,6 +180,7 @@
         :style="{ height: '80%' }"
       >
         <PullDownSelector
+          :showElement="visitShowPicker"
           :options="purposeOfVisitList"
           :doYouNeedTranslation="false"
           @change="visitSelectChange"
@@ -193,6 +194,7 @@
         :style="{ height: '80%' }"
       >
         <PullDownSelector
+          :showElement="remindShowPicker"
           :options="reminderTimeList"
           :doYouNeedTranslation="false"
           @change="remindSelectChange"
@@ -245,7 +247,11 @@ function onSubmit() {
     requests.post(PLAN_TO_ADD_EDITORS, { ...data }).then((res) => {
       toastSuccess("保存成功")
       setTimeout(() => {
-        history.back();
+        router.navigateBack({
+          success: () => {
+            router.emit('visitorDetailsParameter', { row: JSON.stringify({...addOrEditRow.value}) })
+          }
+        })
       }, 2000)
     }).catch(err => {
       toastFail(`保存失败:${err.msg}`)

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/visitorDetails.vue

@@ -242,6 +242,7 @@ function processingDataSource(data) {
 
 useLifecycle({
   load: () => {
+    console.log('开始执行')
     router.on("visitorDetailsParameter", (data) => {
       processingDataSource(data);
     });

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 3 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/utility/generalVariables.js


+ 7 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ContractController.java

@@ -78,6 +78,13 @@ public class ContractController {
         return contractService.exportContractOneToMany(request,number,name,typeName,status,startDate,endDate, paymentStartDate, paymentEndDate, secTypeId,customerOrg,finishStatus);
     }
 
+
+    @RequestMapping("/getContractDetail")
+    public HttpRespMsg getContractDetail (HttpServletRequest request, Integer id){
+        return contractService.getContractDetail(request,id);
+    }
+
+
     /**
      * 导入合同
      */

+ 5 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/TaskController.java

@@ -124,6 +124,11 @@ public class TaskController {
         return taskService.updateTaskStatus(taskDto,request);
     }
 
+    @RequestMapping("getTaskDetail")
+    public HttpRespMsg getTaskDetail(Integer id){
+        return taskService.getTaskDetail(id,request);
+    }
+
     /**
      * 定时修改过期的任务状态
      */

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

@@ -44,4 +44,6 @@ public interface ContractService extends IService<Contract> {
     HttpRespMsg pinContract(Contract contract, HttpServletRequest request);
 
     HttpRespMsg undoPin(Contract contract, HttpServletRequest request);
+
+    HttpRespMsg getContractDetail(HttpServletRequest request, Integer id);
 }

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

@@ -40,4 +40,6 @@ public interface TaskService extends IService<Task> {
     HttpRespMsg pinTasks(Task task, HttpServletRequest request);
 
     HttpRespMsg undoPin(Task task, HttpServletRequest request);
+
+    HttpRespMsg getTaskDetail(Integer id, HttpServletRequest request);
 }

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

@@ -1672,4 +1672,21 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
         );
         return respMsg;
     }
+
+    @Override
+    public HttpRespMsg getContractDetail(HttpServletRequest request, Integer id) {
+        HttpRespMsg respMsg = new HttpRespMsg();
+        Contract contract = contractMapper.selectById(id);
+        List<ContractCustom> selectedList = contractCustomMapper.selectList(new QueryWrapper<ContractCustom>().eq("contract_id", contract.getId()));
+        if (selectedList != null && !selectedList.isEmpty()) {
+            contract.setCustomData(selectedList.get(0));
+        }
+        List<ContractPayCustomized> payCustomizedList = contractPayCustomizedMapper.selectList(new QueryWrapper<ContractPayCustomized>().eq("contract_id", contract.getId()));
+        if (payCustomizedList != null && !payCustomizedList.isEmpty()) {
+            contract.setPayCustomizedData(payCustomizedList.get(0));
+        }
+        respMsg.setData(contract);
+        return respMsg;
+
+    }
 }

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

@@ -14,6 +14,7 @@ import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
+import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.xssf.usermodel.XSSFCell;
@@ -1290,6 +1291,57 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
         return respMsg;
     }
 
+    @Override
+    public HttpRespMsg getTaskDetail(Integer id, HttpServletRequest request) {
+        HttpRespMsg respMsg = new HttpRespMsg();
+        TasKVo tasKVo = new TasKVo();
+        Task task = taskMapper.selectById(id);
+        if (task!=null){
+            BeanUtils.copyProperties(task,tasKVo);
+            if (task.getContactsId()!=null){
+                Contacts contacts = contactsMapper.selectById(task.getContactsId());
+                if (contacts!=null){
+                    tasKVo.setContactsName(contacts.getName());
+                }
+            }
+            if (task.getClueId()!=null){
+                Clue clue = clueMapper.selectById(task.getClueId());
+                if (clue!=null){
+                    tasKVo.setClueName(clue.getClueName());
+                }
+            }
+            if (task.getCustomId()!=null){
+                Custom custom = customMapper.selectById(task.getCustomId());
+                if (custom!=null){
+                    tasKVo.setCustomName(custom.getCustomName());
+                }
+            }
+            if (task.getBusinessOpportunityId()!=null){
+                BusinessOpportunity businessOpportunity = businessOpportunityMapper.selectById(task.getBusinessOpportunityId());
+                if (businessOpportunity!=null){
+                    tasKVo.setBusinessName(businessOpportunity.getName());
+                }
+            }
+            if (task.getOrderId()!=null){
+                SalesOrder salesOrder = salesOrderMapper.selectById(task.getOrderId());
+                if (salesOrder!=null){
+                    tasKVo.setOrderName(salesOrder.getOrderName());
+                }
+            }
+            List<TaskExecutor> executorList = taskExecutorService.list(new QueryWrapper<TaskExecutor>().eq("task_id", id));
+            if (!executorList.isEmpty()){
+                List<String> collect = executorList.stream().map(TaskExecutor::getExecutorName).collect(Collectors.toList());
+                tasKVo.setTaskExecutors(collect);
+            }
+            List<TaskLog> taskLogList = taskLogService.list(new QueryWrapper<TaskLog>().eq("task_id", id));
+            if (!taskLogList.isEmpty()){
+                tasKVo.setTaskLogs(taskLogList);
+            }
+        }
+        respMsg.setData(tasKVo);
+        return respMsg;
+    }
+
     public void updateTaskRepeatConfigure(Task task){
         task.setRepeatType(null).setRepeatEndNever(null).setRepeatEndCount(null)
                 .setRepeatEndDate(null).setRepeatDesignDay(null).setRepeatDesignSameday(null)

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

@@ -3028,8 +3028,8 @@ public class ReportController {
     }
 
     @RequestMapping("/getReportTimeLessThanCardTimeList")
-    public HttpRespMsg getReportTimeLessThanCardTimeList(String date) {
-        return reportService.getReportTimeLessThanCardTimeList(date);
+    public HttpRespMsg getReportTimeLessThanCardTimeList(String date, Integer deptId, String userId) {
+        return reportService.getReportTimeLessThanCardTimeList(date, deptId, userId);
     }
 
 

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

@@ -172,5 +172,5 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg getCurAuditNode(String date, String userId);
 
-    HttpRespMsg getReportTimeLessThanCardTimeList(String date);
+    HttpRespMsg getReportTimeLessThanCardTimeList(String date, Integer deptId, String userId);
 }

+ 47 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -10380,12 +10380,12 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg getReportTimeLessThanCardTimeList(String date) {
+    public HttpRespMsg getReportTimeLessThanCardTimeList(String date, Integer deptId, String userId) {
         //获取自己的考勤未填满的记录
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
         //获取考勤表记录
-        List<UserCorpwxTime> userCorpwxTimeList = null;
+        List<UserCorpwxTime> userCorpwxTimeList = new ArrayList<>();
         //date格式为2024-09, 需要获取该月的第一天和最后一天
         LocalDate firstDay = LocalDate.parse(date + "-01");
         LocalDate lastDay = firstDay.with(TemporalAdjusters.lastDayOfMonth());
@@ -10393,15 +10393,45 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         boolean canViewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全公司工时");
         List<User> manageUserList = new ArrayList<>();
         if (canViewAll) {
-            userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("company_id", companyId).between("create_date", firstDay, lastDay));
-            manageUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+            if (!StringUtils.isEmpty(userId)) {
+                User findUser = userMapper.selectById(userId);
+                if (findUser != null) {
+                    userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("company_id", companyId).eq("corpwx_userid", findUser.getCorpwxUserid()).between("create_date", firstDay, lastDay));
+                    manageUserList.add(findUser);
+                }
+            } else  if (deptId != null) {
+                //按部门过滤
+                List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+                List<Integer> allSubDeptIds = departmentService.getDeptIncludeSubDeptIds(deptId, allDeptList);
+                manageUserList = userMapper.selectList(new QueryWrapper<User>().in("department_id", allSubDeptIds));
+                if (manageUserList.size() > 0) {
+                    List<String> collect = manageUserList.stream().map(User::getCorpwxUserid).collect(Collectors.toList());
+                    userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("company_id", companyId).in("corpwx_userid", collect).between("create_date", firstDay, lastDay));
+                }
+            } else {
+                userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("company_id", companyId).between("create_date", firstDay, lastDay));
+                manageUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+            }
         } else {
             //是否是部门负责人
             List<Integer> allDeptIds = getAllVisibleDeptIdList(user, departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId)));
             if (allDeptIds.size() > 0) {
-                //有部门工时的查看权限
-                //取部门的人员
-                manageUserList = userMapper.selectList(new QueryWrapper<User>().in("department_id", allDeptIds));
+                if (!StringUtils.isEmpty(userId)) {
+                    User findUser = userMapper.selectById(userId);
+                    if (findUser != null) {
+                        manageUserList.add(findUser);
+                    }
+                } else if (deptId != null) {
+                    //按部门过滤
+                    if (allDeptIds.contains(deptId)) {
+                        List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+                        List<Integer> allSubDeptIds = departmentService.getDeptIncludeSubDeptIds(deptId, allDeptList);
+                        manageUserList = userMapper.selectList(new QueryWrapper<User>().in("department_id", allSubDeptIds));
+                    }
+                } else {
+                    //取部门的人员
+                    manageUserList = userMapper.selectList(new QueryWrapper<User>().in("department_id", allDeptIds));
+                }
                 //如果自己不在manageUserList中,加进去
                 if (!manageUserList.stream().anyMatch(u -> u.getId().equals(user.getId()))) {
                     manageUserList.add(user);
@@ -10429,13 +10459,19 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 
         //获取填报工时记录表
         List<Report> reportList = new ArrayList<>();
-        if (canViewAll) {
+        if (canViewAll && StringUtils.isEmpty(userId) && deptId == null) {
+            //查看全公司的
             reportList = reportMapper.selectList(new QueryWrapper<Report>().select("creator_id,create_date, sum(working_time) as working_time").eq("company_id", companyId).between("create_date", firstDay, lastDay).groupBy("creator_id,create_date"));
         } else if (manageUserList.size() > 0) {
             List<String> userIdList = manageUserList.stream().map(User::getId).collect(Collectors.toList());
-            reportList = reportMapper.selectList(new QueryWrapper<Report>().select("creator_id,create_date, sum(working_time) as working_time").in("creator_id", userIdList).between("create_date", firstDay, lastDay).groupBy("creator_id,create_date"));
-        } else {
-            reportList = reportMapper.selectList(new QueryWrapper<Report>().select("creator_id,create_date, sum(working_time) as working_time").eq("creator_id", user.getId()).between("create_date", firstDay, lastDay).groupBy("creator_id,create_date"));
+            if (userIdList.size() > 0) {
+                if (userIdList.size() == 1) {
+                    //按单个人匹配
+                    reportList = reportMapper.selectList(new QueryWrapper<Report>().select("creator_id,create_date, sum(working_time) as working_time").eq("creator_id", userIdList.get(0)).between("create_date", firstDay, lastDay).groupBy("creator_id,create_date"));
+                } else {
+                    reportList = reportMapper.selectList(new QueryWrapper<Report>().select("creator_id,create_date, sum(working_time) as working_time").in("creator_id", userIdList).between("create_date", firstDay, lastDay).groupBy("creator_id,create_date"));
+                }
+            }
         }
         //比对userCorpwxTimeList和reportList,找出工时未填满的记录
         List<Map<String, Object>> resultList = new ArrayList<>();

+ 2 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -1543,8 +1543,8 @@ public class TimingTask {
                         userList = reportService.getNotFullReportUserList(company.getId(), startDate, lastDay);
                     } else {
                         LocalDate startDate = localDate.minusDays(7);
-                        //从2023-11-10号以后开始算
-                        if (startDate.isAfter(LocalDate.parse("2023-11-05"))) {
+                        //针对物奇,从2023-11-10号以后开始算,上周漏填的也要提醒
+                        if (startDate.isAfter(LocalDate.parse("2023-11-05")) && company.getId() == 1071) {
                             //检查上周日报是否漏填
                             LocalDate lastSunday = localDate.with(DayOfWeek.SUNDAY).minusWeeks(1);
                             LocalDate lastMonday = lastSunday.minusDays(6);
@@ -1626,9 +1626,6 @@ public class TimingTask {
                         if (u.get("corpwxUserid") != null){
                             //推送到企业微信
                             String corpUid = (String) u.get("corpwxUserid");
-                            if ("woy9TkCAAAyVAc5oXhGwCO-DFWF8SfKg".equals(corpUid)){
-                                System.out.println("发送给 【顾焕峰】漏填提醒");
-                            }
                             JSONObject json=new JSONObject();
                             JSONArray dataJson = new JSONArray();
                             JSONObject jsonObj = new JSONObject();

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

@@ -4951,7 +4951,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         dpetStatisticsProgressList.forEach(pt->{
             BigDecimal planWorkTime = new BigDecimal(pt.get("planWorkTime") == null ? 0 : Double.valueOf(String.valueOf(pt.get("planWorkTime"))));
             BigDecimal nowWorkTime = new BigDecimal(pt.get("nowWorkTime") == null ? 0 : Double.valueOf(String.valueOf(pt.get("nowWorkTime"))));
-            if(nowWorkTime.compareTo(BigDecimal.ZERO)!=0){
+            if(nowWorkTime.compareTo(BigDecimal.ZERO)!=0&&planWorkTime.compareTo(BigDecimal.ZERO)!=0){
                 BigDecimal divide = nowWorkTime.divide(planWorkTime, 4, RoundingMode.HALF_UP);
                 pt.put("progress",format.format(divide.doubleValue()));
             }
@@ -5069,7 +5069,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             if (map.get("planExtraInfoId")!=null){
                 BigDecimal num = new BigDecimal(String.valueOf(map.get("num")));
                 if (planManNum>1){
-                    avg = num.divide(BigDecimal.valueOf(planManNum)).setScale(2, RoundingMode.HALF_UP);
+                    avg = num.divide(BigDecimal.valueOf(planManNum)).setScale(3, RoundingMode.HALF_UP);
                 }
                 else {
 //                    item.add(String.valueOf(map.get("num")) + " 件");
@@ -5096,19 +5096,19 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             String cost = String.valueOf(map.get("cost"));
             if(planType==0){
                 BigDecimal finishNum = new BigDecimal(map.get("finishNum")==null?String.valueOf(0):String.valueOf(map.get("finishNum")));
-                finishNum=finishNum.multiply(new BigDecimal(map.get("unitPrice")==null?String.valueOf(0):String.valueOf(map.get("unitPrice")))).setScale(2,RoundingMode.HALF_UP);
+                finishNum=finishNum.multiply(new BigDecimal(map.get("unitPrice")==null?String.valueOf(0):String.valueOf(map.get("unitPrice")))).setScale(3,RoundingMode.HALF_UP);
                 item.add(String.valueOf(finishNum.doubleValue()));
             }else {
                 //第二种的报工工序类型
                 if (map.get("planExtraInfoId")!=null){
                     BigDecimal num = avg==null?BigDecimal.ZERO:avg;
                     BigDecimal unitPrice = new BigDecimal(map.get("unitPrice")==null?String.valueOf(0):String.valueOf(map.get("unitPrice")));
-                    BigDecimal total=num.multiply(unitPrice).setScale(2,RoundingMode.HALF_UP);
+                    BigDecimal total=num.multiply(unitPrice).setScale(3,RoundingMode.HALF_UP);
                     item.add(total.toString());
                 }else {
                     //第一种报工工序类型
                     BigDecimal workingTime = new BigDecimal(map.get("workingTime")==null?String.valueOf(0):String.valueOf(map.get("workingTime")));
-                    workingTime=workingTime.multiply(new BigDecimal(map.get("unitPrice")==null?String.valueOf(0):String.valueOf(map.get("unitPrice")))).setScale(2,RoundingMode.HALF_UP);
+                    workingTime=workingTime.multiply(new BigDecimal(map.get("unitPrice")==null?String.valueOf(0):String.valueOf(map.get("unitPrice")))).setScale(3,RoundingMode.HALF_UP);
                     item.add(String.valueOf(workingTime.doubleValue()));
                 }
             }

+ 39 - 5
fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue

@@ -333,7 +333,6 @@
                 :header-cell-style="{'font-weight':'normal'}"
                 highlight-current-row
                 max-height="240"
-                :span-method="objectSpanMethod"
                 style="width: 100%;margin-top:10px;margin-bottom:15px">
                 <el-table-column :label="$t('headerTop.serialNumber')" prop="documentType" min-width="60" align="center">
                     <template slot-scope="scope">
@@ -354,15 +353,18 @@
                         </div>
                     </template>
                 </el-table-column>
-                <el-table-column :label="$t('creationtime')" prop="indate" min-width="140" align="center">
+                <el-table-column :label="$t('creationtime')" prop="indate" min-width="150" align="center">
                     <template slot-scope="scope">
                         <span>{{scope.row.indate}}</span>
                     </template>
                 </el-table-column>
-                <el-table-column :label="$t('operation')" min-width="90" fixed="right">
+                <el-table-column :label="$t('operation')" min-width="150" fixed="right">
                     <template slot-scope="scope">
                         <el-link :href="scope.row.url" :download="scope.row.documentName" type="primary" style="margin-right:7px">{{ $t('other.download') }}</el-link>
                         <el-link @click="taskFileDelete(scope.row.id)">{{ $t('btn.delete') }}</el-link>
+                        <el-upload style="display: inline-block;" action="#" :http-request="(row) => uploadFileClickTwo(row, scope.row)" :show-file-list="false" :multiple="false" v-if="scope.row.fileChargeStatus == 2">
+                            <el-link type="primary">重新上传</el-link>
+                        </el-upload>
                     </template>
                 </el-table-column>
                 <el-table-column label="状态" min-width="140" v-if="user.timeType.taskFileCharge == 1" fixed="right">
@@ -1998,11 +2000,14 @@ export default {
     },
     showReasonForRejection(item) {
         const taskId = this.taskId
+        const {id} = item
         this.http.post('/task/getFileRejectReason',{
             taskId
         },res => {
             if(res.code == 'ok'){
-                this.$alert(res.data, '驳回原因');
+                let text = res.data.find(item => item.id == id)
+                console.log(text)
+                this.$alert(text.fileRejectReason, '驳回原因');
             }else {
                 this.$message.error(res.msg)
             }
@@ -2188,7 +2193,7 @@ export default {
         files.append("projectId",this.curProjectId);
         files.append("taskId", this.addForm.id);
         files.append("file", item.file);
-        this.http.uploadFile('/task-files/uploadFile',files,
+        this.http.uploadFile('/task-files/uploadFile', files,
         res => {
             if(res.code == 'ok'){
                 console.log(res);
@@ -2211,6 +2216,35 @@ export default {
             })
         })
     },
+    uploadFileClickTwo(item, row) {
+        let files = new FormData()
+        files.append("projectId",this.curProjectId);
+        files.append("taskId", this.addForm.id);
+        files.append("taskFileId", row.id);
+        files.append("file", item.file);
+        this.http.uploadFile('/task-files/reUploadFile', files,
+        res => {
+            if(res.code == 'ok'){
+                console.log(res);
+                this.$message({
+                    message: this.$t('yi-shang-chuan'),
+                    type: 'success'
+                })
+                this.gain({ taskId: this.taskId }, 1)
+                this.getTaskFileList()
+            }else {
+                this.$message({
+                    message: res.msg,
+                    type: 'error'
+                })
+            }
+        },error => {
+            this.$message({
+                message: error,
+                type: 'error'
+            })
+        })
+    }
   },
 };
 </script>

+ 5 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/task/list.vue

@@ -806,7 +806,11 @@ import { error } from 'dingtalk-jsapi';
                     taskId
                 },res => {
                     if(res.code == 'ok'){
-                        this.$alert(res.data, '驳回原因');
+                        // this.$alert(res.data, '驳回原因');
+                        const text = (res.data || []).map(item => {
+                            return `文件【${item.documentName}】的驳回原因为:${item.fileRejectReason}<br/>`
+                        })
+                        this.$alert(text.join(''), '驳回原因', { dangerouslyUseHTMLString: true });
                     }else {
                         this.$message.error(res.msg)
                     }

+ 39 - 26
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -1615,17 +1615,6 @@
           </el-table>
           <el-alert style="position:absolute;bottom:0;z-index:10;" v-if="isFlag" :title="$t('message.loading')+'...'" type="success" center :closable="false" show-icon></el-alert>
           <el-alert style="position:absolute;bottom:0;z-index:10;" v-if="isMore" :title="$t('message.noMoreData')" type="warning" center show-icon></el-alert>
-
-          <!-- <div slot="title" class="dialog-title selectworktime_title">
-            <label style="font-size: 16px">员工每日已填报工时数</label>
-            <el-link
-              type="primary"
-              style="float: right; margin-right: 60px"
-              @click="exportMembWorkHours()"
-              >导出已填报数据</el-link
-            > -->
-          <!-- <el-button >导出</el-button> -->
-          <!-- </div> -->
         </el-tab-pane>
 
         <el-tab-pane :label="$t('weiTiJiaoRenYuanLieBiao')" name="second" >
@@ -1735,11 +1724,19 @@
             </div>
             <div>
                 <div style="margin-top:10px;">
+                    <el-cascader v-if="user.userNameNeedTranslate != 1" :size="'small'" v-model="deptIdForHasReport" :placeholder="$t('qing-xuan-ze-bu-men')" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 200px;" @change="showReportTimeLessThanCardTimeList()"></el-cascader>
+                    <vueCascader :size="'small'" :widthStr="'200'" :clearable="true" :subject="trandepartmentList" :radios="true" :distinction="'17'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
+                    <el-input style="width:200px;margin-left: 15px" v-if="user.userNameNeedTranslate != '1'" @keyup.enter.native="searchScreen(2)" v-model="searchKeyword" class="input-with-select" :placeholder="$t('defaultText.pleaseEnterNametoSearch')" clearable="true" size="small">
+                        <el-button slot="append" @click="searchScreen(2)" icon="el-icon-search"></el-button>
+                    </el-input>
+                    <selectCat v-if="user.userNameNeedTranslate == '1'" :filterable="true" :searchBoxTop="'1'" :size="'small'" :subject="usersList" :subjectId="usersListId" :distinction="'15'" :clearable="true" @selectCal="selectCal"></selectCat>
+
                     <!-- <el-link
                         type="primary"
                         style="float: right; vertical-align: middle;height:32px"
                         @click="exportMembNotWorkHours()"
-                        >{{$t('export.exportData')}}</el-link> -->
+                        >{{$t('export.exportData')}}</el-link
+                    > -->
                 </div>
             </div>
             
@@ -2299,6 +2296,8 @@
         },
         data() {
             return {
+                notFullData:[],
+                notFullOriginList:[],
                 singleDate:1,
                 subFillProjectList:[],
                 curAuditNode: 1,
@@ -2760,12 +2759,15 @@
                 this.http.post(
                     "/report/getReportTimeLessThanCardTimeList",
                     {
-                    date: this.notfullSelectDateMonth
+                    date: this.notfullSelectDateMonth,
+                    deptId: this.deptIdForHasReport.length>0?this.deptIdForHasReport[this.deptIdForHasReport.length-1]:null,
+                    userId: this.usersListId
                     },
                     (res) => {
                     if (res.code == "ok") {
                         this.tbload = false
                         this.notFullData = res.data;
+                        this.notFullOriginList = res.data;
                     }
                     },
                     (error) => {
@@ -3433,7 +3435,7 @@
                 }
             },
             searchScreen(e){
-                if(e){
+                if(e == 1){
                     this.monthNotWorkDateS1 = []
                     for (let i = 0; i < this.monthNotWorkDate.length; i++) {
                         if(this.monthNotWorkDate[i].name.indexOf(this.searchKeyword) != -1){
@@ -3445,12 +3447,7 @@
                     }else{
                         this.monthNotWorkDateS = this.monthNotWorkDateS1 
                     }
-                    // if (this.monthNotWorkDateS1.length > 0) {
-                    //     setTimeout(() => {
-                    //         this.tableListenernot()
-                    //     }, 1000);
-                    // }
-                }else{
+                } else if (e == 0) {
                     this.monthWorkDataS1 = []
                     for (let i = 0; i < this.monthWorkData.length; i++) {
                         if(this.monthWorkData[i].name.indexOf(this.searchKeyword) != -1){
@@ -3462,11 +3459,18 @@
                     }else{
                         this.monthWorkDataS = this.monthWorkDataS1 
                     }
-                    // if (this.monthWorkDataS1.length > 0) {
-                    //     setTimeout(() => {
-                    //         this.tableListener()
-                    //     }, 1000);
-                    // }
+                } else if (e == 2) {
+                    this.monthWorkDataS1 = []
+                    for (let i = 0; i < this.notFullOriginList.length; i++) {
+                        if(this.notFullOriginList[i].name.indexOf(this.searchKeyword) != -1){
+                            this.monthWorkDataS1.push(this.notFullOriginList[i])
+                        }
+                    }
+                    if (this.monthWorkDataS1.length > 50) {
+                        this.notFullData = this.monthWorkDataS1.slice(0,50);
+                    }else{
+                        this.notFullData = this.monthWorkDataS1 
+                    }
                 }
             },
             addUpload(data) {
@@ -8876,6 +8880,12 @@
                     this.deptIdForReminder = arr
                     this.showMonthWorkTimeReminder()
                 }
+                if(obj.distinction == '17' && obj) {
+                    let arr = []
+                    arr.push(obj.id)
+                    this.deptIdForHasReport = arr
+                    this.showReportTimeLessThanCardTimeList();
+                }
             },
             //分页
             handleCurrentChange(val) {
@@ -9104,7 +9114,10 @@
                         this.searchKeyword = ''
                     }
                     this.searchScreen(1)
-                }
+                } else if(obj.distinction == '15') {
+                    this.usersListId = obj.id
+                    this.showReportTimeLessThanCardTimeList();
+                } 
             }
         },
         created() {

+ 3 - 3
fhKeeper/formulahousekeeper/timesheet_h5/src/views/project/index.vue

@@ -409,7 +409,7 @@
                         inchargerName:null,
                         inchargerId:null,
                         userId:null,
-                        userNames:null,
+                        userNames:'',
                         associateDegreeNames: null,
                         associateDegrees: null
                     }
@@ -479,6 +479,8 @@
                         formData.append("associateDegrees", sss);
                     }
 
+                    formData.append("isPublic", 0);
+
                     this.$axios.post("/project/editProject", formData)
                     .then(res => {
                         if(res.code == "ok") {    
@@ -494,8 +496,6 @@
                             this.$toast.fail(res.msg);
                         }
                     }).catch(err=> {this.$toast.clear();});
-                    
-
                 } else {
                     this.show = false;
                     this.yanjiuzx()

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

@@ -85,6 +85,8 @@
                     :min-date="minDate"
                     :max-date="maxDate"/>
                 </van-popup>
+                <van-field v-if="user.timeType.taskPlanCost" v-model="taskform.planCost" label="预估研发费用" placeholder="请填写预估研发费用,单位:元" :rules="[{ required: true, message: '请填写' }]"  
+                type="number" required :disabled="!canEdit"></van-field>
                 <!-- 完成时间 -->
                 <van-field v-if="taskform.type == 1" v-model="taskform.finishDate" label="完成时间" placeholder="请选择完成时间" @click="finishDateShow = true" readonly clickable></van-field>
                 <van-popup v-model="finishDateShow" position="bottom" v-if="canEdit">
@@ -561,6 +563,10 @@ export default {
                 this.$toast.fail("请选择所属任务列表");
                 return
             }
+            if(this.user.timeType.taskPlanCost && (this.taskform.planCost == '' || this.taskform.planCost == null)) {
+                this.$toast.fail("请填写预估研发费用");
+                return
+            }
 
             // 去除未选择执行人的执行人列表
             this.taskform.executorList = this.taskform.executorList.filter(item => item.executorId)