+
- {{ item.label }}
- {{ item.value }}
- {{ item.detail }}
+ {{ item.label }}
+ {{ item.value }}
+ {{ item.detail }}
diff --git a/web/src/views/login/LoginView.vue b/web/src/views/login/LoginView.vue
new file mode 100644
index 000000000..b17e78acb
--- /dev/null
+++ b/web/src/views/login/LoginView.vue
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+ Codex Proxy RS
+ Proxy RS · v0.1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 安静进入控制台。
+
+
+ 几条请求轨迹,连接账号池、模型目录与管理入口。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/tests/root-routing.test.mjs b/web/tests/root-routing.test.mjs
new file mode 100644
index 000000000..667cf0171
--- /dev/null
+++ b/web/tests/root-routing.test.mjs
@@ -0,0 +1,20 @@
+import assert from 'node:assert/strict'
+import { readFile } from 'node:fs/promises'
+import { dirname, resolve } from 'node:path'
+import { test } from 'node:test'
+import { fileURLToPath } from 'node:url'
+
+const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
+
+test('frontend is built and routed from the server root', async () => {
+ const viteConfig = await readFile(resolve(root, 'vite.config.ts'), 'utf8')
+ const router = await readFile(resolve(root, 'src/router/index.ts'), 'utf8')
+ const html = await readFile(resolve(root, 'index.html'), 'utf8')
+
+ assert.match(viteConfig, /base:\s*['"]\/['"]/)
+ assert.doesNotMatch(viteConfig, /base:\s*['"]\/admin\/['"]/)
+ assert.match(router, /createWebHistory\(['"]\/['"]\)/)
+ assert.doesNotMatch(router, /createWebHistory\(['"]\/admin\/['"]\)/)
+ assert.match(html, /href=['"]\/favicon\.svg['"]/)
+ assert.doesNotMatch(html, /\/admin\/favicon\.svg/)
+})
diff --git a/web/vite.config.ts b/web/vite.config.ts
index 5dc4104db..63a0b1865 100644
--- a/web/vite.config.ts
+++ b/web/vite.config.ts
@@ -4,7 +4,7 @@ import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
export default defineConfig({
- base: '/admin/',
+ base: '/',
plugins: [vue(), tailwindcss()],
resolve: {
alias: {