Bladeren bron

Merge remote-tracking branch 'origin/master'

yusm 1 maand geleden
bovenliggende
commit
3f17ec87c1

+ 79 - 0
fhKeeper/formulahousekeeper/timesheet_mld/src/components/taskComponent.js

@@ -0,0 +1,79 @@
+import dayjs from 'dayjs';
+import minMax from 'dayjs/plugin/minMax';
+dayjs.extend(minMax);
+/**
+ * 每莱得加班工时和正常工时计算
+ * @param {string} startDateTimeStr YYYY-MM-DD HH:mm:ss
+ * @param {string} endDateTimeStr YYYY-MM-DD HH:mm:ss
+ * @param {Array} restPeriods [{ start: HH:mm:ss, end: HH:mm:ss }]
+ * @returns 
+ */
+export function calculateWorkHours(startDateTimeStr, endDateTimeStr, restPeriods = []) {
+  const start = dayjs(startDateTimeStr);
+  const end = dayjs(endDateTimeStr);
+
+  if (!start.isValid() || !end.isValid() || end.isBefore(start)) return { workHours: 0, overtimeHours: 0 };
+
+  // 全部工作时长(秒)
+  let totalSeconds = end.diff(start, 'second');
+
+  // 计算休息时间重叠(秒)
+  let restSeconds = 0;
+  restPeriods.forEach(period => {
+    const restStart = dayjs(`${start.format('YYYY-MM-DD')} ${period.start}`);
+    const restEnd = dayjs(`${start.format('YYYY-MM-DD')} ${period.end}`);
+    const overlapStart = dayjs.max(start, restStart);
+    const overlapEnd = dayjs.min(end, restEnd);
+    if (overlapEnd.isAfter(overlapStart)) {
+      restSeconds += overlapEnd.diff(overlapStart, 'second');
+    }
+  });
+
+  const netSeconds = totalSeconds - restSeconds;
+  const workHours = +(netSeconds / 3600).toFixed(1);
+
+  // 计算正常工作时段重叠(扣除休息时间)
+  const normalStart = dayjs(`${start.format('YYYY-MM-DD')} 09:00:00`);
+  const normalEnd = dayjs(`${start.format('YYYY-MM-DD')} 17:30:00`);
+  let normalSeconds = 0;
+
+  const overlapStart = dayjs.max(start, normalStart);
+  const overlapEnd = dayjs.min(end, normalEnd);
+
+  if (overlapEnd.isAfter(overlapStart)) {
+    let normalRest = 0;
+    restPeriods.forEach(period => {
+      const restStart = dayjs(`${start.format('YYYY-MM-DD')} ${period.start}`);
+      const restEnd = dayjs(`${start.format('YYYY-MM-DD')} ${period.end}`);
+      const restOverlapStart = dayjs.max(overlapStart, restStart);
+      const restOverlapEnd = dayjs.min(overlapEnd, restEnd);
+      if (restOverlapEnd.isAfter(restOverlapStart)) {
+        normalRest += restOverlapEnd.diff(restOverlapStart, 'second');
+      }
+    });
+    normalSeconds = overlapEnd.diff(overlapStart, 'second') - normalRest;
+  }
+
+  const normalHours = +(normalSeconds / 3600).toFixed(1);
+  const overtimeHours = +(workHours - normalHours).toFixed(1);
+
+  const workTimes = workHours - (overtimeHours > 0 ? overtimeHours : 0)
+
+  return {
+    totalHours: workHours,
+    workHours: workTimes,
+    overtimeHours: overtimeHours > 0 ? overtimeHours : 0
+  };
+}
+
+/**
+ * 获取唯一标识
+ * @returns string
+ */
+export function generateUUID() {
+  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+      var r = Math.random() * 16 | 0,
+          v = c === 'x' ? r : (r & 0x3 | 0x8);
+      return v.toString(16);
+  });
+}

File diff suppressed because it is too large
+ 415 - 31
fhKeeper/formulahousekeeper/timesheet_mld/src/components/taskComponent.vue


+ 72 - 24
fhKeeper/formulahousekeeper/timesheet_mld/src/views/project/project_gantt.vue

@@ -190,6 +190,12 @@
           <el-link type="primary" :underline="false" @click="exportProjectData" download="资源需求导出.xlsx">{{ $t('dao-chu-xu-qiu') }}</el-link>
         </div>
       </template>
+
+      <template v-if="radio1 == $t('an-ren-yuan-cha-kan')">
+        <div class="eachLayout">
+          <el-link type="primary" :underline="false" @click="exportPersonnelData">导出数据</el-link>
+        </div>
+      </template>
     </div>
 
     <div class="ganttChartLayout" v-if="isDataLoaded && user.userNameNeedTranslate != 1">
@@ -520,32 +526,74 @@ export default {
       },
       // 资源需求导出
       exportProjectData() {
-        let parameter = {}
-        if(this.valuex){
-          parameter.projectId = this.valuex
+          let parameter = {}
+          if(this.valuex){
+            parameter.projectId = this.valuex
+          }
+          if(this.valuex2){
+            parameter.groupName = this.valuex2
+          }
+          this.http.post('/project-requirement/exportData',parameter,
+          res => {
+              if (res.code == "ok") {
+                  let filePath = res.data;
+                  const a = document.createElement('a'); // 创建a标签
+                  a.setAttribute('download', this.$t('zi-yuan-xu-qiu-dao-chu')+'.xlsx');// download属性
+                  a.setAttribute('href', filePath);// href链接
+                  a.click(); //自执行点击事件
+                  a.remove();
+              } 
+          },
+          error => {
+              this.$message({
+                  message: error,
+                  type: "error"
+              });
+              }
+          );
+      },
+      // 人员数据导出
+      exportPersonnelData() {
+        let getlistcs = {type : this.reqpar1 , startDate : this.reqpar2[0] , endDate : this.reqpar2[1]}
+        if(this.reqpar1) {
+          if(this.valuex != ''){
+            getlistcs.projectId = this.valuex
+          }
+          if(this.valuex2 != ''){
+            getlistcs.groupName = this.valuex2
+          }
+          getlistcs.taskType = this.taskType
+          
+        }else {
+          if(this.valuex != ''){
+            getlistcs.userId = this.valuex
+          }
         }
-        if(this.valuex2){
-          parameter.groupName = this.valuex2
+        if(this.radio1 == this.$t('an-ren-yuan-cha-kan')) {
+          if(this.departmentValue.length > 0) {
+            getlistcs.deptId = this.departmentValue[this.departmentValue.length - 1]
+          }
         }
-                this.http.post('/project-requirement/exportData',parameter,
-                res => {
-                    if (res.code == "ok") {
-                        let filePath = res.data;
-                        const a = document.createElement('a'); // 创建a标签
-                        a.setAttribute('download', this.$t('zi-yuan-xu-qiu-dao-chu')+'.xlsx');// download属性
-                        a.setAttribute('href', filePath);// href链接
-                        a.click(); //自执行点击事件
-                        a.remove();
-                    } 
-                },
-                error => {
-                    this.$message({
-                        message: error,
-                        type: "error"
-                    });
-                    }
-                );
-            },
+        var urls = '/project/exportGanttData';
+        this.http.post(urls, getlistcs,
+          res => {
+              if (res.code == "ok") {
+                  let filePath = res.data;
+                  const a = document.createElement('a'); // 创建a标签
+                  a.setAttribute('download', `${this.reqpar2[0]}-${this.reqpar2[1]}工作计划导出`+'.xlsx');// download属性
+                  a.setAttribute('href', filePath);// href链接
+                  a.click(); //自执行点击事件
+                  a.remove();
+              } 
+          },
+          error => {
+              this.$message({
+                  message: error,
+                  type: "error"
+              });
+              }
+          );
+      },
       // 资源需求导入
       importProject(item) {
                 //首先判断文件类型