Files
open-gateway-front/src/views/route/RouteList.vue
T
chenxing 77060325ef feat(mock): mock 演进轮——应用列表/代理测试页 + 网关 mock 数据扩充
- views/app/AppList.vue(新)+ views/proxytest/ProxyTest.vue(新):应用列表与代理测试演示页
- router/routes + apiDefinitions + App.vue/layout:新页路由与菜单接线
- assets/mock/gatewayApi.ts:mock 数据扩充(+136 行)
- RouteList:列表页联动增强
- vite.config:mock 相关配置调整
- theme.ts:sync 刷新至 20261006-2013-75c1d10 并补回本仓唯一允许适配(顶部 // @ts-nocheck,strict vue-tsc 契约);typecheck 零错误
2026-10-06 20:22:02 +08:00

130 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="main-wrapper">
<div class="main-container">
<div class="search-wrap fix">
<span class="tip">路由注册表(open_api_route):治理旋钮行内编辑,保存后网关热重载,无须重启。qps&gt;0 时按 调用方×本行 限流(超限裸 429,0=不限);timeout/bodyLimit 立即生效。</span>
<Button type="primary" class="fr" @click="refresh">刷新</Button>
</div>
<TablePageAlovaNew ref="tableRef" :dataApi="tableApi" :columns="columns" :tableHeight="tableHeight">
<template #visibility="{ row }">
<Select v-model="row.visibility" size="small" style="width: 110px">
<Option value="INTERNAL">INTERNAL</Option>
<Option value="EXTERNAL">EXTERNAL</Option>
</Select>
</template>
<template #authMode="{ row }">
<Select v-model="row.authMode" size="small" style="width: 120px">
<Option value="SIGNED">SIGNED</Option>
<Option value="ANON">ANON</Option>
</Select>
</template>
<template #cacheTtlSeconds="{ row }">
<Input v-model="row.cacheTtlSeconds" type="number" size="small" style="width: 80px" />
</template>
<template #cacheScope="{ row }">
<Select v-model="row.cacheScope" size="small" style="width: 100px">
<Option value="CALLER">CALLER</Option>
<Option value="GLOBAL">GLOBAL</Option>
</Select>
</template>
<template #rateLimitQps="{ row }">
<Input v-model="row.rateLimitQps" type="number" size="small" style="width: 80px" />
</template>
<template #timeoutMs="{ row }">
<Input v-model="row.timeoutMs" type="number" size="small" style="width: 90px" placeholder="1000-120000" />
</template>
<template #requestBodyLimitMb="{ row }">
<Input v-model="row.requestBodyLimitMb" type="number" size="small" style="width: 90px" placeholder="1-100" />
</template>
<template #enabled="{ row }">
<i-switch v-model="row.enabled" size="small" />
</template>
<template #remark="{ row }">
<Input v-model="row.remark" size="small" placeholder="-" />
</template>
<template #action="{ row }">
<Button type="primary" size="small" :loading="savingId === row.id" @click="save(row)">保存</Button>
</template>
</TablePageAlovaNew>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import useCurrentInstance from '@/utils/hook/useCurrentInstance';
import TablePageAlovaNew from '@/components/TablePageAlovaNew.vue';
defineOptions({ name: 'RouteList' });
const { $utils } = useCurrentInstance();
const tableRef = ref<InstanceType<typeof TablePageAlovaNew> | null>(null);
const savingId = ref<number | null>(null);
const tableApi = (params: { pageIndex: number; pageSize: number }) =>
Apis.GatewayAdmin.routes({ params, cacheFor: null });
const tableHeight = ref($utils.useTableHeight({ isOperat: false, isPage: true, isSearch: true }));
const columns = [
{ title: 'id', key: 'id', width: 70, align: 'center' },
{ title: 'target', key: 'targetCode', width: 120, ellipsis: true, tooltip: true },
{ title: 'path', key: 'pathPattern', minWidth: 200, ellipsis: true, tooltip: true },
{ title: 'method', key: 'httpMethod', width: 90, align: 'center' },
{ title: 'visibility', slot: 'visibility', width: 130 },
{ title: 'authMode', slot: 'authMode', width: 140 },
{ title: 'cacheTtl(s)', slot: 'cacheTtlSeconds', width: 105 },
{ title: 'cacheScope', slot: 'cacheScope', width: 120 },
{ title: 'qps', slot: 'rateLimitQps', width: 90 },
{ title: 'timeout(ms)', slot: 'timeoutMs', width: 115, align: 'right' },
{ title: 'bodyLimit(mb)', slot: 'requestBodyLimitMb', width: 125, align: 'right' },
{ title: '启用', slot: 'enabled', width: 80, align: 'center' },
{ title: '备注', slot: 'remark', minWidth: 160 },
{ title: '操作', slot: 'action', width: 90, align: 'center', fixed: 'right' as const },
];
function refresh() {
tableRef.value?.refreshData();
}
/** 只提交治理字段(target/pattern/method 是路由身份,后端不接受改动) */
async function save(row: any) {
savingId.value = row.id;
try {
const d: any = await Apis.GatewayAdmin.updateRoute({
pathParams: { id: row.id },
data: {
visibility: row.visibility,
authMode: row.authMode,
cacheTtlSeconds: Number(row.cacheTtlSeconds) || 0,
cacheScope: row.cacheScope,
rateLimitQps: Number(row.rateLimitQps) || 0,
timeoutMs: Number(row.timeoutMs) || 30000,
requestBodyLimitMb: Number(row.requestBodyLimitMb) || 10,
enabled: row.enabled,
remark: row.remark,
},
});
Message.success(`已保存,注册表加载 ${d?.loaded ?? '-'} 条路由`);
} catch (e: any) {
// 错误提示由 alova 全局 onBizError 弹出,这里只做回滚,避免双 toast
tableRef.value?.refreshData();
} finally {
savingId.value = null;
}
}
</script>
<style lang="scss" scoped>
.search-wrap {
line-height: 32px;
.tip {
color: #848c98;
font-size: 13px;
}
}
</style>