14 Commits
armbian ... dev

Author SHA1 Message Date
eric
a3f743de4c 's' 2025-09-29 13:21:10 +08:00
eric
3f402b1398 's' 2025-09-29 13:19:36 +08:00
eric
9e797e018a 's' 2025-09-29 13:16:43 +08:00
eric
cf94ae2926 's' 2025-09-29 13:15:15 +08:00
eric
33793d7370 's' 2025-09-29 12:35:14 +08:00
eric
1753829889 s 2025-09-08 16:45:13 +08:00
eric
fa3e1d5924 's' 2025-09-08 16:27:49 +08:00
eric
39df8bcbf8 's' 2025-09-08 16:19:27 +08:00
eric
c02a8f7172 'ss' 2025-09-08 15:58:34 +08:00
eric
dd6fbe777e s 2025-09-08 15:51:55 +08:00
eric
4ee7e30206 'ss' 2025-09-08 14:41:53 +08:00
eric
0494590f30 's' 2025-09-08 12:32:17 +08:00
eric
f2ba6a0833 'd' 2025-09-08 11:28:16 +08:00
eric
b2cf706636 'ss' 2025-08-28 20:54:48 +08:00
95 changed files with 578 additions and 17 deletions

4
.gitignore vendored
View File

@@ -32,8 +32,8 @@ bin/
build/
# Vue distributable files
/frontend/dist/*
!/frontend/dist/.gitkeep
# /frontend/dist/*
#!/frontend/dist/.gitkeep
# Playwright files
/frontend/test-results/

View File

@@ -59,7 +59,9 @@ func init() {
}
func addServerFlags(flags *pflag.FlagSet) {
flags.StringP("address", "a", "127.0.0.1", "address to listen on")
// flags.StringP("address", "a", "127.0.0.1", "address to listen on")
flags.StringP("address", "a", "0.0.0.0", "address to listen on")
flags.StringP("log", "l", "stdout", "log output")
flags.StringP("port", "p", "8080", "port to listen on")
flags.StringP("cert", "t", "", "tls certificate")

1
file.sh Normal file
View File

@@ -0,0 +1 @@
./filebrowser -r /path/to/srv -a 0.0.0.0 -p 8081

BIN
filebrowser_dev Executable file

Binary file not shown.

View File

@@ -0,0 +1 @@
.editor-font-size[data-v-99630ccc]{margin:0 .5em;color:var(--fg)}

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/ar-DtFJJrir.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/de-CsTqJtDw.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/el-CqCURAvT.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/en-VcjLuOQ9.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/es-BpQk-HGo.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/fr-CI4UQ_Wr.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/he-B4IfBkLC.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/hu-BPfANBiL.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/i18n-B51KFB2t.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/it-CxzZEkDv.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/ja-BGcYKjzK.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/ko-Ck5pBF4s.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/nl-BUJf3J9m.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/pl-pV3PHVMk.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/ro-dgC97dTu.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/ru-dbAG_z6N.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/sk-LuNleX7X.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/tr-DBYvv1ex.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
frontend/dist/assets/uk-D_F9n3KQ.js.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
frontend/dist/img/icons/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

3
frontend/dist/img/icons/favicon.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

147
frontend/dist/img/logo.svg vendored Normal file
View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xml:space="preserve"
width="560"
height="560"
version="1.1"
style="clip-rule:evenodd;fill-rule:evenodd;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
viewBox="0 0 560 560"
id="svg44"
sodipodi:docname="icon_raw.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
inkscape:export-filename="/home/umarcor/filebrowser/logo/icon_raw.svg.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"><metadata
id="metadata48"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="711"
id="namedview46"
showgrid="false"
inkscape:zoom="0.33714286"
inkscape:cx="-172.33051"
inkscape:cy="280"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="1"
inkscape:current-layer="svg44" />
<defs
id="defs4">
<style
type="text/css"
id="style2">
<![CDATA[
.fil1 {fill:#FEFEFE}
.fil6 {fill:#006498}
.fil7 {fill:#0EA5EB}
.fil8 {fill:#2979FF}
.fil3 {fill:#2BBCFF}
.fil0 {fill:#455A64}
.fil4 {fill:#53C6FC}
.fil5 {fill:#BDEAFF}
.fil2 {fill:#332C2B;fill-opacity:0.149020}
]]>
</style>
</defs>
<g
id="g85"
transform="translate(-70,-70)"><path
class="fil1"
d="M 350,71 C 504,71 629,196 629,350 629,504 504,629 350,629 196,629 71,504 71,350 71,196 196,71 350,71 Z"
id="path9"
inkscape:connector-curvature="0"
style="fill:#fefefe" /><path
class="fil2"
d="M 475,236 593,387 C 596,503 444,639 301,585 L 225,486 339,330 c 0,0 138,-95 136,-94 z"
id="path11"
inkscape:connector-curvature="0"
style="fill:#332c2b;fill-opacity:0.14902003" /><path
class="fil3"
d="m 231,211 h 208 l 38,24 v 246 c 0,5 -3,8 -8,8 H 231 c -5,0 -8,-3 -8,-8 V 219 c 0,-5 3,-8 8,-8 z"
id="path13"
inkscape:connector-curvature="0"
style="fill:#2bbcff" /><path
class="fil4"
d="m 231,211 h 208 l 38,24 v 2 L 440,214 H 231 c -4,0 -7,3 -7,7 v 263 c -1,-1 -1,-2 -1,-3 V 219 c 0,-5 3,-8 8,-8 z"
id="path15"
inkscape:connector-curvature="0"
style="fill:#53c6fc" /><polygon
class="fil5"
points="305,212 418,212 418,310 305,310 "
id="polygon17"
style="fill:#bdeaff" /><path
class="fil5"
d="m 255,363 h 189 c 3,0 5,2 5,4 V 483 H 250 V 367 c 0,-2 2,-4 5,-4 z"
id="path19"
inkscape:connector-curvature="0"
style="fill:#bdeaff" /><polygon
class="fil6"
points="250,470 449,470 449,483 250,483 "
id="polygon21"
style="fill:#006498" /><path
class="fil6"
d="m 380,226 h 10 c 3,0 6,2 6,5 v 40 c 0,3 -3,6 -6,6 h -10 c -3,0 -6,-3 -6,-6 v -40 c 0,-3 3,-5 6,-5 z"
id="path23"
inkscape:connector-curvature="0"
style="fill:#006498" /><path
class="fil1"
d="m 254,226 c 10,0 17,7 17,17 0,9 -7,16 -17,16 -9,0 -17,-7 -17,-16 0,-10 8,-17 17,-17 z"
id="path25"
inkscape:connector-curvature="0"
style="fill:#fefefe" /><path
class="fil6"
d="m 267,448 h 165 c 2,0 3,1 3,3 v 0 c 0,1 -1,3 -3,3 H 267 c -2,0 -3,-2 -3,-3 v 0 c 0,-2 1,-3 3,-3 z"
id="path27"
inkscape:connector-curvature="0"
style="fill:#006498" /><path
class="fil6"
d="m 267,415 h 165 c 2,0 3,1 3,3 v 0 c 0,1 -1,2 -3,2 H 267 c -2,0 -3,-1 -3,-2 v 0 c 0,-2 1,-3 3,-3 z"
id="path29"
inkscape:connector-curvature="0"
style="fill:#006498" /><path
class="fil6"
d="m 267,381 h 165 c 2,0 3,2 3,3 v 0 c 0,2 -1,3 -3,3 H 267 c -2,0 -3,-1 -3,-3 v 0 c 0,-1 1,-3 3,-3 z"
id="path31"
inkscape:connector-curvature="0"
style="fill:#006498" /><path
class="fil1"
d="m 236,472 c 3,0 5,2 5,5 0,2 -2,4 -5,4 -3,0 -5,-2 -5,-4 0,-3 2,-5 5,-5 z"
id="path33"
inkscape:connector-curvature="0"
style="fill:#fefefe" /><path
class="fil1"
d="m 463,472 c 3,0 5,2 5,5 0,2 -2,4 -5,4 -3,0 -5,-2 -5,-4 0,-3 2,-5 5,-5 z"
id="path35"
inkscape:connector-curvature="0"
style="fill:#fefefe" /><polygon
class="fil6"
points="305,212 284,212 284,310 305,310 "
id="polygon37"
style="fill:#006498" /><path
class="fil7"
d="m 477,479 v 2 c 0,5 -3,8 -8,8 H 231 c -5,0 -8,-3 -8,-8 v -2 c 0,4 3,8 8,8 h 238 c 5,0 8,-4 8,-8 z"
id="path39"
inkscape:connector-curvature="0"
style="fill:#0ea5eb" /><path
class="fil8"
d="M 350,70 C 505,70 630,195 630,350 630,505 505,630 350,630 195,630 70,505 70,350 70,195 195,70 350,70 Z m 0,46 C 479,116 584,221 584,350 584,479 479,584 350,584 221,584 116,479 116,350 116,221 221,116 350,116 Z"
id="path41"
inkscape:connector-curvature="0"
style="fill:#2979ff" /></g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

163
frontend/dist/index.html vendored Normal file
View File

@@ -0,0 +1,163 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, user-scalable=no"
/>
[{[ if .ReCaptcha -]}]
<script src="[{[ .ReCaptchaHost ]}]/recaptcha/api.js?render=explicit"></script>
[{[ end ]}]
<title>
[{[ if .Name -]}][{[ .Name ]}][{[ else ]}]File Browser[{[ end ]}]
</title>
<meta name="robots" content="noindex,nofollow" />
<link rel="icon" type="image/svg+xml" href="[{[ .StaticURL ]}]/img/icons/favicon.svg" />
<link rel="shortcut icon" href="[{[ .StaticURL ]}]/img/icons/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="[{[ .StaticURL ]}]/img/icons/apple-touch-icon.png" />
<meta name="apple-mobile-web-app-title" content="File Browser" />
<!-- Add to home screen for Android and modern mobile browsers -->
<link
rel="manifest"
id="manifestPlaceholder"
crossorigin="use-credentials"
/>
<meta
name="theme-color"
content="[{[ if .Color -]}][{[ .Color ]}][{[ else ]}]#2979ff[{[ end ]}]"
/>
<!-- Inject Some Variables and generate the manifest json -->
<script>
// We can assign JSON directly
window.FileBrowser = [{[ .Json ]}];
// Global function to prepend static url
window.__prependStaticUrl = (url) => {
return `${window.FileBrowser.StaticURL}/${url.replace(/^\/+/, "")}`;
};
var dynamicManifest = {
name: window.FileBrowser.Name || "File Browser",
short_name: window.FileBrowser.Name || "File Browser",
icons: [
{
src: window.__prependStaticUrl("/img/icons/android-chrome-192x192.png"),
sizes: "192x192",
type: "image/png",
},
{
src: window.__prependStaticUrl("/img/icons/android-chrome-512x512.png"),
sizes: "512x512",
type: "image/png",
},
],
start_url: window.location.origin + window.FileBrowser.BaseURL,
display: "standalone",
background_color: "#ffffff",
theme_color: window.FileBrowser.Color || "#455a64",
};
const stringManifest = JSON.stringify(dynamicManifest);
const blob = new Blob([stringManifest], { type: "application/json" });
const manifestURL = URL.createObjectURL(blob);
document
.querySelector("#manifestPlaceholder")
.setAttribute("href", manifestURL);
</script>
<style>
#loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #fff;
z-index: 9999;
transition: 0.1s ease opacity;
-webkit-transition: 0.1s ease opacity;
}
#loading.done {
opacity: 0;
}
#loading .spinner {
width: 70px;
text-align: center;
position: fixed;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
#loading .spinner > div {
width: 18px;
height: 18px;
background-color: #333;
border-radius: 100%;
display: inline-block;
-webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
}
#loading .spinner .bounce1 {
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
#loading .spinner .bounce2 {
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
@-webkit-keyframes sk-bouncedelay {
0%,
80%,
100% {
-webkit-transform: scale(0);
}
40% {
-webkit-transform: scale(1);
}
}
@keyframes sk-bouncedelay {
0%,
80%,
100% {
-webkit-transform: scale(0);
transform: scale(0);
}
40% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
</style>
</head>
<body>
<div id="app"></div>
<div id="loading">
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
[{[ if .CSS -]}]
<link rel="stylesheet" href="[{[ .StaticURL ]}]/custom.css" />
[{[ end ]}]
</body>
</html>

20
frontend/dist/manifest.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "File Browser",
"short_name": "File Browser",
"icons": [
{
"src": "./img/icons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./static/img/icons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#455a64"
}

154
frontend/dist/public/index.html vendored Normal file
View File

@@ -0,0 +1,154 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, user-scalable=no"
/>
[{[ if .ReCaptcha -]}]
<script src="[{[ .ReCaptchaHost ]}]/recaptcha/api.js?render=explicit"></script>
[{[ end ]}]
<title>
[{[ if .Name -]}][{[ .Name ]}][{[ else ]}]File Browser[{[ end ]}]
</title>
<meta name="robots" content="noindex,nofollow" />
<link rel="icon" type="image/svg+xml" href="[{[ .StaticURL ]}]/img/icons/favicon.svg" />
<link rel="shortcut icon" href="[{[ .StaticURL ]}]/img/icons/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="[{[ .StaticURL ]}]/img/icons/apple-touch-icon.png" />
<meta name="apple-mobile-web-app-title" content="File Browser" />
<!-- Add to home screen for Android and modern mobile browsers -->
<link
rel="manifest"
id="manifestPlaceholder"
crossorigin="use-credentials"
/>
<meta
name="theme-color"
content="[{[ if .Color -]}][{[ .Color ]}][{[ else ]}]#2979ff[{[ end ]}]"
/>
<!-- Inject Some Variables and generate the manifest json -->
<script>
// We can assign JSON directly
window.FileBrowser = [{[ .Json ]}];
// Global function to prepend static url
window.__prependStaticUrl = (url) => {
return `${window.FileBrowser.StaticURL}/${url.replace(/^\/+/, "")}`;
};
var dynamicManifest = {
name: window.FileBrowser.Name || "File Browser",
short_name: window.FileBrowser.Name || "File Browser",
icons: [
{
src: window.__prependStaticUrl("/img/icons/android-chrome-192x192.png"),
sizes: "192x192",
type: "image/png",
},
{
src: window.__prependStaticUrl("/img/icons/android-chrome-512x512.png"),
sizes: "512x512",
type: "image/png",
},
],
start_url: window.location.origin + window.FileBrowser.BaseURL,
display: "standalone",
background_color: "#ffffff",
theme_color: window.FileBrowser.Color || "#455a64",
};
const stringManifest = JSON.stringify(dynamicManifest);
const blob = new Blob([stringManifest], { type: "application/json" });
const manifestURL = URL.createObjectURL(blob);
document
.querySelector("#manifestPlaceholder")
.setAttribute("href", manifestURL);
</script>
<style>
#loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #fff;
z-index: 9999;
transition: 0.1s ease opacity;
-webkit-transition: 0.1s ease opacity;
}
#loading.done {
opacity: 0;
}
#loading .spinner {
width: 70px;
text-align: center;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#loading .spinner > div {
width: 18px;
height: 18px;
background-color: #333;
border-radius: 100%;
display: inline-block;
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
}
#loading .spinner .bounce1 {
animation-delay: -0.32s;
}
#loading .spinner .bounce2 {
animation-delay: -0.16s;
}
@keyframes sk-bouncedelay {
0%,
80%,
100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
</style>
<script type="module" crossorigin src="[{[ .StaticURL ]}]/assets/index-EUD6rfX7.js"></script>
<link rel="modulepreload" crossorigin href="[{[ .StaticURL ]}]/assets/dayjs-DoHIBBbq.js">
<link rel="modulepreload" crossorigin href="[{[ .StaticURL ]}]/assets/i18n-B51KFB2t.js">
<link rel="stylesheet" crossorigin href="[{[ .StaticURL ]}]/assets/index-Cckpz6IB.css">
<script type="module">import.meta.url;import("_").catch(()=>1);(async function*(){})().next();if(location.protocol!="file:"){window.__vite_is_modern_browser=true}</script>
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
</head>
<body>
<div id="app"></div>
<div id="loading">
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
</div>
[{[ if .CSS -]}]
<link rel="stylesheet" href="[{[ .StaticURL ]}]/custom.css" />
[{[ end ]}]
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
<script nomodule crossorigin id="vite-legacy-polyfill" src="[{[ .StaticURL ]}]/assets/polyfills-legacy-whU9bDSR.js"></script>
<script nomodule crossorigin id="vite-legacy-entry" data-src="[{[ .StaticURL ]}]/assets/index-legacy-D1Xq-vUG.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
</body>

View File

@@ -24,7 +24,9 @@ export default defineConfig({
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://127.0.0.1:5173",
// baseURL: "http://127.0.0.1:5173",
baseURL: "http://0.0.0.0:5173",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
@@ -74,7 +76,8 @@ export default defineConfig({
/* Run your local dev server before starting the tests */
webServer: {
command: "npm run dev",
url: "http://127.0.0.1:5173",
// url: "http://127.0.0.1:5173",
url: "http://0.0.0.0:5173",
reuseExistingServer: !process.env.CI,
},
});

View File

@@ -18,12 +18,19 @@
<p class="modified">
<time :datetime="modified">{{ humanTime() }}</time>
<!-- 直播按钮 -->
<button v-if="!isDir && isVideoFile(name)" class="live-button" @click="startLive">
开始直播
<button v-if="!isDir && isVideoFile(name)" class="live-button" @click="loopLive">
循环直播
</button>
<button v-if="!isDir && isVideoFile(name)" class="live-button" @click="stopLive">
<button v-if="!isDir && isVideoFile(name)" class="live-button" @click="startLive">
单次直播
</button>
<button v-if="!isDir && isVideoFile(name)" class="live-button" @click="obsLive">
OBS 推流
</button>
<button v-if="!isDir && isVideoFile(name)" class="live-button" @click="stopLive">
停止直播
</button>
</p>
</div>
@@ -379,8 +386,8 @@ const stopLive = async () => {
const thread_id = props.url.replace(/\//g, "_");
// 调用 FastAPI 停止接口
// const res = await fetch("http://live.local:8700/stop_live", {
const res = await fetch("http://localhost:8700/stop_live", {
// const res = await fetch("http://192.168.31.103:8700/stop_live", {
const res = await fetch(`${location.protocol}//${location.hostname}:8700/stop_live`, {
method: "POST",
headers: { "Content-Type": "application/json" },
@@ -401,17 +408,16 @@ const stopLive = async () => {
};
const startLive = async () => {
const loopLive = async () => {
try {
// props.url 是 FileBrowser 内部路径,例如 /videos/test.mp4
const file_path = props.url;
// const file_path = encodeURIComponent(props.url);
console.log('file_path',file_path)
console.log('file_path', file_path)
// 调用 FastAPI 后端接口
// const res = await fetch("http://live.local:8700/start_live", {
const res = await fetch("http://localhost:8700/start_live", {
// const res = await fetch("http://192.168.31.245:8700/start_live", {
// const res = await fetch("http://192.168.31.103:8700/loop_Live", {
const res = await fetch(`${location.protocol}//${location.hostname}:8700/loop_Live`, {
method: "POST",
headers: { "Content-Type": "application/json" },
@@ -431,6 +437,64 @@ const startLive = async () => {
}
};
const obsLive = async () => {
try {
// props.url 是 FileBrowser 内部路径,例如 /videos/test.mp4
const file_path = props.url;
// const file_path = encodeURIComponent(props.url);
console.log('file_path for OBS:', file_path);
// 这里模拟 OBS 推流逻辑,你可以根据实际后端接口来调整
// const res = await fetch("http://192.168.31.103:8700/obs_live", {
const res = await fetch(`${location.protocol}//${location.hostname}:8700/obs_live`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ filename: file_path })
});
const data = await res.json();
if (data.status === "ok") {
alert(`OBS 推流已启动: ${file_path}`);
} else {
alert(`OBS 推流失败: ${data.msg}`);
}
} catch (err) {
console.error(err);
alert("OBS 推流接口调用失败,请检查后端服务是否启动");
}
};
const startLive = async () => {
try {
// props.url 是 FileBrowser 内部路径,例如 /videos/test.mp4
const file_path = props.url;
// const file_path = encodeURIComponent(props.url);
console.log('file_path', file_path)
// 调用 FastAPI 后端接口
const res = await fetch(`${location.protocol}//${location.hostname}:8700/start_live`, {
// const res = await fetch("http://127.0.0.1:8700/start_live", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ filename: file_path })
});
const data = await res.json();
if (data.status === "ok") {
alert(`直播已开始: ${file_path}`);
} else {
alert(`直播失败: ${data.msg}`);
}
} catch (err) {
console.error(err);
alert("直播接口调用失败,请检查后端服务是否启动");
}
};
</script>
<style scoped>

View File

@@ -41,13 +41,14 @@ export default defineConfig(({ command }) => {
proxy: {
// Zero3 后端 WebSocket如果你有 ws 接口)
"/api/command": {
target: `ws://${location.protocol}//${location.hostname}:8081`,
// target: "ws://live.local:8081",
target: "ws://localhost:8081",
ws: true,
},
// Zero3 后端 HTTP
"/api": `${location.protocol}//${location.hostname}:8081`,
// "/api": "http://live.local:8081",
"/api": "http://localhost:8081",
},
},

BIN
live@live.local Normal file

Binary file not shown.