feat(web): VITE_API_BASE and I6 home module navigation

Made-with: Cursor
This commit is contained in:
2026-04-06 22:46:31 +08:00
parent d9536802db
commit 499fef3c2f
3 changed files with 67 additions and 6 deletions
+10
View File
@@ -15,6 +15,16 @@ npm run dev
浏览器访问 `http://127.0.0.1:5173`,登录 `admin` / `admin``/api` 由 Vite 代理到 `8080` 浏览器访问 `http://127.0.0.1:5173`,登录 `admin` / `admin``/api` 由 Vite 代理到 `8080`
## 生产 / Staging 构建(`VITE_API_BASE`
静态部署到 Nginx 且 **API 为独立主机** 时,构建前设置后端根 URL(**无**尾部斜杠;axios 仍请求 `/api/v1/...`):
```bash
VITE_API_BASE=https://your-platform-api.example.com npm run build
```
与 [I6_CLOSEOUT.md](../../docs/engineering/iterations/I6_CLOSEOUT.md) §4 环境矩阵一致。本地开发通常 **不设** 该变量。
## 构建 ## 构建
```bash ```bash
+6
View File
@@ -7,6 +7,12 @@ import App from "./App.vue";
import router from "./router"; import router from "./router";
import { useAuthStore } from "./stores/auth"; import { useAuthStore } from "./stores/auth";
const apiBase =
typeof import.meta.env.VITE_API_BASE === "string" ? import.meta.env.VITE_API_BASE.trim() : "";
if (apiBase) {
axios.defaults.baseURL = apiBase.replace(/\/+$/, "");
}
const pinia = createPinia(); const pinia = createPinia();
const app = createApp(App); const app = createApp(App);
app.use(pinia); app.use(pinia);
@@ -1,10 +1,25 @@
<template> <template>
<el-card> <div class="home">
<el-alert title="I1JWT + 布局壳;后续迭代挂载 M1M11" type="info" show-icon :closable="false" /> <el-card class="block">
<el-alert
title="交付平台(I6 UAT):以下为已实现模块的快速入口;登录态为 JWT Bearer"
type="info"
show-icon
:closable="false"
/>
<p class="meta">用户{{ auth.displayName }}角色{{ auth.roles.join(", ") || "—" }}</p> <p class="meta">用户{{ auth.displayName }}角色{{ auth.roles.join(", ") || "—" }}</p>
<div class="quick-links" aria-label="模块导航">
<router-link v-for="l in moduleLinks" :key="l.to" class="ql" :to="l.to">
{{ l.label }}
</router-link>
</div>
</el-card>
<el-card class="block">
<template #header>调试</template>
<el-button type="primary" :loading="pingLoading" @click="ping">Bearer 调用 /api/v1/ping</el-button> <el-button type="primary" :loading="pingLoading" @click="ping">Bearer 调用 /api/v1/ping</el-button>
<pre v-if="pingBody">{{ pingBody }}</pre> <pre v-if="pingBody">{{ pingBody }}</pre>
</el-card> </el-card>
</div>
</template> </template>
<script setup> <script setup>
@@ -16,6 +31,18 @@ const auth = useAuthStore();
const pingBody = ref(""); const pingBody = ref("");
const pingLoading = ref(false); const pingLoading = ref(false);
/** I6:全链路导航锚点,与 MainLayout 菜单一致 */
const moduleLinks = [
{ to: "/customers", label: "客户" },
{ to: "/projects", label: "项目" },
{ to: "/contracts", label: "合同" },
{ to: "/deliveries", label: "交付" },
{ to: "/licenses/sn", label: "许可 SN" },
{ to: "/callbacks", label: "Callback 收件箱" },
{ to: "/integration/environments", label: "集成环境" },
{ to: "/integration/product-lines", label: "产品线" },
];
onMounted(() => auth.restoreAxiosAuth()); onMounted(() => auth.restoreAxiosAuth());
async function ping() { async function ping() {
@@ -33,9 +60,27 @@ async function ping() {
</script> </script>
<style scoped> <style scoped>
.home {
display: flex;
flex-direction: column;
gap: 16px;
}
.meta { .meta {
margin: 12px 0; margin: 12px 0;
} }
.quick-links {
display: flex;
flex-wrap: wrap;
gap: 10px 14px;
margin-top: 8px;
}
.ql {
color: var(--el-color-primary);
text-decoration: none;
}
.ql:hover {
text-decoration: underline;
}
pre { pre {
margin-top: 12px; margin-top: 12px;
background: #1e1e1e; background: #1e1e1e;