feat(i7): async webhook delivery queue, OPS RBAC, UI role routing; docs and runbook

- Architect: I7_DESIGN.md, I7_IMPLEMENTATION_REVIEW.md; parallel index + track B
- Backend: @EnableMethodSecurity; OPS login; CallbackInbox PreAuthorize; IntegrationCatalog triple role
- Webhook: V2 webhook_platform_delivery; planner + scheduler + single-shot forwarder; tests
- Frontend: Pinia hasAnyRole; MainLayout/HomeView/router for OPS vs dev
- Runbook §10.5 delivery config

Made-with: Cursor
This commit is contained in:
2026-04-06 23:01:10 +08:00
parent ce49fe143c
commit 5fe7181b35
33 changed files with 936 additions and 200 deletions
+15 -13
View File
@@ -2,14 +2,14 @@
<div class="home">
<el-card class="block">
<el-alert
title="交付平台(I6 UAT):以下为已实现模块的快速入口;登录态为 JWT Bearer"
title="交付平台(I7):按角色展示入口;Callback 仅 OPS / SYS_ADMIN"
type="info"
show-icon
:closable="false"
/>
<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">
<router-link v-for="l in visibleModuleLinks" :key="l.to" class="ql" :to="l.to">
{{ l.label }}
</router-link>
</div>
@@ -23,7 +23,7 @@
</template>
<script setup>
import { ref, onMounted } from "vue";
import { ref, onMounted, computed } from "vue";
import axios from "axios";
import { useAuthStore } from "../stores/auth";
@@ -31,18 +31,20 @@ const auth = useAuthStore();
const pingBody = ref("");
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: "产品线" },
/** I7与 MainLayout / 路由 meta 一致 */
const allModuleLinks = [
{ to: "/customers", label: "客户", roles: ["SYS_ADMIN", "DEVELOPER"] },
{ to: "/projects", label: "项目", roles: ["SYS_ADMIN", "DEVELOPER"] },
{ to: "/contracts", label: "合同", roles: ["SYS_ADMIN", "DEVELOPER"] },
{ to: "/deliveries", label: "交付", roles: ["SYS_ADMIN", "DEVELOPER"] },
{ to: "/licenses/sn", label: "许可 SN", roles: ["SYS_ADMIN", "DEVELOPER"] },
{ to: "/callbacks", label: "Callback 收件箱", roles: ["SYS_ADMIN", "OPS"] },
{ to: "/integration/environments", label: "集成环境", roles: ["SYS_ADMIN", "DEVELOPER", "OPS"] },
{ to: "/integration/product-lines", label: "产品线", roles: ["SYS_ADMIN", "DEVELOPER", "OPS"] },
];
const visibleModuleLinks = computed(() => allModuleLinks.filter((l) => auth.hasAnyRole(l.roles)));
onMounted(() => auth.restoreAxiosAuth());
async function ping() {