From efba453a39559ac59943baa664dc66c205a94bb1 Mon Sep 17 00:00:00 2001 From: zhenggm Date: Wed, 22 Jun 2022 22:10:59 +0800 Subject: [PATCH] =?UTF-8?q?file=E5=8A=9F=E8=83=BD=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- smtweb-system/sw-system-bpm/pom.xml | 10 ++ .../system/bpm/spring/config/FileConfig.java | 26 +++ .../spring/controller/FileDownloadController.java | 185 +++++++++++++++++++++ .../spring/controller/FileUploadController.java | 157 +++++++++++++++++ .../system/bpm/spring/dao/ImageAttachDao.java | 63 +++++++ .../smtweb/system/bpm/spring/dao/SysAttachDao.java | 114 +++++++++++++ .../system/bpm/spring/entity/AttachPathPO.java | 13 ++ .../system/bpm/spring/entity/FileDataVO.java | 8 + .../system/bpm/spring/entity/UploadDataVO.java | 15 ++ .../cc/smtweb/system/bpm/util/FileDynPath.java | 106 ++++++++++++ .../cc/smtweb/system/bpm/util/FileFixPath.java | 51 ++++++ .../smtweb/system/bpm/util/FilePathGenerator.java | 132 +++++++++++++++ .../cc/smtweb/system/bpm/util/FilePathInfo.java | 48 ++++++ .../smtweb/system/bpm/util/MemMultipartFile.java | 79 +++++++++ .../java/cc/smtweb/system/bpm/util/ThumbImage.java | 109 ++++++++++++ .../smtweb/system/bpm/web/sys/user/area/Area.java | 109 ++++++++++++ .../system/bpm/web/sys/user/area/AreaCache.java | 42 +++++ .../system/bpm/web/sys/user/area/AreaService.java | 30 ++++ 18 files changed, 1297 insertions(+) create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/config/FileConfig.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/ImageAttachDao.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/SysAttachDao.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/AttachPathPO.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/FileDataVO.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/UploadDataVO.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileDynPath.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileFixPath.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathGenerator.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathInfo.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/MemMultipartFile.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/ThumbImage.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/Area.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaCache.java create mode 100644 smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaService.java diff --git a/smtweb-system/sw-system-bpm/pom.xml b/smtweb-system/sw-system-bpm/pom.xml index 0cc2989..bc58b5e 100644 --- a/smtweb-system/sw-system-bpm/pom.xml +++ b/smtweb-system/sw-system-bpm/pom.xml @@ -35,6 +35,16 @@ spring-boot-starter-freemarker + net.coobird + thumbnailator + [0.4, 0.5) + + + org.jclarion + image4j + 0.7 + + com.fasterxml.jackson.dataformat jackson-dataformat-yaml 2.11.0 diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/config/FileConfig.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/config/FileConfig.java new file mode 100644 index 0000000..19475c5 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/config/FileConfig.java @@ -0,0 +1,26 @@ +package cc.smtweb.system.bpm.spring.config; + +import cc.smtweb.system.bpm.util.FilePathGenerator; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import cc.smtweb.framework.core.db.jdbc.IdGenerator; + +/** + * 微服务框架封装自动配置类 + */ +@Configuration +public class FileConfig { + // 文件本地存储配置 + @Value("${smtweb.file.local-path}") + private String fileLocalPath; + + // 文件请求URL路径配置 http://127.0.0.1:${server.port}/${server.servlet.context-path}/files/ + @Value("${smtweb.file.url}") + private String fileUrl; + + @Bean + public FilePathGenerator filePathGenerator(IdGenerator idGenerator) { + return new FilePathGenerator(fileLocalPath, fileUrl, idGenerator); + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java new file mode 100644 index 0000000..40e6795 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java @@ -0,0 +1,185 @@ +package cc.smtweb.system.bpm.spring.controller; + +import cc.smtweb.framework.core.cache.redis.RedisManager; +import cc.smtweb.framework.core.session.SessionUtil; +import cc.smtweb.system.bpm.util.FilePathGenerator; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.InputStreamResource; +import org.springframework.http.*; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +@RestController +public class FileDownloadController { + private static final MediaType APPLICATION_JAVASCRIPT = new MediaType("application", "javascript"); + @Value("${smtweb.static.local-path:}") + private String staticLocalPath; + + @Autowired + private FilePathGenerator filePathGenerator; + + @Autowired + private RedisManager redisManager; + + /** path方式下载文件 */ + @GetMapping("/fs/files/**") + public ResponseEntity files(@RequestParam(value="name", required=false) String name, + @RequestParam(value="noCache", required=false) Boolean noCache, + HttpServletRequest request + ) throws FileNotFoundException { + String filePath = request.getRequestURI().substring(10); + return download(filePath, name, noCache, request); + } + + /** 参数方式下载文件 */ + @GetMapping("/fs/download") + public ResponseEntity download(@RequestParam(value="path") String path, + @RequestParam(value="name", required=false) String name, + @RequestParam(value="noCache", required=false) Boolean noCache, + HttpServletRequest request + ) throws FileNotFoundException { + SessionUtil.checkSession(request, redisManager); + + File file = new File(filePathGenerator.getFileDiskPath(path)); + + if (!file.exists()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + + if (StringUtils.isBlank(name)) { + name = file.getName(); + } + + HttpHeaders headers = new HttpHeaders(); + if (Boolean.TRUE.equals(noCache)) { + headers.setCacheControl("no-cache, no-store, must-revalidate"); + headers.setPragma("no-cache"); + headers.setExpires(0); + } + + headers.setLastModified(file.lastModified()); + headers.add("Content-Disposition", + String.format("attachment; filename=\"%s\"", new String(name.getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1))); + + return ResponseEntity.ok() + .headers(headers) + .contentLength(file.length()) + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .body(new InputStreamResource(new FileInputStream(file))); + } + + /** path方式读取静态目录文件 */ + @GetMapping("/fs/static/**") + public ResponseEntity resource(@RequestParam(value="default", required=false) String defaultPath, + @RequestParam(value="noCache", required=false) Boolean noCache, + @RequestHeader(value="If-Modified-Since", required = false) String ifModifiedSince, + HttpServletRequest request) throws FileNotFoundException { + String filePath = request.getRequestURI().substring(11); + + HttpHeaders headers = new HttpHeaders(); + + if (Boolean.TRUE.equals(noCache)) { + headers.setCacheControl("no-cache, no-store, must-revalidate"); + headers.setPragma("no-cache"); + headers.setExpires(0); + } else { + // 暂时缓存1天 + headers.setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS)); + headers.setExpires(Instant.ofEpochMilli(System.currentTimeMillis() + DateUtils.MILLIS_PER_DAY)); + } + + String name = getFileName(filePath); + headers.add("Content-Disposition", + String.format("attachment; filename=\"%s\"", new String(name.getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1))); + + MediaType contentType = getContentType(filePath); + // 先找文件 + if (StringUtils.isNotBlank(staticLocalPath)) { + File file = new File(staticLocalPath + filePath); + + if (file.exists()) { + headers.setLastModified(file.lastModified()); + + return ResponseEntity.ok() + .headers(headers) + .contentLength(file.length()) + .contentType(contentType) + .body(new InputStreamResource(new FileInputStream(file))); + } + } + + // 再找资源目录 + InputStream inputStream = getClass().getResourceAsStream("/static/" + filePath); + if (inputStream != null) { + return buildResource(inputStream, contentType, headers); + } else if (StringUtils.isNotBlank(defaultPath)) { + inputStream = getClass().getResourceAsStream("/static/" + defaultPath); + if (inputStream != null) { + return buildResource(inputStream, contentType, headers); + } + } + + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + + private String getFileName(String filePath) { + int pos = filePath.lastIndexOf("/"); + if (pos >= 0) { + return filePath.substring(pos + 1); + } + + return filePath; + } + + private ResponseEntity buildResource(InputStream inputStream, MediaType contentType, HttpHeaders headers) { + return ResponseEntity.ok() + .headers(headers) +// .contentLength(file.length()) + .contentType(contentType) + .body(new InputStreamResource(inputStream)); + } + + private static MediaType getContentType(String filePath) { + int pos = filePath.lastIndexOf("."); + + if (pos >= 0) { + String fileExt = filePath.substring(pos + 1).toLowerCase(); + switch (fileExt) { + case "htm": + case "html": + case "css": + return MediaType.TEXT_HTML; + case "js": + return APPLICATION_JAVASCRIPT; + case "txt": + return MediaType.TEXT_PLAIN; + case "pdf": + return MediaType.APPLICATION_PDF; + case "xml": + return MediaType.TEXT_XML; + case "gif": + return MediaType.IMAGE_GIF; + case "jpeg": + case "jpg": + return MediaType.IMAGE_JPEG; + case "png": + return MediaType.IMAGE_PNG; + default: + return MediaType.APPLICATION_OCTET_STREAM; + } + } + + return MediaType.APPLICATION_OCTET_STREAM; + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java new file mode 100644 index 0000000..b0f1404 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java @@ -0,0 +1,157 @@ +package cc.smtweb.system.bpm.spring.controller; + +import cc.smtweb.framework.core.common.R; +import cc.smtweb.framework.core.db.DbEngine; +import cc.smtweb.framework.core.cache.redis.RedisManager; +import cc.smtweb.framework.core.session.SessionUtil; +import cc.smtweb.system.bpm.spring.dao.ImageAttachDao; +import cc.smtweb.system.bpm.util.FilePathGenerator; +import cc.smtweb.system.bpm.util.FilePathInfo; +import cc.smtweb.system.bpm.util.MemMultipartFile; +import cc.smtweb.system.bpm.util.ThumbImage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import cc.smtweb.system.bpm.spring.entity.FileDataVO; +import cc.smtweb.system.bpm.spring.entity.UploadDataVO; + +import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; + +@RestController +public class FileUploadController { + @Autowired + private FilePathGenerator filePathGenerator; + + @Autowired + private DbEngine dbEngine; + + @Autowired + private RedisManager redisManager; + + @Autowired + private ImageAttachDao imageAttachDao; + + // TODO: 权限处理,临时文件处理 + @PostMapping("/fs/upload/{path}") + public R upload(@RequestParam("file") MultipartFile file, @PathVariable("path") String path, + @RequestParam(value="thumb", required=false) String thumb, + @RequestParam(value="thumbHeight", required=false) Integer thumbHeight, + @RequestParam(value="commit", required=false) Boolean insert, + @RequestParam(value="keepName", required=false) Boolean keepName, + HttpServletRequest request + ) { + SessionUtil.checkSession(request, redisManager); + return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, insert, keepName); + } + + @PostMapping("/fs/uploadImage/{path}") + public R upload(@RequestBody FileDataVO data, @PathVariable("path") String path, + @RequestParam(value="thumb", required=false) String thumb, + @RequestParam(value="thumbHeight", required=false) Integer thumbHeight, + @RequestParam(value="commit", required=false) Boolean insert, + HttpServletRequest request) { + SessionUtil.checkSession(request, redisManager); + + MultipartFile file = MemMultipartFile.build(data.getData()); + if (file == null) { + return R.error("数据内容格式有错"); + } + + return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, insert, false); + } + + @PostMapping("/fs/uploadAvatar/{path}") + public R uploadAvatar(@RequestParam("file") MultipartFile file, @PathVariable("path") String path, + @RequestParam(value="size", required=false) Integer size, + @RequestParam(value="commit", required=false) Boolean insert, + @RequestParam(value="keepName", required=false) Boolean keepName, + HttpServletRequest request) { + SessionUtil.checkSession(request, redisManager); + return uploadFile(path, file, ThumbImage.TYPE_AVATAR, size, insert, keepName); + } + + // 保存文件和插入数据库数据 + @PostMapping("/fs/commit/{path}") + public R commit(@RequestParam("file") MultipartFile file, @PathVariable("path") String path, + @RequestParam(value="thumb", required=false) String thumb, + @RequestParam(value="thumbHeight", required=false) Integer thumbHeight, + @RequestParam(value="keepName", required=false) Boolean keepName, + HttpServletRequest request) { + SessionUtil.checkSession(request, redisManager); + return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, true, keepName); + } + + private R uploadFile(String path, MultipartFile file, int type, Integer size, Boolean insert, Boolean keepName) { + //获取上传时的文件名 + String fileName = file.getOriginalFilename(); + + //判断文件是否为空 + if(file.isEmpty() && fileName != null){ + return R.error("文件为空"); + } + + // 判断保持文件名不变 + FilePathInfo fileInfo = filePathGenerator.make(path, fileName, Boolean.TRUE.equals(keepName)); + + // 注意是路径+文件名 + File targetFile = new File(fileInfo.getFullFileName()); + + try(InputStream inputStream = file.getInputStream(); OutputStream outputStream = new FileOutputStream(targetFile)) { + // 最后使用资源访问器FileCopyUtils的copy方法拷贝文件 + FileCopyUtils.copy(inputStream, outputStream); + } catch (IOException e) { + //出现异常,则告诉页面失败 + return R.error("上传失败", e); + } + + // 生成缩略图 +// String contentType = file.getContentType(); + UploadDataVO data = new UploadDataVO(); + + data.setPath(fileInfo.getMysqlFilePath()); + data.setName(fileName); + data.setSize(file.getSize()); + data.setContentType(file.getContentType()); + data.setUrl(filePathGenerator.getFileUrl(fileInfo.getMysqlFilePath())); + + if (type == ThumbImage.TYPE_THUMB || type == ThumbImage.TYPE_AVATAR) { + try { + imageAttachDao.makeThumb(data, type == ThumbImage.TYPE_THUMB, targetFile, size); + } catch (IOException e) { + return R.error("生成缩略图失败", e); + } + } + + if (Boolean.TRUE.equals(insert)) { + Long id = dbEngine.nextId(); + Timestamp now = new Timestamp(System.currentTimeMillis()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + + dbEngine.update("insert into sw_user.sys_attach(attach_id, attach_name, attach_path, attach_content_type, attach_size, attach_create_time) values(?, ?, ?, ?, ?, ?)", + id, data.getName(), data.getPath(), data.getContentType(), data.getSize(), sdf.format(now)); + + data.setId(id); + } + + return R.success(data); + } + + // TODO: 修改为安全的后台删除方式 + @PostMapping("/fs/remove") + public R remove(@RequestParam(value="filePath") String filePath, HttpServletRequest request) { + SessionUtil.checkSession(request, redisManager); + + File file = new File(filePathGenerator.getFileDiskPath(filePath)); + if (file.exists() && file.isFile()) { + if (file.delete()) { + R.success(filePath); + } + } + + return R.success(); + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/ImageAttachDao.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/ImageAttachDao.java new file mode 100644 index 0000000..322d293 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/ImageAttachDao.java @@ -0,0 +1,63 @@ +package cc.smtweb.system.bpm.spring.dao; + +import cc.smtweb.system.bpm.util.ThumbImage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import cc.smtweb.system.bpm.spring.entity.UploadDataVO; + +import java.io.File; +import java.io.IOException; + +@Service +public class ImageAttachDao { + public static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + + public void makeThumb(UploadDataVO data, boolean isThumb, File targetFile, Integer size) throws IOException { + boolean imageType = false; + String fileName = data.getName(); + String contentType = data.getContentType(); + + if (contentType.startsWith("image/")) { + imageType = true; + } else if (contentType.equals(APPLICATION_OCTET_STREAM)) { + String fileExt = fileName.substring(fileName.lastIndexOf(".")); + + if (StringUtils.isNotEmpty(fileExt)) { + switch (fileExt.toLowerCase()) { + case ".jpg": + case ".jpeg": + contentType = "image/jpg"; + imageType = true; + break; + case ".gif": + contentType = "image/gif"; + imageType = true; + break; + case ".png": + contentType = "image/png"; + imageType = true; + break; + default: + break; + } + + if (imageType) { + data.setContentType(contentType); + } + } + } + + if (imageType) { + int thumbHeight = 80; + if (size != null) { + thumbHeight = (size > 500) ? 500 : size; + } + + ThumbImage thumbImage = new ThumbImage(); + + thumbImage.makeThumb(isThumb, targetFile, thumbHeight); + data.setWidth(thumbImage.getImageWidth()); + data.setHeight(thumbImage.getImageHeight()); + } + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/SysAttachDao.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/SysAttachDao.java new file mode 100644 index 0000000..166e76b --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/dao/SysAttachDao.java @@ -0,0 +1,114 @@ +package cc.smtweb.system.bpm.spring.dao; + +import cc.smtweb.framework.core.db.DbEngine; +import cc.smtweb.system.bpm.spring.entity.AttachPathPO; +import cc.smtweb.system.bpm.util.FilePathGenerator; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.yaml.snakeyaml.util.UriEncoder; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class SysAttachDao { + @Autowired + private FilePathGenerator filePathGenerator; + + @Autowired + private DbEngine dbEngine; + + /** + * 获取文件本地文件路径 + * + * @param filePath 相对路径 + * @return 本地文件全路径 + */ + public String getDiskPath(String filePath) { + return filePathGenerator.getFileDiskPath(filePath); + } + + /** + * 获取访问文件的URL地址 + * + * @param filePath 文件相对路径 + * @return 文件URL地址 + */ + public String getFileUrl(String filePath) { + return filePathGenerator.getFileUrl(filePath); + } + + /** + * 获取访问文件的URL地址 + * + * @param filePath 文件相对路径 + * @param filePath 文件名 + * @return 文件URL地址 + */ + public String getFileUrl(String filePath, String fileName) { + return "/fs/download?path=" + UriEncoder.encode(filePath) + "&name=" + UriEncoder.encode(fileName); + } + + public AttachPathPO get(Long id) { + if (id != null) { + return dbEngine.queryEntity("select attach_id, attach_name, attach_path, attach_content_type, attach_size, attach_create_time from sw_user.sys_attach where attach_id=?", + AttachPathPO.class, id); + } + + return null; + } + + // 删除文件记录和文件 + public void remove(Long fileId) { +// if (id != null) { +// return dbEngine.queryEntity("select attach_id, attach_name, attach_path, attach_content_type, attach_size, attach_create_time from sw_user.sys_attach where attach_id=?", +// AttachPathPO.class, id); +// } +// +// return null; + } + + // 删除文件 + public void remove(String filePath) { +// if (id != null) { +// return dbEngine.queryEntity("select attach_id, attach_name, attach_path, attach_content_type, attach_size, attach_create_time from sw_user.sys_attach where attach_id=?", +// AttachPathPO.class, id); +// } +// +// return null; + } + + public List list(Long[] ids) { + if (ids != null && ids.length > 0) { + return dbEngine.query("select attach_id, attach_name, attach_path, attach_content_type, attach_size, attach_create_time from sw_user.sys_attach where attach_id in( " + + StringUtils.join(ids, ",") + ")", + AttachPathPO.class); + } + + return null; + } + + public Map map(Long[] ids) { + List list = list(ids); + if (list != null && !list.isEmpty()) { + Map map = new HashMap<>(list.size()); + list.forEach((item) -> map.put(item.getAttachId(), item)); + + return map; + } + + return null; + } + + // 保持文件,删除临时文件记录,避免被定时删除 + public void retain(String filePath) { + + } + + // 保持文件,删除临时文件记录,避免被定时删除 + public void retain(Long fileId) { + + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/AttachPathPO.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/AttachPathPO.java new file mode 100644 index 0000000..399bfc7 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/AttachPathPO.java @@ -0,0 +1,13 @@ +package cc.smtweb.system.bpm.spring.entity; + +import lombok.Data; + +@Data +public class AttachPathPO { + private Long attachId; + private String attachName; + private String attachPath; + private String attachContentType; + private Long attachSize; + private Long attachCreate; +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/FileDataVO.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/FileDataVO.java new file mode 100644 index 0000000..5754e26 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/FileDataVO.java @@ -0,0 +1,8 @@ +package cc.smtweb.system.bpm.spring.entity; + +import lombok.Data; + +@Data +public class FileDataVO { + private String data; +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/UploadDataVO.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/UploadDataVO.java new file mode 100644 index 0000000..d67aeb4 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/spring/entity/UploadDataVO.java @@ -0,0 +1,15 @@ +package cc.smtweb.system.bpm.spring.entity; + +import lombok.Data; + +@Data +public class UploadDataVO { + private Long id; + private Integer height; + private Integer width; + private long size; + private String path; + private String name; + private String contentType; + private String url; +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileDynPath.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileDynPath.java new file mode 100644 index 0000000..34e841b --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileDynPath.java @@ -0,0 +1,106 @@ +package cc.smtweb.system.bpm.util; + +import cc.smtweb.framework.core.util.DateUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.time.DateUtils; + +import java.io.File; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.Random; + +/** + * 动态文件〈文件路径〉 + * + * @author kevin + * @since 1.0.0 + */ +@Slf4j +public class FileDynPath extends FileFixPath { + // 目录允许的最大文件数量,避免批量导入文件时文件太多 + private static final int MAX_FILE_COUNT = 2000; + private static final int MAX_DIR_COUNT = 100000; + private long startTime; + private long endTime; + private final SimpleDateFormat sdf; + // 文件数量 + private int fileCount; + // 目录子索引 + private int pathIndex; + + public FileDynPath(String rootPath, String typeDir, SimpleDateFormat sdf) { + super(rootPath, typeDir); + this.sdf = sdf; + } + + /** + * 返回日期路径字符串 + */ + @Override + public FilePathInfo makeDatePath(long fileId, String fileExt) { + long now = System.currentTimeMillis(); + String fileName; + + // 如果不在就需要重新创建子目录 + if (now < startTime || now >= endTime) { + startTime = DateUtil.getTimesmorning(now); + endTime = startTime + DateUtils.MILLIS_PER_DAY; + + this.path = this.typeDir + "/" + sdf.format(new Timestamp(now)); + createFolder(rootPath + this.path); + } + + // 如果文件数量太大就需要创建新子目录 + while (this.fileCount >= MAX_FILE_COUNT) { + this.pathIndex++; + if(this.pathIndex > MAX_DIR_COUNT) { + throw new RuntimeException("dir is two many"); + } + + createFolder(rootPath + getSubPath()); + } + + Random random = new Random(); + int randomId = random.nextInt(Integer.MAX_VALUE); + + fileName = Long.toHexString(fileId) + "_" + Integer.toHexString(randomId) + fileExt; + + return new FilePathInfo(rootPath, getSubPath(), now, fileName, fileId); + } + + private String getSubPath() { + if (this.pathIndex > 0) { + return String.format("%s%02d/%04d", this.path, MAX_DIR_COUNT / 1000, this.pathIndex % 1000); + } + + return this.path; + } + + private boolean createFolder(String path) { + File file = new File(path); + if (file.exists()) { + if (!file.isDirectory()) { + return false; + } + + File[] list = file.listFiles(); + if (list != null) { + this.fileCount = list.length; + } else { + this.fileCount = 0; + } + + return true; + } + + if (!file.mkdirs()) { + log.error("unable to create folders {}.", rootPath + this.path); + return false; + } + + log.debug("create folders {}.", file); + this.fileCount = 0; + + return true; + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileFixPath.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileFixPath.java new file mode 100644 index 0000000..5838559 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FileFixPath.java @@ -0,0 +1,51 @@ +package cc.smtweb.system.bpm.util; + +import lombok.extern.slf4j.Slf4j; + +import java.io.File; + +/** + * 〈文件路径〉 + * + * @author kevin + * @since 1.0.0 + */ +@Slf4j +public class FileFixPath { + protected String path; + protected String rootPath; + protected String typeDir; + + public FileFixPath(String rootPath, String typeDir) { + this.rootPath = rootPath; + this.typeDir = typeDir; + } + + public FilePathInfo makeDatePath(long fileId, String fileName) { + long now = System.currentTimeMillis(); + this.path = this.typeDir + "/"; + createFolder(rootPath + this.path); + + return new FilePathInfo(rootPath, this.path, now, fileName, fileId); + } + + private boolean createFolder(String path) { + File file = new File(path); + if (file.exists()) { + if (!file.isDirectory()) { + return false; + } + + return true; + } + + if (!file.mkdirs()) { + log.error("unable to create folders {}.", rootPath + this.path); + return false; + } + + log.debug("create folders {}.", file); + + return true; + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathGenerator.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathGenerator.java new file mode 100644 index 0000000..4d307ba --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathGenerator.java @@ -0,0 +1,132 @@ +package cc.smtweb.system.bpm.util; + +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.Map; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.apache.tika.mime.MimeType; +import org.apache.tika.mime.MimeTypeException; +import org.apache.tika.mime.MimeTypes; +import org.springframework.web.multipart.MultipartFile; +import cc.smtweb.framework.core.db.jdbc.IdGenerator; + +/** + * 文件名生成规则 subDir/[yyyymm]/[d]/[hex(fileid)]_[hex(rand)].[fileExt] 如果文件是图片格式,会生成缩略图,文件名会直接添加.thumb.jpg后缀 规则参数 yyyymm: + * 时间的年月,固定6位字符。如200505 d: 时间的日期,值范围1~31。如5 fileid: 上传文件的ID,hex(int64) rand: 防盗链随机数,hex(int32)。 fileExt: 文件扩展名。 + */ +@Slf4j +public class FilePathGenerator { + + public static final String THUMB_FILE_EXT = ".thumb.jpg"; + // 文件时间是否作为PK + private SimpleDateFormat sdf; + @Getter + private String rootPath; + private Map fileFxPathMap = new HashMap<>(); + private Map fileDynPathMap = new HashMap<>(); + private String fileUrl; + private IdGenerator idGenerator; + + public FilePathGenerator(String rootPath, String fileUrl, IdGenerator idGenerator) { + this.fileUrl = fixEnd(fileUrl); + this.idGenerator = idGenerator; + this.rootPath = fixEnd(rootPath); + + sdf = new SimpleDateFormat("yyyyMM/dd/"); + } + + private static String fixEnd(String path) { + if (path.endsWith("/") || path.endsWith("\\")) { + return path; + } else { + return path + "/"; + } + } + + /** + * 生成文件路径,根据日期分目录存储 + * + * @param subPath 子目录,区分不同应用的文件 + * @param originalFileName 原始的文件名,用于提取扩展名用 + * @return 文件路径信息类 + */ + public FilePathInfo make(String subPath, String originalFileName) { + return make(subPath, originalFileName, null, false); + } + + public FilePathInfo make(String subPath, String originalFileName, boolean keepName) { + return make(subPath, originalFileName, null, keepName); + } + /** + * 生成文件路径,根据日期分目录存储 + * + * @param subPath 子目录,区分不同应用的文件 + * @param multipartFile 上传文件流,用于提取扩展名用 + * @return 文件路径信息类 + */ + public FilePathInfo make(String subPath, MultipartFile multipartFile) { + return make(subPath, multipartFile.getOriginalFilename(), multipartFile.getContentType(), false); + } + + private synchronized FilePathInfo make(String subPath, String originFileName, String contentType, boolean keepName) { + if (keepName) { + FileFixPath filePathSub = fileFxPathMap.get(subPath); + if (filePathSub == null) { + filePathSub = new FileFixPath(this.rootPath, subPath); + fileFxPathMap.put(subPath, filePathSub); + } + + return filePathSub.makeDatePath(this.idGenerator.nextId(), originFileName); + } else { + FileDynPath filePathSub = fileDynPathMap.get(subPath); + if (filePathSub == null) { + filePathSub = new FileDynPath(this.rootPath, subPath, sdf); + fileDynPathMap.put(subPath, filePathSub); + } + + return filePathSub.makeDatePath(this.idGenerator.nextId(), ext(originFileName, contentType)); + } + } + + private static String ext(String filename, String contentType) { + int index = filename.lastIndexOf("."); + + if (index == -1) { + if (contentType != null) { + MimeTypes allTypes = MimeTypes.getDefaultMimeTypes(); + try { + MimeType jpeg = allTypes.forName(contentType); + return jpeg.getExtension(); + } catch (MimeTypeException e) { + log.error(contentType, e); + } + } + + return ""; + } + + return filename.substring(index); + } + + // 根据数据库存储文件路径获取URL + public String getFileUrl(FilePathInfo filePathInfo) { + return this.fileUrl + filePathInfo.getMysqlFilePath(); + } + + // 根据数据库存储文件路径获取URL + public String getFileUrl(String mysqlFilePath) { + return this.fileUrl + mysqlFilePath; + } + + // 根据数据库存储文件路径获取磁盘存储路径 + public String getFileDiskPath(String mysqlFilePath) { + return this.rootPath + mysqlFilePath; + } + + // 获取下载路径前缀 + public String getDownloadUrl() { + return this.fileUrl; + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathInfo.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathInfo.java new file mode 100644 index 0000000..de9557e --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/FilePathInfo.java @@ -0,0 +1,48 @@ +package cc.smtweb.system.bpm.util; + +import lombok.Getter; + + +/** + * 数据库需要存储 + * fileId, fileTime, subPath + fileName + */ +@Getter +public class FilePathInfo { + // 文件ID + private long fileId; + // 文件创建时间,数据库需要存储 + private long fileTime; + // 文件子路径 + private String subPath; + // 文件名 + private String fileName; + // 本地根路径 + private String rootPath; + + public FilePathInfo(String rootPath, String subPath, long fileTime, String fileName, long fileId) { + this.rootPath = rootPath; + this.subPath = subPath; + this.fileTime = fileTime; + this.fileName = fileName; + this.fileId = fileId; + } + + /** + * 获取本地需要存储的文件全路径 + */ + public String getFullFileName() { + return getDiskFilePath(); + } + + public String getDiskFilePath() { + return this.rootPath + subPath + fileName; + } + + /** + * 获取数据库存储需要的文件全路径 + */ + public String getMysqlFilePath() { + return subPath + fileName; + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/MemMultipartFile.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/MemMultipartFile.java new file mode 100644 index 0000000..33f5681 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/MemMultipartFile.java @@ -0,0 +1,79 @@ +package cc.smtweb.system.bpm.util; + +import org.apache.commons.codec.binary.Base64; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; + +public class MemMultipartFile implements MultipartFile { + private static final String DATA_IMAGE = "data:image/"; + private byte[] data; + private String contentType; + private String filename; + + public static MemMultipartFile build(String dataUrl) { + if (dataUrl != null && dataUrl.startsWith(DATA_IMAGE)) { + // data:image/png;base64, + int pos1 = dataUrl.indexOf(';', DATA_IMAGE.length()); + int pos2 = dataUrl.indexOf(',', DATA_IMAGE.length()); + if (pos1 > 0 && pos2 > pos1) { + byte[] data = Base64.decodeBase64(dataUrl.substring(pos2)); + + if (data != null) { + String contentType = dataUrl.substring(5, pos1); + return new MemMultipartFile(contentType.replace('/', '.'), contentType, data); + } + } + } + + return null; + } + + private MemMultipartFile(String filename, String contentType, byte[] data) { + this.data = data; + this.contentType = contentType; + this.filename = filename; + } + + @Override + public String getName() { + return "data"; + } + + @Override + public String getOriginalFilename() { + return filename; + } + + @Override + public String getContentType() { + return contentType; + } + + @Override + public boolean isEmpty() { + return data.length == 0; + } + + @Override + public long getSize() { + return data.length; + } + + @Override + public byte[] getBytes() throws IOException { + return data; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(data); + } + + @Override + public void transferTo(File file) throws IOException, IllegalStateException { + try(FileOutputStream os = new FileOutputStream(file)) { + os.write(data); + } + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/ThumbImage.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/ThumbImage.java new file mode 100644 index 0000000..e3b2d22 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/util/ThumbImage.java @@ -0,0 +1,109 @@ +package cc.smtweb.system.bpm.util; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.List; + +import javax.imageio.ImageIO; + +import lombok.Getter; +import net.coobird.thumbnailator.Thumbnails; +import net.coobird.thumbnailator.geometry.Positions; +import net.coobird.thumbnailator.resizers.configurations.Antialiasing; +import net.sf.image4j.codec.ico.ICODecoder; +import org.apache.commons.lang3.StringUtils; + +/** + * 缩略图生成工具 + * @author xkliu + */ +@Getter +public class ThumbImage { + // 图片处理方式 + public static final int TYPE_DEFAULT = 1; + public static final int TYPE_THUMB = 2; + public static final int TYPE_AVATAR = 3; + + private int imageWidth; + private int imageHeight; + + public static int type(String thumb) { + // 解决历史遗留boolean类型 + if (StringUtils.isBlank(thumb) || "false".equalsIgnoreCase(thumb)) { + return TYPE_DEFAULT; + } + + if ("true".equalsIgnoreCase(thumb)) { + return TYPE_THUMB; + } + + return Integer.parseInt(thumb); + } + + public void makeThumb(boolean isThumb, File file, int size) throws IOException { + makeThumb(file, size, size, isThumb); + } + // 后台等比压缩后大小最好控制在20k以内 + public void makeThumb(File file, int w, int h, boolean keepAspectRatio) throws IOException { + String fileName = file.getName().toLowerCase(); + + BufferedImage image; + + if (fileName.endsWith(".ico")) { + List images = ICODecoder.read(file); + image = images.get(images.size() - 1); + } else { + image = ImageIO.read(file); + } + + imageWidth = image.getWidth(); + imageHeight = image.getHeight(); + + if (fileName.endsWith(".png") || fileName.endsWith(".gif")) { + // 把透明的图填充白色背景 + BufferedImage newBufferedImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); + newBufferedImage.createGraphics().drawImage(image, 0, 0, Color.WHITE, null); + image = newBufferedImage; + } + + Thumbnails.Builder builder = Thumbnails.of(image); + + if (keepAspectRatio) { + if (h > 0) { + // 高度为基准调整宽度到达原图缩放比例 + int imageR = imageWidth * 1000 / imageHeight; + w = h * imageR / 1000; + } else { + // 宽度为基准调整宽度到达原图缩放比例 + int imageR = imageHeight * 1000 / imageWidth; + h = w * imageR / 1000; + } + +// int r = w * 1000 / h; +// int imageR = imageWidth * 1000 / imageHeight; +// if (r != imageR) { +// w = imageHeight * r / 1000; +// } + } else { + int r = w * 1000 / h; + int imageR = imageWidth * 1000 / imageHeight; + + if (r != imageR) { + int width = imageWidth; + int height = imageHeight; + if (r > imageR) { + width = imageHeight * r / 1000; + } else { + height = imageWidth * 1000 / r; + } + + builder.sourceRegion(Positions.CENTER, width, height); + } + } + + builder.size(w, h).antialiasing(Antialiasing.ON).outputFormat("jpg").outputQuality(0.9) + .toFile(file.getAbsolutePath() + FilePathGenerator.THUMB_FILE_EXT); + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/Area.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/Area.java new file mode 100644 index 0000000..484fbd3 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/Area.java @@ -0,0 +1,109 @@ +package cc.smtweb.system.bpm.web.sys.user.area; + +import cc.smtweb.framework.core.annotation.SwTable; +import cc.smtweb.framework.core.common.SwMap; +import cc.smtweb.framework.core.db.impl.DefaultEntity; + +/** + * Created by 1 at 2022-06-17 07:58:14 + * 实体【[行政区划](SYS_AREA)】的Entity类 + */ +@SwTable("SYS_AREA") +public class Area extends DefaultEntity { + public static final String ENTITY_NAME = "SYS_AREA"; + + public Area() { + super(ENTITY_NAME); + } + + /** 主键 */ + public long getId() { + return getLong("ar_id"); + } + + /** 主键 */ + public void setId(long ar_id) { + put("ar_id", ar_id); + } + /** 编码 */ + public String getCode() { + return getStr("ar_code"); + } + + /** 编码 */ + public void setCode(String ar_code) { + put("ar_code", ar_code); + } + /** 名称 */ + public String getName() { + return getStr("ar_name"); + } + + /** 名称 */ + public void setName(String ar_name) { + put("ar_name", ar_name); + } + /** 父ID */ + public long getParentId() { + return getLong("ar_parent_id"); + } + + /** 父ID */ + public void setParentId(long ar_parent_id) { + put("ar_parent_id", ar_parent_id); + } + /** 级次码 */ + public String getLevelCode() { + return getStr("ar_level_code"); + } + + /** 级次码 */ + public void setLevelCode(String ar_level_code) { + put("ar_level_code", ar_level_code); + } + /** 全称 */ + public String getFullName() { + return getStr("ar_full_name"); + } + + /** 全称 */ + public void setFullName(String ar_full_name) { + put("ar_full_name", ar_full_name); + } + /** 级次 */ + public int getType() { + return getInt("ar_type"); + } + + /** 级次 */ + public void setType(int ar_type) { + put("ar_type", ar_type); + } + /** 状态 */ + public boolean isStatu() { + return getBool("ar_statu"); + } + + /** 状态 */ + public void set(boolean ar_statu) { + setBool("ar_statu", ar_statu); + } + /** 备注 */ + public String getRemark() { + return getStr("ar_remark"); + } + + /** 备注 */ + public void setRemark(String ar_remark) { + put("ar_remark", ar_remark); + } + /** 排序码 */ + public int getSeq() { + return getInt("ar_seq"); + } + + /** 排序码 */ + public void setSeq(int ar_seq) { + put("ar_seq", ar_seq); + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaCache.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaCache.java new file mode 100644 index 0000000..f09f144 --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaCache.java @@ -0,0 +1,42 @@ +package cc.smtweb.system.bpm.web.sys.user.area; + +import cc.smtweb.framework.core.annotation.SwCache; +import cc.smtweb.framework.core.cache.AbstractEntityCache; +import cc.smtweb.framework.core.cache.CacheManager; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +/** + * Created by 1 at 2022-06-17 07:58:14 + * 实体【[行政区划](SYS_AREA)】的缓存类 + */ +@SwCache(ident = "SYS_AREA", title = "页面定义") +public class AreaCache extends AbstractEntityCache { + //缓存key:按父ID + public final static String mk_pr = "pr"; + //缓存key:按编码 + public final static String mk_code = "code"; + + public static AreaCache getInstance() { + return CacheManager.getIntance().getCache(AreaCache.class); + } + + public AreaCache() { + //缓存key:按父ID + regList(mk_pr, "ar_parent_id"); + //缓存key:按编码 + regList(mk_code, "ar_code"); + } + + //缓存key:按父ID + public final Set getByPr(String key) { + return getListByKey(mk_pr, key); + } + //缓存key:按编码 + public final Set getByCode(String key) { + return getListByKey(mk_code, key); + } +} diff --git a/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaService.java b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaService.java new file mode 100644 index 0000000..1fb31fc --- /dev/null +++ b/smtweb-system/sw-system-bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/area/AreaService.java @@ -0,0 +1,30 @@ +package cc.smtweb.system.bpm.web.sys.user.area; + +import cc.smtweb.framework.core.annotation.SwBody; +import cc.smtweb.framework.core.annotation.SwService; +import cc.smtweb.framework.core.common.R; +import cc.smtweb.framework.core.common.SwMap; +import cc.smtweb.system.bpm.web.engine.dynPage.DynPageService; +import cc.smtweb.framework.core.mvc.service.AbstractHandler; +import cc.smtweb.framework.core.session.UserSession; + +/** + * Created by 1 at 2022-06-17 07:58:14 + * 页面【[区划卡片]的服务类 + */ +@SwService +public class AreaService extends DynPageService { + //public final static String TYPE_DEMO = "demo"; + @Override + protected AbstractHandler createHandler(String type) { + return super.createHandler(type); + } + +/* demo + //自定义 + public R demo(@SwBody SwMap params, UserSession us) { + return pageHandler(params, us, TYPE_DEMO, handler -> ((DemoHandler)handler).demo()); + } +*/ + +}