Browse Source

Merge remote-tracking branch 'origin/master'

yusm 4 months ago
parent
commit
a14e4fc93e
19 changed files with 401 additions and 42 deletions
  1. 10 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js
  2. 26 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleDetails/index.vue
  3. 27 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleList/moduleList.vue
  4. 10 4
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/addEditor.vue
  5. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contract/addEditor.vue
  6. 6 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contract/detail.vue
  7. 4 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/addEditor.vue
  8. 4 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/detail.vue
  9. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/orderInfo.vue
  10. 156 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/paymentCollection.vue
  11. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/newAndModifiedRelatedProducts.vue
  12. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/productInfo.vue
  13. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/tasks/addEditor.vue
  14. 107 9
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/tasks/detail.vue
  15. 18 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/threadInfo.vue
  16. 15 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/utility/customInstructions.js
  17. 0 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  18. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  19. 7 5
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

+ 10 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js

@@ -45,8 +45,10 @@ export const CUSTOMER_ADDED_EDITOR = `/custom/insertAndUpdate` // 客户新增
 export const CONTACT_PERSON_ADDITION_EDITOR = `/contacts/addContacts` // 联系人新增编辑
 export const TASK_ADD_EDIT = `/tasks/addTask` // 任务新增
 export const MODIFY_TASK = `/tasks/updateTask` // 任务编辑
+export const TASK_OPERATION = `/tasks/updateTaskStatus` // 任务操作
 export const PRODUCT_ADD_EDITOR = `/product/addOrUpdate` // 产品新增编辑
-export const CONTRACT_ADDITION_EDITING = `/contract/addContract` // 合同新增编辑
+export const CONTRACT_ADDITION_EDITING = `/contract/addContract` // 合同新增
+export const CONTRACT_EDITING = `/contract/editContract` // 合同编辑
 export const ORDER_ADDITION_EDITING = `/order/addOrUpdate` // 订单新增编辑
 export const PLAN_TO_ADD_EDITORS = `/visitPlan/addOrUpdateVisitPlan` // 计划新增编辑
 
@@ -61,8 +63,9 @@ 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 GET_TASK_DETAILS = `/tasks/getTaskDetail` // 获取任务详情
 export const SELL_AND_OBTAIN_RELATED_PRODUCTS = `/product/orderWithProduct` // 销售订单关联产品
+export const OBTAIN_CONTRACT_DETAILS = `/contract/getContractDetail` // 获取合同详情
 
 export const GET_CONTACTS_WITH_MORE_I_DS = `/contacts/getAllContacts` // 更具Id获取联系人
 export const CONTACT_PERSON_ASSOCIATED_WITH_BUSINESS_OPPORTUNITY = `/business-opportunity/saveContactsId` // 联系人关联商机
@@ -111,4 +114,8 @@ export const OBTAIN_DATA_SUMMARY = `/order/dataSummary` // 获取数据汇总
 export const STAGE_OF_OBTAINING_BUSINESS_OPPORTUNITIES = `/order/businessOpportunityStage` // 获取商机阶段
 export const ACQUISITION_STAGE = `/business-opportunity/getStage` // 获取阶段
 export const PROMOTION_STAGE = `/business-opportunity/saveStageId` // 推进阶段
-export const STAGE_NOTES = `/business-opportunity/saveReason` // 阶段备注
+export const STAGE_NOTES = `/business-opportunity/saveReason` // 阶段备注
+export const OBTAIN_SALES_ORDER_RECEIPTS = `/order/paymentCollectionList` // 获取销售订单收款列表
+export const NEW_SALES_ORDER_PAYMENT_COLLECTION = `/order/paymentCollection` // 新建销售订单收款
+export const SALES_ORDER_COLLECTION_EDITING = `/order/editPayment` // 编辑销售订单收款
+export const DELETE_SALES_ORDER_PAYMENT_RECORDS = `/order/deletePayment` // 删除销售订单收款记录

+ 26 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleDetails/index.vue

@@ -36,13 +36,21 @@
         </template>
       </div>
     </template>
+
+    <template v-slot:headerRight>
+      <template v-if="currentRoutingInformation?.key == 'tasks'">
+        <div class="themeTextColor" @click="jumpEdit()">编辑</div>
+      </template>
+    </template>
   </Page>
 </template>
 
 <script setup>
 import { ref } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
+import { resetListData, getListFieldKey } from '@components/common/formForm/formCorrespondenceProcessing'
 import useRouterStore from "@store/useRouterStore.js";
+import useFixedData from "@store/useFixedData.js"
 
 import Business from "@pages/pageComponents/business/detail.vue"
 import Thread from "@pages/pageComponents/thread/detail.vue"
@@ -53,6 +61,7 @@ import Product from "@pages/pageComponents/product/detail.vue"
 import Contract from "@pages/pageComponents/contract/detail.vue"
 import Order from "@pages/pageComponents/order/detail.vue"
 
+const fixedData = useFixedData()
 const router = useRouterStore()
 const queryParameters = ref({})
 const currentRoutingInformation = ref({})
@@ -62,6 +71,23 @@ function reloadListData(data) {
   currentRoutingInformation.value = JSON.parse(routerInfo)
 }
 
+function jumpEdit() {
+  const formJson = fixedData.formJson[currentRoutingInformation.value.key] || []
+  const formList = resetListData(formJson?.list)
+  const filedObj = getListFieldKey(formList, queryParameters.value)
+  const formVal = { ...queryParameters.value, ...filedObj, id: queryParameters.value.id }
+  console.log(formVal, '<=== formVal')
+  router.navigateTo({
+    pathName: 'addEditor',
+    success: () => {
+      router.emit('addEditorParameter', {
+        routerInfo: JSON.stringify(currentRoutingInformation.value),
+        filedValue: JSON.stringify(formVal)
+      })
+    }
+  })
+}
+
 useLifecycle({
   load: () => {
     router.on('detailParameter', (data) => {

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

@@ -273,6 +273,8 @@ const listData = ref({
 });
 const excessiveData = ref({});
 const dialogSelection = ref({});
+const timeout = ref(null)
+
 
 // 按钮触发的事件: row 为当前点击的行数据, item 为当前点击的按钮
 function longPress(row, item) {
@@ -457,12 +459,17 @@ async function getListData(flag = false) {
   if (flag) {
     loadingList.value = true
   }
-  const res = await requests.post(url, {
+  let formVal = {
     pageIndex: listData.value.pageIndex,
     pageSize: listData.value.pageSize,
     pageFrom: listData.value.pageSize,
-    [queryParameters.value?.searchFiled?.search]: searchVal.value
-  }).finally(() => {
+    [queryParameters.value?.searchFiled?.search]: searchVal.value,
+  }
+
+  if(queryParameters.value?.key == 'product') {
+    formVal.status = 1
+  }
+  const res = await requests.post(url, { ...formVal }).finally(() => {
     if (flag) {
       loadingList.value = false
     }
@@ -511,14 +518,29 @@ function dialogCloseBefo(val) {
   return true
 }
 
+function chuliReloadListData(data) {
+  clearTimeout(timeout.value);
+  timeout.value = setTimeout(() => {
+    reloadListData(data)
+  }, 100);
+}
+
+function chuliOnRefresh(data) {
+  clearTimeout(timeout.value);
+  timeout.value = setTimeout(() => {
+    onRefresh(true)
+  }, 100);
+}
+
 useLifecycle({
   load: () => {
+    chuliOnRefresh(true)
     router.on('moduleListDetailParameter', (data) => {
-      reloadListData(data)
+      chuliReloadListData(data)
     })
 
     router.eventOn('moduleListRefreshData', (data) => {
-      onRefresh(true)
+      chuliOnRefresh(true)
     })
   }
 });

+ 10 - 4
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/addEditor.vue

@@ -64,10 +64,16 @@ function onSubmit() {
     if(flagVal) {
       return
     }
-    newList.forEach((item) => {
-      item.typeName = item.productType
-      delete item.id
-    })
+
+    for(let i in newList) {
+      if(!newList[i].totalPrice || newList[i].totalPrice == '0') {
+        toastText(`相关产品【${newList[i].productName}】请填写完整`)
+        return
+      }
+      newList[i].typeName = newList[i].productType
+      delete newList[i].id
+    }
+
     const newForm = {
       ...props.formValue,
       ...res.data,

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

@@ -17,7 +17,7 @@ import { useLifecycle } from '@hooks/useCommon.js';
 import CustomerForm from '@components/common/formForm/formView.vue'
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
-import { CONTRACT_ADDITION_EDITING } from "@hooks/useApi"
+import { CONTRACT_ADDITION_EDITING, CONTRACT_EDITING } from "@hooks/useApi"
 import useRouterStore from "@store/useRouterStore.js";
 
 const router = useRouterStore()
@@ -38,7 +38,7 @@ function onSubmit() {
       return
     }
     toastLoading('保存中', 0)
-    requests.post(CONTRACT_ADDITION_EDITING, { ...props.formValue, ...res.data }).then(() => {
+    requests.post(props.formValue?.id ? CONTRACT_EDITING : CONTRACT_ADDITION_EDITING, { ...props.formValue, ...res.data }).then(() => {
       toastSuccess('保存成功')
       setTimeout(() => {
         router.navigateBack({

+ 6 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contract/detail.vue

@@ -18,6 +18,8 @@
           {{ infoData.payment ? (100 * infoData.payment / infoData.amounts).toFixed(1) + '%' : '0%' }}
         </template>
       </van-cell>
+      <van-cell title="计划开始时间" :value="infoData.startDate" />
+      <van-cell title="计划结束时间" :value="infoData.endDate" />
       <van-cell title="下笔回款日期" :value="infoData.nextPaymentDate">
         <template #default>
           {{ infoData.nextPaymentDate ? infoData.nextPaymentDate : '-' }}
@@ -64,7 +66,7 @@ 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 { CONTRACT_APPROVED, OBTAIN_CONTRACT_DETAILS } from '@hooks/useApi'
 import useShowToast from '@hooks/useToast'
 import useInfoStore from '@store/useInfoStore'
 import useRouterStore from "@store/useRouterStore.js";
@@ -183,7 +185,9 @@ function jumpEdit() {
 }
 
 function getDetails(id) {
-  // 获取合同详情
+  requests.post(OBTAIN_CONTRACT_DETAILS, { id }).then((res) => {
+    infoData.value = res.data || {}
+  })
 }
 function processingData(id) {
   clearTimeout(timeout.value);

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

@@ -67,6 +67,10 @@ function onSubmit() {
     }
     let newList = businessItemProductList.value.filter(item => item.productId)
     for (let i in newList) {
+      if(!newList[i].totalPrice || newList[i].totalPrice == '0') {
+        toastText(`相关产品【${newList[i].productName}】请填写完整`)
+        return
+      }
       newList[i].sealPrice = newList[i].sellingPrice
       newList[i].discount = newList[i].discount
       newList[i].num = newList[i].quantity

+ 4 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/detail.vue

@@ -10,6 +10,9 @@
       <van-tab title="相关产品" name="相关产品">
         <RelatedProducts :infoList="relatedProductsList" />
       </van-tab>
+      <van-tab title="回款" name="回款">
+        <PaymentCollection :info="infoData" />
+      </van-tab> 
     </van-tabs>
   </div>
 </template>
@@ -22,6 +25,7 @@ import requests from "@common/requests";
 import OrderInfo from './orderInfo.vue';
 import RelatedTasks from '../tasks/relatedTasks.vue';
 import RelatedProducts from '../product/relatedProducts.vue';
+import PaymentCollection from './paymentCollection.vue';
 
 const props = defineProps({
   info: {

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

@@ -25,7 +25,7 @@
           <span class="text-[#FF8B32]" v-if="info.unReceivedPayment">¥ {{ info.unReceivedPayment }}</span>
         </template>
       </van-cell>
-      <van-cell title="订单类型" :value="info.type" />
+      <van-cell title="订单类型" :value="info.typeName" />
       <van-cell title="下单时间" :value="info.placeTime" />
       <van-cell title="订单开始时间" :value="info.orderStartDate" />
       <van-cell title="订单结束时间" :value="info.orderEndDate" />
@@ -75,7 +75,7 @@ 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 { TRANSFER_CLUES, TRANSFER_SALES_ORDERS } from '@hooks/useApi'
 import requests from "@common/requests";
 import useShowToast from '@hooks/useToast'
 import useInfoStore from '@store/useInfoStore'
@@ -154,7 +154,7 @@ function confirmTransfer() {
     return toastText('请选择要转移的人员')
   }
 
-  requests.post(TRANSFER_CLUES, { ids: props.info.id, inchargerId: dialogSelection.value.value }).then((res) => {
+  requests.post(TRANSFER_SALES_ORDERS, { id: props.info.id, userId: dialogSelection.value.value }).then((res) => {
     toastSuccess('转移成功')
     showDialog.value = false
     setTimeout(() => {

+ 156 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/paymentCollection.vue

@@ -0,0 +1,156 @@
+<template>
+  <div class="flex flex-col h-full paymentCollection">
+    <div class="info flex-1 overflow-y-auto cellnormall">
+      <template v-if="paymentPlanList.length">
+        <div class="bg-white py-2 mb-4" v-for="item in paymentPlanList" :key="item.id">
+          <van-cell-group inset>
+            <van-cell title="回款时间" :value="item.createTime" />
+            <van-cell title="操作人">
+              <template #default>
+                <TranslationComponent :openId="item.creatorName"></TranslationComponent>
+              </template>
+            </van-cell>
+            <van-cell title="回款金额" :value="item.money" />
+            <van-cell title="未回款金额" :value="item.unReceivedPayment" />
+            <van-cell title="操作">
+              <template #default>
+                <div class="flex justify-end">
+                  <div class="mr-3 themeTextColor" @click="editPaymentCollection(item)">编辑</div>
+                  <div class="text-[red]" @click="deletePaymentCollection(item)">删除</div>
+                </div>
+              </template>
+            </van-cell>
+          </van-cell-group>
+        </div>
+      </template>
+      <template v-else>
+        <van-empty description="暂无数据" />
+      </template>
+    </div>
+    <div class="bottomButton">
+      <van-button type="primary" class="w-full block" @click="addPaymentCollection">添加回款</van-button>
+    </div>
+
+    <!-- 添加回款 -->
+    <van-dialog v-model:show="showDialog" :title="`${dialogNumberVal.rowId ? '编辑' : '新增'}回款金额`" show-cancel-button
+      @confirm="addEditReceipt" :before-close="dialogCloseBefo">
+      <van-field v-model="dialogNumberVal.val" type="digit" label="回款金额" placeholder="请输入回款金额" />
+    </van-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue';
+import { showConfirmDialog } from 'vant';
+import { useLifecycle } from '@hooks/useCommon.js';
+import { OBTAIN_SALES_ORDER_RECEIPTS, NEW_SALES_ORDER_PAYMENT_COLLECTION, SALES_ORDER_COLLECTION_EDITING, DELETE_SALES_ORDER_PAYMENT_RECORDS } from '@hooks/useApi'
+import requests from "@common/requests";
+import useShowToast from '@hooks/useToast'
+
+const { toastSuccess, toastFail, toastText } = useShowToast()
+const props = defineProps({
+  info: {
+    type: Object,
+    required: true,
+    default: () => ({})
+  }
+})
+const paymentPlanList = ref([])
+const showDialog = ref(false);
+const dialogNumberVal = ref({
+  rowId: null,
+  val: null
+})
+
+watch(() => props.info, (newValue) => {
+  processingData(newValue.id)
+})
+
+function deletePaymentCollection(row) {
+  showConfirmDialog({
+    message: `确定删除该回款记录吗?`,
+  }).then(() => {
+    requests.post(DELETE_SALES_ORDER_PAYMENT_RECORDS, { paymentId: row.id }).then(() => {
+      toastSuccess('操作成功')
+      processingData(props.info.id)
+    }).catch((err) => {
+      toastFail(err.msg ? err.msg : '删除失败')
+    })
+  })
+}
+
+function addEditReceipt() {
+  const { rowId, val } = dialogNumberVal.value
+  if (!val || val <= 0) {
+    toastText('请填写回款金额并且不能为负数')
+    return
+  }
+  const url = rowId ? SALES_ORDER_COLLECTION_EDITING : NEW_SALES_ORDER_PAYMENT_COLLECTION
+  const arrList = paymentPlanList.value.filter(item => item.id !== rowId)
+  const totalMoney = arrList.reduce((acc, item) => acc + item.money, 0);
+  const orderAmount = props.info.price
+  const formVal = {
+    [rowId ? 'paymentId' : 'orderId']: rowId ? rowId : props.info.id,
+    money: val,
+  }
+  if ((+totalMoney + val) > orderAmount) {
+    toastText('回款金额不能大于订单金额')
+    return
+  }
+  requests.post(url, formVal).then(() => {
+    toastSuccess('操作成功')
+    processingData(props.info.id)
+    showDialog.value = false
+  })
+}
+
+function addPaymentCollection() {
+  dialogNumberVal.value = { rowId: null, val: null }
+  showDialog.value = true
+}
+
+function editPaymentCollection(row) {
+  const { id, money } = row
+  dialogNumberVal.value = { rowId: id, val: money }
+  showDialog.value = true
+}
+
+function processingData(id) {
+  requests.post(OBTAIN_SALES_ORDER_RECEIPTS, { orderId: id }).then((res) => {
+    paymentPlanList.value = res.data.reverse()
+  })
+}
+
+function dialogCloseBefo(val) {
+  if (val == 'confirm' && showDialog.value) {
+    return false
+  }
+
+  return true
+}
+
+
+useLifecycle({
+  init: () => {
+    processingData(props.info.id)
+  }
+});
+</script>
+
+<style lang='scss' scoped>
+.paymentCollection {
+  .bottomButton {
+    margin: 0 14px;
+    padding-bottom: 30px;
+
+    :deep(.van-button) {
+      margin-bottom: 20px;
+    }
+  }
+
+  .info {
+    margin: 8px 4px 30px 4px;
+    padding: 10px
+  }
+}
+</style>

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

@@ -71,6 +71,7 @@
       placeholder="请输入"
       :max="form.inventory ? +form.inventory : 0"
       :min="0"
+      @blur="inputNumberChange('quantity')"
       @input="inputNumberChange('quantity')"
     ></van-field>
     <van-field

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

@@ -141,13 +141,13 @@ function confirmTransfer() {
 
 function claimAndClaim() {
   showConfirmDialog({
-    title: '认领线索',
-    message: `确定认领【${props.info.clueName}】线索吗?`,
+    title: '认领产品',
+    message: `确定认领【${props.info.productName}】产品吗?`,
   }).then(() => {
     requests.post(TRANSFER_PRODUCTS, { id: props.info.id, userId: userInfo.userInfo.id }).then((res) => {
       toastSuccess('认领成功')
       listReloadData()
-      props.info.inchargerName = userInfo.userInfo.clueName
+      props.info.inchargerName = userInfo.userInfo.name
       showDialog.value = false
     })
   })

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/tasks/addEditor.vue

@@ -3,7 +3,7 @@
     <div class="flex-1 overflow-y-auto">
       <van-form ref="vanFormRef" show-error :show-error-message="false" label-align="left" input-align="right"
         class="bg-white" @submit="onSubmit">
-        <van-field v-model="vantFormVal.taskName" name="taskName" rows="2" label="任务名称" maxlength="100" required
+        <van-field v-model.trim="vantFormVal.taskName" name="taskName" rows="2" label="任务名称" maxlength="100" required
           show-word-limit type="textarea" placeholder="请输入" />
         <van-field v-model="vantFormVal.priority" name="priority" label="优先级" placeholder="请选择" is-link readonly
           required @click="showSelectionBox('priority', fixedFieldPriority)">

+ 107 - 9
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/tasks/detail.vue

@@ -1,16 +1,58 @@
 <template>
-  <div class="w-full h-full flex-col">
+  <div class="w-full h-full flex flex-col">
     <div class="bg-white info flex-1 overflow-y-auto">
-      <van-cell title="任务名称" :value="''" />
-      <van-cell title="优先级" :value="''" />
+      <van-cell title="任务名称" :value="infoData.taskName" />
+      <van-cell title="优先级">
+        <template #default>
+          {{ fixedFieldPriority.find(subItem => subItem.value == infoData.priority)?.label || '' }}
+        </template>
+      </van-cell>
+      <van-cell title="状态" :value="''">
+        <template #default>
+          <div :style="`color: ${fixedFieldTaskStatus.find(subItem => subItem.value == infoData.status)?.color}`">
+            {{ fixedFieldTaskStatus.find(subItem => subItem.value == infoData.status)?.label || '' }}
+          </div>
+        </template>
+      </van-cell>
+      <van-cell title="执行人">
+        <template #default>
+          <TranslationComponent :openId="infoData.taskExecutors" />
+        </template>
+      </van-cell>
+      <van-cell title="开始时间" :value="infoData.startDate" />
+      <van-cell title="截至时间" :value="infoData.endDate" />
+      <van-cell title="客户名称" :value="infoData.customName" v-if="infoData.customName" />
+      <van-cell title="商机名称" :value="infoData.businessName" v-if="infoData.businessName" />
+      <van-cell title="销售订单" :value="infoData.orderName" v-if="infoData.orderName" />
+      <van-cell title="线索名称" :value="infoData.clueName" v-if="infoData.clueName" />
+      <van-cell title="联系人名称" :value="infoData.contactsName" v-if="!infoData.clueId" />
+      <van-cell title="联系人号码" :value="infoData.contactsPhone" v-if="!infoData.clueId" />
+    </div>
+    <div class="bottomButton">
+      <van-button type="success" class="w-full block" @click="completeTheTask(2)" v-if="infoData.status != 2">完成任务</van-button>
+      <van-button type="primary" class="w-full block" @click="completeTheTask(0)" v-if="infoData.status == 2">重启任务</van-button>
+      <van-button type="danger" class="w-full block" @click="deleteTask">删除任务</van-button>
     </div>
   </div>
 </template>
 
 <script setup>
-import { ref } from 'vue';
+import { ref, watch } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
+import { GET_TASK_DETAILS, TASK_OPERATION } from "@hooks/useApi"
+import requests from "@common/requests";
+import { fixedFieldPaymentStatus, fixedFieldPriority, fixedFieldTaskStatus, fixedFieldStatusArray } from "@utility/defaultData"
+import useShowToast from '@hooks/useToast'
+import { routingInfos } from "@utility/generalVariables"
+import useInfoStore from '@store/useInfoStore'
+import useFixedData from "@store/useFixedData.js"
+import useRouterStore from "@store/useRouterStore.js";
 
+const router = useRouterStore()
+const fixedData = useFixedData()
+const userInfo = useInfoStore()
+const { toastSuccess, toastFail, toastText } = useShowToast()
 const props = defineProps({
   info: {
     type: Object,
@@ -18,25 +60,81 @@ const props = defineProps({
     default: () => ({})
   }
 })
+const routingInformation = routingInfos['tasks']
+const infoData = ref(props.info);
+const timeout = ref(null);
+
+watch(() => props.info, (newValue) => {
+  initializeData(newValue.id)
+})
+
+function completeTheTask(status) {
+  const id = infoData.value.id
+  requests.post(TASK_OPERATION, { id, status }).then(({ data }) => {
+    toastSuccess('操作成功')
+    getTaskDetails(id)
+  })
+}
 
-function getTaskDetails() {
-  
+function deleteTask() {
+  const { name = '', searchFiled = {}, deteleFiled = '' } = routingInformation
+  const row = infoData.value
+  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 initializeData() {
+function getTaskDetails(id) {
+  requests.post(GET_TASK_DETAILS, { id }).then(({ data }) => {
+    infoData.value = data
+  })
+}
 
+function initializeData(id) {
+  clearTimeout(timeout.value);
+  timeout.value = setTimeout(() => {
+    getTaskDetails(id)
+  }, 100);
 }
 
 useLifecycle({
   load: () => {
-    initializeData()
+    initializeData(props.info.id)
   },
   init: () => {
-    initializeData()
+    initializeData(props.info.id)
+  },
+  unLoad: () => {
+    clearTimeout(timeout.value);
   }
 });
 </script>
 
 <style lang='scss' scoped>
+.bottomButton {
+  margin: 0 14px;
+  padding-bottom: 30px;
 
+  :deep(.van-button) {
+    margin-bottom: 20px;
+  }
+}
+.info {
+  margin: 8px 14px 30px 14px;
+}
 </style>

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

@@ -16,6 +16,7 @@
       <van-cell title="备注" :value="info.remark" />
     </div>
     <div class="bottomButton">
+      <van-button type="primary" class="w-full block" v-if="info.inchargerName"  @click="transformBusinessOpportunities()">线索转商机</van-button>
       <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>
@@ -70,6 +71,23 @@ const showDialog = ref(false);
 const showSelect = ref(false);
 const dialogSelection = ref({});
 
+function transformBusinessOpportunities() {
+  const InfoJson = routingInfos['business']
+  const formJson = fixedData.formJson[InfoJson.key] || []
+  const formList = resetListData(formJson?.list)
+  const filedObj = getListFieldKey(formList, props.info)
+  const formVal = { ...filedObj, inchargerId: '', name: props.info?.clueName, clueId: props.info?.id }
+  router.redirectTo({
+    pathName: 'addEditor',
+    success: () => {
+      router.emit('addEditorParameter', {
+        routerInfo: JSON.stringify(InfoJson),
+        filedValue: JSON.stringify(formVal)
+      })
+    }
+  })
+}
+
 function deleteRow() {
   const { name = '', searchFiled = {}, deteleFiled = '' } = routingInformation
   const row = props.info

+ 15 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/utility/customInstructions.js

@@ -1,6 +1,6 @@
 // 权限控制
 const PermissionDirective = { // 数组, 权限 code 和 布尔值,
-    updated(el, binding, vnode ) {
+    updated(el, binding, vnode) {
         const routePath = vnode.ctx.appContext.config.globalProperties.$route.path;
         const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '');
         const authorityCodes = (userInfo?.userInfo?.functionList || []).map(({ code }) => code);
@@ -22,9 +22,22 @@ const PermissionDirective = { // 数组, 权限 code 和 布尔值,
     },
 };
 
+// 去掉输入框首尾空格的指令
+const TrimWhitespaceDirective = {
+    beforeMount(el) {
+        if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
+            // 监听输入事件,去掉首尾空格
+            el.addEventListener('input', () => {
+                el.value = el.value.trim();
+            });
+        }
+    }
+};
+
 // 导出的自定义指令
 const customize = [
-    { key: 'permission', directive: PermissionDirective, name: '角色权限' }
+    { key: 'permission', directive: PermissionDirective, name: '角色权限' },
+    { key: 'trim-whitespace', directive: TrimWhitespaceDirective, name: '去除首尾空格' }
 ]
 
 export default customize;

+ 0 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -10476,8 +10476,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         //比对userCorpwxTimeList和reportList,找出工时未填满的记录
         List<Map<String, Object>> resultList = new ArrayList<>();
         DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        System.out.println("reportList size=" + reportList.size());
-        System.out.println("userCorpwxTimeList size=" + userCorpwxTimeList.size());
         for (UserCorpwxTime corpwxTime : userCorpwxTimeList) {
             boolean isMatch = true;
             double reportTime = 0;

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

@@ -587,7 +587,7 @@
                     </el-form-item>
                     <!-- 增加合同金额字段 -->
                     <el-form-item  :label="$t('contractamount')" v-if="(user.company.nonProjectSimple == 0 || (user.company.nonProjectSimple == 1 && addForm.isPublic == 0))">
-                        <el-input id="contractAmount" v-model="addForm.contractAmount" :disabled="canOnlyModParticipator" style="width:32%;" @input="contractAmountChange(addForm.contractAmount)" :placeholder="$t('zheng-shu')" clearable  @keyup.native="restrictNumber('contractAmount')"></el-input><span style="margin-left:10px;position:absolute;">{{ $t('yuan') }}</span>
+                        <el-input id="contractAmount" v-model="addForm.contractAmount" :disabled="canOnlyModParticipator" style="width:32%;" @input="contractAmountChange(addForm.contractAmount)" :placeholder="$t('zheng-shu')" clearable maxlength="9"  @keyup.native="restrictNumber('contractAmount')"></el-input><span style="margin-left:10px;position:absolute;">{{ $t('yuan') }}</span>
                         <template v-if="title == $t('modifytheproject') && contractAmountReasonShow">
                             <span style="margin-left:63px;margin-right:10px;">{{ $t('modifythereason') }}</span>
                             <el-input v-model="addForm.changeContractReason" style="width:33%" clearable :placeholder="$t('contractamountasd')"></el-input>

+ 7 - 5
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -1724,7 +1724,7 @@
             </div>
             <div>
                 <div style="margin-top:10px;">
-                    <el-cascader v-if="user.userNameNeedTranslate != 1" :size="'small'" v-model="deptIdForNoReport" :placeholder="$t('qing-xuan-ze-bu-men')" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 200px;" @change="showReportTimeLessThanCardTimeList()"></el-cascader>
+                    <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>
@@ -2296,6 +2296,8 @@
         },
         data() {
             return {
+                notFullData:[],
+                notFullOriginList:[],
                 singleDate:1,
                 subFillProjectList:[],
                 curAuditNode: 1,
@@ -2765,6 +2767,7 @@
                     if (res.code == "ok") {
                         this.tbload = false
                         this.notFullData = res.data;
+                        this.notFullOriginList = res.data;
                     }
                     },
                     (error) => {
@@ -3458,12 +3461,11 @@
                     }
                 } else if (e == 2) {
                     this.monthWorkDataS1 = []
-                    for (let i = 0; i < this.notFullData.length; i++) {
-                        if(this.notFullData[i].name.indexOf(this.searchKeyword) != -1){
-                            this.monthWorkDataS1.push(this.notFullData[i])
+                    for (let i = 0; i < this.notFullOriginList.length; i++) {
+                        if(this.notFullOriginList[i].name.indexOf(this.searchKeyword) != -1){
+                            this.monthWorkDataS1.push(this.notFullOriginList[i])
                         }
                     }
-                    console.log(this.monthWorkDataS1);
                     if (this.monthWorkDataS1.length > 50) {
                         this.notFullData = this.monthWorkDataS1.slice(0,50);
                     }else{