Ver código fonte

Merge remote-tracking branch 'origin/master'

ljy121 1 ano atrás
pai
commit
04dbcc98da

+ 25 - 0
client/src/utils/tree.ts

@@ -402,3 +402,28 @@ export const filterNodeMethod = (value, data) => {
   if (!data) return
   return data.name.includes(value)
 }
+
+export const treeValuePath = (treeData, nodeId) => {
+  function traverse(nodes) {
+    for (const node of nodes) {
+      if (node.id === nodeId) {
+        return [node.label]
+      }
+      if (node.children) {
+        const path = traverse(node.children)
+        if (path) {
+          return [node.label, ...path]
+        }
+      }
+    }
+    return null
+  }
+
+  for (const rootNode of treeData) {
+    const path = traverse([rootNode])
+    if (path) {
+      return path
+    }
+  }
+  return []
+}

+ 2 - 2
client/src/views/Login/components/LoginForm.vue

@@ -177,8 +177,8 @@ const loginData = reactive({
   tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE,
   loginForm: {
     tenantName: '芋道源码',
-    username: 'admin',
-    password: 'admin123',
+    username: '',
+    password: '',
     captchaVerification: '',
     rememberMe: false
   }

+ 31 - 0
client/src/views/OaSystem/mineCenter/rightChild/index.ts

@@ -159,6 +159,37 @@ export const formConfigList = [
     ]
   }
 ]
+// 追加的档案
+const additionalConfig = [
+  {
+    title: '工作经历',
+    children: [
+      {
+        name: '',
+        title: ''
+      }
+    ]
+  },
+  {
+    title: '学习经历',
+    children: [
+      {
+        name: '',
+        title: ''
+      }
+    ]
+  },
+  {
+    title: '职称证书',
+    children: [
+      {
+        name: '',
+        title: ''
+      }
+    ]
+  }
+]
+
 const getDictList = () => {
   const dictOptionsObj: any = {}
   // 性别

+ 3 - 1
client/src/views/OaSystem/mineCenter/rightChild/wdda.vue

@@ -4,7 +4,9 @@ import { getRecordsDetail } from '@/api/oa/staffRecords'
 import { useUserStore } from '@/store/modules/user'
 import { getConfigDict } from './index'
 import TechCertificate from '../../personnelManagement/ygdaPage/TechCertificate.vue'
-
+/**
+ * @description 我的档案
+ */
 const formConfigList = getConfigDict()
 
 const userId = useUserStore().getUser.id // 当前登录的编号

+ 3 - 2
client/src/views/OaSystem/officeCenter/noticeAndLearn/add.vue

@@ -55,11 +55,12 @@ const { fileUrls, downloadFile, uploadFile, deleteFile } = useFiles(request)
 defineOptions({
   name: 'NoticeAdd'
 })
-const route = useRoute()
+const route: any = useRoute()
+const routeName: string = route.name ?? ''
 const initFormData: any = {
   id: null,
   title: '',
-  type: route.name.startsWith('notice') ? 1 : 2,
+  type: routeName.startsWith('Notice') || routeName.startsWith('notice') ? 1 : 2,
   studyType: null,
   files: '',
   userId: '',

+ 33 - 0
client/src/views/OaSystem/personnelManagement/ygdaPage/WorkTable.vue

@@ -0,0 +1,33 @@
+<template>
+  <el-table
+    class="detail-table"
+    :header-cell-style="{
+      background: '#F2F4F8',
+      color: '#000000',
+      height: '46px'
+    }"
+    style="width: 100%; height: 100%"
+    :data="tableData"
+    height="150px"
+  >
+    <el-table-column prop="workLocation" label="工作单位" />
+    <el-table-column prop="post" label="职位" />
+    <el-table-column prop="startTime" label="开始时间" />
+    <el-table-column prop="endTime" label="结束时间" />
+    <el-table-column prop="resignReason" label="离职原因" />
+    <el-table-column prop="jyxy" label="是否有竞业限制/未尽法律事宜" />
+    <el-table-column prop="competitionDetail" label="具体条款" />
+  </el-table>
+</template>
+<script lang="ts" setup>
+/**
+ * @description 工作经历
+ */
+const tableData = []
+</script>
+<style scoped lang="scss">
+.detail-table {
+  width: 100%;
+  height: auto;
+}
+</style>

+ 10 - 4
client/src/views/OaSystem/personnelManagement/ygdaPage/staffDetail.vue

@@ -1,14 +1,20 @@
 <script setup lang="ts">
+/**
+ * @description 档案详情
+ */
+
 defineOptions({ name: 'StaffDetail' })
 
 import { useQuery, useMutation } from '@tanstack/vue-query'
 import { getRecordsDetail, editRecordsDetail, generateStaffNum } from '@/api/oa/staffRecords'
 import { getConfigDict } from './index'
 import { ElRow, FormInstance } from 'element-plus'
-import TechCertificate from './TechCertificate.vue'
+// import TechCertificate from './TechCertificate.vue'
 import avatarImg from '@/assets/imgs/avatar.jpg'
 import DeptSelect from '@/components/DeptSelect/index.vue'
 import { createImageViewer } from '@/components/ImageViewer'
+import WorkTable from './WorkTable.vue'
+
 const formConfigList = getConfigDict()
 
 const { query } = useRoute()
@@ -180,9 +186,9 @@ const isEdit = computed(() => {
         <div class="my-portrait-item">
           <div class="title">
             <i></i>
-            <span>技能证书</span>
+            <span>工作经历</span>
           </div>
-          <TechCertificate />
+          <WorkTable />
         </div>
         <el-row justify="end">
           <el-form-item v-if="isEdit">
@@ -234,7 +240,7 @@ const isEdit = computed(() => {
 
     .my-portrait-item {
       margin-bottom: 20px;
-
+      width: 100%;
       .title {
         display: flex;
         align-items: center;

+ 3 - 0
client/src/views/OaSystem/projectCenter/projectDetail/components/fjcl/index.scss

@@ -55,6 +55,9 @@
       }
     }
   }
+  :deep(.el-tree-node) {
+    padding: 5px 0px;
+  }
   :deep(.el-tree-node__content>.el-tree-node__expand-icon) {
     padding-left: 0px !important;
   }

+ 90 - 36
client/src/views/OaSystem/projectCenter/projectDetail/components/fjcl/index.vue

@@ -3,14 +3,38 @@
     <div class="treeBox">
       <h4>材料分类</h4>
       <div>
-        <el-tree
-          :data="treeData"
-          :render-content="renderContent"
-          :props="defaultProps"
-          @node-click="handleNodeClick"
-        />
+        <el-tree :data="treeData" :props="defaultProps" @node-click="handleNodeClick">
+          <template #default="{ data }">
+            <el-dropdown :hide-on-click="false" trigger="contextmenu">
+              <span class="custom-tree-node">
+                <el-icon
+                  style="
+                    margin-right: 5px;
+                    margin-top: -4px;
+                    vertical-align: middle;
+                    font-size: 18px;
+                  "
+                >
+                  <Document v-if="data.type == '3'" style="color: #2e77e6" />
+                  <Folder v-else style="color: #f9a527" />
+                </el-icon>
+                <span>{{ data.name }}</span>
+              </span>
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item v-if="data.type !== 3" @click="uploadClick(data)"
+                    >上传</el-dropdown-item
+                  >
+                  <el-dropdown-item>下载</el-dropdown-item>
+                  <el-dropdown-item v-if="data.type === 3" divided>删除</el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </template>
+        </el-tree>
       </div>
     </div>
+    <input type="file" ref="fileRef" style="display: none" @change="fileChageHandle" />
     <div class="previewBox">
       <div class="tools">
         <h4>{{ fileInfo?.['fileName'] }}</h4>
@@ -33,6 +57,7 @@ import { onMounted } from 'vue'
 import { useRoute } from 'vue-router'
 import request from '@/config/axios'
 import VueOfficePdf from '@vue-office/pdf'
+import { listToTree, treeValuePath } from '@/utils/tree'
 import '@vue-office/excel/lib/index.css'
 import '@vue-office/docx/lib/index.css'
 
@@ -74,45 +99,74 @@ interface Tree {
   children?: Array<Tree>
 }
 const treeData = ref<Tree[]>([])
+
+type MaterialPath = {
+  label: string
+  id: string
+  children: MaterialPath[]
+}
+const materialPathTree = ref<MaterialPath[]>([])
 const queryProjectMaterialByTree = (): void => {
-  const urlApi = `/project-material/tree`
-  request.post({ url: urlApi, data: { projectId: projectId } }, '/business').then((resultData) => {
-    treeData.value = resultData
+  const urlApi = `/project-material-tree`
+  request.get({ url: urlApi, params: { projectId: projectId } }, '/business').then((resultData) => {
+    materialPathTree.value = listToTree(
+      resultData
+        .map((item) => {
+          if (item.type !== 3) {
+            return {
+              label: item['extendData']['mark'],
+              id: item['id'],
+              pid: item['pid'],
+              children: []
+            }
+          }
+        })
+        .filter((item) => item)
+    )
+    treeData.value = listToTree(resultData)
   })
 }
 const queryProjectMaterial = (fileId): void => {
-  const urlApi = `/project-material?id=${fileId}`
+  const urlApi = `/project-material-get?id=${fileId}`
   request.get({ url: urlApi }, '/business').then((resultData) => {
     fileInfo.value = resultData
   })
 }
-const downloadFile = (): void => {}
-const renderContent = (h, { node, data, store }) => {
-  return h(
-    'span',
-    {
-      style: {
-        display: 'inline-block',
-        width: '100%'
-      }
-    },
-    [
-      h('span', [
-        h(resolveComponent(data['nodeType'] === 1 ? 'Document' : 'Folder'), {
-          style: {
-            marginRight: '5px',
-            marginTop: '-4px',
-            verticalAlign: 'middle',
-            width: '18px',
-            height: '18px',
-            color: data['nodeType'] === 1 ? '#2e77e6' : '#f9a527'
-          }
-        }),
-        h('span', data.name)
-      ])
-    ]
-  )
+
+/***
+ * 文件上传
+ */
+const fileRef = ref(null)
+const fileChageHandle = (evt) => {
+  const files = evt.target.files // 获取文件列表
+  uploadProjectMaterial(files[0])
+}
+const currentMaterialsId = ref<string>('')
+const currentMaterialPath = ref<string>()
+const uploadClick = (data) => {
+  currentMaterialsId.value = data.id as string
+  if (data.type !== 3) {
+    const arr: string[] = treeValuePath(materialPathTree.value, data.id)
+    if (arr && arr.length > 0) {
+      currentMaterialPath.value = arr.join('/')
+      currentMaterialsId.value = data.id
+      //@ts-ignore
+      fileRef.value.click()
+    }
+  }
 }
+const uploadProjectMaterial = (file): void => {
+  const urlApi = `/project-material-upload`
+  const formData = new FormData()
+  formData.append('projectId', projectId as string)
+  formData.append('file', file)
+  formData.append('prePath', currentMaterialPath.value as string)
+  formData.append('flowMaterialsId', currentMaterialsId.value as string)
+  request.upload({ url: urlApi, data: formData }, '/business').then((resultData) => {
+    fileInfo.value = resultData
+  })
+}
+const downloadFile = (): void => {}
 onMounted(() => {
   queryProjectMaterialByTree()
 })

+ 5 - 5
zjugis-business/src/main/java/com/zjugis/business/flow/contractRenew/event/ContractRenewEvent.java

@@ -252,19 +252,19 @@ public class ContractRenewEvent extends BaseController {
 
 
     /**
-     * 转到分管领导
+     * 转到下级领导
      */
-    @PostMapping("/to-dept-manager-leader")
+    @PostMapping("/to-leader")
     public String toDeptManagerLeader(String flowInstanceId) {
         try {
             if (StringUtils.isNotBlank(flowInstanceId)) {
                 ContractRenewDO entity = contractRenewService.findByInstanceId(flowInstanceId);
                 List<Map<String, String>> userMaps = new ArrayList<>();
                 if (StringUtils.isNotBlank(entity.getDeptId())) {
-                    AdminUserRespDTO deptLeaderRespDTO = adminUserApi.getUserLeader(entity.getUserId()).getCheckedData();
-                    if (deptLeaderRespDTO != null && StringUtils.isNotBlank(deptLeaderRespDTO.getId())) {
+                    AdminUserRespDTO dept = adminUserApi.getNextLeader(entity.getUserId()).getCheckedData();
+                    if (dept != null && StringUtils.isNotBlank(dept.getId())) {
                         HashMap<String, String> map = new HashMap<>();
-                        map.put("id", deptLeaderRespDTO.getId());
+                        map.put("id", dept.getId());
                         userMaps.add(map);
                     }
                 }

+ 4 - 1
zjugis-module-system/zjugis-module-system-api/src/main/java/com/zjugis/module/system/api/user/AdminUserApi.java

@@ -148,6 +148,9 @@ public interface AdminUserApi {
     CommonResult<Boolean> closeUser(@RequestParam("userId") String userId);
 
 
-
+    @GetMapping(PREFIX + "/getNextLeader")
+    @Operation(summary = "通过用户 ID 获取上一级领导")
+    @Parameter(name = "id", description = "用户编号", example = "1", required = true)
+    CommonResult<AdminUserRespDTO> getNextLeader(@RequestParam("id") String id);
 
 }

+ 6 - 0
zjugis-module-system/zjugis-module-system-biz/src/main/java/com/zjugis/module/system/api/user/AdminUserApiImpl.java

@@ -163,4 +163,10 @@ public class AdminUserApiImpl implements AdminUserApi {
         return success(true);
     }
 
+    @Override
+    public CommonResult<AdminUserRespDTO> getNextLeader(String id) {
+        AdminUserDO user = userService.getNextLeader(id);
+        return success(UserConvert.INSTANCE.convert4(user));
+    }
+
 }

+ 8 - 0
zjugis-module-system/zjugis-module-system-biz/src/main/java/com/zjugis/module/system/service/user/AdminUserService.java

@@ -288,4 +288,12 @@ public interface AdminUserService {
      * @param attendanceFlag
      */
     void updateUserAttendanceFlag(String id, Boolean attendanceFlag);
+
+    /**
+     * 根据用户ID获取领导
+     *
+     * @param id
+     * @return
+     */
+    AdminUserDO getNextLeader(String id);
 }

+ 12 - 0
zjugis-module-system/zjugis-module-system-biz/src/main/java/com/zjugis/module/system/service/user/AdminUserServiceImpl.java

@@ -636,6 +636,18 @@ public class AdminUserServiceImpl implements AdminUserService {
         userMapper.updateById(updateObj);
     }
 
+    @Override
+    public AdminUserDO getNextLeader(String id) {
+        AdminUserDO adminUserDO = userMapper.selectById(id);
+        DeptDO dept = deptService.getDept(adminUserDO.getDeptId());
+        if(dept.getLeaderUserId().equals(id)){
+            DeptLeaderDO deptLeader = deptLeaderService.getDeptLeaderByDeptId(dept.getId());
+            return userMapper.selectById(deptLeader.getUserId());
+        }else {
+            return userMapper.selectById(dept.getLeaderUserId());
+        }
+    }
+
     /**
      * 对密码进行加密
      *