add route group sync
This commit is contained in:
@@ -157,6 +157,22 @@ describe('useRouteGroupStore', () => {
|
||||
expect(api.get).toHaveBeenCalledWith('/api/v1/routes', undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe('syncRoutes', () => {
|
||||
it('calls sync API and refreshes groups + routes', async () => {
|
||||
const store = useRouteGroupStore()
|
||||
vi.mocked(api.post).mockResolvedValueOnce(undefined)
|
||||
vi.mocked(api.get)
|
||||
.mockResolvedValueOnce(mockGroups)
|
||||
.mockResolvedValueOnce(mockRoutes)
|
||||
|
||||
await store.syncRoutes()
|
||||
|
||||
expect(api.post).toHaveBeenCalledWith('/api/v1/routes/sync')
|
||||
expect(api.get).toHaveBeenCalledWith('/api/v1/route-groups')
|
||||
expect(api.get).toHaveBeenCalledWith('/api/v1/routes', undefined)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// ─── Page 组件测试 ───
|
||||
@@ -177,6 +193,7 @@ describe('RouteGroupsPage', () => {
|
||||
EditOutlined: { template: '<span class="icon-edit" />' },
|
||||
DeleteOutlined: { template: '<span class="icon-delete" />' },
|
||||
SaveOutlined: { template: '<span class="icon-save" />' },
|
||||
SyncOutlined: { template: '<span class="icon-sync" />' },
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -242,6 +259,23 @@ describe('RouteGroupsPage', () => {
|
||||
expect(wrapper.text()).toContain('未分组')
|
||||
})
|
||||
|
||||
it('renders 同步路由 button and calls syncRoutes on click', async () => {
|
||||
await mountPage()
|
||||
|
||||
const syncBtn = wrapper.findAll('.ant-btn').find((b) => b.text().includes('同步路由'))
|
||||
expect(syncBtn).toBeDefined()
|
||||
|
||||
vi.mocked(api.post).mockResolvedValueOnce(undefined)
|
||||
vi.mocked(api.get)
|
||||
.mockResolvedValueOnce(mockGroups)
|
||||
.mockResolvedValueOnce(mockRoutes)
|
||||
|
||||
await syncBtn!.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(api.post).toHaveBeenCalledWith('/api/v1/routes/sync')
|
||||
})
|
||||
|
||||
it('calls batchAssignRoutes on save button click', async () => {
|
||||
await mountPage()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
SaveOutlined,
|
||||
SyncOutlined,
|
||||
} from '@ant-design/icons-vue'
|
||||
|
||||
const groupStore = useRouteGroupStore()
|
||||
@@ -55,6 +56,7 @@ const localCheckedKeys = ref<{ checked: (string | number)[], halfChecked: (strin
|
||||
halfChecked: [],
|
||||
})
|
||||
const assignSaving = ref(false)
|
||||
const syncing = ref(false)
|
||||
|
||||
// 当前选中组的名称
|
||||
const selectedGroupName = computed(() => {
|
||||
@@ -148,6 +150,19 @@ async function handleDelete(group: RouteGroupRecord) {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSyncRoutes() {
|
||||
syncing.value = true
|
||||
try {
|
||||
await groupStore.syncRoutes()
|
||||
message.success('路由同步成功')
|
||||
} catch (err: unknown) {
|
||||
const msg = err instanceof Error ? err.message : '同步失败'
|
||||
message.error(msg)
|
||||
} finally {
|
||||
syncing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGroupChange(routeId: number, groupId: number | null) {
|
||||
try {
|
||||
await groupStore.assignRouteToGroup(routeId, groupId)
|
||||
@@ -171,9 +186,14 @@ onMounted(async () => {
|
||||
<a-col :span="8">
|
||||
<a-card title="路由组" :loading="groupStore.loading">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button size="small" :loading="syncing" @click="handleSyncRoutes">
|
||||
<SyncOutlined /> 同步路由
|
||||
</a-button>
|
||||
<a-button type="primary" size="small" @click="openCreateModal">
|
||||
<PlusOutlined /> 新建
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 未分组入口 -->
|
||||
|
||||
@@ -86,6 +86,11 @@ export const useRouteGroupStore = defineStore('route-group', () => {
|
||||
await Promise.all([fetchGroups(), fetchRoutes()])
|
||||
}
|
||||
|
||||
async function syncRoutes() {
|
||||
await api.post('/api/v1/routes/sync')
|
||||
await Promise.all([fetchGroups(), fetchRoutes()])
|
||||
}
|
||||
|
||||
// 按首段资源名分组,避免同名叶节点与目录共存导致 UI 混乱
|
||||
const routeTree = computed(() => {
|
||||
const root: RouteTreeNode[] = []
|
||||
@@ -167,6 +172,7 @@ export const useRouteGroupStore = defineStore('route-group', () => {
|
||||
fetchRoutes,
|
||||
assignRouteToGroup,
|
||||
batchAssignRoutes,
|
||||
syncRoutes,
|
||||
routeTree,
|
||||
checkedRouteKeys,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user