浏览代码

低代码

huangxiao 1 月之前
父节点
当前提交
b5e48bc105

文件差异内容过多而无法显示
+ 0 - 12
doc/backup.json


+ 5 - 0
pom.xml

@@ -64,6 +64,11 @@
             <artifactId>oshi-core</artifactId>
             <version>6.2.2</version>
         </dependency>
+        <dependency>
+            <groupId>org.xerial</groupId>
+            <artifactId>sqlite-jdbc</artifactId>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 

+ 35 - 9
src/test/java/mingsoft/Main.java

@@ -4,12 +4,18 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.ZipUtil;
 import lombok.SneakyThrows;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
 
 import java.io.File;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.StandardCopyOption;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 对<a href="https://code.mingsoft.net/">低代码平台</a>的伪破解
@@ -18,14 +24,26 @@ import java.util.Optional;
  * @date 2025-12-24
  */
 public class Main {
-    private static final File doc = Optional.ofNullable(Main.class.getResource("/"))
-            .map(URL::getFile)
-            .map(File::new)
-            .map(File::getParentFile)
-            .map(File::getParentFile)
-            .map(file -> new File(file, "doc"))
-            .orElseThrow();
-    private static final MingsoftService service = MingsoftService.of(FileUtil.getCanonicalPath(new File(doc, "client.txt")), FileUtil.getCanonicalPath(new File(doc, "backup.json"))).orElseThrow();
+    private static final File doc;
+    private static final MingsoftService service;
+
+    static {
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        ctx.getConfiguration().getRootLogger().setLevel(Level.INFO);
+        ctx.updateLoggers();
+        doc = Optional.ofNullable(Main.class.getResource("/"))
+                .map(URL::getFile)
+                .map(File::new)
+                .map(File::getParentFile)
+                .map(File::getParentFile)
+                .map(file -> new File(file, "doc"))
+                .orElseThrow();
+        service = MingsoftService.of(
+                        FileUtil.getCanonicalPath(new File(doc, "client.txt")),
+                        FileUtil.getCanonicalPath(new File(doc, "backup.db")))
+                .orElseThrow();
+    }
+
 
     public static void main(String[] args) {
         unzip();
@@ -54,7 +72,15 @@ public class Main {
             return true;
         }).forEach(codeFile -> {
             File localFile = new File(localSrc, codeFile.toString().replace(codeSrc.toString(), ""));
-            FileUtil.copyFile(codeFile, localFile, StandardCopyOption.REPLACE_EXISTING);
+            if (codeFile.getName().endsWith(".properties")) {
+                FileUtil.writeLines(Stream.concat(
+                                FileUtil.readLines(codeFile, StandardCharsets.ISO_8859_1).stream(),
+                                FileUtil.readLines(localFile, StandardCharsets.ISO_8859_1).stream())
+                        .distinct()
+                        .collect(Collectors.toList()), localFile, StandardCharsets.ISO_8859_1, false);
+            } else {
+                FileUtil.copyFile(codeFile, localFile, StandardCopyOption.REPLACE_EXISTING);
+            }
         });
     }
 }

+ 69 - 41
src/test/java/mingsoft/MingsoftService.java

@@ -1,22 +1,26 @@
 package mingsoft;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.EnumUtil;
-import cn.hutool.json.JSONArray;
-import cn.hutool.json.JSONObject;
+import cn.hutool.db.DbUtil;
+import cn.hutool.db.ds.pooled.DbConfig;
+import cn.hutool.db.ds.pooled.PooledDataSource;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
 import mingsoft.client.Info;
 import mingsoft.client.MingsoftClient;
 import mingsoft.client.MingsoftData;
 import mingsoft.client.MingsoftPreView;
 
 import java.io.File;
+import java.util.Comparator;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
 
 /**
  * 操作封装
@@ -26,6 +30,7 @@ import java.util.stream.StreamSupport;
  * @author hosea
  * @date 2025-12-24
  */
+@Slf4j(topic = "Service")
 public record MingsoftService(MingsoftClient client, Map<Info, MingsoftData> codes) {
     public MingsoftService {
         Assert.notNull(client, "客户端不能为空");
@@ -34,43 +39,64 @@ public record MingsoftService(MingsoftClient client, Map<Info, MingsoftData> cod
     /**
      * 创建
      *
-     * @param config   客户端配置
-     * @param jsonFile 本地代码备份
+     * @param config 客户端配置
+     * @param dbFile 本地代码备份
      */
-    public static Optional<MingsoftService> of(String config, String jsonFile) {
+    public static Optional<MingsoftService> of(String config, String dbFile) {
         return MingsoftClient.of(config)
-                .flatMap(client -> of(client, jsonFile));
+                .flatMap(client -> of(client, dbFile));
     }
 
     /**
      * 创建
      *
-     * @param client   客户端
-     * @param jsonFile 本地代码备份
+     * @param client 客户端
+     * @param dbFile 本地代码备份
      */
-    public static Optional<MingsoftService> of(MingsoftClient client, String jsonFile) {
-        return loadLocalCodeBackup(jsonFile)
+    @SneakyThrows
+    public static Optional<MingsoftService> of(MingsoftClient client, String dbFile) {
+        return loadLocalCodeBackup(dbFile)
                 .map(codes -> new MingsoftService(client, codes));
     }
 
     /**
      * 加载本地代码备份
      *
-     * @param jsonFile 备份代码的JSON文件
-     */
-    public static Optional<Map<Info, MingsoftData>> loadLocalCodeBackup(String jsonFile) {
-        return Optional.ofNullable(jsonFile)
-                .map(FileUtil::readUtf8String)
-                .map(JSONObject::new)
-                .map(json -> json.getJSONArray("data"))
-                .map(MingsoftService::from);
+     * @param dbFile 备份代码的SQLite文件
+     */
+    public static Optional<Map<Info, MingsoftData>> loadLocalCodeBackup(String dbFile) throws Exception {
+        DbConfig config = new DbConfig();
+        config.setUrl("jdbc:sqlite:" + dbFile);
+        config.setMaxActive(2);
+        try (PooledDataSource ds = new PooledDataSource(config)) {
+            return Optional.of(DbUtil.use(ds)
+                            .query("select * from ms where version is not null")
+                            .stream()
+                            .map(entity -> BeanUtil.fillBeanWithMap(entity, new MingsoftData(), CopyOptions.create().ignoreCase()))
+                            .collect(Collectors.groupingBy(MingsoftData::toInfo, Collectors.maxBy(Comparator.comparing(MingsoftData::getVersion))))
+                            .values()
+                            .stream()
+                            .map(opt -> opt.orElse(null))
+                            .filter(Objects::nonNull)
+                            .collect(Collectors.toMap(MingsoftData::toInfo, v -> v)))
+                    .map(list -> {
+                        log.info("查到SQLite的代码 Size:{}", list.size());
+                        return list;
+                    });
+        }
     }
 
     /**
      * 查服务器上的代码
      */
     public Optional<Map<Info, MingsoftData>> queryCodes() {
-        return client.list().map(MingsoftService::from);
+        return Optional.of(client.list()
+                        .map(json -> json.toBean(MingsoftData.class))
+                        .collect(Collectors.toMap(MingsoftData::toInfo, v -> v)))
+                .map(map -> {
+                    log.info("查到服务器上的代码 Size:{}", map.size());
+                    return map;
+                });
     }
 
     /**
@@ -134,6 +160,7 @@ public record MingsoftService(MingsoftClient client, Map<Info, MingsoftData> cod
      * @param code 代码
      */
     public boolean update(String id, MingsoftData code) {
+        log.info("修改 ID:{} Name:{} Table:{}", id, code.getPmoName(), code.getPmoTableName());
         return client.update(code.clone().setId(id)).isPresent();
     }
 
@@ -152,7 +179,11 @@ public record MingsoftService(MingsoftClient client, Map<Info, MingsoftData> cod
     public Optional<byte[]> downloadCode(String... ids) {
         return Optional.ofNullable(ids)
                 .filter(ArrayUtil::isNotEmpty)
-                .flatMap(client::download);
+                .flatMap(client::download)
+                .map(bs -> {
+                    log.info("下载代码 ID:{} Length:{}", ids, bs.length);
+                    return bs;
+                });
     }
 
     /**
@@ -177,13 +208,18 @@ public record MingsoftService(MingsoftClient client, Map<Info, MingsoftData> cod
                     FileUtil.mkParentDirs(file);
                     return file;
                 })
-                .flatMap(file -> downloadCode(ids).map(bytes -> FileUtil.writeBytes(bytes, file)));
+                .flatMap(file -> downloadCode(ids).map(bytes -> {
+                    File f = FileUtil.writeBytes(bytes, file);
+                    log.info("保存代码 ID:{} Length:{} File:{}", ids, bytes.length, f);
+                    return f;
+                }));
+
     }
 
     /**
      * 预览{@link Info#FORM_ID}代码
      */
-    public Stream<MingsoftPreView> previewCode() {
+    public Optional<Map<String, MingsoftPreView>> previewCode() {
         return previewCode(Info.FORM_ID);
     }
 
@@ -192,21 +228,13 @@ public record MingsoftService(MingsoftClient client, Map<Info, MingsoftData> cod
      *
      * @param id 表单ID
      */
-    public Stream<MingsoftPreView> previewCode(String id) {
-        return client.preview(id)
-                .stream()
-                .map(JSONArray::jsonIter)
-                .map(Iterable::spliterator)
-                .flatMap(iter -> StreamSupport.stream(iter, false))
-                .map(item -> item.toBean(MingsoftPreView.class));
-    }
-
-    /**
-     * 把JSON格式化转实体
-     */
-    private static Map<Info, MingsoftData> from(JSONArray array) {
-        return StreamSupport.stream(array.jsonIter().spliterator(), false)
-                .map(item -> item.toBean(MingsoftData.class))
-                .collect(Collectors.toMap(mingsoftData -> EnumUtil.fromStringQuietly(Info.class, mingsoftData.getPmoTableName().toUpperCase()), v -> v));
+    public Optional<Map<String, MingsoftPreView>> previewCode(String id) {
+        return Optional.of(client.preview(id)
+                        .map(item -> item.toBean(MingsoftPreView.class))
+                        .collect(Collectors.toMap(MingsoftPreView::getCode, v -> v)))
+                .map(map -> {
+                    log.info("预览代码 Size:{}", map.size());
+                    return map;
+                });
     }
 }

+ 19 - 9
src/test/java/mingsoft/client/MingsoftClient.java

@@ -10,10 +10,14 @@ import cn.hutool.http.HttpUtil;
 import cn.hutool.http.Method;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import net.mingsoft.base.entity.ResultData;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 /**
  * 客户端操作
@@ -22,9 +26,11 @@ import java.util.Optional;
  * @author hosea
  * @date 2025-12-24
  */
+@Slf4j(topic = " Client")
 public record MingsoftClient(String token) {
     public MingsoftClient {
         Assert.notBlank(token, "登录标识不能为空");
+        log.info("创建客户端 Token:{}", token);
     }
 
     /**
@@ -39,7 +45,7 @@ public record MingsoftClient(String token) {
     /**
      * 查列表
      */
-    public Optional<JSONArray> list() {
+    public Stream<JSONObject> list() {
         String url = "https://code.mingsoft.net/code-proxy/people/mcode/projectModelObject/list.do?projectId=" + Info.PROJECT_ID;
         try (HttpResponse response = HttpUtil.createRequest(Method.GET, url).addHeaders(createHeaders()).execute()) {
             return getResponseData(response);
@@ -49,7 +55,7 @@ public record MingsoftClient(String token) {
     /**
      * 修改
      */
-    public Optional<JSONObject> update(MingsoftData data) {
+    public Optional<ResultData> update(MingsoftData data) {
         String url = "https://code.mingsoft.net/code-proxy/people/mcode/projectModelObject/update.do";
         Map<String, Object> param = new HashMap<>();
         data.setPmoDatetime(null);
@@ -87,7 +93,7 @@ public record MingsoftClient(String token) {
     /**
      * 预览
      */
-    public Optional<JSONArray> preview(String id) {
+    public Stream<JSONObject> preview(String id) {
         String url = "https://code.mingsoft.net/code-proxy/people/mcode/project/view.do";
         Map<String, Object> param = new HashMap<>();
         param.put("projectModelObjectId", id);
@@ -104,22 +110,26 @@ public record MingsoftClient(String token) {
     /**
      * 获得响应数据
      */
-    private Optional<JSONArray> getResponseData(HttpResponse response) {
-        return checkResponse(response).map(json -> json.getJSONArray("data"));
+    private Stream<JSONObject> getResponseData(HttpResponse response) {
+        return checkResponse(response)
+                .map(result -> result.getData(JSONArray.class))
+                .stream()
+                .flatMap(array -> StreamSupport.stream(array.jsonIter().spliterator(), false));
     }
 
     /**
      * 检查响应
      */
-    private Optional<JSONObject> checkResponse(HttpResponse response) {
+    private Optional<ResultData> checkResponse(HttpResponse response) {
         return Optional.ofNullable(response.body())
                 .map(JSONObject::new)
                 .filter(MapUtil::isNotEmpty)
-                .filter(json -> {
-                    if (json.getInt("code") == HttpStatus.HTTP_OK) {
+                .map(json -> json.toBean(ResultData.class))
+                .filter(result -> {
+                    if (result.isSuccess()) {
                         return true;
                     }
-                    System.err.println(json);
+                    log.error("请求失败 Code:{} Msg:{}", result.getCode(), result.getMsg());
                     return false;
                 });
     }

+ 9 - 0
src/test/java/mingsoft/client/MingsoftData.java

@@ -1,5 +1,6 @@
 package mingsoft.client;
 
+import cn.hutool.core.util.EnumUtil;
 import lombok.Data;
 import lombok.SneakyThrows;
 import lombok.experimental.Accessors;
@@ -35,6 +36,7 @@ public class MingsoftData implements Cloneable {
     private String attachJson;
     private String createDate;
     private String updateDate;
+    private String version;
 
     /**
      * 克隆
@@ -60,4 +62,11 @@ public class MingsoftData implements Cloneable {
         setPmoTableName(info.getTable());
         return this;
     }
+
+    /**
+     * 得到类型
+     */
+    public Info toInfo() {
+        return EnumUtil.fromStringQuietly(Info.class, getPmoTableName().toUpperCase());
+    }
 }

部分文件因为文件数量过多而无法显示