Browse Source

Merge remote-tracking branch 'origin/master'

yusm 5 days ago
parent
commit
8f0ece406e
73 changed files with 2385 additions and 575 deletions
  1. 26 0
      fhKeeper/formulahousekeeper/course-pc/src/common/js/fixedData.js
  2. 62 45
      fhKeeper/formulahousekeeper/course-pc/src/routes.js
  3. 5 1
      fhKeeper/formulahousekeeper/course-pc/src/views/Home.vue
  4. 119 0
      fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/certificates.vue
  5. 0 0
      fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examCertification.vue
  6. 241 0
      fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examRegistrationReview.vue
  7. 113 0
      fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examResults.vue
  8. 107 0
      fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examinationInformation.vue
  9. 111 0
      fhKeeper/formulahousekeeper/course-pc/src/views/orderAndFinancialManagement/orderManagement.vue
  10. 0 0
      fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/offlineTraining.vue
  11. 0 0
      fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/registration.vue
  12. 122 0
      fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/student.vue
  13. 114 0
      fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/studentPayment.vue
  14. 0 0
      fhKeeper/formulahousekeeper/course-pc/src/views/userAndMessageManagement/customerServiceCenter.vue
  15. 0 0
      fhKeeper/formulahousekeeper/course-pc/src/views/userAndMessageManagement/myMessage.vue
  16. 158 0
      fhKeeper/formulahousekeeper/course-pc/src/views/userAndMessageManagement/userManagement.vue
  17. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/index.html
  18. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/ddje.png
  19. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/kehu.png
  20. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/lsjh.png
  21. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/lxr.png
  22. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/sjje.png
  23. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/xsdd.png
  24. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/xzxs.png
  25. 9 4
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/page/footer.vue
  26. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/addEditor/index.vue
  27. 21 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/addEditor.vue
  28. 28 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contacts/addEditor.vue
  29. 28 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contract/addEditor.vue
  30. 28 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/addEditor.vue
  31. 28 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/order/addEditor.vue
  32. 28 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/addEditor.vue
  33. 28 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/tasks/addEditor.vue
  34. 28 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/addEditor.vue
  35. 7 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/dataAnalysis.vue
  36. 45 45
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/salesBriefings.vue
  37. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/index copy.vue
  38. 17 6
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/index.vue
  39. 6 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/my/index.vue
  40. 21 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/addEditorVisitor.vue
  41. 20 12
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java
  42. 17 20
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WechatCallbackController.java
  43. 204 0
      fhKeeper/formulahousekeeper/management-platform-mld/src/main/java/com/management/platform/controller/BusinessTripController.java~
  44. 2 1
      fhKeeper/formulahousekeeper/management-platform-mld/src/main/java/com/management/platform/controller/LeaveSheetController.java
  45. 5 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java
  46. 4 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  47. 30 59
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java
  48. 8 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/U8Controller.java
  49. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  50. 7 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Company.java
  51. 11 9
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractCustom.java
  52. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/ProduceTime.java
  53. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExcelParserService.java
  54. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  55. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  56. 16 10
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java
  57. 59 44
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  58. 22 21
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectMainServiceImpl.java
  59. 159 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  60. 146 25
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  61. 0 147
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/DataCollectTask.java
  62. 21 8
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  63. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/HttpRespMsg.java
  64. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/SyncSapUtils.java
  65. 29 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WebServiceUtils.java
  66. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/CompanyMapper.xml
  67. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ContractCustomMapper.xml
  68. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  69. 65 25
      fhKeeper/formulahousekeeper/timesheet/src/views/contract/components/customContract.vue
  70. 6 5
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  71. 2 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  72. 22 4
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  73. 2 0
      fhKeeper/formulahousekeeper/timesheet_mld/src/views/leave/list.vue

+ 26 - 0
fhKeeper/formulahousekeeper/course-pc/src/common/js/fixedData.js

@@ -0,0 +1,26 @@
+export const fixedDataGender = [
+  { label: "女", value: "0" },
+  { label: "男", value: "1" },
+];
+
+export const fixedDataCertificateType = [
+  { label: "身份证", value: "0" },
+  { label: "港澳通行证", value: "1" },
+  { label: "护照", value: "2" },
+  { label: "台胞证", value: "3" },
+];
+
+export const fixedDataOrNot = [
+  { label: "否", value: "0" },
+  { label: "是", value: "1" },
+];
+
+export const fixedDataInvoiceSubject = [
+  { label: "个人", value: "0" },
+  { label: "单位", value: "1" },
+];
+
+export const fixedDatainvoiceType = [
+  { label: "专票", value: "0" },
+  { label: "普票", value: "1" },
+];

+ 62 - 45
fhKeeper/formulahousekeeper/course-pc/src/routes.js

@@ -9,13 +9,30 @@ import PdfView from './views/pdf/pdfview';
 //课程管理
 import courselist from './views/coursemanagement/list';
 import lecturerList from './views/lecturerManagement/index.vue'
-import offlineTraining from './views/offlineTraining/offlineTraining.vue'
-import examCertification from './views/examCertification/examCertification.vue'
 import gcpCertification from './views/gcpCertification/gcpCertification.vue'
-import offlineRegistration from './views/offlineRegistration/registration.vue'
 import hotTopicCarousel from './views/hotTopicCarousel/hotTopicCarousel.vue'
-import myMessage from './views/myMessage/myMessage.vue'
-import customerServiceCenter from './views/customerServiceCenter/customerServiceCenter.vue'
+
+// 考试管理
+import examCertification from './views/examinationManagement/examCertification.vue' // 考试拿证流程介绍
+import examinationInformation from './views/examinationManagement/examinationInformation.vue' // 考试信息管理
+import examRegistrationReview from './views/examinationManagement/examRegistrationReview.vue' // 考试报名审核
+import examResults from './views/examinationManagement/examResults.vue' // 考试结果
+import certificates from './views/examinationManagement/certificates.vue' // 证书管理
+
+// 研修班管理
+import offlineTraining from './views/trainingClassManagement/offlineTraining.vue' // 线下研修班介绍
+import offlineRegistration from './views/trainingClassManagement/registration.vue' // 线下研修班
+import student from './views/trainingClassManagement/student.vue' // 学员姓名
+import studentPayment from './views/trainingClassManagement/studentPayment.vue' // 学员缴费
+
+// 用户与消息管理
+import myMessage from './views/userAndMessageManagement/myMessage.vue' // 我的消息
+import customerServiceCenter from './views/userAndMessageManagement/customerServiceCenter.vue' // 客服中心
+import userManagement from './views/userAndMessageManagement/userManagement.vue' // 用户管理
+
+// 订单与财务管理
+import orderManagement from './views/orderAndFinancialManagement/orderManagement.vue'
+
 
 Vue.use(Router)
 
@@ -59,80 +76,80 @@ export const allRouters = [
         ]
     },
     {
-        path: '/404',
-        component: NotFound,
-        name: '',
-        hidden: true
-    },
-    {
-        path: '/exam-certification',
+        path: '/hotTopic-carousel',
         component: Home,
-        name: '考试拿证流程介绍',
+        name: '轮播热点内容',
         iconCls: 'iconfont firerock-iconkehu',
         leaf: true,
         children: [
-            { path: '/exam-certification', component: examCertification, name: '考试拿证流程介绍' },
+            { path: '/hotTopic-carousel', component: hotTopicCarousel, name: '轮播热点内容' }
         ]
     },
     {
-        path: '/offline-training',
+        path: '/gcpc-certification',
         component: Home,
-        name: '线下研修班',
+        name: 'GCP证书展示',
         iconCls: 'iconfont firerock-iconkehu',
         leaf: true,
         children: [
-            { path: '/offline-training', component: offlineTraining, name: '线下研修班' }
+            { path: '/gcpc-certification', component: gcpCertification, name: 'GCP证书展示' }
         ]
     },
     {
-        path: '/offline-registration',
+        path: '/',
         component: Home,
-        name: '线下研修班报名',
-        iconCls: 'iconfont firerock-iconkehu',
-        leaf: true,
+        name: '考试管理',
+        iconCls: 'iconfont firerock-iconsetting',
+        leaf: false,//只有一个节点
         children: [
-            { path: '/offline-registration', component: offlineRegistration, name: '线下研修班报名' }
+            { path: '/exam-certification', component: examCertification, name: '考试拿证流程介绍' },
+            { path: '/examination-information', component: examinationInformation, name: '考试信息管理' },
+            { path: '/exam-registrationReview', component: examRegistrationReview, name: '考试报名审核' },
+            { path: '/exam-results', component: examResults, name: '考试结果管理' },
+            { path: '/certificates', component: certificates, name: '证书管理' },
         ]
     },
     {
-        path: '/hotTopic-carousel',
+        path: '/',
         component: Home,
-        name: '轮播热点内容',
-        iconCls: 'iconfont firerock-iconkehu',
-        leaf: true,
+        name: '研修班管理',
+        iconCls: 'iconfont firerock-iconsetting',
+        leaf: false,//只有一个节点
         children: [
-            { path: '/hotTopic-carousel', component: hotTopicCarousel, name: '轮播热点内容' }
+            { path: '/offline-training', component: offlineTraining, name: '线下研修班' },
+            { path: '/offline-registration', component: offlineRegistration, name: '线下研修班报名' },
+            { path: '/student', component: student, name: '学员名单表格' },
+            { path: '/student-payment', component: studentPayment, name: '学员缴费情况表' },
         ]
     },
     {
-        path: '/gcpc-certification',
+        path: '/',
         component: Home,
-        name: 'GCP证书展示',
-        iconCls: 'iconfont firerock-iconkehu',
-        leaf: true,
+        name: '用户与消息管理',
+        iconCls: 'iconfont firerock-iconsetting',
+        leaf: false,//只有一个节点
         children: [
-            { path: '/gcpc-certification', component: gcpCertification, name: 'GCP证书展示' }
+            { path: '/my-message', component: myMessage, name: '我的消息' },
+            { path: '/customer-service-center', component: customerServiceCenter, name: '客服中心' },
+            { path: '/user-management', component: userManagement, name: '用户管理' },
         ]
     },
     {
-        path: '/my-message',
+        path: '/',
         component: Home,
-        name: '我的消息',
-        iconCls: 'iconfont firerock-iconkehu',
-        leaf: true,
+        name: '订单与财务管理',
+        iconCls: 'iconfont firerock-iconsetting',
+        leaf: false,//只有一个节点
         children: [
-            { path: '/my-message', component: myMessage, name: '我的消息' }
+            { path: '/order-management', component: orderManagement, name: '订单管理' },
+            { path: '/wwwwww', component: customerServiceCenter, name: '电子发票登记表' },
         ]
     },
     {
-        path: '/customer-service-center',
-        component: Home,
-        name: '客服中心',
-        iconCls: 'iconfont firerock-iconkehu',
-        leaf: true,
-        children: [
-            { path: '/customer-service-center', component: customerServiceCenter, name: '客服中心' }
-        ]
+        path: '/404',
+        component: NotFound,
+        name: '',
+        hidden: true
     },
     {
         path: '*',

+ 5 - 1
fhKeeper/formulahousekeeper/course-pc/src/views/Home.vue

@@ -34,7 +34,7 @@
             <aside :class="collapsed?'menu-collapsed':'menu-expanded'">
                 <el-scrollbar style="height:100%">
                 <!--导航菜单-->
-                <el-menu :default-active="$route.path" class="el-menu-vertical-demo" unique-opened router v-if="!collapsed">
+                <el-menu :default-active="$route.path" class="el-menu-vertical-demo" unique-opened router v-if="!collapsed" active-text-color="#57A8D1">
                     <template v-for="(item,index) in $router.options.routes" v-if="!item.hidden">
                         <el-submenu :index="index+''" v-if="!item.leaf">
                             <template slot="title">
@@ -369,6 +369,10 @@
             },
         },
         mounted() {
+
+            console.log(this.$router.options.routes)
+            console.log(this.$route.path)
+            
             let height = window.innerHeight;
             this.tableHeight = height - 15;
             const that = this;

+ 119 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/certificates.vue

@@ -0,0 +1,119 @@
+<template>
+    <section>
+        <!--搜索栏-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true" @submit.native.prevent>
+                <el-form-item label="姓名">
+                    <el-input v-model="keyword" placeholder="请输入" clearable @change="searchList"
+                        size="small"></el-input>
+                </el-form-item>
+                <el-form-item label="课程名称">
+                    <el-input v-model="courseName" placeholder="请输入" clearable @change="searchList"
+                        size="small"></el-input>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--表格-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+            <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+            <el-table-column prop="name" label="姓名" min-width="120" align="center"></el-table-column>
+            <el-table-column prop="phone" label="手机号" min-width="160" align="center"></el-table-column>
+            <el-table-column prop="certificate" label="证书" min-width="180" align="center"></el-table-column>
+            <el-table-column prop="dateOfIssue" label="发证日期" min-width="120" align="center"></el-table-column>
+            <el-table-column label="操作" min-width="150" align="center">
+              <template slot-scope="scope">
+                <el-button size="small">上传证书</el-button>
+                <el-button size="small">邮寄</el-button>
+              </template>
+            </el-table-column>
+        </el-table>
+
+        <!--分页-->
+        <el-col :span="24" class="toolbar">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[10, 20, 50, 100]"
+                :page-size="size"
+                layout="total, sizes, prev, pager, next"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+    </section>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            // 搜索条件
+            keyword: null,
+            courseName: null,
+
+            // 表格相关
+            tableHeight: 0,
+            listLoading: false,
+            total: 0,
+            page: 1,
+            size: 20,
+            list: []
+        }
+    },
+    methods: {
+        // 搜索考试信息
+        searchList() {
+            this.page = 1;
+            this.getList();
+        },
+
+        // 获取考试信息列表
+        getList() {
+            // 待接口联调
+            return
+            this.listLoading = true;
+            this.http.post('/exam-info/pageList', {
+                name: this.keyword,
+                courseName: this.courseName,
+                page: this.page,
+                size: this.size
+            }, res => {
+                this.list = res.data.records;
+                this.total = res.data.total;
+                this.listLoading = false;
+            }, () => {
+                this.listLoading = false;
+            })
+        },
+
+        // 分页相关
+        handleCurrentChange(val) {
+            this.page = val;
+            this.getList();
+        },
+        handleSizeChange(val) {
+            this.page = 1;
+            this.size = val;
+            this.getList();
+        }
+    },
+    created() {
+        let height = window.innerHeight;
+        this.tableHeight = height - 195;
+        const that = this;
+        window.onresize = function temp() {
+            that.tableHeight = window.innerHeight - 195;
+        };
+    },
+    mounted() {
+        this.getList();
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+    padding-bottom: 10px;
+}
+</style>

fhKeeper/formulahousekeeper/course-pc/src/views/examCertification/examCertification.vue → fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examCertification.vue


+ 241 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examRegistrationReview.vue

@@ -0,0 +1,241 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true" @submit.native.prevent>
+                <el-form-item label="报名时间">
+                    <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
+                        end-placeholder="结束日期" size="small">
+                    </el-date-picker>
+                </el-form-item>
+                <el-form-item label="姓名">
+                    <el-input v-model="nameKeyword" placeholder="请输入姓名" clearable size="small"></el-input>
+                </el-form-item>
+                <el-form-item label="课程">
+                    <el-input v-model="courseKeyword" placeholder="请输入课程名称" clearable size="small"></el-input>
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" @click="searchList" size="small">搜索</el-button>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--列表-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;"
+            @selection-change="handleSelectionChange">
+            <el-table-column type="selection" width="55" align="center"></el-table-column>
+            <el-table-column prop="parentCourseName" label="考试课程" min-width="240"></el-table-column>
+            <el-table-column prop="name" label="姓名" width="100" align="center"></el-table-column>
+            <el-table-column prop="sex" label="性别" width="80" align="center"></el-table-column>
+            <el-table-column prop="school" label="工作单位" min-width="150" align="center"></el-table-column>
+            <el-table-column prop="phone" label="手机号码" width="120" align="center"></el-table-column>
+            <el-table-column prop="idType" label="证件类型" width="100" align="center"></el-table-column>
+            <el-table-column prop="idNumber" label="证件号码" width="180" align="center"></el-table-column>
+            <el-table-column prop="email" label="邮箱" width="180" align="center"></el-table-column>
+            <el-table-column prop="invoiceType" label="发票类型" width="140" align="center"></el-table-column>
+            <el-table-column prop="isIndivdual" label="开票主体" width="140" align="center"></el-table-column>
+            <el-table-column prop="invoiceHeader" label="开票名称" width="140" align="center"></el-table-column>
+            <el-table-column prop="invoiceDate" label="开票日期" width="120" align="center"></el-table-column>
+            <el-table-column prop="taxCode" label="税号" width="150" align="center"></el-table-column>
+            <el-table-column prop="address" label="联系地址" min-width="340"></el-table-column>
+            <el-table-column label="证件照" width="120" align="center" fixed="right">
+                <template slot-scope="scope">
+                    <img v-if="scope.row.portraitUrl" :src="scope.row.portraitUrl" class="id-photo"
+                        @click="previewImage(scope.row.portraitUrl)" />
+                    <span v-else>无照片</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" width="180" class-name="btns" header-align="center" fixed="right">
+                <template slot-scope="scope">
+                    <el-button size="small" type="success" @click="approve(scope.row)">通过</el-button>
+                    <el-button size="small" type="danger" @click="reject(scope.row)">驳回</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <!--工具条-->
+        <el-col :span="24" class="toolbar">
+            <el-button type="success" @click="batchApprove" :disabled="selectedIds.length === 0"
+                size="small">全部通过</el-button>
+            <el-button type="danger" @click="batchReject" :disabled="selectedIds.length === 0"
+                size="small">全部驳回</el-button>
+            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+                :page-sizes="[10, 20, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next"
+                :total="total" style="float:right;"></el-pagination>
+        </el-col>
+    </section>
+</template>
+
+<script>
+import { post, checkAndAddUpload } from '../../api'
+import { fixedDataGender, fixedDataCertificateType, fixedDataOrNot, fixedDataInvoiceSubject, fixedDatainvoiceType } from '../../common/js/fixedData'
+export default {
+    data() {
+        return {
+            // 搜索条件
+            dateRange: [],
+            nameKeyword: '',
+            courseKeyword: '',
+
+            // 表格相关
+            tableHeight: 0,
+            listLoading: false,
+            total: 0,
+            page: 1,
+            size: 20,
+            list: [],
+            selectedIds: [],
+        }
+    },
+    methods: {
+        // 搜索列表
+        searchList() {
+            this.page = 1;
+            this.getList();
+        },
+        // 图片预览
+        previewImage(url) {
+            this.$viewerApi({
+                images: [url],
+                options: {
+                    initialViewIndex: 0,
+                    toolbar: {
+                        zoomIn: 1,
+                        zoomOut: 1,
+                        oneToOne: 1,
+                        reset: 1,
+                        prev: 1,
+                        next: 1,
+                        rotateLeft: 1,
+                        rotateRight: 1,
+                        flipHorizontal: 1,
+                        flipVertical: 1
+                    }
+                }
+            })
+        },
+        // 获取列表
+        getList() {
+            this.listLoading = true;
+            post(`/exam-check/getAuditList`, { pageSize: this.size, pageIndex: this.page }).then(res => {
+                const { records = [], total = 0 } = res.data
+                this.total = total
+                this.list = records.map(item => {
+                    const { courseId, courseName, id, examStatus, isOnlineCourse } = item
+                    const { sex, idType, invoiceType, isIndivdual } = item.userExamInfo || {}
+                    return {
+                        ...item.userExamInfo,
+                        parenCourseId: courseId,
+                        parentCourseName: courseName,
+                        parentId: id,
+                        parentExamStatus: examStatus,
+                        parentIsOnlineCourse: isOnlineCourse,
+                        sex: fixedDataGender.find(val => val.value == (sex ? 1 : 0)).label,
+                        idType: fixedDataCertificateType.find(val => val.value == idType).label,
+                        invoiceType: fixedDatainvoiceType.find(val => val.value == invoiceType).label,
+                        isIndivdual: fixedDataInvoiceSubject.find(val => val.value == (isIndivdual ? 1 : 0)).label,
+                    }
+                })
+            }).finally(() => {
+                this.listLoading = false;
+            })
+        },
+
+        // 分页相关
+        handleCurrentChange(val) {
+            this.page = val;
+            this.getList();
+        },
+        handleSizeChange(val) {
+            this.page = 1;
+            this.size = val;
+            this.getList();
+        },
+
+        // 选择变化
+        handleSelectionChange(val) {
+            this.selectedIds = val.map(item => item.id);
+        },
+
+        // 通过单个
+        approve(row) {
+            this.$confirm('确认通过该报名申请?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                console.log('通过:', row.id);
+            });
+        },
+
+        // 驳回单个
+        reject(row) {
+            this.$confirm('确认驳回该报名申请?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                console.log('驳回:', row.id);
+            });
+        },
+
+        // 批量通过
+        batchApprove() {
+            if (this.selectedIds.length === 0) return;
+
+            this.$confirm(`确认通过选中的${this.selectedIds.length}条报名申请?`, '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                console.log('批量通过:', this.selectedIds);
+            });
+        },
+
+        // 批量驳回
+        batchReject() {
+            if (this.selectedIds.length === 0) return;
+
+            this.$confirm(`确认驳回选中的${this.selectedIds.length}条报名申请?`, '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                console.log('批量驳回:', this.selectedIds);
+            });
+        }
+    },
+
+    created() {
+        let height = window.innerHeight;
+        this.tableHeight = height - 195;
+        const that = this;
+        window.onresize = function temp() {
+            that.tableHeight = window.innerHeight - 195;
+        };
+    },
+
+    mounted() {
+        this.getList();
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+    padding-bottom: 10px;
+}
+
+.btns .el-button {
+    margin-left: 10px;
+    margin-bottom: 5px;
+}
+
+.id-photo {
+    width: 40px;
+    height: 40px;
+    object-fit: cover;
+    border-radius: 10px;
+    cursor: pointer;
+}
+</style>

+ 113 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examResults.vue

@@ -0,0 +1,113 @@
+<template>
+    <section>
+        <!--搜索栏-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true" @submit.native.prevent>
+                <el-form-item label="姓名">
+                    <el-input v-model="keyword" placeholder="请输入" clearable @change="searchList"
+                        size="small"></el-input>
+                </el-form-item>
+                <el-form-item label="课程名称">
+                    <el-input v-model="courseName" placeholder="请输入" clearable @change="searchList"
+                        size="small"></el-input>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--表格-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+            <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+            <el-table-column prop="course" label="姓名" min-width="120" align="center"></el-table-column>
+            <el-table-column prop="course" label="考试课程" min-width="180" align="center"></el-table-column>
+            <el-table-column prop="name" label="考试结果" min-width="120" align="center"></el-table-column>
+            <el-table-column prop="account" label="考试分数" min-width="150" align="center"></el-table-column>
+        </el-table>
+
+        <!--分页-->
+        <el-col :span="24" class="toolbar">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[10, 20, 50, 100]"
+                :page-size="size"
+                layout="total, sizes, prev, pager, next"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+    </section>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            // 搜索条件
+            keyword: null,
+            courseName: null,
+
+            // 表格相关
+            tableHeight: 0,
+            listLoading: false,
+            total: 0,
+            page: 1,
+            size: 20,
+            list: []
+        }
+    },
+    methods: {
+        // 搜索考试信息
+        searchList() {
+            this.page = 1;
+            this.getList();
+        },
+
+        // 获取考试信息列表
+        getList() {
+            // 待接口联调
+            return
+            this.listLoading = true;
+            this.http.post('/exam-info/pageList', {
+                name: this.keyword,
+                courseName: this.courseName,
+                page: this.page,
+                size: this.size
+            }, res => {
+                this.list = res.data.records;
+                this.total = res.data.total;
+                this.listLoading = false;
+            }, () => {
+                this.listLoading = false;
+            })
+        },
+
+        // 分页相关
+        handleCurrentChange(val) {
+            this.page = val;
+            this.getList();
+        },
+        handleSizeChange(val) {
+            this.page = 1;
+            this.size = val;
+            this.getList();
+        }
+    },
+    created() {
+        let height = window.innerHeight;
+        this.tableHeight = height - 195;
+        const that = this;
+        window.onresize = function temp() {
+            that.tableHeight = window.innerHeight - 195;
+        };
+    },
+    mounted() {
+        this.getList();
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+    padding-bottom: 10px;
+}
+</style>

+ 107 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/examinationManagement/examinationInformation.vue

@@ -0,0 +1,107 @@
+<template>
+    <section>
+        <!--搜索栏-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true" @submit.native.prevent>
+                <el-form-item label="姓名">
+                    <el-input v-model="keyword" placeholder="请输入姓名" clearable @change="searchList"
+                        size="small"></el-input>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--表格-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+            <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+            <el-table-column prop="course" label="考试课程" min-width="180" align="center"></el-table-column>
+            <el-table-column prop="name" label="姓名" min-width="120" align="center"></el-table-column>
+            <el-table-column prop="account" label="账号" min-width="150" align="center"></el-table-column>
+            <el-table-column prop="password" label="密码" min-width="150" align="center"></el-table-column>
+        </el-table>
+
+        <!--分页-->
+        <el-col :span="24" class="toolbar">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[10, 20, 50, 100]"
+                :page-size="size"
+                layout="total, sizes, prev, pager, next"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+    </section>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            // 搜索条件
+            keyword: null,
+
+            // 表格相关
+            tableHeight: 0,
+            listLoading: false,
+            total: 0,
+            page: 1,
+            size: 20,
+            list: []
+        }
+    },
+    methods: {
+        // 搜索考试信息
+        searchList() {
+            this.page = 1;
+            this.getList();
+        },
+
+        // 获取考试信息列表
+        getList() {
+            // 待接口联调
+            return
+            this.listLoading = true;
+            this.http.post('/exam-info/pageList', {
+                name: this.keyword,
+                page: this.page,
+                size: this.size
+            }, res => {
+                this.list = res.data.records;
+                this.total = res.data.total;
+                this.listLoading = false;
+            }, () => {
+                this.listLoading = false;
+            })
+        },
+
+        // 分页相关
+        handleCurrentChange(val) {
+            this.page = val;
+            this.getList();
+        },
+        handleSizeChange(val) {
+            this.page = 1;
+            this.size = val;
+            this.getList();
+        }
+    },
+    created() {
+        let height = window.innerHeight;
+        this.tableHeight = height - 195;
+        const that = this;
+        window.onresize = function temp() {
+            that.tableHeight = window.innerHeight - 195;
+        };
+    },
+    mounted() {
+        this.getList();
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+    padding-bottom: 10px;
+}
+</style>

+ 111 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/orderAndFinancialManagement/orderManagement.vue

@@ -0,0 +1,111 @@
+<template>
+  <section>
+    <!--搜索栏-->
+    <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+      <el-form :inline="true" @submit.native.prevent>
+        <el-form-item label="姓名">
+          <el-input v-model="keyword" placeholder="请输入" clearable @change="searchList" size="small"></el-input>
+        </el-form-item>
+        <el-form-item label="课程名称">
+          <el-input v-model="courseName" placeholder="请输入" clearable @change="searchList" size="small"></el-input>
+        </el-form-item>
+        <el-form-item label="课程分类">
+          <el-select v-model="courseType" placeholder="请选择" size="small" clearable @change="searchList">
+            <!-- <el-option label="线上课" :value="0"></el-option> -->
+            <!-- <el-option label="线下课" :value="1"></el-option> -->
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </el-col>
+
+    <!--表格-->
+    <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+      <el-table-column prop="course" label="姓名" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="name" label="课程分类" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="course" label="课程名称" min-width="180" align="center"></el-table-column>
+      <el-table-column prop="name" label="价格" min-width="120" align="center"></el-table-column>
+    </el-table>
+
+    <!--分页-->
+    <el-col :span="24" class="toolbar">
+      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :page-sizes="[10, 20, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next" :total="total"
+        style="float:right;"></el-pagination>
+    </el-col>
+  </section>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      // 搜索条件
+      keyword: null,
+      courseName: null,
+      courseType: null,
+
+      // 表格相关
+      tableHeight: 0,
+      listLoading: false,
+      total: 0,
+      page: 1,
+      size: 20,
+      list: []
+    }
+  },
+  methods: {
+    // 搜索考试信息
+    searchList() {
+      this.page = 1;
+      this.getList();
+    },
+
+    // 获取考试信息列表
+    getList() {
+      // 待接口联调
+      return
+      this.listLoading = true;
+      this.http.post('/exam-info/pageList', {
+        name: this.keyword,
+        courseName: this.courseName,
+        page: this.page,
+        size: this.size
+      }, res => {
+        this.list = res.data.records;
+        this.total = res.data.total;
+        this.listLoading = false;
+      }, () => {
+        this.listLoading = false;
+      })
+    },
+
+    // 分页相关
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.page = 1;
+      this.size = val;
+      this.getList();
+    }
+  },
+  created() {
+    let height = window.innerHeight;
+    this.tableHeight = height - 195;
+    const that = this;
+    window.onresize = function temp() {
+      that.tableHeight = window.innerHeight - 195;
+    };
+  },
+  mounted() {
+    this.getList();
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+  padding-bottom: 10px;
+}
+</style>

fhKeeper/formulahousekeeper/course-pc/src/views/offlineTraining/offlineTraining.vue → fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/offlineTraining.vue


fhKeeper/formulahousekeeper/course-pc/src/views/offlineRegistration/registration.vue → fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/registration.vue


+ 122 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/student.vue

@@ -0,0 +1,122 @@
+<template>
+  <section>
+    <!--搜索栏-->
+    <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+      <el-form :inline="true" @submit.native.prevent>
+        <el-form-item label="姓名">
+          <el-input v-model="keyword" placeholder="请输入" clearable @change="searchList" size="small"></el-input>
+        </el-form-item>
+        <el-form-item label="课程名称">
+          <el-input v-model="courseName" placeholder="请输入" clearable @change="searchList" size="small"></el-input>
+        </el-form-item>
+
+        <el-button type="primary" size="small" style="float: right;">导出</el-button>
+      </el-form>
+    </el-col>
+
+    <!--表格-->
+    <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+      <el-table-column prop="name" label="姓名" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="gender" label="性别" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="id_type" label="证件类型" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="id_number" label="证件号码" min-width="180" align="center"></el-table-column>
+      <el-table-column prop="phone" label="手机号码" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="work_unit" label="工作单位" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="address" label="联系地址" min-width="180" align="center"></el-table-column>
+      <el-table-column prop="project_name" label="项目名称" min-width="180" align="center"></el-table-column>
+      <el-table-column prop="project_level" label="项目等级" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="start_date" label="培训开始日期" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="end_date" label="培训结束日期" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="study_hours" label="培训学时" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="score" label="评定成绩" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="certificate_date" label="证书日期" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="photo" label="照片" min-width="100" align="center">
+        <template slot-scope="scope">
+          <img :src="scope.row.photo" alt="photo" style="width: 50px; height: 50px; border-radius: 50%;" />
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!--分页-->
+    <el-col :span="24" class="toolbar">
+      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :page-sizes="[10, 20, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next" :total="total"
+        style="float:right;"></el-pagination>
+    </el-col>
+  </section>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      // 搜索条件
+      keyword: null,
+      courseName: null,
+
+      // 表格相关
+      tableHeight: 0,
+      listLoading: false,
+      total: 0,
+      page: 1,
+      size: 20,
+      list: []
+    }
+  },
+  methods: {
+    // 搜索考试信息
+    searchList() {
+      this.page = 1;
+      this.getList();
+    },
+
+    // 获取考试信息列表
+    getList() {
+      // 待接口联调
+      return
+      this.listLoading = true;
+      this.http.post('/exam-info/pageList', {
+        name: this.keyword,
+        courseName: this.courseName,
+        page: this.page,
+        size: this.size
+      }, res => {
+        this.list = res.data.records;
+        this.total = res.data.total;
+        this.listLoading = false;
+      }, () => {
+        this.listLoading = false;
+      })
+    },
+
+    // 分页相关
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.page = 1;
+      this.size = val;
+      this.getList();
+    }
+  },
+  created() {
+    let height = window.innerHeight;
+    this.tableHeight = height - 195;
+    const that = this;
+    window.onresize = function temp() {
+      that.tableHeight = window.innerHeight - 195;
+    };
+  },
+  mounted() {
+    this.getList();
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+  padding-bottom: 10px;
+}
+</style>

+ 114 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/trainingClassManagement/studentPayment.vue

@@ -0,0 +1,114 @@
+<template>
+  <section>
+    <!--搜索栏-->
+    <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+      <el-form :inline="true" @submit.native.prevent>
+        <el-form-item label="姓名">
+          <el-input v-model="keyword" placeholder="请输入" clearable @change="searchList" size="small"></el-input>
+        </el-form-item>
+        <el-form-item label="课程名称">
+          <el-input v-model="courseName" placeholder="请输入" clearable @change="searchList" size="small"></el-input>
+        </el-form-item>
+
+        <el-button type="primary" size="small" style="float: right;">导出</el-button>
+      </el-form>
+    </el-col>
+
+    <!--表格-->
+    <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+      <el-table-column prop="name" label="学员姓名" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="id_number" label="证件号码" min-width="180" align="center"></el-table-column>
+      <el-table-column prop="training_fee" label="培训费/认证费" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="data_fee" label="资料费" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="other_fee_1" label="其他费用1" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="other_fee_2" label="其他费用2" min-width="120" align="center"></el-table-column>
+      <el-table-column prop="payment_date" label="打款日期" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="remitter_name" label="汇款方名称" min-width="180" align="center"></el-table-column>
+      <el-table-column prop="recipient_unit" label="收款单位" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="payment_method" label="打款方式" min-width="150" align="center"></el-table-column>
+      <el-table-column prop="invoice_date" label="开票日期" min-width="150" align="center"></el-table-column>
+    </el-table>
+
+    <!--分页-->
+    <el-col :span="24" class="toolbar">
+      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :page-sizes="[10, 20, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next" :total="total"
+        style="float:right;"></el-pagination>
+    </el-col>
+  </section>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      // 搜索条件
+      keyword: null,
+      courseName: null,
+
+      // 表格相关
+      tableHeight: 0,
+      listLoading: false,
+      total: 0,
+      page: 1,
+      size: 20,
+      list: []
+    }
+  },
+  methods: {
+    // 搜索考试信息
+    searchList() {
+      this.page = 1;
+      this.getList();
+    },
+
+    // 获取考试信息列表
+    getList() {
+      // 待接口联调
+      return
+      this.listLoading = true;
+      this.http.post('/exam-info/pageList', {
+        name: this.keyword,
+        courseName: this.courseName,
+        page: this.page,
+        size: this.size
+      }, res => {
+        this.list = res.data.records;
+        this.total = res.data.total;
+        this.listLoading = false;
+      }, () => {
+        this.listLoading = false;
+      })
+    },
+
+    // 分页相关
+    handleCurrentChange(val) {
+      this.page = val;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.page = 1;
+      this.size = val;
+      this.getList();
+    }
+  },
+  created() {
+    let height = window.innerHeight;
+    this.tableHeight = height - 195;
+    const that = this;
+    window.onresize = function temp() {
+      that.tableHeight = window.innerHeight - 195;
+    };
+  },
+  mounted() {
+    this.getList();
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+  padding-bottom: 10px;
+}
+</style>

fhKeeper/formulahousekeeper/course-pc/src/views/customerServiceCenter/customerServiceCenter.vue → fhKeeper/formulahousekeeper/course-pc/src/views/userAndMessageManagement/customerServiceCenter.vue


fhKeeper/formulahousekeeper/course-pc/src/views/myMessage/myMessage.vue → fhKeeper/formulahousekeeper/course-pc/src/views/userAndMessageManagement/myMessage.vue


+ 158 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/userAndMessageManagement/userManagement.vue

@@ -0,0 +1,158 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true" @submit.native.prevent>
+                <el-form-item label="注册时间">
+                    <el-date-picker
+                        v-model="dateRange"
+                        type="daterange"
+                        range-separator="至"
+                        start-placeholder="开始日期"
+                        end-placeholder="结束日期"
+                        size="small"
+                        @change="searchList">
+                    </el-date-picker>
+                </el-form-item>
+                <el-form-item label="姓名">
+                    <el-input v-model="nameKeyword" placeholder="请输入姓名" clearable size="small" @change="searchList"></el-input>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--列表-->
+        <el-table 
+            :data="list" 
+            highlight-current-row 
+            v-loading="listLoading" 
+            :height="tableHeight" 
+            style="width: 100%;" >
+            <el-table-column prop="courseName" label="用户名" min-width="120" align="center"></el-table-column>
+            <el-table-column prop="name" label="手机号" width="100" align="center"></el-table-column>
+            <el-table-column prop="company" label="注册时间" min-width="150" align="center"></el-table-column>
+            <el-table-column label="操作" width="180" class-name="btns" header-align="center" fixed="right">
+                <template slot-scope="scope">
+                    <el-button size="small" type="success">重置密码</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <!--工具条-->
+        <el-col :span="24" class="toolbar">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[10, 20, 50, 100]"
+                :page-size="size"
+                layout="total, sizes, prev, pager, next"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+    </section>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            // 搜索条件
+            dateRange: [],
+            nameKeyword: '',
+            courseKeyword: '',
+
+            // 表格相关
+            tableHeight: 0,
+            listLoading: false,
+            total: 0,
+            page: 1,
+            size: 20,
+            list: [],
+            selectedIds: [],
+        }
+    },
+    methods: {
+        // 搜索列表
+        searchList() {
+            this.page = 1;
+            this.getList();
+        },
+
+        // 获取列表
+        getList() {
+            this.listLoading = true;
+            // 模拟数据
+            setTimeout(() => {
+                this.list = [
+                    {
+                        id: 1,
+                        courseName: 'GCP认证考试',
+                        name: '张三',
+                        gender: '男',
+                        company: '某某医院',
+                        phone: '13800138000',
+                        idType: '身份证',
+                        idNumber: '110101199003072345',
+                        address: '北京市朝阳区某某路1号',
+                        email: 'zhangsan@example.com',
+                        invoiceType: '增值税普通发票',
+                        invoiceName: '某某医院',
+                        invoiceDate: '2025-07-01',
+                        taxNumber: '123456789012345',
+                        idPhoto: ''
+                    }
+                ];
+                this.total = 1;
+                this.listLoading = false;
+            }, 500);
+        },
+
+        // 分页相关
+        handleCurrentChange(val) {
+            this.page = val;
+            this.getList();
+        },
+        handleSizeChange(val) {
+            this.page = 1;
+            this.size = val;
+            this.getList();
+        },
+
+        // 选择变化
+        handleSelectionChange(val) {
+            this.selectedIds = val.map(item => item.id);
+        },
+    },
+
+    created() {
+        let height = window.innerHeight;
+        this.tableHeight = height - 195;
+        const that = this;
+        window.onresize = function temp() {
+            that.tableHeight = window.innerHeight - 195;
+        };
+    },
+
+    mounted() {
+        this.getList();
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+    padding-bottom: 10px;
+}
+
+.btns .el-button {
+    margin-left: 10px;
+    margin-bottom: 5px;
+}
+
+.id-photo {
+    width: 80px;
+    height: 80px;
+    object-fit: cover;
+    border-radius: 10px;
+}
+</style>

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

@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>客户管家</title>
+    <title>智能客户管家CRM</title>
     <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" referrerpolicy="origin"></script>
     <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" referrerpolicy="origin"></script>
     <!-- <script src="https://s.url.cn/qqun/qun/qqweb/m/qun/confession/js/vconsole.min.js "></script> -->

BIN
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/ddje.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/kehu.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/lsjh.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/lxr.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/sjje.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/xsdd.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/assets/image/module/xzxs.png


+ 9 - 4
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/page/footer.vue

@@ -1,11 +1,11 @@
 <template>
-  <div class="w-full bg-white">
+  <div class="w-full bg-white footer-box">
     <van-tabbar v-model="currentRouteName" safe-area-inset-bottom :fixed="false" @change="toPath">
       <template v-for="item in tabBarOption">
-        <van-tabbar-item :name="item.pathName" :icon="item.icon" v-if="item.pathName != 'news'">{{ item.title
-          }}</van-tabbar-item>
+        <van-tabbar-item :name="item.pathName" :icon="item.icon" v-if="item.pathName != 'news'"><span class="text-smalls">{{ item.title
+          }}</span></van-tabbar-item>
         <van-tabbar-item :name="item.pathName" :icon="item.icon"
-          :dot="userInfo.numberOfMessages > 0 ? true : false" v-else>{{ item.title }}</van-tabbar-item>
+          :dot="userInfo.numberOfMessages > 0 ? true : false" v-else><span class="text-smalls">{{ item.title }}</span></van-tabbar-item>
       </template>
     </van-tabbar>
   </div>
@@ -38,4 +38,9 @@ useLifecycle({
 
 <style lang='scss' scoped>
 /* 样式代码 */
+.footer-box {
+  .text-smalls {
+    font-size: 14px;
+  }
+}
 </style>

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

@@ -1,5 +1,5 @@
 <template>
-  <Page :title="`${currentRoutingInformation?.name}${addOrEdit ? '编辑' : '新增'}`">
+  <Page :title="`${currentRoutingInformation?.name || ''}${addOrEdit ? '编辑' : '新增'}`">
     <template v-slot:body>
       <div class="w-full h-full">
         <van-skeleton title :row="10" v-if="pageLoading" class="w-full h-full" />

+ 21 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/addEditor.vue

@@ -35,6 +35,7 @@ import { ref, onActivated } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { GET_BUSINESS_OPPORTUNITY_DETAILS, NEW_BUSINESS_OPPORTUNITY_EDITING } from "@hooks/useApi"
 import { defaultRelatedProductDataFields } from "@utility/defaultData"
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import dayjs from 'dayjs';
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
@@ -86,12 +87,27 @@ function onSubmit() {
     toastLoading('保存中', 0)
     requests.post(NEW_BUSINESS_OPPORTUNITY_EDITING, { ...commonUtil.getFromValue({ ...newForm }) }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['business']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
     }).catch((err) => {
       toastFail('保存失败:' + err.msg)

+ 28 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/contacts/addEditor.vue

@@ -18,6 +18,7 @@ import CustomerForm from '@components/common/formForm/formView.vue'
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
 import { CONTACT_PERSON_ADDITION_EDITOR, CUSTOMER_ADDED_EDITOR } from "@hooks/useApi"
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import useRouterStore from "@store/useRouterStore.js";
 import commonUtil from "@utility/commonUtil"
 const router = useRouterStore()
@@ -41,13 +42,35 @@ function onSubmit() {
     const url = props.formValue.id ? '/contacts/updateContacts' : CONTACT_PERSON_ADDITION_EDITOR
     requests.post(url, { ...commonUtil.getFromValue({ ...props.formValue, ...res.data }) }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['contacts']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
+      // setTimeout(() => {
+      //   router.navigateBack({
+      //     success: () => {
+      //       router.eventEmit('moduleListRefreshData', {})
+      //     }
+      //   })
+      // }, 2000)
     }).catch((err) => {
       toastFail('保存失败:' + err.msg)
     })

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

@@ -139,6 +139,7 @@ import FoldingPanel from '@components/common/foldingPanel.vue';
 import dayjs from 'dayjs';
 import commonUtil from "@utility/commonUtil"
 import { number } from 'echarts';
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 
 import TreeSelect from "@components/common/treeSelect/selectTree.vue"
 
@@ -298,13 +299,35 @@ function onSubmit() {
       departmentId: departmentRow.value.sureDepartmentId
     }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['contract']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
+      // setTimeout(() => {
+      //   router.navigateBack({
+      //     success: () => {
+      //       router.eventEmit('moduleListRefreshData', {})
+      //     }
+      //   })
+      // }, 2000)
     }).catch((err) => {
       toastFail('保存失败:' + err.msg)
     })

+ 28 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/customer/addEditor.vue

@@ -18,6 +18,7 @@ import CustomerForm from '@components/common/formForm/formView.vue'
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
 import { CUSTOMER_ADDED_EDITOR } from "@hooks/useApi"
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import useRouterStore from "@store/useRouterStore.js";
 import commonUtil from "@utility/commonUtil"
 
@@ -40,13 +41,35 @@ function onSubmit() {
     toastLoading('保存中', 0)
     requests.post(CUSTOMER_ADDED_EDITOR, { ...commonUtil.getFromValue({ ...props.formValue, ...res.data }) }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['customer']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
+      // setTimeout(() => {
+      //   router.navigateBack({
+      //     success: () => {
+      //       router.eventEmit('moduleListRefreshData', {})
+      //     }
+      //   })
+      // }, 2000)
     }).catch(() => {
       toastFail('保存失败')
     })

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

@@ -40,6 +40,7 @@ import { ref, onActivated } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { OBTAIN_ORDER_RELATED_PRODUCTS, ORDER_ADDITION_EDITING } from "@hooks/useApi"
 import { defaultRelatedProductDataFields } from "@utility/defaultData"
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import dayjs from 'dayjs';
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
@@ -84,13 +85,35 @@ function onSubmit() {
     toastLoading('保存中', 0)
     requests.post(ORDER_ADDITION_EDITING, { ...commonUtil.getFromValue({ ...formVal }) }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['order']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
+      // setTimeout(() => {
+      //   router.navigateBack({
+      //     success: () => {
+      //       router.eventEmit('moduleListRefreshData', {})
+      //     }
+      //   })
+      // }, 2000)
     }).catch((err) => {
       toastFail('保存失败:' + err.msg)
     })

+ 28 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/product/addEditor.vue

@@ -18,6 +18,7 @@ import CustomerForm from '@components/common/formForm/formView.vue'
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
 import { PRODUCT_ADD_EDITOR } from "@hooks/useApi"
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import useRouterStore from "@store/useRouterStore.js";
 import commonUtil from "@utility/commonUtil"
 
@@ -40,13 +41,35 @@ function onSubmit() {
     toastLoading('保存中', 0)
     requests.post(PRODUCT_ADD_EDITOR, { ...commonUtil.getFromValue({ ...props.formValue, ...res.data }) }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['product']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
+      // setTimeout(() => {
+      //   router.navigateBack({
+      //     success: () => {
+      //       router.eventEmit('moduleListRefreshData', {})
+      //     }
+      //   })
+      // }, 2000)
     }).catch((err) => {
       toastFail(err.msg)
     })

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

@@ -194,6 +194,7 @@ import { ref, onActivated, computed } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { fixedFieldTaskType, fixedFieldPriority, fixedFieldRepetitiveType } from '@utility/defaultData.js';
 import { GET_ALL_CUSTOMERSLIST, GET_ALL_BUSINESS_OPPORTUNITIES, GET_SALES_ORDER_LIST, GET_OBTAIN_ALL_CLUES, GET_CONTACTS_WITH_MORE_I_DS, TASK_ADD_EDIT, MODIFY_TASK } from "@hooks/useApi";
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
 import dayjs from 'dayjs';
@@ -290,13 +291,35 @@ function onSubmit() {
     const url = formValue.id ? MODIFY_TASK : TASK_ADD_EDIT
     requests.post(url, { ...commonUtil.getFromValue({ ...formValue }) }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['tasks']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
+      // setTimeout(() => {
+      //   router.navigateBack({
+      //     success: () => {
+      //       router.eventEmit('moduleListRefreshData', {})
+      //     }
+      //   })
+      // }, 2000)
     }).finally(() => {
 
     })

+ 28 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/thread/addEditor.vue

@@ -18,6 +18,7 @@ import CustomerForm from '@components/common/formForm/formView.vue'
 import requests from "@common/requests";
 import useToast from "@hooks/useToast"
 import { NEW_CLUE_EDITING } from "@hooks/useApi"
+import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import useRouterStore from "@store/useRouterStore.js";
 import commonUtil from "@utility/commonUtil"
 
@@ -40,13 +41,35 @@ function onSubmit() {
     toastLoading('保存中', 0)
     requests.post(NEW_CLUE_EDITING, { ...commonUtil.getFromValue({ ...props.formValue, ...res.data }) }).then(() => {
       toastSuccess('保存成功')
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
+      const jumpTo = routingInfos['thread']
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.eventEmit('moduleListRefreshData', {})
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'moduleList',
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+              router.emit('moduleListDetailParameter', {
+                row: JSON.stringify(jumpTo)
+              })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.eventEmit('moduleListRefreshData', {})
+            }
+          })
+        }
       }, 2000)
+      // setTimeout(() => {
+      //   router.navigateBack({
+      //     success: () => {
+      //       router.eventEmit('moduleListRefreshData', {})
+      //     }
+      //   })
+      // }, 2000)
     }).catch((err) => {
       toastFail('保存失败:' + err.msg)
     })

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

@@ -46,13 +46,17 @@ useLifecycle({
       .item {
         width: 50%;
         display: flex;
-        margin-top: 20px;
+        margin: 20px 0 10px 0;
 
         .item-img {
-          width: 54px;
-          height: 54px;
+          width: 44px;
+          height: 44px;
           margin-right: 6px;
         }
+
+        .xiaozhiti {
+          font-size: 12px;
+        }
       }
     }
   }

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

@@ -12,36 +12,36 @@
       :style="`height: ${expandAndCollapse ? usePxToVwView(user?.company?.isSimple == 1 ? 180 : 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>
+          <img src="/src/assets/image/module/kehu.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">新增客户</div>
             <div class="flex items-end">
-              <span class="text-[#3C84F3] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.custom?.customCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
         <div class="item" v-if="user?.company?.isSimple != 1">
-          <img src="/src/assets/image/salesKitlianxir.png" class="item-img" />
-          <div class="flex flex-col justify-center text=[#999999]">
-            <div>新增联系人</div>
+          <img src="/src/assets/image/module/lxr.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">新增联系人</div>
             <div class="flex items-end">
-              <span class="text-[#42DC9E] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.contacts?.contactsCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
 
         <div class="item" v-if="user?.company?.isSimple == 1">
-          <img src="/src/assets/image/salesKitlishi.png" class="item-img" />
-          <div class="flex flex-col justify-center text=[#999999]">
-            <div>新增{{ businessLabel }}</div>
+          <img src="/src/assets/image/module/sjje.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">新增{{ businessLabel }}</div>
             <div class="flex items-end">
-              <span class="text-[#F3893C] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.businessOpportunity?.businessOpportunityCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
@@ -49,24 +49,24 @@
 
       <div class="flex items-center w-full" v-if="user?.company?.isSimple != 1">
         <div class="item">
-          <img src="/src/assets/image/salesKitlishi.png" class="item-img" />
-          <div class="flex flex-col justify-center text=[#999999]">
-            <div>新增{{ businessLabel }}</div>
+          <img src="/src/assets/image/module/sjje.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">新增{{ businessLabel }}</div>
             <div class="flex items-end">
-              <span class="text-[#F3893C] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.businessOpportunity?.businessOpportunityCount || 0 }}
-              </span>
+              </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>
+          <img src="/src/assets/image/module/xsdd.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">新增销售订单</div>
             <div class="flex items-end">
-              <span class="text-[#A66AFF] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.salesOrder?.salesOrderCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
@@ -74,36 +74,36 @@
 
       <div class="flex items-center w-full">
         <div class="item" v-if="user?.company?.isSimple != 1">
-          <img src="/src/assets/image/salesKitjer.png" class="item-img" />
-          <div class="flex flex-col justify-center text=[#999999]">
-            <div>销售订单金额</div>
+          <img src="/src/assets/image/module/ddje.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">销售订单金额</div>
             <div class="flex items-end">
-              <span class="text-[#67DF2A] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.salesOrdersPrice?.salesOrdersPrice || 0 }}
-              </span>
+              </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>{{ businessLabel }}金额</div>
+          <img src="/src/assets/image/module/sjje.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">{{ businessLabel }}金额</div>
             <div class="flex items-end">
-              <span class="text-[#EED116] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.businessOpportunityPrice?.businessOpportunityPrice || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
 
         <div class="item" v-if="user?.company?.isSimple == 1">
-          <img src="/src/assets/image/salesKitxianshuo.png" class="item-img" />
-          <div class="flex flex-col justify-center text=[#999999]">
-            <div>新增线索</div>
+          <img src="/src/assets/image/module/xzxs.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">新增线索</div>
             <div class="flex items-end">
-              <span class="text-[#F44873] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.clue?.clueCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>
@@ -111,13 +111,13 @@
 
       <div class="flex items-center w-full" v-if="user?.company?.isSimple != 1">
         <div class="item">
-          <img src="/src/assets/image/salesKitxianshuo.png" class="item-img" />
-          <div class="flex flex-col justify-center text=[#999999]">
-            <div>新增线索</div>
+          <img src="/src/assets/image/module/xzxs.png" class="item-img" />
+          <div class="flex flex-col justify-center">
+            <div class="text-[#999999] xiaozhiti">新增线索</div>
             <div class="flex items-end">
-              <span class="text-[#F44873] text-size-in font-bold mr-1">
+              <span class="text-[#000000] text-size-in font-bold mr-1">
                 {{ salesBriefings?.clue?.clueCount || 0 }}
-              </span>
+              </span>
             </div>
           </div>
         </div>

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/index copy.vue

@@ -3,7 +3,7 @@
     <template v-slot:headerLeft>
       <div class="homeheaderleft">
         <img src="/src/assets/image/home_logo.png">
-        <div class="text-white">客户管家</div>
+        <div class="text-white">智能客户管家CRM</div>
       </div>
     </template>
     <template v-slot:headerRight>
@@ -35,7 +35,7 @@
       <!-- 显示对应的模块 -->
       <van-popup v-model:show="showModule" closeable position="bottom" round>
         <div class="newModuleAdded relative">
-          <div class="text-size-large text-[#474A56] absolute topTitle">客户管家</div>
+          <div class="text-size-large text-[#474A56] absolute topTitle">智能客户管家CRM</div>
           <div class="flex flex-wrap">
             <template v-for="(item) in moduleList" :key="item.id">
               <div class="w-16 flex flex-col items-center mrSpacing" @click.stop="toAddEditor(item)">

+ 17 - 6
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/index.vue

@@ -4,7 +4,7 @@
       <div class="homeheaderleft">
         <img src="/src/assets/image/home_logo.png">
         <!-- <div class="text-white">客户管家<ww-open-data :openid="useInfo.userInfo.name" type="userName"></ww-open-data></div> -->
-        <div class="text-white">客户管家</div>
+        <div class="text-white">智能客户管家CRM</div>
       </div>
     </template>
 
@@ -65,11 +65,11 @@
         </div>
         
         <!-- 弹出层 -->
-        <van-popup v-model:show="showBottom" position="bottom" :overlay-style="{ backgroundColor: 'rgba(0, 0, 0, 0.4)' }">
+        <van-popup v-model:show="showBottom" position="bottom" round :overlay-style="{ backgroundColor: 'rgba(0, 0, 0, 0.4)' }">
           <div class="bg-[#f6f6fa]">
             <div class="w-full text-center bg-white block-div" @click="quickListShow = true">快捷新建设置</div>
             <div class="w-full text-center bg-white block-div biankuang" @click="modulesListShow = true">常用功能设置</div>
-            <div class="w-full text-center mt-4 text-[red] bg-white block-div" @click="showBottom = false">取消</div>
+            <div class="w-full text-center mt-4 text-[red] bg-white block-div biankuangs" @click="showBottom = false">取消</div>
           </div>
         </van-popup>
         
@@ -99,6 +99,7 @@ import Footer from "@components/page/footer.vue";
 import requests from "@common/requests"
 import { GET_FREQUENTLY_USED_CONTACTS, GET_FAST_ACCESS_LIST, GET_ALL_ROUTING_PARAMETERS, COMMON_FUNCTIONS } from "@hooks/useApi";
 import useToast from "@hooks/useToast"
+import dayjs from 'dayjs';
 import { routingInfos, getRouterImg } from "@utility/generalVariables.js";
 import useRouterStore from "@store/useRouterStore.js";
 
@@ -149,7 +150,12 @@ function jumpAdd(rows) {
   if(rows.path == '/visitor') {
     router.navigateTo({
       pathName: 'addEditorVisitor',
-      success: () => {}
+      success: () => {
+        router.emit('addEditorVisitorParameter', {
+          row: JSON.stringify({}),
+          date: JSON.stringify(dayjs().format('YYYY-MM-DD') || {})
+        })
+      }
     })
     return
   }
@@ -398,11 +404,16 @@ useLifecycle({
 }
 
 .biankuang {
-  border-top: 1px solid #eceeef;
+  border-top: 2px solid #eceeef;
+}
+.biankuangs {
+  border-bottom: 4px solid #eceeef;
 }
 
 .block-div {
-  padding: 14px 0;
+  padding: 16px 0;
+  // font-weight: bold;
+  font-size: 15px;
 }
 
 .hoPlaceholderSymbol {

+ 6 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/my/index.vue

@@ -35,35 +35,35 @@
           )
         </div>
       </div>
-      <div class="flex flex-row items-center justify-between mt-3">
+      <div class="flex flex-row items-center justify-between mt-7">
         <div class="list-tile flex">
           <img src="../../../assets/image/gsmc.png" alt="" />
           <div class="list-tile-text">公司名称</div>
         </div>
         <div class="list-text">{{ userInfo.userInfo?.company?.companyName }}</div>
       </div>
-      <div class="flex flex-row items-center justify-between mt-3">
+      <div class="flex flex-row items-center justify-between mt-7">
         <div class="list-tile flex">
           <img src="../../../assets/image/dqzh.png" alt="" />
           <div class="list-tile-text">账号角色</div>
         </div>
         <div class="list-text">{{ userInfo.userInfo?.roleName }}</div>
       </div>
-      <div class="flex flex-row items-center justify-between mt-3">
+      <div class="flex flex-row items-center justify-between mt-7">
         <div class="list-tile flex">
           <img src="../../../assets/image/yxrq.png" alt="" />
           <div class="list-tile-text">有效日期</div>
         </div>
         <div class="list-text">{{ userInfo.userInfo?.company?.expirationDate }}</div>
       </div>
-      <div class="flex flex-row items-center justify-between mt-3" @click="instructions()">
+      <div class="flex flex-row items-center justify-between mt-7" @click="instructions()">
         <div class="list-tile flex">
           <img src="../../../assets/image/sysm.png" alt="" />
           <div class="list-tile-text">使用说明</div>
         </div>
         <img src="../../../assets/image/rightArrow.png" class="list-text-img"></img>
       </div>
-      <div class="flex flex-row items-center justify-between mt-3" @click="applicationMarket()">
+      <div class="flex flex-row items-center justify-between mt-7" @click="applicationMarket()">
         <div class="list-tile flex">
           <img src="../../../assets/image/yysc.png" alt="" />
           <div class="list-tile-text">应用市场</div>
@@ -225,6 +225,7 @@ useLifecycle({
   position: relative;
   top: 2px;
   margin-left: 10px;
+  font-size: 14px;
 }
 .list-text-img {
   width: 16px;

+ 21 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/visitorProgram/addEditorVisitor.vue

@@ -247,12 +247,28 @@ function onSubmit() {
     submitLoading.value = true
     requests.post(PLAN_TO_ADD_EDITORS, { ...data }).then((res) => {
       toastSuccess("保存成功")
+      const currentPages = router.$state.currentPages || []
+      const parentRoute = (currentPages[currentPages.length - 2] || {}).pathName
       setTimeout(() => {
-        router.navigateBack({
-          success: () => {
-            router.emit('visitorDetailsParameter', { row: JSON.stringify({...addOrEditRow.value}) })
-          }
-        })
+        if(parentRoute == 'home') {
+          router.redirectTo({
+            pathName: 'visitor',
+            success: () => {
+              router.emit('visitorDetailsParameter', { row: JSON.stringify({...addOrEditRow.value}) })
+            }
+          })
+        } else {
+          router.navigateBack({
+            success: () => {
+              router.emit('visitorDetailsParameter', { row: JSON.stringify({...addOrEditRow.value}) })
+            }
+          })
+        }
+        // router.navigateBack({
+        //   success: () => {
+        //     router.emit('visitorDetailsParameter', { row: JSON.stringify({...addOrEditRow.value}) })
+        //   }
+        // })
       }, 2000)
     }).catch(err => {
       toastFail(`保存失败:${err.msg}`)

+ 20 - 12
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java

@@ -8,10 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
-import com.management.platform.service.ContactsService;
-import com.management.platform.service.CustomService;
-import com.management.platform.service.WechatUserFollowService;
-import com.management.platform.service.WxCorpInfoService;
+import com.management.platform.service.*;
 import com.management.platform.service.impl.ExcelExportServiceImpl;
 import com.management.platform.util.HttpRespMsg;
 import org.apache.commons.lang3.StringUtils;
@@ -64,6 +61,8 @@ public class CustomController {
     private SalesOrderMapper salesOrderMapper;
     @Autowired
     private WechatUserFollowService wechatUserFollowService;
+    @Resource
+    private MiniBindUserService miniBindUserService;
 
 
     @RequestMapping("list")
@@ -217,17 +216,26 @@ public class CustomController {
                     String value = data.getInchargerName();
                     item.add(value);
                 }
-                Optional<WechatUserFollow> first = userFollows.stream().filter(u -> u.getOpenId() != null && StringUtils.isNotEmpty(data.getCustomName()) && u.getOpenId().equals(data.getCustomName())).findFirst();
-                if (first.isPresent()){
-                    LocalDateTime followTime = first.get().getFollowTime();
-                    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-                    DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
-                    item.add(dateFormatter.format(followTime));
-                    item.add(timeFormatter.format(followTime));
-                }else {
+                String unionId = data.getCustomName();
+                MiniBindUser miniBindUser = miniBindUserService.getOne(new QueryWrapper<MiniBindUser>().eq("unionid", unionId));
+                if (miniBindUser != null) {
+                    String openId = miniBindUser.getOpenid();
+                    Optional<WechatUserFollow> first = userFollows.stream().filter(u -> u.getOpenId() != null && StringUtils.isNotEmpty(openId) && u.getOpenId().equals(openId)).findFirst();
+                    if (first.isPresent()){
+                        LocalDateTime followTime = first.get().getFollowTime();
+                        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
+                        item.add(dateFormatter.format(followTime));
+                        item.add(timeFormatter.format(followTime));
+                    }else {
+                        item.add("");
+                        item.add("");
+                    }
+                } else {
                     item.add("");
                     item.add("");
                 }
+
                 dataList.add(item);
             }
         }

+ 17 - 20
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WechatCallbackController.java

@@ -197,22 +197,23 @@ public class WechatCallbackController {
                         .eq("openid", scanRecord.getOpenId()).eq("user_id",salesmanId));
 
                 if (miniBindUserList.isEmpty()){
-                    int count = customService.count(new QueryWrapper<Custom>().eq("custom_name", openId));
-                    if(count==0) {
-                        Custom custom = new Custom();
-                        custom.setCustomName(openId);//用户的openId
-                        custom.setIsDelete(0);
-                        custom.setCreateTime(new Date());
-                        if (StringUtils.isNotEmpty(salesmanId)) {
-                            custom.setInchargerId(salesmanId);
-                            User user = userService.getById(salesmanId);
-                            custom.setCompanyId(user != null ? user.getCompanyId() : null);
-                            customService.save(custom);
-                            log.info("新增客户成功");
-                        }
-                    }else {
-                        log.info("已存在custom_name为"+openId+"的客户");
-                    }
+                    //此处不生成custom,只有关注了后续的订阅号才算正式关注成功
+//                    int count = customService.count(new QueryWrapper<Custom>().eq("custom_name", openId));
+//                    if(count==0) {
+//                        Custom custom = new Custom();
+//                        custom.setCustomName(openId);//用户的openId
+//                        custom.setIsDelete(0);
+//                        custom.setCreateTime(new Date());
+//                        if (StringUtils.isNotEmpty(salesmanId)) {
+//                            custom.setInchargerId(salesmanId);
+//                            User user = userService.getById(salesmanId);
+//                            custom.setCompanyId(user != null ? user.getCompanyId() : null);
+//                            customService.save(custom);
+//                            log.info("新增客户成功");
+//                        }
+//                    }else {
+//                        log.info("已存在custom_name为"+openId+"的客户");
+//                    }
                     MiniBindUser miniBindUser = new MiniBindUser();
                     miniBindUser.setUserId(salesmanId)
                             .setOpenid(openId)
@@ -220,7 +221,6 @@ public class WechatCallbackController {
                             .setCreateTime(LocalDateTime.now());
                     miniBindUserService.save(miniBindUser);
                     log.info("用户关注服务号销售人员的二维码,绑定销售人员和用户id成功");
-
                 }
             }
         }
@@ -228,12 +228,9 @@ public class WechatCallbackController {
 
     //取消关注
     private void handleUnsubscribe(String openId) {
-
         followMapper.delete(new QueryWrapper<WechatUserFollow>().eq("open_id", openId));
-        customService.remove(new QueryWrapper<Custom>().eq("custom_name", openId));
         miniBindUserService.remove(new QueryWrapper<MiniBindUser>().eq("openid", openId));
         log.info("用户取消绑定销售人员成功");
-
     }
     
     private String successResponse(Element root) {

+ 204 - 0
fhKeeper/formulahousekeeper/management-platform-mld/src/main/java/com/management/platform/controller/BusinessTripController.java~

@@ -0,0 +1,204 @@
+package com.management.platform.controller;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.BusinessTrip;
+import com.management.platform.entity.LeaveSheet;
+import com.management.platform.entity.TimeType;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.TimeTypeMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.BusinessTripService;
+import com.management.platform.util.DockWithMLD;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2022-04-08
+ */
+@RestController
+@RequestMapping("/business-trip")
+public class BusinessTripController {
+
+    @Resource
+    UserMapper userMapper;
+    @Resource
+    BusinessTripService businessTripService;
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private TimeTypeMapper timeTypeMapper;
+
+
+
+    @RequestMapping("/add")
+    public HttpRespMsg add(BusinessTrip sheet) {
+        return businessTripService.add(sheet);
+
+    }
+
+    @RequestMapping("/modifyProject")
+    public HttpRespMsg modifyProject(BusinessTrip sheet) {
+        return businessTripService.modifyProject(sheet);
+
+    }
+
+
+    @RequestMapping("/cancel")
+    public HttpRespMsg cancel(Integer id) {
+        String userId = request.getHeader("Token");
+        return businessTripService.cancel(id, userId);
+    }
+
+
+    @RequestMapping("/delete")
+    public HttpRespMsg delete(Integer id) {
+        return businessTripService.delete(id);
+    }
+
+    @RequestMapping("/list")
+    public HttpRespMsg list(BusinessTrip sheet, @RequestParam Integer pageIndex, @RequestParam Integer pageSize,@RequestParam(defaultValue = "0") Integer checkState) {
+        return businessTripService.queryList(sheet, pageIndex, pageSize,checkState);
+    }
+
+    @RequestMapping("/auditList")
+    public HttpRespMsg auditList(BusinessTrip sheet, @RequestParam Integer pageIndex, @RequestParam Integer pageSize, @RequestParam(defaultValue = "0") Integer checkState) {
+        return businessTripService.auditList(sheet, pageIndex, pageSize, checkState);
+    }
+
+    @RequestMapping("/approve")
+    public HttpRespMsg approve(Integer id) {
+        return businessTripService.approve(id);
+    }
+    @RequestMapping("/deny")
+    public HttpRespMsg deny(Integer id, String reason) {
+        return businessTripService.deny(id, reason);
+
+    }
+
+    /**
+     *
+     * @param keyword 姓名(模糊匹配)
+     * @param startDate 开始日期
+     * @param endDate 结束日期
+     * @return
+     */
+    @RequestMapping("/summaryData")
+    public HttpRespMsg summaryData(String keyword, String startDate, String endDate) {
+        String userId = request.getHeader("Token");
+        return businessTripService.summaryData(keyword, startDate, endDate, userId);
+
+    }
+    @RequestMapping("/exportData")
+    public HttpRespMsg exportData(BusinessTrip sheet,@RequestParam(defaultValue = "0") Integer keyword, String startDate, String endDate){
+        String userId = request.getHeader("Token");
+        return businessTripService.exportData(sheet,keyword, startDate, endDate, userId);
+    }
+    @RequestMapping("/syncData")
+    public HttpRespMsg syncData(BusinessTrip sheet,@RequestParam(defaultValue = "0") Integer keyword, String startDate, String endDate){
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        TimeType one = timeTypeMapper.selectOne(new QueryWrapper<TimeType>().eq("company_id", companyId).eq("sync_fanwei", 1));
+        if(one==null){
+            msg.setError("暂无请假数据待同步");
+            return msg;
+        }
+        if (StringUtils.isEmpty(startDate)) {
+            msg.setError("开始时间不能为空");
+            return msg;
+        }
+        //时间跨度不能超过1个月
+        if (StringUtils.isEmpty(endDate)) {
+            msg.setError("结束时间不能为空");
+            return msg;
+        }
+        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        LocalDate parse = LocalDate.parse(startDate, df);
+        LocalDate parse1 = LocalDate.parse(endDate, df);
+        long between = parse1.toEpochDay() - parse.toEpochDay();
+        if (between > 31) {
+            msg.setError("时间跨度不能超过1个月");
+            return msg;
+        }
+        JSONObject jsonObject=new JSONObject();
+        DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String date = startDate + " 00:00:00," + endDate + " 23:59:59";
+        jsonObject.put("gmtFinished",date);
+        String jsonString = jsonObject.toJSONString();
+        List<User> allUserList=userMapper.selectList(new QueryWrapper<User>().eq("company_id",companyId));
+        List<BusinessTrip> businessTripList=new ArrayList<>();
+        List<BusinessTrip> oldBusinessTripList = businessTripService.list(new QueryWrapper<BusinessTrip>().eq("company_id", companyId));
+        DockWithMLD dockWithMLD=new DockWithMLD();
+        HttpRespMsg travelRecordMsg = dockWithMLD.getResult("http://10.1.10.51:20175/api/cube/restful/interface/getModeDataPageList/getTravelRecord", jsonString);
+        List<Map<String,Object>> travelRecordList= (List<Map<String, Object>>) travelRecordMsg.data;
+        for (Map<String, Object> map : travelRecordList) {
+            Optional<User> optional=allUserList.stream().filter(al->al.getJobNumber()!=null&&al.getJobNumber().equals(map.get("rybh"))).findFirst();
+            if(!optional.isPresent()){
+                continue;
+            }
+            User user=optional.get();
+            BusinessTrip businessTrip=new BusinessTrip();
+            businessTrip.setCompanyId(user.getCompanyId());
+            businessTrip.setOwnerId(user.getId());
+            businessTrip.setOwnerName(user.getName());
+            businessTrip.setStartDate(LocalDate.parse(String.valueOf(map.get("startDate")),dtf1));
+            businessTrip.setEndDate(LocalDate.parse(String.valueOf(map.get("endDate")),dtf1));
+            Integer way=null;
+            switch (String.valueOf(map.get("way"))){
+                case "飞机":way=0;
+                    break;
+                case "高铁/火车":way=1;
+                    break;
+                case "汽车":way=2;
+                    break;
+                case "轮船":way=3;
+                    break;
+                case "其他":way=4;
+                    break;
+            }
+            businessTrip.setWay(way);
+            businessTrip.setCityFrom((String) map.get("cityFrom"));
+            businessTrip.setCityTo((String) map.get("cityTo"));
+            Integer goBack=null;
+            switch (String.valueOf(map.get("goBack"))){
+                case "单程":goBack=0;
+                    break;
+                case "往返":goBack=1;
+                    break;
+            }
+            businessTrip.setGoBack(goBack);
+            Double dayCount =Double.valueOf(String.valueOf(map.get("dayCount")));
+            businessTrip.setDayCount(dayCount.intValue());
+            businessTrip.setProcinstId((String) map.get("id"));
+            businessTrip.setGmtFinished((String)map.get("gmtFinished"));
+            Optional<BusinessTrip> first = oldBusinessTripList.stream().filter(ol -> ol.getStartDate().isEqual(businessTrip.getStartDate())&&ol.getEndDate().isEqual(businessTrip.getEndDate())&& ol.getOwnerId().equals(businessTrip.getOwnerId())&&(ol.getProcinstId()!=null&& ol.getProcinstId().equals(businessTrip.getProcinstId()))).findFirst();
+            if(first.isPresent()){
+                businessTrip.setId(first.get().getId());
+            }
+            businessTripList.add(businessTrip);
+        }
+        if(businessTripList.size()>0){
+            businessTripService.saveOrUpdateBatch(businessTripList);
+        }
+        return msg;
+    }
+}
+

+ 2 - 1
fhKeeper/formulahousekeeper/management-platform-mld/src/main/java/com/management/platform/controller/LeaveSheetController.java

@@ -263,7 +263,8 @@ public class LeaveSheetController {
             }
         }
         if(leaveSheetList.size()>0){
-            leaveSheetService.remove(new QueryWrapper<LeaveSheet>().eq("company_id",companyId));
+            //移除更新范围内的数据
+            leaveSheetService.remove(new QueryWrapper<LeaveSheet>().eq("company_id",companyId).between("gmt_finished", startDate + " 00:00:00", endDate + " 23:59:59"));
             leaveSheetService.saveBatch(leaveSheetList);
         }
         return msg;

+ 5 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java

@@ -203,11 +203,11 @@ public class DingDingController {
     }
 
 //
-//    @RequestMapping("/syncLeaveTime")
-//    public HttpRespMsg syncLeaveTime(Integer companyId, String userId, String startDate, String endDate) {
-//        dingDingService.syncLeaveTime(companyId, userId, startDate, endDate);
-//        return new HttpRespMsg();
-//    }
+    @RequestMapping("/syncLeaveTime")
+    public HttpRespMsg syncLeaveTime(Integer companyId, String userId, String startDate, String endDate) {
+        dingDingService.syncLeaveTime(companyId, userId, startDate, endDate);
+        return new HttpRespMsg();
+    }
 
     @RequestMapping("/fixAttendance")
     public HttpRespMsg fixAttendance(Integer companyId) {

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

@@ -3338,15 +3338,15 @@ public class ReportController {
     }
 
     @RequestMapping("/getProduceTimeReport")
-    public HttpRespMsg getProduceTimeReport(Integer projectId, String startDate,String endDate) {
+    public HttpRespMsg getProduceTimeReport(Integer projectId, String ymonth) {
         User user = userMapper.selectById(request.getHeader("TOKEN"));
-        return reportService.getProduceTimeReport(user.getCompanyId(), projectId,startDate,endDate);
+        return reportService.getProduceTimeReport(user.getCompanyId(), projectId,ymonth);
     }
 
     @RequestMapping("/exportProduceTimeReport")
-    public HttpRespMsg exportProduceTimeReport(Integer projectId, String startDate,String endDate) {
+    public HttpRespMsg exportProduceTimeReport(Integer projectId, String ymonth) {
         User user = userMapper.selectById(request.getHeader("TOKEN"));
-        return reportService.exportProduceTimeReport(user.getCompanyId(), projectId,startDate,endDate);
+        return reportService.exportProduceTimeReport(user.getCompanyId(), projectId,ymonth);
     }
 
 }

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

@@ -101,6 +101,8 @@ public class TaskController {
     @Resource
     private TaskGroupService taskGroupService;
     @Resource
+    private CompanyMapper companyMapper;
+    @Resource
     private TaskAddCtrlMapper taskAddCtrlMapper;
     @Resource
     private TaskRestartMapper taskRestartMapper;
@@ -197,6 +199,7 @@ public class TaskController {
         //当前用户
         User user = userMapper.selectById(userId);
         HttpRespMsg msg = new HttpRespMsg();
+        Company company = companyMapper.selectById(user.getCompanyId());
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
         int isInsert=0;
         int isUpdate=0;
@@ -358,7 +361,7 @@ public class TaskController {
             if (task.getExecutorId() != null) {
                 msgRecepientList = task.getExecutorList().stream().filter(exe->!StringUtils.isEmpty(exe.getExecutorId())).map(TaskExecutor::getExecutorId).collect(Collectors.toList());
             }
-            if (task.getTaskType()!=null&&task.getTaskType() == 1) {
+            if (task.getTaskType()!=null&&((company.getProjectProgressMode() == 0 && task.getTaskType() == 1) || company.getProjectProgressMode() == 1)) {
                 needRecalculateProgress = true;
             }
         } else {
@@ -448,7 +451,7 @@ public class TaskController {
             if(task.getFinishDate()==null){
                 taskMapper.updateFinishDate(task.getId());
             }
-            if ((oldTask.getTaskType() == 1 && task.getTaskType() != 1) || (oldTask.getTaskType() != 1 && task.getTaskType() == 1)) {
+            if (company.getProjectProgressMode() == 0 && ((oldTask.getTaskType() == 1 && task.getTaskType() != 1) || (oldTask.getTaskType() != 1 && task.getTaskType() == 1))) {
                 needRecalculateProgress = true;
             }
         }
@@ -486,7 +489,7 @@ public class TaskController {
 
         //需要重新计算项目进度
         if (needRecalculateProgress) {
-            updateProjectProgress(task.getProjectId());
+            updateProjectProgress(company.getProjectProgressMode(), task.getProjectId());
         }
         if (msgRecepientList.size() > 0) {
             //发消息通知执行人, 带项目id
@@ -526,60 +529,16 @@ public class TaskController {
         return msg;
     }
 
-    //撤回工作计划
-    @RequestMapping("/withdrawalTaskPlan")
-    public HttpRespMsg withdrawalTaskPlan(Integer taskId,HttpServletRequest request) {
-        HttpRespMsg msg = new HttpRespMsg();
-        String token = request.getHeader("TOKEN");
-        User user = userMapper.selectById(token);
-        Task task = taskMapper.selectById(taskId);
-        if (task.getTaskPlan()!=1&&task.getIsTaskPlan()!=1){
-            msg.setError("当前计划已变成任务不能撤回计划");
-            return msg;
-        }
-        /**
-         * 任务状态,0-进行中 1-已完成 2-已撤销 3-待第一审核人审核 4-待第二审核人审核 5-第一审核人驳回  6-第二审核人驳回
-         */
-        int count= projectLeaderMapper.selectCountIsLeader(taskId,user.getId());
-        //是这个计划的小组长
-        if (count>0){
-            //待第一审核人审核
-            if (task.getTaskStatus()==3){
-                task.setTaskStatus(2);
-                taskMapper.updateById(task);
-                Information information = new Information();
-                User owner = userMapper.selectById(task.getCheckFirstId());
-                Project project = projectMapper.selectById(task.getProjectId());
-                information.setMsg(project.getProjectName()+"项目有预计FTE计划撤销");
-//                information.setTaskId(task.getId());
-                information.setUserId(owner.getId());
-                information.setType(11);
-                information.setTime(LocalDateTime.now());
-                informationMapper.insert(information);
-            }else {
-                msg.setError("当前计划已处于二级审核或已审核通过,不能撤回");
-                return msg;
-            }
-        }
-        //计划的第一审核人
-        String checkFirstId = task.getCheckFirstId();
-        if (checkFirstId!=null&&checkFirstId.equals(user.getId())){
-            msg.setError("项目经理不能撤回");
-            return msg;
-        }
-
-        //计划的第二审核人
-        String checkSecondId = task.getCheckSecondId();
-        if (checkSecondId!=null&&checkSecondId.equals(user.getId())){
-            msg.setError("区域经理不能撤回");
-            return msg;
-        }
-        return msg;
-    }
 
-    private void updateProjectProgress(Integer projectId) {
+    private void updateProjectProgress(Integer mode, Integer projectId) {
         //只有里程碑才更新项目进度, 非已撤销状态的
-        List<Task> all = taskMapper.simpleList(new QueryWrapper<Task>().eq("project_id", projectId).ne("task_status", 2).eq("task_type",1),null,null);
+        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().eq("project_id", projectId)
+                .ne("task_status", 2)
+                .isNull("parent_tid");
+        if (mode == 0) {//仅统计里程碑
+            queryWrapper.eq("task_type",1);
+        }
+        List<Task> all = taskMapper.simpleList(queryWrapper,null,null);
         Project project = new Project();
         project.setId(projectId);
         if (all.size() > 0) {
@@ -598,6 +557,7 @@ public class TaskController {
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         String token = request.getHeader("TOKEN");
         User user = userMapper.selectById(token);
+        Company company = companyMapper.selectById(user.getCompanyId());
         //进行完成操作时需要检查子任务是否全部完成
         if (task.getTaskStatus() == 0) {
             QueryWrapper<Task> subQuery = new QueryWrapper<Task>();
@@ -649,6 +609,16 @@ public class TaskController {
                 }
             }
 
+            if (company.getId() == 7757) {
+                //针对梦迪莱斯,同一个任务列表里面的要按创建顺序先后完成
+                QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
+                queryWrapper.eq("stages_id", old.getStagesId()).lt("id", old.getId()).isNull("parent_tid").orderByDesc("id").last("limit 1");
+                Task lastItem = taskService.getOne(queryWrapper);
+                if (lastItem != null && lastItem.getTaskStatus() == 0) {
+                    return msg.setError("存在上一工序任务未完成:[" + lastItem.getName() + "]。");
+                }
+            }
+
             if (old.getFinishDate() == null) {
                 //仅对没有完成日期的任务设置完成日期
                 task.setFinishDate(LocalDate.now());
@@ -717,9 +687,9 @@ public class TaskController {
         }
 
         //如果是里程碑,需要更新项目完成度
-        if (curTask.getTaskType() == 1) {
+        if ((company.getProjectProgressMode() == 0 && curTask.getTaskType() == 1) || company.getProjectProgressMode() == 1) {
             Integer projectId = curTask.getProjectId();
-            updateProjectProgress(projectId);
+            updateProjectProgress(company.getProjectProgressMode(), projectId);
         }
         return msg;
     }
@@ -1198,8 +1168,9 @@ public class TaskController {
 
 
         //删除里程碑,需要重新计算项目进度
-        if (task.getTaskType() == 1) {
-            updateProjectProgress(task.getProjectId());
+        Company company = companyMapper.selectById(user.getCompanyId());
+        if ((company.getProjectProgressMode() == 0 && task.getTaskType() == 1) || company.getProjectProgressMode() == 1) {
+            updateProjectProgress(company.getProjectProgressMode(), task.getProjectId());
         }
         return new HttpRespMsg();
     }

+ 8 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/U8Controller.java

@@ -1,11 +1,9 @@
 package com.management.platform.controller;
 
-import com.management.platform.service.BusinessTripService;
-import com.management.platform.service.ErpOrderInfoService;
-import com.management.platform.service.LeaveSheetService;
-import com.management.platform.service.UserFvTimeService;
+import com.management.platform.service.*;
 import com.management.platform.task.DataCollectTask;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -30,9 +28,11 @@ public class U8Controller {
     private UserFvTimeService userFvTimeService;
     @Resource
     private ErpOrderInfoService erpOrderInfoService;
+    @Autowired
+    private ProjectService projectService;
 
     @RequestMapping("/syncOATime")
-    public HttpRespMsg syncOATime(Boolean syncOrder, Boolean syncCard, Boolean syncLeave, Boolean syncBusinessTrip) {
+    public HttpRespMsg syncOATime(Boolean syncOrder, Boolean syncCard, Boolean syncLeave, Boolean syncBusinessTrip, Boolean syncProject) {
         //自动同步过去7天内的数据(含今天)
         LocalDate now = LocalDate.now();
         LocalDate endDate = now;
@@ -52,6 +52,9 @@ public class U8Controller {
         if (syncBusinessTrip != null && syncBusinessTrip) {
             businessTripService.syncHongHuData(HONGHU_COMP_ID);
         }
+        if (syncProject != null && syncProject) {
+            projectService.syncHongHuData(HONGHU_COMP_ID);
+        }
 
         return new HttpRespMsg();
     }

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -1110,7 +1110,7 @@ public class WeiXinCorpController {
                             //处理项目参与人
                             if (user.getDepartmentId() != null && user.getDepartmentId() != 0) {
                                 List<Participation> toAddList = new ArrayList<>();
-                                projectDeptRelateMapper.selectList(new QueryWrapper<ProjectDeptRelate>().eq("department_id", user.getDepartmentId()).eq("company_id", companyId))
+                                projectDeptRelateMapper.selectList(new QueryWrapper<ProjectDeptRelate>().eq("department_id", user.getDepartmentId()))
                                         .forEach(projectDeptRelate -> {
                                             Participation participation = new Participation();
                                             participation.setProjectId(projectDeptRelate.getProjectId());

+ 7 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Company.java

@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2024-09-27
+ * @since 2025-07-15
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -157,6 +157,12 @@ public class Company extends Model<Company> {
     @TableField("non_project_simple")
     private Integer nonProjectSimple;
 
+    /**
+     * 项目进度统计模式:0-按里程碑完成度,1-按全部类型的任务完成度,2-按填报工时占预估工时比例
+     */
+    @TableField("project_progress_mode")
+    private Integer projectProgressMode;
+
 
     @Override
     protected Serializable pkVal() {

+ 11 - 9
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractCustom.java

@@ -2,11 +2,10 @@ package com.management.platform.entity;
 
 import java.math.BigDecimal;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.time.LocalDate;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
@@ -16,11 +15,11 @@ import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
- *
+ * 
  * </p>
  *
  * @author Seyason
- * @since 2024-09-30
+ * @since 2025-07-21
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -126,22 +125,25 @@ public class ContractCustom extends Model<ContractCustom> {
     private String stampDutyItems;
 
     /**
-     * 印花税缴纳状态 0无需缴纳、1未缴纳、2已缴纳、3部分缴纳。
-     * 合同新增后,默认置值未缴纳,状态随时可修改,不予审核状态关联
+     * 印花税缴纳状态 0无需缴纳、1未缴纳、2已缴纳、3部分缴纳
      */
     @TableField("stamp_duty_status")
     private Integer stampDutyStatus;
 
     /**
-     * 印花税缴纳时间(最新)
-     * 印花税缴纳状态为无需缴纳、未缴纳时,禁用;
-     * 部分缴纳、已缴纳时,启用。
+     * 印花税缴纳时间
      */
     @TableField("stamp_duty_time")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate stampDutyTime;
 
+    /**
+     * 是否平台采购
+     */
+    @TableField("is_platform_buy")
+    private Boolean isPlatformBuy;
+
 
     @Override
     protected Serializable pkVal() {

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/ProduceTime.java

@@ -1,5 +1,6 @@
 package com.management.platform.entity.vo;
 
+import com.management.platform.entity.Finance;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -24,4 +25,8 @@ public class ProduceTime {
     private double salesTime;
     private BigDecimal salesCost;
     private double projectTime;
+
+    private double userTotalTime;//员工总工时数
+
+    private Finance userFinance;
 }

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExcelParserService.java

@@ -172,6 +172,10 @@ public class ExcelParserService {
 
     public static double calculateZhengBeiWorkHours(String startTime, String endTime) {
         // 简单计算工作时长(小时)
+        if (startTime.compareTo("08:30") < 0 && endTime.compareTo("08:30") < 0) {
+            //上下班都是八点半之前,忽略掉
+            return 0;
+        }
         // 实际应用中需要更精确的计算,考虑午休时间等
         if (startTime.compareTo("08:30") < 0) {
             startTime = "08:30";

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

@@ -340,4 +340,6 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg getWorkOrderNumStatistics(Integer pageIndex, Integer pageSize, String startDate, String endDate, HttpServletRequest request);
 
     HttpRespMsg exportWorkOrderNumStatistics(String startDate, String endDate, HttpServletRequest request) throws Exception;
+
+    void syncHongHuData(int honghuCompId);
 }

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

@@ -184,7 +184,7 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg exportReportRateOfTask(Integer projectId, String userIds, Integer companyId, Integer type);
 
-    HttpRespMsg getProduceTimeReport(Integer companyId, Integer projectId, String startDate, String endDate);
+    HttpRespMsg getProduceTimeReport(Integer companyId, Integer projectId, String ymonth);
 
-    HttpRespMsg exportProduceTimeReport(Integer companyId, Integer projectId, String startDate, String endDate);
+    HttpRespMsg exportProduceTimeReport(Integer companyId, Integer projectId, String ymonth);
 }

+ 16 - 10
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java

@@ -1309,8 +1309,10 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
             headList.add("合同类别");
             headList.add("二级分类");
             headList.add("供应商名称");
-            headList.add("供应商联系人");
-            headList.add("对方联系电话");
+            //合并为一列
+//            headList.add("供应商联系人");
+//            headList.add("对方联系电话");
+            headList.add("供应商联系人及电话");
             headList.add("使用部门");
             headList.add("经费来源");
             headList.add("合同承办人");
@@ -1358,8 +1360,10 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
                             ContractCustom customData = contract.getCustomData();
                             if (customData!=null){
                                 item.add(customData.getCustomerOrg()==null?"":customData.getCustomerOrg());
-                                item.add(customData.getCustomerContact()==null?"":customData.getCustomerContact());
-                                item.add(customData.getCustomerPhone()==null?"":customData.getCustomerPhone());
+//                                item.add(customData.getCustomerContact()==null?"":customData.getCustomerContact());
+//                                item.add(customData.getCustomerPhone()==null?"":customData.getCustomerPhone());
+                                String combinedData = (customData.getCustomerContact()==null?"":(customData.getCustomerContact()+ " "))  + (customData.getCustomerPhone()==null?"":customData.getCustomerPhone());
+                                item.add(combinedData);
                                 item.add(customData.getUseDepartment()==null?"":customData.getUseDepartment());
                                 item.add(customData.getFundsSource()==null?"":(customData.getFundsSource().equals("1")?"科研":"其他(专项等)"));
                                 item.add(customData.getUndertaker()==null?"":customData.getUndertaker());
@@ -1368,7 +1372,7 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
                             }else {
                                 item.add("");
                                 item.add("");
-                                item.add("");
+//                                item.add("");
                                 item.add("");
                                 item.add("");
                                 item.add("");
@@ -1456,8 +1460,8 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
                         }
                         else {
                             ArrayList<String> item = new ArrayList<>();
-                            for (int i1 = 0; i1 < 25; i1++) {
-                                item.add("" );
+                            for (int i1 = 0; i1 < 24; i1++) {
+                                item.add("");
                             }
 
 //                            item.add(payCustomizedList.get(j).getPayDate()==null?"":payCustomizedList.get(j).getPayDate());
@@ -1484,8 +1488,10 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
                     ContractCustom customData = contract.getCustomData();
                     if (customData!=null){
                         item.add(customData.getCustomerOrg()==null?"":customData.getCustomerOrg());
-                        item.add(customData.getCustomerContact()==null?"":customData.getCustomerContact());
-                        item.add(customData.getCustomerPhone()==null?"":customData.getCustomerPhone());
+//                        item.add(customData.getCustomerContact()==null?"":customData.getCustomerContact());
+//                        item.add(customData.getCustomerPhone()==null?"":customData.getCustomerPhone());
+                        String combinedData = (customData.getCustomerContact()==null?"":(customData.getCustomerContact()+ " "))  + (customData.getCustomerPhone()==null?"":customData.getCustomerPhone());
+                        item.add(combinedData);
                         item.add(customData.getUseDepartment()==null?"":customData.getUseDepartment());
                         item.add(customData.getFundsSource()==null?"":(customData.getFundsSource().equals("1")?"科研":"其他(专项等)"));
                         item.add(customData.getUndertaker()==null?"":customData.getUndertaker());
@@ -1493,7 +1499,7 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
                         item.add(customData.getSignDate()==null?"":customData.getSignDate());
                     }else {
                         item.add("");
-                        item.add("");
+//                        item.add("");
                         item.add("");
                         item.add("");
                         item.add("");

+ 59 - 44
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java

@@ -1933,9 +1933,17 @@ public class DingDingServiceImpl implements DingDingService {
             //全部的
             List<TimeType> timeTypes = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("sync_dingding", 1));
             List<Integer> companyIds = timeTypes.stream().map(TimeType::getCompanyId).collect(Collectors.toList());
-            List<CompanyDingding> dingdingList = companyDingdingMapper.selectList(new QueryWrapper<CompanyDingding>().in("company_id", companyIds));
-            for (CompanyDingding dingding : dingdingList) {
-                syncOneCompLeave(dingding, userId, startDate, endDate);
+            if (companyIds.size() == 0) {
+                return;
+            }
+            List<Company> companyList = companyMapper.selectList(new QueryWrapper<Company>().in("id", companyIds).ge("expiration_date", LocalDateTime.now()));
+            if (companyList.size() > 0) {
+                //缩小公司范围,只同步有效期内的公司
+                companyIds = companyList.stream().map(Company::getId).collect(Collectors.toList());
+                List<CompanyDingding> dingdingList = companyDingdingMapper.selectList(new QueryWrapper<CompanyDingding>().in("company_id", companyIds));
+                for (CompanyDingding dingding : dingdingList) {
+                    syncOneCompLeave(dingding, userId, startDate, endDate);
+                }
             }
         }
     }
@@ -1961,6 +1969,7 @@ public class DingDingServiceImpl implements DingDingService {
         }
     }
 
+    //仅适用于钉钉企业内部应用
     private void sycUserOneDayWorkData(CompanyDingding dingding, String userId, String workDate, boolean showLog, boolean onlySyncAttendance) {
         List<User> userList = null;
         if (StringUtils.isEmpty(userId)) {
@@ -2172,44 +2181,44 @@ public class DingDingServiceImpl implements DingDingService {
                 OapiAttendanceGetleavetimebynamesResponse rsp = null;
                 try {
                     rsp = client.execute(req, accessToken);
-                    System.out.println(rsp.getBody());
-//                    JSONArray array = JSONObject.parseObject(rsp.getBody()).getJSONObject("result").getJSONArray("columns");
-//                    for (int i=0;i<array.size(); i++) {
-//                        JSONObject item = array.getJSONObject(i);
-//                        String leaveTypeName = item.getJSONObject("columnvo").getString("name");
-//                        int typeIndex = 0;
-//                        for (int index=0;index < Constant.LEAVE_TYPES.length; index++) {
-//                            if (Constant.LEAVE_TYPES[index].equals(leaveTypeName)) {
-//                                typeIndex = index;
-//                                break;
-//                            }
-//                        }
-//                        //获取请假的数据
-//                        JSONArray valArray = item.getJSONArray("columnvals");
-//                        for (int j=0;j<valArray.size(); j++) {
-//                            Float val = valArray.getJSONObject(j).getFloat("value");
-//                            String date = valArray.getJSONObject(j).getString("date");
-//                            LocalDate localDate = LocalDateTime.parse(date, dtf).toLocalDate();
-//                            if (val != null && val > 0.0) {
-//                                //存在请假时长
-//                                LeaveSheet sheet = new LeaveSheet();
-//                                sheet.setCompanyId(dingding.getCompanyId());
-//                                sheet.setOwnerId(u.getId());
-//                                sheet.setOwnerName(u.getName());
-//                                sheet.setLeaveType(typeIndex);
-//                                sheet.setTimeHours(val);
-//                                sheet.setStartDate(localDate);
-//                                sheet.setEndDate(localDate);
-//                                if (val >= timeType.getAllday()) {
-//                                    sheet.setTimeType(0);
-//                                    sheet.setTimeDays(1.0f);
-//                                } else {
-//                                    sheet.setTimeType(1);//按小时
-//                                }
-//                                sheetList.add(sheet);
-//                            }
-//                        }
-//                    }
+//                    System.out.println(rsp.getBody());
+                    JSONArray array = JSONObject.parseObject(rsp.getBody()).getJSONObject("result").getJSONArray("columns");
+                    for (int i=0;i<array.size(); i++) {
+                        JSONObject item = array.getJSONObject(i);
+                        String leaveTypeName = item.getJSONObject("columnvo").getString("name");
+                        int typeIndex = 0;
+                        for (int index=0;index < Constant.LEAVE_TYPES.length; index++) {
+                            if (Constant.LEAVE_TYPES[index].equals(leaveTypeName)) {
+                                typeIndex = index;
+                                break;
+                            }
+                        }
+                        //获取请假的数据
+                        JSONArray valArray = item.getJSONArray("columnvals");
+                        for (int j=0;j<valArray.size(); j++) {
+                            Float val = valArray.getJSONObject(j).getFloat("value");
+                            String date = valArray.getJSONObject(j).getString("date");
+                            LocalDate localDate = LocalDateTime.parse(date, dtf).toLocalDate();
+                            if (val != null && val > 0.0) {
+                                //存在请假时长
+                                LeaveSheet sheet = new LeaveSheet();
+                                sheet.setCompanyId(dingding.getCompanyId());
+                                sheet.setOwnerId(u.getId());
+                                sheet.setOwnerName(u.getName());
+                                sheet.setLeaveType(typeIndex);
+                                sheet.setTimeHours(val);
+                                sheet.setStartDate(localDate);
+                                sheet.setEndDate(localDate);
+                                if (val >= timeType.getAllday()) {
+                                    sheet.setTimeType(0);
+                                    sheet.setTimeDays(1.0f);
+                                } else {
+                                    sheet.setTimeType(1);//按小时
+                                }
+                                sheetList.add(sheet);
+                            }
+                        }
+                    }
                 } catch (ApiException e) {
                     e.printStackTrace();
                 }
@@ -2279,8 +2288,9 @@ public class DingDingServiceImpl implements DingDingService {
         req.setUserIds(ddIds);
         req.setCheckDateFrom(startDate+ " 02:00:00");
         //考虑到可能加班到凌晨,需要设置第二天凌晨6点为下班时间
-        endDate = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(1).toString();
-        req.setCheckDateTo(endDate+ " 06:00:00");
+        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        endDate = LocalDate.parse(endDate, dateTimeFormatter).plusDays(1).toString();
+        req.setCheckDateTo(endDate+ " 09:00:00");
         req.setIsI18n(false);
         OapiAttendanceListRecordResponse rsp = null;
         try {
@@ -2313,6 +2323,9 @@ public class DingDingServiceImpl implements DingDingService {
                     while (dayIter.hasNext()) {
                         Long d = dayIter.next();
                         LocalDate workDate =  LocalDateTime.ofEpochSecond(d/1000, 0, ZoneOffset.ofHours(8)).toLocalDate();
+                        if (workDate.isBefore(LocalDate.parse(startDate, dateTimeFormatter))) {
+                            continue;
+                        }
                         UserDingdingTime timeItem = new UserDingdingTime();
                         timeItem.setWorkDate(workDate);
                         List<DdingCardTimeItem> oneDayTimes = dailyMap.get(d);
@@ -2374,7 +2387,9 @@ public class DingDingServiceImpl implements DingDingService {
                             if (findOld.isPresent()) {
                                 timeItem.setId(findOld.get().getId());
                             }
-                            cardRecordList.add(timeItem);
+                            if (timeItem.getWorkHours() > 0) {
+                                cardRecordList.add(timeItem);
+                            }
                         }
                     }
                 }

+ 22 - 21
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectMainServiceImpl.java

@@ -68,17 +68,18 @@ public class ProjectMainServiceImpl extends ServiceImpl<ProjectMainMapper, Proje
                 httpRespMsg.setError(MessageUtils.message("name.nameRepeat"));
                 return httpRespMsg;
             }
-            if (companyId==4215){
-                if (projectMain.getWorkOrderNumType()!=null&& StringUtils.isNotEmpty(projectMain.getWorkOrderNum())){
-                    Integer count2 = projectMainMapper.selectCount(new QueryWrapper<ProjectMain>().eq("company_id", projectMain.getCompanyId())
-                            .eq("work_order_num", projectMain.getWorkOrderNum()).eq("work_order_num_type", projectMain.getWorkOrderNumType())
-                            .ne("id", projectMain.getId()));
-                    if(count2>0){
-                        httpRespMsg.setError(MessageUtils.message("other.AlreadyExistsPackage"));
-                        return httpRespMsg;
-                    }
-                }
-            }
+            //去掉工作包号重复的校验
+//            if (companyId==4215){
+//                if (projectMain.getWorkOrderNumType()!=null&& StringUtils.isNotEmpty(projectMain.getWorkOrderNum())){
+//                    Integer count2 = projectMainMapper.selectCount(new QueryWrapper<ProjectMain>().eq("company_id", projectMain.getCompanyId())
+//                            .eq("work_order_num", projectMain.getWorkOrderNum()).eq("work_order_num_type", projectMain.getWorkOrderNumType())
+//                            .ne("id", projectMain.getId()));
+//                    if(count2>0){
+//                        httpRespMsg.setError(MessageUtils.message("other.AlreadyExistsPackage"));
+//                        return httpRespMsg;
+//                    }
+//                }
+//            }
             boolean nameChanged = !oldProject.getName().equals(projectMain.getName());
             boolean categoryChanged = !oldProject.getCategoryId().equals(projectMain.getCategoryId());
             projectMainMapper.updateById(projectMain);
@@ -110,16 +111,16 @@ public class ProjectMainServiceImpl extends ServiceImpl<ProjectMainMapper, Proje
                 httpRespMsg.setError(MessageUtils.message("name.nameRepeat"));
                 return httpRespMsg;
             }
-            if (companyId==4215){
-                if (projectMain.getWorkOrderNumType()!=null&& StringUtils.isNotEmpty(projectMain.getWorkOrderNum())){
-                    Integer count4 = projectMainMapper.selectCount(new QueryWrapper<ProjectMain>().eq("company_id", projectMain.getCompanyId())
-                            .eq("work_order_num", projectMain.getWorkOrderNum()).eq("work_order_num_type", projectMain.getWorkOrderNumType()));
-                    if(count4>0){
-                        httpRespMsg.setError(MessageUtils.message("other.AlreadyExistsPackage"));
-                        return httpRespMsg;
-                    }
-                }
-            }
+//            if (companyId==4215){
+//                if (projectMain.getWorkOrderNumType()!=null&& StringUtils.isNotEmpty(projectMain.getWorkOrderNum())){
+//                    Integer count4 = projectMainMapper.selectCount(new QueryWrapper<ProjectMain>().eq("company_id", projectMain.getCompanyId())
+//                            .eq("work_order_num", projectMain.getWorkOrderNum()).eq("work_order_num_type", projectMain.getWorkOrderNumType()));
+//                    if(count4>0){
+//                        httpRespMsg.setError(MessageUtils.message("other.AlreadyExistsPackage"));
+//                        return httpRespMsg;
+//                    }
+//                }
+//            }
             projectMainMapper.insert(projectMain);
         }
         return httpRespMsg;

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

@@ -16,6 +16,7 @@ import com.management.platform.entity.*;
 import com.management.platform.entity.vo.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
+import com.management.platform.task.DataCollectTask;
 import com.management.platform.util.*;
 import com.management.platform.webservice.po.ProjectQueryResponse;
 import com.management.platform.webservice.po.ProjectTask;
@@ -46,10 +47,13 @@ import org.apache.poi.xssf.usermodel.*;
 import org.assertj.core.util.Lists;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.*;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
@@ -93,6 +97,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     @Resource
     ExcelExportService excelExportService;
     @Resource
+    private GtemplateTaskMapper gtemplateTaskMapper;
+    @Resource
+    private GroupTmpstagesMapper groupTmpstagesMapper;
+    @Resource
     UserCorpwxTimeMapper userCorpwxTimeMapper;
     @Resource
     private ProjectNotifyUserService projectNotifyUserService;
@@ -214,7 +222,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     @Resource
     TaskGroupService taskGroupService;
     @Resource
-    GroupTemplateMapper GroupTemplateMapper;
+    GroupTemplateMapper groupTemplateMapper;
     @Resource
     WxCorpInfoMapper wxCorpInfoMapper;
     @Resource
@@ -14151,9 +14159,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         List<ProjectMain> typeCollect0 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 0).collect(Collectors.toList());
         List<ProjectMain> typeCollect1 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 1).collect(Collectors.toList());
         List<ProjectMain> typeCollect2 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 2).collect(Collectors.toList());
-        List<String> typeNum0= typeCollect0.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
-        List<String> typeNum1= typeCollect1.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
-        List<String> typeNum2= typeCollect2.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
+        List<String> typeNum0= typeCollect0.stream().map(ProjectMain::getWorkOrderNum).distinct().collect(Collectors.toList());
+        List<String> typeNum1= typeCollect1.stream().map(ProjectMain::getWorkOrderNum).distinct().collect(Collectors.toList());
+        List<String> typeNum2= typeCollect2.stream().map(ProjectMain::getWorkOrderNum).distinct().collect(Collectors.toList());
         LinkedHashMap<String, Object> totalMap = new LinkedHashMap<>();
 //        totalMap.put("totalRow",projectMainList.size());//总列数
 //        totalMap.put("mainFly",typeCollect0.size());
@@ -14305,6 +14313,153 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return new HttpRespMsg();
     }
 
+    @Override
+    public void syncHongHuData(int honghuCompId) {
+        RestTemplate restTemplate = new RestTemplate();
+        String sumUrl = DataCollectTask.PREFIX_URL+"/dataCollect/getSqlServerProjectDataSum";
+        String listUrl = DataCollectTask.PREFIX_URL+"/dataCollect/getSqlServerProjectDataList";
+        Company company = companyMapper.selectById(honghuCompId);
+        try {
+            ResponseEntity<String> sumResponse = restTemplate.exchange(
+                    sumUrl,
+                    HttpMethod.GET,
+                    null,
+                    String.class
+            );
+            Integer totalNum = 0;
+            if (sumResponse.getStatusCode() == HttpStatus.OK) {
+                totalNum = Integer.parseInt(sumResponse.getBody());
+            } else {
+                System.out.println("请求失败,状态码: " + sumResponse.getStatusCode());
+            }
+            if(totalNum > 0){
+                int pageSize = 1000;
+                int offset = 0;
+                List<Project> toAddList = new ArrayList<>();
+                List<Project> toUpdateList = new ArrayList<>();
+                while (offset < totalNum) {
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_JSON);
+                    Map<String, Object> requestBody = new HashMap<>();
+                    requestBody.put("pageNo", offset);
+                    requestBody.put("pageSize", pageSize);
+                    HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody, headers);
+                    ResponseEntity<List<Project>> listResponse = restTemplate.exchange(
+                            listUrl,
+                            HttpMethod.POST,
+                            requestEntity,
+                            new  ParameterizedTypeReference<List<Project>>(){}
+                    );
+                    if (listResponse.getStatusCode() == HttpStatus.OK) {
+                        List<Project> dataList = listResponse.getBody();
+                        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(dataList)){
+                            List<String> collect = dataList.stream().map(Project::getProjectCode).distinct().collect(Collectors.toList());
+                            List<String> existIds = projectMapper.getExistIds(collect, honghuCompId);
+                            if(!org.springframework.util.CollectionUtils.isEmpty(existIds)){
+                                toUpdateList.addAll(dataList.stream().filter(t -> existIds.contains(t.getProjectCode())).collect(Collectors.toList()));
+                                toAddList.addAll(dataList.stream().filter(t -> !existIds.contains(t.getProjectCode())).collect(Collectors.toList()));
+                            }else{
+                                toAddList.addAll(dataList);
+                            }
+                            if(!org.springframework.util.CollectionUtils.isEmpty(toAddList)){
+                                for (Project project : toAddList) {
+                                    //以项目编码前五为作为分类名称
+                                    String categoryName = project.getProjectCode().substring(0,5);
+                                    project.setCategoryName(categoryName);
+                                    ProjectCategory category = projectCategoryMapper.selectOne(new LambdaQueryWrapper<ProjectCategory>()
+                                            .eq(ProjectCategory::getCompanyId, honghuCompId)
+                                            .eq(ProjectCategory::getName, project.getCategoryName())
+                                            .last(" limit 1 ")
+                                    );
+                                    int categoryId;
+                                    if(null != category){
+                                        categoryId = category.getId();
+                                    }else{
+                                        ProjectCategory tmp = new ProjectCategory();
+                                        tmp.setName(project.getCategoryName());
+                                        tmp.setCompanyId(honghuCompId);
+                                        projectCategoryMapper.insert(tmp);
+                                        categoryId = tmp.getId();
+                                    }
+                                    if(0!= categoryId){
+                                        project.setCategory(categoryId);
+                                        projectMapper.insert(project);
+                                        if (company.getPackageProject() == 1) {
+                                            initGroup(honghuCompId,project.getId());
+                                        }
+                                    }
+                                }
+                            }
+                            if(!org.springframework.util.CollectionUtils.isEmpty(toUpdateList)){
+                                updateBatchById(toUpdateList);
+                            }
+                            toUpdateList.clear();
+                            toAddList.clear();
+                        }
+                    }
+                    offset += pageSize;
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("请求发生异常: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+    public void initGroup(Integer companyId, Integer projectId) {
+        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
+                .eq(User::getRoleName, "超级管理员")
+                .last(" limit 1")
+        );
+        List<GroupTemplate> groupTemplates = groupTemplateMapper.selectList(new QueryWrapper<GroupTemplate>()
+                .eq("company_id", companyId).eq("cre_with_pro", true));
+        if (groupTemplates.size()==0){
+            //创建默认分组
+            TaskGroup group = new TaskGroup();
+            group.setProjectId(projectId);
+            //group.setName("项目阶段");
+            group.setName(MessageUtils.message("entry.projectStage"));
+            taskGroupMapper.insert(group);
+        }else{
+            for (GroupTemplate groupTemplate : groupTemplates) {
+                TaskGroup group = new TaskGroup();
+                group.setProjectId(projectId);
+                group.setName(groupTemplate.getName());
+                taskGroupMapper.insert(group);
+                //从模板创建任务列表
+                List<GroupTmpstages> stages = groupTmpstagesMapper.selectList(new QueryWrapper<GroupTmpstages>().eq("template_id", groupTemplate.getId()));
+                List<Stages> batchList = new ArrayList<>();
+                stages.forEach(s->{
+                    Stages stageItem = new Stages();
+                    stageItem.setGroupId(group.getId());
+                    stageItem.setStagesName(s.getStagesName());
+                    stageItem.setSequence(s.getSequence());
+                    stageItem.setProjectId(projectId);
+                    batchList.add(stageItem);
+                });
+                stagesService.saveBatch(batchList);
+                //阶段的任务,里程碑,风险
+                List<GtemplateTask> gtemplateTaskList = gtemplateTaskMapper.selectList(
+                        new QueryWrapper<GtemplateTask>().eq("gtemplate_id", groupTemplate.getId())
+                                .orderByAsc("seq"));
+                if (gtemplateTaskList.size() > 0) {
+                    List<Task> taskList = new ArrayList<>();
+                    gtemplateTaskList.forEach(gt->{
+                        Task task = gt.toTask();
+                        task.setProjectId(projectId);
+                        task.setGroupId(group.getId());
+                        String sName = stages.stream().filter(s->s.getId().equals(gt.getTstagesId())).findFirst().get().getStagesName();
+                        Integer realStageId = batchList.stream().filter(bat->bat.getStagesName().equals(sName)).findFirst().get().getId();
+                        task.setStagesId(realStageId);
+                        task.setCreaterId(user.getId());
+                        task.setCreaterName(user.getName());
+                        task.setCreatorColor(user.getColor());
+                        taskList.add(task);
+                    });
+                    taskService.saveBatch(taskList);
+                }
+            }
+        }
+    }
     //导出FTE报表数据
     @Override
     public HttpRespMsg exportFTEData(String monthStart,String monthEnd, String area,Integer departmentId,HttpServletRequest request) {

+ 146 - 25
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -114,6 +114,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     @Resource
     private ReportLogDetailMapper reportLogDetailMapper;
     @Resource
+    private FinanceFixedcolnameService financeFixedcolnameService;
+    @Resource
     private CompanyDingdingService companyDingdingService;
     @Resource
     private ReportBatchMapper reportBatchMapper;
@@ -134,6 +136,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     @Resource
     private ReportLogService reportLogService;
     @Resource
+    private FinanceTblcuscolMapper financeTblcuscolMapper;
+    @Resource
     ReportExtraDegreeMapper reportExtraDegreeMapper;
     @Resource
     WxCorpInfoService wxCorpInfoService;
@@ -241,14 +245,13 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     @Value(value = "${upload.path}")
     private String path;
     @Autowired
-    private BusinessTripMapper businessTripMapper;
-    @Autowired
     private BustripProjectMapper bustripProjectMapper;
     @Resource
     private CompanyDingdingMapper companyDingdingMapper;
     @Resource
     private SysRoleFunctionService sysRoleFunctionService;
-    private DingDingService dingDingService;
+    @Resource
+    private FinanceMapper financeMapper;
 
 
     //获取报告列表
@@ -5802,7 +5805,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                                 if (company.getId() == 469) {
                                     report.setState(0);//待审核员审核
                                     //赛元都是非项目,直接取员工所属部门的主要负责人来审核,如果设置了非项目审核人,优先用非项目审核人
-                                    int mode = 0;
                                     String superiorId = user.getSuperiorId();
                                     if (superiorId == null) {
                                         Department department = departmentMapper.selectById(reportCreator.getDepartmentId());
@@ -5817,6 +5819,21 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                                             new QueryWrapper<AuditWorkflowTimeSetting>().eq("dept_id", reportCreator.getDepartmentId()).orderByAsc("seq"));
                                     List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", reportCreator.getCompanyId()));
                                     setReportWorkflowAuditor(auditWorkflowList, allDeptList, report,timeType);
+                                } if (company.getId() == 7544){
+                                    //加力,按照设置的审核模式审核:普通员工到项目经理,项目经理到指定审核人
+                                    report.setState(0);//待审核员审核
+                                    String projectAuditorId;
+                                    if (company.getNonProjectSimple() == 1 && project.getIsPublic() == 1) {
+                                        //非项目,由公司副总审核
+                                        projectAuditorId = timeType.getThirdAuditor();
+                                    } else {
+                                        projectAuditorId = project.getInchargerId();
+                                        if (report.getCreatorId().equals(projectAuditorId)) {
+                                            //自己担任项目经理的情况下,由公司副总审核
+                                            projectAuditorId = timeType.getThirdAuditor();
+                                        }
+                                    }
+                                    report.setProjectAuditorId(projectAuditorId);
                                 } else {
                                     if (timeType.getNeedDeptAudit() == 0) {
                                         report.setState(1);//导入的直接算审核通过
@@ -5825,7 +5842,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                                         report.setDepartmentAuditState(1);//部门已审核,到上层领导审核
                                     }
                                 }
-
                                 report.setCreateDate(LocalDate.parse(reportDate, dtf));
                                 report.setCost(reportCreator.getCost()==null?new BigDecimal(0) : reportCreator.getCost().multiply(new BigDecimal(time)));
                                 if (notAllowedOnNonWorkday == 1 && WorkDayCalculateUtils.isWorkDay(report.getCreateDate()) == false) {
@@ -6550,18 +6566,17 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     titles.add(MessageUtils.message("excel.auditTime"));
                     titles.add(MessageUtils.message("excel.auditProcess"));
                 }else {
-                    titles.add(MessageUtils.message("excel.fillTime"));
                     titles.add("项目经理");
                 }
 
 
 //                logDetails = reportLogDetailMapper.selectList(new QueryWrapper<ReportLogDetail>().select("report_id, msg, operator_id, operate_date").eq("company_id", company.getId()).between("work_date", startDate, endDate));
             }
-            if (exportType==0) {
+            if (exportType==0 || companyId == 1071) {//物奇需要工作事项
                 //titles.add("工作事项");
                 titles.add(MessageUtils.message("excel.workItems"));
             }
-            if(stateKey==1 || stateKey==0 || stateKey==2){
+            if(exportType==0 && (stateKey==1 || stateKey==0 || stateKey==2)){
                 //titles.add("审核状态");
                 titles.add(MessageUtils.message("excel.auditStatus"));
             }
@@ -6574,7 +6589,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 titles.add(MessageUtils.message("excel.reviewProcessStatus"));
             }
             //新版按周填报增加周总结
-            if (timeType.getEnableNewWeeklyfill() == 1) {
+            if (timeType.getEnableNewWeeklyfill() == 1 && exportType==0) {
                 //titles.add("周总结");
                 titles.add(MessageUtils.message("excel.weekSummary"));
             }
@@ -6947,8 +6962,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     item.add(map.get("stage") != null?map.get("stage").toString():"");
                 }
                 if (timeType.getShowFillauditTime() == 1) {
-                    item.add(sdf.format((Date)map.get("time")));
                     if (exportType==0){
+                        item.add(sdf.format((Date)map.get("time")));
                         if(needCorpWxTranslate){
                             String projectAuditorName ="$userName="+String.valueOf(map.get("projectAuditorCorpwxUserId"))+"$";
                             item.add(projectAuditorName);
@@ -7079,10 +7094,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                         item.add(sb.toString());
                     }
                 }
-                if (exportType==0) {
+                if (exportType==0 || companyId == 1071) {
                     item.add((String) map.get("content"));
                 }
-                if(stateKey==1 || stateKey ==0 || stateKey==2){
+                if(exportType==0 && (stateKey==1 || stateKey ==0 || stateKey==2)){
                     Integer state = (Integer) map.get("state");
                     switch (state){
                         //case 0:row.createCell(index).setCellValue("待审核");
@@ -7242,7 +7257,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 }
 
-                if (timeType.getEnableNewWeeklyfill() == 1) {
+                if (timeType.getEnableNewWeeklyfill() == 1 && exportType==0) {
                     ReportBatch batchItem = reportBatchMapper.selectOne(new QueryWrapper<ReportBatch>().eq("creator_id", map.get("creatorId")).eq("start_date", createDate).last("limit 1"));
                     if (batchItem != null) {
                         item.add(batchItem.getSummary());
@@ -7419,7 +7434,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         List<User> allRangeUserList = new ArrayList<>();
         Integer companyId = user.getCompanyId();
         TimeType timeType = timeTypeMapper.selectById(companyId);
-        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
         //获取部门的所有子部门
         List<Department> departments = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id",companyId));
         List<Integer> branchDepartment = null;
@@ -7429,7 +7443,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         List<Map<String, Object>> list = null;
         //分角色权限:管理员看全部的,部门负责人看自己部门的,个人只能看自己的。
         List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全公司工时");
-        boolean hasDeptWorktimePriv = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看本部门工时").size() > 0;
         if (functionList.size() == 0) {
             List<Integer> allVisibleDeptIdList = getAllVisibleDeptIdList(user, null);
             //检查是不是部门负责人
@@ -7521,7 +7534,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     continue;
                 }
                 final String dateStr = dtf.format(date);
-                if (!list.stream().anyMatch(item->item.get("id").equals(curUser.getId())&&sdf.format((java.sql.Date)item.get("createDate")).equals(dateStr))) {
+                if (!list.stream().anyMatch(item->((Integer)item.get("state") == 0 || (Integer)item.get("state") == 1) && item.get("id").equals(curUser.getId())&&sdf.format((java.sql.Date)item.get("createDate")).equals(dateStr))) {
                     UserDailyWorkItem noRecord = new UserDailyWorkItem();
                     noRecord.userId = curUser.getId();
                     noRecord.departmentId = curUser.getDepartmentId();
@@ -12117,15 +12130,17 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg getProduceTimeReport(Integer companyId, Integer projectId, String startDate, String endDate) {
+    public HttpRespMsg getProduceTimeReport(Integer companyId, Integer projectId, String ymonth) {
         HttpRespMsg msg = new HttpRespMsg();
-        msg.setData(getProduceTime(companyId, projectId, startDate, endDate));
+        msg.setData(getProduceTime(companyId, projectId, ymonth));
         return msg;
     }
 
-    private List<ProduceTime> getProduceTime(Integer companyId, Integer projectId, String startDate, String endDate) {
+    private List<ProduceTime> getProduceTime(Integer companyId, Integer projectId, String ymonth) {
         Integer leaveProjectId = 80333;//请假项目,排除在外
         Integer publicProjectId = 77651;//公共项目
+        String startDate = ymonth + "-01";
+        String endDate = ymonth + "-31";
         QueryWrapper<Report> wrapper = new QueryWrapper<Report>().select("id, create_date, creator_id, project_id,dept_id, working_time, group_id, extra_field4").eq("company_id", companyId).ne("project_id", leaveProjectId)
                 .eq("state", 1).between("create_date", startDate, endDate);
         if (projectId != null) {
@@ -12140,6 +12155,21 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         Integer rdDeptId = departmentList.stream().filter(dept->dept.getDepartmentName().equals("研发中心")).findFirst().get().getDepartmentId();
         Integer cuServiceDeptId = departmentList.stream().filter(dept->dept.getDepartmentName().equals("售后部")).findFirst().get().getDepartmentId();
         List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+        //获取薪资数据
+        List<Finance> finances = financeMapper.selectList(new QueryWrapper<Finance>().eq("company_id", companyId).eq("ymonth",ymonth));
+        //按人员分组,获取工时数
+        Map<String, Double> userTime = reportList.stream().collect(Collectors.groupingBy(Report::getCreatorId, Collectors.summingDouble(Report::getWorkingTime)));
+        finances.forEach(f->{
+            String uid = f.getUserId();
+            Double b = userTime.get(uid);
+            if (b != null) {
+                BigDecimal avgHourCost = f.getTotalCost().divide(new BigDecimal(b),6, BigDecimal.ROUND_HALF_UP);
+                f.setHourCost(avgHourCost);
+                //同步设置人员的时薪
+                userList.stream().filter(u->u.getId().equals(f.getUserId())).findFirst().ifPresent(u->u.setCost(avgHourCost));
+            }
+        });
+
         List<ProduceTime> result = new ArrayList<>();
         if (reportList.size() > 0) {
             //按照项目和人员进行分组统计
@@ -12160,8 +12190,15 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     Map<String, List<Report>> membReportList = reports.stream().collect(Collectors.groupingBy(Report::getCreatorId));
 
                     membReportList.forEach((membId, oneMembList )-> {
-                        User user = userList.stream().filter(u->u.getId().equals(membId)).findFirst().get();
                         ProduceTime produceTimeItem = new ProduceTime();
+                        produceTimeItem.setUserTotalTime(userTime.get(membId));
+                        User user = userList.stream().filter(u->u.getId().equals(membId)).findFirst().get();
+                        Optional<Finance> f = finances.stream().filter(finance -> finance.getUserId().equals(membId)).findFirst();
+                        if (f.isPresent()) {
+                            Finance userFinance = f.get();
+                            produceTimeItem.setUserFinance(userFinance);
+                        }
+
                         produceTimeItem.setProjectId(p.getId());
                         produceTimeItem.setProjectCode(p.getProjectCode());
                         produceTimeItem.setProjectName(projectName);
@@ -12210,7 +12247,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                         produceTimeItem.setManufactureCost(user.getCost().multiply(new BigDecimal(manufactureTime)).setScale(2, RoundingMode.HALF_UP));
                         produceTimeItem.setRdCost(user.getCost().multiply(new BigDecimal(rdTime)).setScale(2, RoundingMode.HALF_UP));
                         produceTimeItem.setSalesCost(user.getCost().multiply(new BigDecimal(cusTime)).setScale(2, RoundingMode.HALF_UP));
-
                         result.add(produceTimeItem);
                     });
                 });
@@ -12220,8 +12256,42 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportProduceTimeReport(Integer companyId, Integer projectId, String startDate, String endDate) {
+    public HttpRespMsg exportProduceTimeReport(Integer companyId, Integer projectId, String ymonth) {
         HttpRespMsg msg = new HttpRespMsg();
+        //准备多张sheet
+        final List<FinanceTblcuscol> cusColList = financeTblcuscolMapper.selectList(new QueryWrapper<FinanceTblcuscol>().eq("company_id", companyId));
+        List<String> sheetNameList = new ArrayList<String>();
+        sheetNameList.add("财务数据分摊总表");
+        FinanceFixedcolname fixedItem = financeFixedcolnameService.getFixed(companyId);
+        if(!StringUtils.isEmpty(fixedItem.getMonthCost())){
+            sheetNameList.add(fixedItem.getMonthCost()+"分摊表");
+        }
+        if(!StringUtils.isEmpty(fixedItem.getBonus())){
+            sheetNameList.add(fixedItem.getBonus()+"分摊表");
+        }
+        if(!StringUtils.isEmpty(fixedItem.getAllowance())){
+            sheetNameList.add(fixedItem.getAllowance()+"分摊表");
+        }
+        if(!StringUtils.isEmpty(fixedItem.getInsuranceOld())){
+            sheetNameList.add(fixedItem.getInsuranceOld()+"分摊表");
+        }
+        if(!StringUtils.isEmpty(fixedItem.getInsuranceMedical())){
+            sheetNameList.add(fixedItem.getInsuranceMedical()+"分摊表");
+        }
+
+        if(!StringUtils.isEmpty(fixedItem.getInsuranceLosejob())){
+            sheetNameList.add(fixedItem.getInsuranceLosejob()+"分摊表");
+        }
+        if(!StringUtils.isEmpty(fixedItem.getInsuranceInjury())){
+            sheetNameList.add(fixedItem.getInsuranceInjury()+"分摊表");
+        }
+        if(!StringUtils.isEmpty(fixedItem.getHouseFund())){
+            sheetNameList.add(fixedItem.getHouseFund()+"分摊表");
+        }
+        for (FinanceTblcuscol col : cusColList) {
+            sheetNameList.add(col.getFieldName()+"分摊表");
+        }
+
         List<List<String>> dataList = new ArrayList<>();
         List<String> headList = new ArrayList<>();
         headList.add("项目编号");
@@ -12237,7 +12307,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         headList.add("研发支出-工资");
         headList.add("销售费用-工资");
         dataList.add(headList);
-        List<ProduceTime> produceTimeList = getProduceTime(companyId, projectId, startDate, endDate);
+        List<ProduceTime> produceTimeList = getProduceTime(companyId, projectId, ymonth);
         for (ProduceTime produceTime : produceTimeList) {
             List<String> list = new ArrayList<>();
             list.add(produceTime.getProjectCode());
@@ -12256,9 +12326,60 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         }
         //生成excel文件导出
         //String fileName = "人员每日工时统计_"+startDate+"至"+endDate+"_"+System.currentTimeMillis();
-        String fileName = "生产制造工时费用统计_"+ startDate+"至"+endDate+"_"+System.currentTimeMillis();
+        String fileName = "生产制造工时费用统计_"+ ymonth+"_"+System.currentTimeMillis();
         try {
-            return excelExportService.exportGeneralExcelByTitleAndList(null,null, fileName, dataList, path);
+            List[] multiSheetDataList = new ArrayList[sheetNameList.size()];
+            multiSheetDataList[0] = dataList;
+            for (int i = 1; i < sheetNameList.size(); i++) {
+                String sheetName = sheetNameList.get(i);
+                multiSheetDataList[i] = new ArrayList();
+                multiSheetDataList[i].add(headList);//每个表单的头都一样,数据不一样而已
+                for (ProduceTime produceTime : produceTimeList) {
+                    List<String> list = new ArrayList<String>();
+                    list.add(produceTime.getProjectCode());
+                    list.add(produceTime.getProjectName());
+                    list.add(produceTime.getUserName());
+                    list.add(produceTime.getDepartmentName());
+                    list.add(""+produceTime.getTotalTime());
+                    list.add(produceTime.getProduceTime()+"");
+                    list.add(produceTime.getWorksheetDeptName());
+                    //取费用成本项的值,按比例计算
+                    Finance userFinance = produceTime.getUserFinance();
+                    BigDecimal cost = new BigDecimal(0);
+                    if (userFinance != null) {
+                        if (sheetName.equals(fixedItem.getMonthCost()+"分摊表")){
+                            cost = userFinance.getMonthCost();
+                        } else if (sheetName.equals(fixedItem.getAllowance()+"分摊表")) {
+                            cost = userFinance.getAllowance();
+                        } else if (sheetName.equals(fixedItem.getInsuranceOld()+"分摊表")) {
+                            cost = userFinance.getInsuranceOld();
+                        } else if (sheetName.equals(fixedItem.getInsuranceMedical()+"分摊表")) {
+                            cost = userFinance.getInsuranceMedical();
+                        } else if (sheetName.equals(fixedItem.getInsuranceLosejob()+"分摊表")) {
+                            cost = userFinance.getInsuranceLosejob();
+                        } else if (sheetName.equals(fixedItem.getInsuranceInjury()+"分摊表")) {
+                            cost = userFinance.getInsuranceInjury();
+                        } else if (sheetName.equals(fixedItem.getHouseFund()+"分摊表")) {
+                            cost = userFinance.getHouseFund();
+                        } else if (sheetName.equals(fixedItem.getBonus()+"分摊表")) {
+                            cost = userFinance.getBonus();
+                        }
+                    }
+
+                    BigDecimal produceCost = new BigDecimal(produceTime.getProduceTime()/produceTime.getUserTotalTime()).multiply(cost).setScale(2,BigDecimal.ROUND_HALF_UP);
+                    list.add(produceCost.toString());
+                    list.add(produceTime.getProjectTime()+"");
+                    BigDecimal manufactureCost = new BigDecimal(produceTime.getManufactureTime()/produceTime.getUserTotalTime()).multiply(cost).setScale(2,BigDecimal.ROUND_HALF_UP);
+                    list.add(manufactureCost.toString());
+                    BigDecimal rdCost = new BigDecimal(produceTime.getRdTime()/produceTime.getUserTotalTime()).multiply(cost).setScale(2,BigDecimal.ROUND_HALF_UP);
+                    list.add(rdCost.toString());
+                    BigDecimal salesCost = new BigDecimal(produceTime.getSalesTime()/produceTime.getUserTotalTime()).multiply(cost).setScale(2,BigDecimal.ROUND_HALF_UP);
+                    list.add(salesCost.toString());
+                    multiSheetDataList[i].add(list);
+                }
+            }
+            return excelExportService.exportMultiSheetGeneralExcelByTitleAndList(null,null,fileName , multiSheetDataList, path, sheetNameList.toArray(new String[0]));
+//            return excelExportService.exportGeneralExcelByTitleAndList(null,null, fileName, dataList, path);
         } catch (Exception e) {
             e.printStackTrace();
         }

+ 0 - 147
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/DataCollectTask.java

@@ -117,155 +117,8 @@ public class DataCollectTask {
     public void sqlServerProjectTask() {
         if(isDev){return;}
         if(isPrivateDeploy) return;
-        RestTemplate restTemplate = new RestTemplate();
-        String sumUrl = PREFIX_URL+"/dataCollect/getSqlServerProjectDataSum";
-        String listUrl = PREFIX_URL+"/dataCollect/getSqlServerProjectDataList";
-        Company company = companyMapper.selectById(HONGHU_COMP_ID);
-        try {
-            ResponseEntity<String> sumResponse = restTemplate.exchange(
-                    sumUrl,
-                    HttpMethod.GET,
-                    null,
-                    String.class
-            );
-            Integer totalNum = 0;
-            if (sumResponse.getStatusCode() == HttpStatus.OK) {
-                totalNum = Integer.parseInt(sumResponse.getBody());
-            } else {
-                System.out.println("请求失败,状态码: " + sumResponse.getStatusCode());
-            }
-            if(totalNum > 0){
-                int pageSize = 1000;
-                int offset = 0;
-                List<Project> toAddList = new ArrayList<>();
-                List<Project> toUpdateList = new ArrayList<>();
-                while (offset < totalNum) {
-                    HttpHeaders headers = new HttpHeaders();
-                    headers.setContentType(MediaType.APPLICATION_JSON);
-                    Map<String, Object> requestBody = new HashMap<>();
-                    requestBody.put("pageNo", offset);
-                    requestBody.put("pageSize", pageSize);
-                    HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody, headers);
-                    ResponseEntity<List<Project>> listResponse = restTemplate.exchange(
-                            listUrl,
-                            HttpMethod.POST,
-                            requestEntity,
-                            new  ParameterizedTypeReference<List<Project>>(){}
-                    );
-                    if (listResponse.getStatusCode() == HttpStatus.OK) {
-                        List<Project> dataList = listResponse.getBody();
-                        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(dataList)){
-                            List<String> collect = dataList.stream().map(Project::getProjectCode).distinct().collect(Collectors.toList());
-                            List<String> existIds = projectMapper.getExistIds(collect, HONGHU_COMP_ID);
-                            if(!CollectionUtils.isEmpty(existIds)){
-                                toUpdateList.addAll(dataList.stream().filter(t -> existIds.contains(t.getProjectCode())).collect(Collectors.toList()));
-                                toAddList.addAll(dataList.stream().filter(t -> !existIds.contains(t.getProjectCode())).collect(Collectors.toList()));
-                            }else{
-                                toAddList.addAll(dataList);
-                            }
-                            if(!CollectionUtils.isEmpty(toAddList)){
-                                for (Project project : toAddList) {
-                                    //以项目编码前五为作为分类名称
-                                    String categoryName = project.getProjectCode().substring(0,5);
-                                    project.setCategoryName(categoryName);
-                                    ProjectCategory category = projectCategoryMapper.selectOne(new LambdaQueryWrapper<ProjectCategory>()
-                                            .eq(ProjectCategory::getCompanyId, HONGHU_COMP_ID)
-                                            .eq(ProjectCategory::getName, project.getCategoryName())
-                                            .last(" limit 1 ")
-                                    );
-                                    int categoryId;
-                                    if(null != category){
-                                        categoryId = category.getId();
-                                    }else{
-                                        ProjectCategory tmp = new ProjectCategory();
-                                        tmp.setName(project.getCategoryName());
-                                        tmp.setCompanyId(HONGHU_COMP_ID);
-                                        projectCategoryMapper.insert(tmp);
-                                        categoryId = tmp.getId();
-                                    }
-                                    if(0!= categoryId){
-                                        project.setCategory(categoryId);
-                                        projectMapper.insert(project);
-                                        if (company.getPackageProject() == 1) {
-                                            initGroup(HONGHU_COMP_ID,project.getId());
-                                        }
-                                    }
-                                }
-                            }
-                            if(!CollectionUtils.isEmpty(toUpdateList)){
-                                for (Project orderInfo : toUpdateList) {
-                                    projectMapper.updateById(orderInfo);
-                                }
-                            }
-                            toUpdateList.clear();
-                            toAddList.clear();
-                        }
-                    }
-                    offset += pageSize;
-                }
-            }
-        } catch (Exception e) {
-            System.out.println("请求发生异常: " + e.getMessage());
-            e.printStackTrace();
-        }
-
-    }
 
 
-    public void initGroup(Integer companyId, Integer projectId) {
-        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
-                .eq(User::getRoleName, "超级管理员")
-                .last(" limit 1")
-        );
-        List<GroupTemplate> groupTemplates = groupTemplateMapper.selectList(new QueryWrapper<GroupTemplate>()
-                .eq("company_id", companyId).eq("cre_with_pro", true));
-        if (groupTemplates.size()==0){
-            //创建默认分组
-            TaskGroup group = new TaskGroup();
-            group.setProjectId(projectId);
-            //group.setName("项目阶段");
-            group.setName(MessageUtils.message("entry.projectStage"));
-            taskGroupMapper.insert(group);
-        }else{
-            for (GroupTemplate groupTemplate : groupTemplates) {
-                TaskGroup group = new TaskGroup();
-                group.setProjectId(projectId);
-                group.setName(groupTemplate.getName());
-                taskGroupMapper.insert(group);
-                //从模板创建任务列表
-                List<GroupTmpstages> stages = groupTmpstagesMapper.selectList(new QueryWrapper<GroupTmpstages>().eq("template_id", groupTemplate.getId()));
-                List<Stages> batchList = new ArrayList<>();
-                stages.forEach(s->{
-                    Stages stageItem = new Stages();
-                    stageItem.setGroupId(group.getId());
-                    stageItem.setStagesName(s.getStagesName());
-                    stageItem.setSequence(s.getSequence());
-                    stageItem.setProjectId(projectId);
-                    batchList.add(stageItem);
-                });
-                stagesService.saveBatch(batchList);
-                //阶段的任务,里程碑,风险
-                List<GtemplateTask> gtemplateTaskList = gtemplateTaskMapper.selectList(
-                        new QueryWrapper<GtemplateTask>().eq("gtemplate_id", groupTemplate.getId())
-                                .orderByAsc("seq"));
-                if (gtemplateTaskList.size() > 0) {
-                    List<Task> taskList = new ArrayList<>();
-                    gtemplateTaskList.forEach(gt->{
-                        Task task = gt.toTask();
-                        task.setProjectId(projectId);
-                        task.setGroupId(group.getId());
-                        String sName = stages.stream().filter(s->s.getId().equals(gt.getTstagesId())).findFirst().get().getStagesName();
-                        Integer realStageId = batchList.stream().filter(bat->bat.getStagesName().equals(sName)).findFirst().get().getId();
-                        task.setStagesId(realStageId);
-                        task.setCreaterId(user.getId());
-                        task.setCreaterName(user.getName());
-                        task.setCreatorColor(user.getColor());
-                        taskList.add(task);
-                    });
-                    taskService.saveBatch(taskList);
-                }
-            }
-        }
     }
 
     /**

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

@@ -61,6 +61,8 @@ public class TimingTask {
     //是否是开发环境
     @Value("${configEnv.isDev}")
     boolean isDev;
+    @Value("${configEnv.isSaasProd}")
+    private boolean isSaasProd;
     @Value("${privateDeployURL.pcUrl}")
     private String pcUrl;
     //是否是私有化部署
@@ -252,8 +254,11 @@ public class TimingTask {
         DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         String yesStr = dateTimeFormatter.format(yestoday);
         List<TimeType> typeList = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("sync_dingding", 1));
-        for (TimeType type : typeList) {
-            Integer companyId = type.getCompanyId();
+        List<Integer> compIds = typeList.stream().map(TimeType::getCompanyId).collect(Collectors.toList());
+        if (compIds.size() == 0) return;
+        List<Company> companyList = companyMapper.selectList(new QueryWrapper<Company>().in("id", compIds).ge("expiration_date", LocalDateTime.now()));
+        for (Company company : companyList) {
+            Integer companyId = company.getId();
             System.out.println("钉钉同步:companyId="+companyId);
             dingDingService.syncCardTime(companyId, null, yesStr, yesStr);
         }
@@ -285,6 +290,10 @@ public class TimingTask {
     @Scheduled(cron = "0 11 2 ? * *")
     private void synDingDingWorkData() {
         if (isDev) return;
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        LocalDateTime yestoday = LocalDateTime.now().minusDays(2);
+        String startDate = dtf.format(yestoday);
+        String endDate = dtf.format(yestoday.plusDays(32));
         List<TimeType> timeTypeList = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("sync_dingding", 1));
         if (timeTypeList.size() > 0) {
             List<Integer> compIds = timeTypeList.stream().map(TimeType::getCompanyId).collect(Collectors.toList());
@@ -293,10 +302,7 @@ public class TimingTask {
                     .isNotNull("inner_appkey"));
             System.out.println("==========获取钉钉内部应用的数量是:"+dingdingList.size());
             if (dingdingList.size() > 0) {
-                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-                LocalDateTime yestoday = LocalDateTime.now().minusDays(2);
-                String startDate = dtf.format(yestoday);
-                String endDate = dtf.format(yestoday.plusDays(32));
+
                 for (int i=0;i<dingdingList.size(); i++) {
                     System.out.println("钉钉公司:"+dingdingList.get(i).getCorpName());
                     long t1 = System.currentTimeMillis();
@@ -306,8 +312,13 @@ public class TimingTask {
                 }
             }
         }
+        if (isSaasProd) {
+            dingDingService.syncLeaveTime(null, null, startDate, endDate);
+        }
     }
 
+
+
     //每个月五号一点推送上月日报信息
     @Scheduled(cron = "0 0 1 5 * ?")
     private void pushReportListByToken(){
@@ -1433,7 +1444,7 @@ public class TimingTask {
 
     //每分钟校验是否有需要提醒的填报
     @Scheduled(fixedRate = 60 * 1000)
-    private void process() {
+    private void pushMissReportAlert() {
         if (isDev) {
             return;
         }
@@ -1449,7 +1460,9 @@ public class TimingTask {
             if (str.equals(t.getAlertTime())) {
                 //节假日是否提醒
                 Boolean workDay = timeTypeService.isWorkDay(t.getCompanyId(), localDate, t, null);
-                if ((t.getAlertType() == 0 || t.getAlertType() == 1) && !workDay){
+                LocalDate yesterday = localDate.minusDays(1);
+                boolean isYesterdayWorkDay = timeTypeService.isWorkDay(t.getCompanyId(), yesterday, t, null);
+                if ((t.getAlertType() == 0 && !workDay) ||(t.getAlertType() == 1 && !isYesterdayWorkDay)){
                     return;
                 }
                 //每周几提醒上周的情况下,需要校验当前是周几

+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/HttpRespMsg.java

@@ -48,9 +48,10 @@ public class HttpRespMsg implements Serializable {
         code = "ok";
     }
 
-    public void setError(String errorMsg) {
+    public HttpRespMsg setError(String errorMsg) {
         code = "error";
         msg = errorMsg;
+        return this;
     }
 
     public HttpRespMsg fail(String errorMsg) {

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/SyncSapUtils.java

@@ -262,6 +262,7 @@ public class SyncSapUtils {
             result = result.substring(result.indexOf(">")+1, result.lastIndexOf("</n0:ProjectByElementsResponse_sync>"));
             result="<XMLDATA>"+result+"</XMLDATA>";
         }
+        System.out.println("===============打印同步的项目内容===============");
         System.out.println(result);
         XmlResponseData xmlResponseData = (XmlResponseData) CommonUtils.convertXmlStrToObject(XmlResponseData.class, result);
         return xmlResponseData;

+ 29 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WebServiceUtils.java

@@ -2,18 +2,47 @@ package com.management.platform.util;
 
 import lombok.extern.slf4j.Slf4j;
 
+import javax.net.ssl.*;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.security.cert.X509Certificate;
 import java.util.Base64;
 
 @Slf4j
 public class WebServiceUtils {
+    public static void disableSSLVerification() {
+        try {
+            // 创建信任所有证书的信任管理器
+            TrustManager[] trustAllCerts = new TrustManager[] {
+                    new X509TrustManager() {
+                        public X509Certificate[] getAcceptedIssuers() {
+                            return null;
+                        }
+                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
+                        }
+                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
+                        }
+                    }
+            };
+
+            // 安装信任管理器
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, trustAllCerts, new java.security.SecureRandom());
+            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
 
+            // 创建不验证主机名的HostnameVerifier
+            HostnameVerifier allHostsValid = (hostname, session) -> true;
+            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
     public static String requestByXml(String reqUrl, String sendMsg,int timeout,String userName,String password) throws Exception {
+        disableSSLVerification();
         // 开启HTTP连接ַ
         InputStreamReader isr = null;
         BufferedReader inReader = null;

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

@@ -26,11 +26,12 @@
         <result column="create_date" property="createDate" />
         <result column="reg_from" property="regFrom" />
         <result column="non_project_simple" property="nonProjectSimple" />
+        <result column="project_progress_mode" property="projectProgressMode" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_name, staff_count_max, expiration_date, set_meal, package_worktime, package_project, package_contract, package_oa, package_etimecard, package_expense, package_customer, package_engineering, package_simple, package_finance, package_provider, package_project_approval, package_device, is_international, create_date, reg_from, non_project_simple
+        id, company_name, staff_count_max, expiration_date, set_meal, package_worktime, package_project, package_contract, package_oa, package_etimecard, package_expense, package_customer, package_engineering, package_simple, package_finance, package_provider, package_project_approval, package_device, is_international, create_date, reg_from, non_project_simple, project_progress_mode
     </sql>
 
 </mapper>

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

@@ -20,11 +20,14 @@
         <result column="is_amount_fixed" property="isAmountFixed" />
         <result column="finish_status" property="finishStatus" />
         <result column="stamp_duty_items" property="stampDutyItems" />
+        <result column="stamp_duty_status" property="stampDutyStatus" />
+        <result column="stamp_duty_time" property="stampDutyTime" />
+        <result column="is_platform_buy" property="isPlatformBuy" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        contract_id, customer_org, customer_contact, customer_phone, use_department, funds_source, undertaker, agent, sign_date, filings_date, tax_rate, amounts_no_tax, currency, is_amount_fixed, finish_status, stamp_duty_items
+        contract_id, customer_org, customer_contact, customer_phone, use_department, funds_source, undertaker, agent, sign_date, filings_date, tax_rate, amounts_no_tax, currency, is_amount_fixed, finish_status, stamp_duty_items, stamp_duty_status, stamp_duty_time, is_platform_buy
     </sql>
 
 </mapper>

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

@@ -3039,7 +3039,7 @@
         <if test="startDate!=null and startDate !='' and endDate!=null and endDate !='' ">
             and r.create_date BETWEEN #{startDate} and #{endDate}
         </if>
-        GROUP BY u.id ,pm.id
+        GROUP BY u.id ,pm.work_order_num
         <if test="pageIndex!=null and pageSize !=null">
             LIMIT #{pageIndex} ,#{pageSize}
         </if>

+ 65 - 25
fhKeeper/formulahousekeeper/timesheet/src/views/contract/components/customContract.vue

@@ -89,9 +89,17 @@
           <span v-if="scope.row.finishStatus == 2" style="color: #67C23A;">履约完成</span>
         </template>
       </el-table-column>
-      <el-table-column prop="customerContact" label="供应商联系人" min-width="190"></el-table-column>
-      <el-table-column prop="customerPhone" label="对方联系电话" min-width="190"></el-table-column>
-      <el-table-column prop="useDepartment" label="使用部门" min-width="190"></el-table-column>
+      <!-- <el-table-column prop="customerContact" label="供应商联系人" min-width="190"></el-table-column> -->
+      <!-- <el-table-column prop="customerPhone" label="对方联系电话" min-width="190"></el-table-column> -->
+      <el-table-column label="供应商联系人及电话" min-width="240">
+        <template slot-scope="scope">
+          <div>
+            {{ scope.row.customerContact }} 
+            <span v-if="scope.row.customerPhone">({{ scope.row.customerPhone }})</span>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column prop="useDepartment" label="合同承办部门" min-width="190"></el-table-column>
       <el-table-column prop="fundsSource" label="经费来源" min-width="190">
         <template slot-scope="scope">
           <span v-if="scope.row.fundsSource == 1">科研</span>
@@ -156,7 +164,7 @@
         <el-form ref="contractForm" :model="contractForm" label-width="160px" :rules="rules" class="contractForm">
           <el-form-item :label="$t('contractno')">
             <el-input v-model="contractForm.number" :disabled="contractForm.status == 0" :maxlength="50"
-              style="width:260px;" show-word-limit :placeholder="$t('peaseenterthe')" clearable
+              style="width:300px;" show-word-limit :placeholder="$t('peaseenterthe')" clearable
               @input="searchProject"></el-input>
             <span style="margin-left:20px;">{{ $t('rselatedprojects') }}</span>
             <el-select v-model="contractForm.projectId" filterable clearable style="width:260px;"
@@ -199,8 +207,14 @@
             <el-input v-model="contractForm.customerPhone" :disabled="contractForm.status == 0"
               :placeholder="$t('peaseenterthe')" clearable></el-input>
           </el-form-item>
+          <el-form-item label="是否为平台采购">
+            <el-select v-model="contractForm.isPlatformBuy" :disabled="contractForm.status == 0" placeholder="请选择" style="width:300px;">
+              <el-option label="是" :value="true"></el-option>
+              <el-option label="否" :value="false"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item label="采购方式">
-            <el-select v-model="contractForm.procurementWay" :disabled="contractForm.status == 0" placeholder="请选择">
+            <el-select v-model="contractForm.procurementWay" :disabled="contractForm.status == 0" placeholder="请选择" style="width:300px;">
               <el-option label="公开招标" :value="0"></el-option>
               <el-option label="邀请招标" :value="1"></el-option>
               <el-option label="询比价" :value="2"></el-option>
@@ -213,7 +227,7 @@
               :placeholder="$t('peaseenterthe')" clearable></el-input>
           </el-form-item>
           <el-form-item label="经费来源">
-            <el-select v-model="contractForm.fundsSource" :disabled="contractForm.status == 0" placeholder="请选择">
+            <el-select v-model="contractForm.fundsSource" :disabled="contractForm.status == 0" placeholder="请选择" style="width:300px;">
               <el-option label="科研" value="1"></el-option>
               <el-option label="其他(专项等)" value="2"></el-option>
             </el-select>
@@ -228,19 +242,19 @@
           </el-form-item>
           <el-form-item label="签订日期">
             <el-date-picker v-model="contractForm.signDate" :disabled="contractForm.status == 0"
-              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')"></el-date-picker>
+              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')" style="width:300px;"></el-date-picker>
           </el-form-item>
           <el-form-item label="合同生效日期">
             <el-date-picker v-model="contractForm.startDate" :disabled="contractForm.status == 0"
-              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')"></el-date-picker>
+              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')" style="width:300px;"></el-date-picker>
           </el-form-item>
           <el-form-item label="合同终止日期">
             <el-date-picker v-model="contractForm.endDate" :disabled="contractForm.status == 0"
-              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')"></el-date-picker>
+              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')" style="width:300px;"></el-date-picker>
           </el-form-item>
           <el-form-item label="备案日期">
             <el-date-picker v-model="contractForm.filingsDate" :disabled="contractForm.status == 0"
-              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')"></el-date-picker>
+              value-format="yyyy-MM-dd" type="date" :placeholder="$t('optiondate')" style="width:300px;"></el-date-picker>
           </el-form-item>
           <el-form-item label="合同金额(元)/含税价">
             <el-input v-model="contractForm.amounts" :disabled="contractForm.status == 0 || !contractForm.isAmountFixed"
@@ -262,7 +276,7 @@
           </el-form-item>
           <el-form-item label="是否固定金额">
             <el-select v-model="contractForm.isAmountFixed" :disabled="contractForm.status == 0" placeholder="请选择"
-              @change="processingContractAmount()">
+              @change="processingContractAmount()" style="width:300px;">
               <el-option label="是" :value="true"></el-option>
               <el-option label="否" :value="false"></el-option>
             </el-select>
@@ -272,21 +286,21 @@
               :placeholder="$t('peaseenterthe')" clearable></el-input>
           </el-form-item>
           <el-form-item label="合同状态(是否结清)">
-            <el-select v-model="contractForm.finishStatus" :disabled="contractForm.status == 0" placeholder="请选择">
+            <el-select v-model="contractForm.finishStatus" :disabled="contractForm.status == 0" placeholder="请选择" style="width:300px;">
               <el-option label="履约中" :value="1"></el-option>
               <el-option label="履约完成" :value="2"></el-option>
             </el-select>
           </el-form-item>
           <el-form-item label="合同印花税缴纳状态">
-            <el-select v-model="contractForm.stampDutyStatus" :disabled="contractForm.status == 0 || !permissions.contractStampDuty" placeholder="请选择"
-              @change="stampDutyStatusChange()">
+            <el-select v-model="contractForm.stampDutyStatus" :disabled="!permissions.contractStampDuty" placeholder="请选择"
+              @change="stampDutyStatusChange()" style="width:300px;">
               <el-option v-for="item in stampDutyStatusList" :key="item.id" :label="item.label" :value="item.id"></el-option>
             </el-select>
           </el-form-item>
           <el-form-item label="合同印花税缴纳时间">
             <el-date-picker v-model="contractForm.stampDutyTime" value-format="yyyy-MM-dd" type="date"
-              placeholder="选择缴纳日期" :disabled="contractForm.status == 0 || [0, 1].includes(contractForm.stampDutyStatus) || !permissions.contractStampDuty"
-              :clearable="false" @change="stampDutyTimeChange()"></el-date-picker>
+              placeholder="选择缴纳日期" :disabled="[0, 1].includes(contractForm.stampDutyStatus) || !permissions.contractStampDuty"
+              :clearable="false" @change="stampDutyTimeChange()" style="width:300px;"></el-date-picker>
           </el-form-item>
           <el-form-item :label="$t('bei-zhu')">
             <el-input v-model="contractForm.remarks" :disabled="contractForm.status == 0"
@@ -331,7 +345,7 @@
               </el-table-column>
               <el-table-column prop="stampDutyTime" label="印花税缴纳时间" width="150">
                   <template slot-scope="scope">
-                      <div><el-date-picker type="date" v-model="scope.row.stampDutyTime" style="width:140px;" :placeholder="$t('optiondate')" value-format="yyyy-MM-dd" size="small" :disabled="!permissions.contractStampDuty || contractForm.isAmountFixed"></el-date-picker></div>
+                      <div><el-date-picker type="date" v-model="scope.row.stampDutyTime" style="width:140px;" :placeholder="$t('optiondate')" value-format="yyyy-MM-dd" size="small" :disabled="!permissions.contractStampDuty || contractForm.isAmountFixed || (!contractForm.isAmountFixed && [0, 1].includes(contractForm.stampDutyStatus))"></el-date-picker></div>
                   </template>
                 </el-table-column>
               <el-table-column width="80" fixed="right">
@@ -426,11 +440,20 @@
           <el-form-item label="供应商名称">
             {{ contractForm.customerOrg }}
           </el-form-item>
-          <el-form-item label="供应商联系人">
+          <!-- <el-form-item label="供应商联系人">
             {{ contractForm.customerContact }}
           </el-form-item>
           <el-form-item label="对方联系电话">
             {{ contractForm.customerPhone }}
+          </el-form-item> -->
+          <el-form-item label="供应商联系人及电话">
+            <div>
+            {{ contractForm.customerContact }} 
+            <span v-if="contractForm.customerPhone">({{ contractForm.customerPhone }})</span>
+          </div>
+          </el-form-item>
+          <el-form-item label="是否为平台采购">
+            {{ contractForm.isPlatformBuy ? '是' : '否' }}
           </el-form-item>
           <el-form-item label="采购方式">
             {{ ['公开招标', '邀请招标', '询比价', '竞争性谈判', '单一来源'][contractForm.procurementWay] }}
@@ -887,12 +910,14 @@ export default {
     },
     //添加合同回款情况
     addItem() {
-      // let p = 0;
-      // this.contractPaymentList.push( { contractId:this.contractForm.id, isPayed:false,payDate: null, amount:0.0});
       const { isAmountFixed, stampDutyStatus } = this.contractForm
       if(!isAmountFixed && stampDutyStatus == 2) {
-        this.contractForm.stampDutyStatus = 3
-        this.stampDutyStatusChange()
+        // this.contractForm.stampDutyStatus = 3
+        setTimeout(() => {
+          if ([0, 1].includes(this.contractForm.stampDutyStatus)) {
+            this.contractForm.stampDutyTime = ''
+          }
+        }, 300);
       }
 
       let val = {
@@ -1021,6 +1046,10 @@ export default {
         parameter.startDate = this.dateArray[0]
         parameter.endDate = this.dateArray[1]
       }
+      if (this.paymentDate && this.paymentDate.length == 2) {
+        parameter.paymentStartDate = this.paymentDate[0]
+        parameter.paymentEndDate = this.paymentDate[1]
+      }
 
       if (this.customerOrgs) {
         parameter.customerOrg = this.customerOrgs
@@ -1030,6 +1059,10 @@ export default {
         parameter.finishStatus = this.finishStatuss
       }
 
+      if(this.stampDutyStatusVal || this.stampDutyStatusVal === 0) {
+        parameter.stampDutyStatus = this.stampDutyStatusVal
+      }
+
       this.http.post('/contract/exportContractOneToMany', parameter,
         res => {
           if (res.code == 'ok') {
@@ -1354,21 +1387,28 @@ export default {
             }
             totalPayment += parseFloat(this.contractPaymentList[i].payedAmount);
           }
-          if (totalPayment > parseFloat(this.contractForm.amounts)) {
+          if ((totalPayment > parseFloat(this.contractForm.amounts)) && this.contractForm.isAmountFixed) {
             this.$message({
               message: this.$t('zong-hui-kuan-jinebu-de-da-yu-he-tong-jin-e'),
               type: 'error'
             })
             return;
           }
+          const flagList = this.returnValuableData(this.contractPaymentList)
+          const modifyState = flagList.some(item => !item.hasOwnProperty('stampDutyTime'));
+          if(!this.contractForm.isAmountFixed && modifyState) {
+            this.contractForm.stampDutyStatus = 3
+          }
+          
           this.submitLoading = true
           delete this.contractForm.files
-          this.contractForm.paymentListStr = JSON.stringify(this.returnValuableData(this.contractPaymentList));
+          this.contractForm.paymentListStr = JSON.stringify(flagList);
           delete this.contractForm.msg
           delete this.contractForm.nextPaymentDate
           delete this.contractForm.nextPaymentAmount
           delete this.contractForm.payCustomizedData
           delete this.contractForm.checkerId
+          
           this.http.post(this.dialogTitle == this.$t('add') ? '/contract/addContract' : '/contract/editContract', this.contractForm,
             res => {
               this.submitLoading = false
@@ -1651,7 +1691,7 @@ export default {
 
     stampDutyTimeChange() {
       const { id, isAmountFixed } = this.contractForm
-      if (id && !isAmountFixed) {
+      if (id && !isAmountFixed && this.contractForm.status != 0) {
         this.getStampDutyTimeNullList(id)
       }
     },

+ 6 - 5
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -105,6 +105,8 @@
           </span>
         </template>
 
+        <el-date-picker v-if="ins == 33" v-model="selectYmonth" type="month" placeholder="选择月" :clearable="false" @change="picks()" size="small" value-format="yyyy-MM" style="width: 160px"></el-date-picker>
+
         <!-- 项目分类 -->
         <template v-if="ins == 22">
           <span>
@@ -2175,6 +2177,7 @@ export default {
   props: {},
   data() {
     return {
+      selectYmonth:this.dayjs(new Date()).format('YYYY-MM'),
       themeColor: getThemeColor(),
       screeningCondition: { // 筛选条件的判断
         project: [4, 8, 9, 10, 11, 14, 15, 17, 19, 20, 21, 22, 28, 30, 31,34], // 项目筛选条件 (不等于)
@@ -2182,7 +2185,7 @@ export default {
         monthRange: [19, 30], // 月份区间筛选条件 (等于)
         staff: [6, 8, 9, 19, 11, 14, 18, 23, 25, 26,28, 30, 32], // 人员筛选条件 (等于)
         departments: [14, 15, 23,21,26,28,19, 30], // 部门筛选条件 (等于)
-        timePeriod: [5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 20, 21, 22, 24, 25, 26,28,33,34], // 时间段筛选条件 (等于)
+        timePeriod: [5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 20, 21, 22, 24, 25, 26,28,34], // 时间段筛选条件 (等于)
       },
       efficentList:[],
       groupNames: [],
@@ -3332,8 +3335,7 @@ export default {
           fName = `生产制造成本报表.xlsx`
           url = `/report/exportProduceTimeReport`
           sl.projectId = this.proJuctId
-          sl.startDate = this.rangeDatas[0]
-          sl.endDate = this.rangeDatas[1]
+          sl.ymonth = this.selectYmonth
         } else if(this.ins == 34) {
           fName = `工作包令号工时统计表.xlsx`
           url = `/project/exportWorkOrderNumStatistics`
@@ -5381,8 +5383,7 @@ export default {
     getManufacturingCost() {
       let sl = {}
       sl.projectId = this.proJuctId
-      sl.startDate = this.rangeDatas[0]
-      sl.endDate = this.rangeDatas[1]
+      sl.ymonth = this.selectYmonth;
       this.manufacturingCostLoading = true
       this.postData(`/report/getProduceTimeReport`, { ...sl }).then(res => { 
         this.manufacturingCost = res.data || []

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

@@ -1795,10 +1795,11 @@
                 <el-form-item ><el-checkbox v-model="syncItem.syncCard">同步考勤打卡</el-checkbox></el-form-item>
                 <el-form-item ><el-checkbox v-model="syncItem.syncLeave">同步请假单</el-checkbox></el-form-item>
                 <el-form-item ><el-checkbox v-model="syncItem.syncBusinessTrip">同步出差单</el-checkbox></el-form-item>
+                <el-form-item ><el-checkbox v-model="syncItem.syncProject">同步项目号</el-checkbox></el-form-item>
             </el-form>
             <div slot="footer" class="dialog-footer">
                 <el-button  @click="syncU8DialogVisable = false">{{ $t('btn.cancel') }}</el-button>
-                <el-button type="primary" @click="syncU8Start()" :disabled="!(syncItem.syncOrder||syncItem.syncCard||syncItem.syncLeave||syncItem.syncBusinessTrip)" :loading="startSyncingU8">
+                <el-button type="primary" @click="syncU8Start()" :disabled="!(syncItem.syncOrder||syncItem.syncCard||syncItem.syncLeave||syncItem.syncBusinessTrip||syncItem.syncProject)" :loading="startSyncingU8">
                     {{startSyncingU8?'正在同步':'开始同步'}}</el-button>
             </div>
         </el-dialog>

+ 22 - 4
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -480,6 +480,9 @@
                             v-if="reportTimeType.type == 1"
                             :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
                             :placeholder="$t('defaultText.pleaseSelectWorkingHours') + domain.workingTime"
+                            filterable
+                                :allow-create="user.companyId == 469"
+                                default-first-option
                             @change="seleChn(0,domain)">
                             <el-option v-for="item in timeRange" :key="item" :value="item.toFixed(1)">{{item.toFixed(1)}}</el-option>
                             </el-select>
@@ -1323,9 +1326,12 @@
                     <div class="exportReportRadio">
                         <el-radio v-model="exportType" :label="0">{{ $t('wanZhengDaoChu') }}</el-radio>
                         <el-radio v-model="exportType" :label="1">{{ $t('jingJianDaoChu') }}</el-radio>
-                        <el-tooltip effect="dark" :content="$t('jingJianRiBaoBuHanGongZuoShiXiangHeShenPiXinXiShuJuLiangGengXiaoDaoChuGengKuai')" placement="top-start">
+                        <el-tooltip effect="dark" v-if="user.companyId == '936'" :content="$t('jingJianRiBaoBuHanGongZuoShiXiangHeShenPiXinXiShuJuLiangGengXiaoDaoChuGengKuai')" placement="top-start">
                             <i class="el-icon-question"></i>
                         </el-tooltip>
+                        <!-- <el-tooltip effect="dark" v-if="user.companyId == '1071'" content="精简日报不含填写审核节点信息和周总结" placement="top-start">
+                            <i class="el-icon-question"></i>
+                        </el-tooltip> -->
                     </div>
                 </el-form-item>
             </el-form>
@@ -1767,7 +1773,14 @@
               :label="$t('state.states')"
               align="center"
               prop="status"
-            />
+            >
+            <template slot-scope="scope">
+                    <span v-if="scope.row.status == '待提交'" style="color:orange" >{{ scope.row.status }}</span>
+                    <span v-else-if="scope.row.status == '驳回'" style="color:red" >{{ scope.row.status }}</span>
+                    <span v-else-if="scope.row.status == '请假'" style="color:green" >{{ scope.row.status }}</span>
+                    <span v-else >{{ scope.row.status }}</span>
+                </template>
+            </el-table-column>
             <el-table-column
               min-width="200"
               :label="$t('other.attendanceData')"
@@ -5054,8 +5067,8 @@
                     this.selectDegreeId(domain, index)
                 }
                 
-                domain.projectName = this.fillProjectList.filter(p=>p.id == domain.projectId)[0].projectName;
-                domain.isPublic = this.fillProjectList.filter(p=>p.id == domain.projectId)[0].isPublic;
+                domain.projectName = this.isSubstitude?this.subFillProjectList.filter(p=>p.id == domain.projectId)[0].projectName:this.fillProjectList.filter(p=>p.id == domain.projectId)[0].projectName;
+                domain.isPublic = this.isSubstitude?this.subFillProjectList.filter(p=>p.id == domain.projectId)[0].isPublic:this.fillProjectList.filter(p=>p.id == domain.projectId)[0].isPublic;
                 this.http.post('/sub-project/list',{
                     projectId: domain.projectId,
                     isReport: true
@@ -6251,6 +6264,10 @@
                 if(this.exportParam.plate) {
                     param.plate = this.exportParam.plate
                 }
+                //物奇直接以精简模式导出
+                if (this.user.companyId == '1071') {
+                    param.exportType = 1;
+                }
                 param.stateKey = this.stateKey
                 // param.departmentId = this.user.departmentId
                 this.http.post(this.port.report.export, param,
@@ -6697,6 +6714,7 @@
                             this.workForm = {
                                 ...copyWorkForm
                             }
+                            if (candelete) this.reportCanDelete=candelete;
                         } else {
                             let copyWorkForm = {
                                 createDate: this.workForm.createDate,

+ 2 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/views/leave/list.vue

@@ -1774,6 +1774,8 @@ export default {
                         message: this.$t('operationissuccessful'),
                         type: "success"
                 });
+                //刷新当前页面
+                this.billss();
             } else {
                 this.$message({
                 message: res.msg,