Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

yusm 2 nedēļas atpakaļ
vecāks
revīzija
1338cb0f65
18 mainītis faili ar 534 papildinājumiem un 236 dzēšanām
  1. 143 131
      fhKeeper/formulahousekeeper/course-pc/src/views/coursemanagement/list.vue
  2. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ContractBonusSummaryController.java
  3. 4 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractBonusDetail.java
  4. 30 8
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractBonusSummary.java
  5. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/ContractBonusSummaryVO.java
  6. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ContractBonusSummaryMapper.java
  7. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ContractBonusSummaryService.java
  8. 3 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExcelParserService.java
  9. 12 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractBonusDetailServiceImpl.java
  10. 37 11
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractBonusSummaryServiceImpl.java
  11. 9 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  12. 25 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  13. 3 26
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ContractBonusDetailMapper.xml
  14. 14 16
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ContractBonusSummaryMapper.xml
  15. 4 4
      fhKeeper/formulahousekeeper/timesheet/src/views/Login.vue
  16. 179 5
      fhKeeper/formulahousekeeper/timesheet/src/views/project/financeComponents/incomeDetail.vue
  17. 29 8
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  18. 33 8
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue

+ 143 - 131
fhKeeper/formulahousekeeper/course-pc/src/views/coursemanagement/list.vue

@@ -9,7 +9,7 @@
                             :value="item.value">
                         </el-option>
                     </el-select>
-                </el-form-item> 
+                </el-form-item>
                 <el-form-item label="课程名称">
                     <el-input v-model="keyword" placeholder="请输入" clearable @change="searchList"
                         size="small"></el-input>
@@ -63,15 +63,9 @@
 
         <!--工具条-->
         <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, jumper"
-                :total="total"
-                style="float:right;"
-            ></el-pagination>
+            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+                :page-sizes="[10, 20, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next, jumper"
+                :total="total" style="float:right;"></el-pagination>
         </el-col>
 
         <!-- 分类管理 -->
@@ -86,14 +80,15 @@
                 </el-table-column>
                 <el-table-column label="是否上架" width="80">
                     <template slot-scope="scope">
-                        <span style="color: #5cb87a;" v-if="scope.row.status == 1">上架</span> 
-                        <span style="color: #909399;" v-else>下架</span> 
+                        <span style="color: #5cb87a;" v-if="scope.row.status == 1">上架</span>
+                        <span style="color: #909399;" v-else>下架</span>
                     </template>
                 </el-table-column>
                 <el-table-column label="操作" width="180">
                     <template slot-scope="scope">
                         <el-button size="mini" type="primary" @click="addEditCategory(scope.row)">编辑</el-button>
-                        <el-button size="mini" type="danger" @click="deleteCategory(scope.$index, scope.row)">删除</el-button>
+                        <el-button size="mini" type="danger"
+                            @click="deleteCategory(scope.$index, scope.row)">删除</el-button>
                     </template>
                 </el-table-column>
             </el-table>
@@ -107,21 +102,22 @@
             <div class="newCategoryDialog">
                 <div class="newCategoryDialog-item">
                     <div class="newCategoryDialog-item-label">分类名称:</div>
-                    <el-input v-model.trim="newCategoryDialogForm.label" placeholder="请输入内容" clearable size="small" style="flex: 1"></el-input>
+                    <el-input v-model.trim="newCategoryDialogForm.label" placeholder="请输入内容" clearable size="small"
+                        style="flex: 1"></el-input>
                 </div>
                 <div class="newCategoryDialog-item">
                     <div class="newCategoryDialog-item-label">分类封面:</div>
-                    <el-upload
-                        class="cover-uploader"
-                        :show-file-list="false"
-                        auto-upload
-                        accept="image/*"
+                    <el-upload class="cover-uploader" :show-file-list="false" auto-upload accept="image/*"
                         :http-request="categoryCoverUpload">
-                        <img v-if="newCategoryDialogForm.coverImage" :src="newCategoryDialogForm.coverImage" class="cover-preview">
+                        <img v-if="newCategoryDialogForm.coverImage" :src="newCategoryDialogForm.coverImage"
+                            class="cover-preview">
                         <i v-else class="el-icon-plus cover-uploader-icon"></i>
                         <div v-if="newCategoryDialogForm.coverImage" class="cover-mask">
-                        <el-link icon="el-icon-view" type="success" @click.stop="previewImage(newCategoryDialogForm.coverImage)" :underline="false">查看</el-link>
-                        <el-link icon="el-icon-edit" type="success" :underline="false" style="margin-left: 10px;">修改</el-link>
+                            <el-link icon="el-icon-view" type="success"
+                                @click.stop="previewImage(newCategoryDialogForm.coverImage)"
+                                :underline="false">查看</el-link>
+                            <el-link icon="el-icon-edit" type="success" :underline="false"
+                                style="margin-left: 10px;">修改</el-link>
                         </div>
                     </el-upload>
                 </div>
@@ -135,7 +131,8 @@
             </div>
             <span slot="footer" class="classificationOperation">
                 <el-button @click="newCategoryDialogVisible = false">关 闭</el-button>
-                <el-button type="primary" :disabled="!newCategoryDialogForm.label" :loading="newCategoryDialogLoading" @click="saveCategory()">保存</el-button>
+                <el-button type="primary" :disabled="!newCategoryDialogForm.label" :loading="newCategoryDialogLoading"
+                    @click="saveCategory()">保存</el-button>
             </span>
         </el-dialog>
 
@@ -144,8 +141,8 @@
             <el-form :model="courseForm" :rules="courseRules" ref="courseForm" label-width="120px">
                 <el-form-item label="课程分类" prop="courseTypeId">
                     <el-select v-model="courseForm.courseTypeId" placeholder="请选择" style="width:100%">
-                        <el-option v-for="item in categoryOptions" :key="item.value" 
-                            :label="item.label" :value="item.value">
+                        <el-option v-for="item in categoryOptionsTwo" :key="item.value" :label="item.label"
+                            :value="item.value">
                         </el-option>
                     </el-select>
                 </el-form-item>
@@ -153,22 +150,20 @@
                     <el-input v-model="courseForm.courseName" placeholder="请输入课程名称"></el-input>
                 </el-form-item>
                 <el-form-item label="课程介绍" style="height: 200px;">
-                    <quill-editor style="height: 150px" ref="text" v-model="courseForm.courseDesc" class="myQuillEditor" :options="editorOption"/>
+                    <quill-editor style="height: 150px" ref="text" v-model="courseForm.courseDesc" class="myQuillEditor"
+                        :options="editorOption" />
                 </el-form-item>
                 <el-form-item label="课程价格">
-                    <el-input-number v-model="courseForm.coursePrice" :min="0" :precision="2" step-strictly :step="1" @blur="coursePriceBlur"></el-input-number>
+                    <el-input-number v-model="courseForm.coursePrice" :min="0" :precision="2" step-strictly :step="1"
+                        @blur="coursePriceBlur"></el-input-number>
                 </el-form-item>
                 <el-form-item label="课程时间(分钟)">
-                    <el-input-number v-model="courseForm.courseDuration" :min="1" step-strictly :step="1" @blur="courseDurationBlur"></el-input-number>
+                    <el-input-number v-model="courseForm.courseDuration" :min="1" step-strictly :step="1"
+                        @blur="courseDurationBlur"></el-input-number>
                 </el-form-item>
                 <el-form-item label="课程封面">
-                    <el-upload
-                        class="cover-uploader"
-                        action="#"
-                        :show-file-list="false"
-                        :on-change="handleCourseCoverChange"
-                        :auto-upload="false"
-                        :before-upload="beforeCoverUpload">
+                    <el-upload class="cover-uploader" action="#" :show-file-list="false"
+                        :on-change="handleCourseCoverChange" :auto-upload="false" :before-upload="beforeCoverUpload">
                         <img v-if="courseForm.coverImageUrl" :src="courseForm.coverImageUrl" class="cover-image" />
                         <i v-else class="el-icon-plus cover-uploader-icon"></i>
                     </el-upload>
@@ -187,14 +182,8 @@
                 <div class="title-dios">
                     <div>添加视频</div>
                     <div style="margin-right: 30px;">
-                        <el-upload
-                            ref="uploadVideoRef"
-                            action="#"
-                            :disabled="addVideoLoading"
-                            :show-file-list="false"
-                            :limit="5"
-                            multiple
-                            :http-request="uploadVideo"
+                        <el-upload ref="uploadVideoRef" action="#" :disabled="addVideoLoading" :show-file-list="false"
+                            :limit="5" multiple :http-request="uploadVideo"
                             accept="video/mp4,video/avi,video/x-msvideo">
                             <el-button size="small" type="primary" :loading="addVideoLoading">上传视频</el-button>
                         </el-upload>
@@ -205,7 +194,9 @@
                 <addVideoCom ref="addVideoComRef" v-model="displayVideoList"></addVideoCom>
             </div>
             <span slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="saveVideo()" :disabled="!displayVideoList.length || displayVideoList.some(video => video.videoError) || displayVideoList.some(video => video.videoLoading)" size="small" :loading="saveVideoLoading">保存视频</el-button>
+                <el-button type="primary" @click="saveVideo()"
+                    :disabled="!displayVideoList.length || displayVideoList.some(video => video.videoError) || displayVideoList.some(video => video.videoLoading)"
+                    size="small" :loading="saveVideoLoading">保存视频</el-button>
             </span>
         </el-dialog>
 
@@ -252,6 +243,8 @@ export default {
             // 课程分类选择
             categoryValue: '',
             categoryOptions: [],
+            categoryOptionsTwo: [],
+
             // 搜索条件
             keyword: null, // 课程名称
             instructor: null, // 讲师
@@ -282,29 +275,29 @@ export default {
             currentCategoryIndex: -1,
             coverImageUrl: '',
             coverImageFile: null,
-            
+
             // 用户信息
             user: sessionStorage.user ? JSON.parse(sessionStorage.user) : {},
             editorOption: { // 富文本框里面的默认值
                 placeholder: '请输入内容...',
                 modules: {
-                    toolbar:[
+                    toolbar: [
                         ['bold', 'italic', 'underline', 'strike'],    //加粗,斜体,下划线,删除线
                         // ['blockquote', 'code-block'],     //引用,代码块
-                
+
                         [{ 'header': 1 }, { 'header': 2 }],        // 标题,键值对的形式;1、2表示字体大小
                         // [{ 'list': 'ordered'}, { 'list': 'bullet' }],     //列表
                         // [{ 'script': 'sub'}, { 'script': 'super' }],   // 上下标
                         // [{ 'indent': '-1'}, { 'indent': '+1' }],     // 缩进
                         // [{ 'direction': 'rtl' }],             // 文本方向
-                
+
                         [{ 'size': ['small', false, 'large', 'huge'] }], // 字体大小
                         [{ 'header': [1, 2, 3, 4, 5, 6, false] }],     //几级标题
-                
+
                         [{ 'color': [] }, { 'background': [] }],     // 字体颜色,字体背景颜色
                         // [{ 'font': [] }],     //字体
                         [{ 'align': [] }],    //对齐方式
-                
+
                         ['clean'],    //清除字体样式
                         // ['image','video']    //上传图片、上传视频
                         []    //上传图片、上传视频
@@ -330,6 +323,18 @@ export default {
         }
     },
     methods: {
+        getUpList() {
+            post('/course-type/uplist', {}).then(res => {
+                if (res.code == 'ok') {
+                    this.categoryOptionsTwo = (res.data || []).map(item => ({
+                        label: item.typeName,
+                        value: item.id,
+                    }))
+                } else {
+                    this.$message.error(res.msg);
+                }
+            })
+        },
         saveCategory() {
             this.newCategoryDialogLoading = true
             const { label, value, coverImage, status } = this.newCategoryDialogForm;
@@ -339,7 +344,7 @@ export default {
                 coverImageUrl: coverImage,
                 status: status
             }).then(res => {
-                if(res.code == 'ok') {
+                if (res.code == 'ok') {
                     this.newCategoryDialogVisible = false
                     this.$message.success('保存成功!');
                     this.batchManage()
@@ -360,26 +365,26 @@ export default {
 
             const formData = new FormData();
             formData.append('multipartFile', file.file);
-            
+
             this.http.uploadFile('/common/uploadFile', formData, res => {
                 if (res.code === "ok") {
-                this.newCategoryDialogForm.coverImage = checkAndAddUpload(res.data);
-                this.$message.success('图片上传成功');
+                    this.newCategoryDialogForm.coverImage = checkAndAddUpload(res.data);
+                    this.$message.success('图片上传成功');
                 } else {
-                this.$message.error(res.msg || '上传失败');
+                    this.$message.error(res.msg || '上传失败');
                 }
             });
-        },        
+        },
         previewImage(url) {
             this.previewImages = [url];
             this.$nextTick(() => {
                 if (this.$refs.imageWrapper && this.$refs.imageWrapper.$viewer) {
-                this.$refs.imageWrapper.$viewer.show();
+                    this.$refs.imageWrapper.$viewer.show();
                 }
             });
         },
         addEditCategory(row = false) {
-            if(!row) {
+            if (!row) {
                 this.newCategoryDialogForm = {
                     label: '',
                     value: '',
@@ -396,12 +401,12 @@ export default {
             this.newCategoryDialogVisible = true
         },
         coursePriceBlur(val) {
-            if(!this.courseForm.coursePrice) {
+            if (!this.courseForm.coursePrice) {
                 this.courseForm.coursePrice = 0
             }
         },
         courseDurationBlur(val) {
-            if(!this.courseForm.courseDuration) {
+            if (!this.courseForm.courseDuration) {
                 this.courseForm.courseDuration = 1
             }
         },
@@ -418,10 +423,10 @@ export default {
                     seconds: videoPreviewTime * 60,
                     seq: index + 1
                 }
-                if(coursePreviousUrl) {
+                if (coursePreviousUrl) {
                     obj.coursePreviousUrl = this.checkAndAddUpload(coursePreviousUrl)
                 }
-                if(id) {
+                if (id) {
                     obj.id = id
                 }
                 return obj
@@ -444,11 +449,11 @@ export default {
                 });
                 this.addVideoVisable = false
             })
-            
+
         },
         uploadVideo(file) {
             this.videoList.unshift(file.file)
-            if(this.videiListTime) {
+            if (this.videiListTime) {
                 clearTimeout(this.videiListTime)
             }
             this.videiListTime = setTimeout(() => {
@@ -457,7 +462,7 @@ export default {
             // this.$refs.addVideoComRef.addNewRow()
         },
         batchUploadVideo() {
-            for(let i = 0; i < this.videoList.length; i++) {
+            for (let i = 0; i < this.videoList.length; i++) {
                 const formData = new FormData()
                 formData.append('multipartFile', this.videoList[i])
                 this.displayVideoList.unshift({
@@ -483,7 +488,7 @@ export default {
             }, 1500)
         },
         // 去除视频名称后缀
-        removeVideoSuffix(str) { 
+        removeVideoSuffix(str) {
             if (str.indexOf('.') > -1) {
                 return str.substring(0, str.lastIndexOf('.'))
             } else {
@@ -524,7 +529,7 @@ export default {
                         coverImage: item.coverImage || '',
                         status: item.status
                     }));
-                    
+
                     // 同步更新下拉选项
                     this.categoryOptions = [...this.categoryList];
                 } else {
@@ -661,7 +666,7 @@ export default {
                 this.$message.warning('请先上传封面图片!');
                 return;
             }
-            
+
             // 关闭对话框
             this.coverDialogVisible = false;
             this.$message({
@@ -675,35 +680,35 @@ export default {
             this.coverImageFile = file.raw;
             if (this.coverImageFile) {
                 this.coverImageUrl = URL.createObjectURL(this.coverImageFile);
-                
+
                 // 获取当前分类的ID
                 if (this.currentCategoryIndex >= 0) {
                     const categoryId = this.categoryList[this.currentCategoryIndex].value;
-                    
+
                     // 立即上传封面图片
                     this.listLoading = true;
-                    
+
                     // 创建FormData对象用于上传文件
                     const formData = new FormData();
                     formData.append('id', categoryId);
                     formData.append('coverImage', this.coverImageFile);
-                    
+
                     // 调用上传图片的API
                     this.http.uploadFile('/course-type/uploadCover', formData, res => {
                         this.listLoading = false;
                         if (res.code == "ok") {
                             // 上传成功后,获取返回的图片URL
                             const imageUrl = res.data && res.data.url ? res.data.url : this.coverImageUrl;
-                            
+
                             // 更新本地数据
                             this.categoryList[this.currentCategoryIndex].coverImage = imageUrl;
-                            
+
                             // 同步更新到分类选项中
                             const optionIndex = this.categoryOptions.findIndex(item => item.value === categoryId);
                             if (optionIndex !== -1) {
                                 this.categoryOptions[optionIndex].coverImage = imageUrl;
                             }
-                            
+
                             this.$message({
                                 type: 'success',
                                 message: '封面图片上传成功!'
@@ -725,8 +730,8 @@ export default {
             }
         },
 
-         // 设置分类封面
-         setCategoryCover(index, row) {
+        // 设置分类封面
+        setCategoryCover(index, row) {
             this.currentCategoryIndex = index;
             this.coverImageUrl = row.coverImage || '';
             this.coverDialogVisible = true;
@@ -736,21 +741,21 @@ export default {
         beforeCoverUpload(file) {
             const isImage = file.type.indexOf('image/') === 0;
             const isLt2M = file.size / 1024 / 1024 < 2;
-            
+
             if (!isImage) {
                 this.$message.error('上传封面图片只能是图片格式!');
             }
             if (!isLt2M) {
                 this.$message.error('上传封面图片大小不能超过 2MB!');
             }
-            
+
             return isImage && isLt2M;
         },
 
         // 添加课程
         addCourse(row) {
             this.addDialogVisible = true;
-            if(!row) {
+            if (!row) {
                 this.courseForm = {
                     courseTypeId: '',
                     courseName: '',
@@ -783,9 +788,9 @@ export default {
                 if (!valid) {
                     return false;
                 }
-                
+
                 const formData = new FormData();
-                if(this.courseForm.id) {
+                if (this.courseForm.id) {
                     formData.append('id', this.courseForm.id);
                 }
                 formData.append('courseTypeId', this.courseForm.courseTypeId);
@@ -818,19 +823,19 @@ export default {
             const formData = new FormData();
             formData.append('multipartFile', row);
             this.http.uploadFile('/common/uploadFile', formData, res => {
-              if (res.code == "ok") {
-                this.courseForm.coverImageUrl = this.checkAndAddUpload(res.data)
-              } else {
-                this.$message({
-                  message: res.msg || '图片上传失败',
-                  type: 'error'
-                });
-              }
+                if (res.code == "ok") {
+                    this.courseForm.coverImageUrl = this.checkAndAddUpload(res.data)
+                } else {
+                    this.$message({
+                        message: res.msg || '图片上传失败',
+                        type: 'error'
+                    });
+                }
             })
         },
 
         checkAndAddUpload(str) {
-            if(!str) {
+            if (!str) {
                 return '';
             }
             if (str.includes('/upload/')) {
@@ -849,7 +854,7 @@ export default {
                 });
                 return;
             }
-            
+
             // 调用后端API保存课程分类
             this.http.post('/course-type/saveOrUpdate', {
                 typeName: this.newCategory.label
@@ -858,15 +863,15 @@ export default {
                     // 生成唯一ID作为value,实际项目中应该使用后端返回的ID
                     const categoryId = res.data && res.data.id ? res.data.id : 'category_' + Date.now();
                     this.newCategory.value = categoryId;
-                    
+
                     // 添加到分类列表
-                    this.categoryList.push({...this.newCategory});
-                    this.categoryOptions.push({...this.newCategory});
-                    
+                    this.categoryList.push({ ...this.newCategory });
+                    this.categoryOptions.push({ ...this.newCategory });
+
                     // 清空输入
                     this.newCategory.label = '';
                     this.newCategory.value = '';
-                    
+
                     this.$message({
                         type: 'success',
                         message: '添加分类成功!'
@@ -884,7 +889,7 @@ export default {
                 });
             });
         },
-        
+
         // 删除分类
         deleteCategory(index, row) {
             this.$confirm('确认删除该分类?', '提示', {
@@ -899,13 +904,13 @@ export default {
                     if (res.code == "ok") {
                         // 从分类列表中删除
                         this.categoryList.splice(index, 1);
-                        
+
                         // 从下拉选项中删除
                         const optionIndex = this.categoryOptions.findIndex(item => item.value === row.value);
                         if (optionIndex !== -1) {
                             this.categoryOptions.splice(optionIndex, 1);
                         }
-                        
+
                         this.$message({
                             type: 'success',
                             message: '删除分类成功!'
@@ -966,6 +971,7 @@ export default {
 
         // 获取课程列表
         this.getList();
+        this.getUpList()
     }
 }
 </script>
@@ -979,10 +985,12 @@ export default {
     width: 100%;
     justify-content: space-between;
 }
+
 .addVideoClass {
     height: 65vh;
     overflow-y: auto;
 }
+
 .rg_span {
     display: inline-block;
 }
@@ -1229,72 +1237,76 @@ export default {
     position: relative;
     top: -8px;
 }
+
 .classificationOperation {
     display: flex;
     align-items: center;
     justify-content: space-between;
 }
+
 .newCategoryDialog {
     display: flex;
     flex-direction: column;
 }
+
 .newCategoryDialog-item {
     display: flex;
     align-items: center;
     flex-direction: row;
     margin-bottom: 20px;
 }
+
 .newCategoryDialog-item-label {
     width: 120px;
     text-align: right;
     margin-right: 20px;
 }
+
 .cover-uploader {
-  border: 1px dashed #d9d9d9;
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-  width: 200px;
-  height: 150px;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+    width: 200px;
+    height: 150px;
 }
 
 .cover-uploader:hover {
-  border-color: #409EFF;
+    border-color: #409EFF;
 }
 
 .cover-uploader:hover .cover-mask {
-  opacity: 1;
+    opacity: 1;
 }
 
 .cover-mask {
-  width: 100%;
-  height: 100%;
-  background: rgba(0, 0, 0, 0.5);
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  position: absolute;
-  top: 0;
-  left: 0;
-  opacity: 0;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, 0.5);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: absolute;
+    top: 0;
+    left: 0;
+    opacity: 0;
 }
 
 .cover-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 200px;
-  height: 150px;
-  line-height: 150px;
-  text-align: center;
+    font-size: 28px;
+    color: #8c939d;
+    width: 200px;
+    height: 150px;
+    line-height: 150px;
+    text-align: center;
 }
 
 .cover-preview {
-  width: 200px;
-  height: 150px;
-  object-fit: cover;
-  border-radius: 4px;
-  cursor: pointer;
+    width: 200px;
+    height: 150px;
+    object-fit: cover;
+    border-radius: 4px;
+    cursor: pointer;
 }
-
 </style>

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

@@ -19,10 +19,10 @@ public class ContractBonusSummaryController {
 
     /**获取奖金概要数据*/
     @PostMapping("/getBonusSummary")
-    public HttpRespMsg getBonusSummary(@RequestParam(value = "ym")String ym, HttpServletRequest request){
+    public HttpRespMsg getBonusSummary(@RequestParam(value = "ym")String ym, Boolean isNegative, String bonusType,HttpServletRequest request){
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
-            httpRespMsg = contractBonusSummaryService.getBonusSummary(ym,request);
+            httpRespMsg = contractBonusSummaryService.getBonusSummary(ym, isNegative, bonusType, request);
         } catch (Exception e) {
             e.printStackTrace();
             httpRespMsg.setError(MessageUtils.message("other.error"));

+ 4 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractBonusDetail.java

@@ -33,8 +33,8 @@ public class ContractBonusDetail extends Model<ContractBonusDetail> {
     /**
      * 主键id
      */
-    @TableId("id")
-    private Long id;
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
 
     /**
      * 公司表外键
@@ -117,8 +117,8 @@ public class ContractBonusDetail extends Model<ContractBonusDetail> {
     /**
      * 是否为冲销数据
      */
-    @TableField("is_nagative")
-    private Boolean isNagative;
+    @TableField("is_negative")
+    private Boolean isNegative;
 
 
     @Override

+ 30 - 8
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractBonusSummary.java

@@ -1,29 +1,40 @@
 package com.management.platform.entity;
 
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import java.util.Date;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Date;
-
+/**
+ * <p>
+ * 分摊奖金汇总
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-06-16
+ */
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
 public class ContractBonusSummary extends Model<ContractBonusSummary> {
+
     private static final long serialVersionUID=1L;
 
     /**
      * 主键id
      */
-    @TableId("id")
-    private Long id;
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
 
     /**
      * 公司表外键
@@ -90,6 +101,17 @@ public class ContractBonusSummary extends Model<ContractBonusSummary> {
     @TableField("is_negative")
     private Boolean isNegative;
 
+    /**
+     * 是否已核销
+     */
+    @TableField("is_write_off")
+    private Boolean isWriteOff;
+
+    @TableField(exist = false)
+    private String jobNumber;
+
+    @TableField(exist = false)
+    private String userName;
 
     @Override
     protected Serializable pkVal() {

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

@@ -75,4 +75,9 @@ public class ContractBonusSummaryVO {
      * 是否为负数
      */
     private String isNegative;
+
+    /**
+     * 是否已核销
+     */
+    private Boolean isWriteOff;
 }

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ContractBonusSummaryMapper.java

@@ -10,5 +10,5 @@ import java.util.List;
 public interface ContractBonusSummaryMapper extends BaseMapper<ContractBonusSummary> {
     void batchInsertByImportData(@Param("toAddList") List<ContractBonusSummary> toAddSummaryList);
 
-    List<ContractBonusSummaryVO> getBonusSummary(@Param("ym") String ym, @Param("companyId") Integer companyId);
+    List<ContractBonusSummaryVO> getBonusSummary(@Param("ym") String ym, @Param("companyId") Integer companyId, Boolean isNegative, String bonusType);
 }

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

@@ -7,7 +7,7 @@ import com.management.platform.util.HttpRespMsg;
 import javax.servlet.http.HttpServletRequest;
 
 public interface ContractBonusSummaryService extends IService<ContractBonusSummary> {
-    HttpRespMsg getBonusSummary(String ym, HttpServletRequest request);
+    HttpRespMsg getBonusSummary(String ym, Boolean isNegative, String bonusType, HttpServletRequest request);
 
     HttpRespMsg deleteBonusSummary(String ids, HttpServletRequest request);
 

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

@@ -99,7 +99,7 @@ public class ExcelParserService {
                     // 计算工作时长(这里简化处理,实际需要更精确的计算)
                     if (startTime != null && endTime != null) {
                         try {
-                            double workHours = calculateWorkHours(startTime, endTime);
+                            double workHours = calculateZhengBeiWorkHours(startTime, endTime);
                             attendance.setWorkHours(workHours);
                         } catch (Exception e) {
                             // 时间格式不正确时忽略
@@ -147,12 +147,12 @@ public class ExcelParserService {
     public static void main(String[] args) {
         String startTime = "08:30";
         String endTime = "18:16";
-        double workHours = calculateWorkHours(startTime, endTime);
+        double workHours = calculateZhengBeiWorkHours(startTime, endTime);
 
         System.out.println("工作时长:" + workHours + "小时");
     }
 
-    public static double calculateWorkHours(String startTime, String endTime) {
+    public static double calculateZhengBeiWorkHours(String startTime, String endTime) {
         // 简单计算工作时长(小时)
         // 实际应用中需要更精确的计算,考虑午休时间等
         String[] startParts = startTime.split(":");

+ 12 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractBonusDetailServiceImpl.java

@@ -12,6 +12,7 @@ import com.management.platform.entity.excel.ProjectContractBonusExcelHead;
 import com.management.platform.entity.vo.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.ContractBonusDetailService;
+import com.management.platform.service.ContractBonusSummaryService;
 import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
@@ -21,6 +22,7 @@ import com.management.platform.util.converter.ExcelTemplateTransUtil;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -60,6 +62,9 @@ public class ContractBonusDetailServiceImpl extends ServiceImpl<ContractBonusDet
     @Resource
     private ContractBonusSummaryMapper contractBonusSummaryMapper;
 
+    @Resource
+    private ContractBonusSummaryService contractBonusSummaryService;
+
     @Resource
     private BonusExcludeProjectMapper bonusExcludeProjectMapper;
 
@@ -77,6 +82,9 @@ public class ContractBonusDetailServiceImpl extends ServiceImpl<ContractBonusDet
         bonusTypeMap.put(7,"全年奖");
     }
 
+    @Autowired
+    private ContractBonusDetailService contractBonusDetailService;
+
     @Override
     @Transactional
     public HttpRespMsg transTemplateData(String startYM, String endYM, String bonusType
@@ -431,10 +439,10 @@ public class ContractBonusDetailServiceImpl extends ServiceImpl<ContractBonusDet
                     toAddSummaryList.add(contractBonusSummary);
                 });
                 if(CollectionUtils.isNotEmpty(toAddSummaryList)){
-                    contractBonusSummaryMapper.batchInsertByImportData(toAddSummaryList);
+                    contractBonusSummaryService.saveBatch(toAddSummaryList);
                 }
                 if(CollectionUtils.isNotEmpty(toAddBonusDetailList)){
-                    contractBonusDetailMapper.batchInsert(toAddBonusDetailList);
+                    contractBonusDetailService.saveBatch(toAddBonusDetailList);
                 }
 
             }
@@ -451,7 +459,7 @@ public class ContractBonusDetailServiceImpl extends ServiceImpl<ContractBonusDet
         if(null ==user){
             httpRespMsg.setError("登录凭证有误,请联系管理员");
         }
-        List<ProjectContractBonusExcelHead> contractProjectBonusList=contractBonusDetailMapper.getExportContractProjectBonusForSpecial(year,user.getCompanyId(),null, null);
+        List<ProjectContractBonusExcelHead> contractProjectBonusList=contractBonusDetailMapper.getExportContractProjectBonusForSpecial(year,user.getCompanyId(),isNegative, bonusType);
         httpRespMsg.setData(contractProjectBonusList);
         return httpRespMsg;
     }
@@ -522,6 +530,7 @@ public class ContractBonusDetailServiceImpl extends ServiceImpl<ContractBonusDet
                 rowData.add(detailVO.getUserName());
                 rowData.add(detailVO.getBonusType());
                 rowData.add(detailVO.getProjectName());
+                System.out.println("金额==="+detailVO.getBonusValue());
                 rowData.add(detailVO.getBonusValue().setScale(4, BigDecimal.ROUND_HALF_UP).toString());
                 rowData.add(detailVO.getYm());
                 allDatas.add(rowData);

+ 37 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractBonusSummaryServiceImpl.java

@@ -1,6 +1,7 @@
 package com.management.platform.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.entity.ContractBonusDetail;
 import com.management.platform.entity.ContractBonusSummary;
@@ -21,9 +22,8 @@ import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSummaryMapper, ContractBonusSummary> implements ContractBonusSummaryService{
@@ -37,14 +37,14 @@ public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSu
     private UserMapper userMapper;
 
     @Override
-    public HttpRespMsg getBonusSummary(String ym, HttpServletRequest request) {
+    public HttpRespMsg getBonusSummary(String ym, Boolean isNegative, String bonusType, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("TOKEN"));
         if(null ==user){
             httpRespMsg.setError("登录凭证有误,请联系管理员");
             return httpRespMsg;
         }
-        List<ContractBonusSummaryVO> resList =  contractBonusSummaryMapper.getBonusSummary(ym,user.getCompanyId());
+        List<ContractBonusSummaryVO> resList =  contractBonusSummaryMapper.getBonusSummary(ym,user.getCompanyId(), isNegative, bonusType);
         httpRespMsg.setData(resList);
         return httpRespMsg;
     }
@@ -67,6 +67,7 @@ public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSu
                         .eq(ContractBonusDetail::getBonusType,toDelSummary.getBonusType())
                         .eq(ContractBonusDetail::getYear,toDelSummary.getYear())
                         .in(ContractBonusDetail::getUserId,toDelSummary.getUserId())
+                        .eq(ContractBonusDetail::getIsNegative,toDelSummary.getIsNegative())
                 );
             }
         }
@@ -89,6 +90,7 @@ public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSu
                     .eq(ContractBonusSummary::getYear,contractBonusSummary.getYear())
                     .eq(ContractBonusSummary::getBonusType,contractBonusSummary.getBonusType())
                     .eq(ContractBonusSummary::getIsNegative,true)
+                    .eq(ContractBonusSummary::getUserId, contractBonusSummary.getUserId())
                     .eq(ContractBonusSummary::getCompanyId,contractBonusSummary.getCompanyId())
             );
             if(null != existSummary){
@@ -102,7 +104,8 @@ public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSu
                     contractBonusDetailMapper.delete(new LambdaQueryWrapper<ContractBonusDetail>().eq(ContractBonusDetail::getYear,contractBonusSummary.getYear())
                             .eq(ContractBonusDetail::getBonusType,contractBonusSummary.getBonusType())
                                     .between(ContractBonusDetail::getYm,contractBonusSummary.getStartYM(),contractBonusSummary.getEndYM())
-                                    .eq(ContractBonusDetail::getIsNagative,true)
+                                    .eq(ContractBonusDetail::getIsNegative,true)
+                            .eq(ContractBonusDetail::getUserId, contractBonusSummary.getUserId())
                             .eq(ContractBonusDetail::getCompanyId,contractBonusSummary.getCompanyId()));
                     insertContractNegativeDetail(contractBonusSummary);
                 }
@@ -115,6 +118,10 @@ public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSu
                 insertContractNegativeDetail(contractBonusSummary);
             }
         }
+        //更新核销状态
+        ContractBonusSummary updateSummary = new ContractBonusSummary();
+        updateSummary.setIsWriteOff(true);
+        contractBonusSummaryMapper.update(updateSummary,new LambdaQueryWrapper<ContractBonusSummary>().in(ContractBonusSummary::getId,idList));
         return httpRespMsg;
     }
 
@@ -125,11 +132,16 @@ public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSu
                 .eq(ContractBonusDetail::getYear,contractBonusSummary.getYear())
                 .eq(ContractBonusDetail::getBonusType,contractBonusSummary.getBonusType())
                 .between(ContractBonusDetail::getYm,contractBonusSummary.getStartYM(),contractBonusSummary.getEndYM())
-                .eq(ContractBonusDetail::getIsNagative,false)
+                .eq(ContractBonusDetail::getIsNegative,false)
+                .eq(ContractBonusDetail::getUserId, contractBonusSummary.getUserId())
                 .eq(ContractBonusDetail::getCompanyId,contractBonusSummary.getCompanyId()));
+        System.out.println("contractBonusDetailList.size()======="+contractBonusDetailList.size());
         for (ContractBonusDetail contractBonusDetail : contractBonusDetailList) {
             contractBonusDetail.setId(null);
-            contractBonusDetail.setIsNagative(true);
+            contractBonusDetail.setIsNegative(true);
+            //金额变成负数
+            contractBonusDetail.setBonusValue(contractBonusDetail.getBonusValue().multiply(new BigDecimal(-1)));
+            contractBonusDetail.setTotalBonusValue(contractBonusDetail.getTotalBonusValue().multiply(new BigDecimal(-1)));
             contractBonusDetailMapper.insert(contractBonusDetail);
         }
     }
@@ -138,9 +150,23 @@ public class ContractBonusSummaryServiceImpl extends ServiceImpl<ContractBonusSu
     public HttpRespMsg getBonusSummaryByYear(String year, String bonusType, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("TOKEN"));
-        List<ContractBonusSummary> resList =  contractBonusSummaryMapper.selectList(
-                new LambdaQueryWrapper<ContractBonusSummary>().eq(ContractBonusSummary::getYear,year).eq(ContractBonusSummary::getBonusType,bonusType)
-                        .eq(ContractBonusSummary::getCompanyId,user.getCompanyId()).eq(ContractBonusSummary::getIsNegative,false));
+        LambdaQueryWrapper<ContractBonusSummary> queryWrapper = new LambdaQueryWrapper<ContractBonusSummary>().eq(ContractBonusSummary::getYear,year)
+                .eq(ContractBonusSummary::getCompanyId,user.getCompanyId()).eq(ContractBonusSummary::getIsNegative,false).eq(ContractBonusSummary::getIsWriteOff,false);
+
+        if (StringUtils.isNotBlank(bonusType)) {
+            queryWrapper.eq(ContractBonusSummary::getBonusType,bonusType);
+        }
+        List<ContractBonusSummary> resList =  contractBonusSummaryMapper.selectList(queryWrapper);
+        //填充userName和jobNumber;
+        List<String> userIds = resList.stream().map(ContractBonusSummary::getUserId).collect(Collectors.toList());
+        if (userIds.size() > 0) {
+            List<User> users = userMapper.selectBatchIds(userIds);
+            Map<String, User> userMap = users.stream().collect(Collectors.toMap(User::getId, userItem -> userItem));
+            for (ContractBonusSummary contractBonusSummary : resList) {
+                contractBonusSummary.setUserName(userMap.get(contractBonusSummary.getUserId()).getName());
+                contractBonusSummary.setJobNumber(userMap.get(contractBonusSummary.getUserId()).getJobNumber());
+            }
+        }
         httpRespMsg.setData(resList);
         return httpRespMsg;
     }

+ 9 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java

@@ -2351,9 +2351,15 @@ public class DingDingServiceImpl implements DingDingService {
                                 long timeInSeconds = localDateTime.toEpochSecond(ZoneOffset.UTC);
                                 onDutyEarleast.setUserCheckTime(timeInSeconds*1000);
                             }
-                            long seconds = (offDutyLatest.getUserCheckTime() - onDutyEarleast.getUserCheckTime())/1000;
-                            float hours = seconds*1.0f/3600;
-                            timeItem.setWorkHours(hours);
+                            if (8138 == dingding.getCompanyId()) {
+                                //休息时间段:苏州正北-午休12:00-13:00, 晚修:17:30-18:00
+                                double workHours = ExcelParserService.calculateZhengBeiWorkHours(timeItem.getStartTime(), timeItem.getEndTime());
+                                timeItem.setWorkHours((float)workHours);
+                            } else {
+                                long seconds = (offDutyLatest.getUserCheckTime() - onDutyEarleast.getUserCheckTime())/1000;
+                                float hours = seconds*1.0f/3600;
+                                timeItem.setWorkHours(hours);
+                            }
                             //对比,看看之前是否已经存了
                             Optional<UserDingdingTime> findOld = oldList.stream().filter(old->old.getUserId().equals(timeItem.getUserId()) && old.getWorkDate().isEqual(timeItem.getWorkDate())).findFirst();
                             if (findOld.isPresent()) {

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

@@ -6543,7 +6543,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 //titles.add("审核状态");
                 titles.add(MessageUtils.message("excel.auditStatus"));
             }
-            if(timeType.getSyncCorpwxTime()==1){
+            if(timeType.getSyncCorpwxTime()==1 || timeType.getSyncDingding()==1){
                 //titles.add("考勤时长");
                 titles.add(MessageUtils.message("excel.attDuration"));
             }
@@ -6633,6 +6633,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             if(timeType.getSyncCorpwxTime()==1) {
                 userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("company_id", user.getCompanyId()).between("create_date", startDate, endDate));
             }
+            List<UserDingdingTime> userDingdingTimeList = new ArrayList<>();
+            if(timeType.getSyncDingding()==1) {
+                userDingdingTimeList = userDingdingTimeMapper.selectList(new QueryWrapper<UserDingdingTime>().eq("company_id", user.getCompanyId()).between("work_date", startDate, endDate));
+            }
             if (timeType.getMultiWorktime() == 1) {
                 java.text.DecimalFormat df = new java.text.DecimalFormat("#0.00");
                 //重新处理一下数据,把工作时间和工作事项移出来
@@ -7078,7 +7082,26 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }else {
                         item.add(cellValue);
                     }
-
+                } else if (timeType.getSyncDingding() == 1) {
+                    String cellValue = "";
+                    String uid = map.get("creatorId") + "";
+                    String reportDate = null;
+                    if (map.get("createDate") instanceof java.sql.Date) {
+                        reportDate = timeDf.format(map.get("createDate"));
+                    } else {
+                        reportDate = (String)map.get("createDate");
+                    }
+                    for (UserDingdingTime userDingdingTime : userDingdingTimeList) {
+                        if (userDingdingTime.getUserId().equals(uid) && reportDate.equals(DateTimeFormatter.ofPattern("yyyy-MM-dd").format(userDingdingTime.getWorkDate()))) {
+                            cellValue = userDingdingTime.getStartTime() + "-" + userDingdingTime.getEndTime() + "," + MessageUtils.message("entry.workingHours") + userDingdingTime.getWorkHours();
+                            break;
+                        }
+                    }
+                    if (hideTimeCount>0){
+                        item.add("*");
+                    }else {
+                        item.add(cellValue);
+                    }
                 }
                 //审核流程状态
                 if (exportType==0) {

+ 3 - 26
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ContractBonusDetailMapper.xml

@@ -18,36 +18,13 @@
         <result column="month" property="month" />
         <result column="create_by" property="createBy" />
         <result column="create_time" property="createTime" />
-        <result column="is_nagative" property="isNagative" />
+        <result column="is_negative" property="isNegative" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, user_id, contract, project_id, project_working_time, bonus_type, bonus_value, total_bonus_value, ym, year, month, create_by, create_time, is_nagative
+        id, company_id, user_id, contract, project_id, project_working_time, bonus_type, bonus_value, total_bonus_value, ym, year, month, create_by, create_time, is_negative
     </sql>
-
-    <insert id="batchInsert">
-        insert into contract_bonus_detail(company_id, user_id, contract, project_id,project_working_time, bonus_type, bonus_value
-        , total_bonus_value, ym, year, month, create_by, create_time)
-        VALUES
-        <foreach collection="toAddList" item="detail" separator=",">
-            (#{detail.companyId},#{detail.userId},#{detail.contract},#{detail.projectId},#{detail.projectWorkingTime},#{detail.bonusType}
-            ,#{detail.bonusValue},#{detail.totalBonusValue},#{detail.ym},#{detail.year},null,#{detail.createBy},now())
-        </foreach>
-
-    </insert>
-
-
-    <!--    <resultMap id="contractProjectBonus" type="com.management.platform.entity.vo.ContractProjectBonusVO">-->
-    <!--        <result property="contract" column="contract"></result>-->
-    <!--        <collection property="projectBonusList" ofType="com.management.platform.entity.vo.ProjectBonusVO">-->
-    <!--            <result property="projectId" column="projectId"></result>-->
-    <!--            <result property="projectName" column="projectName"></result>-->
-    <!--            <result property="bonus" column="bonus"></result>-->
-    <!--            <result property="bonusType" column="bonusType"></result>-->
-    <!--        </collection>-->
-    <!--    </resultMap>-->
-
     <select id="getExportContractProjectBonusForSpecial" resultType="com.management.platform.entity.excel.ProjectContractBonusExcelHead">
         select tmp1.*,p.project_name as projectName
         from
@@ -80,7 +57,7 @@
             resultType="com.management.platform.entity.vo.ContractBonusDetailVO">
         select cbd.id, cbd.company_id, cbd.user_id, cbd.contract, cbd.project_id, cbd.project_working_time, cbd.bonus_type
              , cbd.bonus_value, cbd.total_bonus_value, cbd.ym, cbd.year, cbd.month, cbd.create_by, cbd.create_time
-             ,u.name as userName,p.project_name, cbd.is_nagative
+             ,u.name as userName,p.project_name, cbd.is_negative
         from contract_bonus_detail cbd
                  left join user u on cbd.user_id = u.id
                  left join project p on cbd.project_id = p.id

+ 14 - 16
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ContractBonusSummaryMapper.xml

@@ -16,31 +16,29 @@
         <result column="create_by" property="createBy" />
         <result column="create_time" property="createTime" />
         <result column="is_negative" property="isNegative" />
+        <result column="is_write_off" property="isWriteOff" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, contract, user_id, bonus_type, total_bonus_value, year, start_ym, end_ym, create_by, create_time, is_negative
+        id, company_id, contract, user_id, bonus_type, total_bonus_value, year, start_ym, end_ym, create_by, create_time, is_negative, is_write_off
     </sql>
-    <insert id="batchInsertByImportData">
-        insert into contract_bonus_summary(company_id,  user_id,contract, bonus_type, total_bonus_value
-        , start_ym, end_ym, create_by, create_time,year) VALUES
-        <foreach collection="toAddList" item="toAddItem" separator=",">
-            (#{toAddItem.companyId},#{toAddItem.userId},#{toAddItem.contract},#{toAddItem.bonusType},#{toAddItem.totalBonusValue},
-            #{toAddItem.startYM},#{toAddItem.endYM},#{toAddItem.createBy},now(),#{toAddItem.year})
-        </foreach>
-    </insert>
-
     <select id="getBonusSummary" resultType="com.management.platform.entity.vo.ContractBonusSummaryVO">
         select cbs.id, cbs.company_id, cbs.contract, cbs.user_id, cbs.bonus_type, cbs.total_bonus_value
-             , cbs.year, cbs.start_ym, cbs.end_ym, cbs.create_by, cbs.create_time
-             , u.job_number,u.name as userName,cbs.is_negative
+        , cbs.year, cbs.start_ym, cbs.end_ym, cbs.create_by, cbs.create_time
+        , u.job_number,u.name as userName,cbs.is_negative,cbs.is_write_off
         from contract_bonus_summary cbs
-                 left join user u on cbs.user_id = u.id
+        left join user u on cbs.user_id = u.id
         where
-            cbs.year = substr(#{ym},1,4)  and cbs.company_id = #{companyId}
-          and substr(cbs.start_ym,6,7) &lt;= substr(#{ym},6,7)
-          and substr(cbs.end_ym,6,7) &gt;= substr(#{ym},6,7)
+        cbs.year = substr(#{ym},1,4)  and cbs.company_id = #{companyId}
+        and substr(cbs.start_ym,6,7) &lt;= substr(#{ym},6,7)
+        and substr(cbs.end_ym,6,7) &gt;= substr(#{ym},6,7)
+        <if test="isNegative != null">
+            and is_negative = #{isNegative}
+        </if>
+        <if test="bonusType != null">
+            and bonus_type = #{bonusType}
+        </if>
         order by cbs.user_id
     </select>
 </mapper>

+ 4 - 4
fhKeeper/formulahousekeeper/timesheet/src/views/Login.vue

@@ -277,12 +277,12 @@
                 window.location.href = weixinUrl;
             },
             ddworkCli() {
-                var appId = "71020";//钉钉三方的SUIT ID
-                var url = "https://worktime.ttkuaiban.com/api/dingtalk/callback";//授权回调页面
+                var url = encodeURIComponent("https://worktime.ttkuaiban.com/api/dingtalk/callback");//授权回调页面
                 // var weixinUrl=`https://oapi.dingtalk.com/connect/qrconnect?appid=${appId}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=${url}`;
                 const appKey = 'suitejwoq9dw4bxv4stdb'
-                var ddUrl =`https://login.dingtalk.com/oauth2/auth?redirect_uri=${url}&response_type=code&client_id=${appKey}&scope=openid corpid &state=dddd&prompt=consent`;
-                window.location.href = ddUrl ;
+                var scope = encodeURIComponent("openid corpid");
+                var ddUrl =`https://login.dingtalk.com/oauth2/auth?redirect_uri=${url}&response_type=code&client_id=${appKey}&scope=${scope}&state=dddd&prompt=consent`;
+                window.location.href = ddUrl;
             },
             getStaffInfo() {
                 console.log('执行了没')

+ 179 - 5
fhKeeper/formulahousekeeper/timesheet/src/views/project/financeComponents/incomeDetail.vue

@@ -6,10 +6,33 @@
         <i class="fa fa-align-justify" @click.prevent="switchMenu" style="cursor: pointer" />
         <div class="m-lr">选择月份</div>
         <el-date-picker size="small" v-model="selectMonth" :editable="false" format="yyyy-MM" value-format="yyyy-MM"
-          @change="retrieveDataAgain" :clearable="false" type="month" placeholder="选择月份" />
+          @change="retrieveDataAgain" :clearable="false" type="month" placeholder="选择月份" style="width: 160px;" />
+
+        <!-- 奖金类型 -->
+        <div class="item-center" style="margin-left: 15px">
+          <div style="margin-right: 10px">选择奖金类型</div>
+          <el-select v-model="bonusType" placeholder="请选择" clearable @change="retrieveDataAgain" size="small" style="width: 140px;">
+            <el-option v-for="(item, index) in bonusTypeList" :key="index" :label="item.label"
+              :value="item.value">
+            </el-option>
+          </el-select>
+        </div>
+
+        <!-- 数据类型 -->
+        <div class="item-center" style="margin-left: 15px">
+          <div style="margin-right: 10px">选择数据类型</div>
+          <el-select v-model="isNegative" placeholder="请选择" clearable @change="retrieveDataAgain" size="small" style="width: 140px;">
+            <el-option v-for="(item, index) in isNegativeList" :key="index" :label="item.label"
+              :value="item.value">
+            </el-option>
+          </el-select>
+        </div>
       </div>
       <div class="item-center">
-        <el-link type="primary" :underline="false" @click="notParticipatingInSharedProjects()">
+        <el-link type="primary" :underline="false" @click="oneClickVerification()">
+          一键核销
+        </el-link>
+        <el-link type="primary" :underline="false" class="ml" @click="notParticipatingInSharedProjects()">
           不参与分摊项目设置
         </el-link>
         <el-link type="primary" :underline="false" class="ml" @click="bonusDataExport">数据导出</el-link>
@@ -108,12 +131,57 @@
             <el-date-picker v-model="selectYear" type="year" value-format="yyyy" :size="'small'">
             </el-date-picker>
           </el-form-item>
+          <el-form-item label="选择奖金类型">
+            <el-select v-model="exportBonusType" placeholder="请选择" clearable size="small">
+              <el-option v-for="(item, index) in bonusTypeList" :key="index" :label="item.label"
+                :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="选择数据类型">
+            <el-select v-model="exportIsNegative" placeholder="请选择" clearable size="small">
+              <el-option v-for="(item, index) in isNegativeList" :key="index" :label="item.label"
+                :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
         </el-form>
       </div>
       <span slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitExport()" :loading="dataExportLoading">导出</el-button>
       </span>
     </el-dialog>
+
+    <!-- 一键核销 -->
+    <el-dialog title="一键核销" :visible.sync="oneClickVerificationVisable" top="6.2vh" width="1000px">
+      <div>
+        <el-form ref="form" label-width="100px" style="display: flex;">
+          <el-form-item label="选择年份">
+            <el-date-picker v-model="writeOffYear" type="year" value-format="yyyy" :size="'small'" :clearable="false" @change="getWriteOffTableData">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="选择奖金类型" style="margin-left: 20px;">
+            <el-select v-model="writeOffBonusType" placeholder="请选择" clearable size="small" @change="getWriteOffTableData">
+              <el-option v-for="(item, index) in bonusTypeList" :key="index" :label="item.label"
+                :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </el-form>
+        <el-table ref="multipleTable" :data="oneClickVerificationList" border height="56vh" tooltip-effect="dark" style="width: 100%" @selection-change="writeOffSelectionChange" v-loading="oneClickVerificationTableLoading">
+          <el-table-column type="selection" width="55"></el-table-column>
+          <el-table-column prop="jobNumber" label="工号"></el-table-column>
+          <el-table-column prop="userName" label="姓名"></el-table-column>
+          <el-table-column prop="bonusType" label="奖金类型"></el-table-column>
+          <el-table-column prop="totalBonusValue" label="奖金金额(元)"></el-table-column>
+          <el-table-column prop="startYM" label="分摊月份"></el-table-column>
+        </el-table>
+      </div>
+      <span slot="footer" class="writeOffAtTheBottom">
+        <el-button type="primary" size="small" @click="writeOffSelected()" :disabled="!oneClickVerificationSelected.length">一键核销</el-button>
+        <el-button size="small" @click="oneClickVerificationVisable = false">关闭</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
 
@@ -158,6 +226,33 @@ export default {
       projectAllList: [],
       echartsData: [],
       myChart: null,
+
+      bonusTypeList: [
+        { label: '第一季度奖', value: '第一季度奖' },
+        { label: '第二季度奖', value: '第二季度奖' },
+        { label: '第三季度奖', value: '第三季度奖' },
+        { label: '第四季度奖', value: '第四季度奖' },
+        { label: '上半年奖', value: '上半年奖' },
+        { label: '下半年奖', value: '下半年奖' },
+        { label: '全年奖', value: '全年奖' },
+      ],
+      isNegativeList: [
+        { label: '正数', value: 'false' },
+        { label: '负数', value: 'true' },
+      ],
+      exportBonusType: '',
+      exportIsNegative: '',
+      bonusType: '',
+      isNegative: '',
+
+      // 一键核销
+      oneClickVerificationTableLoading: false,
+      oneClickVerificationVisable: false,
+      oneClickVerificationList: [],
+      oneClickVerificationSelected: [],
+      oneClickVerificationBtnLoading: false,
+      writeOffYear: '',
+      writeOffBonusType: ''
     };
   },
   mounted() {
@@ -166,6 +261,53 @@ export default {
     this.loadMonthData()
   },
   methods: {
+    writeOffSelected() {
+      this.$confirm('确定核销当前选中的数据?', '核销', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        const ids = this.oneClickVerificationSelected.map(item => item.id).join(',')
+        this.oneClickVerificationBtnLoading = true
+        this.postData(`/contractBonusSummary/generateNegativeContractBonus`, {
+          ids
+        }).then((res) => {
+          this.$message({
+            type: 'success',
+            message: '核销成功!'
+          });
+          this.getWriteOffTableData()
+          this.retrieveDataAgain()
+        }).finally(() => {
+          this.oneClickVerificationBtnLoading =false
+        })
+      })
+    },
+    writeOffSelectionChange(val) {
+      this.oneClickVerificationSelected = val
+    },
+    oneClickVerification() {
+      this.oneClickVerificationVisable = true
+      this.writeOffYear = this.dayjs().format('YYYY')
+      this.writeOffBonusType = ''
+      this.getWriteOffTableData()
+    },
+    getWriteOffTableData() {
+      this.oneClickVerificationTableLoading = true
+      this.oneClickVerificationSelected = []
+      let formVal = {}
+      if(this.writeOffBonusType) {
+        formVal.bonusType = this.writeOffBonusType
+      }
+      this.postData(`/contractBonusSummary/getBonusSummaryByYear`, {
+        year: this.selectMonth.split('-')[0],
+        ...formVal
+      }).then((res) => {
+        this.oneClickVerificationList = res.data || []
+      }).finally(() => {
+        this.oneClickVerificationTableLoading =false
+      })
+    },
     loadMonthData() {
       this.getSelectProjectBonusAllocation()
       this.retrieveDataAgain()
@@ -233,8 +375,16 @@ export default {
       this.getTableList()
     },
     submitExport() {
+      let formVal = {}
+      if(this.exportBonusType) {
+        formVal.bonusType = this.exportBonusType
+      }
+      if(this.exportIsNegative) {
+        formVal.isNegative = this.exportIsNegative
+      }
       this.http.downloadFile('/contractBonusDetail/exportContractBonus', {
-        year: this.selectYear
+        year: this.selectYear,
+        ...formVal
       }, '奖金项目分摊.xlsx', err => {
         this.$message({
           message: err,
@@ -244,6 +394,8 @@ export default {
     },
     bonusDataExport() {
       this.selectYear = dayjs().format('YYYY')
+      this.exportBonusType = ''
+      this.exportIsNegative = ''
       this.dataExportVisable = true
     },
     batchDeletion() {
@@ -320,7 +472,14 @@ export default {
     },
     getTableList() {
       this.tableListLoading = true
-      this.postData(`/contractBonusSummary/getBonusSummary`, { ym: this.selectMonth }).then((res) => {
+      let formVal = {}
+      if(this.bonusType) {
+        formVal.bonusType = this.bonusType
+      }
+      if(this.isNegative) {
+        formVal.isNegative = this.isNegative
+      }
+      this.postData(`/contractBonusSummary/getBonusSummary`, { ym: this.selectMonth, ...formVal }).then((res) => {
         this.tableList = res.data || []
       }).finally(() => {
         this.tableListLoading = false
@@ -328,7 +487,17 @@ export default {
     },
     getEchartsData() {
       this.echartsLoading = true
-      this.postData(`/contractBonusDetail/getContractBonus`, { year: dayjs(this.selectMonth).format('YYYY') }).then(res => {
+      let formVal = {}
+      if(this.bonusType) {
+        formVal.bonusType = this.bonusType
+      }
+      if(this.isNegative) {
+        formVal.isNegative = this.isNegative
+      }
+      this.postData(`/contractBonusDetail/getContractBonus`, { 
+        year: dayjs(this.selectMonth).format('YYYY'),
+        ...formVal
+      }).then(res => {
         // this.echartsData = res.data || []
         this.instantiateChart(res.data || [])
       }).finally(() => {
@@ -472,4 +641,9 @@ export default {
 .h-full {
   height: 100%;
 }
+.writeOffAtTheBottom {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
 </style>

+ 29 - 8
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -412,7 +412,7 @@
                         <div v-if="isBatch!=0" style="display: inline-block;margin-left:10px">{{jsDay}} {{$t('time.day')}}</div>
                         <span v-if="reportTimeType.type == 3 && user.company.companyName != mingyiName" style="margin-left:10px;">{{isBatch==0? $t('other.total'):$t('weekDay.daily')}}{{$t('time.duration')}}:</span>
                         <el-input-number :disabled="(!canEdit || user.timeType.lockWorktime) && !isWeekend" v-if="reportTimeType.type == 3&& user.company.companyName != mingyiName" style="margin-left:5px;" @change="changeAllTime"
-                            v-model="reportTimeType.allday" :precision="1" :step="0.5" :max="12" :min="0.5"></el-input-number>
+                            v-model="workForm.totalDuration" :precision="1" :step="0.5" :max="yonghuUser.maxReportTime || 12" :min="0.5"></el-input-number>
                         <span v-if="reportTimeType.type == 3 && user.company.companyName != mingyiName">{{$t('time.hour')}}</span>
                         <!-- <span v-if="isBatch && user.company.companyName != mingyiName">, {{$t('other.fillInTheTotal')}} {{jsTime.toFixed(1)}} {{$t('time.hour')}}</span> -->
                         <span v-if="isBatch && user.company.companyName != mingyiName">, {{$t('other.fillInTheTotal')}} <el-input v-model="jsTime" @change="onBatchTimeChange" style="width:80px;"/> {{$t('time.hour')}}</span>
@@ -729,7 +729,7 @@
                         <el-form-item v-if="reportTimeType.type == 3" :label="$t('lable.percentageOfTime')" :prop="'domains.' + index + '.'+timeFields[reportTimeType.type]"
                             :rules="{ required: true, message: $t('defaultText.pleaseSetTheTimeRatio'), trigger: 'blur' }">
                             <div style="width:400px;">
-                                <el-col span="14"><el-slider :disabled="!domain.canEdit" v-model="domain.progress" :min="0" :show-tooltip="false" :step="5" style="width:280px;" @input="domain.workingTime = (reportTimeType.allday*domain.progress/100).toFixed(1)" @change="seleChn(0)" show-input="true" input-size="small"></el-slider></el-col>
+                                <el-col span="14"><el-slider :disabled="!domain.canEdit" v-model="domain.progress" :min="0" :show-tooltip="false" :step="5" style="width:280px;" @input="domain.workingTime = (workForm.totalDuration*domain.progress/100).toFixed(1)" @change="seleChn(0)" show-input="true" input-size="small"></el-slider></el-col>
                                 <el-col :span="isBatch?6:10"><span style="margin-left:10px;float:right;"><span style="margin-right:10px;">{{domain.progress}}%</span><span v-if="isBatch == 0">{{domain.workingTime}}{{$t('time.hour')}}</span></span></el-col>
                             </div>
                             <div class="overtime" v-if="user.timeType.fillOvertime || isWeekend"><el-checkbox :disabled="!domain.canEdit" v-model="domain.isOvertime">{{$t('other.WorkOvertime')}}</el-checkbox>
@@ -969,7 +969,12 @@
 
                     </div>
                     <span id="workFormsItemBottom"></span>
-                    <el-link v-if="showAddMore" type="primary" :underline="false" @click="addDomain(reportTimeType.type)" style="margin-left:40px;">{{$t('other.addMore')}}</el-link>
+                    <template v-if="yonghuUser.type != 3">
+                        <el-link v-if="showAddMore" type="primary" :underline="false" @click="addDomain(reportTimeType.type)" style="margin-left:40px;">{{$t('other.addMore')}}</el-link>
+                    </template>
+                    <template v-if="yonghuUser.type == 3">
+                        <el-link v-if="canEdit" type="primary" :underline="false" @click="addDomain(reportTimeType.type)" style="margin-left:40px;">{{$t('other.addMore')}}</el-link>
+                    </template>
                 </el-form>
             </div>
             <span slot="footer" class="dialog-footer">
@@ -4988,8 +4993,11 @@
             },
             changeAllTime() {
                 //总时长发生改变,自动按比例计算
+                if(!this.workForm.totalDuration) {
+                    this.workForm.totalDuration = 0.5
+                }
                 this.workForm.domains.forEach(d=>{
-                    d.workingTime = (d.progress*this.reportTimeType.allday/100).toFixed(1);
+                    d.workingTime = (d.progress*this.workForm.totalDuration/100).toFixed(1);
                 });
                 //计算jsTime
                 if (this.workForm.createDate) {
@@ -4999,7 +5007,7 @@
                     if (days < 0) {
                         days = 0;
                     }
-                    this.jsTime = this.reportTimeType.allday * days;
+                    this.jsTime = this.workForm.totalDuration * days;
                 }
             },
 
@@ -6665,8 +6673,7 @@
                                     this.getInfoByProjectId(copyData, i, false)
                                 }
                             }
-                            this.reportCanDelete = candelete
-                            this.workForm = {
+                            let copyWorkForm = {
                                 createDate: this.workForm.createDate,
                                 domains: arr,
                                 userNames:null,
@@ -6674,8 +6681,18 @@
                                 time: list.time,
                                 showRefresh: list.showRefresh
                             }
-                        } else {
+                            if(res.data.timeType.type == 3) {
+                                const reportCalculationReportList = res.data.report || []
+                                copyWorkForm.totalDuration = reportCalculationReportList.reduce((accumulator, current) => {
+                                    const workingTime = current.workingTime || 0;
+                                    return accumulator + workingTime;
+                                }, 0);
+                            }
                             this.workForm = {
+                                ...copyWorkForm
+                            }
+                        } else {
+                            let copyWorkForm = {
                                 createDate: this.workForm.createDate,
                                 domains: [{
                                     id: null,
@@ -6698,6 +6715,10 @@
                                 time: this.report.time,
                                 showRefresh: list.showRefresh
                             }
+                            if(res.data.timeType.type == 3) {
+                                copyWorkForm.totalDuration = res.data.timeType.allday
+                            }
+                            this.workForm = copyWorkForm
                             // businessTrips 有数据的情况下
                             const businessTrips = res.data.businessTrips || []
                             this.businessTripsArray = res.data.businessTrips || []

+ 33 - 8
fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue

@@ -81,7 +81,7 @@
             <van-cell title="总时长(h)" v-if="reportTimeType.type == 3">
                 <template>
                     <van-stepper :disabled="(!canEdit || user.timeType.lockWorktime == 1) && !isWeekend"
-                        v-model="reportTimeType.allday" @change="changeAllTime" min="0.5" max="12" step="0.5"
+                        v-model="form.totalDuration" @change="changeAllTime" min="0.5" :max="reportSettingsRow.maxReportTime || 12" step="0.5"
                         :decimal-length="1" />
                 </template>
             </van-cell>
@@ -524,11 +524,21 @@
 
             </div>
             <div style="text-align:center;" v-if="showAddMore">
-                <van-tag size="large"
+                <template v-if="reportSettingsRow.type != 3">
+                    <van-tag size="large"
                     style="text-align:center;margin:10px;padding:12px;margin-bottom:120px;border: 1px solid #20a0ff;"
-                    @click="addNewPro" icon="plus" color="#ffffff"><span
-                        style="color:#999;text-align:center;padding: 0 50px;"> + 新增{{ user.companyId == 781 ? '任务' : '项目' }}
-                    </span></van-tag>
+                    @click="addNewPro" icon="plus" color="#ffffff">
+                        <span style="color:#999;text-align:center;padding: 0 50px;"> + 新增{{ user.companyId == 781 ? '任务' : '项目' }}</span>
+                    </van-tag>
+                </template>
+                <template v-if="reportSettingsRow.type == 3 && canEdit">
+                    <van-tag size="large"
+                    style="text-align:center;margin:10px;padding:12px;margin-bottom:120px;border: 1px solid #20a0ff;"
+                    @click="addNewPro" icon="plus" color="#ffffff">
+                        <span style="color:#999;text-align:center;padding: 0 50px;"> + 新增{{ user.companyId == 781 ? '任务' : '项目' }}</span>
+                    </van-tag>
+                </template>
+                
                 <!-- <van-button id="btn-start-recording" @click="startRecording">录音</van-button>
                 <van-button id="btn-stop-recording" @click="stopRecording">停止</van-button>
                 <van-button id="btn-play-recording" @click="getRecording">获取文件</van-button> -->
@@ -690,6 +700,7 @@ export default {
             timeType: [],
             form: {
                 createDate: this.format(new Date(new Date()), "yyyy-MM-dd"),
+                totalDuration: 8,
                 domains: [{
                     id: null,
                     projectId: "",
@@ -752,7 +763,9 @@ export default {
             showAddMore: false,
             businessTripsArray: [],
             doYouWantToDisplayTheWorkOrder: true,
-            hideWorkingHours: false
+            hideWorkingHours: false,
+
+            reportSettingsRow: {},
         };
     },
 
@@ -1415,7 +1428,8 @@ export default {
         changeAllTime() {
             //总时长发生改变,自动按比例计算
             this.form.domains.forEach(d => {
-                d.workingTime = (d.progress * this.reportTimeType.allday / 100).toFixed(1);
+                // d.workingTime = (d.progress * this.reportTimeType.allday / 100).toFixed(1);
+                d.workingTime = (d.progress * this.form.totalDuration / 100).toFixed(1);
             });
         },
         cancel() {
@@ -1829,6 +1843,7 @@ export default {
                         this.report = res.data;
                         this.businessTripsArray = res.data.businessTrips || []
                         var t = res.data.timeType;
+                        this.reportSettingsRow = res.data.timeType
                         var timeType = [];
                         //转化时间格式
                         if (t.allday != null) {
@@ -1993,6 +2008,13 @@ export default {
                                     const { projectCode } = this.proads.find(item => item.id == list[i].projectId)
                                     this.getInfoByProjectId(projectCode, i, false)
                                 }
+                                if(res.data.timeType.type == 3) {
+                                    const reportCalculationReportList = res.data.report || []
+                                    this.form.totalDuration = reportCalculationReportList.reduce((accumulator, current) => {
+                                        const workingTime = current.workingTime || 0;
+                                        return accumulator + workingTime;
+                                    }, 0);
+                                }
                             }
                             this.form.domains = array;
                             this.setTotalReportHours()
@@ -2001,6 +2023,9 @@ export default {
                             this.canCancel = false;
                             this.canEdit = true;
                             var shuzhi = this.user.timeType.allday + ''
+                            if(res.data.timeType.type == 3) {
+                                this.form.totalDuration = this.user.timeType.allday
+                            }
                             //没有填报的可以点击提交
                             this.form.domains = [{
                                 id: null,
@@ -2825,7 +2850,7 @@ export default {
                         if(!customDegreeMultiple) { // 单选
                             formData.append("degreeId", this.form.domains[i].degreeId);
                         } else {
-                            let newDegreeId = this.form.domains[i].degreeId.split(',')
+                            let newDegreeId = Array.isArray(this.form.domains[i].degreeId) ? this.form.domains[i].degreeId : this.form.domains[i].degreeId.split(',')
                             formData.append("multiDegrId", JSON.stringify(newDegreeId).replace(/,/g, '@'))
                         }
                     } else {