diff --git a/web/apps/web-ele/index.html b/web/apps/web-ele/index.html index 2b59b8d..54b03c9 100644 --- a/web/apps/web-ele/index.html +++ b/web/apps/web-ele/index.html @@ -11,22 +11,8 @@ name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" /> - <%= VITE_APP_TITLE %> - - +
diff --git a/web/apps/web-ele/src/views/_core/authentication/login.vue b/web/apps/web-ele/src/views/_core/authentication/login.vue index ebee0be..0534853 100644 --- a/web/apps/web-ele/src/views/_core/authentication/login.vue +++ b/web/apps/web-ele/src/views/_core/authentication/login.vue @@ -123,6 +123,7 @@ const formSchema = computed((): VbenFormSchema[] => { { component: 'VbenInput', componentProps: { + autocomplete: 'username', placeholder: $t('authentication.usernameTip'), }, defaultValue: '', @@ -133,6 +134,7 @@ const formSchema = computed((): VbenFormSchema[] => { { component: 'VbenInputPassword', componentProps: { + autocomplete: 'current-password', placeholder: $t('authentication.passwordTip'), }, defaultValue: '', diff --git a/web/scripts/serve-web-ele-dist.mjs b/web/scripts/serve-web-ele-dist.mjs new file mode 100644 index 0000000..e324e9c --- /dev/null +++ b/web/scripts/serve-web-ele-dist.mjs @@ -0,0 +1,112 @@ +import { createReadStream } from 'node:fs'; +import { stat } from 'node:fs/promises'; +import http from 'node:http'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = fileURLToPath(new URL('../apps/web-ele/dist', import.meta.url)); +const host = process.env.HOST || '127.0.0.1'; +const port = Number(process.env.PORT || 5777); +const basePath = process.env.BASE_PATH || '/ai-agent-admin'; +const apiPrefix = `${basePath}/basic-api`; +const rootApiPrefix = '/basic-api'; +const apiTarget = + process.env.API_TARGET || 'http://124.220.21.25/zq-ai-admin/basic-api'; + +const mime = { + '.css': 'text/css; charset=utf-8', + '.html': 'text/html; charset=utf-8', + '.ico': 'image/x-icon', + '.js': 'application/javascript; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.mjs': 'application/javascript; charset=utf-8', + '.mp3': 'audio/mpeg', + '.png': 'image/png', + '.svg': 'image/svg+xml', +}; + +async function exists(filePath) { + try { + return (await stat(filePath)).isFile(); + } catch { + return false; + } +} + +async function proxy(req, res) { + const targetBase = apiTarget.replace(/\/$/, ''); + const apiPath = req.url.startsWith(apiPrefix) + ? req.url.replace(apiPrefix, '') + : req.url.replace(rootApiPrefix, ''); + const target = new URL(`${targetBase}${apiPath}`); + const headers = { ...req.headers }; + delete headers.host; + + let upstream; + try { + upstream = await fetch(target, { + body: ['GET', 'HEAD'].includes(req.method) ? undefined : req, + duplex: 'half', + headers, + method: req.method, + }); + } catch (error) { + res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' }); + res.end(`Proxy upstream unavailable: ${target}\n${error.message}`); + return; + } + + res.writeHead(upstream.status, Object.fromEntries(upstream.headers)); + if (upstream.body) { + res.end(Buffer.from(await upstream.arrayBuffer())); + } else { + res.end(); + } +} + +async function serve(req, res) { + const url = new URL(req.url || '/', `http://${host}:${port}`); + if ( + url.pathname.startsWith(apiPrefix) || + url.pathname.startsWith(rootApiPrefix) + ) { + await proxy(req, res); + return; + } + + if (url.pathname === '/' || url.pathname === '') { + res.writeHead(302, { Location: `${basePath}/` }); + res.end(); + return; + } + + if (!url.pathname.startsWith(basePath)) { + res.writeHead(404); + res.end('Not Found'); + return; + } + + let rel = url.pathname.slice(basePath.length) || '/index.html'; + if (rel === '/') rel = '/index.html'; + + let filePath = path.join(root, rel); + if (!(await exists(filePath))) { + filePath = path.join(root, 'index.html'); + } + + const ext = path.extname(filePath); + res.setHeader('Content-Type', mime[ext] || 'application/octet-stream'); + createReadStream(filePath).pipe(res); +} + +const server = http.createServer((req, res) => { + serve(req, res).catch((error) => { + res.writeHead(500); + res.end(error?.stack || String(error)); + }); +}); + +server.listen(port, host, () => { + console.log(`web-ele dist server: http://${host}:${port}${basePath}/`); + console.log(`api proxy: ${apiPrefix} -> ${apiTarget}`); +});