Explorar o código

feat(service): 权限限制

Go %!s(int64=4) %!d(string=hai) anos
pai
achega
ce3a540a77

+ 7 - 4
front/project/www/components/Login/index.js

@@ -120,6 +120,7 @@ export default class Login extends Component {
   scanLogin(code) {
     User.loginWechat(code, true, false)
       .then(result => {
+        this.needScan = false;
         if (result.bindMobile) {
           this.close();
         } else {
@@ -127,6 +128,7 @@ export default class Login extends Component {
         }
       })
       .catch(err => {
+        this.needScan = true;
         if (err.message !== '登录失败') {
           asyncSMessage(err.message, 'error');
         }
@@ -136,9 +138,11 @@ export default class Login extends Component {
   scanBind(code) {
     User.loginWechat(code, false, false)
       .then(() => {
+        this.needScan = false;
         this.close();
       })
       .catch(() => {
+        this.needScan = true;
         this.changeType(BIND_WX_ERROR);
       });
   }
@@ -215,13 +219,12 @@ export default class Login extends Component {
       });
   }
 
-  changeType(type) {
+  changeType(nextType) {
     let { scanNumber } = this.state;
-    if (type === LOGIN_WX || type === BIND_WX) {
-      this.needScan = true;
+    if (nextType === LOGIN_WX || nextType === BIND_WX) {
       scanNumber += 1;
     }
-    this.setState({ scanNumber, type, empty: {}, mobileError: '', emailError: '', validError: '', data: { area: MobileArea[0].value } });
+    this.setState({ scanNumber, type: nextType, empty: {}, mobileError: '', emailError: '', validError: '', data: { area: MobileArea[0].value } });
   }
 
   render() {

+ 5 - 3
server/gateway-api/src/main/java/com/qxgmat/controller/api/CourseController.java

@@ -19,6 +19,7 @@ import com.qxgmat.data.relation.entity.UserPreviewPaperRelation;
 import com.qxgmat.dto.extend.*;
 import com.qxgmat.dto.request.*;
 import com.qxgmat.dto.response.*;
+import com.qxgmat.help.PdfHelp;
 import com.qxgmat.help.ShiroHelp;
 import com.qxgmat.service.UserCollectExperienceService;
 import com.qxgmat.service.UserNoteCourseService;
@@ -45,6 +46,9 @@ public class CourseController {
     private ShiroHelp shiroHelp;
 
     @Autowired
+    private PdfHelp pdfHelp;
+
+    @Autowired
     private CommentService commentService;
 
     @Autowired
@@ -279,10 +283,8 @@ public class CourseController {
                 dto.setAnswerNumber(answerNumber);
 
                 // 签名信息:同pdfHelp
-
+                dto.setWaters(pdfHelp.getUserWater(user));
             }
-
-
         }
         return ResponseHelp.success(dto);
     }

+ 58 - 22
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -146,6 +146,9 @@ public class MyController {
     private UserMessageService userMessageService;
 
     @Autowired
+    private UserCourseService userCourseService;
+
+    @Autowired
     private UserCourseRecordService userCourseRecordService;
 
     @Autowired
@@ -2204,9 +2207,38 @@ public class MyController {
         return ResponseHelp.success(pr);
     }
 
+    @RequestMapping(value = "/download/course", method = RequestMethod.GET)
+    @ApiOperation(value = "获取视频", httpMethod = "GET")
+    public void courseDownload(@RequestParam(required = true) Integer id, HttpServletRequest request, HttpServletResponse response){
+        User user = (User) shiroHelp.getLoginUser();
+        CourseNo courseNo = courseNoService.get(id);
+        if (!userCourseService.hasService(user.getId(), courseNo.getCourseId())){
+            throw new AuthException("未授权");
+        }
+        try {
+            String resource = courseNo.getResource();
+//            String fileName = pdfHelp.generatePdfImage(user, resource, false);
+//            String fileUrl = pdfHelp.getOfflineUrl(fileName);
+            response.setHeader("content-disposition","attachment;filename="+Tools.stringMD5(resource)+resource.substring(resource.lastIndexOf(".")));
+            response.setHeader("content-type", "application/octet-stream");
+            response.setHeader("X-Accel-Redirect", resource);
+//            FileInputStream fileInputStream = new FileInputStream(fileName);
+//            ServletOutputStream outputStream = response.getOutputStream();
+//            //输出
+//            int len = 1;
+//            byte[] bs = new byte[1024];
+//            while((len = fileInputStream.read(bs)) != -1){
+//                outputStream.write(bs, 0, len);
+//            }
+//            fileInputStream.close();
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+        }
+    }
+
     @RequestMapping(value = "/download/data", method = RequestMethod.GET)
     @ApiOperation(value = "获取资料", httpMethod = "GET")
-    public void pdfDownLoad(@RequestParam(required = true) Integer id, HttpServletRequest request, HttpServletResponse response){
+    public void dataDownload(@RequestParam(required = true) Integer id, HttpServletRequest request, HttpServletResponse response){
         User user = (User) shiroHelp.getLoginUser();
         CourseData courseData = courseDataService.get(id);
         if (!userOrderRecordService.hasData(user.getId(), courseData.getId())){
@@ -2215,17 +2247,19 @@ public class MyController {
         try {
             String resource = courseData.getResource();
             String fileName = pdfHelp.generatePdfImage(user, resource, false);
-            FileInputStream fileInputStream = new FileInputStream(fileName);
-            ServletOutputStream outputStream = response.getOutputStream();
-            response.setHeader("content-disposition","attachment;filename="+fileName);
+            String fileUrl = pdfHelp.getOfflineUrl(fileName);
+            response.setHeader("content-disposition","attachment;filename="+Tools.stringMD5(fileName)+fileName.substring(fileName.lastIndexOf(".")));
             response.setHeader("content-type", "application/pdf");
-            //输出
-            int len = 1;
-            byte[] bs = new byte[1024];
-            while((len = fileInputStream.read(bs)) != -1){
-                outputStream.write(bs, 0, len);
-            }
-            fileInputStream.close();
+            response.setHeader("X-Accel-Redirect", fileUrl);
+//            FileInputStream fileInputStream = new FileInputStream(fileName);
+//            ServletOutputStream outputStream = response.getOutputStream();
+//            //输出
+//            int len = 1;
+//            byte[] bs = new byte[1024];
+//            while((len = fileInputStream.read(bs)) != -1){
+//                outputStream.write(bs, 0, len);
+//            }
+//            fileInputStream.close();
         } catch (Exception e) {
             System.out.println(e.getMessage());
         }
@@ -2233,7 +2267,7 @@ public class MyController {
 
     @RequestMapping(value = "/download/textbook", method = RequestMethod.GET)
     @ApiOperation(value = "获取机经", httpMethod = "GET")
-    public void pdfDownLoad(@RequestParam(required = true) String subject, HttpServletRequest request, HttpServletResponse response){
+    public void textbookDownload(@RequestParam(required = true) String subject, HttpServletRequest request, HttpServletResponse response){
         User user = (User) shiroHelp.getLoginUser();
         if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
             throw new AuthException("未授权");
@@ -2257,17 +2291,19 @@ public class MyController {
                     break;
             }
             String fileName = pdfHelp.generatePdfImage(user, resource, false);
-            FileInputStream fileInputStream = new FileInputStream(fileName);
-            ServletOutputStream outputStream = response.getOutputStream();
-            response.setHeader("content-disposition","attachment;filename="+fileName);
+            String fileUrl = pdfHelp.getOfflineUrl(fileName);
+            response.setHeader("content-disposition","attachment;filename="+Tools.stringMD5(fileName)+fileName.substring(fileName.lastIndexOf(".")));
             response.setHeader("content-type", "application/pdf");
-            //输出
-            int len = 1;
-            byte[] bs = new byte[1024];
-            while((len = fileInputStream.read(bs)) != -1){
-                outputStream.write(bs, 0, len);
-            }
-            fileInputStream.close();
+            response.setHeader("X-Accel-Redirect", fileUrl);
+//            FileInputStream fileInputStream = new FileInputStream(fileName);
+//            ServletOutputStream outputStream = response.getOutputStream();
+//            //输出
+//            int len = 1;
+//            byte[] bs = new byte[1024];
+//            while((len = fileInputStream.read(bs)) != -1){
+//                outputStream.write(bs, 0, len);
+//            }
+//            fileInputStream.close();
         } catch (Exception e) {
             System.out.println(e.getMessage());
         }

+ 1 - 1
server/gateway-api/src/main/java/com/qxgmat/controller/api/OrderController.java

@@ -170,7 +170,7 @@ public class OrderController {
         if (!order.getUserId().equals(user.getId())){
             throw new ParameterException("订单不存在");
         }
-        PayResponseData data = tradeService.pay(user.getId(), "千行GMAT", "千行服务购买", PayModule.ORDER, order.getId(), BigDecimal.valueOf(0.1), PayChannel.WECHAT_JS, request);
+        PayResponseData data = tradeService.pay(user.getId(), "千行GMAT", "千行服务购买", PayModule.ORDER, order.getId(), order.getMoney(), PayChannel.WECHAT_JS, request);
         return ResponseHelp.success(data);
     }
 

+ 10 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/CourseDetailDto.java

@@ -67,6 +67,8 @@ public class CourseDetailDto extends Course {
 
     private Collection<BasePaperExtendDto> papers;
 
+    private String[] waters;
+
     public Integer getId() {
         return id;
     }
@@ -302,4 +304,12 @@ public class CourseDetailDto extends Course {
     public void setPapers(Collection<BasePaperExtendDto> papers) {
         this.papers = papers;
     }
+
+    public String[] getWaters() {
+        return waters;
+    }
+
+    public void setWaters(String[] waters) {
+        this.waters = waters;
+    }
 }

+ 46 - 17
server/gateway-api/src/main/java/com/qxgmat/help/PdfHelp.java

@@ -6,6 +6,7 @@ package com.qxgmat.help;
 //import com.spire.pdf.widget.PdfPageCollection;
 import com.itextpdf.text.*;
 import com.itextpdf.text.Font;
+import com.itextpdf.text.Rectangle;
 import com.itextpdf.text.pdf.*;
 import com.qxgmat.data.dao.entity.User;
 import org.slf4j.Logger;
@@ -34,11 +35,23 @@ public class PdfHelp {
     @Value("${upload.web_url}")
     private String webUrl;
 
+    @Value("${upload.offline_path}")
+    private String offlinePath;
+
+    @Value("${upload.offline_url}")
+    private String offlineUrl;
+
     @Value("${upload.water}")
     private String water;
 
     private BaseFont font;
 
+    private int top = 72;
+
+    private int left = 93;
+
+    private int size = 10;
+
     @Autowired
     private void getFont(@Value("${upload.font}") String path) throws IOException, DocumentException {
         FontFactory.registerDirectories();
@@ -79,9 +92,21 @@ public class PdfHelp {
         return bimage;
     }
 
+    public String[] getUserWater(User user){
+        // 2份水印文字
+        String mobile = user.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})","$1****$2");
+        String name = (user.getRealStatus() > 0? user.getRealName().replaceAll("(.{1}).*(.{1})?","$1*$2 ") : "") + mobile;
+        String qx = "千行ID "+String.format("%04d", user.getId());
+        return new String[]{name, qx};
+    }
+
+    public String getOfflineUrl(String offline){
+        return offline.replace(offlinePath, offlineUrl);
+    }
+
     public String generatePdfImage(User user, String pdfUrl, boolean force) throws IOException, DocumentException {
         String pdfFile = pdfUrl.replace(webUrl, localPath);
-        String dest = pdfFile.replace(".pdf", String.format("_%d.pdf", user.getId()));
+        String dest = pdfFile.replace(".pdf", String.format("_%d.pdf", user.getId())).replace(localPath, offlinePath);
         File file = new File(dest);
 
         if (!force && file.exists()){
@@ -89,10 +114,7 @@ public class PdfHelp {
         }else if(file.exists()){
             file.delete();
         }
-        // 2份水印文字
-        String mobile = user.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})","$1****$2");
-        String name = (user.getRealStatus() > 0? user.getRealName().replaceAll("(.{1}).*(.{1})?","$1*$2 ") : "") + mobile;
-        String qx = "千行ID "+String.format("%04d", user.getId());
+        String[] waters = getUserWater(user);
 
         PdfReader reader = new PdfReader(pdfFile);
         // 如果是web项目,直接下载应该放到response的流里面
@@ -102,33 +124,40 @@ public class PdfHelp {
         int pageSize = reader.getNumberOfPages();
         PdfContentByte under;
         for (int i = 1; i<=pageSize;i++){
-            under = stamper.getUnderContent(i);
-            AddTextWatermark(under, name);
-            AddTextWatermark(under, qx);
+            under = stamper.getOverContent(i);
+            Rectangle r = reader.getPageSize(i);
+            float width = r.getWidth();
+            float height = r.getHeight();
+            float[] a = new float[]{top, (height/2-top)/2-size/2 + top, height / 2-size/2, (height/2 + (height - top - height/2)/2)-size/2, height-top-size};
+            for (int j = 0; j < 5; j ++){
+                AddTextWatermark(under, waters[0], Element.ALIGN_LEFT, left, a[j]);
+                AddTextWatermark(under, waters[1], Element.ALIGN_CENTER, width / 2,a[j]);
+                AddTextWatermark(under, waters[0], Element.ALIGN_RIGHT, width - left,a[j]);
+            }
         }
         stamper.close();
         reader.close();
         return dest;
     }
-    void AddTextWatermark(PdfContentByte content, String textWatermark){
+    void AddTextWatermark(PdfContentByte content, String textWatermark, int alignment, float width, float y){
         content.saveState();
-        Font f = new Font(font, 10);
-        f.setColor(0,0,0);
-        f.setStyle(Font.NORMAL);
+//        Font f = new Font(font, 10);
+//        f.setColor(0,0,0);
+//        f.setStyle(Font.NORMAL);
         PdfGState gs = new PdfGState();
         gs.setFillOpacity(0.2f);
         content.setGState(gs);
-        Phrase p = new Phrase(textWatermark, f);
+//        Phrase p = new Phrase(textWatermark, f);
 
         content.beginText();
         content.setColorFill(new BaseColor(0,0,0));// 文字水印 颜色
-        content.setFontAndSize(font, 10);// 文字水印 字体及字号
-        content.setTextMatrix(0, 0);// 文字水印 起始位置
-        content.showTextAligned(Element.ALIGN_CENTER, textWatermark, 200, 100, 0);
+        content.setFontAndSize(font, size);// 文字水印 字体及字号
+//        content.setTextMatrix(0, 0);// 文字水印 起始位置
+        content.showTextAligned(alignment, textWatermark, width, y, 0);
         content.endText();
 
         // 在页面中添加多次,计算为止
-        ColumnText.showTextAligned(content,  Element.ALIGN_CENTER, p, 100f,100f, 0);
+//        ColumnText.showTextAligned(content,  Element.ALIGN_CENTER, p, 100f,100f, 0);
         content.restoreState();
     }
 

+ 4 - 0
server/gateway-api/src/main/java/com/qxgmat/service/extend/CourseExtendService.java

@@ -278,6 +278,10 @@ public class CourseExtendService {
                 for(CourseNo courseNo : courseNoList){
                     courseNo.setResource(courseNo.getTrailResource());
                 }
+            }else{
+                for(CourseNo courseNo : courseNoList){
+                    courseNo.setResource("/api/my/download/course?id="+courseNo.getId());
+                }
             }
         }else{
             for(CourseNo courseNo : courseNoList){

+ 20 - 0
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserCourseService.java

@@ -54,6 +54,26 @@ public class UserCourseService extends AbstractService {
         return one(userCourseMapper, example);
     }
 
+    /**
+     * 判断是否有权限
+     * @param userId
+     * @param courseId
+     * @return
+     */
+    public boolean hasService(Integer userId, Integer courseId){
+        if (courseId == null) return false;
+        Example example = new Example(UserService.class);
+        example.and(
+                example.createCriteria()
+                        .andEqualTo("userId", userId)
+                        .andEqualTo("courseId", courseId)
+                        .andLessThanOrEqualTo("startTime", new Date())
+                        .andGreaterThan("expireTime", new Date())
+        );
+        UserCourse service = one(userCourseMapper, example);
+        return service != null;
+    }
+
     public List<UserCourse> listByCourse(Integer userId, Collection ids){
         if (ids == null || ids.size() == 0) return new ArrayList<>();
         Example example = new Example(UserCourse.class);

+ 2 - 0
server/gateway-api/src/main/profile/dev/application-runtime.yml

@@ -86,6 +86,8 @@ spring:
 upload:
   local_path: ../../upload/
   web_url: /upload/
+  offline_path: ../../offline/
+  offline_url: /offline/
   water: /upload
   font: ./NotoSansCJK-Bold.ttc
 

+ 2 - 0
server/gateway-api/src/main/profile/prod/application-runtime.yml

@@ -86,6 +86,8 @@ spring:
 upload:
   local_path: ../upload/
   web_url: /upload/
+  offline_path: ../offline/
+  offline_url: /offline/
   water: /upload
   font: ./NotoSansCJK-Bold.ttc
 

+ 2 - 0
server/gateway-api/src/main/profile/test/application-runtime.yml

@@ -86,6 +86,8 @@ spring:
 upload:
   local_path: ../upload/
   web_url: /upload/
+  offline_path: ../offline/
+  offline_url: /offline/
   water: /upload
   font: ./NotoSansCJK-Bold.ttc