美文网首页
ruoyi框架使用总结(一)

ruoyi框架使用总结(一)

作者: Raral | 来源:发表于2021-03-13 16:14 被阅读0次

1. 前后端返回longint数据精度缺失?

处理springboot 前后端精度问题?
数据转换,长整型和时间格式化?
https://www.cnblogs.com/mfser/p/10138648.html
https://www.freesion.com/article/1548455900/
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.cms2.common.annotation.Excel;
import com.cms2.common.core.domain.BaseEntity;

/**
 * 官网的banner图对象 ow_banner
 * 
 * @author cms2
 * @date 2021-03-09
 */

public class OwBanner extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
}

2. 咋样引入一个不知道版本号的jar包?

https://www.freesion.com/article/1548455900/

3. 优化若依框架自带的 图片上传ui和功能?

3.1 我们要先定义一个 上传图片的接口

  • xxx-commons/utils/file/FtpFileUploadUtils.java 定义工具类
package com.cms2.common.utils.file;

import com.alibaba.fastjson.JSONObject;
import com.cms2.common.utils.DateUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**

 * @description:ftp文件上传工具

 */
public class FtpFileUploadUtils {

    //ftp服务器ip地址
    private static final String FTP_ADDRESS = "";
    //端口号
    private static final int FTP_PORT = 21;
    //用户名
    private static final String FTP_USERNAME = "";
    //密码
    private static final String FTP_PASSWORD = "";
    //图片路径
    private static final String FTP_BASE_PATH = "/usr/local/images/";

    public static JSONObject uploadRemoteFile(String typeDir,String urlString){
        URL url = null;
        try {
            url = new URL(urlString);
            //打开链接
            URLConnection conn = url.openConnection();
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            return uploadFile(typeDir,"xxx.png",inStream);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;

    }


    public static JSONObject uploadFile(String typeDir, String originFileName, InputStream input) {
        JSONObject json = new JSONObject();
        FTPClient ftp = new FTPClient();
        ftp.setControlEncoding("UTF8");
        try {
            int reply;
            ftp.connect(FTP_ADDRESS, FTP_PORT);
            ftp.login(FTP_USERNAME, FTP_PASSWORD);
//            ftp.enterLocalPassiveMode();
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);

            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return json;
            }
            String timePath = fmtTimeFilePath(typeDir);
            makeDir(ftp,timePath,FTP_BASE_PATH);
            String finalPath = FTP_BASE_PATH +"/"+ timePath;
            String fileExt = originFileName.substring(originFileName.lastIndexOf("."));
            /*新文件名*/
            String newUploadFileName = System.nanoTime() + fileExt;

            ftp.makeDirectory(finalPath);

            ftp.changeWorkingDirectory(finalPath);
            ftp.storeFile(newUploadFileName, input);
            input.close();
            ftp.logout();
            json.put("url","/images"+timePath+newUploadFileName);
            json.put("filePath",timePath+newUploadFileName);
            json.put("fileName",newUploadFileName);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }

        return json;
    }


    public static boolean makeDir(FTPClient ftp,String finalPath,String basePath) throws IOException {
        // 切换到上传目录
        if (!ftp.changeWorkingDirectory(finalPath)) {
            // 如果目录不存在创建目录
            String[] dirs = finalPath.split("/");
            String tempPath = basePath;
            for (String dir : dirs) {
                if (null == dir || "".equals(dir)) {
                    continue;
                }
                tempPath += "/" + dir;
                if (!ftp.changeWorkingDirectory(tempPath)) {
                    if (!ftp.makeDirectory(tempPath)) {
                    } else {
                        ftp.changeWorkingDirectory(tempPath);
                    }
                }
            }
        }
        return true;
    }

    /**
     * 格式化文件夹格式 采用时间
     * @param typeDir
     * @return
     */
    public static String fmtTimeFilePath(String typeDir) {
        String timePath = DateUtils.getCurrentYear() + "/" + DateUtils.getCurrentMonth() + "/" + DateUtils.getCurrentDay();
        return "/"+typeDir +"/"+ timePath+"/";
    }

}

3.2 在 xxx-admin/controller/common/CommonController.java 定义通用ftp上传的方法

  /**
     * 通用FTP上传
     */
    @PostMapping("/common/ftp/upload")
    @ResponseBody
    public AjaxResult ftpUploadFile(MultipartFile file, String typeDir) throws Exception {
        try {
            // 上传并返回新文件名称
            String fileName = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            String url = null;

            JSONObject json = FtpFileUploadUtils.uploadFile(typeDir, fileName, inputStream);

            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", json.get("fileName"));
            ajax.put("url", IMG_PATH + json.get("url"));
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

3.3 模板使用 上传图片的插件;当前模板引入对应的dragImgUpload.js插件

 <div class="form-group">
    <label class="col-sm-3 control-label">banner图片:</label>
    <div class="col-sm-8">
        <input id="url"  name="url" class="form-control" type="hidden">
        <div id="drop_area"></div>
    </div>
</div>

<script>
    var dragImgUpload = new DragImgUpload("#drop_area",{
                callback:function (files) {
                    //回调函数,可以传递给后台等等
                    var file = files[0];
                    var data = new FormData();
                    data.append("file", file);
                    data.append("typeDir","ow_navigation");
                    $.ajax({
                        type: "POST",
                        url: ctx + "common/ftp/upload",
                        data: data,
                        cache: false,
                        contentType: false,
                        processData: false,
                        dataType: 'json',
                        success: function(result) {
                            if (result.code == web_status.SUCCESS) {

                                $("#url").val(result.url);
                            } else {
                                $.modal.alertError(result.msg);
                            }
                        },
                        error: function(error) {
                            $.modal.alertWarning("图片上传失败。");
                        }
                    });
                }
            })
        });
</script>

3.4 通过jquery封装简单版上传图片的插件 dragImgUpload.js

function DragImgUpload(id,options) {
    this.me = $(id);
    var defaultOpt = {
        boxWidth:'200px',
        boxHeight:'auto'
    }
    this.preview = $('<div id="preview"><img src="/img/upload.png" class="img-responsive"  style="width: 100%;height: auto;" alt="" title=""> </div>');
    this.opts=$.extend(true, defaultOpt,{
    }, options);
    this.init();
    this.callback = this.opts.callback;
}

//定义原型方法
DragImgUpload.prototype = {
    init:function () {
        var imageUrl = $("#thumbnail").val();
        if(imageUrl == null || imageUrl == ""){
            this.me.append(this.preview);
        }
        this.me.append(this.fileupload);
        this.cssInit();
        this.eventClickInit();
    },
    cssInit:function () {
        this.me.css({
            'width':this.opts.boxWidth,
            'height':this.opts.boxHeight,
            'border':'1px solid #cccccc',
            'padding':'10px',
            'cursor':'pointer'
        })
        this.preview.css({
            'height':'100%',
            'overflow':'hidden'
        })

    },
    onDragover:function (e) {
        e.stopPropagation();
        e.preventDefault();
        e.dataTransfer.dropEffect = 'copy';
    },
    onDrop:function (e) {
        var self = this;
        e.stopPropagation();
        e.preventDefault();
        var fileList = e.dataTransfer.files; //获取文件对象
        // do something upload
        if(fileList.length == 0){
            return false;
        }
        //检测文件是不是图片
        if(fileList[0].type.indexOf('image') === -1){
            alert("您拖的不是图片!");
            return false;
        }

        //拖拉图片到浏览器,可以实现预览功能
        var img = window.URL.createObjectURL(fileList[0]);
        var filename = fileList[0].name; //图片名称
        var filesize = Math.floor((fileList[0].size)/1024);
        if(filesize>500){
            alert("上传大小不能超过500K.");
            return false;
        }

        self.me.find("img").attr("src",img);
        self.me.find("img").attr("title",filename);
        if(this.callback){
            this.callback(fileList);
        }
    },
    eventClickInit:function () {
        var self = this;
        this.me.unbind().click(function () {
            self.createImageUploadDialog();
        })
        var dp = this.me[0];
        dp.addEventListener('dragover', function(e) {
            self.onDragover(e);
        });
        dp.addEventListener("drop", function(e) {
            self.onDrop(e);
        });


    },
    onChangeUploadFile:function () {
        var fileInput = this.fileInput;
        var files = fileInput.files;
        var file = files[0];
        var img = window.URL.createObjectURL(file);
        var filename = file.name;
        this.me.find("img").attr("src",img);
        this.me.find("img").attr("title",filename);
        if(this.callback){
            this.callback(files);
        }
    },
    createImageUploadDialog:function () {
        var fileInput = this.fileInput;
        if (!fileInput) {
            //创建临时input元素
            fileInput = document.createElement('input');
            //设置input type为文件类型
            fileInput.type = 'file';
            //设置文件name
            fileInput.name = 'ime-images';
            //允许上传多个文件
            fileInput.multiple = true;
            fileInput.onchange  = this.onChangeUploadFile.bind(this);
            this.fileInput = fileInput;
        }
        //触发点击input点击事件,弹出选择文件对话框
        fileInput.click();
    }




}

4. 使用代码生成和菜单管理?;咋样同时生成自定义包名的文件?

参考文献
* 先使用菜单管理创建预定好的菜单
* 创建表,然后通过代码生成导入表,配置好参数,生成对应的 controller,service, dao,mapper, template

5. 咋样创建带有层级结构的树形表格?实现有具体层级表结构?

通过代码生成器,创建树形表格,选择id,和pid配置,很简单。

```html
<div class="form-group">    
    <label class="col-sm-3 control-label">父导航id:</label>
    <div class="col-sm-8">
        <div class="input-group">
            <input id="treeId" name="pid" type="hidden"       ="${owNavigation?.id}"/>
            <input class="form-control" type="text"   onclick="selectOwNavigationTree()" id="treeName" readonly="true" th:value="${owNavigation?.name}">
            <span class="input-group-addon"><i class="fa fa-search"></i></span>
        </div>
    </div>
</div>
```

6. 进入首页如何自动展开某菜单?

例如,进入自动打开用户管理,调用applyPath,填入你请求菜单对应的url地址。

applyPath("/system/role")

7. 做下拉框的三级联动效果?咋样在模板调用 service层数据?使用行内获取值语法[[${@xxx.yyy()}]]?

  1. 当一个业务线需要其他业务线支撑完成
    比如:官网内容管理新增和编辑,需要导航管理中的导航分类一级 二级绑定时,需要查询导航管理分类级别 显示到 内容管理的页面中。
  • 引入第三放js css,
<!--下拉框树形级联效果-->
<div th:fragment="bootstrap-cascader-min-css">
    <link th:href="@{/ajax/libs/bootstrap-cascader/css/bootstrap-cascader.min.css}" rel="stylesheet"/>
</div>
<div th:fragment="bootstrap-cascader-min-js">
    <script th:src="@{/ajax/libs/bootstrap-cascader/js/bootstrap-cascader.min.js}"></script>
</div>
  • 使用模板地方
 <div class="form-group">    
    <label class="col-sm-3 control-label">导航类别:</label>
    <div class="col-sm-8">
        <!--<input name="navId" class="form-control" type="text">-->
        <div id="navType"></div>
    </div>
</div>

<script>
// 引入自定义的 service 层返回的 加工后的数据
   var navTypes = [[${@navTypeService.getList()}]];
    console.log(navTypes);
    $(function() {
        $("#navType").bsCascader({
            openOnHover: true,
            loadData: function(openedItems, callback) {
                callback(navTypes)
            }
        })
    })
</script>

  • 自定义的service 写在 xxx-framework/.../service
package com.cms2.framework.web.service;

import com.cms2.common.core.domain.Ztree;
import com.cms2.system.domain.OwNavTypeTree;
import com.cms2.system.service.IOwNavigationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @description: 导航分类 service
 */
@Service("navTypeService")
public class NavTypeService {

    @Autowired
    public IOwNavigationService owNavigationService;


    public List<OwNavTypeTree> getList() {
        List<OwNavTypeTree> list = owNavigationService.getTreeNavType();
        return list;
    }

}
  • 在模板service层 定义新的方法: 作用就是数据转换树形结构
// xxx-system/.../service/impl/
 @Override
    public List<OwNavTypeTree> getTreeNavType() {
        List<OwNavTypeTree> types = owNavigationMapper.getTreeNavType();
        //将返回的一个集合数据 转换成 树形结构数据
        types = this.parseNavTypeTree(types);


        return types;
    }

    //转换树形结构方法
    public List<OwNavTypeTree> parseNavTypeTree(List<OwNavTypeTree> list) {
        //1.先创建一个新的集合
        List<OwNavTypeTree> result = new ArrayList<>();
        //2. 获取第一个节点 如果等于null 就是根节点
        for(OwNavTypeTree navType: list) {
            if(null == navType.getPid()) {
                result.add(navType);
            }
        }
        //3. 递归获取子节点
        for(OwNavTypeTree parent : result) {
            parent = recurTree(parent, list);
        }
        return result;
    }

    //递归方法
    public OwNavTypeTree recurTree(OwNavTypeTree parent, List<OwNavTypeTree> list) {
        for(OwNavTypeTree navType : list) {
            if(parent.getId().equals(navType.getPid())) {
                navType = recurTree(navType, list);
                parent.getData().add(navType);

            }
        }
        return parent;
    }
  • 定义新的实体类
// xxx-system/.../domain/
    package com.cms2.system.domain;

import com.cms2.common.annotation.Excel;
import com.cms2.common.core.domain.BaseEntity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

import java.util.ArrayList;
import java.util.List;

/**
 * @description: 导航分类树形结构 实体类
 */
public class OwNavTypeTree extends BaseEntity {
    private static final long serialVersionUID = 1L;
    /** 主键id */
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    /** 父导航id */
    @JsonSerialize(using = ToStringSerializer.class)
    private Long pid;

    /** 导航名称 */
    private String name;

//    当前导航的子分类数据
    private List<OwNavTypeTree> childNavTypes;

    //给当前分类添加一个空集合
    private List<OwNavTypeTree> data = new ArrayList<>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<OwNavTypeTree> getChildNavTypes() {
        if(null == childNavTypes) {
            childNavTypes = new ArrayList<>();
        }
        return childNavTypes;
    }

    public void setChildNavTypes(List<OwNavTypeTree> childNavTypes) {
        this.childNavTypes = childNavTypes;
    }

    public List<OwNavTypeTree> getData() {
        return data;
    }

    public void setData(List<OwNavTypeTree> data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "OwNavTypeTree{" +
                "id=" + id +
                ", pid=" + pid +
                ", name='" + name + '\'' +
                ", childNavTypes=" + childNavTypes +
                ", data=" + data +
                '}';
    }
}

  • 在 mapper 中写入对应的 方法
  • 然后再 mapper映射文件写入对应的方法即可
    效果:


    1615622263(1).png

8. 删除已分配菜单?

https://www.jianshu.com/p/7b70c3569f8a
先把和这个菜单关联的角色删除,或者修改;在把这个角色关联的用户删除或者修改即可

相关文章

网友评论

      本文标题:ruoyi框架使用总结(一)

      本文链接:https://www.haomeiwen.com/subject/appxcltx.html