feat: support select child packer

This commit is contained in:
ReaJason
2026-06-28 21:22:31 +08:00
parent a267048ed3
commit f19b1be9d4
16 changed files with 842 additions and 509 deletions
@@ -1,4 +1,4 @@
import type { PackerConfig } from "@/types/memshell";
import type { PackerConfig, PackerOption } from "@/types/memshell";
import type { MemShellFormSchema } from "@/types/schema";
import { PackageIcon } from "lucide-react";
@@ -6,9 +6,8 @@ import { useMemo } from "react";
import { Controller, type UseFormReturn, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import PackerSelector from "@/components/packer-selector";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { FieldLabel, FieldSet } from "@/components/ui/field";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Spinner } from "@/components/ui/spinner";
export default function PackageConfigCard({
@@ -30,8 +29,8 @@ export default function PackageConfigCard({
name: "server",
});
const options = useMemo(() => {
const filteredOptions = (packerConfig ?? []).filter((name) => {
const parents = useMemo<PackerOption[]>(() => {
return (packerConfig ?? []).filter(({ name }) => {
if (!shellType || shellType === " ") {
return true;
}
@@ -43,12 +42,7 @@ export default function PackageConfigCard({
}
return !name.startsWith("Agent") && !name.toLowerCase().startsWith("xxl");
});
form.setValue("packingMethod", filteredOptions[0]);
return filteredOptions.map((name) => ({
name: t(name),
value: name,
}));
}, [packerConfig, shellType, server, t, form]);
}, [packerConfig, shellType, server]);
return (
<Card className="w-full">
@@ -59,30 +53,12 @@ export default function PackageConfigCard({
</CardTitle>
</CardHeader>
<CardContent>
{options.length > 0 ? (
{parents.length > 0 ? (
<Controller
control={form.control}
name="packingMethod"
render={({ field }) => (
<FieldSet>
<FieldLabel>{t("packerMethod")}</FieldLabel>
<RadioGroup
name={field.name}
value={field.value}
defaultValue={options[0].value}
onValueChange={field.onChange}
className="grid grid-cols-2 md:grid-cols-3"
>
{options.map(({ name, value }) => (
<div key={value} className="flex items-center space-x-3">
<RadioGroupItem value={value} id={value} />
<FieldLabel className="text-xs" htmlFor={value}>
{name}
</FieldLabel>
</div>
))}
</RadioGroup>
</FieldSet>
<PackerSelector parents={parents} value={field.value} onChange={field.onChange} />
)}
/>
) : (
@@ -27,6 +27,24 @@ export function ResultComponent({
const isAgent = packMethod.startsWith("Agent");
const isJar = packMethod.endsWith("Jar");
const { t } = useTranslation();
const shellClassName = generateResult?.shellClassName;
const handleDownload = useCallback(() => {
const fileName = shellClassName?.substring(shellClassName?.lastIndexOf(".") ?? 0) ?? "";
if (packMethod.includes("JSP")) {
const fileExtension = packMethod.includes("JSPX") ? ".jspx" : ".jsp";
const content = new Blob([packResult as string], { type: "text/plain" });
return downloadContent(content, fileName, fileExtension);
} else if (packMethod.includes("JavaCommons") || packMethod.includes("Hessian")) {
const content = new Blob([base64ToBytes(packResult as string)], {
type: "application/octet-stream",
});
return downloadContent(content, fileName, ".data");
} else if (packMethod === "Base64") {
return downloadBytes(packResult as string, shellClassName);
}
}, [packMethod, packResult, shellClassName]);
if (allPackResults) {
return (
<MultiPackResult
@@ -55,24 +73,6 @@ export function ResultComponent({
);
}
const shellClassName = generateResult?.shellClassName;
const handleDownload = useCallback(() => {
const fileName = shellClassName?.substring(shellClassName?.lastIndexOf(".") ?? 0) ?? "";
if (packMethod.includes("JSP")) {
const fileExtension = packMethod.includes("JSPX") ? ".jspx" : ".jsp";
const content = new Blob([packResult as string], { type: "text/plain" });
return downloadContent(content, fileName, fileExtension);
} else if (packMethod.includes("JavaCommons") || packMethod.includes("Hessian")) {
const content = new Blob([base64ToBytes(packResult as string)], {
type: "application/octet-stream",
});
return downloadContent(content, fileName, ".data");
} else if (packMethod === "Base64") {
return downloadBytes(packResult as string, shellClassName);
}
}, [packMethod, packResult, shellClassName]);
return (
<CodeViewer
code={packResult ?? ""}