yusm 1 週間 前
コミット
d11e2dfe17

+ 8 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/DepartmentController.java

@@ -55,6 +55,14 @@ public class DepartmentController {
         return departmentService.getDepartmentList(request);
     }
 
+    /**
+     *
+     */
+    @RequestMapping("/userlist")
+    public HttpRespMsg getDepartmentUserList(HttpServletRequest request) {
+        return departmentService.getDepartmentUserList(request);
+    }
+
     /**
      * 对部门进行排序
      * @param request

+ 1 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/DepartmentService.java

@@ -27,6 +27,7 @@ public interface DepartmentService extends IService<Department> {
     HttpRespMsg getNormalDepartmentList(HttpServletRequest request);
 
     HttpRespMsg getDepartmentList(HttpServletRequest request);
+    HttpRespMsg getDepartmentUserList(HttpServletRequest request);
 
     HttpRespMsg getDepartmentListById(User user);
 

+ 100 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java

@@ -397,6 +397,95 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
         return httpRespMsg;
     }
 
+    // 获取部门列表
+    @Override
+    public HttpRespMsg getDepartmentUserList(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        try {
+            //筛选公司下所有的部门
+            Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
+            List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>()
+                    .eq("company_id", companyId));
+            List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("company_id", companyId));
+            List<DepartmentQualityManager> departmentQualityManagerList = departmentQualityManagerMapper.selectList(new QueryWrapper<DepartmentQualityManager>().eq("company_id", companyId));
+
+            // 获取公司所有活跃用户
+            List<User> userList = userMapper.selectList(new QueryWrapper<User>()
+                    .eq("company_id", companyId)
+                    .eq("is_active", 1));
+
+            //结果列表
+            List<DepartmentVO> list = new ArrayList<>();
+            //获取全部的顶层部门
+            List<Department> rootDepartments = departmentList.stream().filter(dept -> dept.getSuperiorId() == null).collect(Collectors.toList());
+            rootDepartments.forEach(root->{
+                DepartmentVO rootDeptVO = formatDepartmentToVO(root, departmentOtherManagerList,departmentQualityManagerList);
+                list.add(rootDeptVO);
+                fillSubDepartmentListWithUsers(departmentList, rootDeptVO, departmentOtherManagerList,departmentQualityManagerList, userList);
+            });
+            //递归排序
+            sortResultDeptList(list);
+            //返回数据
+            httpRespMsg.data = list;
+        } catch (NullPointerException e) {
+            //httpRespMsg.setError("验证失败");
+            httpRespMsg.setError(MessageUtils.message("Company.validationError"));
+            return httpRespMsg;
+        }
+        return httpRespMsg;
+    }
+
+    private void fillSubDepartmentListWithUsers(List<Department> allDepts, DepartmentVO parentDept,
+                                          List<DepartmentOtherManager> otherManagerList,
+                                          List<DepartmentQualityManager> qualityManagerList,
+                                          List<User> allUsers) {
+    Integer id = parentDept.getId();
+    List<Department> collect = allDepts.stream()
+            .filter(all -> all.getSuperiorId() != null && all.getSuperiorId().intValue() == id)
+            .collect(Collectors.toList());
+
+    List<DepartmentVO> subResult = new ArrayList<>();
+    if (collect.size() > 0) {
+        collect.forEach(c->{
+            DepartmentVO vo = formatDepartmentToVO(c, otherManagerList, qualityManagerList);
+            // 添加当前部门的用户
+            addUserListToDepartment(vo, allUsers);
+            subResult.add(vo);
+            //继续添加当前部门的子部门
+            fillSubDepartmentListWithUsers(allDepts, vo, otherManagerList, qualityManagerList, allUsers);
+        });
+    }
+
+    // 设置子部门列表
+    if (subResult.size() > 0) {
+        parentDept.setChildren(subResult);
+    }
+
+    // 为当前部门添加用户列表
+    addUserListToDepartment(parentDept, allUsers);
+}
+
+private void addUserListToDepartment(DepartmentVO departmentVO, List<User> allUsers) {
+    List<HashMap> userMapList = new ArrayList<>();
+    // 筛选出属于当前部门的用户
+    List<User> deptUsers = allUsers.stream()
+            .filter(user -> user.getDepartmentId() != null &&
+                           user.getDepartmentId().equals(departmentVO.getId()))
+            .collect(Collectors.toList());
+
+    // 将用户转换为前端需要的格式
+    for (User user : deptUsers) {
+        HashMap<String, Object> userMap = new HashMap<>();
+        userMap.put("id", user.getId());
+        userMap.put("name", user.getName());
+        userMap.put("label", user.getName()); // 用于显示的标签
+        userMap.put("value", user.getId());   // 用于值的标识
+        userMapList.add(userMap);
+    }
+
+    departmentVO.setUserList(userMapList);
+}
+
     //获取某个人所在的部门列表
     @Override
     public HttpRespMsg getDepartmentListById(User user) {
@@ -450,7 +539,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
         List<String> collect = departmentOtherManagerList.stream().filter(dm -> dm.getDepartmentId().equals(department.getDepartmentId())).map(vo -> vo.getOtherManagerId()).collect(Collectors.toList());
         List<String> collect1 = departmentQualityManagerList.stream().filter(dm -> dm.getDepartmentId().equals(department.getDepartmentId())).map(vo -> vo.getQualityId()).collect(Collectors.toList());
         //这俩东西并没有继承关系
-        return new DepartmentVO()
+         DepartmentVO vo = new DepartmentVO()
                 .setId(department.getDepartmentId())
                 .setManagerId(department.getManagerId())
                 .setLabel(department.getDepartmentName())
@@ -460,6 +549,16 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
                 .setReportAuditUserid(department.getReportAuditUserid())
                 .setDdDeptid(department.getDdDeptid())
                 .setSeq(department.getSeq());
+
+    // 确保初始化children和userList
+    if (vo.getChildren() == null) {
+        vo.setChildren(new ArrayList<>());
+    }
+    if (vo.getUserList() == null) {
+        vo.setUserList(new ArrayList<>());
+    }
+
+    return vo;
     }
 
     //获取某个项目下的统计

+ 18 - 1
fhKeeper/formulahousekeeper/timesheet-workshop/src/routes.js

@@ -47,6 +47,10 @@ import mealTypeSetting from './views/settings/mealTypeSetting.vue'
 // 出勤日历
 import attendanceCalendar from './views/attendanceCalendar/index.vue'
 
+//加班管理
+import applyOvertime from './views/workOvertime/apply.vue'
+import applyOvertimeList from './views/workOvertime/applyList.vue'
+
 Vue.use(Router)
 
 export const fixedRouter = [
@@ -82,6 +86,17 @@ export const allRouters = [
             { path: '/report', component: daily, name: '查看报工' },
         ],
     },
+    {
+        path: '/workOvertime',
+        component: Home,
+        name: '加班管理',
+        iconCls: 'iconfont firerock-iconxiangmu',
+        leaf: false,
+        children: [
+            { path: '/workOvertime/apply', component: applyOvertime, name: '员工加班申请',},
+            { path: '/workOvertime/applyList', component: applyOvertimeList, name: '加班申请列表'},
+        ],
+    },
 
     // 出勤日历
     {
@@ -176,14 +191,16 @@ export const allRouters = [
             { path: '/role', component: quanx, name: '角色权限'},
         ],
     },
+
     {
         path: '/',
         component: Home,
         name: '系统设置',
         iconCls: 'iconfont firerock-iconsetting',
         leaf: false,//只有一个节点
+        redirect: '/settings',
         children: [
-            { path: '/settings', component: settings, name: '角色权限'},
+            { path: '/settings', component: settings, name: '基础设置'},
             { path: '/factorySetting', component: factorySetting, name: '厂区设置'},
             { path: '/mealTypeSetting', component: mealTypeSetting, name: '餐别设置'},
         ],

+ 360 - 0
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/workOvertime/apply.vue

@@ -0,0 +1,360 @@
+<template>
+  <div class="overtime-apply">
+    <el-card class="form-card">
+      <div slot="header" class="clearfix">
+        <span>加班申请</span>
+      </div>
+      <el-form :model="overtimeForm" :rules="rules" ref="overtimeForm" label-width="100px">
+        <el-form-item label="加班日期" prop="overtimeDate">
+          <el-date-picker
+              v-model="overtimeForm.overtimeDate"
+              type="date"
+              placeholder="选择加班日期"
+              value-format="yyyy-MM-dd"
+              format="yyyy-MM-dd">
+          </el-date-picker>
+        </el-form-item>
+
+        <el-form-item label="加班人员" prop="employees">
+          <el-cascader
+              v-model="overtimeForm.employees"
+              :options="departmentTree"
+              :props="cascaderProps"
+              clearable
+              filterable
+              multiple
+              collapse-tags
+              placeholder="请选择部门及人员"
+              @change="handleEmployeeChange">
+          </el-cascader>
+          <el-button type="primary" size="small" @click="showEmployeeDialog" style="margin-left: 10px;">添加加班人员</el-button>
+        </el-form-item>
+
+        <el-form-item label="开始时间" prop="startTime">
+          <el-time-picker
+              v-model="overtimeForm.startTime"
+              value-format="HH:mm"
+              format="HH:mm"
+              placeholder="选择开始时间">
+          </el-time-picker>
+        </el-form-item>
+
+        <el-form-item label="结束时间" prop="endTime">
+          <el-time-picker
+              v-model="overtimeForm.endTime"
+              value-format="HH:mm"
+              format="HH:mm"
+              placeholder="选择结束时间">
+          </el-time-picker>
+        </el-form-item>
+
+        <el-form-item label="加班时长" prop="duration">
+          <el-input v-model="overtimeForm.duration" placeholder="自动计算或手动输入" readonly>
+            <template slot="append">小时</template>
+          </el-input>
+        </el-form-item>
+
+        <el-form-item label="工作内容" prop="workContent">
+          <el-input
+              type="textarea"
+              :rows="4"
+              placeholder="请输入工作内容"
+              v-model="overtimeForm.workContent">
+          </el-input>
+        </el-form-item>
+
+        <el-form-item>
+          <el-button type="primary" @click="submitForm('overtimeForm')">提交申请</el-button>
+          <el-button @click="resetForm('overtimeForm')">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 添加人员对话框 -->
+    <el-dialog title="添加加班人员" :visible.sync="employeeDialogVisible" width="600px">
+      <el-table :data="allEmployees" style="width: 100%" max-height="400">
+        <el-table-column prop="name" label="姓名" width="120"></el-table-column>
+        <el-table-column prop="department" label="部门"></el-table-column>
+        <el-table-column prop="position" label="职位"></el-table-column>
+        <el-table-column label="操作" width="100">
+          <template slot-scope="scope">
+            <el-button
+                size="mini"
+                @click="addEmployee(scope.row)"
+                :disabled="isEmployeeSelected(scope.row.id)">
+              添加
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="employeeDialogVisible = false">关闭</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>export default {
+  name: 'OvertimeApply',
+  data() {
+    return {
+      overtimeForm: {
+        overtimeDate: '',
+        employees: [],
+        startTime: '',
+        endTime: '',
+        duration: '',
+        workContent: ''
+      },
+      // 级联选择器配置
+     cascaderProps: {
+  value: 'id',
+  label: 'label',
+  children: 'children',
+  emitPath: false,
+  checkStrictly: false,
+  expandTrigger: 'hover',
+  // 添加以下配置以支持用户选择
+  leaf: (data, node) => {
+    // 可以根据数据特征判断是否为叶子节点(如用户节点)
+    return !data.children || data.children.length === 0;
+  }
+},
+      departmentTree: [],
+      rules: {
+        overtimeDate: [
+          { required: true, message: '请选择加班日期', trigger: 'change' }
+        ],
+        employees: [
+          { required: true, message: '请选择加班人员', trigger: 'change' }
+        ],
+        startTime: [
+          { required: true, message: '请选择开始时间', trigger: 'change' }
+        ],
+        endTime: [
+          { required: true, message: '请选择结束时间', trigger: 'change' }
+        ],
+        workContent: [
+          { required: true, message: '请输入工作内容', trigger: 'blur' }
+        ]
+      },
+      employeeOptions: [],
+      allEmployees: [],
+      employeeLoading: false,
+      employeeDialogVisible: false
+    }
+  },
+  mounted() {
+    // 初始化加载部门数据
+    this.searchEmployees();
+  },
+  watch: {
+    // 监听开始时间和结束时间变化,自动计算时长
+    'overtimeForm.startTime'(newVal) {
+      this.calculateDuration();
+    },
+    'overtimeForm.endTime'(newVal) {
+      this.calculateDuration();
+    }
+  },
+  methods: {
+    // 计算加班时长
+    calculateDuration() {
+      if (this.overtimeForm.startTime && this.overtimeForm.endTime) {
+        const start = this.overtimeForm.startTime.split(':');
+        const end = this.overtimeForm.endTime.split(':');
+
+        const startDate = new Date();
+        startDate.setHours(start[0], start[1], 0);
+
+        const endDate = new Date();
+        endDate.setHours(end[0], end[1], 0);
+
+        // 处理跨天情况
+        if (endDate < startDate) {
+          endDate.setDate(endDate.getDate() + 1);
+        }
+
+        const diff = (endDate - startDate) / (1000 * 60 * 60); // 转换为小时
+        this.overtimeForm.duration = diff.toFixed(2);
+      }
+    },
+    // 获取部门树形结构
+    searchEmployees() {
+      // this.employeeLoading = true;
+      // this.http.post('/department/list'),{},
+      //     res=> {
+      //       this.employeeLoading = false;
+      //       if (res.code == "ok") {
+      //         this.departmentTree = this.transformDepartmentData(res.data);
+      //       } else {
+      //         this.departmentTree = [];
+      //         this.$message({
+      //           message: res.message || '获取部门数据失败',
+      //           type: "error"
+      //         });
+      //       }
+      //     },
+      //     error => {
+      //       this.employeeLoading = false;
+      //       this.$message({
+      //         message: '请求异常',
+      //         type: "error"
+      //       });
+      //     };
+      //
+      this.listLoading = true;
+      this.http.post('/department/userlist',{
+          },
+          res => {
+            this.listLoading = false;
+            if (res.code == "ok") {
+              this.departmentTree = this.transformDepartmentData(res.data);
+            } else {
+              this.departmentTree = [];
+               this.$message({
+                 message: res.message || '获取部门数据失败',
+                 type: "error"
+               });
+            }
+          },
+          error => {
+            this.employeeLoading = false;
+            this.$message({
+              message: '请求异常',
+              type: "error"
+            });
+          }
+      )
+    },
+
+// 转换部门数据为级联选择器格式
+    transformDepartmentData(departments) {
+      return departments.map(dept => {
+        const item = {
+          id: dept.id,
+          label: dept.label,
+          value: dept.id
+        };
+
+        // 如果有子部门,递归处理
+        if (dept.children && dept.children.length > 0) {
+          item.children = this.transformDepartmentData(dept.children);
+        }
+
+        // 如果有用户列表,添加到子节点中
+        if (dept.userList && dept.userList.length > 0) {
+          if (!item.children) {
+            item.children = [];
+          }
+          dept.userList.forEach(user => {
+            item.children.push({
+              id: user.id,
+              label: user.name,
+              value: user.id
+            });
+          });
+        }
+
+        return item;
+      });
+    },
+    handleEmployeeChange(value) {
+      console.log('选择的员工:', value);
+    },
+    // 搜索员工
+    // searchEmployees(query) {
+    //   if (query !== '') {
+    //     this.employeeLoading = true;
+    //     request({
+    //       url: "/department/list",
+    //       method: "get",
+    //
+    //     })
+    //         .then(response => {
+    //           this.loading = false;
+    //           if (response.code == 'ok') {
+    //             this.$message({
+    //               message: "操作成功",
+    //               type: "success"
+    //             });
+    //             this.dialogVisible = false;
+    //             this.employeeOptions=response.data;
+    //           } else {
+    //             this.employeeOptions=[];
+    //             this.$message({
+    //               message: response.message,
+    //               type: "error"
+    //             });
+    //           }
+    //
+    //         })
+    //         .catch(error => {
+    //           this.loading = false;
+    //         });
+    //   }
+    // },
+
+    // 显示添加员工对话框
+    showEmployeeDialog() {
+      this.employeeDialogVisible = true;
+      this.allEmployees = [
+        { id: 1, name: '张三', department: '技术部', position: '前端工程师' },
+        { id: 2, name: '李四', department: '产品部', position: '产品经理' },
+        { id: 3, name: '王五', department: '设计部', position: 'UI设计师' },
+        { id: 4, name: '赵六', department: '技术部', position: '后端工程师' },
+        { id: 5, name: '钱七', department: '测试部', position: '测试工程师' }
+      ];
+    },
+
+    // 添加员工到加班列表
+    addEmployee(employee) {
+      if (!this.overtimeForm.employees.includes(employee.id)) {
+        this.overtimeForm.employees.push(employee.id);
+      }
+    },
+
+    // 检查员工是否已选择
+    isEmployeeSelected(employeeId) {
+      return this.overtimeForm.employees.includes(employeeId);
+    },
+
+    // 提交表单
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          // 这里处理表单提交逻辑
+          console.log('提交表单:', this.overtimeForm);
+          this.$message.success('加班申请提交成功!');
+        } else {
+          this.$message.error('请完善表单信息!');
+          return false;
+        }
+      });
+    },
+
+    // 重置表单
+    resetForm(formName) {
+      this.$refs[formName].resetFields();
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">.overtime-apply {
+  padding: 20px;
+
+  .form-card {
+    max-width: 800px;
+    margin: 0 auto;
+  }
+
+  .el-form-item {
+    margin-bottom: 20px;
+  }
+
+  .el-select {
+    width: 100%;
+  }
+}
+</style>

+ 14 - 0
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/workOvertime/applyList.vue

@@ -0,0 +1,14 @@
+<template>
+<div>111</div>
+</template>
+
+<script setup>
+export default {
+
+}
+
+</script>
+
+<style scoped lang="scss">
+
+</style>