mod: 代码生成模板,缓存,系统插件crud,异常处理,上传文件磁盘位置、domain

This commit is contained in:
冼子明 2025-03-22 23:19:24 +08:00
parent 9b33e7bd51
commit 9e3bcd298c
27 changed files with 864 additions and 50 deletions

2
.gitignore vendored
View File

@ -3,5 +3,5 @@
.idea/* .idea/*
.mvn/ .mvn/
aitangbao.iml aitangbao.iml
logs/ log/
target/ target/

View File

@ -136,6 +136,15 @@
<groupId>org.noear</groupId> <groupId>org.noear</groupId>
<artifactId>sa-token-solon-plugin</artifactId> <artifactId>sa-token-solon-plugin</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-cache-jedis</artifactId>
<!-- 或者用 (如果不需要 CacheService直接用它
<artifactId>redisx</artifactId>
-->
</dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>

View File

@ -2,8 +2,13 @@ package vip.fuck.sm;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.noear.solon.Solon; import org.noear.solon.Solon;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.SolonMain; import org.noear.solon.annotation.SolonMain;
import org.noear.solon.web.cors.CrossFilter; import org.noear.solon.web.cors.CrossFilter;
import org.noear.solon.web.staticfiles.StaticConfig;
import org.noear.solon.web.staticfiles.StaticMappings;
import org.noear.solon.web.staticfiles.repository.ClassPathStaticRepository;
import org.noear.solon.web.staticfiles.repository.FileStaticRepository;
/** /**
* 启动类 * 启动类
@ -14,10 +19,14 @@ import org.noear.solon.web.cors.CrossFilter;
@SolonMain @SolonMain
public class SolonManagerApplication { public class SolonManagerApplication {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
Solon.start(SolonManagerApplication.class, args, app->{ Solon.start(SolonManagerApplication.class, args, app->{
//或者增加全局处理用过滤器模式 //或者增加全局处理用过滤器模式
app.filter(-1, new CrossFilter().allowedOrigins("*")); //-1 优先级更高 app.filter(-1, new CrossFilter().allowedOrigins("*")); //-1 优先级更高
String filePath = app.cfg().getProperty("file.path" );
StaticMappings.add("/files/", new FileStaticRepository(filePath));
StaticMappings.add("/static/", new ClassPathStaticRepository(StaticConfig.RES_STATIC_LOCATION));
}); });
} }

View File

@ -0,0 +1,34 @@
package vip.fuck.sm.common.config;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.solon.dao.SaTokenDaoOfRedis;
import org.noear.redisx.RedisClient;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.cache.jedis.RedisCacheService;
import org.noear.solon.data.cache.CacheService;
@Configuration
public class RedisCacheConfig {
// 构建 redis client如直接用
@Bean
public RedisClient redisClient(@Inject("${redis}") RedisClient client) {
return client;
}
//构建 Cache Service @Cache
@Bean
public CacheService cacheService(@Inject RedisClient client){
RedisCacheService service = new RedisCacheService(client, 30);
service.enableMd5key(false);
return service;
}
//构建 SaToken Dao
@Bean
public SaTokenDao saTokenDao(@Inject RedisClient client){
return new SaTokenDaoOfRedis(client);
}
}

View File

@ -29,15 +29,10 @@ import java.util.List;
@Configuration @Configuration
public class WebMvcConfigurer { public class WebMvcConfigurer {
@Inject("${file.path}")
private String filePath;
@Bean
public void staticFiles() {
StaticMappings.add("/files/", new FileStaticRepository(filePath));
StaticMappings.add("/static/", new ClassPathStaticRepository("static"));
}
//添加拦截器 //添加拦截器

View File

@ -1,5 +1,6 @@
package vip.fuck.sm.common.exception; package vip.fuck.sm.common.exception;
import lombok.Data;
import vip.fuck.sm.common.exception.code.BaseResponseCode; import vip.fuck.sm.common.exception.code.BaseResponseCode;
import vip.fuck.sm.common.exception.code.ResponseCodeInterface; import vip.fuck.sm.common.exception.code.ResponseCodeInterface;
@ -10,6 +11,7 @@ import vip.fuck.sm.common.exception.code.ResponseCodeInterface;
* @version V1.0 * @version V1.0
* @date 2020年3月18日 * @date 2020年3月18日
*/ */
@Data
public class BusinessException extends RuntimeException { public class BusinessException extends RuntimeException {
/** /**
* 异常编号 * 异常编号
@ -21,6 +23,8 @@ public class BusinessException extends RuntimeException {
*/ */
private final String detailMessage; private final String detailMessage;
Throwable throwable;
public BusinessException(int messageCode, String message) { public BusinessException(int messageCode, String message) {
super(message); super(message);
this.messageCode = messageCode; this.messageCode = messageCode;
@ -33,6 +37,13 @@ public class BusinessException extends RuntimeException {
this.detailMessage = message; this.detailMessage = message;
} }
public BusinessException(String message,Throwable throwable) {
super(message);
this.messageCode = BaseResponseCode.OPERATION_ERRO.getCode();
this.detailMessage = message;
this.throwable = throwable;
}
/** /**
* 构造函数 * 构造函数
* *
@ -42,11 +53,5 @@ public class BusinessException extends RuntimeException {
this(code.getCode(), code.getMsg()); this(code.getCode(), code.getMsg());
} }
public int getMessageCode() {
return messageCode;
}
public String getDetailMessage() {
return detailMessage;
}
} }

View File

@ -28,7 +28,7 @@ public class AppFilter implements Filter {
BaseResponseCode.METHODARGUMENTNOTVALIDEXCEPTION.getCode(), BaseResponseCode.METHODARGUMENTNOTVALIDEXCEPTION.getCode(),
e.getMessage())); e.getMessage()));
}catch (BusinessException e){ }catch (BusinessException e){
ctx.render(new DataResult(e.getMessageCode(), e.getDetailMessage())); ctx.render(new DataResult(e.getMessageCode(), e.getDetailMessage(),e.getThrowable(),null));
} catch (StatusException e){ } catch (StatusException e){
ctx.status(e.getCode()); ctx.status(e.getCode());
if (e.getCode() == 404){ if (e.getCode() == 404){

View File

@ -30,6 +30,9 @@ public class DataResult {
@ApiModelProperty(value = "需要返回的数据", name = "data") @ApiModelProperty(value = "需要返回的数据", name = "data")
private Object data; private Object data;
@ApiModelProperty(value = "开发环境错误信息", name = "devErrorMsg")
private String devErrorMsg;
public DataResult(int code, Object data) { public DataResult(int code, Object data) {
this.code = code; this.code = code;
this.data = data; this.data = data;
@ -42,6 +45,13 @@ public class DataResult {
this.data = data; this.data = data;
} }
public DataResult(int code, String msg,Throwable throwable, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
this.devErrorMsg = throwable!=null ?throwable.getMessage():null;
}
public DataResult(int code, String msg) { public DataResult(int code, String msg) {
this.code = code; this.code = code;
this.msg = msg; this.msg = msg;

View File

@ -1,13 +1,20 @@
package vip.fuck.sm.controller; package vip.fuck.sm.controller;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ClassLoaderUtil;
import cn.hutool.core.util.ClassUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import org.noear.solon.annotation.Controller; import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Get; import org.noear.solon.annotation.Get;
import org.noear.solon.annotation.Mapping; import org.noear.solon.annotation.Mapping;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ModelAndView; import org.noear.solon.core.handle.ModelAndView;
import org.noear.solon.core.util.PathUtil;
import org.noear.solon.validation.annotation.Valid; import org.noear.solon.validation.annotation.Valid;
import java.io.InputStream;
/** /**
* 视图 * 视图
@ -22,6 +29,13 @@ import org.noear.solon.validation.annotation.Valid;
@Valid @Valid
public class IndexController { public class IndexController {
@Mapping ("/favicon.ico")
public void favicon(Context ctx){
InputStream file = ClassLoaderUtil.getClassLoader()
.getResourceAsStream("/static/favicon.ico" );
ctx.output(file);
}
@Get @Mapping ("/index/login") @Get @Mapping ("/index/login")
public ModelAndView login1(){ public ModelAndView login1(){
return this.loginIndex(); return this.loginIndex();

View File

@ -60,7 +60,7 @@ public class SysFilesController {
@Post @Mapping ("/listByPage") @Post @Mapping ("/listByPage")
@SaCheckPermission("sysFiles:list") @SaCheckPermission("sysFiles:list")
public IPage<SysFilesEntity> findListByPage( SysFilesEntity sysFiles) { public IPage<SysFilesEntity> findListByPage( SysFilesEntity sysFiles) {
return sysFilesService.page(sysFiles.getQueryPage(), Wrappers.<SysFilesEntity>lambdaQuery().orderByDesc(SysFilesEntity::getCreateDate)); return sysFilesService.filesPage(sysFiles);
} }

View File

@ -0,0 +1,88 @@
package vip.fuck.sm.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.noear.solon.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.util.List;
import org.noear.solon.core.handle.ModelAndView;
import vip.fuck.sm.common.utils.DataResult;
import vip.fuck.sm.entity.SysPlugsEntity;
import vip.fuck.sm.service.SysPlugsService;
/**
* 系统插件
*
* @author Rish
* @email xian.zi.ming@qq.com
* @date 2025-03-22 20:59:06
*/
@Controller
@Mapping("/")
public class SysPlugsController {
@Inject
private SysPlugsService sysPlugsService;
/**
* 跳转到页面
*/
@Get
@Mapping ("/index/sysPlugs")
public ModelAndView sysPlugs() {
return new ModelAndView("sysplugs/list.html");
}
@ApiOperation(value = "查询分页数据")
@Post @Mapping ("sysPlugs/listByPage")
@SaCheckPermission("sysPlugs:list")
public DataResult findListByPage( SysPlugsEntity sysPlugs){
LambdaQueryWrapper<SysPlugsEntity> queryWrapper = Wrappers.lambdaQuery();
//查询条件示例
queryWrapper.eq(sysPlugs.getQualifiedVersion() != null, SysPlugsEntity::getQualifiedVersion, sysPlugs.getQualifiedVersion());
queryWrapper.orderByDesc(SysPlugsEntity::getQualifiedVersion);
IPage<SysPlugsEntity> iPage = sysPlugsService.page(sysPlugs.getQueryPage(), queryWrapper);
return DataResult.success(iPage);
}
@ApiOperation(value = "新增")
@Post @Mapping ("sysPlugs/add")
@SaCheckPermission("sysPlugs:add")
public DataResult add( SysPlugsEntity sysPlugs){
sysPlugsService.save(sysPlugs);
return DataResult.success();
}
@ApiOperation(value = "删除")
@Delete @Mapping ("sysPlugs/delete")
@SaCheckPermission("sysPlugs:delete")
public DataResult delete( @ApiParam(value = "id集合") List<String> ids){
sysPlugsService.removeByIds(ids);
return DataResult.success();
}
@ApiOperation(value = "更新")
@Put
@Mapping ("sysPlugs/update")
@SaCheckPermission("sysPlugs:update")
public DataResult update( SysPlugsEntity sysPlugs){
sysPlugsService.updateById(sysPlugs);
return DataResult.success();
}
}

View File

@ -0,0 +1,86 @@
package vip.fuck.sm.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import vip.fuck.sm.entity.BasePageEntity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import java.util.Date;
import java.io.Serializable;
import lombok.Data;
/**
* 系统插件
*
* @author Rish
* @email xian.zi.ming@qq.com
* @date 2025-03-22 20:59:06
*/
@Data
@TableName("sys_plugs")
public class SysPlugsEntity extends BasePageEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 全限版本
*/
@TableId("qualified_version")
private String qualifiedVersion;
/**
* 作者
*/
@TableField("author")
private String author;
/**
* 首页
*/
@TableField("site_url")
private String siteUrl;
/**
* 文档地址
*/
@TableField("doc_url")
private String docUrl;
/**
* 描述
*/
@TableField("description")
private String description;
/**
* 版本
*/
@TableField("version")
private String version;
/**
* 磁盘位置
*/
@TableField("jar_path")
private String jarPath;
/**
* 插件大小
*/
@TableField("jar_size")
private Long jarSize;
/**
* 状态
*/
@TableField("status")
private Integer status;
/**
* 获取时间
*/
@TableField("upload_time")
private Date uploadTime;
}

View File

@ -0,0 +1,17 @@
package vip.fuck.sm.mapper;
import vip.fuck.sm.entity.SysPlugsEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 系统插件
*
* @author Rish
* @email xian.zi.ming@qq.com
* @date 2025-03-22 20:59:06
*/
@Mapper
public interface SysPlugsMapper extends BaseMapper<SysPlugsEntity> {
}

View File

@ -1,5 +1,6 @@
package vip.fuck.sm.service; package vip.fuck.sm.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import vip.fuck.sm.entity.SysFilesEntity; import vip.fuck.sm.entity.SysFilesEntity;
import org.noear.solon.core.handle.Context; import org.noear.solon.core.handle.Context;
@ -32,5 +33,7 @@ public interface SysFilesService extends IService<SysFilesEntity> {
* @param ids * @param ids
*/ */
void removeByIdsAndFiles(List<String> ids); void removeByIdsAndFiles(List<String> ids);
IPage<SysFilesEntity> filesPage(SysFilesEntity sysFiles);
} }

View File

@ -0,0 +1,16 @@
package vip.fuck.sm.service;
import com.baomidou.mybatisplus.extension.service.IService;
import vip.fuck.sm.entity.SysPlugsEntity;
/**
* 系统插件
*
* @author Rish
* @email xian.zi.ming@qq.com
* @date 2025-03-22 20:59:06
*/
public interface SysPlugsService extends IService<SysPlugsEntity> {
}

View File

@ -1,5 +1,9 @@
package vip.fuck.sm.service.impl; package vip.fuck.sm.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import vip.fuck.sm.common.exception.BusinessException; import vip.fuck.sm.common.exception.BusinessException;
import vip.fuck.sm.common.utils.DateUtils; import vip.fuck.sm.common.utils.DateUtils;
@ -25,11 +29,17 @@ import java.util.UUID;
*/ */
@Component(value = "share:sysFilesService",typed = true) @Component(value = "share:sysFilesService",typed = true)
public class SysFilesServiceImpl extends ServiceImpl<SysFilesMapper, SysFilesEntity> implements SysFilesService { public class SysFilesServiceImpl extends ServiceImpl<SysFilesMapper, SysFilesEntity> implements SysFilesService {
@Inject("${server.contextPath}")
private String contextPath;
@Inject("${file.path}") @Inject("${file.path}")
private String filePath; private String filePath;
@Inject("${file.contextPath}")
private String fileContextPath;
@Inject("${file.schema}")
private String fileSchema;
@Override @Override
public String saveFile(UploadedFile file, HttpRequest request) { public String saveFile(UploadedFile file, HttpRequest request) {
//存储文件夹 //存储文件夹
@ -48,11 +58,14 @@ public class SysFilesServiceImpl extends ServiceImpl<SysFilesMapper, SysFilesEnt
//id与filename保持一直删除文件 //id与filename保持一直删除文件
String fileNameNew = UUID.randomUUID().toString().replace("-", "") + getFileType(fileName); String fileNameNew = UUID.randomUUID().toString().replace("-", "") + getFileType(fileName);
String newFilePathName = newPath + fileNameNew; String newFilePathName = newPath + fileNameNew;
String url = this.getRootDir(request) + ("/" + contextPath + "/files/" + createTime + "/" + fileNameNew).replaceAll("/+", "/"); String url = ( "/files/" + createTime + "/" + fileNameNew).replaceAll("/+", "/");
//创建输出文件对象 //创建输出文件对象
File outFile = new File(newFilePathName); File outFile = new File(newFilePathName);
if(!outFile.exists()){
FileUtil.mkParentDirs(newFilePathName);
FileUtil.newFile(newFilePathName);
}
//拷贝文件到输出文件对象 //拷贝文件到输出文件对象
// FileUtils.copyInputStreamToFile(file.getInputStream(), outFile);
file.transferTo(outFile); file.transferTo(outFile);
//保存文件记录 //保存文件记录
SysFilesEntity sysFilesEntity = new SysFilesEntity(); SysFilesEntity sysFilesEntity = new SysFilesEntity();
@ -62,7 +75,7 @@ public class SysFilesServiceImpl extends ServiceImpl<SysFilesMapper, SysFilesEnt
this.save(sysFilesEntity); this.save(sysFilesEntity);
return url; return url;
} catch (Exception e) { } catch (Exception e) {
throw new BusinessException("上传文件失败"); throw new BusinessException("上传文件失败",e);
} }
} }
@ -80,6 +93,20 @@ public class SysFilesServiceImpl extends ServiceImpl<SysFilesMapper, SysFilesEnt
} }
@Override
public IPage<SysFilesEntity> filesPage(SysFilesEntity sysFiles) {
IPage<SysFilesEntity> p = this.page(sysFiles.getQueryPage(), Wrappers.<SysFilesEntity>lambdaQuery().orderByDesc(SysFilesEntity::getCreateDate));
if(ObjectUtil.isNotEmpty(p) && ObjectUtil.isNotEmpty(p.getRecords())){
for (SysFilesEntity record : p.getRecords()) {
if(ObjectUtil.isNotEmpty(record.getUrl())){
record.setUrl(String.format("%s://%s",fileSchema,
String.format("%s/%s",fileContextPath,record.getUrl()).replaceAll("/+","/") ) );
}
}
}
return p;
}
/** /**
* 获取文件后缀名 * 获取文件后缀名
* *

View File

@ -0,0 +1,15 @@
package vip.fuck.sm.service.impl;
import org.noear.solon.annotation.Component;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import vip.fuck.sm.mapper.SysPlugsMapper;
import vip.fuck.sm.entity.SysPlugsEntity;
import vip.fuck.sm.service.SysPlugsService;
@Component(value = "sysPlugsService",typed = true)
public class SysPlugsServiceImpl extends ServiceImpl<SysPlugsMapper, SysPlugsEntity> implements SysPlugsService {
}

View File

@ -1,18 +1,20 @@
server.port: 8080 server.port: 8080
server.contextPath: '/' server.contextPath: '/manager'
solon.env: 'dev' solon.env: 'dev'
solon.app: solon:
app:
name: 'solon-manager' name: 'solon-manager'
group: 'vip.fuck' group: 'vip.fuck'
logging:
solon.logging:
appender: appender:
console: console:
level: INFO level: INFO
file: file:
name: "log/${solon.app.name}"
level: INFO level: INFO
solon.dataSources: solon.dataSources:
master!: master!:
class: "com.zaxxer.hikari.HikariDataSource" class: "com.zaxxer.hikari.HikariDataSource"
@ -21,8 +23,12 @@ solon.dataSources:
driverClassName: com.mysql.cj.jdbc.Driver driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/company_project?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8 jdbcUrl: jdbc:mysql://localhost:3306/company_project?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8
redis:
server: "localhost:6379"
db: 0 #默认为 0可不配置
password: ""
maxTotal: 200 #默认为 200可不配
serializer: 'org.noear.redisx.utils.SerializerJson'
mybatis.master: mybatis.master:
typeAliases: #支持包名 或 类名(大写开头 或 *//支持 ** 或 * 占位符 typeAliases: #支持包名 或 类名(大写开头 或 *//支持 ** 或 * 占位符
- "vip.fuck.sm.entity" - "vip.fuck.sm.entity"
@ -75,6 +81,8 @@ project:
database: mysql database: mysql
file: file:
schema: 'http'
contextPath: 'localhost:${server.port}/${server.contextPath}/'
#文件上传目录 绝对路径 末尾不需要加 / #文件上传目录 绝对路径 末尾不需要加 /
path: D:/files #windows path: 'D:/files' #windows
#path: /data/files #linux #path: /data/files #linux

View File

@ -0,0 +1,21 @@
<?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="vip.fuck.sm.mapper.SysPlugsMapper">
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="vip.fuck.sm.entity.SysPlugsEntity" id="sysPlugsMap">
<result property="qualifiedVersion" column="qualified_version"/>
<result property="author" column="author"/>
<result property="siteUrl" column="site_url"/>
<result property="docUrl" column="doc_url"/>
<result property="description" column="description"/>
<result property="version" column="version"/>
<result property="jarPath" column="jar_path"/>
<result property="jarSize" column="jar_size"/>
<result property="status" column="status"/>
<result property="uploadTime" column="upload_time"/>
</resultMap>
</mapper>

View File

View File

@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.noear.solon.core.handle.ModelAndView;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -36,19 +36,18 @@ public class ${className}Controller {
* 跳转到页面 * 跳转到页面
*/ */
@Get @Mapping ("/index/${classname}") @Get @Mapping ("/index/${classname}")
public String ${classname}() { public ModelAndView ${classname}() {
return "${classNameLower}/list"; return new ModelAndView("${classNameLower}/list.html");
} }
@ApiOperation(value = "查询分页数据") @ApiOperation(value = "查询分页数据")
@Post @Mapping ("${classname}/listByPage") @Post @Mapping ("${classname}/listByPage")
@SaCheckPermission("${classname}:list") @SaCheckPermission("${classname}:list")
@ResponseBody
public DataResult findListByPage( ${className}Entity ${classname}){ public DataResult findListByPage( ${className}Entity ${classname}){
LambdaQueryWrapper<${className}Entity> queryWrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<${className}Entity> queryWrapper = Wrappers.lambdaQuery();
//查询条件示例 //查询条件示例
queryWrapper.eq(tbGoods.getId() != null, ${className}Entity::getId, ${classname}.getId()); queryWrapper.eq(${classname}.getId() != null, ${className}Entity::getId, ${classname}.getId());
queryWrapper.orderByDesc(${className}Entity::getId); queryWrapper.orderByDesc(${className}Entity::getId);
IPage<${className}Entity> iPage = ${classname}Service.page(${classname}.getQueryPage(), queryWrapper); IPage<${className}Entity> iPage = ${classname}Service.page(${classname}.getQueryPage(), queryWrapper);
return DataResult.success(iPage); return DataResult.success(iPage);
@ -58,7 +57,6 @@ public class ${className}Controller {
@ApiOperation(value = "新增") @ApiOperation(value = "新增")
@Post @Mapping ("${classname}/add") @Post @Mapping ("${classname}/add")
@SaCheckPermission("${classname}:add") @SaCheckPermission("${classname}:add")
@ResponseBody
public DataResult add( ${className}Entity ${classname}){ public DataResult add( ${className}Entity ${classname}){
${classname}Service.save(${classname}); ${classname}Service.save(${classname});
return DataResult.success(); return DataResult.success();
@ -67,7 +65,6 @@ public class ${className}Controller {
@ApiOperation(value = "删除") @ApiOperation(value = "删除")
@Delete @Mapping ("${classname}/delete") @Delete @Mapping ("${classname}/delete")
@SaCheckPermission("${classname}:delete") @SaCheckPermission("${classname}:delete")
@ResponseBody
public DataResult delete( @ApiParam(value = "id集合") List<String> ids){ public DataResult delete( @ApiParam(value = "id集合") List<String> ids){
${classname}Service.removeByIds(ids); ${classname}Service.removeByIds(ids);
return DataResult.success(); return DataResult.success();
@ -76,7 +73,6 @@ public class ${className}Controller {
@ApiOperation(value = "更新") @ApiOperation(value = "更新")
@Put @Mapping ("${classname}/update") @Put @Mapping ("${classname}/update")
@SaCheckPermission("${classname}:update") @SaCheckPermission("${classname}:update")
@ResponseBody
public DataResult update( ${className}Entity ${classname}){ public DataResult update( ${className}Entity ${classname}){
${classname}Service.updateById(${classname}); ${classname}Service.updateById(${classname});
return DataResult.success(); return DataResult.success();

View File

@ -8,7 +8,7 @@ import ${package}.entity.${className}Entity;
import ${package}.service.${className}Service; import ${package}.service.${className}Service;
@Service("${classname}Service") @Component(value = "${classname}Service",typed = true)
public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${className}Entity> implements ${className}Service { public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${className}Entity> implements ${className}Service {

View File

@ -5,7 +5,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Title</title> <title>Title</title>
<!--公共模块--> <!--公共模块-->
<div th:replace="~{layout}"></div> <div th:replace="~{layout.html}"></div>
<body> <body>
<div class="panel panel-default operation" hidden> <div class="panel panel-default operation" hidden>
<div class="panel-heading title"></div> <div class="panel-heading title"></div>

View File

@ -1,15 +1,15 @@
-- 默认上级目录菜单为其他 -- 默认上级目录菜单为其他
INSERT INTO sys_permission (id, name, pid, url,target, type,order_num, deleted, status) INSERT INTO sys_permission (id, name, pid, url,target, type,order_num, deleted, status)
VALUES ('${identity}', '${comments}' ,'21', 'index/${classname}','_self', '2', '10',1, 1); VALUES ('${identity}', '${comments}' ,'21', 'index/${classname}','_self', '2', '10',0, 1);
-- 菜单对应按钮SQL -- 菜单对应按钮SQL
INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status) INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status)
VALUES ('${selectId}', '${identity}', '列表' , '${classname}/listByPage','${classname}:list', '3',1, 1); VALUES ('${selectId}', '${identity}', '列表' , '${classname}/listByPage','${classname}:list', '3',0, 1);
INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status) INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status)
VALUES ('${addId}', '${identity}', '新增' , '${classname}/add','${classname}:add', '3',1, 1); VALUES ('${addId}', '${identity}', '新增' , '${classname}/add','${classname}:add', '3',0, 1);
INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status) INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status)
VALUES ('${updateId}', '${identity}', '修改' , '${classname}/update','${classname}:update', '3',1, 1); VALUES ('${updateId}', '${identity}', '修改' , '${classname}/update','${classname}:update', '3',0, 1);
INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status) INSERT INTO sys_permission (id,pid, name, url, perms, type, deleted, status)
VALUES ('${deleteId}', '${identity}', '删除' , '${classname}/delete','${classname}:delete', '3',1, 1); VALUES ('${deleteId}', '${identity}', '删除' , '${classname}/delete','${classname}:delete', '3',0, 1);
-- 赋予admin用户权限 -- 赋予admin用户权限
INSERT INTO sys_role_permission(id, role_id, permission_id) VALUES ('${identityJoinId}', '1', '${identity}'); INSERT INTO sys_role_permission(id, role_id, permission_id) VALUES ('${identityJoinId}', '1', '${identity}');
INSERT INTO sys_role_permission(id, role_id, permission_id) VALUES ('${selectIdJoinId}', '1', '${selectId}'); INSERT INTO sys_role_permission(id, role_id, permission_id) VALUES ('${selectIdJoinId}', '1', '${selectId}');

View File

@ -0,0 +1,156 @@
<!DOCTYPE html>
<html lang="en" xmlns:sa="http://www.thymeleaf.org/extras/sa-token"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--公共模块-->
<div th:replace="~{layout.html}"></div>
</head>
<body>
<div id="searchParam">
<form class="layui-form layui-form-pane" action="">
<div class="layui-form-item" sa:hasPermission="sys:log:list">
<div class="layui-input-inline">
<input type="text" name="username" class="layui-input" autocomplete="off" placeholder="请输入账号">
</div>
<div class="layui-input-inline">
<input type="text" name="operation" class="layui-input" autocomplete="off" placeholder="用户操作动作">
</div>
<div class="layui-input-inline">
<input type="text" readonly class="layui-input" name="createTimeBegin" id="createTimeBegin" placeholder="开始时间">
</div>
<div class="layui-input-inline">
<input type="text" readonly class="layui-input" name="createTimeEnd" id="createTimeEnd" placeholder="结束时间">
</div>
<div class="layui-input-inline ">
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
</div>
</div>
</form>
</div>
<table class="layui-hide" id="log_table" lay-filter="log_table"></table>
<div id="laypage"></div>
</body>
<script type="text/html" id="toolbar">
<div class="layui-btn-group">
<button sa:hasPermission="sys:log:deleted" type="button" class="layui-btn layui-btn-sm"
lay-event="getCheckData">
批量删除
</button>
</div>
</script>
<script type="text/html" id="tool">
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del" sa:hasPermission="sys:log:deleted">删除</a>
</script>
<script>
//查询条件
layui.use(function () {
var table = layui.table;
var form = layui.form;
var layer = layui.layer;
var laydate = layui.laydate;
//加载table
var tableIns1 = table.render({
elem: '#log_table'
, contentType: 'application/json'
, page: true //开启分页
, url: ctx + 'sys/logs' //数据接口
, method: 'POST'
, parseData: function (res) { //将原始数据解析成 table 组件所规定的数据
return {
"code": res.code, //解析接口状态
"msg": res.msg, //解析提示文本
"count": CoreUtil.isEmpty(res.data) ? 0 : res.data.total, //解析数据长度
"data": CoreUtil.isEmpty(res.data) ? null : res.data.records //解析数据列表
}
}
, cols: [
[
{type: 'checkbox', fixed: 'left'},
{field: 'username', title: '账号', width: 130},
{field: 'operation', title: '用户操作', width: 140},
{field: 'method', title: '请求方法', width: 400},
{field: 'params', title: '请求参数', width: 300},
{field: 'createTime', title: '创建时间', minWidth: 120},
{width: 150, toolbar: "#tool", title: '操作'}
]
]
, toolbar: '#toolbar'
});
//日期范围
laydate.render({
elem: '#createTimeBegin'
, type: 'datetime'
});
//日期范围
laydate.render({
elem: '#createTimeEnd'
, type: 'datetime'
});
//表头工具栏事件
table.on('toolbar(log_table)', function (obj) {
var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) {
case 'getCheckData':
var data = checkStatus.data;
if (data.length == 0) {
layer.msg("请选择要批量删除的日志");
} else {
var logIds = [];
$(data).each(function (index, item) {
logIds.push(item.id);
});
tipDialog(logIds);
}
break;
}
;
});
//操作工具栏事件
table.on('tool(log_table)', function (obj) {
var data = obj.data;
switch (obj.event) {
case 'del':
var logIds = [];
logIds.push(data.id);
tipDialog(logIds);
break;
}
});
//删除前确认对话框
var tipDialog = function (logIds) {
layer.open({
content: '确定要删除么',
yes: function (index, layero) {
layer.close(index); //如果设定了yes回调需进行手工关闭
CoreUtil.sendDelete(ctx + "/logs", logIds, function (res) {
layer.msg(res.msg);
tableIns1.reload();
});
}
});
}
// 监听搜索操作
form.on('submit(data-search-btn)', function (data) {
//执行搜索重载
tableIns1.reload({
page: {
curr: 1
}
, where: data.field
});
return false;
});
});
</script>
</html>

View File

@ -70,13 +70,19 @@
//执行实例 //执行实例
var uploadInst = upload.render({ var uploadInst = upload.render({
elem: '#upload' //绑定元素 elem: '#upload' //绑定元素
,ext: 'jpg|png|gif|bmp|jpeg|jar|doc|docx|txt|mp4|mp3'
,url: ctx + 'sysFiles/upload' //上传接口 ,url: ctx + 'sysFiles/upload' //上传接口
,done: function(res){ ,done: function(res){
if(res.code){
layer.msg(res.msg);
}else{
tableIns1.reload(); tableIns1.reload();
}
//上传完毕回调 //上传完毕回调
} }
,error: function(){ ,error: function(){
//请求异常回调 //请求异常回调
layer.msg('上传失败');
} }
}); });

View File

@ -0,0 +1,299 @@
<!DOCTYPE html>
<html lang="en" xmlns:sa="http://www.thymeleaf.org/extras/sa-token"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--公共模块-->
<div th:replace="~{layout.html}"></div>
<body>
<div class="panel panel-default operation" hidden>
<div class="panel-heading title"></div>
<div class="layui-card-body">
<form class="layui-form " action="" lay-filter="info">
<input name="qualifiedVersion" hidden/>
<div class="layui-form-item">
<label class="layui-form-label">作者</label>
<div class="layui-input-block">
<input type="author" name="author" placeholder="请输入作者" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">首页</label>
<div class="layui-input-block">
<input type="siteUrl" name="siteUrl" placeholder="请输入首页" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">文档地址</label>
<div class="layui-input-block">
<input type="docUrl" name="docUrl" placeholder="请输入文档地址" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<div class="layui-input-block">
<input type="description" name="description" placeholder="请输入描述" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">版本</label>
<div class="layui-input-block">
<input type="version" name="version" placeholder="请输入版本" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">磁盘位置</label>
<div class="layui-input-block">
<input type="jarPath" name="jarPath" placeholder="请输入磁盘位置" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">插件大小</label>
<div class="layui-input-block">
<input type="jarSize" name="jarSize" placeholder="请输入插件大小" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<input type="status" name="status" placeholder="请输入状态" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">获取时间</label>
<div class="layui-input-block">
<input type="uploadTime" name="uploadTime" placeholder="请输入获取时间" autocomplete="off" class="layui-input disabled">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="submit" class="layui-btn" lay-submit="" lay-filter="submit">保存</button>
<button class="layui-btn layui-btn-primary" id="btn_cancel">返回</button>
</div>
</div>
</form>
</div>
</div>
<div class="table_div">
<div id="searchParam" sa:hasPermission="sysPlugs:list">
<form class="layui-form ">
<div class="layui-form-item">
<div class="layui-input-inline">
<input type="text" name="key" class="layui-input" autocomplete="off" placeholder="请输入">
</div>
<div class="layui-input-inline ">
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
</div>
</div>
</form>
</div>
<table class="layui-table" id="showTable" lay-filter="showTable" ></table>
</div>
<script type="text/html" id="toolbar">
<div class="layui-btn-container oper">
<button class="layui-btn layui-btn-sm" lay-event="add" sa:hasPermission="sysPlugs:add">添加</button>
<button class="layui-btn layui-btn-sm" lay-event="batchDeleted" sa:hasPermission="sysPlugs:delete">删除</button>
</div>
</script>
<script type="text/html" id="tool">
<a class="layui-btn layui-btn-xs" lay-event="look">查看</a>
<a class="layui-btn layui-btn-xs" lay-event="edit" sa:hasPermission="sysPlugs:update">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del" sa:hasPermission="sysPlugs:delete">删除</a>
</script>
</body>
</html>
<script>
layui.use(function () {
var table = layui.table;
var form = layui.form;
var layer = layui.layer;
//加载table
var tableIns1 = table.render({
elem: '#showTable'
, contentType: 'application/json'
, page: true //开启分页
, url: ctx + 'sysPlugs/listByPage' //数据接口
, method: 'POST'
, parseData: function (res) { //将原始数据解析成 table 组件所规定的数据
return {
"code": res.code, //解析接口状态
"msg": res.msg, //解析提示文本
"count": CoreUtil.isEmpty(res.data) ? 0 : res.data.total, //解析数据长度
"data": CoreUtil.isEmpty(res.data) ? null : res.data.records //解析数据列表
}
}
, cols: [
[
{type: 'checkbox', fixed: 'left'},
{field: 'qualifiedVersion', title: '全限版本', sort: true},
{field: 'author', title: '作者', sort: true},
{field: 'siteUrl', title: '首页', sort: true},
{field: 'docUrl', title: '文档地址', sort: true},
{field: 'description', title: '描述', sort: true},
{field: 'version', title: '版本', sort: true},
{field: 'jarPath', title: '磁盘位置', sort: true},
{field: 'jarSize', title: '插件大小', sort: true},
{field: 'status', title: '状态', sort: true},
{field: 'uploadTime', title: '获取时间', sort: true},
{width: 120, toolbar: "#tool", title: '操作'}
]
]
, toolbar: '#toolbar'
});
//表头工具
table.on('toolbar(showTable)', function(obj){
switch(obj.event){
case 'batchDeleted':
var checkStatus = table.checkStatus(obj.config.id);
var data = checkStatus.data;
if(data.length==0){
layer.msg("请选择要批量删除的列");
}else {
var ids = [];
$(data).each(function (index,item) {
ids.push(item.id);
});
tipDialog(ids);
}
break;
case 'add':
toUnDisabled();
$(".table_div").hide();
$(".operation").show();
$(".title").html("新增");
setTimeout(function () {
form.val('info', {
"test": "test"
, "qualifiedVersion": ""
, "author": ""
, "siteUrl": ""
, "docUrl": ""
, "description": ""
, "version": ""
, "jarPath": ""
, "jarSize": ""
, "status": ""
, "uploadTime": ""
});
}, 200);
break;
};
});
//列操作
table.on('tool(showTable)',function (obj) {
var data = obj.data;
switch (obj.event) {
case 'del':
var ids=[];
ids.push(data.id);
tipDialog(ids);
break;
case 'look':
backshow(data);
toDisabled();
break;
case 'edit':
backshow(data);
$(".title").html("编辑");
toUnDisabled();
break;
}
});
//删除
var tipDialog=function (ids) {
layer.open({
content: "确定要删除么?",
yes: function(index, layero){
layer.close(index); //如果设定了yes回调需进行手工关闭
CoreUtil.sendDelete(ctx + "sysPlugs/delete",ids,function (res) {
layer.msg(res.msg, {time:1000},function () {
tableIns1.reload();
});
});
}
});
};
//返回
$("#btn_cancel").click(function() {
$(".table_div").show();
$(".operation").hide();
return false;
});
//监听保存
form.on('submit(submit)', function(data){
if(data.field.id===undefined || data.field.id===null || data.field.id===""){
CoreUtil.sendPost(ctx + "sysPlugs/add",data.field,function (res) {
$(".table_div").show();
$(".operation").hide();
tableIns1.reload();
});
}else {
CoreUtil.sendPut(ctx + "sysPlugs/update",data.field,function (res) {
$(".table_div").show();
$(".operation").hide();
tableIns1.reload();
});
}
return false;
});
// 监听搜索操作
form.on('submit(data-search-btn)', function (data) {
//执行搜索重载
tableIns1.reload({
page: {
curr: 1
}
, where: data.field
});
return false;
});
//回显
var backshow = function (data) {
$(".table_div").hide();
$(".operation").show();
$(".title").html("查看");
setTimeout(function () {
form.val('info', {
"test": "test"
, "qualifiedVersion": data.qualifiedVersion
, "author": data.author
, "siteUrl": data.siteUrl
, "docUrl": data.docUrl
, "description": data.description
, "version": data.version
, "jarPath": data.jarPath
, "jarSize": data.jarSize
, "status": data.status
, "uploadTime": data.uploadTime
});
}, 200);
}
//禁用输入
var toDisabled = function () {
$(".oper").hide();
$(".disabled").each(function (index, elem) {
$(elem).attr("disabled", "")
})
}
//放开输入
var toUnDisabled = function () {
$(".oper").show();
$(".disabled").each(function (index, elem) {
$(elem).removeAttr("disabled", "")
})
}
});
</script>