浏览代码

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

zhouyy 4 月之前
父节点
当前提交
491e748e0d
共有 39 个文件被更改,包括 1249 次插入148 次删除
  1. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/package.json
  2. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/kehuhz.png
  3. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitdingdan.png
  4. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitjer.png
  5. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitkehu.png
  6. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitlianxir.png
  7. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitlishi.png
  8. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitshangji.png
  9. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitxianshuo.png
  10. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/shangjihz.png
  11. 二进制
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/xiansuohz.png
  12. 5 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/pullDownSelector.vue
  13. 64 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/dataView/reRcharts.vue
  14. 5 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js
  15. 4 4
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleList/moduleList.vue
  16. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/businessInfo.vue
  17. 4 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/customerInfo.vue
  18. 4 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/newAndModifiedRelatedProducts.vue
  19. 3 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/threadInfo.vue
  20. 146 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/businessEcharts.vue
  21. 111 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/dataAnalysis.vue
  22. 165 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/dataSummary.vue
  23. 176 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/filterItem.vue
  24. 184 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/salesBriefings.vue
  25. 23 4
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/workbench.vue
  26. 0 9
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/index.vue
  27. 7 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/addEditorVisitor.vue
  28. 45 9
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/visitorDetails.vue
  29. 14 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/utility/defaultData.js
  30. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/vite.config.js
  31. 20 0
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/yarn.lock
  32. 12 8
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectApprovalController.java
  33. 12 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectApproval.java
  34. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectApprovalService.java
  35. 37 8
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectApprovalServiceImpl.java
  36. 5 1
      fhKeeper/formulahousekeeper/timesheet/src/components/selectPersonnel.vue
  37. 5 1
      fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue
  38. 45 41
      fhKeeper/formulahousekeeper/timesheet/src/views/project/info.vue
  39. 148 42
      fhKeeper/formulahousekeeper/timesheet/src/views/projectApproval/projectApproval.vue

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

@@ -13,6 +13,7 @@
   "dependencies": {
     "axios": "^1.6.7",
     "dayjs": "^1.11.13",
+    "echarts": "^5.5.1",
     "pinia": "^2.1.7",
     "pinia-plugin-persist": "^1.0.0",
     "vant": "^4.5.0",

二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/kehuhz.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitdingdan.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitjer.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitkehu.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitlianxir.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitlishi.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitshangji.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/salesKitxianshuo.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/shangjihz.png


二进制
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/xiansuohz.png


+ 5 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/pullDownSelector.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="w-full h-full flex flex-col">
-    <div class="w-full pt-2">
+    <div class="w-full pt-2 searchKeywords">
       <van-search v-model.trim="searchForValue" shape="round" placeholder="请输入搜索关键词"
-        @update:model-value="debouncedSearchOptions" />
+        @update:model-value="debouncedSearchOptions" input-align="left" />
     </div>
     <div class="flex-1 my-2 overflow-y-auto">
       <template v-if="renderingOptions.length == 1 && renderingOptions[0] && !renderingOptions[0].label">
@@ -187,3 +187,6 @@ onMounted(() => {
   }
 });
 </script>
+
+<style lang="scss" scoped>
+</style>

+ 64 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/dataView/reRcharts.vue

@@ -0,0 +1,64 @@
+<script setup lang="ts">
+import { ECharts, EChartsOption, init } from 'echarts';
+import { ref, watch, onMounted, onBeforeUnmount } from 'vue';
+
+const props = defineProps({
+  width: {
+    type: String,
+    default: '100%'
+  },
+  height: {
+    type: String,
+    default: '100%'
+  },
+  option: {
+    type: Object,
+    default: () => ({})
+  }
+});
+
+const myChartsRef = ref();
+let myChart;
+let timer;
+
+// 初始化echarts
+const initChart = () => {
+  if (myChart !== undefined) {
+    myChart.dispose();
+  }
+  myChart = init(myChartsRef.value);
+  // 拿到option配置项,渲染echarts
+  myChart?.setOption(props.option, true);
+  resizeChart()
+};
+// 重新渲染echarts
+const resizeChart = () => {
+  timer = setTimeout(() => {
+    if (myChart) {
+      myChart.resize();
+    }
+  }, 500);
+};
+
+onMounted(() => {
+  initChart();
+  window.addEventListener('resize', resizeChart);
+});
+
+onBeforeUnmount(() => {
+  window.removeEventListener('resize', resizeChart);
+  clearTimeout(timer);
+  timer = null;
+});
+
+watch(() => props.option, () => {
+  initChart();
+}, {
+  deep: true
+}
+);
+</script>
+
+<template>
+  <div ref="myChartsRef" :style="{ height: height, width: width }" :option="option"></div>
+</template>

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

@@ -99,4 +99,8 @@ export const TOP_DATA_OF_CONTRACT_LIST = `/contract/pageContractByPin` // 合同
 
 export const SALES_ORDER_TOP_PLACEMENT = `/order/pinOrder` // 销售订单顶置
 export const CANCEL_THE_TOP_PLACEMENT_OF_THE_SALES_ORDER = `/order/undoPin` // 取消顶置
-export const TOP_DATA_OF_SALES_ORDER_LIST = `/order/pageOrderByPin` // 销售订单列表顶置数据
+export const TOP_DATA_OF_SALES_ORDER_LIST = `/order/pageOrderByPin` // 销售订单列表顶置数据
+
+export const GET_SALES_BRIEFINGS = `/order/salesKit` // 获取销售简报
+export const OBTAIN_DATA_SUMMARY = `/order/dataSummary` // 获取数据汇总
+export const STAGE_OF_OBTAINING_BUSINESS_OPPORTUNITIES = `/order/businessOpportunityStage` // 获取商机阶段

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

@@ -500,13 +500,13 @@ useLifecycle({
     router.on('moduleListDetailParameter', (data) => {
       reloadListData(data)
     })
+
+    router.eventOn('moduleListRefreshData', (data) => {
+      onRefresh(true)
+    })
   }
 });
 
-router.eventOn('moduleListRefreshData', (data) => {
-  onRefresh(true)
-})
-
 </script>
 
 <style lang='scss' scoped>

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/businessInfo.vue

@@ -60,6 +60,7 @@
 
 <script setup>
 import { ref } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { BUSINESS_OPPORTUNITY_TRANSFER, GET_CONTACTS_WITH_MORE_I_DS, CONTACT_PERSON_ASSOCIATED_WITH_BUSINESS_OPPORTUNITY } from '@hooks/useApi'
 import requests from "@common/requests";

+ 4 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/customerInfo.vue

@@ -3,7 +3,7 @@
     <div class="bg-white info flex-1 overflow-y-auto cellnormall">
       <van-cell title="客户名称" :value="info.customName" />
       <van-cell title="客户来源" :value="info.customSourceValue" />
-      <van-cell title="电话号码" :value="info.telPhone" />
+      <van-cell title="电话号码" :value="info.companyPhone" />
       <van-cell title="邮箱" :value="info.email" />
       <van-cell title="客户行业" :value="info.customerIndustryValue" />
       <van-cell title="客户级别" :value="info.customerLevelValue" />
@@ -44,6 +44,7 @@
 import { ref } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { TRANSFER_CUSTOMERS } from '@hooks/useApi'
+import { showConfirmDialog } from 'vant';
 import requests from "@common/requests";
 import useShowToast from '@hooks/useToast'
 import useInfoStore from '@store/useInfoStore'
@@ -81,12 +82,12 @@ function confirmTransfer() {
 function claimAndClaim() {
   showConfirmDialog({
     title: '认领客户',
-    message: `确定认领【${props.info.name}】客户吗?`,
+    message: `确定认领【${props.info.customName}】客户吗?`,
   }).then(() => {
     requests.post(TRANSFER_CUSTOMERS, { ids: props.info.id, inchargerId: userInfo.userInfo.id }).then((res) => {
       toastSuccess('认领成功')
       listReloadData()
-      props.info.inchargerName = userInfo.userInfo.name
+      props.info.inchargerName = userInfo.userInfo.customName
       showDialog.value = false
     })
   })

+ 4 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/newAndModifiedRelatedProducts.vue

@@ -11,7 +11,6 @@
       v-model="form.productId"
       is-link
       readonly
-      required
       name="productId"
       label="产品名称"
       placeholder="请选择"
@@ -26,7 +25,7 @@
       readonly
       name="productType"
       label="产品类型"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置类型'"
     ></van-field>
     <van-field
       class="resetStyles"
@@ -34,7 +33,7 @@
       readonly
       name="unit"
       label="单位"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置单位'"
     ></van-field>
     <van-field
       class="resetStyles"
@@ -43,7 +42,7 @@
       readonly
       name="price"
       label="标准价格"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置标准价格'"
     ></van-field>
     <van-field
       class="resetStyles"
@@ -52,7 +51,7 @@
       readonly
       name="inventory"
       label="库存"
-      placeholder="请先选择产品"
+      :placeholder="!form.productId ? '请先选择产品' : '该产品未设置标准库存'"
     ></van-field>
     <van-field
       class="resetStyles"

+ 3 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/threadInfo.vue

@@ -40,6 +40,7 @@
 
 <script setup>
 import { ref } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { TRANSFER_CLUES } from '@hooks/useApi'
 import requests from "@common/requests";
@@ -86,12 +87,12 @@ function confirmTransfer() {
 function claimAndClaim() {
   showConfirmDialog({
     title: '认领线索',
-    message: `确定认领【${props.info.name}】线索吗?`,
+    message: `确定认领【${props.info.clueName}】线索吗?`,
   }).then(() => {
     requests.post(TRANSFER_CLUES, { ids: props.info.id, inchargerId: userInfo.userInfo.id }).then((res) => {
       toastSuccess('认领成功')
       listReloadData()
-      props.info.inchargerName = userInfo.userInfo.name
+      props.info.inchargerName = userInfo.userInfo.clueName
       showDialog.value = false
     })
   })

+ 146 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/businessEcharts.vue

@@ -0,0 +1,146 @@
+<template>
+  <div class="businessOpportunityStage box mt-4">
+    <div class="box-title">
+      <div class="box-title-left text-size-in">商机阶段</div>
+      <div class="box-title-right text-size-small" @click="showPopUpLayer()">
+        {{ scopeText }}/{{ dateText }}
+        <van-icon name="play" class="ml-2 rotate-90" color="#747474" />
+      </div>
+    </div>
+
+    <div class="content w-full overflow-hidden transitionEffect"
+      :style="`height: ${expandAndCollapse ? usePxToVwView(echartsHeight) : '0'}`">
+      <ReRcharts :option="echartsOption" />
+    </div>
+
+    <div class="w-full flex justify-center mt-2" @click="expandAndCollapseSwitch()">
+      <van-icon name="arrow-up" color="#AFAFAF" :class="`${!expandAndCollapse && 'rotate-180'} transitionEffect`" />
+    </div>
+
+    <van-popup v-model:show="filterCriteriaPopUpLayerFlag" position="bottom" :style="{ height: '100%' }" closeable>
+      <FilterItem :dataFilters="filterCriteria" @submit="FilterItemSubmit" />
+    </van-popup>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue';
+import { useLifecycle } from '@hooks/useCommon.js';
+import { STAGE_OF_OBTAINING_BUSINESS_OPPORTUNITIES } from '@hooks/useApi.js';
+import { fixedFieldPermissionOptions, fixedFieldDateOptions } from '@utility/defaultData.js';
+import requests from "@common/requests"
+import usePxToVwView from "@hooks/usePxTransform.js";
+import ReRcharts from '@components/dataView/reRcharts.vue';
+import FilterItem from './filterItem.vue';
+
+const filterCriteriaPopUpLayerFlag = ref(false);
+const filterCriteria = ref({
+  scopeSelection: 0,
+  dateSelection: 0,
+  customTime: []
+})
+const expandAndCollapse = ref(true);
+const echartsHeight = ref(140)
+const echartsOption = ref({})
+
+const scopeText = computed(() => {
+  return fixedFieldPermissionOptions[filterCriteria.value.scopeSelection].label
+})
+
+const dateText = computed(() => {
+  if(filterCriteria.value.dateSelection == -1) {
+    const { customTime = [] } = filterCriteria.value
+    return ` ${customTime[0]} 至 ${customTime[1]}`
+  }
+  
+  return fixedFieldDateOptions[filterCriteria.value.dateSelection].label
+})
+
+function FilterItemSubmit(val) {
+  filterCriteria.value = val
+
+  filterCriteriaPopUpLayerFlag.value = false;
+  getEchartsData()
+}
+
+function showPopUpLayer() {
+  filterCriteriaPopUpLayerFlag.value = true;
+}
+
+function expandAndCollapseSwitch() {
+  expandAndCollapse.value = !expandAndCollapse.value;
+}
+
+function processChartData(yAxisData = [], seriesData = []) {
+  const dataLength = yAxisData.length
+  if(dataLength > 3) {
+    echartsHeight.value = dataLength * 38
+  }
+  echartsOption.value = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      show: false
+    },
+    grid: {
+      top: usePxToVwView(60),
+      left: usePxToVwView(250),
+      right: usePxToVwView(60),
+      bottom: usePxToVwView(100),
+    },
+    xAxis: {
+      type: 'value',
+      axisLabel: {
+        fontSize: usePxToVwView(12),
+      }
+    },
+    yAxis: {
+      type: 'category',
+      data: yAxisData,
+      axisLabel: {
+        fontSize: usePxToVwView(14),
+      }
+    },
+    series: [
+      {
+        name: '2011',
+        type: 'bar',
+        data: seriesData,
+        barWidth: usePxToVwView(80),
+      },
+    ]
+  }
+}
+
+function getEchartsData() {
+  const { scopeSelection = 0, dateSelection = 0, customTime = [] } = filterCriteria.value
+  const formVal = {
+    queryType: scopeSelection,
+    ...(dateSelection !== -1 ? { dateType: dateSelection } : { startDate: customTime[0], endDate: customTime[1] })
+  }
+  requests.post(STAGE_OF_OBTAINING_BUSINESS_OPPORTUNITIES, {
+    ...formVal
+  }).then((res) => {
+    const yAxisData = (res.data?.dataMap || []).map(item => item.stageName);
+    const seriesData = (res.data?.dataMap || []).map(item => item.num);
+    processChartData(yAxisData, seriesData)
+  })
+}
+
+useLifecycle({
+  load: () => {
+    getEchartsData()
+  },
+  init: () => {
+    getEchartsData()
+  }
+});
+</script>
+
+<style lang='scss' scoped>
+/* 样式代码 */
+</style>

+ 111 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/dataAnalysis.vue

@@ -1,18 +1,126 @@
 <template>
-  <div>数据统计</div>
+  <div class="dataAnalysis">
+    <!-- 销售简报 -->
+    <SalesBriefings />
+
+    <!-- 数据汇总 -->
+    <DataSummary />
+
+    <!-- 商机阶段 -->
+    <BusinessEcharts />
+  </div>
 </template>
 
 <script setup>
 import { ref } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
+import requests from "@common/requests"
+
+import SalesBriefings from './salesBriefings.vue';
+import DataSummary from './dataSummary.vue';
+import BusinessEcharts from './businessEcharts.vue'
 
 useLifecycle({
   load: () => {
     // 添加加载逻辑
+  },
+  init: () => {
   }
 });
 </script>
 
-<style lang='scss' scoped>
-  /* 样式代码 */
+<style lang='scss'>
+/* 样式代码 */
+.dataAnalysis {
+  margin: 20px 0 16px 0;
+  padding: 0 16px;
+
+  .transitionEffect {
+    transition: all .5s ease-in-out;
+  }
+
+  .salesKit {
+    .content {
+      width: 100%;
+
+      .item {
+        width: 50%;
+        display: flex;
+        margin-top: 20px;
+
+        .item-img {
+          width: 54px;
+          height: 54px;
+          margin-right: 6px;
+        }
+      }
+    }
+  }
+
+  .dataSummary {
+    .data-item {
+      padding: 15px;
+      border-radius: 6px;
+      margin-top: 16px;
+
+      .kehu-img {
+        width: 21px;
+        height: 22px;
+        margin-right: 12.5px;
+      }
+
+      .businessOpportunity-img {
+        width: 23px;
+        height: 23px;
+        margin-right: 12px;
+      }
+
+      .xiansuo-img {
+        width: 23px;
+        height: 23px;
+        margin-right: 12px;
+      }
+    }
+  }
+
+  .businessOpportunityStage {}
+
+  .box {
+    background: #fff;
+    border-radius: 10px;
+    padding: 6px 16px 6px 16px;
+
+    .box-title {
+      height: 40px;
+      border-bottom: 1px solid #E5E4EE;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      position: relative;
+
+      .box-title-left {
+        padding-left: 10px;
+        color: #0E1012;
+
+        &::after {
+          content: '';
+          width: 2px;
+          border-radius: 10px;
+          background: #075985;
+          height: 18px;
+          position: absolute;
+          left: 0;
+          top: 50%;
+          transform: translateY(-50%);
+        }
+      }
+
+      .box-title-right {
+        color: #747474;
+        display: flex;
+        align-items: center;
+      }
+    }
+  }
+}
 </style>

+ 165 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/dataSummary.vue

@@ -0,0 +1,165 @@
+<template>
+  <div class="dataSummary box mt-4">
+    <div class="box-title">
+      <div class="box-title-left text-size-in">数据汇总</div>
+      <div class="box-title-right text-size-small" @click="showPopUpLayer()">
+        {{ scopeText }}/{{ dateText }}
+        <van-icon name="play" class="ml-2 rotate-90" color="#747474" />
+      </div>
+    </div>
+
+    <div class="content w-full overflow-hidden transitionEffect"
+      :style="`height: ${expandAndCollapse ? usePxToVwView(313) : '0'}`">
+      <div class="data-item flex flex-row bg-[#F8F8FA]">
+        <img src="/src/assets/image/kehuhz.png" class="kehu-img">
+        <div class="flex-1">
+          <div class="font-bold text-[#000]">客户汇总</div>
+          <div class="flex mt-2">
+            <div class="text-size-small text-[#999]" style="width: 40%">
+              新增客户 <span class="ml-1 text-[#FFBD27]">
+                {{ dataSummary?.customDataSummary?.newNum || 0 }}
+              </span> 人
+            </div>
+            <div class="text-size-small text-[#999]" style="width: 60%">
+              转成交客户 <span class="ml-1 text-[#FFBD27]">
+                {{ dataSummary?.closeDealNum?.newNum || 0 }}
+              </span> 人
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-item flex flex-row bg-[#F8F8FA]">
+        <img src="/src/assets/image/shangjihz.png" class="businessOpportunity-img">
+        <div class="flex-1">
+          <div class="font-bold text-[#000]">商机汇总</div>
+          <div class="flex mt-2">
+            <div class="text-size-small text-[#999]" style="width: 40%;">
+              新增商机 <span class="ml-1 text-[#51C2FF]">
+                {{ dataSummary?.businessOpportunityDataSummary?.newNum || 0 }}
+              </span> 人
+            </div>
+            <div class="text-size-small text-[#999]" style="width: 60%;">
+              商机赢单 <span class="ml-1 text-[#51C2FF]">
+                {{ dataSummary?.businessOpportunityDataSummary?.losting || 0 }}
+              </span> 个
+            </div>
+          </div>
+          <div class="flex mt-2">
+            <div class="text-size-small text-[#999]" style="width: 40%;">
+              输单商机 <span class="ml-1 text-[#51C2FF]">
+                {{ dataSummary?.businessOpportunityDataSummary?.winning || 0 }}
+              </span> 人
+            </div>
+            <div class="text-size-small text-[#999]" style="width: 60%;">
+              商机总金额 <span class="ml-1 text-[#51C2FF]">
+                {{ dataSummary?.businessOpportunityDataSummary?.allAmountOfMoney || 0 }}
+              </span> 元
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="data-item flex flex-row bg-[#F8F8FA]">
+        <img src="/src/assets/image/xiansuohz.png" class="xiansuo-img">
+        <div class="flex-1">
+          <div class="font-bold text-[#000]">线索汇总</div>
+          <div class="flex mt-2">
+            <div class="w-1/2 text-size-small text-[#999]">
+              新增线索 <span class="ml-1 text-[#28C67E]">
+                {{ dataSummary?.clueDataSummary?.newNum || 0 }}
+              </span> 人
+            </div>
+            <div class="w-1/2 text-size-small text-[#999]">
+              线索转商机 <span class="ml-1 text-[#28C67E]">
+                {{ dataSummary?.clueDataSummary?.changeNum || 0 }}
+              </span> 人
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="w-full flex justify-center mt-2" @click="expandAndCollapseSwitch()">
+      <van-icon name="arrow-up" color="#AFAFAF"
+        :class="`${!expandAndCollapse && 'rotate-180'} transitionEffect`" />
+    </div>
+
+    <van-popup v-model:show="filterCriteriaPopUpLayerFlag" position="bottom" :style="{ height: '100%' }" closeable>
+      <FilterItem :dataFilters="filterCriteria" @submit="FilterItemSubmit" />
+    </van-popup>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue';
+import { useLifecycle } from '@hooks/useCommon.js';
+import { OBTAIN_DATA_SUMMARY } from '@hooks/useApi.js';
+import { fixedFieldPermissionOptions, fixedFieldDateOptions } from '@utility/defaultData.js';
+import requests from "@common/requests"
+import usePxToVwView from "@hooks/usePxTransform.js";
+import FilterItem from './filterItem.vue';
+
+const filterCriteriaPopUpLayerFlag = ref(false);
+const expandAndCollapse = ref(true);
+const dataSummary = ref({});
+const filterCriteria = ref({
+  scopeSelection: 0,
+  dateSelection: 0,
+  customTime: []
+})
+
+const scopeText = computed(() => {
+  return fixedFieldPermissionOptions[filterCriteria.value.scopeSelection].label
+})
+
+const dateText = computed(() => {
+  if(filterCriteria.value.dateSelection == -1) {
+    const { customTime = [] } = filterCriteria.value
+    return ` ${customTime[0]} 至 ${customTime[1]}`
+  }
+  
+  return fixedFieldDateOptions[filterCriteria.value.dateSelection].label
+})
+
+function FilterItemSubmit(val) {
+  filterCriteria.value = val
+
+  filterCriteriaPopUpLayerFlag.value = false;
+  obtainDataSummary()
+}
+
+function showPopUpLayer() {
+  filterCriteriaPopUpLayerFlag.value = true;
+}
+
+function expandAndCollapseSwitch() {
+  expandAndCollapse.value = !expandAndCollapse.value;
+}
+
+function obtainDataSummary() {
+  const { scopeSelection = 0, dateSelection = 0, customTime = [] } = filterCriteria.value
+  const formVal = {
+    queryType: scopeSelection,
+    ...(dateSelection !== -1 ? { dateType: dateSelection } : { startDate: customTime[0], endDate: customTime[1] })
+  }
+  requests.post(OBTAIN_DATA_SUMMARY, {
+    ...formVal
+  }).then((res) => {
+    dataSummary.value = res.data
+  })
+}
+
+useLifecycle({
+  load: () => {
+    obtainDataSummary()
+  },
+  init: () => {
+    obtainDataSummary()
+  }
+});
+</script>
+
+<style lang='scss' scoped>
+/* 样式代码 */
+</style>

+ 176 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/filterItem.vue

@@ -0,0 +1,176 @@
+<template>
+  <div class="filterCriteria">
+    <div class="flex-1 overflow-x-auto">
+      <div class="filterCriteria-title">范围选择</div>
+      <div class="flex flex-wrap">
+        <template v-for="(item, index) in fixedFieldPermissionOptions">
+          <div :class="`${dataFilter.scopeSelection == item.value && 'selected'} item item-special`"
+            @click="scopeSelectionCli(item)">{{ item.label }}</div>
+        </template>
+      </div>
+      <div class="filterCriteria-title">时间选择</div>
+      <div class="flex flex-wrap">
+        <template v-for="(item, index) in fixedFieldDateOptions">
+          <div :class="`${dataFilter.dateSelection == item.value && 'selected'} item`" @click="timeSelectionCli(item)">
+            {{ item.label }}</div>
+        </template>
+      </div>
+
+      <template v-if="dataFilter.dateSelection == -1">
+        <div class="filterCriteria-title">日期选择</div>
+        <div class="dateSelection flex justify-between flex-row items-center mb-4">
+          <div class="mr-6">开始日期</div>
+          <div class="dateItem flex-1" @click="showDate(0)">
+            <div>{{ dataFilter.customTime[0] ? dataFilter.customTime[0] : '请选择' }}</div>
+            <van-icon name="arrow" />
+          </div>
+        </div>
+        <div class="dateSelection flex justify-between flex-row items-center">
+          <div class="mr-6">结束日期</div>
+          <div class="dateItem flex-1" @click="showDate(1)">
+            <div>{{ dataFilter.customTime[1] ? dataFilter.customTime[1] : '请选择' }}</div>
+            <van-icon name="arrow" />
+          </div>
+        </div>
+      </template>
+    </div>
+
+    <van-button type="primary" class=" mt-6 mb-12 w-full" @click="submitSave">确定</van-button>
+
+    <van-popup v-model:show="showPicker" destroy-on-close position="bottom" :style="{ height: '50%' }">
+      <van-date-picker v-model="current" :min-date="minDate" :max-date="maxDate" @confirm="showPickerConfirm"
+        @cancel="showPicker = false" />
+    </van-popup>
+  </div>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue';
+import { defineProps, defineEmits } from 'vue'
+import { useLifecycle } from '@hooks/useCommon.js';
+import { fixedFieldPermissionOptions, fixedFieldDateOptions } from '@utility/defaultData.js';
+import dayjs from 'dayjs';
+import useShowToast from "@hooks/useToast";
+
+const { toastText } = useShowToast();
+const emit = defineEmits()
+const props = defineProps({
+  dataFilters: {
+    typeof: Object,
+    default: () => ({})
+  }
+})
+
+const minDate = ref(new Date(dayjs().add(-2, 'year')))
+const maxDate = ref(new Date(dayjs().add(2, 'year')))
+const showPicker = ref(false)
+const current = ref([])
+const dateFiledIndex = ref(0)
+const dataFilter = ref({
+  scopeSelection: 0,
+  dateSelection: 0,
+  customTime: []
+})
+
+watch(() => props.dataFilters, (newValue) => {
+  dataFilter.value = newValue
+})
+
+function submitSave() {
+  const { dateSelection, customTime = [] } = dataFilter.value
+  if(dateSelection == -1 && customTime.length == 0) {
+    toastText('请选择日期', 1000)
+    return
+  }
+  emit('submit', dataFilter.value)
+}
+function showPickerConfirm({ selectedValues }) {
+  dataFilter.value.customTime[dateFiledIndex.value] = selectedValues.join('-')
+  showPicker.value = false
+}
+
+function showDate(index) {
+  if (index == 0) {
+    maxDate.value = dataFilter.value.customTime[1] ? new Date(dataFilter.value.customTime[1]) : new Date(dayjs().add(2, 'year'))
+  }
+
+  if (index == 1) {
+    minDate.value = dataFilter.value.customTime[0] ? new Date(dataFilter.value.customTime[0]) : new Date(dayjs().add(-2, 'year'))
+  }
+  const dateVal = dataFilter.value.customTime[index] || '';
+  const todaySDate = dayjs().format("YYYY-MM-DD");
+  current.value = dateVal ? dateVal.split("-") : todaySDate.split("-");
+  dateFiledIndex.value = index
+  showPicker.value = true;
+}
+
+function scopeSelectionCli(item) {
+  dataFilter.value.scopeSelection = item.value
+}
+
+function timeSelectionCli(item) {
+  dataFilter.value.dateSelection = item.value
+  if(item.value == -1) {
+    dataFilter.value.customTime = []
+  }
+}
+
+useLifecycle({
+  load: () => {
+    // 添加加载逻辑
+  }
+});
+</script>
+
+<style lang='scss' scoped>
+.filterCriteria {
+  padding: 14px 0;
+  margin: 0 20px;
+  position: relative;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+
+  .filterCriteria-title {
+    font-size: 18px;
+    color: #474A56;
+    margin-bottom: 20px;
+  }
+
+  .item {
+    width: 98px;
+    text-align: center;
+    padding: 10px 0;
+    color: #000000;
+    border: 1px solid #F8F8FA;
+    border-radius: 6px;
+    background: #F8F8FA;
+    margin-right: 20px;
+    margin-bottom: 20px;
+
+    &:nth-child(3n) {
+      margin-right: 0;
+    }
+  }
+
+  .item-special:last-child {
+    width: 160px;
+  }
+
+  .selected {
+    border-color: $themeColor;
+    color: $themeColor;
+  }
+
+  .dateSelection {
+    .dateItem {
+      border-radius: 6px;
+      background: #F8F8FA;
+      padding: 10px 14px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+  }
+}
+</style>

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

@@ -0,0 +1,184 @@
+<template>
+  <div class="salesKit box">
+    <div class="box-title">
+      <div class="box-title-left text-size-in">销售简报</div>
+      <div class="box-title-right text-size-small" @click="showPopUpLayer()">
+        {{ scopeText }}/{{ dateText }}
+        <van-icon name="play" class="ml-2 rotate-90" color="#747474" />
+      </div>
+    </div>
+
+    <div class="content overflow-hidden transitionEffect"
+      :style="`height: ${expandAndCollapse ? usePxToVwView(298) : '0'}`">
+      <div class="flex items-center w-full">
+        <div class="item">
+          <img src="/src/assets/image/salesKitkehu.png" class="item-img" />
+          <div class="flex flex-col justify-center text=[#999999]">
+            <div>新增客户</div>
+            <div class="flex items-end">
+              <span class="text-[#3C84F3] text-size-in font-bold mr-1">
+                {{ salesBriefings?.custom?.customCount || 0 }}
+              </span>人
+            </div>
+          </div>
+        </div>
+        <div class="item">
+          <img src="/src/assets/image/salesKitlianxir.png" class="item-img" />
+          <div class="flex flex-col justify-center text=[#999999]">
+            <div>新增联系人</div>
+            <div class="flex items-end">
+              <span class="text-[#42DC9E] text-size-in font-bold mr-1">
+                {{ salesBriefings?.contacts?.contactsCount || 0 }}
+              </span>人
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="flex items-center w-full">
+        <div class="item">
+          <img src="/src/assets/image/salesKitlishi.png" class="item-img" />
+          <div class="flex flex-col justify-center text=[#999999]">
+            <div>新增商机</div>
+            <div class="flex items-end">
+              <span class="text-[#F3893C] text-size-in font-bold mr-1">
+                {{ salesBriefings?.businessOpportunity?.businessOpportunityCount || 0 }}
+              </span>人
+            </div>
+          </div>
+        </div>
+        <div class="item">
+          <img src="/src/assets/image/salesKitdingdan.png" class="item-img" />
+          <div class="flex flex-col justify-center text=[#999999]">
+            <div>新增销售订单</div>
+            <div class="flex items-end">
+              <span class="text-[#A66AFF] text-size-in font-bold mr-1">
+                {{ salesBriefings?.salesOrder?.salesOrderCount || 0 }}
+              </span>人
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="flex items-center w-full">
+        <div class="item">
+          <img src="/src/assets/image/salesKitjer.png" class="item-img" />
+          <div class="flex flex-col justify-center text=[#999999]">
+            <div>销售订单金额</div>
+            <div class="flex items-end">
+              <span class="text-[#67DF2A] text-size-in font-bold mr-1">
+                {{ salesBriefings?.salesOrdersPrice?.salesOrdersPriceCount || 0 }}
+              </span>人
+            </div>
+          </div>
+        </div>
+        <div class="item">
+          <img src="/src/assets/image/salesKitshangji.png" class="item-img" />
+          <div class="flex flex-col justify-center text=[#999999]">
+            <div>商机金额</div>
+            <div class="flex items-end">
+              <span class="text-[#EED116] text-size-in font-bold mr-1">
+                {{ salesBriefings?.businessOpportunityPrice?.businessOpportunityPriceCount || 0 }}
+              </span>人
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="flex items-center w-full">
+        <div class="item">
+          <img src="/src/assets/image/salesKitxianshuo.png" class="item-img" />
+          <div class="flex flex-col justify-center text=[#999999]">
+            <div>新增线索</div>
+            <div class="flex items-end">
+              <span class="text-[#F44873] text-size-in font-bold mr-1">
+                {{ salesBriefings?.clue?.clueCount || 0 }}
+              </span>人
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="w-full flex justify-center mt-2" @click="expandAndCollapseSwitch()">
+      <van-icon name="arrow-up" color="#AFAFAF" :class="`${!expandAndCollapse && 'rotate-180'} transitionEffect`" />
+    </div>
+    <van-popup v-model:show="filterCriteriaPopUpLayerFlag" position="bottom" :style="{ height: '100%' }" closeable>
+      <FilterItem :dataFilters="filterCriteria" @submit="FilterItemSubmit" />
+    </van-popup>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue';
+import { useLifecycle } from '@hooks/useCommon.js';
+import { GET_SALES_BRIEFINGS } from '@hooks/useApi.js';
+import { fixedFieldPermissionOptions, fixedFieldDateOptions } from '@utility/defaultData.js';
+
+import requests from "@common/requests"
+import usePxToVwView from "@hooks/usePxTransform.js";
+import FilterItem from './filterItem.vue';
+
+const filterCriteriaPopUpLayerFlag = ref(false);
+const expandAndCollapse = ref(true);
+const salesBriefings = ref({});
+const filterCriteria = ref({
+  scopeSelection: 0,
+  dateSelection: 0,
+  customTime: []
+})
+
+const scopeText = computed(() => {
+  return fixedFieldPermissionOptions[filterCriteria.value.scopeSelection].label
+})
+
+const dateText = computed(() => {
+  if(filterCriteria.value.dateSelection == -1) {
+    const { customTime = [] } = filterCriteria.value
+    return ` ${customTime[0]} 至 ${customTime[1]}`
+  }
+  
+  return fixedFieldDateOptions[filterCriteria.value.dateSelection].label
+})
+
+function FilterItemSubmit(val) {
+  filterCriteria.value = val
+
+  filterCriteriaPopUpLayerFlag.value = false;
+  getData()
+}
+
+function expandAndCollapseSwitch() {
+  expandAndCollapse.value = !expandAndCollapse.value;
+}
+
+function showPopUpLayer() {
+  filterCriteriaPopUpLayerFlag.value = true;
+}
+
+function getData() {
+  const { scopeSelection = 0, dateSelection = 0, customTime = [] } = filterCriteria.value
+  const formVal = {
+    queryType: scopeSelection,
+    ...(dateSelection !== -1 ? { dateType: dateSelection } : { startDate: customTime[0], endDate: customTime[1] })
+  }
+  requests.post(GET_SALES_BRIEFINGS, {
+    ...formVal
+  }).then((res) => {
+    salesBriefings.value = res.data
+  })
+}
+
+useLifecycle({
+  load: () => {
+    getData()
+  },
+  init: () => {
+    getData()
+  }
+});
+</script>
+
+<style lang='scss' scoped>
+/* 样式代码 */
+</style>

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

@@ -6,7 +6,7 @@
         :show-title="false" :show-mark="false" :poppable="false" :show-confirm="false" :row-height="'3rem'"
         :min-date="minDate"
         :style="{ borderRadius: '0.3rem', height: expandAndCollapse ? (calendarHeight ? calendarHeight + 'px' : 'auto') : usePxToVwView(140) }"
-        :formatter="formatter" @select="calendarSelect">
+        :formatter="formatter" @select="calendarSelect" @panel-change="calendarPanelChangeSet">
         <template #month-title></template>
         <template #bottom-info="day">
           <div class="doT" v-if="day?.bottomInfo"></div>
@@ -42,7 +42,8 @@
                   <div class="w-2/3 text-[#505050]" style="width: 62%;">拜访时间: {{ item.visitTime }}</div>
                   <div class="w-1/3 text-[#505050] flex items-center" style="width: 38%;">
                     <van-icon name="phone-o" class="text-size-in mr-2" />
-                    {{ item.telPhone }}
+                    <!-- {{ item.telPhone }} -->
+                    {{ item?.companyPhone }}
                   </div>
                 </div>
               </div>
@@ -78,7 +79,7 @@
       <div class="p16 pt-0 pb-0 flex justify-between overflow-x-auto">
         <div class="flex">
           <template v-for="item in commonModulesList">
-            <div class="w80 bg-[#FFA359] h-28 rounded-md flex flex-col items-center justify-center">
+            <div class="w80 bg-[#FFA359] h-28 rounded-md flex flex-col items-center justify-center" @click="jumpToAdd(item)">
               <div class="formImage">
                 <img class="w-full h-full" src="/src/assets/image/form.png">
               </div>
@@ -185,6 +186,23 @@ const commonExpressionsHaveBeenNodded = ref([])
 const areYouRequesting = ref(false)
 const displayFrequentlyUsedContacts = ref(false)
 
+function calendarPanelChangeSet(data) {
+  dateConditions.value = dayjs(data.date).format('YYYY-MM-DD')
+  getVisitorPlan()
+}
+
+function jumpToAdd(rows) {
+  const jumpTo = routingInfos[rows.path.replace('/', '')]
+  router.navigateTo({
+    pathName: 'addEditor',
+    success: () => {
+      router.emit('addEditorParameter', {
+        routerInfo: JSON.stringify(jumpTo)
+      })
+    }
+  })
+}
+
 function toContactDetails(item) {
   router.navigateTo({
     pathName: 'details',
@@ -266,7 +284,8 @@ function jumpToAddNewVisitors(row) {
     pathName: 'addEditorVisitor',
     success: () => {
       router.emit('addEditorVisitorParameter', {
-        row: JSON.stringify(row || {})
+        row: JSON.stringify(row || {}),
+        date: JSON.stringify(dateConditions.value || {})
       })
     }
   })

+ 0 - 9
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/index.vue

@@ -91,11 +91,7 @@ function obtainEnterpriseWeChatParameters(data = {}) {
   const token = data.id
   // const curUrl = window.location.href.split('home')[0]
   const curUrl = window.location.href
-  console.log(wx, '开始调用接口')
-  console.log(token, curUrl)
-  console.log(requests, '<==== requests')
   requests.post('/wxcorp/getCorpWXConfig', { url: curUrl, token }).then((res) => {
-    console.log(res, '<====== 返回的参数 /wxcorp/getCorpWXConfig')
     wx.config({
       beta: true,
       debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
@@ -118,19 +114,16 @@ function obtainEnterpriseWeChatParameters(data = {}) {
           signature: res.data.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
           jsApiList: ['selectExternalContact', 'openThirdAppServiceChat', 'openAppManage'], //必填,传入需要使用的接口名称
           success: function (result) {
-            console.log(result, '《+========== 成功1')
             //  wx.agentConfig成功回调后,WWOpenData 才会注入到 window 对象上面
             window.WWOpenData.bind(document.querySelector('ww-open-data'))
           },
           fail: function (res) {
-            console.log(res, '<===== 失败1')
             if (res.errMsg.indexOf('function not exist') > -1) {
               alert('版本过低请升级')
             }
           },
         })
       }).catch(err => {
-        console.log(err, '<===== 失败2')
         if (err.errMsg.indexOf('function not exist') > -1) {
           alert('版本过低请升级')
         }
@@ -141,7 +134,6 @@ function obtainEnterpriseWeChatParameters(data = {}) {
       // alert('wxConfig发生异常:'+JSON.stringify(res));
       // 企业第一次授权安装进入后会报not in reliable domain的错误,刷新后正常
       // location.reload();
-      console.log(res, '<===== 失败3')
     });
   }).catch(err => {
     alert(err);
@@ -153,7 +145,6 @@ useLifecycle({
 
   },
   init: () => {
-    console.log('执行一次')
     const currentEnvironment = navigator.userAgent.toLowerCase();
     const isCorpWX = currentEnvironment.indexOf("wxwork") > 0 ? true : false
     if(isCorpWX) {

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

@@ -2,6 +2,9 @@
   <Page :title="`${addOrEdit ? '编辑' : '新增'}访客计划`">
     <template v-slot:body>
       <div class="w-full h-full flex flex-col">
+        <div class="bg-[#EAEAEA] py-4 px-5" v-if="headDate">
+          {{ headDate }}
+        </div>
         <van-form
           ref="addEditFormRef"
           show-error
@@ -98,7 +101,6 @@
             name="remindTime"
             label="提醒时间"
             placeholder="请选择"
-            :disabled="addOrEdit"
             :rules="[{ required: true, message: '' }]"
             @click="showPickerClick('remindTime')"
           >
@@ -230,6 +232,7 @@ const currentTime = ref(dayjs(new Date()).format("HH:mm").split(":"));
 const dateSelectionFiled = ref("");
 const addOrEdit = ref(true); // true 编辑,false 新增
 const addOrEditRow = ref({})
+const headDate = ref('')
 
 function onSubmit() {
   addEditFormRef.value.validate().then((res) => {
@@ -291,7 +294,7 @@ function timeConfirm({ selectedValues }) {
 }
 
 function showPickerClick(filed) {
-  const dateTimeVal = form.value[filed] ? form.value[filed] : new Date()
+  const dateTimeVal = form.value[filed] ? form.value[filed] : headDate.value ? new Date(headDate.value) : new Date()
   dateSelectionValue.value = dayjs(dateTimeVal).format("YYYY-MM-DD").split("-")
   currentTime.value = dayjs(dateTimeVal).format("HH:mm").split(":")
   dateSelectionFiled.value = filed;
@@ -301,8 +304,10 @@ function showPickerClick(filed) {
 function processingDataSource(data) {
   const row = JSON.parse(data.row);
   addOrEdit.value = Object.keys(row).length > 0 ? true : false;
+  headDate.value = JSON.parse(data.date)
   addOrEditRow.value = row
   form.value = row
+  addEditFormRef.value?.resetValidation()
   obtainThePurposeOfTheVisit();
   getReminderTime();
   getAllCustomers();

+ 45 - 9
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/visitorDetails.vue

@@ -1,5 +1,8 @@
 <template>
   <Page title="访客计划详情">
+    <template v-slot:headerRight>
+      <div class="themeTextColor" v-if="detailedData.finishState == 0" @click="visitorEditor">编辑</div>
+    </template>
     <template v-slot:body>
       <!-- 头部 -->
       <div class="planDetailsHead">
@@ -14,7 +17,8 @@
         <div class="w-full flex items-center">
           <van-icon name="user-circle-o" class="text-size-in mr-2" />
           客户:
-          <div class="ml-2 themeTextColor decoration-auto underline">{{ detailedData.customName }}</div>
+          <div class="ml-2 themeTextColor decoration-auto underline" @click="jumpToCustomerDetails()">{{
+            detailedData.customName }}</div>
         </div>
       </div>
 
@@ -71,19 +75,14 @@
         <van-date-picker v-model="showDatePickerVal" @confirm="showPickerConfirm" @cancel="showDatePicker = false" />
       </van-popup>
 
-      <van-popup
-        v-model:show="timeShowPicker"
-        destroy-on-close
-        position="bottom"
-        :style="{ height: '50%' }"
-      >
+      <van-popup v-model:show="timeShowPicker" destroy-on-close position="bottom" :style="{ height: '50%' }">
         <van-time-picker v-model="currentTime" title="选择时间" @confirm="timeConfirm" />
       </van-popup>
     </template>
 
     <template v-slot:footer v-if="detailedData.finishState == 0">
       <div class="w-full flex justify-between layout">
-        <div class="footerBtnLeft layouts" @click="showContacts = true">
+        <div class="footerBtnLeft layouts" @click="showContactsCli()">
           <div class="imgClss"></div>
           联系人
         </div>
@@ -105,11 +104,12 @@
 import { ref } from "vue";
 import { showConfirmDialog } from 'vant';
 import { useLifecycle } from "@hooks/useCommon.js";
-import { OBTAIN_DETAILS_OF_THE_VISIT_PLAN, POSTPONE_THE_VISIT_PLAN, COMPLETE_THE_VISIT_PLAN } from "@hooks/useApi"
+import { OBTAIN_DETAILS_OF_THE_VISIT_PLAN, POSTPONE_THE_VISIT_PLAN, COMPLETE_THE_VISIT_PLAN, OBTAIN_CUSTOMER_DETAILS } from "@hooks/useApi"
 import useToast from "@hooks/useToast"
 import requests from "@common/requests";
 import useRouterStore from "@store/useRouterStore.js";
 import dayjs from "dayjs";
+import { routingInfos } from "@utility/generalVariables.js";
 import useFixedData from "@store/useFixedData.js";
 import PullDownSelector from "@components/common/pullDownSelector.vue";
 
@@ -125,6 +125,41 @@ const showDelayData = ref('')
 const currentTime = ref('')
 const contactList = ref([]);
 
+function visitorEditor() {
+  router.navigateTo({
+    pathName: 'addEditorVisitor',
+    success: () => {
+      router.emit('addEditorVisitorParameter', {
+        row: JSON.stringify(detailedData.value || {}),
+        date: JSON.stringify(detailedData.value.visitTime || {})
+      })
+    }
+  })
+}
+
+function jumpToCustomerDetails() {
+  const routerInfo = routingInfos['customer']
+  requests.post(OBTAIN_CUSTOMER_DETAILS, { id: detailedData.value.customId }).then(res => {
+    router.navigateTo({
+      pathName: 'details',
+      success: () => {
+        router.emit('detailParameter', {
+          routerInfo: JSON.stringify(routerInfo || {}),
+          parameter: JSON.stringify(res.data || {})
+        })
+      }
+    })
+  })
+}
+
+function showContactsCli() {
+  if(!((contactList.value || []).length)) {
+    toastText('该联系人无号码')
+    return
+  }
+  showContacts.value = true
+}
+
 function completeThePlan() {
   showConfirmDialog({
     title: `完成访客计划`,
@@ -141,6 +176,7 @@ function delayTimeEvent() {
   requests.post(POSTPONE_THE_VISIT_PLAN, { planId: detailedData.value.id, visitTime: showDelayData.value }).then(() => {
     toastSuccess(`操作成功`)
     getDetailData(detailedData.value)
+    showDelay.value = false
   })
 }
 

+ 14 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/utility/defaultData.js

@@ -57,4 +57,18 @@ export const fixedFieldPaymentStatus = [
   { value: 0, label: '未回款' },
   { value: 1, label: '已回款' },
   { value: 2, label: '已完全回款' },
+]
+
+export const fixedFieldPermissionOptions = [
+  { value: 0, label: '仅本人' },
+  { value: 1, label: '本人及下属' },
+  { value: 2, label: '仅本部门' },
+  { value: 3, label: '本部门及下属部门' },
+]
+
+export const fixedFieldDateOptions = [
+  { value: 0, label: '本月' },
+  { value: 1, label: '本周' },
+  { value: 2, label: '本年' },
+  { value: -1, label: '自定义' },
 ]

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/vite.config.js

@@ -5,8 +5,8 @@ import Components from "unplugin-vue-components/vite";
 import { VantResolver } from "unplugin-vue-components/resolvers";
 import { postcssConfig } from "./postcss.config.js";
 
-// const target = 'http://192.168.2.7:10010';
-const target = 'http://192.168.2.3:10010';
+const target = 'http://192.168.2.7:10010';
+// const target = 'http://192.168.2.3:10010';
 // const target = 'http://192.168.2.17:10010';
 // const target = 'http://47.101.180.183:10010';
 

+ 20 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/yarn.lock

@@ -658,6 +658,14 @@ eastasianwidth@^0.2.0:
   resolved "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz"
   integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
 
+echarts@^5.5.1:
+  version "5.5.1"
+  resolved "https://registry.npmmirror.com/echarts/-/echarts-5.5.1.tgz#8dc9c68d0c548934bedcb5f633db07ed1dd2101c"
+  integrity sha512-Fce8upazaAXUVUVsjgV6mBnGuqgO+JNDlcgF79Dksy4+wgGpQB2lmYoO4TSweFg/mZITdpGHomw/cNBJZj1icA==
+  dependencies:
+    tslib "2.3.0"
+    zrender "5.6.0"
+
 electron-to-chromium@^1.5.41:
   version "1.5.71"
   resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.71.tgz"
@@ -1317,6 +1325,11 @@ ts-interface-checker@^0.1.9:
   resolved "https://registry.npmmirror.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
   integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
 
+tslib@2.3.0:
+  version "2.3.0"
+  resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
+  integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
+
 unplugin-vue-components@^0.25.1:
   version "0.25.2"
   resolved "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.25.2.tgz"
@@ -1445,3 +1458,10 @@ yaml@^2.3.4:
   version "2.6.1"
   resolved "https://registry.npmmirror.com/yaml/-/yaml-2.6.1.tgz"
   integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==
+
+zrender@5.6.0:
+  version "5.6.0"
+  resolved "https://registry.npmmirror.com/zrender/-/zrender-5.6.0.tgz#01325b0bb38332dd5e87a8dbee7336cafc0f4a5b"
+  integrity sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==
+  dependencies:
+    tslib "2.3.0"

+ 12 - 8
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectApprovalController.java

@@ -115,12 +115,16 @@ public class ProjectApprovalController {
             projectApproval.setInchargerName(id.getName());
         }
         if (projectApproval.getId() != null) {
-            //编辑
-            Integer count=projectMapper.selectCount(new LambdaQueryWrapper<Project>().eq(Project::getCompanyId, companyId).eq(Project::getProjectCode, projectApproval.getProjectCode()));
-            Integer count1=projectApprovalService.count(new LambdaQueryWrapper<ProjectApproval>().eq(ProjectApproval::getCompanyId, companyId).eq(ProjectApproval::getProjectCode, projectApproval.getProjectCode()).ne(ProjectApproval::getId,projectApproval.getId()));
-            if(count>0||count1>0){
-                msg.setError("已存在项目编号为["+projectApproval.getProjectCode()+"]的项目/立项");
-                return msg;
+            if (org.apache.commons.lang3.StringUtils.isNotEmpty(projectApproval.getProjectCode())){
+                //编辑
+                Integer count=projectMapper.selectCount(new LambdaQueryWrapper<Project>().eq(Project::getCompanyId, companyId)
+                        .eq( Project::getProjectCode, projectApproval.getProjectCode())
+                        .ne(Project::getApproveId,projectApproval.getId()));
+                Integer count1=projectApprovalService.count(new LambdaQueryWrapper<ProjectApproval>().eq(ProjectApproval::getCompanyId, companyId).eq(ProjectApproval::getProjectCode, projectApproval.getProjectCode()).ne(ProjectApproval::getId,projectApproval.getId()));
+                if(count>0||count1>0){
+                    msg.setError("已存在项目编号为["+projectApproval.getProjectCode()+"]的项目/立项");
+                    return msg;
+                }
             }
         } else {
             //新增
@@ -319,8 +323,8 @@ public class ProjectApprovalController {
 
     @RequestMapping("/check")
     @Transactional(rollbackFor = Exception.class)
-    public HttpRespMsg check(Integer id,Integer checkType,Integer revokeType){
-        return projectApprovalService.check(id,checkType,revokeType);
+    public HttpRespMsg check(Integer id,Integer checkType,Integer revokeType,String rejectInfo){
+        return projectApprovalService.check(id,checkType,revokeType,rejectInfo);
     }
 
     @RequestMapping("/importData")

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

@@ -247,6 +247,12 @@ public class ProjectApproval extends Model<ProjectApproval> {
     @TableField("wx_corp_sp_no")
     private String wxCorpSpNo;
 
+    /**
+     * 驳回原因
+     */
+    @TableField("reject_info")
+    private String rejectInfo;
+
     @TableField(exist = false)
     private List<ProjectApprovalBasecost> projectApprovalBasecostList;
 
@@ -265,6 +271,12 @@ public class ProjectApproval extends Model<ProjectApproval> {
     @TableField(exist = false)
     private Integer canChecked;
 
+    @TableField(exist = false)
+    private Boolean isFirstCheckUser;
+
+    @TableField(exist = false)
+    private Boolean isCheckedUser;
+
 
     @Override
     protected Serializable pkVal() {

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

@@ -24,5 +24,5 @@ public interface ProjectApprovalService extends IService<ProjectApproval> {
 
     HttpRespMsg exportData(String keyword, Integer searchField, String statuses, Integer category, Integer viewId);
 
-    HttpRespMsg check(Integer id, Integer checkType, Integer revokeType);
+    HttpRespMsg check(Integer id, Integer checkType, Integer revokeType,String rejectInfo);
 }

+ 37 - 8
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectApprovalServiceImpl.java

@@ -161,6 +161,25 @@ public class ProjectApprovalServiceImpl extends ServiceImpl<ProjectApprovalMappe
             if(optional.isPresent()){
                 r.setInchargerName(optional.get().getName());
             }
+            Optional<ProjectApprovalCheck> first1 = approvalCheckList.stream().filter(p -> p.getProjectApprovalId().equals(r.getId()) && p.getStatus() == 0).min(Comparator.comparing(ProjectApprovalCheck::getSeq));
+            Optional<ProjectApprovalCheck> first2 = approvalCheckList.stream().filter(p -> p.getProjectApprovalId().equals(r.getId()) && p.getStatus() == 1&&p.getUserId().equals(user.getId())).findFirst();
+            if (first1.isPresent()){
+                ProjectApprovalCheck projectApprovalCheck = first1.get();
+                if (projectApprovalCheck.getUserId().equals(user.getId())){
+                    r.setIsFirstCheckUser(true);
+                }else {
+                    r.setIsFirstCheckUser(false);
+                }
+            }else r.setIsFirstCheckUser(false);
+
+            if (first2.isPresent()){
+                ProjectApprovalCheck projectApprovalCheck = first2.get();
+                if (projectApprovalCheck.getUserId().equals(user.getId())){
+                    r.setIsCheckedUser(true);
+                }else {
+                    r.setIsFirstCheckUser(false);
+                }
+            }else r.setIsCheckedUser(false);
 //            List<ProjectApprovalCheck> checkList = approvalCheckList.stream().filter(a -> a.getProjectApprovalId().equals(r.getId())).collect(Collectors.toList());
 //            Optional<ProjectApprovalCheck> first = checkList.stream().filter(c -> c.getUserId().equals(user.getId())&&c.getStatus()==0).findFirst();
         });
@@ -788,20 +807,22 @@ public class ProjectApprovalServiceImpl extends ServiceImpl<ProjectApprovalMappe
     }
 
     @Override
-    public HttpRespMsg check(Integer id, Integer checkType, Integer revokeType) {
+    public HttpRespMsg check(Integer id, Integer checkType, Integer revokeType,String rejectInfo) {
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         ProjectApproval projectApproval = getById(id);
-        List<ProjectApprovalCheck> projectApprovalChecks = projectApprovalCheckService.list(new LambdaQueryWrapper<ProjectApprovalCheck>().eq(ProjectApprovalCheck::getProjectApprovalId, id));
-        Optional<ProjectApprovalCheck> first = projectApprovalChecks.stream().filter(p -> p.getUserId().equals(user.getId())&&p.getStatus()==0).findFirst();
+        List<ProjectApprovalCheck> projectApprovalChecks = projectApprovalCheckService.list(new LambdaQueryWrapper<ProjectApprovalCheck>().eq(ProjectApprovalCheck::getProjectApprovalId, id).orderByAsc(ProjectApprovalCheck::getSeq));
+        if (null==projectApprovalChecks||projectApprovalChecks.isEmpty()){
+            msg.setError("该项目未设置审核人");
+            return msg;
+        }
+        Optional<ProjectApprovalCheck> first = projectApprovalChecks.stream().filter(p ->  p.getStatus() == 0&& p.getUserId().equals(user.getId())).min(Comparator.comparing(ProjectApprovalCheck::getSeq));
 //        boolean hasAllPriviledge = sysFunctionService.hasPriviledge(user.getRoleId(), "管理全部立项申请");
 //        boolean hasCheckPriviledge = sysFunctionService.hasPriviledge(user.getRoleId(), "审核立项申请");
         if(checkType!=3){
-            if(projectApprovalChecks.size()>0){
-                if(!first.isPresent()){
-                    msg.setError("审核人验证失败,请按照审核人顺序审核");
-                    return msg;
-                }
+            if(!first.isPresent()){
+                msg.setError("审核人验证失败,请按照审核人顺序审核");
+                return msg;
             }
         }
         ProjectApprovalLog projectApprovalLog=new ProjectApprovalLog();
@@ -861,11 +882,19 @@ public class ProjectApprovalServiceImpl extends ServiceImpl<ProjectApprovalMappe
                     //通过
                     projectApprovalLog.setType(2);
                     projectApprovalLogService.save(projectApprovalLog);
+                    if (first.get().getSeq()==projectApprovalChecks.size()){
+                        projectApproval.setStatus(1);
+                        projectApprovalService.updateById(projectApproval);
+                    }
                 }
                 break;
             /*驳回*/
             case 2:
+                ProjectApprovalCheck check = first.get();
+                check.setStatus(2);
+                projectApprovalCheckService.updateById(check);
                 projectApproval.setStatus(2);
+                projectApproval.setRejectInfo(rejectInfo);
                 projectApprovalService.updateById(projectApproval);
                 //新增操作记录数据
                 projectApprovalLog.setCreateTime(LocalDateTime.now());

+ 5 - 1
fhKeeper/formulahousekeeper/timesheet/src/components/selectPersonnel.vue

@@ -1,7 +1,7 @@
 <template>
   <el-select v-model="selectPersonnelValue" filterable @visible-change="toggleSelectPrefix" remote
     :remote-method="userListRemotemethod" :multiple="multiple" @focus="userFocus" :size="size" collapse-tags
-    @change="updateValue" clearable :ref="`select${timeRef}`" :style="`width: ${width}`" :class="`custom-select ${user.userNameNeedTranslate == 1 && selectPrefixFlg ? 'setUpInput' : ''}`">
+    @change="updateValue" clearable :ref="`select${timeRef}`" :style="`width: ${width}`" :class="`custom-select ${user.userNameNeedTranslate == 1 && selectPrefixFlg ? 'setUpInput' : ''}`" :disabled="disabled">
     <template #prefix>
       <div style="height: 100%;display: flex;align-items: center;">
         <!-- 单选 -->
@@ -74,6 +74,10 @@ export default {
     width: { // 宽度
       type: String,
       default: '200px'
+    },
+    disabled: {
+      type: Boolean,
+      default: () => false
     }
   },
   data() {

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

@@ -77,7 +77,8 @@
                                         <span style="float: right; color: #8492a6; font-size: 13px;margin-left: 20px" v-if="item.jobNumber">{{ item.jobNumber }}</span>
                                     </el-option>
                                 </el-select>
-                                <selectCat v-if="user.userNameNeedTranslate == 1" :size="'mini'" :filterable="true" :subject="users" :subjectId="executorItem.executorId" :distinction="'1'" @selectCal="selectCal" :index="executorItem.indexList" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)"></selectCat>
+                                <selectCat v-if="user.userNameNeedTranslate == 1" :size="'mini'" :filterable="true" :subject="users" :subjectId="executorItem.executorId" :distinction="'1'" @selectCal="selectCal" :index="executorItem.indexList" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)" :key="executorItem.indexList"></selectCat>
+                                <!-- <selectPersonnel v-if="user.userNameNeedTranslate == 1" v-model="executorItem.executorId" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)"  @change="$forceUpdate()" :key="executorItem.indexList" /> -->
                             </div>
                             <!-- 项目服务 -->
                             <div v-if="user.companyId==3092">
@@ -637,6 +638,7 @@
 
 <script>
 import selectCat from "@/components/select.vue"
+import selectPersonnel from "@/components/selectPersonnel.vue"
 // 富文本样式
 import 'quill/dist/quill.core.css'
 import 'quill/dist/quill.snow.css'
@@ -659,6 +661,7 @@ export default {
   components: {
     quillEditor, // 富文本
     selectCat,
+    selectPersonnel
   },
   data() {
     return {
@@ -882,6 +885,7 @@ export default {
         newList.forEach((item, index) => {
             item.indexList = index
         })
+        console.log(newList.slice(this.startNum, this.endNum), '<==== newList')
         return newList.slice(this.startNum, this.endNum)
     },
     containerHeight() {

+ 45 - 41
fhKeeper/formulahousekeeper/timesheet/src/views/project/info.vue

@@ -6,65 +6,68 @@
                 <div class="box info">
                     <label>{{ $t('basicinformation') }}<el-link v-if="(user.id == project.creatorId || user.id == project.inchargerId) || permissions.projectManagement" @click="showEdit" style="float:right;"><i class="el-icon-edit"  ></i></el-link></label>
                     <el-row :gutter="10" >
-                        <el-col :span="5" ><span class="gray_label">{{ $t('headerTop.projectName') }}:</span></el-col><el-col :span="7" ><span >{{project.projectName}}</span></el-col>
-                        <el-col :span="5" ><span class="gray_label">{{ $t('projectclassification') }}:</span></el-col><el-col :span="7" ><span >{{project.categoryName}}</span></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('headerTop.projectName') }}:</div></el-col><el-col :span="7" ><div >{{project.projectName}}</div></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('projectclassification') }}:</div></el-col><el-col :span="7" ><div >{{project.categoryName}}</div></el-col>
                     </el-row>
                     <el-row :gutter="10" >
-                        <el-col :span="5" ><span class="gray_label">{{ $t('other.projectDescription') }}:</span></el-col><el-col :span="7" ></el-col>
-                        <el-col :span="18" ><span>{{project.projectDesc}}</span></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('other.projectDescription') }}:</div></el-col><el-col :span="7" ></el-col>
+                        <el-col :span="18" ><div>{{project.projectDesc}}</div></el-col>
                     </el-row>
                     <el-row :gutter="10" v-if="user.timeType.projectWithDept">
-                        <el-col :span="5" ><span class="gray_label">{{ $t('subordinatedepartments') }}:</span></el-col><el-col :span="7" ></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('subordinatedepartments') }}:</div></el-col><el-col :span="7" ></el-col>
                         <el-col :span="18" >
-                            <span v-if="user.userNameNeedTranslate != 1">{{project.departmentName}}</span>
-                            <span v-if="user.userNameNeedTranslate == 1"><TranslationOpenDataText type='departmentName' :openid='project.departmentName'></TranslationOpenDataText></span>
+                            <div v-if="user.userNameNeedTranslate != 1">{{project.departmentName}}</div>
+                            <div v-if="user.userNameNeedTranslate == 1"><TranslationOpenDataText type='departmentName' :openid='project.departmentName'></TranslationOpenDataText></div>
                         </el-col>
                     </el-row>
                     <el-row :gutter="10">
-                        <el-col :span="5" ><span class="gray_label">{{ $t('state.states') }}:</span></el-col><el-col :span="7" ><span >{{project.status==null?'-':statusTxt[project.status]}}</span></el-col>
-                        <el-col :span="5" v-if="user.company.packageEngineering==0"><span class="gray_label">{{ $t('completeness') }}: </span></el-col><el-col :span="7" >
-                        <span v-if="user.company.packageEngineering==0">
+                        <el-col :span="5" ><div class="gray_label">{{ $t('state.states') }}:</div></el-col><el-col :span="7" ><div >{{project.status==null?'-':statusTxt[project.status]}}</div></el-col>
+                        <el-col :span="5" v-if="user.company.packageEngineering==0"><div class="gray_label">{{ $t('completeness') }}: </div></el-col><el-col :span="7" >
+                        <div v-if="user.company.packageEngineering==0">
                             <el-progress  :percentage="project.progress == null?0:project.progress"></el-progress>
-                        </span></el-col>
+                        </div></el-col>
                     </el-row>
                     <el-row :gutter="10">
-                        <el-col :span="5" ><span class="gray_label">{{ user.companyId == '7030' ? '项目令号' : $t('Itemno') }}: </span></el-col><el-col :span="7" ><span >{{project.projectCode}}&nbsp;</span></el-col>
-                        <el-col :span="5" v-if="permissions.projectContract"><span class="gray_label">{{ $t('contractamount') }}:</span></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ user.companyId == '7030' ? '项目令号' : $t('Itemno') }}: </div></el-col><el-col :span="7" ><div >{{project.projectCode}}&nbsp;</div></el-col>
+                        <el-col :span="5" v-if="permissions.projectContract"><div class="gray_label">{{ $t('contractamount') }}:</div></el-col>
                         <el-col :span="7" >
-                        <span style="float:left;" v-if="permissions.projectContract">{{project.contractAmount == null?'-':project.contractAmount | numberToCurrency}} 元</span>
+                        <div style="float:left;" v-if="permissions.projectContract">{{project.contractAmount == null?'-':project.contractAmount | numberToCurrency}} 元</div>
                         <el-link v-if="user.id == project.creatorId || user.id == project.inchargerId" @click="contractRecord" style="float:left;"><i class="iconfont firerock-iconrecord"></i></el-link>
                         <el-link v-if="user.id == project.creatorId || user.id == project.inchargerId || permissions.projectManagement" @click="contractChange" style="float:right;"><i class="el-icon-edit"  ></i></el-link>
                         </el-col>
                         
                     </el-row>
                     <el-row :gutter="10">
-                        <el-col :span="5" ><span class="gray_label">{{ $t('jihuajibie') }}: </span></el-col><el-col :span="7" ><span >{{levelTextShow(project.level)}}</span></el-col>
-                        <el-col :span="5" ><span class="gray_label">{{ $t('creationdate') }}:</span></el-col><el-col :span="7" ><span>{{project.createDate}}</span></el-col>
+                        <el-col :span="5" ><div class="gray_label ">{{ $t('jihuajibie') }}: </div></el-col>
+                        <el-col :span="7" ><div class="gray_label ">{{levelTextShow(project.level)}}</div></el-col>
+                        <el-col :span="5" ><div class="gray_label ">{{ $t('creationdate') }}:</div>
+                        </el-col><el-col :span="7" ><div class="gray_label ">{{project.createDate}}</div></el-col>
                     </el-row>
+             
                     <el-row :gutter="10">
-                        <el-col :span="5" ><span class="gray_label">{{ $t('ommencementDate') }}:</span></el-col>
-                        <el-col :span="7" ><span >{{project.planStartDate==null?'-':project.planStartDate}}</span></el-col>
-                        <el-col :span="5" ><span class="gray_label">{{ $t('ji-hua-jie-shu-ri-qi') }}:</span></el-col>
-                        <el-col :span="7" ><span>{{project.planEndDate == null?'-':project.planEndDate}}</span></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('ommencementDate') }}:</div></el-col>
+                        <el-col :span="7" ><div >{{project.planStartDate==null?'-':project.planStartDate}}</div></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('ji-hua-jie-shu-ri-qi') }}:</div></el-col>
+                        <el-col :span="7" ><div>{{project.planEndDate == null?'-':project.planEndDate}}</div></el-col>
                     </el-row>
                     <el-row :gutter="10">
-                        <el-col :span="5" ><span class="gray_label">{{ $t('shijiawancheng') }}:</span></el-col>
-                        <el-col :span="7" ><span>{{project.finishDate==null?'-':project.finishDate}}</span></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('shijiawancheng') }}:</div></el-col>
+                        <el-col :span="7" ><div>{{project.finishDate==null?'-':project.finishDate}}</div></el-col>
                         <template v-if="user.timeType.outputValueStatus == 1">
-                        <el-col :span="5" ><span class="gray_label">{{ $t('projectoutput') }}:</span></el-col>
-                        <el-col :span="7" ><span>{{project.outputValue == null?'-':project.outputValue | numberToCurrency}} {{ $t('yuan') }}</span></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{ $t('projectoutput') }}:</div></el-col>
+                        <el-col :span="7" ><div>{{project.outputValue == null?'-':project.outputValue | numberToCurrency}} {{ $t('yuan') }}</div></el-col>
                         </template>
                     </el-row>
                     <el-row :gutter="10" v-if="yonghuUser.customDegreeActive == 1">
-                        <el-col :span="5" ><span class="gray_label">{{yonghuUser.customDegreeName}}:</span></el-col>
-                        <el-col :span="18" ><span>{{project.associateDegreeNames}}</span></el-col>
+                        <el-col :span="5" ><div class="gray_label">{{yonghuUser.customDegreeName}}:</div></el-col>
+                        <el-col :span="18" ><div>{{project.associateDegreeNames}}</div></el-col>
                     </el-row>
 
                     <div v-if="user.timeType.projectCustom">
                         <el-row :gutter="10" v-for="(item,index) in dataListTwo" :key="index">
-                            <el-col :span="5" ><span class="gray_label">{{ item.customName }}:</span></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ item.customName }}:</div></el-col>
                             <el-col :span="18" v-if="item.customType != 1">
-                                <span>{{item.value}}</span>
+                                <div>{{item.value}}</div>
                             </el-col>
                             <el-col :span="18" v-if="item.customType == 1">
                                 <viewer :images="item.value" class="detailsPicture">
@@ -78,31 +81,31 @@
                     <!-- this.project  -->
                     <div v-if="user.companyId == '936'">
                         <el-row :gutter="10" >
-                            <el-col :span="5" ><span class="gray_label">{{ $t('contractno') }}:</span></el-col><el-col :span="7" ></el-col>
-                            <el-col :span="18" ><span>{{project.projectSeparate && project.projectSeparate.contractCode}}</span></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ $t('contractno') }}:</div></el-col><el-col :span="7" ></el-col>
+                            <el-col :span="18" ><div>{{project.projectSeparate && project.projectSeparate.contractCode}}</div></el-col>
                         </el-row>
                         <el-row :gutter="10">
-                            <el-col :span="5" ><span class="gray_label">{{ $t('warrantystartime') }}:</span></el-col><el-col :span="7" >
-                                <span >{{project.projectSeparate.warrantyStartDate==null?'-':project.projectSeparate.warrantyStartDate}}</span></el-col>
-                            <el-col :span="5" ><span class="gray_label">{{ $t('warrantyexpirationtime') }}:</span></el-col><el-col :span="7" ><span>
-                                {{project.projectSeparate.warrantyEndDate == null?'-':project.projectSeparate.warrantyEndDate}}</span></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ $t('warrantystartime') }}:</div></el-col><el-col :span="7" >
+                                <div >{{project.projectSeparate.warrantyStartDate==null?'-':project.projectSeparate.warrantyStartDate}}</div></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ $t('warrantyexpirationtime') }}:</div></el-col><el-col :span="7" ><div>
+                                {{project.projectSeparate.warrantyEndDate == null?'-':project.projectSeparate.warrantyEndDate}}</div></el-col>
                         </el-row>
                         <el-row :gutter="10" >
-                            <el-col :span="5" ><span class="gray_label">{{ $t('IndependentProject') }}:</span></el-col><el-col :span="7" ></el-col>
-                            <el-col :span="18" ><span>{{project.projectSeparate.projectCategorySub}}</span></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ $t('IndependentProject') }}:</div></el-col><el-col :span="7" ></el-col>
+                            <el-col :span="18" ><div>{{project.projectSeparate.projectCategorySub}}</div></el-col>
                         </el-row>
                         <el-row :gutter="10" >
-                            <el-col :span="5" ><span class="gray_label">{{ $t('region') }}:</span></el-col><el-col :span="7" ></el-col>
-                            <el-col :span="18" ><span>{{project.projectSeparate.region}}</span></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ $t('region') }}:</div></el-col><el-col :span="7" ></el-col>
+                            <el-col :span="18" ><div>{{project.projectSeparate.region}}</div></el-col>
                         </el-row>
                         <el-row :gutter="10" >
-                            <el-col :span="5" ><span class="gray_label">{{ $t('subordinateBU') }}:</span></el-col><el-col :span="7" ></el-col>
-                            <el-col :span="18" ><span>{{project.projectSeparate.bu}}</span></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ $t('subordinateBU') }}:</div></el-col><el-col :span="7" ></el-col>
+                            <el-col :span="18" ><div>{{project.projectSeparate.bu}}</div></el-col>
                         </el-row>
                     </div>
                     <div v-if="user.timeType.projectManDay">
                         <el-row :gutter="10" >
-                            <el-col :span="5" ><span class="gray_label">{{ $t('shiJiYuGuGongShi') }}</span></el-col><el-col :span="7" ></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{ $t('shiJiYuGuGongShi') }}</div></el-col><el-col :span="7" ></el-col>
                             <el-col :span="18" ><b :style="fillTimeData.total>project.manDay*user.timeType.allday?'color:red;':''">{{fillTimeData.total}}</b>/<b>{{project.manDay*user.timeType.allday}}</b>&nbsp;{{ $t('time.hour') }}</el-col>
                         </el-row>
                     </div>
@@ -721,6 +724,7 @@
 }
 .gray_label {
     color:#999 !important;
+    min-height: 20px;
 }
 
 .el-row {

+ 148 - 42
fhKeeper/formulahousekeeper/timesheet/src/views/projectApproval/projectApproval.vue

@@ -29,6 +29,15 @@
                 </el-form-item>
             </el-form>
         </el-col>
+        <el-dialog :title="$t('defaultText.pleaseEnterTheReason')"  v-if="denyReasonDialog" :visible.sync="denyReasonDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
+            <div>
+                <span style="color:red;">*</span><el-input type="textarea" v-model="denyReasonRReason" rows="2" placeholder="请输入驳回原因" />
+            </div>
+            <div slot="footer" class="dialog-footer">
+                <el-button  @click="denyReasonDialog = false" >{{ $t('btn.cancel') }}</el-button>
+                <el-button type="primary" @click="deny()" :disabled="!denyReasonRReason">{{ $t('btn.determine') }}</el-button>
+            </div>
+        </el-dialog>
         <div style="display: flex;width: 100%;">
                 <div class="classification">
                     <div>
@@ -43,13 +52,13 @@
                         </el-table-column>
                         <el-table-column prop="projectCode" :label="user.companyId == '7030' ? '项目令号' : $t('Itemno')"  width="150"></el-table-column>
                         <el-table-column prop="projectName" :label="$t('headerTop.projectName')" min-width="250" sortable="custom">
-                        <template slot-scope="scope">
-                            <div> 
-                                <el-button type="text" v-if="user.company.packageProject==1 && (user.company.nonProjectSimple==0 || (user.company.nonProjectSimple==1&&scope.row.isPublic==0))" @click="showProjectApprovalDeatil(scope.row)">{{scope.row.projectName}}</el-button>
-                                <span v-else>{{scope.row.projectName}}</span>
-                            </div>
-                        </template>
-                    </el-table-column>
+                            <template slot-scope="scope">
+                                <div> 
+                                    <el-button type="text" v-if="user.company.packageProject==1 && (user.company.nonProjectSimple==0 || (user.company.nonProjectSimple==1&&scope.row.isPublic==0))" @click="showProjectApprovalDeatil(scope.row)">{{scope.row.projectName}}</el-button>
+                                    <span v-else>{{scope.row.projectName}}</span>
+                                </div>
+                            </template>
+                        </el-table-column>
                         <el-table-column prop="categoryName" :label="$t('projectclassification')"  width="140"></el-table-column>
                         <el-table-column prop="isPublic" :label="$t('projecttype')"  width="140">
                             <template slot-scope="scope">{{scope.row.isPublic==0?$t('zheng-shi-xiang-mu'):$t('fei-xiang-mu')}}</template>
@@ -78,11 +87,12 @@
                                 {{scope.row.status == null?"-":approvalStatusStr[scope.row.status]}}
                             </template>
                         </el-table-column>
+                        <el-table-column prop="rejectInfo" :label="$t('dismissreason')" min-width="250" ></el-table-column>
                         <el-table-column :label="$t('operation')" :width="300" align="left" fixed="right">
                             <template slot-scope="scope">
                                 <el-button size="mini" type="primary" v-if="(permissions.projectApprovalEdit||permissions.projectApprovalCheck)&&scope.row.status!=1" @click="handleAdd(scope.$index, scope.row)">{{'编辑'}}</el-button>
-                                <el-button size="mini" type="success" v-if="(permissions.projectApprovalEdit||permissions.projectApprovalCheck) && scope.row.status==0"  @click="check(scope.row,1)" >{{'通过'}}</el-button>
-                                <el-button size="mini" v-if="(permissions.projectApprovalEdit||permissions.projectApprovalCheck) && scope.row.status==0" @click="check(scope.row,2)">{{'驳回'}}</el-button>
+                                <el-button size="mini" type="success" v-if="(permissions.projectApprovalEdit||permissions.projectApprovalCheck) && scope.row.status==0" :disabled="!scope.row.isFirstCheckUser"  @click="check(scope.row,1)" >{{'通过'}}</el-button>
+                                <el-button size="mini" v-if="(permissions.projectApprovalEdit||permissions.projectApprovalCheck) && scope.row.status==0" :disabled="!scope.row.isFirstCheckUser"  @click="showDenyDialog(scope.row,2)">{{'驳回'}}</el-button>
                                 <el-button size="mini" v-if="(permissions.projectApprovalEdit ||permissions.projectApprovalCheck) && scope.row.status==1" @click="check(scope.row,3)">{{'撤销'}}</el-button>
                             </template>
                         </el-table-column>
@@ -227,9 +237,11 @@
                                 </div>
                                 <el-divider></el-divider>
                                 <template>
-                                    <div><span>{{'审核人'}}</span></div>
-                                    <div>
-                                        <div v-for="(item, index) in pointList" :key="index" >
+                                    <div style="padding: 7px 0; ">
+                                        <span style="color: #409EFF; font-size: 17px;">{{'审核人'}}</span>
+                                    </div>
+                                    <!-- <div >
+                                        <div  v-for="(item, index) in pointList" :key="index" >
                                         第{{index+1}}审核人:
                                         <el-select  v-if="user.userNameNeedTranslate != 1" :disabled="item.status!=0" v-model="item.userId" style="width:140px;" :placeholder="$t('defaultText.pleaseChoose')" clearable @change="manageSelect" size="small" filterable popper-class="managePopperClass">
                                             <el-option v-for="item in participator" :key="item.id" :label="item.name" :value="item.id">
@@ -241,6 +253,20 @@
                                         <i class="el-icon-remove-outline" v-if="pointList.length>1 && item.status==0"  @click="deleteInput(index)"></i>
                                         <span>{{item.status==0?'待审核':item.status==1?"已审核":"已驳回"}}</span>
                                         </div>
+                                    </div> -->
+                                    <div>
+                                        <div v-for="(item, index) in pointList" :key="index" style="margin-bottom: 10px; padding: 10px; border: 1px solid #e0e0e0; border-radius: 5px;">
+                                            第{{index + 1}}审核人:
+                                            <el-select v-if="user.userNameNeedTranslate != 1" :disabled="item.status != 0" v-model="item.userId" style="width: 140px; margin-left: 10px;" :placeholder="$t('defaultText.pleaseChoose')" clearable @change="manageSelect" size="small" filterable popper-class="managePopperClass">
+                                                <el-option v-for="participatorItem in participator" :key="participatorItem.id" :label="participatorItem.name" :value="participatorItem.id">
+                                                    <span style="float: left">{{ participatorItem.name }}</span>
+                                                </el-option>
+                                            </el-select>
+                                            <selectCat v-if="user.userNameNeedTranslate == 1" :size="'medium'" :subject="participator" :subjectId="item.userId" :distinction="'12'" @selectCal="selectCal" :disabled="canOnlyModParticipator || projectManagerEdit || isShowProjectName"></selectCat>
+                                            <i class="el-icon-circle-plus-outline" @click="addInput(index)" v-if="index == pointList.length - 1" style="margin-left: 10px;"></i>
+                                            <i class="el-icon-remove-outline" v-if="pointList.length > 1 && item.status == 0" @click="deleteInput(index)" style="margin-left: 10px;"></i>
+                                            <span style="margin-left: 10px;">{{ item.status == 0 ? '待审核' : item.status == 1 ? "已审核" : "已驳回" }}</span>
+                                        </div>
                                     </div>
                                 </template>
                             </el-form>  
@@ -312,14 +338,27 @@
                     </el-dialog>
 
                     <!--查看立项-->
-                    <el-dialog :title="$t('Checkthedetails')" v-if="projectApprovalDetailVisible" :visible.sync="projectApprovalDetailVisible" :close-on-click-modal="false" customClass="customWidth" width="400px">
-                        <div class="line"><span>{{user.companyId='7030' ? '项目令号:' : '项目编号:'}}</span><span>{{projectApprocalDetail.projectCode}}</span></div>
-                        <div class="line"><span>{{'项目名称:'}}</span><span>{{projectApprocalDetail.projectName}}</span></div>
-                        <div class="line"><span>{{'项目分类:'}}</span><span>{{projectApprocalDetail.categoryName}}</span></div>
-                        <div class="line"><span>{{'项目类型:'}}</span><span>{{projectApprocalDetail.isPublic==0?"正式项目":"非项目"}}</span></div>
-                        <div class="line"><span>{{'项目描述:'}}</span><span>{{projectApprocalDetail.projectDesc}}</span></div>
-                        <div class="line"><span>{{'全部参与人:'}}</span>
-                            <span v-for="(par, index) in projectApprocalDetail.participationApprovalList" :key="par.userId">
+                    <el-dialog :title="$t('Checkthedetails')" v-if="projectApprovalDetailVisible" :visible.sync="projectApprovalDetailVisible" :close-on-click-modal="false" customClass="customWidth" width="800px">
+                        <el-row :gutter="10" >
+                            <el-col :span="5" ><div class="gray_label">{{user.companyId='7030' ? '项目令号:' : '项目编号:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{projectApprocalDetail.projectCode}}</div></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{'项目名称:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{projectApprocalDetail.projectName}}</div></el-col>
+                        </el-row>
+                        <el-row :gutter="10" >
+                            <el-col :span="5" ><div class="gray_label">{{'项目分类:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{projectApprocalDetail.categoryName}}</div></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{'项目类型:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{projectApprocalDetail.isPublic==0?"正式项目":"非项目"}}</div></el-col>
+                        </el-row>
+                        <el-row :gutter="10" >
+                            <el-col :span="3" ><div class="gray_label">{{'项目描述:'}}</div></el-col>
+                            <el-col :span="21" ><div class="gray_label ">{{projectApprocalDetail.projectDesc}}</div></el-col>
+                        </el-row>
+                        <el-row :gutter="10" >
+                            <el-col :span="3" ><div class="gray_label">{{'全部参与人:'}}</div></el-col>
+                            <el-col :span="21" ><div class="gray_label ">
+                                <span v-for="(par, index) in projectApprocalDetail.participationApprovalList" :key="par.userId">
                                 <span v-if="user.userNameNeedTranslate != 1">
                                     {{par.userName}}
                                 </span>
@@ -328,13 +367,18 @@
                                 </span>
                                 <span v-if="index < projectApprocalDetail.participationApprovalList.length-1">,</span>
                             </span>
-                        </div>
-                        <div class="line"><span>{{'项目经理:'}}</span>
-                            <span v-if="user.userNameNeedTranslate != 1">{{projectApprocalDetail.inchargerName}}</span>
-                            <span v-if="user.userNameNeedTranslate == 1&&projectApprocalDetail.inchargerName"><TranslationOpenDataText type='userName' :openid='projectApprocalDetail.inchargerName'></TranslationOpenDataText></span>
-                        </div>
-                        <div class="line"><span>{{'日报审核人:'}}</span>
-                            <span v-for="(par,index) in projectApprocalDetail.projectApprovalAuditorList" :key="par.auditorId">
+                            </div></el-col>
+                        </el-row>
+                        <el-row :gutter="10" >
+                            <el-col :span="5" ><div class="gray_label">{{'项目经理:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label " > 
+                                <span v-if="user.userNameNeedTranslate != 1">{{projectApprocalDetail.inchargerName}}</span>
+                                <span v-if="user.userNameNeedTranslate == 1&&projectApprocalDetail.inchargerName"><TranslationOpenDataText type='userName' :openid='projectApprocalDetail.inchargerName'></TranslationOpenDataText></span>
+                                </div>
+                            </el-col>
+                            <el-col :span="5" ><div class="gray_label">{{'日报审核人:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">
+                                <span v-for="(par,index) in projectApprocalDetail.projectApprovalAuditorList" :key="par.auditorId">
                                 <span v-if="user.userNameNeedTranslate != 1">
                                     {{par.auditorName}}
                                 </span>
@@ -343,25 +387,36 @@
                                 </span>
                                 <span v-if="index < projectApprocalDetail.projectApprovalAuditorList.length-1">,</span>
                             </span>
-                        </div>
-                        <div class="line"><span>{{'级别:'}}</span><span>{{importanceListLable[projectApprocalDetail.level-1]}}</span></div>
-                        <div class="line"><span>{{'合同金额:'}}</span><span>{{projectApprocalDetail.contractAmount}}</span></div>
-                        <div class="line">
-                            <span>{{'计划开始日期:'}}</span><span>{{projectApprocalDetail.planStartDate}}</span>
-                            <span>{{'计划结束日期:'}}</span><span>{{projectApprocalDetail.planEndDate}}</span>
-                        </div>
+                            </div></el-col>
+                        </el-row>
+                        <el-row :gutter="10" >
+                            <el-col :span="5" ><div class="gray_label">{{'级别:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{importanceListLable[projectApprocalDetail.level-1]}}</div></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{'合同金额:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{projectApprocalDetail.contractAmount}}</div></el-col>
+                        </el-row>
+                        <el-row :gutter="10" >
+                            <el-col :span="5" ><div class="gray_label">{{'计划开始日期:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{projectApprocalDetail.planStartDate}}</div></el-col>
+                            <el-col :span="5" ><div class="gray_label">{{'计划结束日期:'}}</div></el-col>
+                            <el-col :span="7" ><div class="gray_label ">{{projectApprocalDetail.planEndDate}}</div></el-col>
+                        </el-row>
+                       
                         <el-divider></el-divider>
-                        <div class="line">
-                            <span>{{ $t('costbaseline') }}</span>
-                        </div>
-                        <div class="line" v-for="(item,index) in projectApprocalDetail.projectApprovalBasecostList">
+                        <el-row :gutter="10" >
+                            <el-col :span="24" ><div class="gray_label">{{'成本基线'}}</div></el-col>
+                        </el-row>
+            
+                        <div class="gray_label" v-for="(item,index) in projectApprocalDetail.projectApprovalBasecostList">
                             <span>{{item.baseName+":"}}</span><span>{{item.baseAmount}}</span>
                         </div>
                         <el-divider></el-divider>
-                        <div class="line">
-                            <span>{{ $t('caoZuoJiLu') }}</span>
-                        </div>
-                        <div class="line" v-for="(item,index) in approvalLogData">
+
+                        <el-row :gutter="10" >
+                            <el-col :span="24" ><div class="gray_label">{{'操作记录'}}</div></el-col>
+                        </el-row>
+        
+                        <div class="gray_label" v-for="(item,index) in approvalLogData">
                             <span v-if="user.userNameNeedTranslate != 1">{{item.userName}} {{item.createTime}} {{approvalTypeStr[item.type]}}{{ $t('leRiBao') }}</span>
                             <span v-if="user.userNameNeedTranslate == 1"><TranslationOpenDataText type='userName' :openid='item.userName'></TranslationOpenDataText> {{item.createTime}}{{approvalTypeStr[item.type]}}{{ $t('leRiBao') }}</span>
                         </div>
@@ -400,6 +455,9 @@ components: {
 props: { },
 data() { 
 return {
+    denyReasonDialog:false,
+    denyReasonValue: {},
+    denyReasonRReason: '',
     keyword:"",
     searchField:"1",
     user: JSON.parse(sessionStorage.getItem("user")),
@@ -486,6 +544,49 @@ mounted () {
     this.getUsers();
 },
 methods: {
+    deny() {
+        // console.log(this.denyReasonValue);
+        // console.log(this.denyReasonRReason);
+
+        this.listLoading = true;
+        this.http.post('/project-approval/check',{ 
+            id:this.denyReasonValue.item.id ,
+            checkType:this.denyReasonValue.num,
+            revokeType:'',
+            rejectInfo:this.denyReasonRReason
+        },
+        res => {
+            this.listLoading = false;
+            if (res.code == "ok") {
+                this.$message({
+                    message: this.$t('operationissuccessful'),
+                    type: "success"
+                });
+                this.addFormVisible=false
+                this.denyReasonDialog=false
+                this.getList();
+            } else {
+                this.$message({
+                    message: res.msg,
+                    type: "error"
+                });
+            }
+        },
+        error => {
+            this.listLoading = false;
+            this.$message({
+                message: error,
+                type: "error"
+            });
+            }
+        );
+        
+    },
+    showDenyDialog(item, num) {
+                this.denyReasonDialog = true;
+                this.denyReasonValue = {item,num}
+        
+            },
     isSelectable(row,index){
         if(row.creatorId == this.user.id || row.inchargerId == this.user.id || this.permissions.projectApprovalEdit){
             return true
@@ -754,6 +855,7 @@ methods: {
                 creatorId: item.creatorId,
                 outputValue: item.outputValue,
                 status: item.status,
+
             }
             this.participator=theData.participationApprovalList
             this.changeParticipator();
@@ -1407,4 +1509,8 @@ methods: {
 .on {
     color: #409EFF;
 }
+.gray_label {
+    color:#999 !important;
+    min-height: 20px;
+}
 </style>