Browse Source

系统反馈

xiaoqiao 10 months ago
parent
commit
32c125383f
57 changed files with 3092 additions and 869 deletions
  1. 554 424
      lib/华北油田Ai检索.PDM
  2. 547 424
      lib/华北油田Ai检索.pdb
  3. 47 0
      src/main/java/com/bowintek/practice/controller/system/FeedbackController.java
  4. 1 1
      src/main/java/com/bowintek/practice/controller/system/FileController.java
  5. 2 3
      src/main/java/com/bowintek/practice/mapper/CfFileMapper.java
  6. 30 0
      src/main/java/com/bowintek/practice/mapper/SysFeedbackMapper.java
  7. 65 0
      src/main/java/com/bowintek/practice/model/SysFeedback.java
  8. 610 0
      src/main/java/com/bowintek/practice/model/SysFeedbackExample.java
  9. 80 0
      src/main/java/com/bowintek/practice/services/impl/system/FeedbackServiceImpl.java
  10. 51 0
      src/main/java/com/bowintek/practice/services/impl/system/FileServiceImpl.java
  11. 16 0
      src/main/java/com/bowintek/practice/services/service/FeedbackService.java
  12. 3 1
      src/main/java/com/bowintek/practice/services/service/system/FileService.java
  13. 1 1
      src/main/resources/application.yml
  14. 1 1
      src/main/resources/generatorConfig.xml
  15. 291 0
      src/main/resources/mapping/CfFileMapper.xml
  16. 228 0
      src/main/resources/mapping/SysFeedbackMapper.xml
  17. BIN
      src/main/resources/static/doc/upload/202404/20240423171331_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png
  18. BIN
      src/main/resources/static/doc/upload/202404/20240423171745_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png
  19. BIN
      src/main/resources/static/doc/upload/202404/20240423172031_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png
  20. BIN
      src/main/resources/static/doc/upload/202404/20240423172543_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png
  21. BIN
      src/main/resources/static/doc/upload/202404/20240423173330_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png
  22. BIN
      src/main/resources/static/doc/upload/202404/20240424102822_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png
  23. BIN
      src/main/resources/static/doc/upload/202404/20240424103050_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png
  24. BIN
      src/main/resources/static/excel/07f4a177-47c3-41c3-b2f2-c492e602a354.xlsx
  25. BIN
      src/main/resources/static/excel/10b9f2a0-afec-40d6-8d5e-caa1d2a40df5.xlsx
  26. BIN
      src/main/resources/static/excel/13f3796d-b782-4f90-95e8-70faa1340764.xlsx
  27. BIN
      src/main/resources/static/excel/1419b5c6-990e-40c2-bae3-81cb56b50a99.xlsx
  28. BIN
      src/main/resources/static/excel/1d6de2dd-7d0d-45b9-a653-da3e470c9f59.xlsx
  29. BIN
      src/main/resources/static/excel/20c2505f-077d-4212-ac4c-bd284914910a.xlsx
  30. BIN
      src/main/resources/static/excel/3299b18b-b315-4856-8084-c69464fe83c9.xlsx
  31. BIN
      src/main/resources/static/excel/3679c85b-2cd0-4f4f-9ed7-c1217a214d39.xlsx
  32. BIN
      src/main/resources/static/excel/39d07c51-1fc8-429a-9ce4-5ad1b1f0d29d.xlsx
  33. BIN
      src/main/resources/static/excel/53d24279-b7bc-4f87-b2b6-534f44690d14.xlsx
  34. BIN
      src/main/resources/static/excel/5e506489-2f8b-4ab6-a803-1c6152a9af60.xlsx
  35. BIN
      src/main/resources/static/excel/84d708ce-2654-4f4a-94f7-31409b57247e.xlsx
  36. BIN
      src/main/resources/static/excel/88bcd5ea-8d99-4239-a4a2-3a51af92240f.xlsx
  37. BIN
      src/main/resources/static/excel/aeea8256-ed27-4ed0-8a87-81e37e818f4a.xlsx
  38. BIN
      src/main/resources/static/excel/c0456169-8886-4c71-afb4-4c633198d41f.xlsx
  39. BIN
      src/main/resources/static/excel/d6ce0377-86ff-405b-8c98-643764520b4f.xlsx
  40. BIN
      src/main/resources/static/excel/d841c3e9-5086-43a4-9cb5-51e1c6556276.xlsx
  41. BIN
      src/main/resources/static/excel/e92a4b46-fe84-4145-b568-4c5a4dc9fd3f.xlsx
  42. BIN
      src/main/resources/static/excel/fc5b18d3-802e-466f-8c2f-8b3c9b2344f0.xlsx
  43. 1 1
      target/classes/application.yml
  44. BIN
      target/classes/com/bowintek/practice/controller/system/FileController.class
  45. BIN
      target/classes/com/bowintek/practice/services/impl/system/FileServiceImpl.class
  46. BIN
      target/classes/com/bowintek/practice/services/service/system/FileService.class
  47. 1 1
      target/classes/generatorConfig.xml
  48. 38 5
      vue/package-lock.json
  49. 1 0
      vue/package.json
  50. 1 1
      vue/public/appconfig.json
  51. 26 0
      vue/src/api/system/file/index.ts
  52. BIN
      vue/src/assets/images/fk.jpg
  53. 179 0
      vue/src/layout/tabs/feedback.vue
  54. 25 6
      vue/src/layout/tabs/tabs-view.vue
  55. 1 0
      vue/src/router/asyncModules/system.ts
  56. 183 0
      vue/src/views/system/feedback/index.vue
  57. 109 0
      vue/src/views/system/feedback/view.vue

File diff suppressed because it is too large
+ 554 - 424
lib/华北油田Ai检索.PDM


File diff suppressed because it is too large
+ 547 - 424
lib/华北油田Ai检索.pdb


+ 47 - 0
src/main/java/com/bowintek/practice/controller/system/FeedbackController.java

@@ -0,0 +1,47 @@
+package com.bowintek.practice.controller.system;
+
+import com.bowintek.practice.AppConfig;
+import com.bowintek.practice.filter.exception.BaseResponse;
+import com.bowintek.practice.filter.exception.RespGenerstor;
+import com.bowintek.practice.model.SysFeedback;
+import com.bowintek.practice.services.service.AccountService;
+import com.bowintek.practice.services.service.FeedbackService;
+import com.bowintek.practice.vo.system.AnnouncementModel;
+import com.bowintek.practice.vo.temp.TempObjectModel;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/system/feedback")
+public class FeedbackController {
+
+    @Autowired
+    private AccountService accountService;
+    @Autowired
+    private AppConfig appConfig;
+    @Autowired
+    private FeedbackService feedbackService;
+
+    @PostMapping("/saveFeedback")
+    public BaseResponse saveFeedback(@RequestBody SysFeedback data) {
+        RespGenerstor.success(feedbackService.saveFeedback(data, accountService.getLoginUserID(),
+                accountService.getUserByUserID(accountService.getLoginUserID()).name));
+        return RespGenerstor.success(1);
+    }
+    @GetMapping("getFeedbackList")
+    public BaseResponse<PageInfo<SysFeedback>> getFeedbackList(@RequestParam("page") int page, @RequestParam("rows") int rows,
+                                                                         @RequestParam(required = false) String content,
+                                                                   @RequestParam(required = false) String createByName,
+                                                                         @RequestParam(required = false)String beginDate,
+                                                                         @RequestParam(required = false)String endDate) {
+        return RespGenerstor.success(feedbackService.getFeedbackList(page, rows,content, createByName,beginDate,endDate));
+    }
+    @ResponseBody
+    @PostMapping("/delete")
+    public BaseResponse<Integer> delete(@RequestBody List<String> idList) {
+        return RespGenerstor.success(feedbackService.delete(idList));
+    }
+}

+ 1 - 1
src/main/java/com/bowintek/practice/controller/system/FileController.java

@@ -42,7 +42,7 @@ public class FileController {
 
     @PostMapping("upload")
     public BaseResponse<Integer> upload(MultipartFile[] files, String fileRefId, Integer fileType, Integer isSingle) throws Exception {
-        return RespGenerstor.success(fileService.saveFile(files, fileRefId, fileType, accountService.getLoginUserID(), isSingle));
+        return RespGenerstor.success(fileService.uploadToLocal(files[0], fileRefId, fileType, accountService.getLoginUserID(), isSingle));
     }
 
     @PostMapping("uploadBase64")

+ 2 - 3
src/main/java/com/bowintek/practice/mapper/CfFileMapper.java

@@ -2,9 +2,8 @@ package com.bowintek.practice.mapper;
 
 import com.bowintek.practice.model.CfFile;
 import com.bowintek.practice.model.CfFileExample;
-import org.apache.ibatis.annotations.Param;
-
 import java.util.List;
+import org.apache.ibatis.annotations.Param;
 
 public interface CfFileMapper {
     long countByExample(CfFileExample example);
@@ -28,4 +27,4 @@ public interface CfFileMapper {
     int updateByPrimaryKeySelective(CfFile row);
 
     int updateByPrimaryKey(CfFile row);
-}
+}

+ 30 - 0
src/main/java/com/bowintek/practice/mapper/SysFeedbackMapper.java

@@ -0,0 +1,30 @@
+package com.bowintek.practice.mapper;
+
+import com.bowintek.practice.model.SysFeedback;
+import com.bowintek.practice.model.SysFeedbackExample;
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+
+public interface SysFeedbackMapper {
+    long countByExample(SysFeedbackExample example);
+
+    int deleteByExample(SysFeedbackExample example);
+
+    int deleteByPrimaryKey(String feedbackId);
+
+    int insert(SysFeedback row);
+
+    int insertSelective(SysFeedback row);
+
+    List<SysFeedback> selectByExample(SysFeedbackExample example);
+
+    SysFeedback selectByPrimaryKey(String feedbackId);
+
+    int updateByExampleSelective(@Param("row") SysFeedback row, @Param("example") SysFeedbackExample example);
+
+    int updateByExample(@Param("row") SysFeedback row, @Param("example") SysFeedbackExample example);
+
+    int updateByPrimaryKeySelective(SysFeedback row);
+
+    int updateByPrimaryKey(SysFeedback row);
+}

+ 65 - 0
src/main/java/com/bowintek/practice/model/SysFeedback.java

@@ -0,0 +1,65 @@
+package com.bowintek.practice.model;
+
+import java.util.Date;
+
+public class SysFeedback {
+    private String feedbackId;
+
+    private String content;
+
+    private String url;
+
+    private String createBy;
+
+    private String createByName;
+
+    private Date createTime;
+
+    public String getFeedbackId() {
+        return feedbackId;
+    }
+
+    public void setFeedbackId(String feedbackId) {
+        this.feedbackId = feedbackId == null ? null : feedbackId.trim();
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content == null ? null : content.trim();
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url == null ? null : url.trim();
+    }
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy == null ? null : createBy.trim();
+    }
+
+    public String getCreateByName() {
+        return createByName;
+    }
+
+    public void setCreateByName(String createByName) {
+        this.createByName = createByName == null ? null : createByName.trim();
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+}

+ 610 - 0
src/main/java/com/bowintek/practice/model/SysFeedbackExample.java

@@ -0,0 +1,610 @@
+package com.bowintek.practice.model;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class SysFeedbackExample {
+    protected String orderByClause;
+
+    protected boolean distinct;
+
+    protected List<Criteria> oredCriteria;
+
+    public SysFeedbackExample() {
+        oredCriteria = new ArrayList<>();
+    }
+
+    public void setOrderByClause(String orderByClause) {
+        this.orderByClause = orderByClause;
+    }
+
+    public String getOrderByClause() {
+        return orderByClause;
+    }
+
+    public void setDistinct(boolean distinct) {
+        this.distinct = distinct;
+    }
+
+    public boolean isDistinct() {
+        return distinct;
+    }
+
+    public List<Criteria> getOredCriteria() {
+        return oredCriteria;
+    }
+
+    public void or(Criteria criteria) {
+        oredCriteria.add(criteria);
+    }
+
+    public Criteria or() {
+        Criteria criteria = createCriteriaInternal();
+        oredCriteria.add(criteria);
+        return criteria;
+    }
+
+    public Criteria createCriteria() {
+        Criteria criteria = createCriteriaInternal();
+        if (oredCriteria.size() == 0) {
+            oredCriteria.add(criteria);
+        }
+        return criteria;
+    }
+
+    protected Criteria createCriteriaInternal() {
+        Criteria criteria = new Criteria();
+        return criteria;
+    }
+
+    public void clear() {
+        oredCriteria.clear();
+        orderByClause = null;
+        distinct = false;
+    }
+
+    protected abstract static class GeneratedCriteria {
+        protected List<Criterion> criteria;
+
+        protected GeneratedCriteria() {
+            super();
+            criteria = new ArrayList<>();
+        }
+
+        public boolean isValid() {
+            return criteria.size() > 0;
+        }
+
+        public List<Criterion> getAllCriteria() {
+            return criteria;
+        }
+
+        public List<Criterion> getCriteria() {
+            return criteria;
+        }
+
+        protected void addCriterion(String condition) {
+            if (condition == null) {
+                throw new RuntimeException("Value for condition cannot be null");
+            }
+            criteria.add(new Criterion(condition));
+        }
+
+        protected void addCriterion(String condition, Object value, String property) {
+            if (value == null) {
+                throw new RuntimeException("Value for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value));
+        }
+
+        protected void addCriterion(String condition, Object value1, Object value2, String property) {
+            if (value1 == null || value2 == null) {
+                throw new RuntimeException("Between values for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value1, value2));
+        }
+
+        public Criteria andFeedbackIdIsNull() {
+            addCriterion("feedbackId is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdIsNotNull() {
+            addCriterion("feedbackId is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdEqualTo(String value) {
+            addCriterion("feedbackId =", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdNotEqualTo(String value) {
+            addCriterion("feedbackId <>", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdGreaterThan(String value) {
+            addCriterion("feedbackId >", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdGreaterThanOrEqualTo(String value) {
+            addCriterion("feedbackId >=", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdLessThan(String value) {
+            addCriterion("feedbackId <", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdLessThanOrEqualTo(String value) {
+            addCriterion("feedbackId <=", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdLike(String value) {
+            addCriterion("feedbackId like", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdNotLike(String value) {
+            addCriterion("feedbackId not like", value, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdIn(List<String> values) {
+            addCriterion("feedbackId in", values, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdNotIn(List<String> values) {
+            addCriterion("feedbackId not in", values, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdBetween(String value1, String value2) {
+            addCriterion("feedbackId between", value1, value2, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andFeedbackIdNotBetween(String value1, String value2) {
+            addCriterion("feedbackId not between", value1, value2, "feedbackId");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentIsNull() {
+            addCriterion("content is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentIsNotNull() {
+            addCriterion("content is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentEqualTo(String value) {
+            addCriterion("content =", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentNotEqualTo(String value) {
+            addCriterion("content <>", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentGreaterThan(String value) {
+            addCriterion("content >", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentGreaterThanOrEqualTo(String value) {
+            addCriterion("content >=", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentLessThan(String value) {
+            addCriterion("content <", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentLessThanOrEqualTo(String value) {
+            addCriterion("content <=", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentLike(String value) {
+            addCriterion("content like", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentNotLike(String value) {
+            addCriterion("content not like", value, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentIn(List<String> values) {
+            addCriterion("content in", values, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentNotIn(List<String> values) {
+            addCriterion("content not in", values, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentBetween(String value1, String value2) {
+            addCriterion("content between", value1, value2, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andContentNotBetween(String value1, String value2) {
+            addCriterion("content not between", value1, value2, "content");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlIsNull() {
+            addCriterion("url is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlIsNotNull() {
+            addCriterion("url is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlEqualTo(String value) {
+            addCriterion("url =", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotEqualTo(String value) {
+            addCriterion("url <>", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlGreaterThan(String value) {
+            addCriterion("url >", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlGreaterThanOrEqualTo(String value) {
+            addCriterion("url >=", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlLessThan(String value) {
+            addCriterion("url <", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlLessThanOrEqualTo(String value) {
+            addCriterion("url <=", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlLike(String value) {
+            addCriterion("url like", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotLike(String value) {
+            addCriterion("url not like", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlIn(List<String> values) {
+            addCriterion("url in", values, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotIn(List<String> values) {
+            addCriterion("url not in", values, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlBetween(String value1, String value2) {
+            addCriterion("url between", value1, value2, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotBetween(String value1, String value2) {
+            addCriterion("url not between", value1, value2, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByIsNull() {
+            addCriterion("CreateBy is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByIsNotNull() {
+            addCriterion("CreateBy is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByEqualTo(String value) {
+            addCriterion("CreateBy =", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNotEqualTo(String value) {
+            addCriterion("CreateBy <>", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByGreaterThan(String value) {
+            addCriterion("CreateBy >", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByGreaterThanOrEqualTo(String value) {
+            addCriterion("CreateBy >=", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByLessThan(String value) {
+            addCriterion("CreateBy <", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByLessThanOrEqualTo(String value) {
+            addCriterion("CreateBy <=", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByLike(String value) {
+            addCriterion("CreateBy like", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNotLike(String value) {
+            addCriterion("CreateBy not like", value, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByIn(List<String> values) {
+            addCriterion("CreateBy in", values, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNotIn(List<String> values) {
+            addCriterion("CreateBy not in", values, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByBetween(String value1, String value2) {
+            addCriterion("CreateBy between", value1, value2, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNotBetween(String value1, String value2) {
+            addCriterion("CreateBy not between", value1, value2, "createBy");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameIsNull() {
+            addCriterion("CreateByName is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameIsNotNull() {
+            addCriterion("CreateByName is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameEqualTo(String value) {
+            addCriterion("CreateByName =", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameNotEqualTo(String value) {
+            addCriterion("CreateByName <>", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameGreaterThan(String value) {
+            addCriterion("CreateByName >", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameGreaterThanOrEqualTo(String value) {
+            addCriterion("CreateByName >=", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameLessThan(String value) {
+            addCriterion("CreateByName <", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameLessThanOrEqualTo(String value) {
+            addCriterion("CreateByName <=", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameLike(String value) {
+            addCriterion("CreateByName like", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameNotLike(String value) {
+            addCriterion("CreateByName not like", value, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameIn(List<String> values) {
+            addCriterion("CreateByName in", values, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameNotIn(List<String> values) {
+            addCriterion("CreateByName not in", values, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameBetween(String value1, String value2) {
+            addCriterion("CreateByName between", value1, value2, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateByNameNotBetween(String value1, String value2) {
+            addCriterion("CreateByName not between", value1, value2, "createByName");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeIsNull() {
+            addCriterion("CreateTime is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeIsNotNull() {
+            addCriterion("CreateTime is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeEqualTo(Date value) {
+            addCriterion("CreateTime =", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeNotEqualTo(Date value) {
+            addCriterion("CreateTime <>", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeGreaterThan(Date value) {
+            addCriterion("CreateTime >", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeGreaterThanOrEqualTo(Date value) {
+            addCriterion("CreateTime >=", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeLessThan(Date value) {
+            addCriterion("CreateTime <", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeLessThanOrEqualTo(Date value) {
+            addCriterion("CreateTime <=", value, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeIn(List<Date> values) {
+            addCriterion("CreateTime in", values, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeNotIn(List<Date> values) {
+            addCriterion("CreateTime not in", values, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeBetween(Date value1, Date value2) {
+            addCriterion("CreateTime between", value1, value2, "createTime");
+            return (Criteria) this;
+        }
+
+        public Criteria andCreateTimeNotBetween(Date value1, Date value2) {
+            addCriterion("CreateTime not between", value1, value2, "createTime");
+            return (Criteria) this;
+        }
+    }
+
+    public static class Criteria extends GeneratedCriteria {
+        protected Criteria() {
+            super();
+        }
+    }
+
+    public static class Criterion {
+        private String condition;
+
+        private Object value;
+
+        private Object secondValue;
+
+        private boolean noValue;
+
+        private boolean singleValue;
+
+        private boolean betweenValue;
+
+        private boolean listValue;
+
+        private String typeHandler;
+
+        public String getCondition() {
+            return condition;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+
+        public Object getSecondValue() {
+            return secondValue;
+        }
+
+        public boolean isNoValue() {
+            return noValue;
+        }
+
+        public boolean isSingleValue() {
+            return singleValue;
+        }
+
+        public boolean isBetweenValue() {
+            return betweenValue;
+        }
+
+        public boolean isListValue() {
+            return listValue;
+        }
+
+        public String getTypeHandler() {
+            return typeHandler;
+        }
+
+        protected Criterion(String condition) {
+            super();
+            this.condition = condition;
+            this.typeHandler = null;
+            this.noValue = true;
+        }
+
+        protected Criterion(String condition, Object value, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.typeHandler = typeHandler;
+            if (value instanceof List<?>) {
+                this.listValue = true;
+            } else {
+                this.singleValue = true;
+            }
+        }
+
+        protected Criterion(String condition, Object value) {
+            this(condition, value, null);
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.secondValue = secondValue;
+            this.typeHandler = typeHandler;
+            this.betweenValue = true;
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue) {
+            this(condition, value, secondValue, null);
+        }
+    }
+}

+ 80 - 0
src/main/java/com/bowintek/practice/services/impl/system/FeedbackServiceImpl.java

@@ -0,0 +1,80 @@
+package com.bowintek.practice.services.impl.system;
+
+import com.bowintek.practice.mapper.SysFeedbackMapper;
+import com.bowintek.practice.model.SysFeedback;
+import com.bowintek.practice.model.SysFeedbackExample;
+import com.bowintek.practice.services.service.AccountService;
+import com.bowintek.practice.services.service.FeedbackService;
+import com.bowintek.practice.util.DateUtils;
+import com.bowintek.practice.util.StringUtils;
+import com.bowintek.practice.vo.system.AnnouncementModel;
+import com.bowintek.practice.vo.temp.TempObjectModel;
+import com.bowintek.practice.vo.temp.TempSaveResult;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.Date;
+import java.util.List;
+
+@Service("FeedbackService")
+@Slf4j
+public class FeedbackServiceImpl implements FeedbackService {
+
+    @Autowired
+    private SysFeedbackMapper feedbackMapper;
+    @Autowired
+    private DateUtils dateUtils;
+
+    @Override
+    public PageInfo<SysFeedback>  getFeedbackList(Integer page, Integer rows,String content, String createByName,
+                                             String beginDate,
+                                             String endDate) {
+        PageHelper.startPage(page, rows);
+
+        SysFeedbackExample example = new SysFeedbackExample();
+        SysFeedbackExample.Criteria criteria = example.or();
+        if (!StringUtils.IsNullEmpty(content)) {
+            criteria.andContentLike(content);
+        }
+        if (!StringUtils.IsNullEmpty(createByName)) {
+            criteria.andCreateByNameLike(createByName);
+        }
+        if (!StringUtils.IsNullEmpty(beginDate)) {
+            criteria.andCreateTimeGreaterThan(dateUtils.StrToDate(beginDate, "yyyy-MM-dd"));
+        }
+        if (!StringUtils.IsNullEmpty(endDate)) {
+            criteria.andCreateTimeLessThanOrEqualTo(dateUtils.getDateOfAddDay(dateUtils.StrToDate(endDate, "yyyy-MM-dd"), 1));
+        }
+        example.setOrderByClause("createTime desc");
+        var dataList = feedbackMapper.selectByExample(example);
+        PageInfo<SysFeedback> result = new PageInfo(dataList);
+        return result;
+    }
+
+    @Override
+    public int saveFeedback(SysFeedback dataModel, String userID, String userName) {
+        var dbModel = feedbackMapper.selectByPrimaryKey(dataModel.getFeedbackId());
+        if (dbModel == null) {
+            dataModel.setCreateTime(new Date());
+            dataModel.setCreateBy(userID);
+            dataModel.setCreateByName(userName);
+            feedbackMapper.insert(dataModel);
+        } else {
+            dbModel.setContent(dataModel.getContent());
+            feedbackMapper.updateByPrimaryKeySelective(dbModel);
+        }
+        return 1;
+    }
+    @Override
+    public int delete(List<String> feedbackIdList){
+        SysFeedbackExample example = new SysFeedbackExample();
+        example.or().andFeedbackIdIn(feedbackIdList);
+        return feedbackMapper.deleteByExample(example);
+    }
+}

+ 51 - 0
src/main/java/com/bowintek/practice/services/impl/system/FileServiceImpl.java

@@ -8,6 +8,7 @@ import com.bowintek.practice.model.CfFileExample;
 import com.bowintek.practice.services.service.system.FileService;
 import com.bowintek.practice.util.FtpHelper;
 import com.bowintek.practice.vo.system.FileModel;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.net.ftp.FTP;
 import org.apache.commons.net.ftp.FTPClient;
 import org.apache.commons.net.ftp.FTPFile;
@@ -26,6 +27,7 @@ import java.time.format.DateTimeFormatter;
 import java.util.*;
 
 @Service("FileService")
+@Slf4j
 public class FileServiceImpl implements FileService {
 
     @Autowired
@@ -99,6 +101,55 @@ public class FileServiceImpl implements FileService {
 
         return result;
     }
+    @Override
+    public CfFile uploadToLocal(MultipartFile file, String fileRefID, Integer fileType, String userId, Integer isSingle) throws Exception {
+
+        log.info("开始文件上传:" + file.getOriginalFilename());
+        CfFile cfFile = new CfFile();
+        try {
+            //如果是单文件上传,删除原先数据
+            if (isSingle == 1) {
+                CfFileExample example = new CfFileExample();
+                example.or().andFileRefIDEqualTo(fileRefID);
+                cfFileMapper.deleteByExample(example);
+            }
+            String fileName = file.getOriginalFilename();
+            String fileSuffix = fileName.indexOf(".") >= 0 ? fileName.substring(fileName.lastIndexOf(".")) : "";
+            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+            fileName = df.format(LocalDateTime.now()) + "_" + fileName + this.getFileSuffix(fileSuffix);
+
+
+            cfFile.setFileId(UUID.randomUUID().toString());
+            cfFile.setUserID(userId);
+            cfFile.setFileType(fileType);
+            cfFile.setFileRefID(fileRefID);
+            cfFile.setCreateTime(new Date());
+            cfFile.setFileSuffix(fileName.indexOf(".") >= 0 ? fileName.substring(fileName.lastIndexOf(".")) : "");
+            cfFile.setFileName(fileName);
+
+            String uploadFolderPath = appConfig.uploadfileUrl + "/upload/";
+            log.info("开始文件上传:uploadFolderPath_" + uploadFolderPath);
+            Path dictPath = Paths.get(uploadFolderPath);
+            if (!Files.exists(dictPath)) {
+                Files.createDirectory(dictPath);
+            }
+
+            df = DateTimeFormatter.ofPattern("yyyyMM");
+            String filePath = uploadFolderPath + df.format(LocalDateTime.now()) + "/";
+            dictPath = Paths.get(filePath);
+            if (!Files.exists(dictPath)) {
+                Files.createDirectory(dictPath);
+            }
+            log.info("开始文件上传:filePath_" + filePath+ fileName);
+            File newFile = new File(filePath + fileName);
+            file.transferTo(newFile);
+            cfFile.setFileUrl(df.format(LocalDateTime.now()) + "/" + fileName);
+            cfFileMapper.insert(cfFile);
+        } catch (Exception ex) {
+            logger.info("文件上传出错:" + ex.getMessage());
+        }
+        return cfFile;
+    }
 
     private String getFileSuffix(String fileSuffix) {
         switch (fileSuffix) {

+ 16 - 0
src/main/java/com/bowintek/practice/services/service/FeedbackService.java

@@ -0,0 +1,16 @@
+package com.bowintek.practice.services.service;
+
+import com.bowintek.practice.model.SysFeedback;
+import com.github.pagehelper.PageInfo;
+
+import java.util.List;
+
+public interface FeedbackService {
+    PageInfo<SysFeedback> getFeedbackList(Integer page, Integer rows, String content, String createByName,
+                                          String beginDate,
+                                          String endDate);
+
+    int saveFeedback(SysFeedback dataModel, String userID, String userName);
+
+    int delete(List<String> feedbackIdList);
+}

+ 3 - 1
src/main/java/com/bowintek/practice/services/service/system/FileService.java

@@ -15,7 +15,9 @@ public interface FileService {
 
     CfFile getFileByID(String fileID);
 
-    Integer saveFile(MultipartFile[] files, String fileRefID, Integer fileType, String userId,Integer isSingle) throws Exception;
+    Integer saveFile(MultipartFile[] files, String fileRefID, Integer fileType, String userId, Integer isSingle) throws Exception;
+
+    CfFile uploadToLocal(MultipartFile file, String fileRefID, Integer fileType, String userId, Integer isSingle) throws Exception;
 
     CfFile downFtpFile(String fileId, OutputStream os);
 

+ 1 - 1
src/main/resources/application.yml

@@ -112,7 +112,7 @@ pagehelper:
 appconfig:
   #开发平台设置
   isDev: true
-  uploadfile-url: d:/sitefile
+  uploadfile-url: D:\我的文件\博颖项目\华北油田AI检索\smartsearch\src\main\resources\static\doc
   desKey: MMmmHHss
 
   #ftp配置 192.168.0.51:21@aqfxgk:qwe123

+ 1 - 1
src/main/resources/generatorConfig.xml

@@ -118,6 +118,6 @@
             <columnOverride column="StandardMajorID" javaType="java.lang.Integer" jdbcType="INTEGER" />
             <table schema="" tableName="Sys_Log"><property name="useActualColumnNames" value="true"/></table>
         </table>-->
-        <table schema="" tableName="es_indexField"><property name="useActualColumnNames" value="true"/></table>
+        <table schema="" tableName="sys_feedback"><property name="useActualColumnNames" value="true"/></table>
     </context>
 </generatorConfiguration>

+ 291 - 0
src/main/resources/mapping/CfFileMapper.xml

@@ -0,0 +1,291 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.bowintek.practice.mapper.CfFileMapper">
+  <resultMap id="BaseResultMap" type="com.bowintek.practice.model.CfFile">
+    <id column="fileId" jdbcType="VARCHAR" property="fileId" />
+    <result column="fileName" jdbcType="VARCHAR" property="fileName" />
+    <result column="fileSuffix" jdbcType="VARCHAR" property="fileSuffix" />
+    <result column="fileUrl" jdbcType="VARCHAR" property="fileUrl" />
+    <result column="fileType" jdbcType="INTEGER" property="fileType" />
+    <result column="fileNote" jdbcType="VARCHAR" property="fileNote" />
+    <result column="sFileId" jdbcType="VARCHAR" property="sFileId" />
+    <result column="userID" jdbcType="VARCHAR" property="userID" />
+    <result column="fileRefID" jdbcType="VARCHAR" property="fileRefID" />
+    <result column="createTime" jdbcType="TIMESTAMP" property="createTime" />
+  </resultMap>
+  <sql id="Example_Where_Clause">
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    fileId, fileName, fileSuffix, fileUrl, fileType, fileNote, sFileId, userID, fileRefID, 
+    createTime
+  </sql>
+  <select id="selectByExample" parameterType="com.bowintek.practice.model.CfFileExample" resultMap="BaseResultMap">
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from cf_file
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from cf_file
+    where fileId = #{fileId,jdbcType=VARCHAR}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+    delete from cf_file
+    where fileId = #{fileId,jdbcType=VARCHAR}
+  </delete>
+  <delete id="deleteByExample" parameterType="com.bowintek.practice.model.CfFileExample">
+    delete from cf_file
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="com.bowintek.practice.model.CfFile">
+    insert into cf_file (fileId, fileName, fileSuffix, 
+      fileUrl, fileType, fileNote, 
+      sFileId, userID, fileRefID, 
+      createTime)
+    values (#{fileId,jdbcType=VARCHAR}, #{fileName,jdbcType=VARCHAR}, #{fileSuffix,jdbcType=VARCHAR}, 
+      #{fileUrl,jdbcType=VARCHAR}, #{fileType,jdbcType=INTEGER}, #{fileNote,jdbcType=VARCHAR}, 
+      #{sFileId,jdbcType=VARCHAR}, #{userID,jdbcType=VARCHAR}, #{fileRefID,jdbcType=VARCHAR}, 
+      #{createTime,jdbcType=TIMESTAMP})
+  </insert>
+  <insert id="insertSelective" parameterType="com.bowintek.practice.model.CfFile">
+    insert into cf_file
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="fileId != null">
+        fileId,
+      </if>
+      <if test="fileName != null">
+        fileName,
+      </if>
+      <if test="fileSuffix != null">
+        fileSuffix,
+      </if>
+      <if test="fileUrl != null">
+        fileUrl,
+      </if>
+      <if test="fileType != null">
+        fileType,
+      </if>
+      <if test="fileNote != null">
+        fileNote,
+      </if>
+      <if test="sFileId != null">
+        sFileId,
+      </if>
+      <if test="userID != null">
+        userID,
+      </if>
+      <if test="fileRefID != null">
+        fileRefID,
+      </if>
+      <if test="createTime != null">
+        createTime,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="fileId != null">
+        #{fileId,jdbcType=VARCHAR},
+      </if>
+      <if test="fileName != null">
+        #{fileName,jdbcType=VARCHAR},
+      </if>
+      <if test="fileSuffix != null">
+        #{fileSuffix,jdbcType=VARCHAR},
+      </if>
+      <if test="fileUrl != null">
+        #{fileUrl,jdbcType=VARCHAR},
+      </if>
+      <if test="fileType != null">
+        #{fileType,jdbcType=INTEGER},
+      </if>
+      <if test="fileNote != null">
+        #{fileNote,jdbcType=VARCHAR},
+      </if>
+      <if test="sFileId != null">
+        #{sFileId,jdbcType=VARCHAR},
+      </if>
+      <if test="userID != null">
+        #{userID,jdbcType=VARCHAR},
+      </if>
+      <if test="fileRefID != null">
+        #{fileRefID,jdbcType=VARCHAR},
+      </if>
+      <if test="createTime != null">
+        #{createTime,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="com.bowintek.practice.model.CfFileExample" resultType="java.lang.Long">
+    select count(*) from cf_file
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    update cf_file
+    <set>
+      <if test="row.fileId != null">
+        fileId = #{row.fileId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.fileName != null">
+        fileName = #{row.fileName,jdbcType=VARCHAR},
+      </if>
+      <if test="row.fileSuffix != null">
+        fileSuffix = #{row.fileSuffix,jdbcType=VARCHAR},
+      </if>
+      <if test="row.fileUrl != null">
+        fileUrl = #{row.fileUrl,jdbcType=VARCHAR},
+      </if>
+      <if test="row.fileType != null">
+        fileType = #{row.fileType,jdbcType=INTEGER},
+      </if>
+      <if test="row.fileNote != null">
+        fileNote = #{row.fileNote,jdbcType=VARCHAR},
+      </if>
+      <if test="row.sFileId != null">
+        sFileId = #{row.sFileId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.userID != null">
+        userID = #{row.userID,jdbcType=VARCHAR},
+      </if>
+      <if test="row.fileRefID != null">
+        fileRefID = #{row.fileRefID,jdbcType=VARCHAR},
+      </if>
+      <if test="row.createTime != null">
+        createTime = #{row.createTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    update cf_file
+    set fileId = #{row.fileId,jdbcType=VARCHAR},
+      fileName = #{row.fileName,jdbcType=VARCHAR},
+      fileSuffix = #{row.fileSuffix,jdbcType=VARCHAR},
+      fileUrl = #{row.fileUrl,jdbcType=VARCHAR},
+      fileType = #{row.fileType,jdbcType=INTEGER},
+      fileNote = #{row.fileNote,jdbcType=VARCHAR},
+      sFileId = #{row.sFileId,jdbcType=VARCHAR},
+      userID = #{row.userID,jdbcType=VARCHAR},
+      fileRefID = #{row.fileRefID,jdbcType=VARCHAR},
+      createTime = #{row.createTime,jdbcType=TIMESTAMP}
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="com.bowintek.practice.model.CfFile">
+    update cf_file
+    <set>
+      <if test="fileName != null">
+        fileName = #{fileName,jdbcType=VARCHAR},
+      </if>
+      <if test="fileSuffix != null">
+        fileSuffix = #{fileSuffix,jdbcType=VARCHAR},
+      </if>
+      <if test="fileUrl != null">
+        fileUrl = #{fileUrl,jdbcType=VARCHAR},
+      </if>
+      <if test="fileType != null">
+        fileType = #{fileType,jdbcType=INTEGER},
+      </if>
+      <if test="fileNote != null">
+        fileNote = #{fileNote,jdbcType=VARCHAR},
+      </if>
+      <if test="sFileId != null">
+        sFileId = #{sFileId,jdbcType=VARCHAR},
+      </if>
+      <if test="userID != null">
+        userID = #{userID,jdbcType=VARCHAR},
+      </if>
+      <if test="fileRefID != null">
+        fileRefID = #{fileRefID,jdbcType=VARCHAR},
+      </if>
+      <if test="createTime != null">
+        createTime = #{createTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where fileId = #{fileId,jdbcType=VARCHAR}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.bowintek.practice.model.CfFile">
+    update cf_file
+    set fileName = #{fileName,jdbcType=VARCHAR},
+      fileSuffix = #{fileSuffix,jdbcType=VARCHAR},
+      fileUrl = #{fileUrl,jdbcType=VARCHAR},
+      fileType = #{fileType,jdbcType=INTEGER},
+      fileNote = #{fileNote,jdbcType=VARCHAR},
+      sFileId = #{sFileId,jdbcType=VARCHAR},
+      userID = #{userID,jdbcType=VARCHAR},
+      fileRefID = #{fileRefID,jdbcType=VARCHAR},
+      createTime = #{createTime,jdbcType=TIMESTAMP}
+    where fileId = #{fileId,jdbcType=VARCHAR}
+  </update>
+</mapper>

+ 228 - 0
src/main/resources/mapping/SysFeedbackMapper.xml

@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.bowintek.practice.mapper.SysFeedbackMapper">
+  <resultMap id="BaseResultMap" type="com.bowintek.practice.model.SysFeedback">
+    <id column="feedbackId" jdbcType="VARCHAR" property="feedbackId" />
+    <result column="content" jdbcType="VARCHAR" property="content" />
+    <result column="url" jdbcType="VARCHAR" property="url" />
+    <result column="CreateBy" jdbcType="VARCHAR" property="createBy" />
+    <result column="CreateByName" jdbcType="VARCHAR" property="createByName" />
+    <result column="CreateTime" jdbcType="TIMESTAMP" property="createTime" />
+  </resultMap>
+  <sql id="Example_Where_Clause">
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    feedbackId, content, url, CreateBy, CreateByName, CreateTime
+  </sql>
+  <select id="selectByExample" parameterType="com.bowintek.practice.model.SysFeedbackExample" resultMap="BaseResultMap">
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from sys_feedback
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from sys_feedback
+    where feedbackId = #{feedbackId,jdbcType=VARCHAR}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+    delete from sys_feedback
+    where feedbackId = #{feedbackId,jdbcType=VARCHAR}
+  </delete>
+  <delete id="deleteByExample" parameterType="com.bowintek.practice.model.SysFeedbackExample">
+    delete from sys_feedback
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="com.bowintek.practice.model.SysFeedback">
+    insert into sys_feedback (feedbackId, content, url, 
+      CreateBy, CreateByName, CreateTime
+      )
+    values (#{feedbackId,jdbcType=VARCHAR}, #{content,jdbcType=VARCHAR}, #{url,jdbcType=VARCHAR}, 
+      #{createBy,jdbcType=VARCHAR}, #{createByName,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}
+      )
+  </insert>
+  <insert id="insertSelective" parameterType="com.bowintek.practice.model.SysFeedback">
+    insert into sys_feedback
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="feedbackId != null">
+        feedbackId,
+      </if>
+      <if test="content != null">
+        content,
+      </if>
+      <if test="url != null">
+        url,
+      </if>
+      <if test="createBy != null">
+        CreateBy,
+      </if>
+      <if test="createByName != null">
+        CreateByName,
+      </if>
+      <if test="createTime != null">
+        CreateTime,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="feedbackId != null">
+        #{feedbackId,jdbcType=VARCHAR},
+      </if>
+      <if test="content != null">
+        #{content,jdbcType=VARCHAR},
+      </if>
+      <if test="url != null">
+        #{url,jdbcType=VARCHAR},
+      </if>
+      <if test="createBy != null">
+        #{createBy,jdbcType=VARCHAR},
+      </if>
+      <if test="createByName != null">
+        #{createByName,jdbcType=VARCHAR},
+      </if>
+      <if test="createTime != null">
+        #{createTime,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="com.bowintek.practice.model.SysFeedbackExample" resultType="java.lang.Long">
+    select count(*) from sys_feedback
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    update sys_feedback
+    <set>
+      <if test="row.feedbackId != null">
+        feedbackId = #{row.feedbackId,jdbcType=VARCHAR},
+      </if>
+      <if test="row.content != null">
+        content = #{row.content,jdbcType=VARCHAR},
+      </if>
+      <if test="row.url != null">
+        url = #{row.url,jdbcType=VARCHAR},
+      </if>
+      <if test="row.createBy != null">
+        CreateBy = #{row.createBy,jdbcType=VARCHAR},
+      </if>
+      <if test="row.createByName != null">
+        CreateByName = #{row.createByName,jdbcType=VARCHAR},
+      </if>
+      <if test="row.createTime != null">
+        CreateTime = #{row.createTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    update sys_feedback
+    set feedbackId = #{row.feedbackId,jdbcType=VARCHAR},
+      content = #{row.content,jdbcType=VARCHAR},
+      url = #{row.url,jdbcType=VARCHAR},
+      CreateBy = #{row.createBy,jdbcType=VARCHAR},
+      CreateByName = #{row.createByName,jdbcType=VARCHAR},
+      CreateTime = #{row.createTime,jdbcType=TIMESTAMP}
+    <if test="example != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="com.bowintek.practice.model.SysFeedback">
+    update sys_feedback
+    <set>
+      <if test="content != null">
+        content = #{content,jdbcType=VARCHAR},
+      </if>
+      <if test="url != null">
+        url = #{url,jdbcType=VARCHAR},
+      </if>
+      <if test="createBy != null">
+        CreateBy = #{createBy,jdbcType=VARCHAR},
+      </if>
+      <if test="createByName != null">
+        CreateByName = #{createByName,jdbcType=VARCHAR},
+      </if>
+      <if test="createTime != null">
+        CreateTime = #{createTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where feedbackId = #{feedbackId,jdbcType=VARCHAR}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.bowintek.practice.model.SysFeedback">
+    update sys_feedback
+    set content = #{content,jdbcType=VARCHAR},
+      url = #{url,jdbcType=VARCHAR},
+      CreateBy = #{createBy,jdbcType=VARCHAR},
+      CreateByName = #{createByName,jdbcType=VARCHAR},
+      CreateTime = #{createTime,jdbcType=TIMESTAMP}
+    where feedbackId = #{feedbackId,jdbcType=VARCHAR}
+  </update>
+</mapper>

BIN
src/main/resources/static/doc/upload/202404/20240423171331_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png


BIN
src/main/resources/static/doc/upload/202404/20240423171745_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png


BIN
src/main/resources/static/doc/upload/202404/20240423172031_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png


BIN
src/main/resources/static/doc/upload/202404/20240423172543_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png


BIN
src/main/resources/static/doc/upload/202404/20240423173330_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png


BIN
src/main/resources/static/doc/upload/202404/20240424102822_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png


BIN
src/main/resources/static/doc/upload/202404/20240424103050_jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png


BIN
src/main/resources/static/excel/07f4a177-47c3-41c3-b2f2-c492e602a354.xlsx


BIN
src/main/resources/static/excel/10b9f2a0-afec-40d6-8d5e-caa1d2a40df5.xlsx


BIN
src/main/resources/static/excel/13f3796d-b782-4f90-95e8-70faa1340764.xlsx


BIN
src/main/resources/static/excel/1419b5c6-990e-40c2-bae3-81cb56b50a99.xlsx


BIN
src/main/resources/static/excel/1d6de2dd-7d0d-45b9-a653-da3e470c9f59.xlsx


BIN
src/main/resources/static/excel/20c2505f-077d-4212-ac4c-bd284914910a.xlsx


BIN
src/main/resources/static/excel/3299b18b-b315-4856-8084-c69464fe83c9.xlsx


BIN
src/main/resources/static/excel/3679c85b-2cd0-4f4f-9ed7-c1217a214d39.xlsx


BIN
src/main/resources/static/excel/39d07c51-1fc8-429a-9ce4-5ad1b1f0d29d.xlsx


BIN
src/main/resources/static/excel/53d24279-b7bc-4f87-b2b6-534f44690d14.xlsx


BIN
src/main/resources/static/excel/5e506489-2f8b-4ab6-a803-1c6152a9af60.xlsx


BIN
src/main/resources/static/excel/84d708ce-2654-4f4a-94f7-31409b57247e.xlsx


BIN
src/main/resources/static/excel/88bcd5ea-8d99-4239-a4a2-3a51af92240f.xlsx


BIN
src/main/resources/static/excel/aeea8256-ed27-4ed0-8a87-81e37e818f4a.xlsx


BIN
src/main/resources/static/excel/c0456169-8886-4c71-afb4-4c633198d41f.xlsx


BIN
src/main/resources/static/excel/d6ce0377-86ff-405b-8c98-643764520b4f.xlsx


BIN
src/main/resources/static/excel/d841c3e9-5086-43a4-9cb5-51e1c6556276.xlsx


BIN
src/main/resources/static/excel/e92a4b46-fe84-4145-b568-4c5a4dc9fd3f.xlsx


BIN
src/main/resources/static/excel/fc5b18d3-802e-466f-8c2f-8b3c9b2344f0.xlsx


+ 1 - 1
target/classes/application.yml

@@ -112,7 +112,7 @@ pagehelper:
 appconfig:
   #开发平台设置
   isDev: true
-  uploadfile-url: d:/sitefile
+  uploadfile-url: D:\我的文件\博颖项目\华北油田AI检索\smartsearch\src\main\resources\static\doc
   desKey: MMmmHHss
 
   #ftp配置 192.168.0.51:21@aqfxgk:qwe123

BIN
target/classes/com/bowintek/practice/controller/system/FileController.class


BIN
target/classes/com/bowintek/practice/services/impl/system/FileServiceImpl.class


BIN
target/classes/com/bowintek/practice/services/service/system/FileService.class


+ 1 - 1
target/classes/generatorConfig.xml

@@ -118,6 +118,6 @@
             <columnOverride column="StandardMajorID" javaType="java.lang.Integer" jdbcType="INTEGER" />
             <table schema="" tableName="Sys_Log"><property name="useActualColumnNames" value="true"/></table>
         </table>-->
-        <table schema="" tableName="es_indexField"><property name="useActualColumnNames" value="true"/></table>
+        <table schema="" tableName="sys_feedback"><property name="useActualColumnNames" value="true"/></table>
     </context>
 </generatorConfiguration>

+ 38 - 5
vue/package-lock.json

@@ -3911,6 +3911,11 @@
         }
       }
     },
+    "base64-arraybuffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+      "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
+    },
     "base64-js": {
       "version": "1.5.1",
       "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
@@ -5212,6 +5217,14 @@
       "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==",
       "dev": true
     },
+    "css-line-break": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
+      "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+      "requires": {
+        "utrie": "^1.0.2"
+      }
+    },
     "css-loader": {
       "version": "6.7.1",
       "resolved": "https://registry.npmmirror.com/css-loader/-/css-loader-6.7.1.tgz",
@@ -7493,6 +7506,15 @@
         }
       }
     },
+    "html2canvas": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz",
+      "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+      "requires": {
+        "css-line-break": "^2.1.0",
+        "text-segmentation": "^1.0.3"
+      }
+    },
     "htmlparser2": {
       "version": "8.0.1",
       "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-8.0.1.tgz",
@@ -12880,6 +12902,14 @@
       "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==",
       "dev": true
     },
+    "text-segmentation": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz",
+      "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+      "requires": {
+        "utrie": "^1.0.2"
+      }
+    },
     "text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz",
@@ -13438,6 +13468,14 @@
       "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
       "dev": true
     },
+    "utrie": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz",
+      "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+      "requires": {
+        "base64-arraybuffer": "^1.0.2"
+      }
+    },
     "uuid": {
       "version": "9.0.1",
       "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz",
@@ -13705,11 +13743,6 @@
         "is-plain-object": "5.0.0"
       }
     },
-    "vue3-pdf-app": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmmirror.com/vue3-pdf-app/-/vue3-pdf-app-1.0.3.tgz",
-      "integrity": "sha512-qegWTIF4wYKiocZ3KreB70wRXhqSdXWbdERDyyKzT7d5PbjKbS9tD6vaKkCqh3PzTM84NyKPYrQ3iuwJb60YPQ=="
-    },
     "w3c-keyname": {
       "version": "2.2.8",
       "resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz",

+ 1 - 0
vue/package.json

@@ -51,6 +51,7 @@
     "dayjs": "~1.11.5",
     "echarts": "~5.4.3",
     "file-saver": "~2.0.5",
+    "html2canvas": "^1.4.1",
     "lodash-es": "~4.17.21",
     "mitt": "~3.0.0",
     "mockjs": "~1.1.0",

+ 1 - 1
vue/public/appconfig.json

@@ -1,5 +1,5 @@
 {
   "isDev": true,
   "SSOLoginUrl": "",
-  "huabeiHost": "http://10.73.178.206:8077/"
+  "huabeiHost": "http://localhost:8077/"
 }

+ 26 - 0
vue/src/api/system/file/index.ts

@@ -52,6 +52,20 @@ export function getFileBase64(params: any) {
   );
 }
 
+
+export function getPicBase64(params: any) {
+  return request<object>(
+    {
+      url: 'system/file/getPicBase64',
+      method: 'get',
+      params: params,
+    },
+    {
+      isNew: true,
+    },
+  );
+}
+
 export async function getFileByte(params: any) {
   return request<object>(
     {
@@ -67,3 +81,15 @@ export async function getFileByte(params: any) {
   );
 }
 
+export function uploadSingleFile(data: any) {
+  return request<object>(
+    {
+      url: 'system/file/uploadSingleFile',
+      method: 'post',
+      data: data,
+    },
+    {
+      isNew: true,
+    },
+  );
+}

BIN
vue/src/assets/images/fk.jpg


+ 179 - 0
vue/src/layout/tabs/feedback.vue

@@ -0,0 +1,179 @@
+<template>
+  <Modal style="width:70%;" okText="提交" v-model:visible="visible" title="反馈" @ok="handleOk()" @cancel="handleCancel()">
+    <div>
+      <Form ref="modalFormRef" :model="dataModel" autocomplete="off" id="appAddModel">
+        <a-form-item label=" 问题描述或建议" :label-col="{span:24}" name="content"
+                     :rules="[{ required: true, message: '问题描述或建议!' }]">
+          <a-textarea :rows="5" v-model:value="dataModel.content" class="form-input" placeholder="请先阐明问题,然后在发送反馈"/>
+        </a-form-item>
+        <a-form-item label="上传图片" labelAlign="left" :label-col="{span:24}" name="iconId" extra="图片不能超过2MB">
+          <div class="clearfix">
+            <a-upload
+              v-model:file-list="fileList"
+              :before-upload="picUpload"
+              list-type="picture-card"
+              @preview="handlePreview"
+            >
+              <div v-if="fileList.length < 8">
+                <plus-outlined/>
+                <div style="margin-top: 8px">上传</div>
+              </div>
+            </a-upload>
+            <a-modal v-model:visible="previewVisible" :title="previewTitle" :footer="null" @cancel="uploadCancel"
+                     style="z-index: 999;">
+              <img style="width: 100%" :src="previewImage"/>
+            </a-modal>
+          </div>
+        </a-form-item>
+      </Form>
+    </div>
+  </Modal>
+</template>
+
+<script setup lang="ts">
+import {Form, Modal} from 'ant-design-vue';
+import type {FormInstance, UploadProps} from 'ant-design-vue';
+import {ref} from "vue";
+import {CloudUploadOutlined, AndroidOutlined} from "@ant-design/icons-vue";
+import {message} from "ant-design-vue";
+import Button from "@/components/basic/button/button.vue";
+import {upload} from '@/api/system/file';
+import {v4 as uuidv4} from 'uuid';
+import {getConfig} from "@/utils/config";
+import {postData, save} from '@/api/common';
+
+defineOptions({
+  name: 'feedbackModal',
+  inheritAttrs: false,
+  components: {
+    Form, Modal, CloudUploadOutlined, AndroidOutlined, Button
+  }
+});
+
+const modalFormRef = ref<FormInstance>();
+const visible = ref<boolean>(false);
+const isEdit = ref<boolean>(false);
+const spinning = ref<boolean>(false);
+const dataModel = ref();
+const fileList = ref<any[]>([]);
+
+const show = () => {
+  dataModel.value = {
+    feedbackId: uuidv4(),
+    content: '',
+    url: ''
+  };
+  fileList.value = [];
+  visible.value = true;
+};
+defineExpose({show});
+
+function getBase64(file: File) {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.readAsDataURL(file);
+    reader.onload = () => resolve(reader.result);
+    reader.onerror = error => reject(error);
+  });
+}
+
+const previewVisible = ref(false);
+const previewImage = ref('');
+const previewTitle = ref('');
+const huabeiHost = ref('');
+getConfig().then((res: any) => {
+  huabeiHost.value = res.huabeiHost;
+})
+
+const picUpload = file => {
+  const isAccept = "'.png,.jpeg,.jpg,.gif,.webp".indexOf(file.name.slice(file.name.lastIndexOf('.'))) > -1;
+  if (!isAccept) {
+    message.error(`${file.name} 不是规定的图片类型文件`);
+    return false;
+  }
+  const isLt2M = file.size / 1024 / 1024 < 2;
+  if (!isLt2M) {
+    message.error('预览图片大小不能超过2MB!');
+    return false;
+  }
+
+  const formData = new FormData();
+  formData.append('files', file as any);
+  formData.append("fileRefId", dataModel.value.feedbackId);
+  formData.append("fileType", "1");
+  formData.append("isSingle", "0");
+
+  upload(formData).then(curFile => {
+    if (curFile) {
+      console.log("curPicInfo", curFile);
+      fileList.value.splice(fileList.value.length - 1, 1);
+      fileList.value.push({
+        uid: curFile.fileId,
+        name: file.name,
+        status: 'done',
+        url: huabeiHost.value + 'doc/upload/' + curFile.fileUrl,
+      });
+      message.success('预览图片上传成功.');
+    }
+  });
+};
+const uploadCancel = () => {
+  previewVisible.value = false;
+  previewTitle.value = '';
+};
+const handlePreview = async (file: UploadProps['fileList'][number]) => {
+  if (!file.url && !file.preview) {
+    file.preview = (await getBase64(file.originFileObj)) as string;
+  }
+  previewImage.value = file.url || file.preview;
+  previewVisible.value = true;
+  previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
+};
+const handleOk = () => {
+  if (modalFormRef.value == undefined) {
+    return false;
+  }
+  modalFormRef.value?.validate().then(() => {
+    dataModel.value.url = window.location.href;
+    postData('/system/feedback/saveFeedback', dataModel.value).then(result => {
+      if (result) {
+        message.info("已成功反馈您的问题。");
+        visible.value = false;
+      }
+    })
+  });
+}
+const handleCancel = () => {
+
+}
+</script>
+
+<style>
+.form-input {
+  width: 85%;
+}
+
+.noPackage {
+  width: 100px;
+  height: 100px;
+  border: 1px gray dashed;
+  text-align: center;
+  padding-top: 10px;
+  background-color: #f0f0f0;
+}
+
+.hasPackage {
+  width: 100px;
+  height: 100px;
+  border: 1px gray dashed;
+  text-align: center;
+  padding-top: 10px;
+  background-color: white;
+}
+
+.noPackage svg, .hasPackage svg {
+  width: 60px;
+  height: 60px;
+  color: #999;
+}
+</style>

+ 25 - 6
vue/src/layout/tabs/tabs-view.vue

@@ -12,7 +12,7 @@
         <template #tab>
           <Dropdown :trigger="['contextmenu']">
             <div style="display: inline-block">
-              <component :is="$antIcons[pageItem.meta?.icon]" />
+              <component :is="$antIcons[pageItem.meta?.icon]"/>
               <TitleI18n :title="pageItem.meta?.title"/>
             </div>
             <template #overlay>
@@ -79,6 +79,9 @@
       </template>
     </Tabs>
     <div class="tabs-view-content">
+      <div class="sys-feedback" @click="screenShot">
+        <img src="~@/assets/images/fk.jpg" title="反馈问题"/>
+      </div>
       <router-view v-slot="{ Component }">
         <template v-if="Component">
           <transition :duration="100"
@@ -92,14 +95,14 @@
         </template>
       </router-view>
     </div>
+    <FeedbackModal ref="feedbackModalRef"></FeedbackModal>
   </div>
 </template>
 
 <script setup lang="ts">
-import {computed, unref, watch} from 'vue';
+import {computed, unref, watch,ref} from 'vue';
 import {useRoute, useRouter} from 'vue-router';
 import {
-  DownOutlined,
   ReloadOutlined,
   CloseOutlined,
   VerticalRightOutlined,
@@ -115,6 +118,7 @@ import {useTabsViewStore, blackList} from '@/store/modules/tabsView';
 import {useKeepAliveStore} from '@/store/modules/keepAlive';
 import {REDIRECT_NAME} from '@/router/constant';
 import {TitleI18n} from '@/components/basic/title-i18n';
+import FeedbackModal from "./feedback.vue";
 
 type RouteItem = Omit<RouteLocation, 'matched' | 'redirectedFrom'>;
 
@@ -122,6 +126,7 @@ const route = useRoute();
 const router = useRouter();
 const tabsViewStore = useTabsViewStore();
 const keepAliveStore = useKeepAliveStore();
+const feedbackModalRef = ref();
 
 const handleTabChanged = (a) => {
   console.log(a);
@@ -232,6 +237,10 @@ const closeAll = () => {
   tabsViewStore.closeAllTabs();
   router.replace('/');
 };
+
+const screenShot = async () => {
+  feedbackModalRef.value.show();
+}
 </script>
 
 <style lang="less" scoped>
@@ -252,7 +261,7 @@ const closeAll = () => {
 .tabs-view {
   border-top: 1px solid #f6f8f9;
 
-  .ant-tabs-top{
+  .ant-tabs-top {
     box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
     margin-bottom: 5px;
   }
@@ -265,8 +274,8 @@ const closeAll = () => {
       user-select: none;
     }
 
-    .ant-tabs-nav:before{
-      border:none;
+    .ant-tabs-nav:before {
+      border: none;
     }
 
     .ant-tabs-tabpane {
@@ -336,6 +345,16 @@ const closeAll = () => {
     height: calc(100vh - 170px);
     padding: 10px;
     overflow: auto;
+    position: relative;
+  }
+
+  .sys-feedback {
+    position: fixed;
+    right: 10px;
+    bottom: 30px;
+    width: 55px;
+    z-index: 99;
+    cursor: pointer;
   }
 }
 </style>

+ 1 - 0
vue/src/router/asyncModules/system.ts

@@ -8,4 +8,5 @@ export default {
   'views/log': () => import('@/views/system/log/index.vue'),
   'syssetting/userslist': () => import( '@/views/system/users/index.vue'),
   'syssetting/usersEdit':()=> import( '@/views/system/users/index.vue'),
+  'views/feedback':()=> import( '@/views/system/feedback/index.vue')
 };

+ 183 - 0
vue/src/views/system/feedback/index.vue

@@ -0,0 +1,183 @@
+<template>
+  <div class="card-search">
+    <a-form
+      ref="formRef"
+      name="advanced_search"
+      class="ant-advanced-search-form"
+      :model="formState"
+      @finish="onFinish"
+    >
+      <a-row :gutter="24">
+        <a-col :span="6">
+          <a-form-item
+            name="studentCode"
+            label="反馈人"
+            :label-col="{span:6}">
+            <a-input v-model:value="formState.createByName" style="width: 200px"></a-input>
+          </a-form-item>
+        </a-col>
+        <a-col :span="8">
+          <a-form-item label="反馈时间区间" :label-col="{span:8}" name="name">
+            <a-range-picker format="YYYY-MM-DD" :placeholder="['开始时间', '结束时间']" @change="onRangeChange"/>
+          </a-form-item>
+        </a-col>
+        <a-col :span="6" style="text-align: left">
+          <a-button type="primary" html-type="submit" @click="onFinish">查询</a-button>
+          <a-button style="margin: 0 8px" @click="() => {formRef.resetFields();loadData()}">重置</a-button>
+        </a-col>
+      </a-row>
+      <a-row>
+        <a-col :span="24" style="text-align: right">
+          <a-popconfirm placement="leftTop"
+                        title="是否删除数据?"
+                        @confirm="onDelete()">
+            <a-button type="primary" style="margin: 0 8px" html-type="button">删除</a-button>
+          </a-popconfirm>
+        </a-col>
+      </a-row>
+    </a-form>
+    <div class="search-result-list">
+      <a-table :columns="columns" :data-source="data" :pagination="pagination"
+               :loading="loading"
+               :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+               @change="handleTableChange" :row-key="record=>record.feedbackId"
+               bordered>
+        <template #bodyCell="{ column,record }">
+          <template v-if="column.key === 'operation'">
+            <a-button type="link" size="small" @click="edit(record)">查看
+            </a-button>
+          </template>
+        </template>
+      </a-table>
+    </div>
+    <viewModal ref="modalRef" ></viewModal>
+  </div>
+</template>
+
+<script lang="ts">
+import {reactive, ref, defineComponent, computed} from 'vue';
+import type {FormInstance} from 'ant-design-vue';
+import type {TableColumnsType, TableProps} from 'ant-design-vue';
+import {get, postdel} from '@/api/common';
+import {message} from "ant-design-vue";
+import dayjs from "dayjs";
+import {DownOutlined, UpOutlined} from "@ant-design/icons-vue";
+import {getPaginationTotalTitle} from "@/utils/common";
+import viewModal from "./view.vue";
+
+export default defineComponent({
+  name: 'feedback-list',
+  components: {DownOutlined, UpOutlined, viewModal},
+  setup() {
+
+    const expand = ref(false);
+    const formRef = ref<FormInstance>();
+    const selectedRowKeys = ref([]);
+    const modalRef = ref();
+
+    const formState = reactive({
+      page: 1, rows: 10, endDate: '',
+      beginDate: '',
+      createByName: '', total: 0,
+    });
+
+    const columns: TableColumnsType = [
+      {
+        title: '序号',
+        width: 80,
+        dataIndex: 'index',
+        key: 'index',
+        align: "center",
+        customRender: ({index}) => {
+          return `${index + 1}`;
+        }
+      },
+      {title: '问题描述或建议', dataIndex: 'content', key: '1',},
+      {title: '反馈人', dataIndex: 'createByName', key: '2', width: 80, align: "center"},
+      {
+        title: '反馈时间', dataIndex: 'createTime', key: '1', width: 120, customRender: ({record}) =>
+          record.createTime == null ? "" :
+            dayjs(record.createTime).format('YYYY-MM-DD')
+      },
+      {
+        title: '操作', key: 'operation', width: 60, align: "center"
+      },
+    ];
+    const onRangeChange = (dateString) => {
+      formState.beginDate = dateString ? dateString[0].format("YYYY-MM-DD") : '';
+      formState.endDate = dateString ? dateString[1].format("YYYY-MM-DD") : '';
+      loadData();
+    };
+    const data = ref([]);
+    const pagination = computed(() => ({
+      total: formState.total,
+      current: formState.page,
+      pageSize: formState.rows,
+      showSizeChanger: true,
+      showTotal: total => getPaginationTotalTitle(total)
+    }));
+    const loading = ref(false);
+
+    const handleTableChange: TableProps['onChange'] = (
+      pag: { pageSize: number; current: number },
+    ) => {
+      formState.page = pag.current;
+      formState.rows = pag.pageSize;
+      loadData();
+    };
+
+    const onFinish = () => {
+      loadData();
+    }
+
+    const loadData = async function () {
+      loading.value = true;
+      const result: any = await get('system/feedback/getFeedbackList', formState);
+
+      data.value = result.list;
+      formState.total = result.total;
+      loading.value = false;
+    }
+    const onDelete = () => {
+      if (selectedRowKeys.value.length <= 0) {
+        message.warning('请选择需要删除的数据!');
+        return false;
+      }
+      postdel('system/feedback/delete', selectedRowKeys.value).then(() => {
+        loadData();
+      })
+    };
+
+    const dicModalClosed = (d) => {
+      if (d) {
+        loadData();
+      }
+    }
+    const edit = (record) => {
+      modalRef.value.show(record);
+    };
+
+    const onSelectChange = (keys: any) => {
+      selectedRowKeys.value = keys;
+    };
+
+    return {
+      formRef,
+      expand,
+      data,
+      loadData, loading, selectedRowKeys,
+      onSelectChange, onRangeChange,
+      formState,
+      columns,
+      pagination, modalRef,
+      edit, dicModalClosed,
+      handleTableChange,
+      onFinish,
+      onDelete
+    };
+  },
+  created() {
+    this.loadData();
+  }
+});
+</script>

+ 109 - 0
vue/src/views/system/feedback/view.vue

@@ -0,0 +1,109 @@
+<template>
+  <Modal style="width:50%;" v-model:visible="visible" title="查看反馈" :footer="null" @cancel="visible=false">
+    <div>
+      <Form ref="modalFormRef" :model="dataModel" autocomplete="off">
+        <a-form-item label="问题描述或建议" :label-col="{span:24}" name="content">
+          {{ dataModel.content }}
+        </a-form-item>
+        <a-form-item label="上传图片" labelAlign="left" :label-col="{span:24}" name="iconId" extra="图片不能超过2MB">
+          <div class="clearfix">
+            <a-upload
+              v-model:file-list="fileList"
+              list-type="picture-card"
+              @preview="handlePreview"
+              :showUploadList="{ showRemoveIcon: false }"
+            >
+            </a-upload>
+            <a-modal v-model:visible="previewVisible" :title="previewTitle" :footer="null"
+                     @cancel="previewVisible=false"
+                     style="z-index: 999;">
+              <img style="width: 100%" :src="previewImage"/>
+            </a-modal>
+          </div>
+        </a-form-item>
+        <a-form-item label="反馈时间" :label-col="{span:24}" name="content">
+          {{ dayjs(dataModel.createTime).format('YYYY-MM-DD') }}
+        </a-form-item>
+        <a-form-item label="反馈人" :label-col="{span:24}" name="content">
+          {{ dataModel.createByName }}
+        </a-form-item>
+      </Form>
+    </div>
+  </Modal>
+</template>
+
+<script setup lang="ts">
+import {Form, Modal} from 'ant-design-vue';
+import type {FormInstance, UploadProps} from 'ant-design-vue';
+import {ref} from "vue";
+import {CloudUploadOutlined, AndroidOutlined} from "@ant-design/icons-vue";
+import dayjs from "dayjs";
+import Button from "@/components/basic/button/button.vue";
+import {getConfig} from "@/utils/config";
+import {get, save} from '@/api/common';
+
+defineOptions({
+  name: 'feedbackViewModal',
+  inheritAttrs: false,
+  components: {
+    Form, Modal, CloudUploadOutlined, AndroidOutlined, Button
+  }
+});
+
+const modalFormRef = ref<FormInstance>();
+const visible = ref<boolean>(false);
+const isEdit = ref<boolean>(false);
+const spinning = ref<boolean>(false);
+const dataModel = ref({
+  feedbackId: '',
+  content: '',
+  url: ''
+});
+
+
+function getBase64(file: File) {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.readAsDataURL(file);
+    reader.onload = () => resolve(reader.result);
+    reader.onerror = error => reject(error);
+  });
+}
+
+const previewVisible = ref(false);
+const previewImage = ref('');
+const previewTitle = ref('');
+const huabeiHost = ref('');
+getConfig().then((res: any) => {
+  huabeiHost.value = res.huabeiHost;
+})
+const fileList = ref<any[]>([]);
+
+const handlePreview = async (file: UploadProps['fileList'][number]) => {
+  if (!file.url && !file.preview) {
+    file.preview = (await getBase64(file.originFileObj)) as string;
+  }
+  previewImage.value = file.url || file.preview;
+  previewVisible.value = true;
+  previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
+};
+const show = (row) => {
+  dataModel.value = row;
+  fileList.value = [];
+  get('system/file/getList', {fileRefID: dataModel.value.feedbackId}).then(data => {
+    if (!data) {
+      return;
+    }
+    data.forEach(curFile => {
+      fileList.value.push({
+        uid: curFile.fileId,
+        name: curFile.name,
+        status: 'done',
+        url: huabeiHost.value + 'doc/upload/' + curFile.fileUrl,
+      });
+    });
+  })
+  visible.value = true;
+};
+defineExpose({show});
+</script>