瀏覽代碼

模块开发1

wwh 4 月之前
父節點
當前提交
0ea724980a
共有 69 個文件被更改,包括 1823 次插入0 次删除
  1. 6 0
      snowy-plugin/snowy-plugin-auth/target/classes/vip/xiaonuo/auth/modular/third/mapper/mapping/AuthThirdMapper.xml
  2. 二進制
      snowy-plugin/snowy-plugin-biz/target/classes/userExportTemplate.docx
  3. 6 0
      snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/dict/mapper/mapping/BizDictMapper.xml
  4. 6 0
      snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/org/mapper/mapping/BizOrgMapper.xml
  5. 6 0
      snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/position/mapper/mapping/BizPositionMapper.xml
  6. 5 0
      snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserMapper.xml
  7. 6 0
      snowy-plugin/snowy-plugin-client/target/classes/vip/xiaonuo/client/modular/relation/mapper/mapping/ClientRelationMapper.xml
  8. 6 0
      snowy-plugin/snowy-plugin-client/target/classes/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserMapper.xml
  9. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/config/mapper/mapping/DevConfigMapper.xml
  10. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/dict/mapper/mapping/DevDictMapper.xml
  11. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/email/mapper/mapping/DevEmailMapper.xml
  12. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/file/mapper/mapping/DevFileMapper.xml
  13. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/job/mapper/mapping/DevJobMapper.xml
  14. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/log/mapper/mapping/DevLogMapper.xml
  15. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/message/mapper/mapping/DevMessageMapper.xml
  16. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/relation/mapper/mapping/DevRelationMapper.xml
  17. 6 0
      snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/sms/mapper/mapping/DevSmsMapper.xml
  18. 45 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/AddParam.java.btl
  19. 131 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/Controller.java.btl
  20. 45 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/EditParam.java.btl
  21. 54 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/Entity.java.btl
  22. 34 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/Enum.java.btl
  23. 35 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/IdParam.java.btl
  24. 25 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/Mapper.java.btl
  25. 5 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/Mapper.xml.btl
  26. 70 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/PageParam.java.btl
  27. 80 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/Service.java.btl
  28. 123 0
      snowy-plugin/snowy-plugin-gen/target/classes/backend/ServiceImpl.java.btl
  29. 28 0
      snowy-plugin/snowy-plugin-gen/target/classes/frontend/Api.js.btl
  30. 176 0
      snowy-plugin/snowy-plugin-gen/target/classes/frontend/form.vue.btl
  31. 262 0
      snowy-plugin/snowy-plugin-gen/target/classes/frontend/index.vue.btl
  32. 34 0
      snowy-plugin/snowy-plugin-gen/target/classes/mobile/Api.js.btl
  33. 121 0
      snowy-plugin/snowy-plugin-gen/target/classes/mobile/form.vue.btl
  34. 128 0
      snowy-plugin/snowy-plugin-gen/target/classes/mobile/index.vue.btl
  35. 62 0
      snowy-plugin/snowy-plugin-gen/target/classes/mobile/more.vue.btl
  36. 47 0
      snowy-plugin/snowy-plugin-gen/target/classes/mobile/page.json.btl
  37. 99 0
      snowy-plugin/snowy-plugin-gen/target/classes/mobile/search.vue.btl
  38. 25 0
      snowy-plugin/snowy-plugin-gen/target/classes/sqlend/Mysql.sql.btl
  39. 25 0
      snowy-plugin/snowy-plugin-gen/target/classes/sqlend/Oracle.sql.btl
  40. 5 0
      snowy-plugin/snowy-plugin-gen/target/classes/vip/xiaonuo/gen/modular/basic/mapper/mapping/GenBasicMapper.xml
  41. 5 0
      snowy-plugin/snowy-plugin-gen/target/classes/vip/xiaonuo/gen/modular/config/mapper/mapping/GenConfigMapper.xml
  42. 1 0
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/README.md
  43. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/docx.png
  44. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/file.png
  45. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/gif.png
  46. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/html.png
  47. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/img.png
  48. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/pdf.png
  49. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/png.png
  50. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/ppt.png
  51. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/rar.png
  52. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/txt.png
  53. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/xlsx.png
  54. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/zip.png
  55. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/swiper/swiper1.jpg
  56. 二進制
      snowy-plugin/snowy-plugin-mobile/target/classes/static/images/swiper/swiper2.jpg
  57. 5 0
      snowy-plugin/snowy-plugin-mobile/target/classes/vip/xiaonuo/mobile/modular/resource/mapper/mapping/MobileButtonMapper.xml
  58. 5 0
      snowy-plugin/snowy-plugin-mobile/target/classes/vip/xiaonuo/mobile/modular/resource/mapper/mapping/MobileMenuMapper.xml
  59. 5 0
      snowy-plugin/snowy-plugin-mobile/target/classes/vip/xiaonuo/mobile/modular/resource/mapper/mapping/MobileModuleMapper.xml
  60. 二進制
      snowy-plugin/snowy-plugin-sys/target/classes/userExportTemplate.docx
  61. 二進制
      snowy-plugin/snowy-plugin-sys/target/classes/userImportTemplate.xlsx
  62. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgMapper.xml
  63. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/position/mapper/mapping/SysPositionMapper.xml
  64. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/relation/mapper/mapping/SysRelationMapper.xml
  65. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysButtonMapper.xml
  66. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysMenuMapper.xml
  67. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysModuleMapper.xml
  68. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/role/mapper/mapping/SysRoleMapper.xml
  69. 6 0
      snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserMapper.xml

+ 6 - 0
snowy-plugin/snowy-plugin-auth/target/classes/vip/xiaonuo/auth/modular/third/mapper/mapping/AuthThirdMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.auth.modular.third.mapper.AuthThirdMapper">
+
+
+</mapper>

二進制
snowy-plugin/snowy-plugin-biz/target/classes/userExportTemplate.docx


+ 6 - 0
snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/dict/mapper/mapping/BizDictMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.biz.modular.dict.mapper.BizDictMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/org/mapper/mapping/BizOrgMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.biz.modular.org.mapper.BizOrgMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/position/mapper/mapping/BizPositionMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.biz.modular.position.mapper.BizPositionMapper">
+
+
+</mapper>

+ 5 - 0
snowy-plugin/snowy-plugin-biz/target/classes/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserMapper.xml

@@ -0,0 +1,5 @@
+<?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.xiaonuo.biz.modular.user.mapper.BizUserMapper">
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-client/target/classes/vip/xiaonuo/client/modular/relation/mapper/mapping/ClientRelationMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.client.modular.relation.mapper.ClientRelationMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-client/target/classes/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.client.modular.user.mapper.ClientUserMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/config/mapper/mapping/DevConfigMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.config.mapper.DevConfigMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/dict/mapper/mapping/DevDictMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.dict.mapper.DevDictMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/email/mapper/mapping/DevEmailMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.email.mapper.DevEmailMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/file/mapper/mapping/DevFileMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.file.mapper.DevFileMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/job/mapper/mapping/DevJobMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.job.mapper.DevJobMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/log/mapper/mapping/DevLogMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.log.mapper.DevLogMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/message/mapper/mapping/DevMessageMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.message.mapper.DevMessageMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/relation/mapper/mapping/DevRelationMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.relation.mapper.DevRelationMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-dev/target/classes/vip/xiaonuo/dev/modular/sms/mapper/mapping/DevSmsMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.dev.modular.sms.mapper.DevSmsMapper">
+
+
+</mapper>

+ 45 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/AddParam.java.btl

@@ -0,0 +1,45 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * ${functionName}添加参数
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+@Getter
+@Setter
+public class ${className}AddParam {
+
+    <% for(var i = 0; i < configList.~size; i++) { %>
+    <% if(configList[i].needAdd) { %>
+    /** ${configList[i].fieldRemark} */
+    @ApiModelProperty(value = "${configList[i].fieldRemark}",<% if(configList[i].required) { %> required = true,<% } %> position = ${i + 1})
+    <% if(configList[i].required) { %>
+    <% if(configList[i].fieldJavaType == 'String') { %>@NotBlank<% } else { %>@NotNull<% } %>(message = "${configList[i].fieldNameCamelCase}不能为空")
+    <% } else { %><% } %>
+    private ${configList[i].fieldJavaType} ${configList[i].fieldNameCamelCase};
+
+    <% } %>
+    <% } %>
+}

+ 131 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/Controller.java.btl

@@ -0,0 +1,131 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.github.xiaoymin.knife4j.annotations.ApiSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import ${packageName}.common.annotation.CommonLog;
+import ${packageName}.common.pojo.CommonResult;
+import ${packageName}.common.pojo.CommonValidList;
+import ${packageName}.${moduleName}.modular.${busName}.entity.${className};
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}AddParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}EditParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}IdParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}PageParam;
+import ${packageName}.${moduleName}.modular.${busName}.service.${className}Service;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import javax.validation.constraints.NotEmpty;
+
+/**
+ * ${functionName}控制器
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ */
+@Api(tags = "${functionName}控制器")
+@ApiSupport(author = "SNOWY_TEAM", order = 1)
+@RestController
+@Validated
+public class ${className}Controller {
+
+    @Resource
+    private ${className}Service ${classNameFirstLower}Service;
+
+    /**
+     * 获取${functionName}分页
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    @ApiOperationSupport(order = 1)
+    @ApiOperation("获取${functionName}分页")
+    @SaCheckPermission("/${moduleName}/${busName}/page")
+    @GetMapping("/${moduleName}/${busName}/page")
+    public CommonResult<Page<${className}>> page(${className}PageParam ${classNameFirstLower}PageParam) {
+        return CommonResult.data(${classNameFirstLower}Service.page(${classNameFirstLower}PageParam));
+    }
+
+    /**
+     * 添加${functionName}
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    @ApiOperationSupport(order = 2)
+    @ApiOperation("添加${functionName}")
+    @CommonLog("添加${functionName}")
+    @SaCheckPermission("/${moduleName}/${busName}/add")
+    @PostMapping("/${moduleName}/${busName}/add")
+    public CommonResult<String> add(@RequestBody @Valid ${className}AddParam ${classNameFirstLower}AddParam) {
+        ${classNameFirstLower}Service.add(${classNameFirstLower}AddParam);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 编辑${functionName}
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    @ApiOperationSupport(order = 3)
+    @ApiOperation("编辑${functionName}")
+    @CommonLog("编辑${functionName}")
+    @SaCheckPermission("/${moduleName}/${busName}/edit")
+    @PostMapping("/${moduleName}/${busName}/edit")
+    public CommonResult<String> edit(@RequestBody @Valid ${className}EditParam ${classNameFirstLower}EditParam) {
+        ${classNameFirstLower}Service.edit(${classNameFirstLower}EditParam);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 删除${functionName}
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    @ApiOperationSupport(order = 4)
+    @ApiOperation("删除${functionName}")
+    @CommonLog("删除${functionName}")
+    @SaCheckPermission("/${moduleName}/${busName}/delete")
+    @PostMapping("/${moduleName}/${busName}/delete")
+    public CommonResult<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
+                                                   CommonValidList<${className}IdParam> ${classNameFirstLower}IdParamList) {
+        ${classNameFirstLower}Service.delete(${classNameFirstLower}IdParamList);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 获取${functionName}详情
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    @ApiOperationSupport(order = 5)
+    @ApiOperation("获取${functionName}详情")
+    @SaCheckPermission("/${moduleName}/${busName}/detail")
+    @GetMapping("/${moduleName}/${busName}/detail")
+    public CommonResult<${className}> detail(@Valid ${className}IdParam ${classNameFirstLower}IdParam) {
+        return CommonResult.data(${classNameFirstLower}Service.detail(${classNameFirstLower}IdParam));
+    }
+}

+ 45 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/EditParam.java.btl

@@ -0,0 +1,45 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * ${functionName}编辑参数
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+@Getter
+@Setter
+public class ${className}EditParam {
+
+    <% for(var i = 0; i < configList.~size; i++) { %>
+    <% if(configList[i].needEdit) { %>
+    /** ${configList[i].fieldRemark} */
+    @ApiModelProperty(value = "${configList[i].fieldRemark}",<% if(configList[i].required) { %> required = true,<% } %> position = ${i + 1})
+    <% if(configList[i].required) { %>
+    <% if(configList[i].fieldJavaType == 'String') { %>@NotBlank<% } else { %>@NotNull<% } %>(message = "${configList[i].fieldNameCamelCase}不能为空")
+    <% } else { %><% } %>
+    private ${configList[i].fieldJavaType} ${configList[i].fieldNameCamelCase};
+
+    <% } %>
+    <% } %>
+}

+ 54 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/Entity.java.btl

@@ -0,0 +1,54 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * ${functionName}实体
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+@Getter
+@Setter
+@TableName("${dbTable}")
+public class ${className} {
+
+    <% for(var i = 0; i < configList.~size; i++) { %>
+    /** ${configList[i].fieldRemark} */
+    <% if(configList[i].needTableId) { %>
+    @TableId
+    <% } else { %><% } %>
+    @ApiModelProperty(value = "${configList[i].fieldRemark}", position = ${i + 1})
+    <% if(configList[i].needAutoInsert) { %>
+    @TableField(fill = FieldFill.INSERT)
+    <% } else { %><% } %>
+    <% if(configList[i].needAutoUpdate) { %>
+    @TableField(fill = FieldFill.UPDATE)
+    <% } else { %><% } %>
+    <% if(configList[i].needLogicDelete) { %>
+    @TableLogic
+    @TableField(fill = FieldFill.INSERT)
+    <% } else { %><% } %>
+    private ${configList[i].fieldJavaType} ${configList[i].fieldNameCamelCase};
+    <% if(i == configList.~size - 1) { %><% } else { %>
+
+    <% } %>
+    <% } %>
+}

+ 34 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/Enum.java.btl

@@ -0,0 +1,34 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.enums;
+
+import lombok.Getter;
+
+/**
+ * ${functionName}枚举
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+@Getter
+public enum ${className}Enum {
+
+    /** 测试 */
+    TEST("TEST");
+
+    private final String value;
+
+    ${className}Enum(String value) {
+        this.value = value;
+    }
+}

+ 35 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/IdParam.java.btl

@@ -0,0 +1,35 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * ${functionName}Id参数
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+@Getter
+@Setter
+public class ${className}IdParam {
+
+    /** ${dbTableKeyRemark} */
+    @ApiModelProperty(value = "${dbTableKeyRemark}", required = true)
+    @NotBlank(message = "${dbTableKeyCamelCase}不能为空")
+    private ${dbTableKeyJavaType} ${dbTableKeyCamelCase};
+}

+ 25 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/Mapper.java.btl

@@ -0,0 +1,25 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import ${packageName}.${moduleName}.modular.${busName}.entity.${className};
+
+/**
+ * ${functionName}Mapper接口
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+public interface ${className}Mapper extends BaseMapper<${className}> {
+}

+ 5 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/Mapper.xml.btl

@@ -0,0 +1,5 @@
+<?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="${packageName}.${moduleName}.modular.${busName}.mapper.${className}Mapper">
+
+</mapper>

+ 70 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/PageParam.java.btl

@@ -0,0 +1,70 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * ${functionName}查询参数
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+@Getter
+@Setter
+public class ${className}PageParam {
+
+    /** 当前页 */
+    @ApiModelProperty(value = "当前页码")
+    private Integer current;
+
+    /** 每页条数 */
+    @ApiModelProperty(value = "每页条数")
+    private Integer size;
+
+    /** 排序字段 */
+    @ApiModelProperty(value = "排序字段,字段驼峰名称,如:userName")
+    private String sortField;
+
+    /** 排序方式 */
+    @ApiModelProperty(value = "排序方式,升序:ASCEND;降序:DESCEND")
+    private String sortOrder;
+
+    /** 关键词 */
+    @ApiModelProperty(value = "关键词")
+    private String searchKey;
+
+    <% for(var i = 0; i < configList.~size; i++) { %>
+    <% if(configList[i].needPage) { %>
+    <% if(configList[i].effectType == 'datepicker') { %>
+    /** ${configList[i].fieldRemark}开始 */
+    @ApiModelProperty(value = "${configList[i].fieldRemark}开始")
+    private String start${configList[i].fieldNameCamelCaseFirstUpper};
+
+    /** ${configList[i].fieldRemark}结束 */
+    @ApiModelProperty(value = "${configList[i].fieldRemark}结束")
+    private String end${configList[i].fieldNameCamelCaseFirstUpper};
+
+    <% } else { %>
+    /** ${configList[i].fieldRemark} */
+    @ApiModelProperty(value = "${configList[i].fieldRemark}")
+    private ${configList[i].fieldJavaType} ${configList[i].fieldNameCamelCase};
+
+    <% } %>
+    <% } %>
+    <% } %>
+}

+ 80 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/Service.java.btl

@@ -0,0 +1,80 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import ${packageName}.${moduleName}.modular.${busName}.entity.${className};
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}AddParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}EditParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}IdParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}PageParam;
+
+import java.util.List;
+
+/**
+ * ${functionName}Service接口
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+public interface ${className}Service extends IService<${className}> {
+
+    /**
+     * 获取${functionName}分页
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    Page<${className}> page(${className}PageParam ${classNameFirstLower}PageParam);
+
+    /**
+     * 添加${functionName}
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    void add(${className}AddParam ${classNameFirstLower}AddParam);
+
+    /**
+     * 编辑${functionName}
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    void edit(${className}EditParam ${classNameFirstLower}EditParam);
+
+    /**
+     * 删除${functionName}
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    void delete(List<${className}IdParam> ${classNameFirstLower}IdParamList);
+
+    /**
+     * 获取${functionName}详情
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     */
+    ${className} detail(${className}IdParam ${classNameFirstLower}IdParam);
+
+    /**
+     * 获取${functionName}详情
+     *
+     * @author ${authorName}
+     * @date ${genTime}
+     **/
+    ${className} queryEntity(String id);
+}

+ 123 - 0
snowy-plugin/snowy-plugin-gen/target/classes/backend/ServiceImpl.java.btl

@@ -0,0 +1,123 @@
+/*
+ * Copyright [2022] [https://www.baiduc.com]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.baiduc.com
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.baiduc.com
+ */
+package ${packageName}.${moduleName}.modular.${busName}.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollStreamUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import ${packageName}.common.enums.CommonSortOrderEnum;
+import ${packageName}.common.exception.CommonException;
+import ${packageName}.common.page.CommonPageRequest;
+import ${packageName}.${moduleName}.modular.${busName}.entity.${className};
+import ${packageName}.${moduleName}.modular.${busName}.mapper.${className}Mapper;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}AddParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}EditParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}IdParam;
+import ${packageName}.${moduleName}.modular.${busName}.param.${className}PageParam;
+import ${packageName}.${moduleName}.modular.${busName}.service.${className}Service;
+
+import java.util.List;
+
+/**
+ * ${functionName}Service接口实现类
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+@Service
+public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${className}> implements ${className}Service {
+
+    @Override
+    public Page<${className}> page(${className}PageParam ${classNameFirstLower}PageParam) {
+        QueryWrapper<${className}> queryWrapper = new QueryWrapper<>();
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(configList[i].needPage) { %>
+        <% if(configList[i].effectType == 'datepicker') { %>
+        if(ObjectUtil.isNotEmpty(${classNameFirstLower}PageParam.getStart${configList[i].fieldNameCamelCaseFirstUpper}()) && ObjectUtil.isNotEmpty(${classNameFirstLower}PageParam.getEnd${configList[i].fieldNameCamelCaseFirstUpper}())) {
+            queryWrapper.lambda().between(${className}::get${configList[i].fieldNameCamelCaseFirstUpper}, ${classNameFirstLower}PageParam.getStart${configList[i].fieldNameCamelCaseFirstUpper}(), ${classNameFirstLower}PageParam.getEnd${configList[i].fieldNameCamelCaseFirstUpper}());
+        }
+        <% } else { %>
+        if(ObjectUtil.isNotEmpty(${classNameFirstLower}PageParam.get${configList[i].fieldNameCamelCaseFirstUpper}())) {
+            queryWrapper.lambda().${configList[i].needPageType}(${className}::get${configList[i].fieldNameCamelCaseFirstUpper}, ${classNameFirstLower}PageParam.get${configList[i].fieldNameCamelCaseFirstUpper}());
+        }
+        <% } %>
+        <% } %>
+        <% } %>
+        if(ObjectUtil.isAllNotEmpty(${classNameFirstLower}PageParam.getSortField(), ${classNameFirstLower}PageParam.getSortOrder())) {
+            CommonSortOrderEnum.validate(${classNameFirstLower}PageParam.getSortOrder());
+            queryWrapper.orderBy(true, ${classNameFirstLower}PageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
+                    StrUtil.toUnderlineCase(${classNameFirstLower}PageParam.getSortField()));
+        } else {
+            <% if(hasSortCodeField) { %>
+            queryWrapper.lambda().orderByAsc(${className}::getSortCode);
+            <% } else { %>
+            queryWrapper.lambda().orderByAsc(${className}::get${dbTableKeyFirstUpper});
+            <% } %>
+        }
+        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void add(${className}AddParam ${classNameFirstLower}AddParam) {
+        ${className} ${classNameFirstLower} = BeanUtil.toBean(${classNameFirstLower}AddParam, ${className}.class);
+        this.save(${classNameFirstLower});
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void edit(${className}EditParam ${classNameFirstLower}EditParam) {
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(configList[i].needTableId) { %>
+        ${className} ${classNameFirstLower} = this.queryEntity(${classNameFirstLower}EditParam.get${configList[i].fieldNameCamelCaseFirstUpper}());
+        <% } %>
+        <% } %>
+        BeanUtil.copyProperties(${classNameFirstLower}EditParam, ${classNameFirstLower});
+        this.updateById(${classNameFirstLower});
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void delete(List<${className}IdParam> ${classNameFirstLower}IdParamList) {
+        // 执行删除
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(configList[i].needTableId) { %>
+        this.removeByIds(CollStreamUtil.toList(${classNameFirstLower}IdParamList, ${className}IdParam::get${configList[i].fieldNameCamelCaseFirstUpper}));
+        <% } %>
+        <% } %>
+    }
+
+    @Override
+    public ${className} detail(${className}IdParam ${classNameFirstLower}IdParam) {
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(configList[i].needTableId) { %>
+        return this.queryEntity(${classNameFirstLower}IdParam.get${configList[i].fieldNameCamelCaseFirstUpper}());
+        <% } %>
+        <% } %>
+    }
+
+    @Override
+    public ${className} queryEntity(String id) {
+        ${className} ${classNameFirstLower} = this.getById(id);
+        if(ObjectUtil.isEmpty(${classNameFirstLower})) {
+            throw new CommonException("${functionName}不存在,id值为:{}", id);
+        }
+        return ${classNameFirstLower};
+    }
+}

+ 28 - 0
snowy-plugin/snowy-plugin-gen/target/classes/frontend/Api.js.btl

@@ -0,0 +1,28 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/${moduleName}/${busName}/` + url, ...arg)
+
+/**
+ * ${functionName}Api接口管理器
+ *
+ * @author ${authorName}
+ * @date ${genTime}
+ **/
+export default {
+	// 获取${functionName}分页
+	${classNameFirstLower}Page(data) {
+		return request('page', data, 'get')
+	},
+	// 提交${functionName}表单 edit为true时为编辑,默认为新增
+	${classNameFirstLower}SubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除${functionName}
+	${classNameFirstLower}Delete(data) {
+		return request('delete', data)
+	},
+	// 获取${functionName}详情
+	${classNameFirstLower}Detail(data) {
+		return request('detail', data, 'get')
+	}
+}

+ 176 - 0
snowy-plugin/snowy-plugin-gen/target/classes/frontend/form.vue.btl

@@ -0,0 +1,176 @@
+<template>
+	<xn-form-container
+		<% for(var i = 0; i < configList.~size; i++) { %>
+		<% if(configList[i].needTableId) { %>
+		:title="formData.${configList[i].fieldNameCamelCase} ? '编辑${functionName}' : '增加${functionName}'"
+		<% } %>
+		<% } %>
+		:width="700"
+		:visible="visible"
+		:destroy-on-close="true"
+		@close="onClose"
+	>
+		<a-form ref="formRef" :model="formData" :rules="formRules" layout="${formLayout}">
+		<% if(gridWhether) { %>
+			<a-row :gutter="16">
+			<% for(var i = 0; i < configList.~size; i++) { %>
+			<% if(!configList[i].needTableId && configList[i].whetherAddUpdate) { %>
+				<a-col :span="12">
+					<a-form-item label="${configList[i].fieldRemark}:" name="${configList[i].fieldNameCamelCase}">
+						<% if(configList[i].effectType == 'input') { %>
+						<a-input v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" allow-clear />
+						<% } else if (configList[i].effectType == 'textarea') {%>
+						<a-textarea v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" :auto-size="{ minRows: 3, maxRows: 5 }" />
+						<% } else if (configList[i].effectType == 'select') {%>
+						<a-select v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+						<% } else if (configList[i].effectType == 'radio') {%>
+						<a-radio-group v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+						<% } else if (configList[i].effectType == 'checkbox') {%>
+						<a-checkbox-group v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+						<% } else if (configList[i].effectType == 'datepicker') {%>
+						<a-date-picker v-model:value="formData.${configList[i].fieldNameCamelCase}" value-format="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择${configList[i].fieldRemark}" style="width: 100%" />
+						<% } else if (configList[i].effectType == 'timepicker') {%>
+						<a-time-picker v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" style="width: 100%" />
+						<% } else if (configList[i].effectType == 'inputNumber') {%>
+						<a-input-number v-model:value="formData.${configList[i].fieldNameCamelCase}" :min="1" :max="10000" style="width: 100%" />
+						<% } else if (configList[i].effectType == 'slider') {%>
+						<a-slider v-model:value="formData.${configList[i].fieldNameCamelCase}" :max="1000" style="width: 100%" />
+						<% } %>
+					</a-form-item>
+				</a-col>
+			<% } %>
+			<% } %>
+			</a-row>
+		<% } else { %>
+		<% for(var i = 0; i < configList.~size; i++) { %>
+		<% if(!configList[i].needTableId && configList[i].whetherAddUpdate) { %>
+			<a-form-item label="${configList[i].fieldRemark}:" name="${configList[i].fieldNameCamelCase}">
+				<% if(configList[i].effectType == 'input') { %>
+				<a-input v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" allow-clear />
+				<% } else if (configList[i].effectType == 'textarea') {%>
+				<a-textarea v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" :auto-size="{ minRows: 3, maxRows: 5 }" />
+				<% } else if (configList[i].effectType == 'select') {%>
+				<a-select v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+				<% } else if (configList[i].effectType == 'radio') {%>
+				<a-radio-group v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+				<% } else if (configList[i].effectType == 'checkbox') {%>
+				<a-checkbox-group v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+				<% } else if (configList[i].effectType == 'datepicker') {%>
+				<a-date-picker v-model:value="formData.${configList[i].fieldNameCamelCase}" value-format="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择${configList[i].fieldRemark}" style="width: 100%" />
+				<% } else if (configList[i].effectType == 'timepicker') {%>
+				<a-time-picker v-model:value="formData.${configList[i].fieldNameCamelCase}" value-format="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择${configList[i].fieldRemark}" style="width: 100%" />
+				<% } else if (configList[i].effectType == 'inputNumber') {%>
+				<a-input-number v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" :min="1" :max="10000" style="width: 100%" />
+				<% } else if (configList[i].effectType == 'slider') {%>
+				<a-slider v-model:value="formData.${configList[i].fieldNameCamelCase}" placeholder="请滑动${configList[i].fieldRemark}" :max="1000" style="width: 100%" />
+				<% } %>
+			</a-form-item>
+		<% } %>
+		<% } %>
+		<% } %>
+		</a-form>
+		<template #footer>
+			<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+			<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+		</template>
+	</xn-form-container>
+</template>
+
+<script setup name="${classNameFirstLower}Form">
+	<%
+	var iptTool = 0;
+	for(var i = 0; i < configList.~size; i++) {
+		if(!configList[i].needTableId) {
+		if(configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') {
+			iptTool++;
+		}
+		}
+	}
+	%>
+	<% if(iptTool > 0) { %>
+	import tool from '@/utils/tool'
+	<% } %>
+	import { cloneDeep } from 'lodash-es'
+	import { required } from '@/utils/formRules'
+	import ${classNameFirstLower}Api from '@/api/${moduleName}/${classNameFirstLower}Api'
+	// 抽屉状态
+	const visible = ref(false)
+	const emit = defineEmits({ successful: null })
+	const formRef = ref()
+	// 表单数据
+	const formData = ref({})
+	const submitLoading = ref(false)
+	<% for(var i = 0; i < configList.~size; i++) { %>
+	<% if(!configList[i].needTableId) { %>
+	<% if(configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') { %>
+	const ${configList[i].fieldNameCamelCase}Options = ref([])
+	<% } %>
+	<% } %>
+	<% } %>
+
+	// 打开抽屉
+	const onOpen = (record) => {
+		visible.value = true
+		if (record) {
+			let recordData = cloneDeep(record)
+			<% for(var i = 0; i < configList.~size; i++) { %>
+			<% if(!configList[i].needTableId && configList[i].whetherAddUpdate && configList[i].effectType == 'checkbox') { %>
+			recordData.${configList[i].fieldNameCamelCase} = JSON.parse(recordData.${configList[i].fieldNameCamelCase})
+			<% } %>
+			<% } %>
+			formData.value = Object.assign({}, recordData)
+		}
+		<% for(var i = 0; i < configList.~size; i++) { %>
+		<% if(!configList[i].needTableId) { %>
+		<% if(configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') { %>
+		${configList[i].fieldNameCamelCase}Options.value = tool.dictList('${configList[i].dictTypeCode}')
+		<% } %>
+		<% } %>
+		<% } %>
+	}
+	// 关闭抽屉
+	const onClose = () => {
+		formRef.value.resetFields()
+		formData.value = {}
+		visible.value = false
+	}
+	// 默认要校验的
+	const formRules = {
+		<% for(var i = 0; i < configList.~size; i++) { %>
+		<% if(!configList[i].needTableId) { %>
+		<% if(configList[i].required) { %>
+		${configList[i].fieldNameCamelCase}: [required('请输入${configList[i].fieldRemark}')],
+		<% } %>
+		<% } %>
+		<% } %>
+	}
+	// 验证并提交数据
+	const onSubmit = () => {
+		formRef.value.validate().then(() => {
+			submitLoading.value = true
+			const formDataParam = cloneDeep(formData.value)
+			<% for(var i = 0; i < configList.~size; i++) { %>
+			<% if(configList[i].whetherAddUpdate && configList[i].effectType == 'checkbox') { %>
+			formDataParam.${configList[i].fieldNameCamelCase} = JSON.stringify(formDataParam.${configList[i].fieldNameCamelCase})
+			<% } %>
+			<% } %>
+			${classNameFirstLower}Api
+				<% for(var i = 0; i < configList.~size; i++) { %>
+				<% if(configList[i].needTableId) { %>
+				.${classNameFirstLower}SubmitForm(formDataParam, formDataParam.${configList[i].fieldNameCamelCase})
+				<% } %>
+				<% } %>
+				.then(() => {
+					onClose()
+					emit('successful')
+				})
+				.finally(() => {
+					submitLoading.value = false
+				})
+		})
+	}
+	// 抛出函数
+	defineExpose({
+		onOpen
+	})
+</script>

+ 262 - 0
snowy-plugin/snowy-plugin-gen/target/classes/frontend/index.vue.btl

@@ -0,0 +1,262 @@
+<template>
+	<%
+	var searchCount = 0;
+	var row = 0;
+	%>
+	<% for(var i = 0; i < configList.~size; i++) { %>
+		<% if(!configList[i].needTableId && configList[i].needPage) { searchCount ++; }%>
+	<% } %>
+	<a-card :bordered="false">
+		<% if (searchCount > 0) { %>
+		<a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
+			<a-row :gutter="24">
+				<% for(var i = 0; i < configList.~size; i++) { %>
+				<% if(!configList[i].needTableId && configList[i].needPage) { row ++; %>
+				<% if(row <= 3) { %>
+				<a-col :span="6">
+				<% if(configList[i].effectType == 'input' || configList[i].effectType == 'textarea') { %>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-input v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" />
+					</a-form-item>
+				<% } else if (configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-select v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+					</a-form-item>
+				<% } else if (configList[i].effectType == 'inputNumber' || configList[i].effectType == 'slider') {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-input-number v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" style="width: 100%" />
+					</a-form-item>
+				<% } else if (configList[i].effectType == 'datepicker') {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-range-picker v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" value-format="YYYY-MM-DD HH:mm:ss" show-time />
+					</a-form-item>
+				<% } else {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-input v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" />
+					</a-form-item>
+				<% } %>
+				</a-col>
+				<% } else { %>
+				<a-col :span="6" v-show="advanced">
+				<% if(configList[i].effectType == 'input' || configList[i].effectType == 'textarea') { %>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-input v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" />
+					</a-form-item>
+				<% } else if (configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-select v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请选择${configList[i].fieldRemark}" :options="${configList[i].fieldNameCamelCase}Options" />
+					</a-form-item>
+				<% } else if (configList[i].effectType == 'inputNumber' || configList[i].effectType == 'slider') {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-input-number v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" style="width: 100%" />
+					</a-form-item>
+				<% } else if (configList[i].effectType == 'datepicker') {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-range-picker v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" show-time />
+					</a-form-item>
+				<% } else {%>
+					<a-form-item label="${configList[i].fieldRemark}" name="${configList[i].fieldNameCamelCase}">
+						<a-input v-model:value="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}" />
+					</a-form-item>
+				<% } %>
+				</a-col>
+				<% } %>
+				<% } %>
+				<% } %>
+				<a-col :span="6">
+					<a-button type="primary" @click="table.refresh(true)">查询</a-button>
+					<a-button style="margin: 0 8px" @click="reset">重置</a-button>
+					<% if(searchCount > 3) { %>
+					<a @click="toggleAdvanced" style="margin-left: 8px">
+						{{ advanced ? '收起' : '展开' }}
+						<component :is="advanced ? 'up-outlined' : 'down-outlined'"/>
+					</a>
+					<% }%>
+				</a-col>
+			</a-row>
+		</a-form>
+		<% } %>
+		<s-table
+			ref="table"
+			:columns="columns"
+			:data="loadData"
+			:alert="options.alert.show"
+			bordered
+			<% for(var i = 0; i < configList.~size; i++) { %>
+			<% if(configList[i].needTableId) { %>
+			:row-key="(record) => record.${configList[i].fieldNameCamelCase}"
+			<% } %>
+			<% } %>
+			:tool-config="toolConfig"
+			:row-selection="options.rowSelection"
+		>
+			<template #operator class="table-operator">
+				<a-space>
+					<a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('${classNameFirstLower}Add')">
+						<template #icon><plus-outlined /></template>
+						新增
+					</a-button>
+					<xn-batch-delete
+						v-if="hasPerm('${classNameFirstLower}BatchDelete')"
+						:selectedRowKeys="selectedRowKeys"
+						@batchDelete="deleteBatch${className}"
+					/>
+				</a-space>
+			</template>
+			<template #bodyCell="{ column, record }">
+				<% for(var i = 0; i < configList.~size; i++) { %>
+				<% if(!configList[i].needTableId && configList[i].whetherTable) { %>
+				<% if (configList[i].effectType == 'select' || configList[i].effectType == 'radio') { %>
+				<template v-if="column.dataIndex === '${configList[i].fieldNameCamelCase}'">
+					{{ $TOOL.dictTypeData('${configList[i].dictTypeCode}', record.${configList[i].fieldNameCamelCase}) }}
+				</template>
+				<% } else if (configList[i].effectType == 'checkbox') { %>
+				<template v-if="column.dataIndex === '${configList[i].fieldNameCamelCase}'">
+					<a-tag v-for="textValue in JSON.parse(record.${configList[i].fieldNameCamelCase})" :key="textValue" color="green">{{ $TOOL.dictTypeData('${configList[i].dictTypeCode}', textValue) }}</a-tag>
+				</template>
+				<% } %>
+				<% } %>
+				<% } %>
+				<template v-if="column.dataIndex === 'action'">
+					<a-space>
+						<a @click="formRef.onOpen(record)" v-if="hasPerm('${classNameFirstLower}Edit')">编辑</a>
+						<a-divider type="vertical" v-if="hasPerm(['${classNameFirstLower}Edit', '${classNameFirstLower}Delete'], 'and')" />
+						<a-popconfirm title="确定要删除吗?" @confirm="delete${className}(record)">
+							<a-button type="link" danger size="small" v-if="hasPerm('${classNameFirstLower}Delete')">删除</a-button>
+						</a-popconfirm>
+					</a-space>
+				</template>
+			</template>
+		</s-table>
+	</a-card>
+	<Form ref="formRef" @successful="table.refresh(true)" />
+</template>
+
+<script setup name="${busName}">
+	<%
+	var iptTool = 0;
+	if (searchCount > 0) {
+		for(var i = 0; i < configList.~size; i++) {
+			if(!configList[i].needTableId) {
+			if(configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') {
+				iptTool++;
+			}
+			}
+		}
+	}
+	%>
+	<% if(iptTool > 0) { %>
+	import tool from '@/utils/tool'
+	<% } %>
+	import Form from './form.vue'
+	import ${classNameFirstLower}Api from '@/api/${moduleName}/${classNameFirstLower}Api'
+	<% if (searchCount > 0) { %>
+	let searchFormState = reactive({})
+	const searchFormRef = ref()
+	<% } %>
+	const table = ref()
+	const formRef = ref()
+	const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+	<% if(searchCount > 3) { %>
+	// 查询区域显示更多控制
+	const advanced = ref(false)
+	const toggleAdvanced = () => {
+		advanced.value = !advanced.value
+	}
+	<% } %>
+	const columns = [
+	<% for(var i = 0; i < configList.~size; i++) { %>
+	<% if(!configList[i].needTableId && configList[i].whetherTable) { %>
+		{
+			title: '${configList[i].fieldRemark}',
+			dataIndex: '${configList[i].fieldNameCamelCase}'<% if(configList[i].whetherRetract) { %>,<% } %>
+			<% if(configList[i].whetherRetract) { %>
+			ellipsis: true
+			<% } %>
+		},
+	<% } %>
+	<% } %>
+	]
+	// 操作栏通过权限判断是否显示
+	if (hasPerm(['${classNameFirstLower}Edit', '${classNameFirstLower}Delete'])) {
+		columns.push({
+			title: '操作',
+			dataIndex: 'action',
+			align: 'center',
+			width: '150px'
+		})
+	}
+	const selectedRowKeys = ref([])
+	// 列表选择配置
+	const options = {
+		// columns数字类型字段加入 needTotal: true 可以勾选自动算账
+		alert: {
+			show: true,
+			clear: () => {
+				selectedRowKeys.value = ref([])
+			}
+		},
+		rowSelection: {
+			onChange: (selectedRowKey, selectedRows) => {
+				selectedRowKeys.value = selectedRowKey
+			}
+		}
+	}
+	const loadData = (parameter) => {
+		<% if (searchCount > 0) { %>
+		const searchFormParam = JSON.parse(JSON.stringify(searchFormState))
+		<% for(var i = 0; i < configList.~size; i++) { %>
+		<% if(!configList[i].needTableId && configList[i].needPage) { %>
+		<% if (configList[i].effectType == 'datepicker') {%>
+		// ${configList[i].fieldNameCamelCase}范围查询条件重载
+		if (searchFormParam.${configList[i].fieldNameCamelCase}) {
+			searchFormParam.start${configList[i].fieldNameCamelCaseFirstUpper} = searchFormParam.${configList[i].fieldNameCamelCase}[0]
+			searchFormParam.end${configList[i].fieldNameCamelCaseFirstUpper} = searchFormParam.${configList[i].fieldNameCamelCase}[1]
+			delete searchFormParam.${configList[i].fieldNameCamelCase}
+		}
+		<% } %>
+		<% } %>
+		<% } %>
+		return ${classNameFirstLower}Api.${classNameFirstLower}Page(Object.assign(parameter, searchFormParam)).then((data) => {
+		<% } else { %>
+		return ${classNameFirstLower}Api.${classNameFirstLower}Page(parameter).then((data) => {
+		<% } %>
+			return data
+		})
+	}
+	// 重置
+	const reset = () => {
+		searchFormRef.value.resetFields()
+		table.value.refresh(true)
+	}
+	// 删除
+	const delete${className} = (record) => {
+		let params = [
+			{
+				<% for(var i = 0; i < configList.~size; i++) { %>
+				<% if(configList[i].needTableId) { %>
+				${configList[i].fieldNameCamelCase}: record.${configList[i].fieldNameCamelCase}
+				<% } %>
+				<% } %>
+			}
+		]
+		${classNameFirstLower}Api.${classNameFirstLower}Delete(params).then(() => {
+			table.value.refresh(true)
+		})
+	}
+	// 批量删除
+	const deleteBatch${className} = (params) => {
+		${classNameFirstLower}Api.${classNameFirstLower}Delete(params).then(() => {
+			table.value.clearRefreshSelected()
+		})
+	}
+	<% if (searchCount > 0) { %>
+	<% for(var i = 0; i < configList.~size; i++) { %>
+	<% if(!configList[i].needTableId && configList[i].needPage) { %>
+	<% if (configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') { %>
+	const ${configList[i].fieldNameCamelCase}Options = tool.dictList('${configList[i].dictTypeCode}')
+	<% } %>
+	<% } %>
+	<% } %>
+	<% } %>
+</script>

+ 34 - 0
snowy-plugin/snowy-plugin-gen/target/classes/mobile/Api.js.btl

@@ -0,0 +1,34 @@
+import request from '@/utils/request'
+
+// 获取${functionName}分页
+export function ${classNameFirstLower}Page(data) {
+    return request({
+        url: '/${moduleName}/${busName}/page',
+        method: 'get',
+        data: data
+    })
+}
+// 提交${functionName}表单 add为false时为编辑,默认为新增
+export function ${classNameFirstLower}SubmitForm(data, add = true) {
+    return request({
+        url: '/${moduleName}/${busName}/'+ (add ? 'add' : 'edit'),
+        method: 'post',
+        data: data
+    })
+}
+// 删除${functionName}
+export function ${classNameFirstLower}Delete(data) {
+    return request({
+        url: '/${moduleName}/${busName}/delete',
+        method: 'post',
+        data: data
+    })
+}
+//  获取${functionName}详情
+export function ${classNameFirstLower}Detail(data) {
+    return request({
+        url: '/${moduleName}/${busName}/detail',
+        method: 'get',
+        data: data
+    })
+}

+ 121 - 0
snowy-plugin/snowy-plugin-gen/target/classes/mobile/form.vue.btl

@@ -0,0 +1,121 @@
+<template>
+    <view class="container snowy-shadow">
+        <uv-form ref="formRef" :model="formData" :rules="rules" label-position="top" labelWidth="auto" :labelStyle="{marginBottom: '25rpx', fontSize: '27rpx', color: '#606266'}">
+            <% for(var i = 0; i < configList.~size; i++) { %>
+            <% if(!configList[i].needTableId && configList[i].whetherAddUpdate && configList[i].fieldNameCamelCase != 'tenantId') { %>
+            <% if(configList[i].effectType == 'input') { %>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+            	<uv-input v-model="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}"></uv-input>
+            </uv-form-item>
+            <% } else if (configList[i].effectType == 'textarea') {%>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+            	<uv-textarea v-model="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}"></uv-textarea>
+            </uv-form-item>
+            <% } else if (configList[i].effectType == 'select') {%>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+                <snowy-sel-picker :map="{key: 'value', label: 'text'}" v-model="formData.${configList[i].fieldNameCamelCase}" :rangeData="${configList[i].fieldNameCamelCase}Options" placeholder="请选择${configList[i].fieldRemark}"></snowy-sel-picker>
+            </uv-form-item>
+            <% } else if (configList[i].effectType == 'radio') {%>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+                <uv-radio-group v-model="formData.${configList[i].fieldNameCamelCase}">
+                    <uv-radio :customStyle="{marginRight: '50rpx'}" v-for="(item, index) in ${configList[i].fieldNameCamelCase}Options" :key="index" :name="item.value" :label="item.text"></uv-radio>
+                </uv-radio-group>
+            </uv-form-item>
+            <% } else if (configList[i].effectType == 'checkbox') {%>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+                <uv-checkbox-group v-model="formData.${configList[i].fieldNameCamelCase}">
+                    <uv-checkbox :customStyle="{marginRight: '50rpx'}" v-for="(item, index) in ${configList[i].fieldNameCamelCase}Options" :key="index"  :name="item.value" :label="item.text"></uv-checkbox>
+                </uv-checkbox-group>
+            </uv-form-item>
+            <% } else if (configList[i].effectType == 'datepicker') {%>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+                <snowy-calendar v-model="formData.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}"></snowy-calendar>
+            </uv-form-item>
+            <% } else if (configList[i].effectType == 'timepicker') {%>
+
+            <% } else if (configList[i].effectType == 'inputNumber') {%>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+                <uv-number-box v-model="formData.${configList[i].fieldNameCamelCase}" :min="1" :max="100"></uv-number-box>
+            </uv-form-item>
+            <% } else if (configList[i].effectType == 'slider') {%>
+            <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}" :required="${configList[i].required}">
+                <slider :value="formData.${configList[i].fieldNameCamelCase}" :min="1" :max="100" :step="1" @change="(e)=>{formData.${configList[i].fieldNameCamelCase} = e.detail.value}"></slider>
+            </uv-form-item>
+            <% } %>
+            <% } %>
+            <% } %>
+        </uv-form>
+        <tui-button margin="50rpx 0" :preventClick="true" :shadow="true" @click="submit">提交</tui-button>
+    </view>
+</template>
+<script setup name="${classNameFirstLower}Form">
+    import { onLoad } from "@dcloudio/uni-app"
+    import { ${classNameFirstLower}Detail, ${classNameFirstLower}SubmitForm } from '@/api/${moduleName}/${classNameFirstLower}Api'
+    import { reactive, ref, getCurrentInstance } from "vue"
+
+    const { proxy } = getCurrentInstance()
+    const formRef = ref()
+    const formData = ref({
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(!configList[i].needTableId && configList[i].whetherAddUpdate && configList[i].fieldNameCamelCase != 'tenantId') { %>
+        ${configList[i].fieldNameCamelCase}: '',
+        <% } %>
+        <% } %>
+    })
+    // https://www.uvui.cn/components/form.html
+    // 去pages/biz/user/form.vue中寻找示例
+    const rules = reactive({
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(!configList[i].needTableId && configList[i].whetherAddUpdate && configList[i].fieldNameCamelCase != 'tenantId' && configList[i].required) { %>
+        ${configList[i].fieldNameCamelCase}: [{
+            type: 'string',
+            required: true,
+            message: '请输入${configList[i].fieldRemark}',
+            trigger: ['blur', 'change']
+        }],
+        <% } %>
+        <% } %>
+    })
+    <% for(var i = 0; i < configList.~size; i++) { %>
+    <% if(!configList[i].needTableId) { %>
+    <% if(configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') { %>
+    const ${configList[i].fieldNameCamelCase}Options = ref([])
+    <% } %>
+    <% } %>
+    <% } %>
+    onLoad((option) => {
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(!configList[i].needTableId) { %>
+        <% if(configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') { %>
+        ${configList[i].fieldNameCamelCase}Options.value = uni.$snowy.tool.dictList('${configList[i].dictTypeCode}')
+        <% } %>
+        <% } %>
+        <% } %>
+        if(!option.id){
+            return
+        }
+        ${classNameFirstLower}Detail({
+            id: option.id
+        }).then(res => {
+            formData.value = res?.data
+        })
+    })
+    const submit = () => {
+        formRef.value.validate().then(res => {
+            ${classNameFirstLower}SubmitForm(formData.value, !formData.value.id).then(respond => {
+                uni.$emit('formBack', {
+                    data: respond.data
+                })
+                uni.navigateBack({
+                    delta: 1
+                })
+            })
+        })
+    }
+</script>
+<style lang="scss" scoped>
+    .container {
+        margin: 80rpx 0 0;
+        padding: 30rpx;
+    }
+</style>

+ 128 - 0
snowy-plugin/snowy-plugin-gen/target/classes/mobile/index.vue.btl

@@ -0,0 +1,128 @@
+<template>
+    <%
+    var searchCount = 0;
+    var row = 0;
+    %>
+    <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(!configList[i].needTableId && configList[i].needPage) { searchCount ++; }%>
+    <% } %>
+    <% if (searchCount > 0) { %>
+    <% for(var i = 0; i < configList.~size; i++) { %>
+    <% if(!configList[i].needTableId && configList[i].needPage) { row ++; %>
+    <% if(row <= 1) { %>
+    <snowy-search placeholder="请输入${configList[i].fieldRemark}" v-model="searchFormState.${configList[i].fieldNameCamelCase}" @confirm="loadData(true)" @clear="loadData(true)" :enableSenior="true" @seniorSearch="$refs.searchRef.open()"></snowy-search>
+    <% } %>
+    <% } %>
+    <% } %>
+    <search ref="searchRef" :searchFormState="searchFormState" @confirm="loadData(true)"></search>
+    <% } %>
+    <view class="${busName}-list">
+        <view class="item" v-for="(item, index) in ${classNameFirstLower}Data" :key="index" :index="index" @tap="moreTapItem(item, index)">
+            <% for(var i = 0; i < configList.~size; i++) { %>
+            <% if(!configList[i].needTableId && configList[i].whetherTable && configList[i].fieldNameCamelCase != 'tenantId') { %>
+            <uv-row customStyle="margin-bottom: 15rpx">
+                <uv-col :span="1">
+                    <uv-icon size="18" name="tags-fill" color="#5677fc"></uv-icon>
+                </uv-col>
+                <uv-col :span="5">
+                    <view class="item-left">${configList[i].fieldRemark}</view>
+                </uv-col>
+                <uv-col :span="6" textAlign="right">
+                    <view class="item-right snowy-bold snowy-ellipsis"> {{ item.${configList[i].fieldNameCamelCase} }} </view>
+                </uv-col>
+            </uv-row>
+            <% } %>
+            <% } %>
+        </view>
+    </view>
+    <snowy-empty :fixed="true" v-show="$xeu.isEmpty(${classNameFirstLower}Data)" />
+    <snowy-float-btn v-if="$snowy.hasPerm('mobile${className}Add')" @click="add"></snowy-float-btn>
+    <more ref="moreRef" @handleOk="loadData(true)"></more>
+</template>
+
+<script setup name="${busName}">
+    <% if (searchCount > 0) { %>
+    import search from './search.vue'
+    <% } %>
+    import { ${classNameFirstLower}Page } from '@/api/${moduleName}/${classNameFirstLower}Api'
+    import more from './more.vue'
+    import { onLoad, onShow, onReady, onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app"
+    import { reactive, ref, getCurrentInstance } from "vue"
+    const { proxy } = getCurrentInstance()
+    const searchFormState = reactive({
+        <% if (searchCount > 0) { %>
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(!configList[i].needTableId && configList[i].needPage) { %>
+        ${configList[i].fieldNameCamelCase}: '',
+        <% } %>
+        <% } %>
+        <% } %>
+    })
+    const parameter = reactive({
+    	current: 1,
+    	size: 10
+    })
+    const ${classNameFirstLower}Data = ref([])
+    const loadData = (isReset) => {
+        if (isReset) {
+        	parameter.current = 1
+        	${classNameFirstLower}Data.value = []
+        }
+        Object.assign(parameter, searchFormState)
+        ${classNameFirstLower}Page(parameter).then(res => {
+            if (uni.$xeu.isEmpty(res?.data?.records)){
+            	return
+            }
+            ${classNameFirstLower}Data.value = ${classNameFirstLower}Data.value.concat(res.data.records)
+            parameter.current++
+        }).finally(()=>{
+          	uni.stopPullDownRefresh()
+        })
+    }
+    loadData(true)
+    onShow(() => {
+    	uni.$once('formBack', (data) => {
+            loadData(true)
+    	})
+    })
+    // 下拉刷新
+    onPullDownRefresh(() => {
+    	loadData(true)
+    })
+    // 上拉加载
+    onReachBottom(() => {
+    	loadData()
+    })
+    // 新增
+    const add = () => {
+    	uni.navigateTo({
+            url: '/pages/${moduleName}/${busName}/form'
+    	})
+    }
+    // 更多操作
+    const moreRef = ref()
+    const moreTapItem = (item, index) => {
+        moreRef.value.open(item)
+    }
+</script>
+
+<style lang="scss" scoped>
+    .${busName}-list {}
+    .item {
+        background: #ffffff;
+        margin: 20rpx 0;
+        padding: 25rpx;
+        box-shadow: 0 1px 2px #ccc;
+        border-radius: 15rpx;
+        .item-left {
+            color: #999;
+            font-size: 26rpx;
+        }
+        .item-right {
+            font-size: 26rpx;
+        }
+    }
+    .item:hover {
+        box-shadow: 1upx 5upx 5upx #5677fc;
+    }
+</style>

+ 62 - 0
snowy-plugin/snowy-plugin-gen/target/classes/mobile/more.vue.btl

@@ -0,0 +1,62 @@
+<template>
+    <uv-popup ref="popRef" mode="bottom" bg-color="null" z-index="99">
+        <view class="container">
+            <tui-list-view unlined="all" background-color="transparent">
+                <tui-list-cell v-if="$snowy.hasPerm('mobile${className}Edit')" :hover="true" :arrow="false" @click="edit" :radius="10" >
+                    <view class="item"> 编辑 </view>
+                </tui-list-cell>
+                <tui-list-cell v-if="$snowy.hasPerm('mobile${className}Delete')" :hover="true" :arrow="false" @click="del" :radius="10" :margin-top="2">
+                    <view class="item"> 刪除 </view>
+                </tui-list-cell>
+                <tui-list-cell :hover="true" :arrow="false" @click="cancel" :margin-top="10" :radius="10">
+                    <view class="item"> 取消 </view>
+                </tui-list-cell>
+            </tui-list-view>
+        </view>
+    </uv-popup>
+</template>
+<script setup name="${classNameFirstLower}More">
+    import { ${classNameFirstLower}Delete } from '@/api/${moduleName}/${classNameFirstLower}Api'
+    import { reactive, ref, getCurrentInstance } from "vue"
+    const emits = defineEmits(['handleOk'])
+    const popRef = ref()
+    const record = ref({})
+    const open = (data) => {
+    	record.value = data
+    	popRef.value.open()
+    }
+    // 编辑
+    const edit = () => {
+    	uni.navigateTo({
+            url: '/pages/${moduleName}/${busName}/form?id=' + record.value.id
+    	})
+    	popupRef.value.close()
+    }
+    // 删除
+    const del = () => {
+    	uni.$snowy.modal.confirm(`确定要删除吗?`).then(() => {
+            ${classNameFirstLower}Delete([{
+                id: record.value.id
+            }]).then(res => {
+                emits('handleOk')
+                popupRef.value.close()
+            })
+    	})
+    }
+    // 取消
+    const cancel = () => {
+    	popupRef.value.close()
+    }
+    defineExpose({
+    	open
+    })
+</script>
+<style lang="scss" scoped>
+    .container {
+        padding: 5upx;
+        background-color: transparent;
+        .item {
+            text-align: center;
+        }
+    }
+</style>

+ 47 - 0
snowy-plugin/snowy-plugin-gen/target/classes/mobile/page.json.btl

@@ -0,0 +1,47 @@
+// 二选一 将代码复制到page.json文件中
+
+// 不使用分包
+{
+    "path": "pages/${moduleName}/${busName}/index",
+    "style": {
+        "navigationBarTitleText": "${functionName}管理",
+        "enablePullDownRefresh": true,
+        //#ifdef H5
+        "navigationStyle": "custom"
+        //#endif
+    }
+}, {
+    "path": "pages/${moduleName}/${busName}/form",
+    "style": {
+        "navigationBarTitleText": "${functionName}管理",
+        "enablePullDownRefresh": false,
+        //#ifdef H5
+        "navigationStyle": "custom"
+        //#endif
+    }
+},
+
+
+// 使用分包(微信小程序开发主包不能超过2m,所以建议使用分包)
+{
+    "root": "pages/${moduleName}/${busName}",
+    "pages": [{
+        "path": "index",
+        "style": {
+            "navigationBarTitleText": "${functionName}管理",
+            "enablePullDownRefresh": true,
+            //#ifdef H5
+            "navigationStyle": "custom"
+            //#endif
+        }
+    },{
+        "path": "form",
+        "style": {
+            "navigationBarTitleText": "${functionName}管理",
+            "enablePullDownRefresh": false,
+            //#ifdef H5
+            "navigationStyle": "custom"
+            //#endif
+        }
+    }]
+}

+ 99 - 0
snowy-plugin/snowy-plugin-gen/target/classes/mobile/search.vue.btl

@@ -0,0 +1,99 @@
+<template>
+    <%
+    var searchCount = 0;
+    var row = 0;
+    %>
+    <% for(var i = 0; i < configList.~size; i++) { %>
+       <% if(!configList[i].needTableId && configList[i].needPage) { searchCount ++; }%>
+    <% } %>
+    <uv-popup ref="popRef" mode="bottom" bg-color="null" z-index="99">
+        <view class="container">
+            <view class="close">
+                <icon type="clear" :size="20" color="#5677fc" @click="close"></icon>
+            </view>
+            <% if (searchCount > 0) { %>
+            <uv-form ref="formRef" :model="searchFormState" label-position="top" labelWidth="auto" :labelStyle="{marginBottom: '25rpx', fontSize: '27rpx', color: '#606266'}">
+                <% for(var i = 0; i < configList.~size; i++) { %>
+                <% if(!configList[i].needTableId && configList[i].needPage) { %>
+                <% if(configList[i].effectType == 'input' || configList[i].effectType == 'textarea') { %>
+                <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}">
+                    <uv-input v-model="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}"></uv-input>
+                </uv-form-item>
+                <% } else if (configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') {%>
+                <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}">
+                    <snowy-sel-picker :map="{key: 'value', label: 'text'}" v-model="searchFormState.${configList[i].fieldNameCamelCase}" :rangeData="${configList[i].fieldNameCamelCase}Options" placeholder="请选择${configList[i].fieldRemark}"></snowy-sel-picker>
+                </uv-form-item>
+                <% } else {%>
+                <uv-form-item label="${configList[i].fieldRemark}" prop="${configList[i].fieldNameCamelCase}">
+                    <uv-input v-model="searchFormState.${configList[i].fieldNameCamelCase}" placeholder="请输入${configList[i].fieldRemark}"></uv-input>
+                </uv-form-item>
+                <% } %>
+                <% } %>
+                <% } %>
+            </uv-form>
+            <% } %>
+            <uv-row :gutter="10">
+                <uv-col :span="6">
+                    <tui-button height="90rpx" type="gray" @click="reset">重置</tui-button>
+                </uv-col>
+                <uv-col :span="6">
+                    <tui-button height="90rpx" type="primary" @click="confirm">确认</tui-button>
+                </uv-col>
+            </uv-row>
+        </view>
+    </uv-popup>
+</template>
+<script setup name="${classNameFirstLower}Search">
+    import { ref } from "vue"
+    const emits = defineEmits(['reset', 'confirm'])
+    const props = defineProps({
+    	searchFormState: {
+            type: Object,
+            required: true
+    	},
+    })
+    <% if (searchCount > 0) { %>
+    <% for(var i = 0; i < configList.~size; i++) { %>
+    <% if(!configList[i].needTableId && configList[i].needPage) { %>
+    <% if (configList[i].effectType == 'select' || configList[i].effectType == 'radio' || configList[i].effectType == 'checkbox') { %>
+    const ${configList[i].fieldNameCamelCase}Options = uni.$snowy.tool.dictList('${configList[i].dictTypeCode}')
+    <% } %>
+    <% } %>
+    <% } %>
+    <% } %>
+    const popRef = ref()
+    const open = () => {
+    	popRef.value.open()
+    }
+    const reset = () =>{
+        // 重置数据
+        <% for(var i = 0; i < configList.~size; i++) { %>
+        <% if(!configList[i].needTableId && configList[i].needPage) { %>
+        props.searchFormState.${configList[i].fieldNameCamelCase} = ''
+        <% } %>
+        <% } %>
+    	emits('reset', props.searchFormState)
+    }
+    const confirm = () => {
+    	popRef.value.close()
+    	emits('confirm', props.searchFormState)
+    }
+    const close = () => {
+        popRef.value.close()
+    }
+    defineExpose({
+    	open
+    })
+</script>
+<style lang="scss" scoped>
+    .container {
+        margin: 5rpx;
+        border-radius: 10rpx;
+        padding: 20rpx;
+        background-color: white;
+        .close {
+            display: flex;
+            justify-content: flex-end;
+        }
+    }
+</style>

+ 25 - 0
snowy-plugin/snowy-plugin-gen/target/classes/sqlend/Mysql.sql.btl

@@ -0,0 +1,25 @@
+/*
+ Source Server Type: MySQL
+ Date: ${genTime}
+*/
+
+INSERT INTO `SYS_RESOURCE` VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `SYS_RESOURCE` VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `SYS_RESOURCE` VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `SYS_RESOURCE` VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `SYS_RESOURCE` VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+
+<% if (mobileModuleId != null && mobileModuleId != '') { %>
+INSERT INTO `MOBILE_RESOURCE` VALUES ('${menuId}', '0', '${functionName}管理', NULL, 'MENU', '${mobileModuleId}', 'MENU', '/pages/${moduleName}/${busName}/index', 'apartment-outlined',  '#1890ff', 'YES', 'ENABLE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `MOBILE_RESOURCE` VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', 'mobile${className}Add', 'BUTTON', NULL, NULL, NULL, NULL,  NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `MOBILE_RESOURCE` VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', 'mobile${className}Edit', 'BUTTON', NULL, NULL, NULL, NULL,  NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO `MOBILE_RESOURCE` VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', 'mobile${className}Delete', 'BUTTON', NULL, NULL, NULL, NULL,  NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+<% } %>

+ 25 - 0
snowy-plugin/snowy-plugin-gen/target/classes/sqlend/Oracle.sql.btl

@@ -0,0 +1,25 @@
+/*
+ Source Server Type: Oracle
+ Date: ${genTime}
+*/
+
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, '99', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '1', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '3', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '4', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+
+<% if (mobileModuleId != null && mobileModuleId != '') { %>
+INSERT INTO "SNOWY"."MOBILE_RESOURCE" VALUES ('${menuId}', '0', '${functionName}管理', NULL, 'MENU', '${mobileModuleId}', 'MENU', '/pages/${moduleName}/${busName}/index', 'apartment-outlined',  '#1890ff', 'YES', 'ENABLE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."MOBILE_RESOURCE" VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', 'mobile${className}Add', 'BUTTON', NULL, NULL, NULL, NULL,  NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."MOBILE_RESOURCE" VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', 'mobile${className}Edit', 'BUTTON', NULL, NULL, NULL, NULL,  NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+
+INSERT INTO "SNOWY"."MOBILE_RESOURCE" VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', 'mobile${className}Delete', 'BUTTON', NULL, NULL, NULL, NULL,  NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
+<% } %>

+ 5 - 0
snowy-plugin/snowy-plugin-gen/target/classes/vip/xiaonuo/gen/modular/basic/mapper/mapping/GenBasicMapper.xml

@@ -0,0 +1,5 @@
+<?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.xiaonuo.gen.modular.basic.mapper.GenBasicMapper">
+
+</mapper>

+ 5 - 0
snowy-plugin/snowy-plugin-gen/target/classes/vip/xiaonuo/gen/modular/config/mapper/mapping/GenConfigMapper.xml

@@ -0,0 +1,5 @@
+<?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.xiaonuo.gen.modular.config.mapper.GenConfigMapper">
+
+</mapper>

+ 1 - 0
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/README.md

@@ -0,0 +1 @@
+图标文件来源:https://www.aigei.com/s?q=%E6%96%87%E4%BB%B6&detailTab=file&type=icon_7&page=11#resContainer

二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/docx.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/file.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/gif.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/html.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/img.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/pdf.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/png.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/ppt.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/rar.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/txt.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/xlsx.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/fileImg/zip.png


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/swiper/swiper1.jpg


二進制
snowy-plugin/snowy-plugin-mobile/target/classes/static/images/swiper/swiper2.jpg


+ 5 - 0
snowy-plugin/snowy-plugin-mobile/target/classes/vip/xiaonuo/mobile/modular/resource/mapper/mapping/MobileButtonMapper.xml

@@ -0,0 +1,5 @@
+<?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.xiaonuo.mobile.modular.resource.mapper.MobileButtonMapper">
+
+</mapper>

+ 5 - 0
snowy-plugin/snowy-plugin-mobile/target/classes/vip/xiaonuo/mobile/modular/resource/mapper/mapping/MobileMenuMapper.xml

@@ -0,0 +1,5 @@
+<?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.xiaonuo.mobile.modular.resource.mapper.MobileMenuMapper">
+
+</mapper>

+ 5 - 0
snowy-plugin/snowy-plugin-mobile/target/classes/vip/xiaonuo/mobile/modular/resource/mapper/mapping/MobileModuleMapper.xml

@@ -0,0 +1,5 @@
+<?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.xiaonuo.mobile.modular.resource.mapper.MobileModuleMapper">
+
+</mapper>

二進制
snowy-plugin/snowy-plugin-sys/target/classes/userExportTemplate.docx


二進制
snowy-plugin/snowy-plugin-sys/target/classes/userImportTemplate.xlsx


+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.org.mapper.SysOrgMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/position/mapper/mapping/SysPositionMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.position.mapper.SysPositionMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/relation/mapper/mapping/SysRelationMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.relation.mapper.SysRelationMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysButtonMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.resource.mapper.SysButtonMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysMenuMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.resource.mapper.SysMenuMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysModuleMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.resource.mapper.SysModuleMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/role/mapper/mapping/SysRoleMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.role.mapper.SysRoleMapper">
+
+
+</mapper>

+ 6 - 0
snowy-plugin/snowy-plugin-sys/target/classes/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserMapper.xml

@@ -0,0 +1,6 @@
+<?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.xiaonuo.sys.modular.user.mapper.SysUserMapper">
+
+
+</mapper>