From 3caab77bfdca912248cc6f5632039c344c08d45d Mon Sep 17 00:00:00 2001 From: pikachuim Date: Mon, 9 Mar 2026 14:49:58 +0800 Subject: [PATCH 1/2] feat(func): support virtual host --- src/lang/en/entry.ts | 2 + src/lang/en/manage.json | 1 + src/lang/en/virtual_hosts.json | 9 ++ src/pages/manage/routes.tsx | 8 ++ src/pages/manage/sidemenu_items.tsx | 7 + src/pages/manage/virtual_hosts/AddOrEdit.tsx | 127 ++++++++++++++++++ .../manage/virtual_hosts/VirtualHosts.tsx | 115 ++++++++++++++++ src/types/index.ts | 1 + src/types/virtual_host.ts | 7 + 9 files changed, 277 insertions(+) create mode 100644 src/lang/en/virtual_hosts.json create mode 100644 src/pages/manage/virtual_hosts/AddOrEdit.tsx create mode 100644 src/pages/manage/virtual_hosts/VirtualHosts.tsx create mode 100644 src/types/virtual_host.ts diff --git a/src/lang/en/entry.ts b/src/lang/en/entry.ts index c9ab66178..238c69933 100644 --- a/src/lang/en/entry.ts +++ b/src/lang/en/entry.ts @@ -13,6 +13,7 @@ import shares from "./shares.json" import storages from "./storages.json" import tasks from "./tasks.json" import users from "./users.json" +import virtual_hosts from "./virtual_hosts.json" export const dict = { br, @@ -30,4 +31,5 @@ export const dict = { storages, tasks, users, + virtual_hosts, } diff --git a/src/lang/en/manage.json b/src/lang/en/manage.json index 5829c6ee7..226958751 100644 --- a/src/lang/en/manage.json +++ b/src/lang/en/manage.json @@ -11,6 +11,7 @@ "storages": "Storages", "shares": "Shares", "metas": "Metas", + "virtual_hosts": "Virtual Hosts", "profile": "Profile", "about": "About", "tasks": "Tasks", diff --git a/src/lang/en/virtual_hosts.json b/src/lang/en/virtual_hosts.json new file mode 100644 index 000000000..7e04017aa --- /dev/null +++ b/src/lang/en/virtual_hosts.json @@ -0,0 +1,9 @@ +{ + "domain": "Domain", + "domain_help": "The domain name to bind (e.g. blog.example.com)", + "path": "Path", + "path_help": "The OpenList path to map this domain to", + "enabled": "Enabled", + "web_hosting": "Web Hosting", + "web_hosting_help": "If enabled, HTML files will be served directly instead of the file browser" +} diff --git a/src/pages/manage/routes.tsx b/src/pages/manage/routes.tsx index 5fa444dfb..9da937714 100644 --- a/src/pages/manage/routes.tsx +++ b/src/pages/manage/routes.tsx @@ -39,6 +39,14 @@ const hide_routes: Route[] = [ to: "/metas/edit/:id", component: lazy(() => import("./metas/AddOrEdit")), }, + { + to: "/virtual_hosts/add", + component: lazy(() => import("./virtual_hosts/AddOrEdit")), + }, + { + to: "/virtual_hosts/edit/:id", + component: lazy(() => import("./virtual_hosts/AddOrEdit")), + }, { to: "/2fa", component: lazy(() => import("./users/2fa")), diff --git a/src/pages/manage/sidemenu_items.tsx b/src/pages/manage/sidemenu_items.tsx index 6776e38e4..360d1e00a 100644 --- a/src/pages/manage/sidemenu_items.tsx +++ b/src/pages/manage/sidemenu_items.tsx @@ -14,6 +14,7 @@ import { BsBucket, BsHddNetwork, BsArrowLeftRight, + BsGlobe, } from "solid-icons/bs" import { FiLogIn } from "solid-icons/fi" import { SiMetabase } from "solid-icons/si" @@ -187,6 +188,12 @@ export const side_menu_items: SideMenuItem[] = [ to: "/@manage/metas", component: lazy(() => import("./metas/Metas")), }, + { + title: "manage.sidemenu.virtual_hosts", + icon: BsGlobe, + to: "/@manage/virtual_hosts", + component: lazy(() => import("./virtual_hosts/VirtualHosts")), + }, { title: "manage.sidemenu.indexes", icon: BsSearch, diff --git a/src/pages/manage/virtual_hosts/AddOrEdit.tsx b/src/pages/manage/virtual_hosts/AddOrEdit.tsx new file mode 100644 index 000000000..ad8d264d8 --- /dev/null +++ b/src/pages/manage/virtual_hosts/AddOrEdit.tsx @@ -0,0 +1,127 @@ +import { + Button, + Switch as HopeSwitch, + FormControl, + FormHelperText, + FormLabel, + Heading, + Input, + VStack, +} from "@hope-ui/solid" +import { MaybeLoading, FolderChooseInput } from "~/components" +import { useFetch, useRouter, useT } from "~/hooks" +import { handleResp, notify, r } from "~/utils" +import { VirtualHost, PEmptyResp, PResp } from "~/types" +import { createStore } from "solid-js/store" + +const AddOrEdit = () => { + const t = useT() + const { params, back } = useRouter() + const { id } = params + const [vhost, setVhost] = createStore({ + id: 0, + enabled: true, + domain: "", + path: "", + web_hosting: false, + }) + const [vhostLoading, loadVhost] = useFetch( + (): PResp => r.get(`/admin/vhost/get?id=${id}`), + ) + + const initEdit = async () => { + const resp = await loadVhost() + handleResp(resp, setVhost) + } + if (id) { + initEdit() + } + const [okLoading, ok] = useFetch((): PEmptyResp => { + return r.post(`/admin/vhost/${id ? "update" : "create"}`, vhost) + }) + return ( + + + {t(`global.${id ? "edit" : "add"}`)} + + {/* 启用开关 */} + + + {t("virtual_hosts.enabled")} + + setVhost("enabled", e.currentTarget.checked)} + /> + + + {/* 域名 */} + + {t("virtual_hosts.domain")} + setVhost("domain", e.currentTarget.value)} + /> + {t("virtual_hosts.domain_help")} + + + {/* 路径 */} + + {t("virtual_hosts.path")} + setVhost("path", path)} + /> + {t("virtual_hosts.path_help")} + + + {/* Web 托管开关 */} + + + + {t("virtual_hosts.web_hosting")} + + + setVhost("web_hosting", e.currentTarget.checked) + } + /> + + {t("virtual_hosts.web_hosting_help")} + + + + + + ) +} + +export default AddOrEdit diff --git a/src/pages/manage/virtual_hosts/VirtualHosts.tsx b/src/pages/manage/virtual_hosts/VirtualHosts.tsx new file mode 100644 index 000000000..80dc39015 --- /dev/null +++ b/src/pages/manage/virtual_hosts/VirtualHosts.tsx @@ -0,0 +1,115 @@ +import { + Box, + Button, + HStack, + Table, + Tbody, + Td, + Th, + Thead, + Tr, + VStack, +} from "@hope-ui/solid" +import { createSignal, For } from "solid-js" +import { + useFetch, + useListFetch, + useManageTitle, + useRouter, + useT, +} from "~/hooks" +import { handleResp, notify, r } from "~/utils" +import { VirtualHost, PEmptyResp, PPageResp } from "~/types" +import { DeletePopover } from "../common/DeletePopover" +import { Wether } from "~/components" + +const VirtualHosts = () => { + const t = useT() + useManageTitle("manage.sidemenu.virtual_hosts") + const { to } = useRouter() + const [getVhostsLoading, getVhosts] = useFetch( + (): PPageResp => r.get("/admin/vhost/list"), + ) + const [vhosts, setVhosts] = createSignal([]) + const refresh = async () => { + const resp = await getVhosts() + handleResp(resp, (data) => setVhosts(data.content)) + } + refresh() + + const [deleting, deleteVhost] = useListFetch( + (id: number): PEmptyResp => r.post(`/admin/vhost/delete?id=${id}`), + ) + return ( + + + + + + + + + + + {(title) => } + + + + + + + {(vhost) => ( + + + + + + + + )} + + +
{t(`virtual_hosts.${title}`)}{t("global.operations")}
{vhost.domain}{vhost.path} + + + + + + + { + const resp = await deleteVhost(vhost.id) + handleResp(resp, () => { + notify.success(t("global.delete_success")) + refresh() + }) + }} + /> + +
+
+
+ ) +} + +export default VirtualHosts diff --git a/src/types/index.ts b/src/types/index.ts index 52f45e97b..8241449c1 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -8,3 +8,4 @@ export * from "./item_type" export * from "./meta" export * from "./task" export * from "./share" +export * from "./virtual_host" diff --git a/src/types/virtual_host.ts b/src/types/virtual_host.ts new file mode 100644 index 000000000..5114e5639 --- /dev/null +++ b/src/types/virtual_host.ts @@ -0,0 +1,7 @@ +export interface VirtualHost { + id: number + enabled: boolean + domain: string + path: string + web_hosting: boolean +} From e1c618ccd0097ad54e83a885b7a01328881e9b11 Mon Sep 17 00:00:00 2001 From: pikachuim Date: Thu, 14 May 2026 12:13:35 +0800 Subject: [PATCH 2/2] feat(func): merge vhost_db to sharing_db --- src/lang/en/entry.ts | 2 - src/lang/en/manage.json | 1 - src/lang/en/shares.json | 6 +- src/lang/en/virtual_hosts.json | 9 -- src/pages/manage/routes.tsx | 8 -- src/pages/manage/shares/AddOrEdit.tsx | 19 +++ src/pages/manage/shares/Share.tsx | 5 + src/pages/manage/shares/Shares.tsx | 11 +- src/pages/manage/sidemenu_items.tsx | 7 - src/pages/manage/virtual_hosts/AddOrEdit.tsx | 127 ------------------ .../manage/virtual_hosts/VirtualHosts.tsx | 115 ---------------- src/types/index.ts | 1 - src/types/share.ts | 2 + src/types/virtual_host.ts | 7 - 14 files changed, 41 insertions(+), 279 deletions(-) delete mode 100644 src/lang/en/virtual_hosts.json delete mode 100644 src/pages/manage/virtual_hosts/AddOrEdit.tsx delete mode 100644 src/pages/manage/virtual_hosts/VirtualHosts.tsx delete mode 100644 src/types/virtual_host.ts diff --git a/src/lang/en/entry.ts b/src/lang/en/entry.ts index 238c69933..c9ab66178 100644 --- a/src/lang/en/entry.ts +++ b/src/lang/en/entry.ts @@ -13,7 +13,6 @@ import shares from "./shares.json" import storages from "./storages.json" import tasks from "./tasks.json" import users from "./users.json" -import virtual_hosts from "./virtual_hosts.json" export const dict = { br, @@ -31,5 +30,4 @@ export const dict = { storages, tasks, users, - virtual_hosts, } diff --git a/src/lang/en/manage.json b/src/lang/en/manage.json index 226958751..5829c6ee7 100644 --- a/src/lang/en/manage.json +++ b/src/lang/en/manage.json @@ -11,7 +11,6 @@ "storages": "Storages", "shares": "Shares", "metas": "Metas", - "virtual_hosts": "Virtual Hosts", "profile": "Profile", "about": "About", "tasks": "Tasks", diff --git a/src/lang/en/shares.json b/src/lang/en/shares.json index 75d807d6e..08054ff9a 100644 --- a/src/lang/en/shares.json +++ b/src/lang/en/shares.json @@ -37,5 +37,9 @@ }, "input_password": "Please enter Share Code", "copy_msg": "Copy link", - "no_permission_tip": "To create a share, you need \"Share\" permission." + "no_permission_tip": "To create a share, you need \"Share\" permission.", + "domain": "Domain", + "domain_help": "The domain name to bind (e.g. blog.example.com); leave empty for a normal share link.", + "web_hosting": "Web Hosting", + "web_hosting_help": "If enabled, HTML files will be served directly via the bound domain instead of the file browser." } diff --git a/src/lang/en/virtual_hosts.json b/src/lang/en/virtual_hosts.json deleted file mode 100644 index 7e04017aa..000000000 --- a/src/lang/en/virtual_hosts.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "domain": "Domain", - "domain_help": "The domain name to bind (e.g. blog.example.com)", - "path": "Path", - "path_help": "The OpenList path to map this domain to", - "enabled": "Enabled", - "web_hosting": "Web Hosting", - "web_hosting_help": "If enabled, HTML files will be served directly instead of the file browser" -} diff --git a/src/pages/manage/routes.tsx b/src/pages/manage/routes.tsx index 9da937714..5fa444dfb 100644 --- a/src/pages/manage/routes.tsx +++ b/src/pages/manage/routes.tsx @@ -39,14 +39,6 @@ const hide_routes: Route[] = [ to: "/metas/edit/:id", component: lazy(() => import("./metas/AddOrEdit")), }, - { - to: "/virtual_hosts/add", - component: lazy(() => import("./virtual_hosts/AddOrEdit")), - }, - { - to: "/virtual_hosts/edit/:id", - component: lazy(() => import("./virtual_hosts/AddOrEdit")), - }, { to: "/2fa", component: lazy(() => import("./users/2fa")), diff --git a/src/pages/manage/shares/AddOrEdit.tsx b/src/pages/manage/shares/AddOrEdit.tsx index 0deffb106..96c3b0e62 100644 --- a/src/pages/manage/shares/AddOrEdit.tsx +++ b/src/pages/manage/shares/AddOrEdit.tsx @@ -170,6 +170,25 @@ const AddOrEdit = () => { setShare("header", h) }} /> + { + setShare("domain", d) + }} + /> + { + setShare("web_hosting", w) + }} + /> - - - ) -} - -export default AddOrEdit diff --git a/src/pages/manage/virtual_hosts/VirtualHosts.tsx b/src/pages/manage/virtual_hosts/VirtualHosts.tsx deleted file mode 100644 index 80dc39015..000000000 --- a/src/pages/manage/virtual_hosts/VirtualHosts.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { - Box, - Button, - HStack, - Table, - Tbody, - Td, - Th, - Thead, - Tr, - VStack, -} from "@hope-ui/solid" -import { createSignal, For } from "solid-js" -import { - useFetch, - useListFetch, - useManageTitle, - useRouter, - useT, -} from "~/hooks" -import { handleResp, notify, r } from "~/utils" -import { VirtualHost, PEmptyResp, PPageResp } from "~/types" -import { DeletePopover } from "../common/DeletePopover" -import { Wether } from "~/components" - -const VirtualHosts = () => { - const t = useT() - useManageTitle("manage.sidemenu.virtual_hosts") - const { to } = useRouter() - const [getVhostsLoading, getVhosts] = useFetch( - (): PPageResp => r.get("/admin/vhost/list"), - ) - const [vhosts, setVhosts] = createSignal([]) - const refresh = async () => { - const resp = await getVhosts() - handleResp(resp, (data) => setVhosts(data.content)) - } - refresh() - - const [deleting, deleteVhost] = useListFetch( - (id: number): PEmptyResp => r.post(`/admin/vhost/delete?id=${id}`), - ) - return ( - - - - - - - - - - - {(title) => } - - - - - - - {(vhost) => ( - - - - - - - - )} - - -
{t(`virtual_hosts.${title}`)}{t("global.operations")}
{vhost.domain}{vhost.path} - - - - - - - { - const resp = await deleteVhost(vhost.id) - handleResp(resp, () => { - notify.success(t("global.delete_success")) - refresh() - }) - }} - /> - -
-
-
- ) -} - -export default VirtualHosts diff --git a/src/types/index.ts b/src/types/index.ts index 8241449c1..52f45e97b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -8,4 +8,3 @@ export * from "./item_type" export * from "./meta" export * from "./task" export * from "./share" -export * from "./virtual_host" diff --git a/src/types/share.ts b/src/types/share.ts index 8871d385e..995fa6ffe 100644 --- a/src/types/share.ts +++ b/src/types/share.ts @@ -12,6 +12,8 @@ export interface Share { remark: string readme: string header: string + domain?: string + web_hosting?: boolean } export interface ShareUpdate extends Share { diff --git a/src/types/virtual_host.ts b/src/types/virtual_host.ts deleted file mode 100644 index 5114e5639..000000000 --- a/src/types/virtual_host.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface VirtualHost { - id: number - enabled: boolean - domain: string - path: string - web_hosting: boolean -}