Jelajahi Sumber

导入任务

seyason 4 tahun lalu
induk
melakukan
9a91cd1950

+ 0 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/aop/AopLogConfiguration.java

@@ -38,8 +38,6 @@ public class AopLogConfiguration {
         }
         //打印请求内容
         log.info("---------------请求内容---------------");
-        log.info("请求地址:"+request.getRequestURL().toString());
-        log.info("请求方式:"+request.getMethod());
         log.info("请求类方法:"+joinPoint.getSignature().getName());
         log.info("请求类方法参数:"+ Arrays.toString(joinPoint.getArgs()));
         log.info("---------------请求内容---------------");
@@ -55,9 +53,6 @@ public class AopLogConfiguration {
         if(request.getRequestURL().toString().contains("/imageProcessing")){
             return;
         }
-        log.info("===============返回内容===============");
-        log.info("返回的内容:"+ o.toString());
-        log.info("===============返回内容===============");
     }
 
     /**

+ 7 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java

@@ -14,8 +14,10 @@ import org.springframework.web.bind.WebDataBinder;
 import org.springframework.web.bind.annotation.InitBinder;
 import org.springframework.web.bind.annotation.RequestMapping;
 
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
@@ -503,5 +505,10 @@ public class TaskController {
     public HttpRespMsg exportTask(Integer projectId, Integer taskType) {
         return taskService.exportTask(projectId, taskType);
     }
+
+    @RequestMapping("/importTask")
+    public HttpRespMsg importUser(Integer projectId, Integer groupId, Integer stagesId, @RequestParam MultipartFile file) {
+        return taskService.importTask(projectId, groupId, stagesId, file, request);
+    }
 }
 

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

@@ -5,7 +5,9 @@ import com.management.platform.entity.Task;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.management.platform.util.HttpRespMsg;
 import org.apache.poi.ss.formula.functions.T;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 
 /**
@@ -31,4 +33,6 @@ public interface TaskService extends IService<Task> {
     HttpRespMsg exportTaskTimeCompare(Integer projectId);
 
     HttpRespMsg exportTask(Integer projectId, Integer taskType);
+
+    HttpRespMsg importTask(Integer projectId, Integer groupId, Integer stagesId, MultipartFile file, HttpServletRequest request);
 }

+ 156 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java

@@ -1,31 +1,37 @@
 package com.management.platform.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.management.platform.entity.Project;
-import com.management.platform.entity.Task;
-import com.management.platform.entity.TimeTask;
-import com.management.platform.entity.User;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.*;
 import com.management.platform.mapper.ProjectMapper;
+import com.management.platform.mapper.StagesMapper;
 import com.management.platform.mapper.TaskMapper;
+import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.TaskService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.management.platform.util.ExcelUtil;
-import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.*;
 import org.apache.poi.hssf.usermodel.*;
 import org.apache.poi.ss.formula.functions.T;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
-import java.io.FileOutputStream;
-import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * <p>
@@ -36,6 +42,7 @@ import java.util.Map;
  * @since 2021-04-19
  */
 @Service
+@Transactional
 public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
     @Value(value = "${upload.path}")
     private String path;
@@ -43,6 +50,10 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
     private TaskMapper taskMapper;
     @Resource
     private ProjectMapper projectMapper;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private StagesMapper stagesMapper;
     @Override
     public HttpRespMsg getExecutorPanel(Integer projectId) {
         HttpRespMsg msg = new HttpRespMsg();
@@ -264,4 +275,138 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
         }
         return httpRespMsg;
     }
+
+    @Override
+    public HttpRespMsg importTask(Integer projectId, Integer groupId, Integer stagesId, MultipartFile multipartFile, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+
+        //首先先搞到公司id
+        Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
+        List<User> allUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+        //获取当前导入的任务列表
+        Stages stages = stagesMapper.selectById(stagesId);
+        List<Task> maxList = taskMapper.selectList(new QueryWrapper<Task>().eq("stages_id", stagesId).orderByDesc("seq").last("limit 1"));
+        int seq = 1;
+        if (maxList.size() > 0) {
+            seq = maxList.get(0).getSeq() + 1;
+        }
+        HashMap<String, Integer> taskTypeMap = new HashMap<>();
+        taskTypeMap.put("任务", 0);
+        taskTypeMap.put("里程碑", 1);
+        taskTypeMap.put("风险", 2);
+        HashMap<String, Integer> taskLevelMap = new HashMap<>();
+        taskTypeMap.put("一般", 0);
+        taskTypeMap.put("重要", 1);
+        taskTypeMap.put("紧急", 2);
+        //然后处理文件
+        String fileName = multipartFile.getOriginalFilename();
+        File file = new File(fileName == null ? "file" : fileName);
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        try {
+            inputStream = multipartFile.getInputStream();
+            outputStream = new FileOutputStream(file);
+            byte[] buffer = new byte[4096];
+            int temp = 0;
+            while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
+                outputStream.write(buffer, 0, temp);
+            }
+            inputStream.close();
+            outputStream.close();
+            //然后解析表格
+            XSSFWorkbook workbook = new XSSFWorkbook(file);
+            //我们只需要第一个sheet
+            XSSFSheet sheet = workbook.getSheetAt(0);
+            //查重检验的手机号列表
+            List<String> phoneList = new ArrayList<>();
+            //要插入的账号列表
+            List<Task> taskList = new ArrayList<>();
+            //由于第一行需要指明列对应的标题
+            for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
+                XSSFRow row = sheet.getRow(rowIndex);
+                if (row == null) {
+                    continue;
+                }
+                //此处新建账号 默认密码为000000 默认 姓名第一列 手机号第二列 月薪第三列
+                XSSFCell nameCell = row.getCell(0);
+                if (nameCell == null) {
+                    break;
+                }
+                XSSFCell typeCell = row.getCell(1);
+                XSSFCell executorCell = row.getCell(2);
+                XSSFCell levelCell = row.getCell(3);
+                XSSFCell endDateCell = row.getCell(4);
+                XSSFCell planHoursCell = row.getCell(5);
+                nameCell.setCellType(CellType.STRING);
+                typeCell.setCellType(CellType.STRING);
+                endDateCell.setCellType(CellType.NUMERIC);
+                planHoursCell.setCellType(CellType.STRING);
+                String name = nameCell.getStringCellValue();
+                String type = typeCell.getStringCellValue();
+                //忽略表头
+                if (name.equals("标题") && type.equals("类型") && rowIndex == 0) {
+                    continue;
+                }
+                Task task = new Task();
+                task.setProjectId(projectId);
+                task.setGroupId(groupId);
+                String executorName = executorCell.getStringCellValue();
+                System.out.println("姓名=="+executorCell.getStringCellValue());
+                Optional<User> first = allUserList.stream().filter(u -> u.getName().equals(executorName)).findFirst();
+                if (first.isPresent()) {
+                    User find = first.get();
+                    task.setExecutorId(find.getId());
+                    task.setExecutorName(find.getName());
+                    task.setExecutorColor(find.getColor());
+                }
+                task.setStagesId(stagesId);
+                task.setStagesName(stages.getStagesName());
+                task.setSeq(seq++);
+                task.setName(name);
+                task.setTaskType(taskTypeMap.get(typeCell.getStringCellValue()));
+                task.setTaskLevel(taskLevelMap.get(levelCell.getStringCellValue()));
+                Date dateCellValue = endDateCell.getDateCellValue();
+                System.out.println("日期=="+dateCellValue.toString());
+                String formatValue = new SimpleDateFormat("yyyy-MM-dd").format(dateCellValue);
+                LocalDate endDate = LocalDate.parse(formatValue, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+                task.setEndDate(endDate);
+                task.setPlanHours(Integer.parseInt(planHoursCell.getStringCellValue()));
+
+                task.setCreateDate(LocalDate.now());
+                taskList.add(task);
+            }
+            saveBatch(taskList);
+            //最后删掉这个文件
+//            if (!file.delete()) {
+//                System.out.println("临时文件" + file.getName() + "删除失败");
+//            }
+            //校验是否有重复账号
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            httpRespMsg.setError("文件处理出错");
+            return httpRespMsg;
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            httpRespMsg.setError("数据格式有误或存在空数据 导入失败");
+            return httpRespMsg;
+        } catch (Exception e) {
+            e.printStackTrace();
+            httpRespMsg.setError("发生其他错误");
+            return httpRespMsg;
+        } finally {
+            //关闭流
+            try {
+                if (outputStream != null && inputStream != null) {
+                    outputStream.close();
+                    inputStream.close();
+                    System.out.println("流已关闭");
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            System.out.println(file.delete());
+        }
+        return httpRespMsg;
+    }
 }

TEMPAT SAMPAH
fhKeeper/formulahousekeeper/management-platform/新版任务模板.xlsx


+ 49 - 3
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/demo_index.html

@@ -54,6 +54,18 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe613;</span>
+                <div class="name">导入</div>
+                <div class="code-name">&amp;#xe613;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6ab;</span>
+                <div class="name">导出</div>
+                <div class="code-name">&amp;#xe6ab;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe72d;</span>
                 <div class="name">export</div>
@@ -240,9 +252,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1621152979500') format('woff2'),
-       url('iconfont.woff?t=1621152979500') format('woff'),
-       url('iconfont.ttf?t=1621152979500') format('truetype');
+  src: url('iconfont.woff2?t=1621300718527') format('woff2'),
+       url('iconfont.woff?t=1621300718527') format('woff'),
+       url('iconfont.ttf?t=1621300718527') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -268,6 +280,24 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont firerock-icondaoru"></span>
+            <div class="name">
+              导入
+            </div>
+            <div class="code-name">.firerock-icondaoru
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-icondaochu"></span>
+            <div class="name">
+              导出
+            </div>
+            <div class="code-name">.firerock-icondaochu
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont firerock-iconexport"></span>
             <div class="name">
@@ -547,6 +577,22 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-icondaoru"></use>
+                </svg>
+                <div class="name">导入</div>
+                <div class="code-name">#firerock-icondaoru</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-icondaochu"></use>
+                </svg>
+                <div class="name">导出</div>
+                <div class="code-name">#firerock-icondaochu</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#firerock-iconexport"></use>

+ 11 - 3
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2390497 */
-  src: url('iconfont.woff2?t=1621152979500') format('woff2'),
-       url('iconfont.woff?t=1621152979500') format('woff'),
-       url('iconfont.ttf?t=1621152979500') format('truetype');
+  src: url('iconfont.woff2?t=1621300718527') format('woff2'),
+       url('iconfont.woff?t=1621300718527') format('woff'),
+       url('iconfont.ttf?t=1621300718527') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,14 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.firerock-icondaoru:before {
+  content: "\e613";
+}
+
+.firerock-icondaochu:before {
+  content: "\e6ab";
+}
+
 .firerock-iconexport:before {
   content: "\e72d";
 }

File diff ditekan karena terlalu besar
+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.js


+ 14 - 0
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.json

@@ -5,6 +5,20 @@
   "css_prefix_text": "firerock-icon",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "20147073",
+      "name": "导入",
+      "font_class": "daoru",
+      "unicode": "e613",
+      "unicode_decimal": 58899
+    },
+    {
+      "icon_id": "20154661",
+      "name": "导出",
+      "font_class": "daochu",
+      "unicode": "e6ab",
+      "unicode_decimal": 59051
+    },
     {
       "icon_id": "19441448",
       "name": "export",

TEMPAT SAMPAH
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.ttf


TEMPAT SAMPAH
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.woff


TEMPAT SAMPAH
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.woff2


+ 72 - 3
fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue

@@ -76,7 +76,7 @@
                     
                     <el-main style="background:#f7f7f7;padding:0px;">
                         <el-row style="color:#999;margin-top:10px;padding: 0px 10px;" :gutter="10">
-                        <el-col :span="18">
+                        <el-col :span="16">
                             <el-link @click="toggleGroup"><i v-if="selectedGroup != null" :class="groupWidth==0?'el-icon-d-arrow-right':'el-icon-d-arrow-left'" style="margin-top:10px;">{{selectedGroup.name}}</i></el-link>
                         </el-col>
                         <el-col :span="4">
@@ -86,8 +86,9 @@
                                 </el-option>
                             </el-select>
                         </el-col>
-                        <el-col :span="2">
-                            <el-button icon="iconfont firerock-iconexport" size="mini" @click="showExportDialog">导出</el-button>
+                        <el-col :span="4">
+                            <el-button icon="iconfont firerock-icondaochu" size="mini" @click="showExportDialog">导出</el-button>
+                            <el-button icon="iconfont firerock-icondaoru" size="mini" @click="importTaskDialog = true;importToStageId = stageList[0].id;">导入</el-button>
                         </el-col>
                         </el-row>
                         <!-- <div style="color:#999;margin-top:10px;">
@@ -587,6 +588,26 @@
                 <el-button type="primary" @click="exportTask" style="width:100%;" >导出</el-button>
             </div>
         </el-dialog>
+
+        <!--导入数据,下载模板 -->
+        <el-dialog title="工作计划导入" v-if="importTaskDialog" :visible.sync="importTaskDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
+            <el-form ref="form4" >
+                <el-form-item label="1. 请先下载模板并填写后上传" >
+                    <el-link type="primary" :underline="false" href="./upload/项目任务导入模板.xlsx" download="项目任务导入模板.xlsx">项目任务模板下载</el-link>
+                </el-form-item>
+                <el-form-item label="2. 选择要导入的任务列表">
+                    <el-select v-model="importToStageId" placeholder="任务列表"  style="width:350px;">
+                        <el-option v-for="item in stageList" :label="item.stagesName" :value="item.id" :key="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <div><span style="font-size:12px;color:#999;">如导入的任务属于多个列表,可在导入后拖拽来更改所属列表</span></div>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-upload ref="upload" action="#" :limit="1" :http-request="importTask" :show-file-list="false">
+                        <el-button type="primary" :underline="false" style="width:100%;">上传文件</el-button>
+                </el-upload>
+            </div>
+        </el-dialog>
     </section>
 </template>
 <script>
@@ -623,6 +644,8 @@
         
         data() {
             return {
+                importTaskDialog:false,
+                importToStageId:null,
                 exportDialog: false,
                 exportTaskType:null,
                 groupTemplateList:[],
@@ -755,6 +778,52 @@
             
         },
         methods: {
+            // 批量导入人员
+            importTask(item) {
+                //首先判断文件类型
+                let str = item.file.name.split(".");
+                let format = str[str.length - 1];
+                if (format != "xls" && format != "xlsx") {
+                    this.$message({
+                        message: "请选择.xls或.xlsx文件",
+                        type: "error"
+                    });
+                } else {
+                    this.listLoading = true;
+                    let formData = new FormData();
+                    formData.append("file", item.file);
+                    formData.append("projectId", this.curProjectId);
+                    formData.append("groupId", this.selectedGroup.id);
+                    formData.append("stagesId", this.importToStageId);
+                    this.http.uploadFile('/task/importTask', formData,
+                    res => {
+                        this.$refs.upload.clearFiles();
+                        this.listLoading = false;
+                        if (res.code == "ok") {
+                            this.$message({
+                                message: "导入成功",
+                                type: "success"
+                            });
+                            //重新读取列表
+                            this.getStageList();
+                            this.importTaskDialog = false;
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.$refs.upload.clearFiles();
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                }
+            },
             //删除任务进展
             deleteTaskProgress(id) {
                 console.log(id, '删除传过来的数据');