From 5bd123fb20899d3ba261063f60625daecee57a84 Mon Sep 17 00:00:00 2001 From: liuyiwuqing <1520431201@qq.com> Date: Mon, 3 Jun 2024 17:13:53 +0800 Subject: [PATCH] =?UTF-8?q?v1.1.0=201.=20=E5=AF=B9=E6=8E=A5imgtp=E5=9B=BE?= =?UTF-8?q?=E5=BA=8A=202.=20=E4=BC=98=E5=8C=96=E9=99=84=E4=BB=B6=E9=80=89?= =?UTF-8?q?=E9=A1=B9=E5=8D=A1=EF=BC=8C=E5=AE=9E=E7=8E=B0=E5=9B=BE=E5=BA=8A?= =?UTF-8?q?=E9=80=89=E9=A1=B9=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD=203.=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BE=9D=E8=B5=96=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 +- .../picturebed/constant/CommonConstant.java | 1 + .../muyin/picturebed/domain/ImgtpImage.java | 28 ++ .../picturebed/service/BaseImageService.java | 45 +++ .../picturebed/service/ImgtpService.java | 12 + .../service/Impl/ImgtpServiceImpl.java | 134 +++++++ .../picturebed/service/LskyProService.java | 35 +- .../picturebed/service/PictureBedService.java | 26 ++ .../muyin/picturebed/service/SmmsService.java | 36 +- src/main/resources/extensions/settings.yaml | 6 +- ui/package.json | 2 +- ui/src/components/ImgtpSelectorProvider.vue | 330 ++++++++++++++++++ ui/src/components/image/ImageUploadModal.vue | 11 +- ui/src/index.ts | 33 +- ui/src/views/PictureBeds.vue | 54 ++- 15 files changed, 650 insertions(+), 107 deletions(-) create mode 100644 src/main/java/site/muyin/picturebed/domain/ImgtpImage.java create mode 100644 src/main/java/site/muyin/picturebed/service/BaseImageService.java create mode 100644 src/main/java/site/muyin/picturebed/service/ImgtpService.java create mode 100644 src/main/java/site/muyin/picturebed/service/Impl/ImgtpServiceImpl.java create mode 100644 ui/src/components/ImgtpSelectorProvider.vue diff --git a/build.gradle b/build.gradle index 771b0d3..45fdabb 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation platform('run.halo.tools.platform:plugin:2.14.0-SNAPSHOT') + implementation platform('run.halo.tools.platform:plugin:2.15.0-SNAPSHOT') compileOnly 'run.halo.app:api' testImplementation 'run.halo.app:api' @@ -53,6 +53,6 @@ build { } halo { - version = '2.15.2' + version = '2.16.0' debug = true } diff --git a/src/main/java/site/muyin/picturebed/constant/CommonConstant.java b/src/main/java/site/muyin/picturebed/constant/CommonConstant.java index 31edf16..18768dc 100644 --- a/src/main/java/site/muyin/picturebed/constant/CommonConstant.java +++ b/src/main/java/site/muyin/picturebed/constant/CommonConstant.java @@ -11,5 +11,6 @@ public class CommonConstant { public static class PictureBedType { public static final String LSKY = "lsky"; public static final String SMMS = "smms"; + public static final String IMGTP = "imgtp"; } } diff --git a/src/main/java/site/muyin/picturebed/domain/ImgtpImage.java b/src/main/java/site/muyin/picturebed/domain/ImgtpImage.java new file mode 100644 index 0000000..2a53d8f --- /dev/null +++ b/src/main/java/site/muyin/picturebed/domain/ImgtpImage.java @@ -0,0 +1,28 @@ +package site.muyin.picturebed.domain; + +import lombok.Data; + +/** + * @author: lywq + * @date: 2024/05/29 09:41 + * @version: v1.0.0 + * @description: + **/ +@Data +public class ImgtpImage { + private String id; + private String strategy; + private String path; + private String name; + private String alias_name; + private String pathname; + private Float size; + private String mime; + private String sha1; + private String md5; + private String ip; + private Integer suspicious; + private String upload_time; + private String upload_date; + private String url; +} diff --git a/src/main/java/site/muyin/picturebed/service/BaseImageService.java b/src/main/java/site/muyin/picturebed/service/BaseImageService.java new file mode 100644 index 0000000..6e2439f --- /dev/null +++ b/src/main/java/site/muyin/picturebed/service/BaseImageService.java @@ -0,0 +1,45 @@ +package site.muyin.picturebed.service; + +import org.springframework.util.MultiValueMap; +import reactor.core.publisher.Mono; +import site.muyin.picturebed.query.CommonQuery; +import site.muyin.picturebed.vo.PageResult; +import site.muyin.picturebed.vo.ResultsVO; + +/** + * @author: lywq + * @date: 2024/05/29 09:51 + * @version: v1.0.0 + * @description: + **/ +public interface BaseImageService { + /** + * 上传图片 + * + * @param multipartData: + * @return: reactor.core.publisher.Mono + * @author: lywq + * @date: 2024/05/22 21:33 + **/ + Mono uploadImage(MultiValueMap multipartData); + + /** + * 获取图片列表 + * + * @param query: + * @return: reactor.core.publisher.Mono> + * @author: lywq + * @date: 2024/05/22 21:33 + **/ + Mono> getImageList(CommonQuery query); + + /** + * 删除图片 + * + * @param query: + * @return: reactor.core.publisher.Mono + * @author: lywq + * @date: 2024/05/22 21:33 + **/ + Mono deleteImage(CommonQuery query); +} diff --git a/src/main/java/site/muyin/picturebed/service/ImgtpService.java b/src/main/java/site/muyin/picturebed/service/ImgtpService.java new file mode 100644 index 0000000..2f69ec9 --- /dev/null +++ b/src/main/java/site/muyin/picturebed/service/ImgtpService.java @@ -0,0 +1,12 @@ +package site.muyin.picturebed.service; + +import site.muyin.picturebed.domain.ImgtpImage; + +/** + * @author: lywq + * @date: 2024/05/29 09:48 + * @version: v1.0.0 + * @description: Imgtp图床服务接口 + **/ +public interface ImgtpService extends BaseImageService { +} diff --git a/src/main/java/site/muyin/picturebed/service/Impl/ImgtpServiceImpl.java b/src/main/java/site/muyin/picturebed/service/Impl/ImgtpServiceImpl.java new file mode 100644 index 0000000..52f6a93 --- /dev/null +++ b/src/main/java/site/muyin/picturebed/service/Impl/ImgtpServiceImpl.java @@ -0,0 +1,134 @@ +package site.muyin.picturebed.service.Impl; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import site.muyin.picturebed.config.PictureBedConfig; +import site.muyin.picturebed.domain.ImgtpImage; +import site.muyin.picturebed.query.CommonQuery; +import site.muyin.picturebed.service.ImgtpService; +import site.muyin.picturebed.utils.PluginCacheManager; +import site.muyin.picturebed.vo.PageResult; +import site.muyin.picturebed.vo.ResultsVO; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static site.muyin.picturebed.constant.CommonConstant.PictureBedType.IMGTP; + +/** + * @author: lywq + * @date: 2024/05/29 09:52 + * @version: v1.0.0 + * @description: Imgtp图床服务接口 + **/ +@Service +@RequiredArgsConstructor +public class ImgtpServiceImpl implements ImgtpService { + + private final PluginCacheManager pluginCacheManager; + + @Override + public Mono uploadImage(MultiValueMap multipartData) { + Map paramMap = new HashMap(1); + paramMap.put("file", multipartData); + return req("upload", paramMap) + .map(response -> { + if (response.code == 200) { + return ResultsVO.success(response.msg, response.data); + } + return ResultsVO.failure(response.msg); + }); + } + + @Override + public Mono> getImageList(CommonQuery query) { + Map paramMap = new HashMap(1); + paramMap.put("page", query.getPage()); + paramMap.put("rows", query.getSize()); + String params = HttpUtil.toParams(paramMap); + + return req("images" + "?" + params, null) + .map(response -> { + if (response.code == 200) { + ImgtpImagePageRes imgtpImagePageRes = JSONUtil.toBean(JSONUtil.toJsonStr(response.data), ImgtpImagePageRes.class); + return new PageResult<>(imgtpImagePageRes.current_page, imgtpImagePageRes.per_page, imgtpImagePageRes.total, imgtpImagePageRes.last_page, imgtpImagePageRes.data); + } + return null; + }); + } + + @Override + public Mono deleteImage(CommonQuery query) { + if (ObjectUtil.isEmpty(query.getImageId())) { + return Mono.just(false); + } + Map paramMap = new HashMap(1); + paramMap.put("id", query.getImageId()); + String params = HttpUtil.toParams(paramMap); + return req("delete" + "?" + params, null) + .map(response -> { + return response.code == 200; + }); + } + + private Mono req(String path, Map paramMap) { + PictureBedConfig pictureBedConfig = pluginCacheManager.getConfig(PictureBedConfig.class); + PictureBedConfig.PictureBed config = pictureBedConfig.getPictureBeds().stream().filter(p -> p.getPictureBedType().equals(IMGTP)).findFirst().orElseThrow(); + String url = config.getPictureBedUrl(); + String authorization = config.getPictureBedToken(); + + WebClient WEB_CLIENT = + WebClient.builder() + .defaultHeader("token", authorization).build(); + + if (StrUtil.startWithAny(path, "images", "delete")) { + return WEB_CLIENT.post() + .uri(url + path) + .retrieve() + .bodyToMono(new ParameterizedTypeReference<>() { + }); + } else if (StrUtil.equals(path, "upload")) { + MultiValueMap multiValueMap = (MultiValueMap) paramMap.get("file"); + MultiValueMap multipartData = new LinkedMultiValueMap<>(); + multipartData.add("image", multiValueMap.getFirst("file")); + + return WEB_CLIENT.post() + .uri(url + path) + .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_JPEG_VALUE) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(multipartData)) + .retrieve() + .bodyToMono(new ParameterizedTypeReference<>() { + }); + + } else { + throw new IllegalArgumentException("Unsupported path: " + path); + } + } + + @Data + class ImgtpImagePageRes { + Integer total; + Integer per_page; + Integer current_page; + Integer last_page; + List data; + } + + public record ImgtpResponseRecord(Integer code, String msg, Object data, Integer time) { + } +} diff --git a/src/main/java/site/muyin/picturebed/service/LskyProService.java b/src/main/java/site/muyin/picturebed/service/LskyProService.java index f2ca7ac..a4c0992 100644 --- a/src/main/java/site/muyin/picturebed/service/LskyProService.java +++ b/src/main/java/site/muyin/picturebed/service/LskyProService.java @@ -1,12 +1,9 @@ package site.muyin.picturebed.service; -import org.springframework.util.MultiValueMap; import reactor.core.publisher.Mono; import site.muyin.picturebed.domain.LskyProAlbum; import site.muyin.picturebed.domain.LskyProImage; import site.muyin.picturebed.query.CommonQuery; -import site.muyin.picturebed.vo.PageResult; -import site.muyin.picturebed.vo.ResultsVO; import java.util.List; @@ -16,17 +13,7 @@ * @version: v1.0.0 * @description: 兰空图床服务接口 **/ -public interface LskyProService { - - /** - * 上传图片 - * - * @param multipartData: - * @return: reactor.core.publisher.Mono - * @author: lywq - * @date: 2024/05/22 21:31 - **/ - Mono uploadImage(MultiValueMap multipartData); +public interface LskyProService extends BaseImageService { /** * 获取图库列表 @@ -37,24 +24,4 @@ public interface LskyProService { * @date: 2024/05/22 21:31 **/ Mono> getAlbumList(CommonQuery query); - - /** - * 获取图片列表 - * - * @param query: - * @return: reactor.core.publisher.Mono> - * @author: lywq - * @date: 2024/05/22 21:31 - **/ - Mono> getImageList(CommonQuery query); - - /** - * 删除图片 - * - * @param query: - * @return: reactor.core.publisher.Mono - * @author: lywq - * @date: 2024/05/22 21:31 - **/ - Mono deleteImage(CommonQuery query); } diff --git a/src/main/java/site/muyin/picturebed/service/PictureBedService.java b/src/main/java/site/muyin/picturebed/service/PictureBedService.java index 1765187..b5c4af9 100644 --- a/src/main/java/site/muyin/picturebed/service/PictureBedService.java +++ b/src/main/java/site/muyin/picturebed/service/PictureBedService.java @@ -6,6 +6,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.MultiValueMap; import reactor.core.publisher.Mono; +import site.muyin.picturebed.domain.ImgtpImage; import site.muyin.picturebed.domain.LskyProAlbum; import site.muyin.picturebed.domain.LskyProImage; import site.muyin.picturebed.domain.SmmsImage; @@ -18,6 +19,7 @@ import java.io.File; import java.util.List; +import static site.muyin.picturebed.constant.CommonConstant.PictureBedType.IMGTP; import static site.muyin.picturebed.constant.CommonConstant.PictureBedType.LSKY; import static site.muyin.picturebed.constant.CommonConstant.PictureBedType.SMMS; @@ -33,6 +35,7 @@ public class PictureBedService { private final LskyProService lskyProService; private final SmmsService smmsService; + private final ImgtpService imgtpService; public Mono uploadImage(CommonQuery query, MultiValueMap parts) { String type = query.getType(); @@ -41,6 +44,8 @@ public Mono uploadImage(CommonQuery query, MultiValueMap> getImageList(CommonQuery query) { PageResult imageVOPageResult = convertSmmsImageListToImageVOList(smmsImages); return Mono.just(imageVOPageResult); }); + case IMGTP: + return imgtpService.getImageList(query).flatMap(imgtpImages -> { + PageResult imageVOPageResult = convertImgtpImageListToImageVOList(imgtpImages); + return Mono.just(imageVOPageResult); + }); default: // TODO: get image list from other picture bed service throw new IllegalArgumentException("暂不支持该图片托管服务"); @@ -91,6 +101,8 @@ public Mono deleteImage(CommonQuery query) { return lskyProService.deleteImage(query); case SMMS: return smmsService.deleteImage(query); + case IMGTP: + return imgtpService.deleteImage(query); default: // TODO: delete image from other picture bed service throw new IllegalArgumentException("暂不支持该图片托管服务"); @@ -137,6 +149,20 @@ private PageResult convertSmmsImageListToImageVOList(PageResult(page.getPage(), page.getSize(), page.getTotalCount(), page.getTotalPages(), imageVOList); } + private PageResult convertImgtpImageListToImageVOList(PageResult imgtpImages) { + List imageList = imgtpImages.getList(); + List imageVOList = imageList.stream().map(image -> { + ImageVO imageVO = new ImageVO(); + imageVO.setId(image.getId()) + .setName(image.getName()) + .setUrl(image.getUrl()) + .setMediaType(image.getMime()) + .setSize(image.getSize()); + return imageVO; + }).toList(); + return new PageResult<>(imgtpImages.getPage(), imgtpImages.getSize(), imgtpImages.getTotalCount(), imgtpImages.getTotalPages(), imageVOList); + } + public static String getMediaType(String fileName) { MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap(); File file = new File(fileName); diff --git a/src/main/java/site/muyin/picturebed/service/SmmsService.java b/src/main/java/site/muyin/picturebed/service/SmmsService.java index c4dee7a..9269ffc 100644 --- a/src/main/java/site/muyin/picturebed/service/SmmsService.java +++ b/src/main/java/site/muyin/picturebed/service/SmmsService.java @@ -1,11 +1,6 @@ package site.muyin.picturebed.service; -import org.springframework.util.MultiValueMap; -import reactor.core.publisher.Mono; import site.muyin.picturebed.domain.SmmsImage; -import site.muyin.picturebed.query.CommonQuery; -import site.muyin.picturebed.vo.PageResult; -import site.muyin.picturebed.vo.ResultsVO; /** * @author: lywq @@ -13,34 +8,5 @@ * @version: v1.0.0 * @description: SM.MS图床服务接口 **/ -public interface SmmsService { - - /** - * 上传图片 - * - * @param multipartData: - * @return: reactor.core.publisher.Mono - * @author: lywq - * @date: 2024/05/22 21:33 - **/ - Mono uploadImage(MultiValueMap multipartData); - - /** - * 获取图片列表 - * - * @param query: - * @return: reactor.core.publisher.Mono> - * @author: lywq - * @date: 2024/05/22 21:33 - **/ - Mono> getImageList(CommonQuery query); - - /** - * 删除图片 - * @param query: - * @return: reactor.core.publisher.Mono - * @author: lywq - * @date: 2024/05/22 21:33 - **/ - Mono deleteImage(CommonQuery query); +public interface SmmsService extends BaseImageService { } diff --git a/src/main/resources/extensions/settings.yaml b/src/main/resources/extensions/settings.yaml index 184b21a..2236157 100644 --- a/src/main/resources/extensions/settings.yaml +++ b/src/main/resources/extensions/settings.yaml @@ -11,7 +11,7 @@ spec: name: pictureBeds label: 图床接口 value: [] - max: 2 + max: 3 min: 1 children: - $formkit: select @@ -21,8 +21,10 @@ spec: options: - label: 兰空图床 value: lsky - - label: SM.MS + - label: SM.MS图床 value: smms + - label: ImgTP图床 + value: imgtp - $formkit: select name: pictureBedEnabled key: pictureBedEnabled diff --git a/ui/package.json b/ui/package.json index a0ce8c3..078ca73 100644 --- a/ui/package.json +++ b/ui/package.json @@ -8,7 +8,7 @@ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" }, "dependencies": { - "@uppy/core": "^3.8.0", + "@uppy/core": "^3.11.3", "@vueuse/core": "^10.3.0", "pretty-bytes": "^6.0.0", "path-browserify": "^1.0.1", diff --git a/ui/src/components/ImgtpSelectorProvider.vue b/ui/src/components/ImgtpSelectorProvider.vue new file mode 100644 index 0000000..601c444 --- /dev/null +++ b/ui/src/components/ImgtpSelectorProvider.vue @@ -0,0 +1,330 @@ + + diff --git a/ui/src/components/image/ImageUploadModal.vue b/ui/src/components/image/ImageUploadModal.vue index a118b81..42036b9 100644 --- a/ui/src/components/image/ImageUploadModal.vue +++ b/ui/src/components/image/ImageUploadModal.vue @@ -25,14 +25,13 @@ const onVisibleChange = (visible: boolean) => { } }; -const onProcessCompleted = (response: SuccessResponse) => { +const onUploaded = async (response: SuccessResponse) => { console.log("上传结果", response); Toast.success("上传成功!"); }; const onError = (file: UppyFile, response: ErrorResponse) => { - const body = response.body; - console.error(`上传失败:${file.name} ${body}`); + console.log("上传失败", file, response, response.body); }; const uploadUrl = `/apis/picturebed.muyin.site/v1alpha1/uploadImage?type=${props.picBedType}`; @@ -52,12 +51,12 @@ const uploadUrl = `/apis/picturebed.muyin.site/v1alpha1/uploadImage?type=${props :restrictions="{ allowedFileTypes: ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.bmp', '.webp'], }" + width="100%" note="仅支持图片格式" :endpoint="uploadUrl" - width="100%" - @uploaded="onProcessCompleted" - :done-button-handler="() => onVisibleChange(false)" + @uploaded="onUploaded" @error="onError" + :doneButtonHandler="() => onVisibleChange(false)" /> diff --git a/ui/src/index.ts b/ui/src/index.ts index e214835..170a658 100644 --- a/ui/src/index.ts +++ b/ui/src/index.ts @@ -1,23 +1,31 @@ import {type AttachmentSelectProvider, definePlugin,} from "@halo-dev/console-shared"; -import {markRaw} from "vue"; +import {markRaw, ref} from "vue"; import "./styles/tailwind.css"; -import LskySelectorProvider from "@/components/LskySelectorProvider.vue"; -import SmmsSelectorProvider from "@/components/SmmsSelectorProvider.vue"; import MdiPicture360Outline from '~icons/mdi/picture-360-outline'; import PictureBeds from "@/views/PictureBeds.vue"; +import LskySelectorProvider from "@/components/LskySelectorProvider.vue"; +import SmmsSelectorProvider from "@/components/SmmsSelectorProvider.vue"; +import ImgtpSelectorProvider from "@/components/ImgtpSelectorProvider.vue"; +import axios from "axios"; + -const attachmentSelectProviders: AttachmentSelectProvider[] = [ - { +const pictureBedSelectProviders = ref({ + 'lsky': { id: "lsky-selector", label: "兰空图床", component: markRaw(LskySelectorProvider), }, - { + 'smms': { id: "smms-selector", label: "SM.MS图床", component: markRaw(SmmsSelectorProvider), }, -]; + 'imgtp': { + id: "imgtp-selector", + label: "ImgTP图床", + component: markRaw(ImgtpSelectorProvider), + } +}); export default definePlugin({ components: {}, @@ -43,7 +51,16 @@ export default definePlugin({ }, ], extensionPoints: { - "attachment:selector:create": (): AttachmentSelectProvider[] => { + "attachment:selector:create": async () => { + const attachmentSelectProviders: AttachmentSelectProvider[] = []; + const {data} = await axios.get( + "/apis/picturebed.muyin.site/v1alpha1/pictureBeds" + ); + data.forEach(item => { + if (item.enabled) { + attachmentSelectProviders.push(pictureBedSelectProviders.value[item.type]); + } + }); return attachmentSelectProviders; }, }, diff --git a/ui/src/views/PictureBeds.vue b/ui/src/views/PictureBeds.vue index 6768eba..b823353 100644 --- a/ui/src/views/PictureBeds.vue +++ b/ui/src/views/PictureBeds.vue @@ -1,16 +1,16 @@ @@ -50,18 +62,22 @@ onMounted(() => {
- + + +