From 881f273bca0f94345efb2c0cac52279af4a7f4e4 Mon Sep 17 00:00:00 2001
From: admin <weikou2014>
Date: 星期五, 24 九月 2021 15:16:08 +0800
Subject: [PATCH] 后台管理自动化代码生成

---
 src/main/java/org/yeshi/utils/generater/entity/MongoDBDaoData.java              |   22 
 src/main/java/org/yeshi/utils/generater/util/AnotationUtil.java                 |  132 +++++
 src/main/resources/generater/admin/form/textArea.ftl                            |    3 
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/Switch.java       |   28 +
 src/main/java/org/yeshi/utils/generater/entity/admin/AdminGeneraterInfo.java    |  115 ++++
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/RadioGroup.java   |   31 +
 src/main/resources/generater/admin/form/switch.ftl                              |    3 
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/Password.java     |   37 +
 src/main/java/org/yeshi/utils/generater/exception/AnotationException.java       |    9 
 src/main/resources/generater/admin/adminController.template                     |   10 
 src/main/java/org/yeshi/utils/FreemarkerUtils.java                              |   29 +
 src/main/resources/generater/admin/form/select.ftl                              |    9 
 src/main/resources/generater/mongoDBDao.template                                |   10 
 src/main/java/org/yeshi/utils/generater/entity/CommonSearchForm.java            |   44 +
 src/main/resources/generater/admin/list.flt                                     |   10 
 src/main/resources/generater/admin/update.ftl                                   |   10 
 src/main/java/org/yeshi/utils/generater/util/FormAnotationValidUtil.java        |  127 ++++
 src/main/java/org/yeshi/utils/generater/entity/admin/FormVerifyType.java        |   17 
 src/main/resources/generater/admin/form/checkBox.ftl                            |    3 
 src/main/resources/generater/serviceImpl.template                               |    0 
 src/main/java/org/yeshi/utils/generater/SpringComponentGenerater.java           |    6 
 src/main/resources/generater/admin/form/img.ftl                                 |    6 
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/TextArea.java     |   52 ++
 src/main/resources/generater/admin/form/text.ftl                                |    4 
 src/main/java/org/yeshi/utils/generater/annotation/admin/DaoQueryCondition.java |   27 +
 src/test/java/com/generater/GeneratorTest.java                                  |   69 ++
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/CheckBox.java     |   37 +
 src/main/java/org/yeshi/utils/generater/entity/DaoQueryColumnData.java          |   23 
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/Img.java          |   34 +
 src/main/resources/generater/admin/form/password.ftl                            |    4 
 src/main/java/org/yeshi/utils/generater/annotation/admin/Show.java              |   44 +
 src/main/java/org/yeshi/utils/ios/pay/vo/IOSAPPBuyVerifyResult.java             |   11 
 src/test/java/com/generater/TestEntity.java                                     |  132 +++++
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/Select.java       |   39 +
 src/main/java/org/yeshi/utils/generater/entity/admin/FormRowData.java           |   43 +
 src/main/java/org/yeshi/utils/generater/annotation/admin/form/Text.java         |   62 ++
 src/main/java/org/yeshi/utils/generater/annotation/admin/AdminController.java   |   40 +
 src/main/resources/generater/admin/form/radioGroup.ftl                          |    5 
 src/main/resources/generater/admin/add.ftl                                      |  181 ++++++
 src/main/java/org/yeshi/utils/generater/entity/KeyValue.java                    |   33 +
 src/main/java/org/yeshi/utils/ios/pay/IOSPayVerifyUtil.java                     |   18 
 src/main/resources/generater/service.template                                   |    0 
 42 files changed, 1,496 insertions(+), 23 deletions(-)

diff --git a/src/main/java/org/yeshi/utils/FreemarkerUtils.java b/src/main/java/org/yeshi/utils/FreemarkerUtils.java
index 7227ce3..c552804 100644
--- a/src/main/java/org/yeshi/utils/FreemarkerUtils.java
+++ b/src/main/java/org/yeshi/utils/FreemarkerUtils.java
@@ -6,6 +6,8 @@
 import org.apache.commons.io.IOUtils;
 
 import java.io.*;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 public class FreemarkerUtils {
@@ -54,17 +56,40 @@
         return generateString(data, str);
     }
 
+
+    public static String generateInputStream(Object data, String name, Map<String, InputStream> templateStreams) throws IOException {
+        String result = null;
+        try {
+            StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
+            for (Iterator<String> its = templateStreams.keySet().iterator(); its.hasNext(); ) {
+                String key = its.next();
+                stringTemplateLoader.putTemplate(key, IOUtils.toString(templateStreams.get(key), "UTF-8"));
+            }
+            cfg.setTemplateLoader(stringTemplateLoader);
+            Template template = cfg.getTemplate(name, defaultCharacter);
+            StringWriter out = new StringWriter();
+            template.process(data, out);
+            out.flush();
+            result = out.toString();
+            out.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+
     /**
      * 灏嗘ā鏉挎覆鏌撲互鍚庝繚瀛樺埌鏂囦欢
      *
      * @param templateFileDir  妯℃澘鐩綍
      * @param templateFileName 妯℃澘鏂囦欢鍚嶇О
      * @param targetFilePath   娓叉煋鍚庢枃浠跺悕绉�
-     * @param data          鏁版嵁
+     * @param data             鏁版嵁
      * @return
      */
     public static boolean renderingTemplateAndGenerateFile(String templateFileDir,
-                                                           String templateFileName, String targetFilePath,Object data) {
+                                                           String templateFileName, String targetFilePath, Object data) {
         boolean flag = true;
         try {
             // 璁剧疆鏂囦欢鎵�鍦ㄧ洰褰曠殑璺緞
diff --git a/src/main/java/org/yeshi/utils/generater/SpringComponentGenerater.java b/src/main/java/org/yeshi/utils/generater/SpringComponentGenerater.java
index 73b0bd0..9ad08b6 100644
--- a/src/main/java/org/yeshi/utils/generater/SpringComponentGenerater.java
+++ b/src/main/java/org/yeshi/utils/generater/SpringComponentGenerater.java
@@ -17,7 +17,7 @@
      * @throws Exception
      */
     public static void createMongoDao(MongoDBDaoData data, String targetDir) throws Exception {
-        FreemarkerUtils.renderingTemplateAndGenerateFile(SpringComponentGenerater.class.getClassLoader().getResourceAsStream("mongoDBDao.template"), new File(targetDir, data.getDaoName() + ".java").getAbsolutePath(), data);
+        FreemarkerUtils.renderingTemplateAndGenerateFile(SpringComponentGenerater.class.getClassLoader().getResourceAsStream("generater/mongoDBDao.template"), new File(targetDir, data.getDaoName() + ".java").getAbsolutePath(), data);
     }
 
     /**
@@ -29,7 +29,7 @@
      */
     public static void createService(ServiceData data, String targetDir) throws Exception {
 
-        FreemarkerUtils.renderingTemplateAndGenerateFile(SpringComponentGenerater.class.getClassLoader().getResourceAsStream("service.template"), new File(targetDir, data.getServiceClassName() + ".java").getAbsolutePath(), data);
+        FreemarkerUtils.renderingTemplateAndGenerateFile(SpringComponentGenerater.class.getClassLoader().getResourceAsStream("generater/service.template"), new File(targetDir, data.getServiceClassName() + ".java").getAbsolutePath(), data);
     }
 
     /**
@@ -41,7 +41,7 @@
      */
     public static void createServiceImpl(ServiceData data, String targetDir) throws Exception {
 
-        FreemarkerUtils.renderingTemplateAndGenerateFile(SpringComponentGenerater.class.getClassLoader().getResourceAsStream("serviceImpl.template"), new File(targetDir, data.getServiceClassName() + "Impl.java").getAbsolutePath(), data);
+        FreemarkerUtils.renderingTemplateAndGenerateFile(SpringComponentGenerater.class.getClassLoader().getResourceAsStream("generater/serviceImpl.template"), new File(targetDir, data.getServiceClassName() + "Impl.java").getAbsolutePath(), data);
     }
 
 
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/AdminController.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/AdminController.java
new file mode 100644
index 0000000..0e40e8a
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/AdminController.java
@@ -0,0 +1,40 @@
+package org.yeshi.utils.generater.annotation.admin;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: AdminController
+ * @projectName utils
+ * @description: 鍚庡彴鎺ュ彛controller
+ * @date 2021/9/2315:10
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AdminController {
+
+    //鎺ュ彛
+    String mapping();
+
+    String title();
+
+    //鏄惁寮�鍚伐鍏锋爮
+    boolean toolbar() default true;
+
+    //鏄惁寮�鍚搷浣滄爮
+    boolean operate() default true;
+
+    //榛樿寮�鍚垹闄�
+    boolean delete() default true;
+
+    //榛樿寮�鍚紪杈�
+    boolean edit() default true;
+
+    //榛樿寮�鍚垎椤�
+    boolean page() default true;
+
+    Class searchForm() default Void.class;
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/DaoQueryCondition.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/DaoQueryCondition.java
new file mode 100644
index 0000000..40ce4d3
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/DaoQueryCondition.java
@@ -0,0 +1,27 @@
+package org.yeshi.utils.generater.annotation.admin;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: DaoQueryCondition
+ * @projectName utils
+ * @description:
+ * @date 2021/9/23 13:42
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DaoQueryCondition {
+
+    //鏌ヨ绫诲瀷
+    QueryType queryType() default QueryType.equal;
+
+    //鏄剧ず绫诲瀷
+    enum QueryType {
+        start, end, contains, equal
+    }
+
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/Show.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/Show.java
new file mode 100644
index 0000000..1dcc81d
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/Show.java
@@ -0,0 +1,44 @@
+package org.yeshi.utils.generater.annotation.admin;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: Show
+ * @projectName utils
+ * @description: 鏄惁鍦ㄥ垪琛ㄤ腑鏄剧ず
+ * @date 2021/9/2313:42
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Show {
+
+    //鏄剧ず鐨勯『搴�
+    int order() default 0;
+
+    //鏍囬
+    String title();
+
+
+    //鏄剧ず绫诲瀷
+    ShowType showType() default ShowType.TEXT;
+
+
+    //鏄剧ず绫诲瀷涓篒MG鏃剁敓鏁�
+    int imgWidth() default -1;
+
+    int imgHeight() default -1;
+
+
+    //褰撴牸寮忎负鏃ユ湡鏍煎紡鏃堕�夊~姝ら」
+    String dateFormate() default "yyyy.MM.dd";
+
+    //鏄剧ず绫诲瀷
+    enum ShowType {
+        TEXT, IMG;
+    }
+
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/CheckBox.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/CheckBox.java
new file mode 100644
index 0000000..aabf51c
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/CheckBox.java
@@ -0,0 +1,37 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: CheckBox
+ * @projectName utils
+ * @description: 澶嶉�夋
+ * @date 2021/9/2313:42
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CheckBox {
+
+
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+
+    //鍊�,閿�奸噰鐢ㄩ�楀彿鍒嗛殧
+    String[] values();
+
+
+
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Img.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Img.java
new file mode 100644
index 0000000..01ca254
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Img.java
@@ -0,0 +1,34 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: Img
+ * @projectName utils
+ * @description: 鍥剧墖鎺т欢
+ * @date 2021/9/2312:06
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Img {
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+
+    //鍥剧墖瀹藉害px锛岄粯璁や笉璁剧疆
+    int width() default -1;
+
+    //鍥剧墖楂樺害px锛岄粯璁や笉璁剧疆
+    int height() default -1;
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Password.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Password.java
new file mode 100644
index 0000000..bb081de
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Password.java
@@ -0,0 +1,37 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: Password
+ * @projectName utils
+ * @description: 瀵嗙爜
+ * @date 2021/9/2313:43
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Password {
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+
+    //鏄惁蹇呴』
+    boolean require() default false;
+
+    //鏈�灏忛暱搴�
+    int minLength() default -1;
+
+    //鏈�闀块暱搴�
+    int maxLength() default -1;
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/RadioGroup.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/RadioGroup.java
new file mode 100644
index 0000000..c0e3cb8
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/RadioGroup.java
@@ -0,0 +1,31 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: RadioGroup
+ * @projectName utils
+ * @description: 鍗曢�夋
+ * @date 2021/9/2313:41
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RadioGroup {
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+
+    //鍊�,閿�奸噰鐢ㄩ�楀彿鍒嗛殧
+    String[] values();
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Select.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Select.java
new file mode 100644
index 0000000..02b5762
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Select.java
@@ -0,0 +1,39 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: Select
+ * @projectName utils
+ * @description: 涓嬫媺鍒楄〃
+ * @date 2021/9/2312:07
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Select {
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+
+    //鏄惁蹇呴』
+    boolean require() default false;
+
+    //鍊�,閿�奸噰鐢ㄩ�楀彿鍒嗛殧
+    String[] values() default "";
+
+    //閾炬帴璇锋眰鐨勮矾寰�
+    String apiPath() default "";
+
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Switch.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Switch.java
new file mode 100644
index 0000000..22a7bdf
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Switch.java
@@ -0,0 +1,28 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: Switch
+ * @projectName utils
+ * @description: 寮�鍏�
+ * @date 2021/9/2313:42
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Switch {
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Text.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Text.java
new file mode 100644
index 0000000..62974fe
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/Text.java
@@ -0,0 +1,62 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import org.yeshi.utils.generater.entity.admin.FormVerifyType;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: Text
+ * @projectName utils
+ * @description: 鏂囨湰
+ * @date 2021/9/2312:07
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Text {
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+
+    //鏄惁蹇呴』
+    boolean require() default false;
+
+    //鏈�灏忛暱搴�
+    int minLength() default -1;
+
+    //鏈�闀块暱搴�
+    int maxLength() default -1;
+
+    //楠岃瘉绫诲瀷
+    FormVerifyType verifyType() default FormVerifyType.none;
+
+    //濡傛灉楠岃瘉绫诲瀷涓烘鍒欓渶瑕佹椤�
+    String verifyValue() default "";
+
+    //濡傛灉楠岃瘉绫诲瀷涓烘鍒欓渶瑕佹椤�
+    String verifyNotifyMsg() default "";
+
+    String placeHolder() default "";
+
+    Type inputType() default Type.TEXT;
+
+    //褰搃nputType涓篋ATE鎴栬�匘ATETIME鏃舵湁鏁�
+    String dateFormat() default "yyyy.MM.dd";
+
+
+    enum Type {
+        TEXT, DATE, DATETIME;
+    }
+
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/annotation/admin/form/TextArea.java b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/TextArea.java
new file mode 100644
index 0000000..5700d95
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/annotation/admin/form/TextArea.java
@@ -0,0 +1,52 @@
+package org.yeshi.utils.generater.annotation.admin.form;
+
+import org.yeshi.utils.generater.entity.admin.FormVerifyType;
+
+import java.lang.annotation.*;
+
+/**
+ * @author Administrator
+ * @title: TextArea
+ * @projectName utils
+ * @description: 鏂囨湰鍩�
+ * @date 2021/9/2312:07
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TextArea {
+
+    //鏍囬
+    String title();
+
+    //鏄惁鍙洿鏂�
+    boolean update() default true;
+
+    //绠�浠�
+    String desc() default "";
+
+    //鏄惁绂佹缂栬緫
+    boolean disable() default false;
+
+    //鏄惁蹇呴』
+    boolean require() default false;
+
+    //鏈�灏忛暱搴�
+    int minLength() default -1;
+
+    //鏈�闀块暱搴�
+    int maxLength() default -1;
+
+    //楠岃瘉绫诲瀷
+    FormVerifyType verifyType();
+
+    //濡傛灉楠岃瘉绫诲瀷涓烘鍒欓渶瑕佹椤�
+    String verifyValue() default "";
+
+    //濡傛灉楠岃瘉绫诲瀷涓烘鍒欓渶瑕佹椤�
+    String verifyNotifyMsg() default "";
+
+    String placeHolder() default "";
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/entity/CommonSearchForm.java b/src/main/java/org/yeshi/utils/generater/entity/CommonSearchForm.java
new file mode 100644
index 0000000..a23acfe
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/entity/CommonSearchForm.java
@@ -0,0 +1,44 @@
+package org.yeshi.utils.generater.entity;
+
+import org.yeshi.utils.generater.annotation.admin.form.Text;
+
+/**
+ * @author Administrator
+ * @title: CommonSearchForm
+ * @description: 鎼滅储琛ㄥ崟
+ * @date 2021/9/23 16:12
+ */
+public class CommonSearchForm {
+
+    @Text(title = "寮�濮嬫棩鏈�", inputType = Text.Type.DATE)
+    private String startDate;
+    @Text(title = "缁撴潫鏃ユ湡", inputType = Text.Type.DATE)
+    private String endDate;
+    @Text(title = "璇疯緭鍏ュ叧閿瘝", inputType = Text.Type.TEXT)
+    private String key;
+
+
+    public String getStartDate() {
+        return startDate;
+    }
+
+    public void setStartDate(String startDate) {
+        this.startDate = startDate;
+    }
+
+    public String getEndDate() {
+        return endDate;
+    }
+
+    public void setEndDate(String endDate) {
+        this.endDate = endDate;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+}
diff --git a/src/main/java/org/yeshi/utils/generater/entity/DaoQueryColumnData.java b/src/main/java/org/yeshi/utils/generater/entity/DaoQueryColumnData.java
new file mode 100644
index 0000000..35a3e97
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/entity/DaoQueryColumnData.java
@@ -0,0 +1,23 @@
+package org.yeshi.utils.generater.entity;
+
+import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
+
+public class DaoQueryColumnData extends ColumnData {
+
+    //鏌ヨ鏂瑰紡
+    private DaoQueryCondition.QueryType queryType;
+
+    public DaoQueryColumnData(String columnName, String type, DaoQueryCondition.QueryType queryType) {
+        super(columnName, type);
+        this.queryType = queryType;
+    }
+
+
+    public DaoQueryCondition.QueryType getQueryType() {
+        return queryType;
+    }
+
+    public void setQueryType(DaoQueryCondition.QueryType queryType) {
+        this.queryType = queryType;
+    }
+}
diff --git a/src/main/java/org/yeshi/utils/generater/entity/KeyValue.java b/src/main/java/org/yeshi/utils/generater/entity/KeyValue.java
new file mode 100644
index 0000000..255aff0
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/entity/KeyValue.java
@@ -0,0 +1,33 @@
+package org.yeshi.utils.generater.entity;
+
+/**
+ * @author Administrator
+ * @title: KeyValue
+ * @description: 閿�煎
+ * @date 2021/9/23 17:42
+ */
+public class KeyValue {
+    private String key;
+    private String value;
+
+    public KeyValue(String key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+}
diff --git a/src/main/java/org/yeshi/utils/generater/entity/MongoDBDaoData.java b/src/main/java/org/yeshi/utils/generater/entity/MongoDBDaoData.java
index 10f5e97..21637a9 100644
--- a/src/main/java/org/yeshi/utils/generater/entity/MongoDBDaoData.java
+++ b/src/main/java/org/yeshi/utils/generater/entity/MongoDBDaoData.java
@@ -2,6 +2,7 @@
 
 import org.springframework.data.annotation.Id;
 import org.springframework.data.annotation.Transient;
+import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
@@ -19,6 +20,8 @@
 
     private ColumnData identityColumn;
     private List<ColumnData> columnDataList;
+
+    private List<DaoQueryColumnData> daoQueryColumnDataList;
 
     public static class Builder {
 
@@ -62,6 +65,7 @@
             String identityColumnName = null;
             String identityColumnType = null;
             List<ColumnData> columlist = new ArrayList<>();
+            List<DaoQueryColumnData> daoQueryColumnList = new ArrayList<>();
             for (Field fd : fields) {
                 //private/public 闈瀎inal锛宻tatic灞炴�ф墠浼氬弬涓庤В鏋�
                 if (fd.getModifiers() != 1 && fd.getModifiers() != 2) {
@@ -89,6 +93,14 @@
                     //涓嶅弬涓庤В鏋�
                     if (a instanceof Transient || a instanceof java.beans.Transient) {
                         columName = null;
+                        break;
+                    }
+                }
+
+                //鑾峰彇鏌ヨ鏉′欢
+                for (Annotation a : as) {
+                    if (a instanceof DaoQueryCondition) {
+                        daoQueryColumnList.add(new DaoQueryColumnData(columName, columnDataType, ((DaoQueryCondition) a).queryType()));
                         break;
                     }
                 }
@@ -121,6 +133,7 @@
             MongoDBDaoData data = new MongoDBDaoData();
             data.setBaseDaoClassName(baseDaoClass.getSimpleName());
             data.setColumnDataList(columnDataList);
+            data.setDaoQueryColumnDataList(daoQueryColumnList);
             data.setDaoName(daoName);
             data.setEntityClass(entityClass.getName());
             data.setEntityClassName(entityClass.getSimpleName());
@@ -185,4 +198,13 @@
     public void setImportClasses(Set<String> importClasses) {
         this.importClasses = importClasses;
     }
+
+
+    public List<DaoQueryColumnData> getDaoQueryColumnDataList() {
+        return daoQueryColumnDataList;
+    }
+
+    public void setDaoQueryColumnDataList(List<DaoQueryColumnData> daoQueryColumnDataList) {
+        this.daoQueryColumnDataList = daoQueryColumnDataList;
+    }
 }
diff --git a/src/main/java/org/yeshi/utils/generater/entity/admin/AdminGeneraterInfo.java b/src/main/java/org/yeshi/utils/generater/entity/admin/AdminGeneraterInfo.java
new file mode 100644
index 0000000..65c382a
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/entity/admin/AdminGeneraterInfo.java
@@ -0,0 +1,115 @@
+package org.yeshi.utils.generater.entity.admin;
+
+import org.yeshi.utils.generater.annotation.admin.AdminController;
+import org.yeshi.utils.generater.util.AnotationUtil;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Administrator
+ * @title: AdminGeneraterInfo
+ * @description: TODO
+ * @date 2021/9/24 11:03
+ */
+public class AdminGeneraterInfo {
+
+    //entity绫�
+    private Class entity;
+    //controller娉ㄨВ瀵硅薄
+    private Map<String, Object> controllerData;
+    //淇敼鐨勮〃鍗曡鏁版嵁
+    private List<FormRowData> updateFormRows;
+    //娣诲姞鐨勮〃鍗曡鏁版嵁
+    private List<FormRowData> addFormRows;
+    //鎼滅储鐨勮〃鍗曡鏁版嵁
+    private List<FormRowData> searchFormRows;
+
+    private List<Map<String, Object>> showDataList;
+
+
+    public Class getEntity() {
+        return entity;
+    }
+
+    public void setEntity(Class entity) {
+        this.entity = entity;
+    }
+
+    public Map<String, Object> getControllerData() {
+        return controllerData;
+    }
+
+    public void setControllerData(Map<String, Object> controllerData) {
+        this.controllerData = controllerData;
+    }
+
+
+    public List<FormRowData> getUpdateFormRows() {
+        return updateFormRows;
+    }
+
+    public void setUpdateFormRows(List<FormRowData> updateFormRows) {
+        this.updateFormRows = updateFormRows;
+    }
+
+    public List<FormRowData> getAddFormRows() {
+        return addFormRows;
+    }
+
+    public void setAddFormRows(List<FormRowData> addFormRows) {
+        this.addFormRows = addFormRows;
+    }
+
+    public List<FormRowData> getSearchFormRows() {
+        return searchFormRows;
+    }
+
+    public void setSearchFormRows(List<FormRowData> searchFormRows) {
+        this.searchFormRows = searchFormRows;
+    }
+
+    public List<Map<String, Object>> getShowDataList() {
+        return showDataList;
+    }
+
+    public void setShowDataList(List<Map<String, Object>> showDataList) {
+        this.showDataList = showDataList;
+    }
+
+
+    public static class Builder {
+
+        private Class entity;
+
+        public Builder setEntityClass(Class clazz) {
+            this.entity = clazz;
+            return this;
+        }
+
+        public AdminGeneraterInfo build() throws Exception {
+            if (entity == null) {
+                throw new Exception("灏氭湭璁剧疆entity");
+            }
+            //鏌ヨ鏄惁闇�瑕佺敓鎴愮鐞嗙晫闈笌controller
+            Annotation[] ans = entity.getAnnotations();
+            for (Annotation an : ans) {
+                if (an instanceof AdminController) {
+                    Class searchFormClass = ((AdminController) an).searchForm();
+                    AdminGeneraterInfo info = new AdminGeneraterInfo();
+                    info.setControllerData(AnotationUtil.getParamsMap(an));
+                    info.setSearchFormRows(AnotationUtil.getFormRowData(searchFormClass));
+                    info.setAddFormRows(AnotationUtil.getFormRowData(entity));
+                    info.setUpdateFormRows(AnotationUtil.getUpdateFormRowData(entity));
+                    info.setShowDataList(AnotationUtil.getShowDataList(entity));
+                    return info;
+                }
+            }
+            return null;
+        }
+
+    }
+
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/entity/admin/FormRowData.java b/src/main/java/org/yeshi/utils/generater/entity/admin/FormRowData.java
new file mode 100644
index 0000000..434559e
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/entity/admin/FormRowData.java
@@ -0,0 +1,43 @@
+package org.yeshi.utils.generater.entity.admin;
+
+import java.util.Map;
+
+/**
+ * @author Administrator
+ * @title: FormRowData
+ * @description: 鍚庡彴缂栬緫琛ㄥ崟姣忎竴琛岀殑淇℃伅
+ * @date 2021/9/24 10:39
+ */
+public class FormRowData {
+    //閿��
+    private String key;
+    //琛岀被鍨�
+    private String type;
+    //鍙傛暟
+    private Map<String, Object> params;
+
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Map<String, Object> getParams() {
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params) {
+        this.params = params;
+    }
+}
diff --git a/src/main/java/org/yeshi/utils/generater/entity/admin/FormVerifyType.java b/src/main/java/org/yeshi/utils/generater/entity/admin/FormVerifyType.java
new file mode 100644
index 0000000..ad69201
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/entity/admin/FormVerifyType.java
@@ -0,0 +1,17 @@
+package org.yeshi.utils.generater.entity.admin;
+
+/**
+ * @author Administrator
+ * @title: FormVerifyType
+ * @description: 琛ㄥ崟楠岃瘉绫诲瀷
+ * @date 2021/9/23 14:00
+ */
+public enum FormVerifyType {
+    number("鏁板瓧"), phone("鐢佃瘽鍙风爜"), email("閭"), date("鏃ユ湡"), url("閾炬帴"), identity("韬唤璇�"), regex("姝e垯"),none("鏃犻獙璇佽鍒�");
+
+
+    private FormVerifyType(String desc) {
+
+    }
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/exception/AnotationException.java b/src/main/java/org/yeshi/utils/generater/exception/AnotationException.java
new file mode 100644
index 0000000..bb50578
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/exception/AnotationException.java
@@ -0,0 +1,9 @@
+package org.yeshi.utils.generater.exception;
+
+public class AnotationException extends Exception {
+
+    public AnotationException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/util/AnotationUtil.java b/src/main/java/org/yeshi/utils/generater/util/AnotationUtil.java
new file mode 100644
index 0000000..f70653e
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/util/AnotationUtil.java
@@ -0,0 +1,132 @@
+package org.yeshi.utils.generater.util;
+
+import org.yeshi.utils.StringUtil;
+import org.yeshi.utils.generater.annotation.admin.Show;
+import org.yeshi.utils.generater.annotation.admin.form.*;
+import org.yeshi.utils.generater.entity.KeyValue;
+import org.yeshi.utils.generater.entity.admin.FormRowData;
+import org.yeshi.utils.generater.exception.AnotationException;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.*;
+
+/**
+ * @author Administrator
+ * @title: FormAnotationUtil
+ * @description: 娉ㄨВ甯姪绫�
+ * @date 2021/9/24 10:31
+ */
+public class AnotationUtil {
+
+    public static Map<String, Object> getParamsMap(Annotation a) throws InvocationTargetException, IllegalAccessException {
+        Map<String, Object> params = new HashMap<>();
+        Method[] fs = a.getClass().getDeclaredMethods();
+        for (Method md : fs) {
+            if (md.getGenericParameterTypes().length > 0)
+                continue;
+            if (md.getName().equals("toString") || md.getName().equals("hashCode") || md.getName().equalsIgnoreCase("annotationType"))
+                continue;
+            Object value = md.invoke(a);
+            if (value instanceof String[]) {
+                params.put(md.getName(), value);
+                List<KeyValue> values = new ArrayList<>();
+                String[] arrays = (String[]) value;
+                if (arrays.length == 1 && StringUtil.isNullOrEmpty(arrays[0])) {
+                } else {
+                    for (String st : (String[]) value) {
+                        values.add(new KeyValue(st.substring(0, st.indexOf(",")), st.substring(st.indexOf(",") + 1)));
+                    }
+                }
+                params.put(md.getName(), values);
+            } else {
+                params.put(md.getName(), value);
+            }
+        }
+        return params;
+    }
+
+    //鑾峰彇琛ㄥ崟鐨勮鏁版嵁
+    public static List<FormRowData> getFormRowData(Class entity) throws AnotationException, Exception {
+        List<FormRowData> list = new ArrayList<>();
+        Field[] fields = entity.getDeclaredFields();
+        for (Field fd : fields) {
+            Annotation[] as = fd.getAnnotations();
+            FormRowData formRowData = null;
+            for (Annotation an : as) {
+
+                formRowData = new FormRowData();
+
+                if (an instanceof CheckBox) {
+                    FormAnotationValidUtil.valid((CheckBox) an);
+                } else if (an instanceof Img) {
+                    FormAnotationValidUtil.valid((Img) an);
+                } else if (an instanceof Password) {
+                    FormAnotationValidUtil.valid((Password) an);
+                } else if (an instanceof RadioGroup) {
+                    FormAnotationValidUtil.valid((RadioGroup) an);
+                } else if (an instanceof Select) {
+                    FormAnotationValidUtil.valid((Select) an);
+                } else if (an instanceof Switch) {
+                    FormAnotationValidUtil.valid((Switch) an);
+                } else if (an instanceof Text) {
+                    FormAnotationValidUtil.valid((Text) an);
+                } else if (an instanceof TextArea) {
+                    FormAnotationValidUtil.valid((TextArea) an);
+                } else {
+                    formRowData = null;
+                }
+
+                if (formRowData != null) {
+                    formRowData.setKey(fd.getName());
+                    formRowData.setType(an.annotationType().getSimpleName());
+                    formRowData.setParams(getParamsMap(an));
+                    list.add(formRowData);
+                    break;
+                }
+            }
+        }
+        return list;
+    }
+
+
+    //鑾峰彇鍙互鏇存柊鐨勫瓧娈�
+    public static List<FormRowData> getUpdateFormRowData(Class entity) throws AnotationException, Exception {
+        List<FormRowData> list = getFormRowData(entity);
+        if (list != null) {
+            for (int i = 0; i < list.size(); i++) {
+                if (list.get(i) == null || list.get(i).getParams() == null || !((Boolean) list.get(i).getParams().get("update"))) {
+                    //娌℃湁閰嶇疆鏇存柊椤圭洰
+                    list.remove(i--);
+                }
+            }
+        }
+        return list;
+    }
+
+    //鑾峰彇鏄剧ず鐨勫瓧娈垫暟鎹�
+    public static List<Map<String, Object>> getShowDataList(Class entity) throws InvocationTargetException, IllegalAccessException {
+        List<Map<String, Object>> list = new ArrayList<>();
+        Field[] fields = entity.getDeclaredFields();
+        for (Field fd : fields) {
+            Annotation[] as = fd.getAnnotations();
+            FormRowData formRowData = null;
+            for (Annotation an : as) {
+                if (an instanceof Show) {
+                    list.add(getParamsMap(an));
+                }
+            }
+        }
+        if (list != null && list.size() > 0) {
+            Comparator<Map<String, Object>> cm = (Map<String, Object> o1, Map<String, Object> o2) -> {
+                return (int) (o1.get("order")) - (int) (o2.get("order"));
+            };
+            Collections.sort(list, cm);
+        }
+        return list;
+    }
+
+}
diff --git a/src/main/java/org/yeshi/utils/generater/util/FormAnotationValidUtil.java b/src/main/java/org/yeshi/utils/generater/util/FormAnotationValidUtil.java
new file mode 100644
index 0000000..0aff7a2
--- /dev/null
+++ b/src/main/java/org/yeshi/utils/generater/util/FormAnotationValidUtil.java
@@ -0,0 +1,127 @@
+package org.yeshi.utils.generater.util;
+
+import org.yeshi.utils.StringUtil;
+import org.yeshi.utils.generater.annotation.admin.form.*;
+import org.yeshi.utils.generater.entity.admin.FormVerifyType;
+import org.yeshi.utils.generater.exception.AnotationException;
+
+/**
+ * @author Administrator
+ * @title: FormEditValidUtil
+ * @description: 楠岃瘉琛ㄥ崟鐨勬敞瑙f槸鍚︽纭�
+ * @date 2021/9/23 15:30
+ */
+public class FormAnotationValidUtil {
+
+    private static void validTitle(String title) throws AnotationException {
+        if (StringUtil.isNullOrEmpty(title)) {
+            throw new AnotationException("title涓嶈兘涓虹┖");
+        }
+    }
+
+    public static void valid(Text text) throws AnotationException {
+        validTitle(text.title());
+        //楠岃瘉闀垮害
+        if (text.minLength() > text.maxLength()) {
+            throw new AnotationException("鏈�澶ч暱搴︿笉鑳藉皬浜庢渶灏忛暱搴�");
+        }
+
+        if (text.verifyType() == FormVerifyType.regex && StringUtil.isNullOrEmpty(text.verifyValue())) {
+            throw new AnotationException("楠岃瘉鐨勮緭鍏ョ殑姝e垯琛ㄨ揪寮忎笉鑳戒负绌�");
+        }
+
+        if (text.verifyType() == FormVerifyType.regex && StringUtil.isNullOrEmpty(text.verifyNotifyMsg())) {
+            throw new AnotationException("涓嶆弧瓒虫鍒欒〃杈惧紡鐨勬彁绀鸿涓嶈兘涓虹┖");
+        }
+
+        if (text.inputType() == Text.Type.DATE || text.inputType() == Text.Type.DATETIME) {
+            if (StringUtil.isNullOrEmpty(text.dateFormat())) {
+                throw new AnotationException("鏃ュ織鏍煎紡鍖栬〃杈惧紡涓嶈兘涓虹┖");
+            }
+        }
+    }
+
+    public static void valid(TextArea text) throws AnotationException {
+        validTitle(text.title());
+        //楠岃瘉闀垮害
+        if (text.minLength() > text.maxLength()) {
+            throw new AnotationException("鏈�澶ч暱搴︿笉鑳藉皬浜庢渶灏忛暱搴�");
+        }
+
+        if (text.verifyType() == FormVerifyType.regex && StringUtil.isNullOrEmpty(text.verifyValue())) {
+            throw new AnotationException("楠岃瘉鐨勮緭鍏ョ殑姝e垯琛ㄨ揪寮忎笉鑳戒负绌�");
+        }
+
+        if (text.verifyType() == FormVerifyType.regex && StringUtil.isNullOrEmpty(text.verifyNotifyMsg())) {
+            throw new AnotationException("涓嶆弧瓒虫鍒欒〃杈惧紡鐨勬彁绀鸿涓嶈兘涓虹┖");
+        }
+
+    }
+
+
+    public static void valid(CheckBox checkBox) throws AnotationException {
+        validTitle(checkBox.title());
+        //楠岃瘉闀垮害
+        if (checkBox.values() == null || checkBox.values().length < 1) {
+            throw new AnotationException("澶嶉�夋鐨勫唴瀹逛笉鑳戒负绌�");
+        }
+
+        for (String st : checkBox.values()) {
+            if (!st.contains(",")) {
+                throw new AnotationException("澶嶉�夋鐨勫唴瀹规牸寮忛敊璇紝閿�煎瑕佺敤閫楀彿鍒嗛殧");
+            }
+        }
+    }
+
+    public static void valid(Img img) throws AnotationException {
+        validTitle(img.title());
+    }
+
+
+    public static void valid(Password password) throws AnotationException {
+        validTitle(password.title());
+        //楠岃瘉闀垮害
+        if (password.minLength() > password.maxLength()) {
+            throw new AnotationException("鏈�澶ч暱搴︿笉鑳藉皬浜庢渶灏忛暱搴�");
+        }
+    }
+
+    public static void valid(RadioGroup radioGroup) throws AnotationException {
+        validTitle(radioGroup.title());
+
+        if (radioGroup.values() == null || radioGroup.values().length < 1) {
+            throw new AnotationException("鍗曢�夋鐨勫唴瀹逛笉鑳戒负绌�");
+        }
+
+        for (String st : radioGroup.values()) {
+            if (!st.contains(",")) {
+                throw new AnotationException("鍗曢�夋鐨勫唴瀹规牸寮忛敊璇紝閿�煎瑕佺敤閫楀彿鍒嗛殧");
+            }
+        }
+
+    }
+
+
+    public static void valid(Select select) throws AnotationException {
+        validTitle(select.title());
+
+        if ((select.values() == null || select.values().length < 1 || (select.values().length == 1 && StringUtil.isNullOrEmpty(select.values()[0])))) {
+            if (StringUtil.isNullOrEmpty(select.apiPath())) {
+                throw new AnotationException("涓嬫媺妗嗙殑鍐呭涓嶈兘涓虹┖");
+            }
+        } else {
+            for (String st : select.values()) {
+                if (!st.contains(",")) {
+                    throw new AnotationException("涓嬫媺妗嗙殑鍐呭鏍煎紡閿欒锛岄敭鍊煎瑕佺敤閫楀彿鍒嗛殧");
+                }
+            }
+        }
+    }
+
+
+    public static void valid(Switch st) throws AnotationException {
+        validTitle(st.title());
+    }
+
+
+}
diff --git a/src/main/java/org/yeshi/utils/ios/pay/IOSPayVerifyUtil.java b/src/main/java/org/yeshi/utils/ios/pay/IOSPayVerifyUtil.java
index ef68cef..e11d5e8 100644
--- a/src/main/java/org/yeshi/utils/ios/pay/IOSPayVerifyUtil.java
+++ b/src/main/java/org/yeshi/utils/ios/pay/IOSPayVerifyUtil.java
@@ -1,8 +1,9 @@
 package org.yeshi.utils.ios.pay;
 
 import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
-import org.yeshi.utils.HttpUtil;
 import org.yeshi.utils.ios.pay.vo.IOSAPPBuyVerifyResult;
 
 import javax.net.ssl.*;
@@ -10,9 +11,11 @@
 import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.lang.reflect.Type;
 import java.net.URL;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
+import java.util.List;
 import java.util.Locale;
 
 public class IOSPayVerifyUtil {
@@ -91,6 +94,15 @@
             JSONObject receiptNew = root.optJSONObject("receipt");
             Gson gson = new Gson();
             IOSAPPBuyVerifyResult verifyResult = gson.fromJson(receiptNew.toString(), IOSAPPBuyVerifyResult.class);
+
+            JSONArray latestReceiptInfo = root.optJSONArray("latest_receipt_info");
+            if (latestReceiptInfo != null) {
+                Type type = new TypeToken<List<IOSAPPBuyVerifyResult.OrderInfo>>() {
+                }.getType();
+                List<IOSAPPBuyVerifyResult.OrderInfo> orderInfoList = gson.fromJson(latestReceiptInfo.toString(), type);
+                verifyResult.setLatestReceiptInfo(orderInfoList);
+            }
+
             return verifyResult;
         } catch (Exception ex) {
             ex.printStackTrace();
@@ -99,9 +111,9 @@
     }
 
     public static void main(String[] args) {
-        String receiptData = "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";
+        String receiptData = "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";
         try {
-            IOSAPPBuyVerifyResult result=    buyAppVerify(receiptData, "28ca52e358b94c4eba3de41dfa7dd023", true);
+            IOSAPPBuyVerifyResult result = buyAppVerify(receiptData, "28ca52e358b94c4eba3de41dfa7dd023", true);
             System.out.println(result);
         } catch (Exception e) {
             e.printStackTrace();
diff --git a/src/main/java/org/yeshi/utils/ios/pay/vo/IOSAPPBuyVerifyResult.java b/src/main/java/org/yeshi/utils/ios/pay/vo/IOSAPPBuyVerifyResult.java
index 741ac79..1484755 100644
--- a/src/main/java/org/yeshi/utils/ios/pay/vo/IOSAPPBuyVerifyResult.java
+++ b/src/main/java/org/yeshi/utils/ios/pay/vo/IOSAPPBuyVerifyResult.java
@@ -21,6 +21,17 @@
     private Long requestDateMs;
     @SerializedName("in_app")
     private List<OrderInfo> inApps;
+    @SerializedName("latest_receipt_info")
+    private  List<OrderInfo> latestReceiptInfo;
+
+
+    public List<OrderInfo> getLatestReceiptInfo() {
+        return latestReceiptInfo;
+    }
+
+    public void setLatestReceiptInfo(List<OrderInfo> latestReceiptInfo) {
+        this.latestReceiptInfo = latestReceiptInfo;
+    }
 
     public String getBundleId() {
         return bundleId;
diff --git a/src/main/resources/generater/admin/add.ftl b/src/main/resources/generater/admin/add.ftl
new file mode 100644
index 0000000..693c9e4
--- /dev/null
+++ b/src/main/resources/generater/admin/add.ftl
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<html class="x-admin-sm">
+
+<head>
+    <meta charset="UTF-8">
+    <title>鏂板${controllerData.title}</title>
+    <meta name="renderer" content="webkit">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="viewport"
+          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
+    <link rel="stylesheet" href="./css/font.css">
+    <link rel="stylesheet" href="./css/xadmin.css">
+    <script type="text/javascript" src="./lib/layui/layui.js" charset="utf-8"></script>
+    <script type="text/javascript" src="./js/xadmin.js"></script>
+    <script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
+    <script src="js/http.js" type="text/javascript" charset="utf-8"></script>
+    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
+    <!-- 璁㊣E8/9鏀寔濯掍綋鏌ヨ锛屼粠鑰屽吋瀹规爡鏍� -->
+    <!--[if lt IE 9]>
+    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
+    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
+    <![endif]-->
+</head>
+<body>
+<div class="layui-fluid">
+    <div class="layui-row">
+        <form class="layui-form" lay-filter="add">
+
+            <#list addFormRows as value>
+                <div class="layui-form-item">
+                    <label for="L_appCode" class="layui-form-label">
+                        <#if value.params.require??&&value.params.require>
+                           <span class="x-red">*</span>
+                        </#if>
+                        ${value.params.title}</label>
+
+                    <#switch value.type>
+                        <#case "CheckBox"><#include "/admin/form/checkBox.ftl" ><#break>
+                        <#case "Img">  <#include "/admin/form/img.ftl"><#break>
+                        <#case "Password">  <#include "/admin/form/password.ftl"><#break>
+                        <#case "RadioGroup">  <#include "/admin/form/radioGroup.ftl"><#break>
+                        <#case "Select">  <#include "/admin/form/select.ftl"><#break>
+                        <#case "Switch">  <#include "/admin/form/switch.ftl"><#break>
+                        <#case "Text">  <#include "/admin/form/text.ftl"><#break>
+                        <#case "TextArea">  <#include "/admin/form/textArea.ftl"><#break>
+                        <#default>
+                    </#switch>
+
+                <#if (value.desc!"") != "">
+                    <div class="layui-form-mid layui-word-aux">${value.desc}</div>
+                </#if>
+                </div>
+            </#list>
+
+            <div class="layui-form-item">
+                <label for="L_remarks" class="layui-form-label"></label>
+                <button class="layui-btn" lay-filter="add" lay-submit="">纭畾</button>
+            </div>
+        </form>
+    </div>
+</div>
+<script>
+
+    layui.use(['form', 'layer', 'jquery'], function () {
+        $ = layui.jquery;
+        var form = layui.form,
+                layer = layui.layer;
+
+        //鑷畾涔夐獙璇佽鍒�
+        form.verify({
+            username: function (value) {
+                if (value.length < 3) {
+                    return '鍚嶇О鑷冲皯寰�3涓瓧绗�';
+                }
+            },
+            code: function (value) {
+                if (value) {
+                    if (!(/^([A-Za-z0-9]|\-|_)+$/).test(value)) {
+                        return '鏍囪瘑鍙兘鍖呭惈 鏁板瓧銆佽嫳鏂囧瓧绗︺�乢 銆�-';
+                    }
+                }
+            },
+            packageName: [/^([A-Za-z0-9]|\-|_|\.)+$/, '鍖呭悕鍙兘鍖呭惈 鏁板瓧銆佽嫳鏂囧瓧绗︺�乢 銆�-銆�.'],
+            desc: function (value) {
+                if (value != null && value.length > 128) {
+                    return '绠�浠嬫渶澶т负128涓瓧绗�';
+                }
+            },
+            remarks: function (value) {
+                if (value != null && value.length > 128) {
+                    return '澶囨敞鏈�澶т负128涓瓧绗�';
+                }
+            },
+
+        });
+
+
+        //鐩戝惉鎻愪氦
+        form.on('submit(add)',
+                function (data) {
+                    console.log(data.field);
+                    //杞崲json瀵硅薄
+                    for (key in data.field) {
+                        if (key.indexOf(".") > -1) {
+                            var value = data.field[key];
+                            delete data.field[key];
+                            var onkeys = key.split(".");
+                            //鍒涘缓瀵硅薄
+                            if (data.field[onkeys[0]] == undefined) {
+                                data.field[onkeys[0]] = {};
+                            }
+                            data.field[onkeys[0]][onkeys[1]] = value;
+                        }
+                    }
+                    //鍙戝紓姝ワ紝鎶婃暟鎹彁浜ょ粰php
+                    ksapp.postJSON('/admin/api/pushplatform-app/add', data.field, function (res) {
+                        if (res.code == 0) {
+                            layer.alert("澧炲姞鎴愬姛", {
+                                        icon: 6
+                                    },
+                                    function () {
+                                        //鍏抽棴褰撳墠frame
+                                        xadmin.close();
+                                        // 鍙互瀵圭埗绐楀彛杩涜鍒锋柊
+                                        // xadmin.father_reload();
+                                    });
+                        } else {
+                            layer.msg(res.msg);
+                        }
+
+                    }, function (res) {
+                    });
+                    return false;
+                });
+
+    });
+
+
+
+    var app = new Vue({
+        el: '.layui-form',
+        data: {
+            appList: [],
+            platformList: [
+                {name: "灏忕背", platform: "xm"},
+                {name: "鍗庝负", platform: "hw"},
+                {name: "OPPO", platform: "oppo"},
+                {name: "VIVO", platform: "vivo"},
+                {name: "榄呮棌", platform: "mz"}
+            ]
+        },
+        created: function () {
+            this.getAppList();
+        },
+        watch: {
+            appList: function () {
+                app.render();
+            }
+
+        },
+        methods: {
+            getAppList: function () {
+                ksapp.post("/admin/api/app/list", {page: 1, limit: 100}, function (e) {
+                    if (e.code == 0) {
+                        app.appList = e.data.list;
+                    } else
+                        layer.msg(e.msg);
+                }, function (e) {
+                });
+            },
+            render: function () {
+                console.log("render")
+
+            }
+        }
+    });
+
+</script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/src/main/resources/mongoDBDao.template b/src/main/resources/generater/admin/adminController.template
similarity index 88%
copy from src/main/resources/mongoDBDao.template
copy to src/main/resources/generater/admin/adminController.template
index 1ef3608..cc5ba65 100644
--- a/src/main/resources/mongoDBDao.template
+++ b/src/main/resources/generater/admin/adminController.template
@@ -47,7 +47,7 @@
 
     private Query getQuery(DaoQuery daoQuery){
           List<Criteria> andList=new ArrayList<>();
-           <#list columnDataList as value>
+           <#list daoQueryColumnDataList as value>
                <#if (value.type!"") == "Date">
                if(daoQuery.min${value.columnName?cap_first}!=null){
                     andList.add(Criteria.where("${value.columnName}").gte(daoQuery.min${value.columnName?cap_first}));
@@ -57,7 +57,11 @@
                }
                <#else>
                if(daoQuery.${value.columnName}!=null){
+                 <#if (value.queryType!"") == "equal">
                     andList.add(Criteria.where("${value.columnName}").is(daoQuery.${value.columnName}));
+                 <#else>
+                      andList.add(Criteria.where("${value.columnName}").regex(daoQuery.${value.columnName}));
+                 </#if>
                }
                </#if>
           </#list>
@@ -71,8 +75,8 @@
     }
 
   public static class DaoQuery{
-     <#if columnDataList??>
-       <#list columnDataList as value>
+     <#if daoQueryColumnDataList??>
+       <#list daoQueryColumnDataList as value>
         <#if (value.type!"") == "Date">
         public ${value.type} min${value.columnName?cap_first};
         public ${value.type} max${value.columnName?cap_first};
diff --git a/src/main/resources/generater/admin/form/checkBox.ftl b/src/main/resources/generater/admin/form/checkBox.ftl
new file mode 100644
index 0000000..6e2431d
--- /dev/null
+++ b/src/main/resources/generater/admin/form/checkBox.ftl
@@ -0,0 +1,3 @@
+                       <div class="layui-input-block">
+                            <input type="checkbox" name="${value.key}" title="鍐欎綔">
+                        </div>
\ No newline at end of file
diff --git a/src/main/resources/generater/admin/form/img.ftl b/src/main/resources/generater/admin/form/img.ftl
new file mode 100644
index 0000000..17ddfea
--- /dev/null
+++ b/src/main/resources/generater/admin/form/img.ftl
@@ -0,0 +1,6 @@
+                    <div class="layui-input-inline">
+                        <select id="L_appCode" name="appCode" lay-verify="required" lay-search="">
+                            <option value="">鐩存帴閫夋嫨鎴栨悳绱㈠簲鐢�</option>
+                            <option v-for="item in appList" :value="item.appCode">{{item.name}}</option>
+                        </select>
+                    </div>
diff --git a/src/main/resources/generater/admin/form/password.ftl b/src/main/resources/generater/admin/form/password.ftl
new file mode 100644
index 0000000..32a20b6
--- /dev/null
+++ b/src/main/resources/generater/admin/form/password.ftl
@@ -0,0 +1,4 @@
+                    <div class="layui-input-inline">
+                        <input type="password" name="${value.key}" required lay-verify="required" placeholder="璇疯緭鍏ュ瘑鐮�" autocomplete="off"
+                               class="layui-input">
+                    </div>
\ No newline at end of file
diff --git a/src/main/resources/generater/admin/form/radioGroup.ftl b/src/main/resources/generater/admin/form/radioGroup.ftl
new file mode 100644
index 0000000..7f117a7
--- /dev/null
+++ b/src/main/resources/generater/admin/form/radioGroup.ftl
@@ -0,0 +1,5 @@
+                    <div class="layui-input-block">
+                            <#list value.params.values as item >
+                                <input type="radio" name="${value.key}" value="${item.key}" title="${item.value}">
+                            </#list>
+                    </div>
\ No newline at end of file
diff --git a/src/main/resources/generater/admin/form/select.ftl b/src/main/resources/generater/admin/form/select.ftl
new file mode 100644
index 0000000..70cbb86
--- /dev/null
+++ b/src/main/resources/generater/admin/form/select.ftl
@@ -0,0 +1,9 @@
+                    <div class="layui-input-block">
+                        <select name="${value.key}" lay-verify="required">
+                                <#if value.params.values??&&(value.params.values?size>0)>
+                                    <#list value.params.values as item>
+                                      <option value="${item.key}">${item.value}</option>
+                                    </#list>
+                                </#if>
+                        </select>
+                    </div>
\ No newline at end of file
diff --git a/src/main/resources/generater/admin/form/switch.ftl b/src/main/resources/generater/admin/form/switch.ftl
new file mode 100644
index 0000000..8c3bde9
--- /dev/null
+++ b/src/main/resources/generater/admin/form/switch.ftl
@@ -0,0 +1,3 @@
+                    <div class="layui-input-block">
+                        <input type="checkbox" name="${value.key}" lay-skin="switch">
+                    </div>
\ No newline at end of file
diff --git a/src/main/resources/generater/admin/form/text.ftl b/src/main/resources/generater/admin/form/text.ftl
new file mode 100644
index 0000000..39a4952
--- /dev/null
+++ b/src/main/resources/generater/admin/form/text.ftl
@@ -0,0 +1,4 @@
+                    <div class="layui-input-block">
+                        <input type="text" name="${value.key}" required lay-verify="required" placeholder="${value.params.placeHolder}" autocomplete="off"
+                               class="layui-input">
+                    </div>
diff --git a/src/main/resources/generater/admin/form/textArea.ftl b/src/main/resources/generater/admin/form/textArea.ftl
new file mode 100644
index 0000000..762d552
--- /dev/null
+++ b/src/main/resources/generater/admin/form/textArea.ftl
@@ -0,0 +1,3 @@
+                    <div class="layui-input-block">
+                        <textarea name="${value.key}" placeholder="${value.params.placeHolder}" class="layui-textarea"></textarea>
+                    </div>
\ No newline at end of file
diff --git a/src/main/resources/mongoDBDao.template b/src/main/resources/generater/admin/list.flt
similarity index 88%
copy from src/main/resources/mongoDBDao.template
copy to src/main/resources/generater/admin/list.flt
index 1ef3608..cc5ba65 100644
--- a/src/main/resources/mongoDBDao.template
+++ b/src/main/resources/generater/admin/list.flt
@@ -47,7 +47,7 @@
 
     private Query getQuery(DaoQuery daoQuery){
           List<Criteria> andList=new ArrayList<>();
-           <#list columnDataList as value>
+           <#list daoQueryColumnDataList as value>
                <#if (value.type!"") == "Date">
                if(daoQuery.min${value.columnName?cap_first}!=null){
                     andList.add(Criteria.where("${value.columnName}").gte(daoQuery.min${value.columnName?cap_first}));
@@ -57,7 +57,11 @@
                }
                <#else>
                if(daoQuery.${value.columnName}!=null){
+                 <#if (value.queryType!"") == "equal">
                     andList.add(Criteria.where("${value.columnName}").is(daoQuery.${value.columnName}));
+                 <#else>
+                      andList.add(Criteria.where("${value.columnName}").regex(daoQuery.${value.columnName}));
+                 </#if>
                }
                </#if>
           </#list>
@@ -71,8 +75,8 @@
     }
 
   public static class DaoQuery{
-     <#if columnDataList??>
-       <#list columnDataList as value>
+     <#if daoQueryColumnDataList??>
+       <#list daoQueryColumnDataList as value>
         <#if (value.type!"") == "Date">
         public ${value.type} min${value.columnName?cap_first};
         public ${value.type} max${value.columnName?cap_first};
diff --git a/src/main/resources/mongoDBDao.template b/src/main/resources/generater/admin/update.ftl
similarity index 88%
copy from src/main/resources/mongoDBDao.template
copy to src/main/resources/generater/admin/update.ftl
index 1ef3608..cc5ba65 100644
--- a/src/main/resources/mongoDBDao.template
+++ b/src/main/resources/generater/admin/update.ftl
@@ -47,7 +47,7 @@
 
     private Query getQuery(DaoQuery daoQuery){
           List<Criteria> andList=new ArrayList<>();
-           <#list columnDataList as value>
+           <#list daoQueryColumnDataList as value>
                <#if (value.type!"") == "Date">
                if(daoQuery.min${value.columnName?cap_first}!=null){
                     andList.add(Criteria.where("${value.columnName}").gte(daoQuery.min${value.columnName?cap_first}));
@@ -57,7 +57,11 @@
                }
                <#else>
                if(daoQuery.${value.columnName}!=null){
+                 <#if (value.queryType!"") == "equal">
                     andList.add(Criteria.where("${value.columnName}").is(daoQuery.${value.columnName}));
+                 <#else>
+                      andList.add(Criteria.where("${value.columnName}").regex(daoQuery.${value.columnName}));
+                 </#if>
                }
                </#if>
           </#list>
@@ -71,8 +75,8 @@
     }
 
   public static class DaoQuery{
-     <#if columnDataList??>
-       <#list columnDataList as value>
+     <#if daoQueryColumnDataList??>
+       <#list daoQueryColumnDataList as value>
         <#if (value.type!"") == "Date">
         public ${value.type} min${value.columnName?cap_first};
         public ${value.type} max${value.columnName?cap_first};
diff --git a/src/main/resources/mongoDBDao.template b/src/main/resources/generater/mongoDBDao.template
similarity index 89%
rename from src/main/resources/mongoDBDao.template
rename to src/main/resources/generater/mongoDBDao.template
index 1ef3608..cc5ba65 100644
--- a/src/main/resources/mongoDBDao.template
+++ b/src/main/resources/generater/mongoDBDao.template
@@ -47,7 +47,7 @@
 
     private Query getQuery(DaoQuery daoQuery){
           List<Criteria> andList=new ArrayList<>();
-           <#list columnDataList as value>
+           <#list daoQueryColumnDataList as value>
                <#if (value.type!"") == "Date">
                if(daoQuery.min${value.columnName?cap_first}!=null){
                     andList.add(Criteria.where("${value.columnName}").gte(daoQuery.min${value.columnName?cap_first}));
@@ -57,7 +57,11 @@
                }
                <#else>
                if(daoQuery.${value.columnName}!=null){
+                 <#if (value.queryType!"") == "equal">
                     andList.add(Criteria.where("${value.columnName}").is(daoQuery.${value.columnName}));
+                 <#else>
+                      andList.add(Criteria.where("${value.columnName}").regex(daoQuery.${value.columnName}));
+                 </#if>
                }
                </#if>
           </#list>
@@ -71,8 +75,8 @@
     }
 
   public static class DaoQuery{
-     <#if columnDataList??>
-       <#list columnDataList as value>
+     <#if daoQueryColumnDataList??>
+       <#list daoQueryColumnDataList as value>
         <#if (value.type!"") == "Date">
         public ${value.type} min${value.columnName?cap_first};
         public ${value.type} max${value.columnName?cap_first};
diff --git a/src/main/resources/service.template b/src/main/resources/generater/service.template
similarity index 100%
rename from src/main/resources/service.template
rename to src/main/resources/generater/service.template
diff --git a/src/main/resources/serviceImpl.template b/src/main/resources/generater/serviceImpl.template
similarity index 100%
rename from src/main/resources/serviceImpl.template
rename to src/main/resources/generater/serviceImpl.template
diff --git a/src/test/java/com/generater/GeneratorTest.java b/src/test/java/com/generater/GeneratorTest.java
index be8a329..818a88f 100644
--- a/src/test/java/com/generater/GeneratorTest.java
+++ b/src/test/java/com/generater/GeneratorTest.java
@@ -1,19 +1,82 @@
 package com.generater;
 
+import freemarker.cache.StringTemplateLoader;
+import freemarker.template.Template;
 import org.springframework.data.annotation.Id;
+import org.springframework.data.annotation.Transient;
+import org.yeshi.utils.FreemarkerUtils;
 import org.yeshi.utils.generater.SpringComponentGenerater;
+import org.yeshi.utils.generater.annotation.admin.form.CheckBox;
+import org.yeshi.utils.generater.annotation.admin.form.Select;
+import org.yeshi.utils.generater.annotation.admin.form.Text;
+import org.yeshi.utils.generater.entity.KeyValue;
 import org.yeshi.utils.generater.entity.MongoDBDaoData;
+import org.yeshi.utils.generater.entity.admin.AdminGeneraterInfo;
 import org.yeshi.utils.generater.mybatis.Column;
 import org.yeshi.utils.generater.mybatis.MyBatisMapperUtil;
 import org.yeshi.utils.generater.mybatis.Table;
 
-import java.util.Date;
+import java.io.File;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.regex.Pattern;
 
 public class GeneratorTest {
 
-        public static void main(String[] args) throws Exception {
+    public static void main(String[] args) throws Exception {
         //SpringComponentGenerater.createMongoDao(new MongoDBDaoData.Builder().setBaseDaoClass(BaseDao.class).setDaoPackageName("com.generator.result").setEntityClass(Entity.class).create(), "D:\\workspace\\server\\utils\\src\\test\\java\\com\\generater\\result");
-        MyBatisMapperUtil.createMapper(Entity.class);
+//        MyBatisMapperUtil.createMapper(Entity.class);
+
+
+//鎵撲贡xml涓殑鏁版嵁
+//        Scanner scanner = new Scanner(new File("D:\\workspace\\Android\\buwan\\HanJuPlayer\\app\\res\\values\\strings.xml"));
+//        List<String> lines = new ArrayList<>();
+//        while (scanner.hasNextLine()) {
+//            String line = scanner.nextLine().trim();
+//            if (line == null || (line.startsWith("<?xml") || line.contains("<resources>") || line.contains("</resources>")))
+//                continue;
+//            lines.add(line);
+//        }
+//        scanner.close();
+//        Collections.shuffle(lines);
+//        for (String line : lines) {
+//            System.out.println(line);
+//        }
+
+
+        AdminGeneraterInfo info = new AdminGeneraterInfo.Builder().setEntityClass(TestEntity.class).build();
+
+        //灏嗘墍鏈夌殑鎺т欢妯℃澘鍔犺浇杩涘幓
+        String[] template = new String[]{
+                "admin/form/checkBox.ftl",
+                "admin/form/img.ftl",
+                "admin/form/password.ftl",
+                "admin/form/radioGroup.ftl",
+                "admin/form/select.ftl",
+                "admin/form/switch.ftl",
+                "admin/form/text.ftl",
+                "admin/form/textArea.ftl",
+                "admin/add.ftl"
+        };
+
+        Map<String, InputStream> map = new HashMap<>();
+        for (String st : template) {
+            map.put(st, SpringComponentGenerater.class.getClassLoader().getResourceAsStream("generater/" + st));
+        }
+
+        String result = FreemarkerUtils.generateInputStream(info, "admin/add.ftl", map);
+
+
+        System.out.println(result);
+
+
+        //
+//        boolean match = Pattern.matches("^(https://){1}.*(\\.m3u8)$", "https://n1.szjal.cn/20210805/qnDXhXBa/index.m3u8123");
+//        System.out.println(match);
 
     }
 
diff --git a/src/test/java/com/generater/TestEntity.java b/src/test/java/com/generater/TestEntity.java
new file mode 100644
index 0000000..0d6211b
--- /dev/null
+++ b/src/test/java/com/generater/TestEntity.java
@@ -0,0 +1,132 @@
+package com.generater;
+
+import org.springframework.data.annotation.Id;
+import org.yeshi.utils.generater.annotation.admin.AdminController;
+import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
+import org.yeshi.utils.generater.annotation.admin.Show;
+import org.yeshi.utils.generater.annotation.admin.form.Img;
+import org.yeshi.utils.generater.annotation.admin.form.RadioGroup;
+import org.yeshi.utils.generater.annotation.admin.form.Select;
+import org.yeshi.utils.generater.annotation.admin.form.Text;
+import org.yeshi.utils.generater.entity.admin.FormVerifyType;
+
+/**
+ * @author Administrator
+ * @title: TestEntity
+ * @description: 娴嬭瘯entity
+ * @date 2021/9/23 14:22
+ */
+@AdminController(mapping = "admin/api/test", title = "娴嬭瘯", searchForm = TestEntity.SearchForm.class)
+public class TestEntity {
+    @Id
+    private String id;
+
+    @DaoQueryCondition(queryType = DaoQueryCondition.QueryType.contains)
+    @Show(order = 0, title = "鏄电О")
+    @Text(title = "鏄电О", maxLength = 50, require = true, placeHolder = "璇疯緭鍏ユ樀绉�", desc = "鏄电О涓嶈兘鍖呭惈鐗规畩瀛楃", verifyType = FormVerifyType.regex, verifyValue = "^.{0-100}$", verifyNotifyMsg = "璇疯緭鍏ユ纭殑鏄电О")
+    private String nickName;
+
+    @DaoQueryCondition
+    @Show(order = 1, title = "绫诲瀷")
+    @Select(values = {"1,鐢�", "2,濂�"}, title = "绫诲瀷")
+    private int type;
+
+    @DaoQueryCondition
+    @Show(order = 2, title = "鎬у埆")
+    @RadioGroup(values = {"1,鐢�", "2,濂�"}, title = "鎬у埆")
+    private int sex;
+
+    @Show(order = 3, title = "澶村儚", showType = Show.ShowType.IMG, imgWidth = 50, imgHeight = 50)
+    @Img(width = 50, height = 50, title = "澶村儚")
+    private String portrait;
+
+    @DaoQueryCondition
+    @Show(order = 4, title = "鐪�")
+    @Select(apiPath = "/admin/api/getProvince", title = "鐪�")
+    private String province;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(String nickName) {
+        this.nickName = nickName;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    public int getSex() {
+        return sex;
+    }
+
+    public void setSex(int sex) {
+        this.sex = sex;
+    }
+
+    public String getPortrait() {
+        return portrait;
+    }
+
+    public void setPortrait(String portrait) {
+        this.portrait = portrait;
+    }
+
+    public String getProvince() {
+        return province;
+    }
+
+    public void setProvince(String province) {
+        this.province = province;
+    }
+
+
+    public class SearchForm {
+
+        @Text(title = "寮�濮嬫棩鏈�", inputType = Text.Type.DATE)
+        private String startDate;
+        @Text(title = "缁撴潫鏃ユ湡", inputType = Text.Type.DATE)
+        private String endDate;
+        @Text(title = "璇疯緭鍏ュ叧閿瘝", inputType = Text.Type.TEXT)
+        private String key;
+
+
+        public String getStartDate() {
+            return startDate;
+        }
+
+        public void setStartDate(String startDate) {
+            this.startDate = startDate;
+        }
+
+        public String getEndDate() {
+            return endDate;
+        }
+
+        public void setEndDate(String endDate) {
+            this.endDate = endDate;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public void setKey(String key) {
+            this.key = key;
+        }
+    }
+}

--
Gitblit v1.8.0