添加vite

This commit is contained in:
qaq
2025-06-27 13:45:18 +08:00
parent a5d7be8405
commit 2789fc8f5e
26 changed files with 31482 additions and 2 deletions
+2
View File
@@ -45,6 +45,8 @@ $RECYCLE.BIN/
# IntelliJ IDEA
.idea/
.vitepress/dist/
.vitepress/cache/
*.iws
*.iml
*.ipr
+1 -1
View File
@@ -11,7 +11,7 @@
- 可针对 **指定用户的指定隧道进行限速** 设置
- 支持配置 **单向或双向流量计费方式**,灵活适配不同计费模型
- 提供灵活的转发策略配置,适用于多种网络代理场景
- 内置轻量级 Agent 端 API 服务,默认强制启用自签发 SSL,仅响应已认证请求,静默运行、安全可控
---
# 流量统计算法
+275
View File
@@ -0,0 +1,275 @@
import {
useMediaQuery
} from "./chunk-ECKPOFXB.js";
import {
computed,
ref,
shallowRef,
watch
} from "./chunk-W6V53FDX.js";
// node_modules/vitepress/dist/client/theme-default/index.js
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/fonts.css";
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/vars.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/base.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/icons.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/utils.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css";
import "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css";
import VPBadge from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
import Layout from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/Layout.vue";
import { default as default2 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
import { default as default3 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPButton.vue";
import { default as default4 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue";
import { default as default5 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPFeatures.vue";
import { default as default6 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPHomeContent.vue";
import { default as default7 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue";
import { default as default8 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue";
import { default as default9 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue";
import { default as default10 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPImage.vue";
import { default as default11 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPLink.vue";
import { default as default12 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPNavBarSearch.vue";
import { default as default13 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPSocialLink.vue";
import { default as default14 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPSocialLinks.vue";
import { default as default15 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPSponsors.vue";
import { default as default16 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue";
import { default as default17 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue";
import { default as default18 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue";
import { default as default19 } from "/Users/helei/Downloads/gost/vitepress/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue";
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
import { onContentUpdated } from "vitepress";
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
import { getScrollOffset } from "vitepress";
// node_modules/vitepress/dist/client/theme-default/support/utils.js
import { withBase } from "vitepress";
// node_modules/vitepress/dist/client/theme-default/composables/data.js
import { useData as useData$ } from "vitepress";
var useData = useData$;
// node_modules/vitepress/dist/client/theme-default/support/utils.js
function ensureStartingSlash(path) {
return path.startsWith("/") ? path : `/${path}`;
}
// node_modules/vitepress/dist/client/theme-default/support/sidebar.js
function getSidebar(_sidebar, path) {
if (Array.isArray(_sidebar))
return addBase(_sidebar);
if (_sidebar == null)
return [];
path = ensureStartingSlash(path);
const dir = Object.keys(_sidebar).sort((a, b) => {
return b.split("/").length - a.split("/").length;
}).find((dir2) => {
return path.startsWith(ensureStartingSlash(dir2));
});
const sidebar = dir ? _sidebar[dir] : [];
return Array.isArray(sidebar) ? addBase(sidebar) : addBase(sidebar.items, sidebar.base);
}
function getSidebarGroups(sidebar) {
const groups = [];
let lastGroupIndex = 0;
for (const index in sidebar) {
const item = sidebar[index];
if (item.items) {
lastGroupIndex = groups.push(item);
continue;
}
if (!groups[lastGroupIndex]) {
groups.push({ items: [] });
}
groups[lastGroupIndex].items.push(item);
}
return groups;
}
function addBase(items, _base) {
return [...items].map((_item) => {
const item = { ..._item };
const base = item.base || _base;
if (base && item.link)
item.link = base + item.link;
if (item.items)
item.items = addBase(item.items, base);
return item;
});
}
// node_modules/vitepress/dist/client/theme-default/composables/sidebar.js
function useSidebar() {
const { frontmatter, page, theme: theme2 } = useData();
const is960 = useMediaQuery("(min-width: 960px)");
const isOpen = ref(false);
const _sidebar = computed(() => {
const sidebarConfig = theme2.value.sidebar;
const relativePath = page.value.relativePath;
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [];
});
const sidebar = ref(_sidebar.value);
watch(_sidebar, (next, prev) => {
if (JSON.stringify(next) !== JSON.stringify(prev))
sidebar.value = _sidebar.value;
});
const hasSidebar = computed(() => {
return frontmatter.value.sidebar !== false && sidebar.value.length > 0 && frontmatter.value.layout !== "home";
});
const leftAside = computed(() => {
if (hasAside)
return frontmatter.value.aside == null ? theme2.value.aside === "left" : frontmatter.value.aside === "left";
return false;
});
const hasAside = computed(() => {
if (frontmatter.value.layout === "home")
return false;
if (frontmatter.value.aside != null)
return !!frontmatter.value.aside;
return theme2.value.aside !== false;
});
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value);
const sidebarGroups = computed(() => {
return hasSidebar.value ? getSidebarGroups(sidebar.value) : [];
});
function open() {
isOpen.value = true;
}
function close() {
isOpen.value = false;
}
function toggle() {
isOpen.value ? close() : open();
}
return {
isOpen,
sidebar,
sidebarGroups,
hasSidebar,
hasAside,
leftAside,
isSidebarEnabled,
open,
close,
toggle
};
}
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
var ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/;
var resolvedHeaders = [];
function getHeaders(range) {
const headers = [
...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")
].filter((el) => el.id && el.hasChildNodes()).map((el) => {
const level = Number(el.tagName[1]);
return {
element: el,
title: serializeHeader(el),
link: "#" + el.id,
level
};
});
return resolveHeaders(headers, range);
}
function serializeHeader(h) {
let ret = "";
for (const node of h.childNodes) {
if (node.nodeType === 1) {
if (ignoreRE.test(node.className))
continue;
ret += node.textContent;
} else if (node.nodeType === 3) {
ret += node.textContent;
}
}
return ret.trim();
}
function resolveHeaders(headers, range) {
if (range === false) {
return [];
}
const levelsRange = (typeof range === "object" && !Array.isArray(range) ? range.level : range) || 2;
const [high, low] = typeof levelsRange === "number" ? [levelsRange, levelsRange] : levelsRange === "deep" ? [2, 6] : levelsRange;
return buildTree(headers, high, low);
}
function buildTree(data, min, max) {
resolvedHeaders.length = 0;
const result = [];
const stack = [];
data.forEach((item) => {
const node = { ...item, children: [] };
let parent = stack[stack.length - 1];
while (parent && parent.level >= node.level) {
stack.pop();
parent = stack[stack.length - 1];
}
if (node.element.classList.contains("ignore-header") || parent && "shouldIgnore" in parent) {
stack.push({ level: node.level, shouldIgnore: true });
return;
}
if (node.level > max || node.level < min)
return;
resolvedHeaders.push({ element: node.element, link: node.link });
if (parent)
parent.children.push(node);
else
result.push(node);
stack.push(node);
});
return result;
}
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
function useLocalNav() {
const { theme: theme2, frontmatter } = useData();
const headers = shallowRef([]);
const hasLocalNav = computed(() => {
return headers.value.length > 0;
});
onContentUpdated(() => {
headers.value = getHeaders(frontmatter.value.outline ?? theme2.value.outline);
});
return {
headers,
hasLocalNav
};
}
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
var theme = {
Layout,
enhanceApp: ({ app }) => {
app.component("Badge", VPBadge);
}
};
var without_fonts_default = theme;
export {
default2 as VPBadge,
default3 as VPButton,
default4 as VPDocAsideSponsors,
default5 as VPFeatures,
default6 as VPHomeContent,
default7 as VPHomeFeatures,
default8 as VPHomeHero,
default9 as VPHomeSponsors,
default10 as VPImage,
default11 as VPLink,
default12 as VPNavBarSearch,
default13 as VPSocialLink,
default14 as VPSocialLinks,
default15 as VPSponsors,
default16 as VPTeamMembers,
default17 as VPTeamPage,
default18 as VPTeamPageSection,
default19 as VPTeamPageTitle,
without_fonts_default as default,
useLocalNav,
useSidebar
};
//# sourceMappingURL=@theme_index.js.map
File diff suppressed because one or more lines are too long
+40
View File
@@ -0,0 +1,40 @@
{
"hash": "653f3fb1",
"configHash": "78039c44",
"lockfileHash": "c333c031",
"browserHash": "3b2d3674",
"optimized": {
"vue": {
"src": "../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js",
"fileHash": "16700907",
"needsInterop": false
},
"vitepress > @vue/devtools-api": {
"src": "../../../node_modules/@vue/devtools-api/dist/index.js",
"file": "vitepress___@vue_devtools-api.js",
"fileHash": "32515e01",
"needsInterop": false
},
"vitepress > @vueuse/core": {
"src": "../../../node_modules/@vueuse/core/index.mjs",
"file": "vitepress___@vueuse_core.js",
"fileHash": "8f71fbc0",
"needsInterop": false
},
"@theme/index": {
"src": "../../../node_modules/vitepress/dist/client/theme-default/index.js",
"file": "@theme_index.js",
"fileHash": "7e2c2dcf",
"needsInterop": false
}
},
"chunks": {
"chunk-ECKPOFXB": {
"file": "chunk-ECKPOFXB.js"
},
"chunk-W6V53FDX": {
"file": "chunk-W6V53FDX.js"
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,583 @@
import {
DefaultMagicKeysAliasMap,
StorageSerializers,
TransitionPresets,
assert,
breakpointsAntDesign,
breakpointsBootstrapV5,
breakpointsElement,
breakpointsMasterCss,
breakpointsPrimeFlex,
breakpointsQuasar,
breakpointsSematic,
breakpointsTailwind,
breakpointsVuetify,
breakpointsVuetifyV2,
breakpointsVuetifyV3,
bypassFilter,
camelize,
clamp,
cloneFnJSON,
computedAsync,
computedEager,
computedInject,
computedWithControl,
containsProp,
controlledRef,
createEventHook,
createFetch,
createFilterWrapper,
createGlobalState,
createInjectionState,
createRef,
createReusableTemplate,
createSharedComposable,
createSingletonPromise,
createTemplatePromise,
createUnrefFn,
customStorageEventName,
debounceFilter,
defaultDocument,
defaultLocation,
defaultNavigator,
defaultWindow,
executeTransition,
extendRef,
formatDate,
formatTimeAgo,
get,
getLifeCycleTarget,
getSSRHandler,
hasOwn,
hyphenate,
identity,
increaseWithUnit,
injectLocal,
invoke,
isClient,
isDef,
isDefined,
isIOS,
isObject,
isWorker,
makeDestructurable,
mapGamepadToXbox360Controller,
noop,
normalizeDate,
notNullish,
now,
objectEntries,
objectOmit,
objectPick,
onClickOutside,
onElementRemoval,
onKeyDown,
onKeyPressed,
onKeyStroke,
onKeyUp,
onLongPress,
onStartTyping,
pausableFilter,
promiseTimeout,
provideLocal,
provideSSRWidth,
pxValue,
rand,
reactify,
reactifyObject,
reactiveComputed,
reactiveOmit,
reactivePick,
refAutoReset,
refDebounced,
refDefault,
refThrottled,
refWithControl,
resolveRef,
resolveUnref,
set,
setSSRHandler,
syncRef,
syncRefs,
templateRef,
throttleFilter,
timestamp,
toArray,
toReactive,
toRef,
toRefs,
toValue,
tryOnBeforeMount,
tryOnBeforeUnmount,
tryOnMounted,
tryOnScopeDispose,
tryOnUnmounted,
unrefElement,
until,
useActiveElement,
useAnimate,
useArrayDifference,
useArrayEvery,
useArrayFilter,
useArrayFind,
useArrayFindIndex,
useArrayFindLast,
useArrayIncludes,
useArrayJoin,
useArrayMap,
useArrayReduce,
useArraySome,
useArrayUnique,
useAsyncQueue,
useAsyncState,
useBase64,
useBattery,
useBluetooth,
useBreakpoints,
useBroadcastChannel,
useBrowserLocation,
useCached,
useClipboard,
useClipboardItems,
useCloned,
useColorMode,
useConfirmDialog,
useCountdown,
useCounter,
useCssVar,
useCurrentElement,
useCycleList,
useDark,
useDateFormat,
useDebounceFn,
useDebouncedRefHistory,
useDeviceMotion,
useDeviceOrientation,
useDevicePixelRatio,
useDevicesList,
useDisplayMedia,
useDocumentVisibility,
useDraggable,
useDropZone,
useElementBounding,
useElementByPoint,
useElementHover,
useElementSize,
useElementVisibility,
useEventBus,
useEventListener,
useEventSource,
useEyeDropper,
useFavicon,
useFetch,
useFileDialog,
useFileSystemAccess,
useFocus,
useFocusWithin,
useFps,
useFullscreen,
useGamepad,
useGeolocation,
useIdle,
useImage,
useInfiniteScroll,
useIntersectionObserver,
useInterval,
useIntervalFn,
useKeyModifier,
useLastChanged,
useLocalStorage,
useMagicKeys,
useManualRefHistory,
useMediaControls,
useMediaQuery,
useMemoize,
useMemory,
useMounted,
useMouse,
useMouseInElement,
useMousePressed,
useMutationObserver,
useNavigatorLanguage,
useNetwork,
useNow,
useObjectUrl,
useOffsetPagination,
useOnline,
usePageLeave,
useParallax,
useParentElement,
usePerformanceObserver,
usePermission,
usePointer,
usePointerLock,
usePointerSwipe,
usePreferredColorScheme,
usePreferredContrast,
usePreferredDark,
usePreferredLanguages,
usePreferredReducedMotion,
usePreferredReducedTransparency,
usePrevious,
useRafFn,
useRefHistory,
useResizeObserver,
useSSRWidth,
useScreenOrientation,
useScreenSafeArea,
useScriptTag,
useScroll,
useScrollLock,
useSessionStorage,
useShare,
useSorted,
useSpeechRecognition,
useSpeechSynthesis,
useStepper,
useStorage,
useStorageAsync,
useStyleTag,
useSupported,
useSwipe,
useTemplateRefsList,
useTextDirection,
useTextSelection,
useTextareaAutosize,
useThrottleFn,
useThrottledRefHistory,
useTimeAgo,
useTimeout,
useTimeoutFn,
useTimeoutPoll,
useTimestamp,
useTitle,
useToNumber,
useToString,
useToggle,
useTransition,
useUrlSearchParams,
useUserMedia,
useVModel,
useVModels,
useVibrate,
useVirtualList,
useWakeLock,
useWebNotification,
useWebSocket,
useWebWorker,
useWebWorkerFn,
useWindowFocus,
useWindowScroll,
useWindowSize,
watchArray,
watchAtMost,
watchDebounced,
watchDeep,
watchIgnorable,
watchImmediate,
watchOnce,
watchPausable,
watchThrottled,
watchTriggerable,
watchWithFilter,
whenever
} from "./chunk-ECKPOFXB.js";
import "./chunk-W6V53FDX.js";
export {
DefaultMagicKeysAliasMap,
StorageSerializers,
TransitionPresets,
assert,
computedAsync as asyncComputed,
refAutoReset as autoResetRef,
breakpointsAntDesign,
breakpointsBootstrapV5,
breakpointsElement,
breakpointsMasterCss,
breakpointsPrimeFlex,
breakpointsQuasar,
breakpointsSematic,
breakpointsTailwind,
breakpointsVuetify,
breakpointsVuetifyV2,
breakpointsVuetifyV3,
bypassFilter,
camelize,
clamp,
cloneFnJSON,
computedAsync,
computedEager,
computedInject,
computedWithControl,
containsProp,
computedWithControl as controlledComputed,
controlledRef,
createEventHook,
createFetch,
createFilterWrapper,
createGlobalState,
createInjectionState,
reactify as createReactiveFn,
createRef,
createReusableTemplate,
createSharedComposable,
createSingletonPromise,
createTemplatePromise,
createUnrefFn,
customStorageEventName,
debounceFilter,
refDebounced as debouncedRef,
watchDebounced as debouncedWatch,
defaultDocument,
defaultLocation,
defaultNavigator,
defaultWindow,
computedEager as eagerComputed,
executeTransition,
extendRef,
formatDate,
formatTimeAgo,
get,
getLifeCycleTarget,
getSSRHandler,
hasOwn,
hyphenate,
identity,
watchIgnorable as ignorableWatch,
increaseWithUnit,
injectLocal,
invoke,
isClient,
isDef,
isDefined,
isIOS,
isObject,
isWorker,
makeDestructurable,
mapGamepadToXbox360Controller,
noop,
normalizeDate,
notNullish,
now,
objectEntries,
objectOmit,
objectPick,
onClickOutside,
onElementRemoval,
onKeyDown,
onKeyPressed,
onKeyStroke,
onKeyUp,
onLongPress,
onStartTyping,
pausableFilter,
watchPausable as pausableWatch,
promiseTimeout,
provideLocal,
provideSSRWidth,
pxValue,
rand,
reactify,
reactifyObject,
reactiveComputed,
reactiveOmit,
reactivePick,
refAutoReset,
refDebounced,
refDefault,
refThrottled,
refWithControl,
resolveRef,
resolveUnref,
set,
setSSRHandler,
syncRef,
syncRefs,
templateRef,
throttleFilter,
refThrottled as throttledRef,
watchThrottled as throttledWatch,
timestamp,
toArray,
toReactive,
toRef,
toRefs,
toValue,
tryOnBeforeMount,
tryOnBeforeUnmount,
tryOnMounted,
tryOnScopeDispose,
tryOnUnmounted,
unrefElement,
until,
useActiveElement,
useAnimate,
useArrayDifference,
useArrayEvery,
useArrayFilter,
useArrayFind,
useArrayFindIndex,
useArrayFindLast,
useArrayIncludes,
useArrayJoin,
useArrayMap,
useArrayReduce,
useArraySome,
useArrayUnique,
useAsyncQueue,
useAsyncState,
useBase64,
useBattery,
useBluetooth,
useBreakpoints,
useBroadcastChannel,
useBrowserLocation,
useCached,
useClipboard,
useClipboardItems,
useCloned,
useColorMode,
useConfirmDialog,
useCountdown,
useCounter,
useCssVar,
useCurrentElement,
useCycleList,
useDark,
useDateFormat,
refDebounced as useDebounce,
useDebounceFn,
useDebouncedRefHistory,
useDeviceMotion,
useDeviceOrientation,
useDevicePixelRatio,
useDevicesList,
useDisplayMedia,
useDocumentVisibility,
useDraggable,
useDropZone,
useElementBounding,
useElementByPoint,
useElementHover,
useElementSize,
useElementVisibility,
useEventBus,
useEventListener,
useEventSource,
useEyeDropper,
useFavicon,
useFetch,
useFileDialog,
useFileSystemAccess,
useFocus,
useFocusWithin,
useFps,
useFullscreen,
useGamepad,
useGeolocation,
useIdle,
useImage,
useInfiniteScroll,
useIntersectionObserver,
useInterval,
useIntervalFn,
useKeyModifier,
useLastChanged,
useLocalStorage,
useMagicKeys,
useManualRefHistory,
useMediaControls,
useMediaQuery,
useMemoize,
useMemory,
useMounted,
useMouse,
useMouseInElement,
useMousePressed,
useMutationObserver,
useNavigatorLanguage,
useNetwork,
useNow,
useObjectUrl,
useOffsetPagination,
useOnline,
usePageLeave,
useParallax,
useParentElement,
usePerformanceObserver,
usePermission,
usePointer,
usePointerLock,
usePointerSwipe,
usePreferredColorScheme,
usePreferredContrast,
usePreferredDark,
usePreferredLanguages,
usePreferredReducedMotion,
usePreferredReducedTransparency,
usePrevious,
useRafFn,
useRefHistory,
useResizeObserver,
useSSRWidth,
useScreenOrientation,
useScreenSafeArea,
useScriptTag,
useScroll,
useScrollLock,
useSessionStorage,
useShare,
useSorted,
useSpeechRecognition,
useSpeechSynthesis,
useStepper,
useStorage,
useStorageAsync,
useStyleTag,
useSupported,
useSwipe,
useTemplateRefsList,
useTextDirection,
useTextSelection,
useTextareaAutosize,
refThrottled as useThrottle,
useThrottleFn,
useThrottledRefHistory,
useTimeAgo,
useTimeout,
useTimeoutFn,
useTimeoutPoll,
useTimestamp,
useTitle,
useToNumber,
useToString,
useToggle,
useTransition,
useUrlSearchParams,
useUserMedia,
useVModel,
useVModels,
useVibrate,
useVirtualList,
useWakeLock,
useWebNotification,
useWebSocket,
useWebWorker,
useWebWorkerFn,
useWindowFocus,
useWindowScroll,
useWindowSize,
watchArray,
watchAtMost,
watchDebounced,
watchDeep,
watchIgnorable,
watchImmediate,
watchOnce,
watchPausable,
watchThrottled,
watchTriggerable,
watchWithFilter,
whenever
};
//# sourceMappingURL=vitepress___@vueuse_core.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
+343
View File
@@ -0,0 +1,343 @@
import {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBaseVNode,
createBlock,
createCommentVNode,
createElementBlock,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId
} from "./chunk-W6V53FDX.js";
export {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBlock,
createCommentVNode,
createElementBlock,
createBaseVNode as createElementVNode,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId
};
//# sourceMappingURL=vue.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
+20
View File
@@ -0,0 +1,20 @@
import { defineConfig } from 'vitepress'
export default defineConfig({
title: '哆啦A梦',
description: '基于gost的转发面板',
themeConfig: {
nav: [
{ text: '首页', link: '/' },
{ text: '快速开始', link: '/getting-started' },
{ text: '使用指南', link: '/guide' },
{ text: '项目结构', link: '/project-structure' },
{ text: '常见问题', link: '/faq' }
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/bqlpfy/forward-panel' }
]
}
})
+63
View File
@@ -0,0 +1,63 @@
# 常见问题
## 日志查看
### 查看后端服务日志
当后端服务出现问题时,可以通过以下命令查看实时日志:
```bash
docker logs -f springboot-backend
```
**说明**:
- `docker logs` - 查看Docker容器日志
- `-f` - 持续跟踪日志输出(类似tail -f)
- `springboot-backend` - 后端服务容器名称
**使用场景**:
- API 接口报错
- 用户登录问题
- 数据库连接异常
- 隧道/转发创建失败
### 查看转发引擎日志
当转发功能出现问题时,可以通过以下命令查看gost服务日志:
```bash
journalctl -u gost -f
```
**说明**:
- `journalctl` - 系统日志查看工具
- `-u gost` - 指定查看gost服务的日志
- `-f` - 持续跟踪日志输出
**使用场景**:
- 转发连接失败
- 流量统计异常
- 节点连接问题
- 限速功能故障
## 日志分析技巧
### 常用日志筛选
```bash
# 查看最近100行日志
docker logs --tail 100 springboot-backend
# 查看指定时间段的日志
journalctl -u gost --since "2024-01-01" --until "2024-01-02"
# 搜索包含ERROR的日志
docker logs springboot-backend | grep ERROR
```
### 日志等级说明
- **ERROR** - 错误信息,需要立即处理
- **WARN** - 警告信息,建议关注
- **INFO** - 一般信息,正常运行状态
- **DEBUG** - 调试信息,详细执行过程
+203
View File
@@ -0,0 +1,203 @@
# 快速开始
本指南将帮助您快速安装和配置哆啦A梦,让您在几分钟内开始使用流量转发功能。
## 系统要求
在开始之前,请确保您的系统满足以下要求:
- **操作系统**: Linux (推荐 Ubuntu 18.04+, CentOS 7+) 或 macOS,**推荐纯净系统安装**
- **Docker**: 20.10+
- **Docker Compose**: 1.29+ 或 Docker 内置 compose 命令
- **内存**: 至少 1GB RAM
- **存储**: 至少 1GB 可用空间
- **网络**: 确保相关端口未被占用
## 一键安装(推荐)
我们提供了交互式安装脚本,会自动检测系统环境并引导您完成配置:
```bash
curl -L https://github.com/bqlpfy/forward-panel/raw/refs/heads/main/panel_install.sh -o panel_install.sh && chmod +x panel_install.sh && ./panel_install.sh
```
### 安装流程说明
1. **运行脚本后选择操作**:
```
===============================================
面板管理脚本
===============================================
请选择操作:
1. 安装面板 ← 选择这个
2. 更新面板
3. 卸载面板
4. 退出
===============================================
```
2. **输入配置参数**:
- **面板服务器地址**: 需要节点服务器能正常访问的地址
- **前端端口**: 默认 6366
- **后端端口**: 默认 6365
3. **自动化处理**:
- 检测 Docker 环境
- 自动检测 IPv6 支持并选择合适的配置
- 生成随机的数据库配置
- 下载并启动服务
### 配置示例
```bash
当前面板服务器地址: 192.168.1.100 # 或您的公网IP
前端端口(默认 6366): 6366 # 直接回车使用默认值
后端端口(默认 6365): 6365 # 直接回车使用默认值
```
## 手动安装
如果需要更多控制,可以手动执行以下步骤:
### 1. 下载项目文件
```bash
# 下载 docker-compose 配置(IPv4)
curl -L -o docker-compose.yml https://github.com/bqlpfy/forward-panel/raw/refs/heads/main/docker-compose-v4.yml
# 或下载 IPv6 配置
curl -L -o docker-compose.yml https://github.com/bqlpfy/forward-panel/raw/refs/heads/main/docker-compose-v6.yml
# 下载数据库初始化文件
curl -L -o gost.sql https://github.com/bqlpfy/forward-panel/raw/refs/heads/main/gost.sql
```
### 2. 创建环境配置
创建 `.env` 文件并设置配置参数:
```bash
cat > .env <<EOF
DB_NAME=your_random_db_name
DB_USER=your_random_user
DB_PASSWORD=your_random_password
JWT_SECRET=your_random_jwt_secret
SERVER_HOST=192.168.1.100:6365
FRONTEND_PORT=6366
BACKEND_PORT=6365
EOF
```
### 3. 启动服务
```bash
# 检查 Docker 命令
if command -v docker-compose &> /dev/null; then
docker-compose up -d
else
docker compose up -d
fi
```
## 验证安装
### 1. 检查服务状态
```bash
# 使用 docker-compose
docker-compose ps
# 或使用 docker compose
docker compose ps
```
您应该看到以下服务都处于 `Up` 状态:
- `gost-mysql` - 数据库服务
- `springboot-backend` - 后端 API 服务
- `vue-frontend` - 前端 Web 界面
### 2. 访问 Web 界面
打开浏览器访问:`http://your-server-ip:6366`
### 3. 登录系统
使用默认管理员账号登录:
- **用户名**: `admin_user`
- **密码**: `admin_user`
⚠️ **重要**: 首次登录后请立即修改默认密码!
## IPv6 支持
脚本会自动检测系统的 IPv6 支持:
- ✅ **支持 IPv6**: 自动使用 IPv6 配置文件并配置 Docker IPv6 支持
- ⚠️ **不支持 IPv6**: 使用 IPv4 配置文件
### Docker IPv6 配置
如果检测到 IPv6 支持,脚本会自动配置:
```json
{
"ipv6": true,
"fixed-cidr-v6": "fd00::/80"
}
```
## 端口说明
| 端口 | 服务 | 说明 | 可配置 |
|------|------|------|--------|
| 6366 | Web 界面 | 前端管理界面 | ✅ |
| 6365 | API 服务 | 后端 REST API | ✅ |
| 3306 | MySQL | 数据库服务(容器内部) | ❌ |
| 动态分配 | 转发端口 | 用户创建的转发规则 | ✅ |
## 面板管理
安装脚本提供了完整的生命周期管理:
### 更新面板
```bash
./panel_install.sh
# 选择 "2. 更新面板"
```
更新功能包括:
- 下载最新配置文件
- 拉取最新镜像
- 自动执行数据库结构更新
- 保留现有配置和数据
### 卸载面板
```bash
./panel_install.sh
# 选择 "3. 卸载面板"
```
⚠️ **警告**: 卸载会删除所有数据,请提前备份重要信息!
## 获取帮助
如果在安装过程中遇到问题:
1. 🔍 查看安装日志和错误信息
2. 📋 检查系统要求是否满足
3. 🐛 提交 [GitHub Issues](https://github.com/bqlpfy/forward-panel/issues)
4. 💬 参与社区讨论
## 备份建议
安装完成后,建议定期备份:
```bash
# 备份数据库
docker exec gost-mysql mysqldump -u $DB_USER -p$DB_PASSWORD $DB_NAME > backup_$(date +%Y%m%d).sql
# 备份配置文件
tar czf panel_backup_$(date +%Y%m%d).tar.gz .env docker-compose.yml
```
+295
View File
@@ -0,0 +1,295 @@
# 使用指南
哆啦A梦是一个基于 go-gost 的现代化转发面板,提供了直观的 Web 界面来管理网络流量转发。
## 项目介绍
### 核心功能
- 🔄 **TCP/UDP/TLS 端口转发**: 支持多种协议的流量转发
- 👥 **用户管理**: 按账号级别管理流量转发数量和流量限额
- 📊 **流量统计**: 支持双向/单向计费模式,实时监控
- ⚡ **限速控制**: 可创建限速规则进行精细化流量控制
- 🖥️ **节点管理**: 分布式节点部署和监控
- 🚇 **隧道管理**: 灵活的隧道配置和管理
- 🔒 **安全可控**: 内置认证系统,权限分级管理
### 技术架构
- **前端**: Vue.js 2 + Element UI
- **后端**: Spring Boot + MySQL
- **转发引擎**: go-gost
- **部署方式**: Docker Compose
## 第一步:登录系统
安装完成后,打开浏览器访问面板地址:
```
http://your-server-ip:6366
```
使用默认管理员账号登录:
- **用户名**: `admin_user`
- **密码**: `admin_user`
## 第二步:修改默认密码
登录后**务必立即修改默认密码**:
1. 点击右上角用户头像
2. 选择 **"修改密码"**
3. 输入当前密码:`admin_user`
4. 设置新密码并确认
5. 点击确定完成修改
## 第三步:创建节点
节点是运行转发服务的服务器,需要先创建节点才能部署转发服务。
### 添加节点
1. 在左侧菜单点击 **"节点管理"**
2. 点击 **"新增节点"** 按钮
3. 填写节点信息:
- **节点名称**: 自定义名称(如:香港节点-01)
- **服务器IP**: 节点服务器的IP地址
- **状态**: 启用
4. 点击 **"确定"** 保存节点
### IP地址说明
**服务器IP**:
- 用于创建隧道转发时入口-出口两台服务器之间的通信地址
- 通常是服务器的主要通信IP
- 确保入口和出口节点能够通过此IP互相访问
**入口IP**:
- 用于展示在转发页面,面向用户的访问地址
- 适用于有多个IP的服务器(如多线BGP)
### 节点状态说明
- 🟢 **在线**: 节点正常运行,可以查看CPU、内存等系统信息
- 🔴 **离线**: 节点未连接或agent未安装
## 第四步:安装节点Agent
创建节点后,需要在对应的服务器上安装agent程序。
### 获取安装命令
1. 在节点列表中找到刚创建的节点
2. 点击节点卡片中的 **"复制安装命令"** 按钮
3. 系统会自动复制安装命令到剪贴板
### 执行安装
在目标服务器上执行复制的安装命令:
```bash
# 示例安装命令(实际命令请从面板复制)
curl -L https://your-panel-server:6365/agent/install | bash -s -- --server=your-panel-server:6365 --token=your-node-token
```
### 验证安装
安装完成后,回到面板查看节点状态:
- 节点状态应该变为 🟢 **在线**
- 可以看到CPU使用率、内存使用率等系统信息
## 第五步:创建隧道
隧道定义了流量的入口和出口节点。
### 添加隧道
1. 在左侧菜单点击 **"隧道管理"**
2. 点击 **"新增隧道"** 按钮
3. 配置隧道参数:
**基本信息**:
- **隧道名称**: 自定义名称(如:Web服务隧道)
- **隧道类型**:
- **端口转发**: 在单个节点上进行直接端口映射
- **隧道转发**: 在入口节点和出口节点之间建立隧道连接
- **流量计算**:
- 单向计算(仅上传):仅计算上传流量
- 双向计算:计算上传和下载的总流量
- **流量倍率**: 计费倍率(默认1.0,设置为2.0表示按实际流量的2倍计费,范围:0.0-100.0)
**入口配置**:
- **入口节点**: 选择流量入口节点
- **起始端口**: 端口范围起始值(默认1)
- **结束端口**: 端口范围结束值(默认65535)
- **监听地址**: 保持默认即可(TCP/UDP 都默认 0.0.0.0)
**出口配置**(仅隧道转发类型需要):
- **协议类型**: 保持默认即可,如有特殊需求可选择:
- TLS:数据过墙推荐选择
- TCP:普通场景
- **出口节点**: 选择流量出口节点
- **起始端口**: 出口端口范围起始值(默认1)
- **结束端口**: 出口端口范围结束值(默认65535)
4. 点击 **"创建"** 保存隧道
### 隧道流程图
创建后可以在隧道列表中看到流程图:
```
入口节点 → 出口节点 → 目标服务
```
## 第六步:创建转发
转发规则定义了具体的端口映射关系。
### 添加转发
1. 在左侧菜单点击 **"转发管理"**
2. 点击 **"新增转发"** 按钮
3. 配置转发参数:
**基本信息**:
- **转发名称**: 自定义名称(如:SSH转发)
- **选择隧道**: 选择已创建的隧道
**端口配置**:
- **入口端口**:
- **端口**: 手动指定端口号
- **留空自动分配**: 系统自动分配可用端口
- 建议:先选择隧道以查看端口范围,留空将自动分配可用端口
**目标配置**:
- **远程地址**: 最终目标服务地址,支持多种格式:
- IPv4:`192.168.1.100:8080`
- IPv6:`[2001:db8::1]:8080`
- 域名:`example.com:8080`
**示例配置**:
```
转发名称: SSH服务转发
选择隧道: Web服务隧道
入口端口: 留空自动分配(或手动指定如 2222)
远程地址: 192.168.1.100:22
```
4. 点击 **"确定"** 保存转发规则
## 第七步:用户管理(可选)
如果需要多用户使用,可以创建普通用户账号并分配资源。
### 创建用户
1. 在左侧菜单点击 **"用户管理"**
2. 点击 **"新增用户"** 按钮
3. 填写用户信息:
**基本信息**:
- **用户名**: 登录用户名(如:15284851274)
- **密码**: 登录密码(系统会自动加密显示)
**资源限制**:
- **流量(GB)**: 总流量限额,如需无限制可设置较大数值(如999999)
- **转发数量**: 可创建的转发数量,如需无限制可设置较大数值(如999999)
- **过期时间**: 账号有效期,可选择具体日期
- **流量重置**: 流量重置周期,默认"每月1号(0点重置)"
**账号状态**:
- **正常**: 用户可正常使用
- **禁用**: 暂停用户使用
**示例配置**:
```
用户名: user001
密码: ********
流量(GB): 100(或999999表示无限制)
转发数量: 10(或999999表示无限制)
过期时间: 2025-12-31
流量重置: 每月1号(0点重置)
状态: 正常
```
4. 点击 **"确定"** 创建用户
### 分配隧道权限
创建用户后,需要为用户分配具体的隧道使用权限:
1. 在用户列表中找到目标用户
2. 点击用户的 **"隧道权限管理"** 按钮
3. 在弹出窗口中配置权限:
**分配新隧道权限**:
- **选择隧道**: 选择要分配给用户的隧道
- **流量限制(GB)**: 该隧道的流量限额
- **转发数量**: 该隧道允许创建的转发数量
- **到期时间**: 该隧道权限的有效期
- **限速规则**: 选择是否应用限速(默认"不限速")
4. 点击 **"分配权限"** 保存配置
**权限管理**:
- 在"已有隧道权限"列表中可以查看用户的所有隧道权限
- 显示每个隧道的状态、流量统计、转发数量、限速规则、到期时间
- 可以编辑或删除现有权限
### 权限优先级说明
系统采用两级权限管理,优先级如下:
**用户级别权限(优先级最高)**:
- 用户的流量限额和转发数量限制影响该用户的所有转发
- 即使隧道权限设置更大的限额,也不能超过用户级别的总限制
- 例如:用户总流量100GB,即使单个隧道分配200GB,用户实际最多只能使用100GB
**隧道级别权限**:
- 隧道的流量和转发数量限制只影响对应的隧道
- 在用户总限额范围内,进一步细分到具体隧道的使用限制
- 例如:用户总流量100GB,可以分配给隧道A 60GB,隧道B 40GB
## 第八步:限速规则(可选)
如果需要对特定用户或隧道进行限速,需要先创建限速规则。
### 创建限速规则
1. 在左侧菜单点击 **"限速规则"**
2. 点击 **"新增限速"** 按钮
3. 配置限速参数:
**基本配置**:
- **规则名称**: 自定义限速规则名称(如:游戏隧道限速)
- **速度限制**: 设置带宽限制值
- 单位:Mbps(兆比特每秒)
- 范围:1-1000000 Mbps
- 例如:100 表示限制带宽为100Mbps
- **绑定隧道**: 选择要应用此限速规则的隧道
**示例配置**:
```
规则名称: 普通用户限速
速度限制: 100 Mbps
绑定隧道: Web服务隧道
```
4. 点击 **"确定"** 保存限速规则
## 获取帮助
如果在使用过程中遇到问题:
1. 📖 查看本文档的相关章节
2. 🔍 检查系统日志和错误信息
3. 🐛 提交 [GitHub Issues](https://github.com/bqlpfy/forward-panel/issues)
4. 💬 参与社区讨论
## 免责声明
本项目仅供个人学习与研究使用,基于开源项目进行二次开发。使用本项目所带来的任何风险由使用者自行承担。请确保在合法、合规、安全的前提下使用本项目。
+59
View File
@@ -0,0 +1,59 @@
---
layout: home
hero:
name: "哆啦A梦"
text: "基于gost的转发面板"
tagline: "功能强大的流量转发管理平台,支持灵活的流量计费和限速功能"
actions:
- theme: brand
text: 快速开始
link: /getting-started
- theme: alt
text: 查看源码
link: https://github.com/bqlpfy/forward-panel
features:
- icon: 🔄
title: 多协议支持
details: 支持 TCP 和 UDP 协议的转发,满足各种网络代理需求
- icon: 👥
title: 账号级别管理
details: 支持按隧道账号级别管理流量转发数量,可用于用户/隧道配额控制
- icon: 🚀
title: 双模式转发
details: 支持端口转发与隧道转发两种模式,灵活适配不同场景
- icon: ⚡
title: 精细化限速
details: 可针对指定用户的指定隧道进行限速设置,提供精准的流量控制
- icon: 💰
title: 灵活计费
details: 支持配置单向或双向流量计费方式,灵活适配不同计费模型
- icon: 🔒
title: 安全可控
details: 内置轻量级 Agent 端 API 服务,强制启用自签发 SSL,安全可控
- icon: 📊
title: 实时监控
details: 提供实时的流量统计和监控功能,让您随时掌握服务状态
- icon: 🐳
title: 容器化部署
details: 支持 Docker Compose 一键部署,简化安装和维护流程
---
## 社区支持
如果您在使用过程中遇到问题或有功能建议,欢迎:
- 🐛 [报告问题](https://github.com/bqlpfy/forward-panel/issues)
- 💡 [功能建议](https://github.com/bqlpfy/forward-panel/issues)
- 🤝 [参与贡献](https://github.com/bqlpfy/forward-panel/pulls)
## 免责声明
本项目仅供个人学习与研究使用,基于开源项目进行二次开发。使用本项目所带来的任何风险由使用者自行承担。请确保在合法、合规、安全的前提下使用本项目。
+2422
View File
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
{
"name": "doraemon-docs",
"version": "1.0.0",
"description": "哆啦A梦转发面板文档",
"type": "module",
"scripts": {
"dev": "vitepress dev",
"build": "vitepress build",
"preview": "vitepress preview"
},
"devDependencies": {
"vitepress": "^1.0.0-rc.4"
},
"keywords": [
"gost",
"proxy",
"forward",
"panel",
"documentation"
],
"author": "bqlpfy",
"license": "Apache-2.0"
}
+263
View File
@@ -0,0 +1,263 @@
# 项目结构
哆啦A梦是一个基于微服务架构的现代化网络转发面板,采用前后端分离设计,集成了多个核心组件。
## 总体架构
```
forward-panel/
├── 部署配置文件
├── 转发引擎 (go-gost)
├── 后端服务 (Spring Boot)
├── 前端界面 (Vue.js)
└── 文档站点 (VitePress)
```
## 完整目录结构
```
forward-panel/
├── docker-compose-v4.yml # IPv4 环境部署配置
├── docker-compose-v6.yml # IPv6 环境部署配置
├── gost.sql # MySQL 数据库初始化脚本
├── panel_install.sh # 一键安装部署脚本
├── README.md # 项目说明文档
│
├── go-gost/ # 转发引擎核心 (基于 go-gost)
│ ├── config.go # 主配置文件
│ ├── go.mod # Go 模块依赖管理
│ ├── go.sum # 依赖版本锁定
│ └── x/ # 扩展功能模块
│ ├── admission/ # 准入控制
│ │ ├── admission.go # 准入控制逻辑
│ │ └── plugin/ # 插件实现
│ ├── api/ # API 接口定义
│ │ ├── api.go # API 核心逻辑
│ │ ├── config_*.go # 各种配置 API
│ │ └── service/ # 服务层实现
│ ├── auth/ # 认证模块
│ ├── bypass/ # 绕行规则
│ ├── chain/ # 转发链管理
│ ├── config/ # 配置管理
│ │ ├── cmd/ # 命令行工具
│ │ ├── loader/ # 配置加载器
│ │ └── parsing/ # 配置解析器
│ ├── connector/ # 连接器实现
│ │ ├── direct/ # 直连模式
│ │ ├── http/ # HTTP 连接器
│ │ ├── socks/ # SOCKS 代理
│ │ ├── relay/ # 中继连接
│ │ └── ... # 其他连接器
│ ├── dialer/ # 拨号器实现
│ │ ├── direct/ # 直接拨号
│ │ ├── tcp/ # TCP 拨号器
│ │ ├── tls/ # TLS 拨号器
│ │ ├── ws/ # WebSocket 拨号器
│ │ └── ... # 其他拨号器
│ ├── handler/ # 处理器实现
│ │ ├── http/ # HTTP 处理器
│ │ ├── socks/ # SOCKS 处理器
│ │ ├── relay/ # 中继处理器
│ │ ├── tunnel/ # 隧道处理器
│ │ └── ... # 其他处理器
│ ├── listener/ # 监听器实现
│ │ ├── tcp/ # TCP 监听器
│ │ ├── tls/ # TLS 监听器
│ │ ├── ws/ # WebSocket 监听器
│ │ ├── quic/ # QUIC 监听器
│ │ └── ... # 其他监听器
│ ├── limiter/ # 限流控制
│ │ ├── conn/ # 连接限流
│ │ ├── rate/ # 速率限流
│ │ └── traffic/ # 流量限流
│ ├── metrics/ # 监控指标
│ ├── recorder/ # 记录器
│ ├── resolver/ # 域名解析
│ ├── router/ # 路由管理
│ └── ... # 其他核心模块
│
├── springboot-backend/ # Spring Boot 后端服务
│ ├── Dockerfile # 后端 Docker 镜像构建文件
│ ├── pom.xml # Maven 项目配置和依赖管理
│ ├── applog/ # 应用日志目录
│ ├── src/ # 源代码目录
│ │ ├── main/ # 主要源码
│ │ │ ├── java/ # Java 源码
│ │ │ │ └── com/ # 包结构
│ │ │ │ └── panel/ # 项目主包
│ │ │ │ ├── controller/ # 控制层 (API 接口)
│ │ │ │ ├── service/ # 服务层 (业务逻辑)
│ │ │ │ ├── mapper/ # 数据访问层 (MyBatis)
│ │ │ │ ├── entity/ # 实体类 (数据模型)
│ │ │ │ ├── config/ # 配置类
│ │ │ │ └── util/ # 工具类
│ │ │ └── resources/ # 资源文件
│ │ │ ├── application.yml # 应用配置
│ │ │ ├── mapper/ # MyBatis 映射文件
│ │ │ └── static/ # 静态资源
│ │ └── test/ # 测试代码
│ │ └── java/ # 测试源码
│ └── target/ # 编译输出目录
│
├── vue-frontend/ # Vue.js 前端应用
│ ├── Dockerfile # 前端 Docker 镜像构建文件
│ ├── nginx.conf # Nginx 服务器配置
│ ├── package.json # NPM 包管理和脚本配置
│ ├── package-lock.json # NPM 依赖版本锁定
│ ├── babel.config.js # Babel 编译配置
│ ├── vue.config.js # Vue CLI 构建配置
│ ├── jsconfig.json # JavaScript 项目配置
│ ├── public/ # 静态资源
│ │ ├── index.html # HTML 模板
│ │ └── favicon.ico # 网站图标
│ ├── src/ # 前端源码
│ │ ├── main.js # 应用入口文件
│ │ ├── App.vue # 根组件
│ │ ├── api/ # API 接口封装
│ │ │ ├── index.js # 主 API 文件
│ │ │ └── network.js # 网络请求配置
│ │ ├── assets/ # 静态资源
│ │ │ └── logo.png # 项目 Logo
│ │ ├── components/ # 可复用组件
│ │ │ └── EmptyState.vue # 空状态组件
│ │ ├── directives/ # 自定义指令
│ │ │ └── permission.js # 权限指令
│ │ ├── router/ # 路由配置
│ │ │ └── index.js # 路由定义
│ │ ├── utils/ # 工具函数
│ │ │ ├── auth.js # 认证工具
│ │ │ ├── clipboard.js # 剪贴板工具
│ │ │ └── jwt.js # JWT 处理
│ │ └── views/ # 页面组件
│ │ ├── Login.vue # 登录页面
│ │ ├── Home.vue # 主框架页面
│ │ ├── Index.vue # 仪表板首页
│ │ ├── ChangePassword.vue # 修改密码页面
│ │ ├── node.vue # 节点管理页面
│ │ ├── Tunnel.vue # 隧道管理页面
│ │ ├── Forward.vue # 转发管理页面
│ │ ├── User.vue # 用户管理页面
│ │ └── Limit.vue # 限速规则页面
│ └── node_modules/ # NPM 依赖包
│
└── vitepress/ # 文档站点 (VitePress)
├── .vitepress/ # VitePress 配置
│ └── config.js # 站点配置文件
├── package.json # 文档站点依赖
├── index.md # 文档首页
├── getting-started.md # 快速开始指南
├── guide.md # 详细使用指南
└── public/ # 静态资源
└── favicon.ico # 文档站点图标
```
## 核心组件详解
### 1. 转发引擎 (go-gost)
**功能**: 网络流量转发的核心引擎
**技术栈**: Go 语言
**主要特性**:
- 支持多种协议: TCP, UDP, TLS, WebSocket, QUIC 等
- 灵活的连接器和监听器架构
- 内置流量限制和监控功能
- 支持中继链和负载均衡
- 插件化的认证和绕行机制
**关键模块**:
- `connector/`: 实现各种出站连接器
- `listener/`: 实现各种入站监听器
- `handler/`: 处理不同协议的数据转发
- `limiter/`: 提供流量控制和限速功能
- `recorder/`: 记录流量统计和连接信息
### 2. 后端服务 (Spring Boot)
**功能**: 提供 RESTful API 和业务逻辑处理
**技术栈**: Java + Spring Boot + MyBatis + MySQL
**主要特性**:
- 用户认证和权限管理
- 节点、隧道、转发规则的 CRUD 操作
- 流量统计和监控数据收集
- 与 go-gost 引擎的配置同步
- 用户权限分级和资源限额管理
**核心模块**:
- `controller/`: REST API 接口层
- `service/`: 业务逻辑处理层
- `mapper/`: 数据访问层 (MyBatis)
- `entity/`: 数据模型和实体类
- `config/`: 系统配置和安全配置
### 3. 前端界面 (Vue.js)
**功能**: 现代化的 Web 管理界面
**技术栈**: Vue.js 2 + Element UI + Axios
**主要特性**:
- 响应式设计,支持桌面和移动端
- 实时数据更新和图表展示
- 直观的操作界面和用户体验
- 权限控制和路由守卫
- 组件化开发和代码复用
**页面结构**:
- `Login.vue`: 用户登录界面
- `Home.vue`: 主框架布局
- `Index.vue`: 仪表板和统计概览
- `node.vue`: 节点管理和监控
- `Tunnel.vue`: 隧道配置和管理
- `Forward.vue`: 转发规则管理
- `User.vue`: 用户和权限管理
- `Limit.vue`: 限速规则配置
### 4. 数据库设计
**技术**: MySQL 8.0+
**主要表结构**:
- `users`: 用户账号和基本信息
- `nodes`: 节点信息和状态
- `tunnels`: 隧道配置和参数
- `forwards`: 转发规则定义
- `user_permissions`: 用户权限分配
- `traffic_stats`: 流量统计数据
- `limit_rules`: 限速规则配置
### 5. 部署架构
**容器化**: Docker + Docker Compose
**网络模式**: 支持 IPv4/IPv6 双栈
**服务组件**:
- `vue-frontend`: Nginx + Vue.js 静态文件服务
- `springboot-backend`: Spring Boot API 服务
- `mysql`: MySQL 数据库服务
- `go-gost`: 转发引擎实例
**端口分配**:
- `6366`: 前端 Web 界面
- `6365`: 后端 API 服务
- `3306`: MySQL 数据库 (内部)
- `动态`: 转发端口范围
## 开发和扩展
### 添加新功能
1. **后端 API**: 在 `springboot-backend/src/main/java/` 中添加新的 Controller 和 Service
2. **前端页面**: 在 `vue-frontend/src/views/` 中创建新的 Vue 组件
3. **数据库**: 修改 `gost.sql` 添加新的表结构
4. **转发逻辑**: 扩展 `go-gost/x/` 中的相关模块
### 自定义配置
- **Docker 配置**: 修改 `docker-compose-*.yml` 文件
- **前端配置**: 调整 `vue-frontend/vue.config.js`
- **后端配置**: 修改 `springboot-backend/src/main/resources/application.yml`
- **Nginx 配置**: 更新 `vue-frontend/nginx.conf`
### 文档维护
- **用户文档**: 在 `vitepress/` 目录下编辑 Markdown 文件
- **API 文档**: 使用 Swagger 注解自动生成
- **代码注释**: 遵循各语言的文档注释规范
这个项目采用了现代化的微服务架构,各个组件职责明确,易于维护和扩展。通过容器化部署,可以快速在不同环境中部署和运行。
+1
View File
@@ -0,0 +1 @@
+1 -1
View File
@@ -332,7 +332,7 @@
<!-- 用户隧道权限分配对话框 -->
<el-dialog
:title="`用户 ${currentUser.name} 的隧道权限管理`"
:title="`用户 ${currentUser.user} 的隧道权限管理`"
:visible.sync="tunnelDialogVisible"
width="50%"
@close="resetTunnelDialog"