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.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; /** * 操作封装 * * @param client 客户端 * @param codes 本地代码备份 * @author hosea * @date 2025-12-24 */ @Slf4j(topic = "Service") public record MingsoftService(MingsoftClient client, Map codes) { public MingsoftService { Assert.notNull(client, "客户端不能为空"); } /** * 创建 * * @param config 客户端配置 * @param dbFile 本地代码备份 */ public static Optional of(String config, String dbFile) { return MingsoftClient.of(config) .flatMap(client -> of(client, dbFile)); } /** * 创建 * * @param client 客户端 * @param dbFile 本地代码备份 */ @SneakyThrows public static Optional of(MingsoftClient client, String dbFile) { return loadLocalCodeBackup(dbFile) .map(codes -> new MingsoftService(client, codes)); } /** * 加载本地代码备份 * * @param dbFile 备份代码的SQLite文件 */ public static Optional> 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> queryCodes() { 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; }); } /** * 复制代码,永远还原到{@link Info#FORM_ID}这个表单ID *

* {@link #copy(Info, Info, String)} * * @param old 旧的 * @param news 新的 */ public boolean copy(Info old, Info news) { return copy(old, news, Info.FORM_ID); } /** * 复制代码 *

* 从{@link #codes}备份中取是旧的代码 *

* 然后设置新的信息进去 *

* 还原到服务器上指定ID的表单 * * @param old 旧的 * @param news 新的 * @param id 表单ID */ public boolean copy(Info old, Info news, String id) { return update(id, codes.get(old).clone().info(news)); } /** * 还原代码,永远还原到{@link Info#FORM_ID}这个表单ID *

* {@link #restore(Info, String)} * * @param old 旧的 */ public boolean restore(Info old) { return restore(old, Info.FORM_ID); } /** * 还原代码 *

* 从{@link #codes}备份中取是旧的代码 *

* 还原到服务器上指定ID的表单 * * @param old 旧的 * @param id 表单ID */ public boolean restore(Info old, String id) { return update(id, codes.get(old)); } /** * 修改指定表单ID的代码 * * @param id 表单ID * @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(); } /** * 下载{@link Info#FORM_ID}代码 */ public Optional downloadCode() { return downloadCode(Info.FORM_ID); } /** * 下载代码 * * @param ids 表单ID */ public Optional downloadCode(String... ids) { return Optional.ofNullable(ids) .filter(ArrayUtil::isNotEmpty) .flatMap(client::download) .map(bs -> { log.info("下载代码 ID:{} Length:{}", ids, bs.length); return bs; }); } /** * 保存下载{@link Info#FORM_ID}代码 * * @param saveFile 保存的文件,如果已经存在,则不会保存 */ public Optional saveDownloadCode(File saveFile) { return saveDownloadCode(saveFile, Info.FORM_ID); } /** * 保存下载代码 * * @param saveFile 保存的文件,如果已经存在,则不会保存 * @param ids 表单ID */ public Optional saveDownloadCode(File saveFile, String... ids) { return Optional.ofNullable(saveFile) .filter(file -> !file.exists()) .map(file -> { FileUtil.mkParentDirs(file); return 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 Optional> previewCode() { return previewCode(Info.FORM_ID); } /** * 预览代码 * * @param id 表单ID */ public Optional> 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; }); } }