All checks were successful
Gitea Actions Build / Build (push) Successful in 1m23s
195 lines
6.1 KiB
Vue
195 lines
6.1 KiB
Vue
<template>
|
|
<div>
|
|
<n-tabs v-model:value="tabValue" :bar-width="28" placement="left" style="height: 100%" type="line">
|
|
<n-tab-pane name="api信息" tab="api信息">
|
|
<NCard>
|
|
<div class="title">
|
|
<label class="lable">{{ data?.info.title }}</label>
|
|
<n-tag :bordered="false" style="font-weight: 900" type="success">V{{ data?.info.version }}</n-tag>
|
|
<n-tag :bordered="false" style="font-weight: 900" type="info">openapi-{{ data?.openapi }}</n-tag>
|
|
</div>
|
|
<div style="margin-bottom: 20px">
|
|
<a :href="apiUrl">{{ apiUrl }}</a>
|
|
</div>
|
|
<div style="margin-bottom: 20px">{{ data?.info.summary }}</div>
|
|
<div style="margin-bottom: 20px">{{ data?.info.description }}</div>
|
|
<div><a :href="data?.info.termsOfService">Terms of service</a></div>
|
|
<div>
|
|
<a :href="data?.info.contact?.url">{{ data?.info.contact?.name }} - Website</a>
|
|
</div>
|
|
<div>
|
|
<a :href="data?.info.contact?.url">Send email to {{ data?.info.contact?.name }}</a>
|
|
</div>
|
|
<div>
|
|
<a :href="data?.info.license?.url">{{ data?.info.license?.name }}</a>
|
|
</div>
|
|
<div>
|
|
<a :href="data?.externalDocs?.url">{{ data?.externalDocs?.description }}</a>
|
|
</div>
|
|
</NCard>
|
|
</n-tab-pane>
|
|
<n-tab-pane v-for="(v, k) in tags" :name="k" :tab="k">
|
|
<NCard
|
|
:segmented="{
|
|
content: true,
|
|
footer: 'soft',
|
|
}">
|
|
<template #header>
|
|
<div>
|
|
<label style="font-weight: 700; font-size: 27px">{{ k }}</label>
|
|
</div>
|
|
<div>
|
|
<label style="font-weight: 700; font-size: 20px">{{ v.description }}</label>
|
|
</div>
|
|
</template>
|
|
<n-collapse accordion default-expanded-names="1">
|
|
<template v-for="(v2, k2) in v.data">
|
|
<template v-for="(v3, k3) in v2">
|
|
<OpenApiDocMethod :id="`${k}+${k3}-${k2}`" :type="k3" :url="k2" :data="v3" />
|
|
</template>
|
|
</template>
|
|
</n-collapse>
|
|
</NCard>
|
|
</n-tab-pane>
|
|
<n-tab-pane name="schema" tab="架构">
|
|
<NCard
|
|
:segmented="{
|
|
content: true,
|
|
footer: 'soft',
|
|
}">
|
|
<template #header>
|
|
<div>
|
|
<label style="font-weight: 700; font-size: 27px">架构</label>
|
|
</div>
|
|
<div>
|
|
<label style="font-weight: 700; font-size: 20px">一些类型而已</label>
|
|
</div>
|
|
</template>
|
|
<n-collapse accordion default-expanded-names="2">
|
|
<OpenApiDocSchema :id="`schema+${k}`" v-for="(v, k) in
|
|
data?.components?.schemas"
|
|
:data="v" :name="k" />
|
|
</n-collapse>
|
|
</NCard>
|
|
</n-tab-pane>
|
|
<n-tab-pane name="权限验证" tab="权限验证">
|
|
<NCard
|
|
:segmented="{
|
|
content: true,
|
|
footer: 'soft',
|
|
}">
|
|
<template #header>
|
|
<div>
|
|
<label style="font-weight: 700; font-size: 27px">权限验证</label>
|
|
</div>
|
|
<div>
|
|
<label style="font-weight: 700; font-size: 20px">验证你的权限</label>
|
|
</div>
|
|
</template>
|
|
<n-collapse accordion default-expanded-names="3">
|
|
<OpenApiDocSecuritySchemes v-for="(v, k) in data?.components?.securitySchemes" :data="v" :name="k" />
|
|
</n-collapse>
|
|
</NCard>
|
|
</n-tab-pane>
|
|
</n-tabs>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, type PropType, ref } from 'vue';
|
|
import { NTag } from 'naive-ui';
|
|
import type { OpenAPIV3_1 } from 'openapi-types';
|
|
import OpenApiDocMethod from '@/components/OpenApiDocMethod.vue';
|
|
import { router } from '@/plugin';
|
|
import type { RouteLocationNormalizedGeneric } from 'vue-router';
|
|
import OpenApiDocSchema from '@/components/OpenApiDocSchema.vue';
|
|
import OpenApiDocSecuritySchemes from '@/components/OpenApiDocSecuritySchemes.vue';
|
|
|
|
const data = ref<OpenAPIV3_1.Document>();
|
|
const tags = ref<{
|
|
[key: string]: {
|
|
data: { [key: string]: OpenAPIV3_1.PathItemObject };
|
|
description: string;
|
|
};
|
|
}>({});
|
|
export type TFunctionType = (args: string) => string;
|
|
export type getApiFunType = (args: string) => PromiseLike<string>;
|
|
|
|
onMounted(() => {
|
|
prop
|
|
.getApiFun(prop.apiUrl)
|
|
.then((res) => {
|
|
data.value = JSON.parse(res);
|
|
return data.value;
|
|
})
|
|
.then((res) => {
|
|
for (const pathsKey in res?.paths) {
|
|
const models = res?.paths[pathsKey];
|
|
for (const model in models) {
|
|
for (const i of models[model]?.tags) {
|
|
if (!tags.value[i]) {
|
|
tags.value[i] = {
|
|
data: {},
|
|
description: data.value?.tags?.find((is) => is.name === i)?.description,
|
|
};
|
|
}
|
|
tags.value[i].data[pathsKey] = models;
|
|
}
|
|
}
|
|
}
|
|
})
|
|
.then(() => {
|
|
hashback(router.currentRoute.value);
|
|
});
|
|
});
|
|
|
|
function hashback(to: RouteLocationNormalizedGeneric) {
|
|
if (!to.hash) return;
|
|
const tab = to.hash.split('+')?.[0].replace('#', '');
|
|
setTimeout(() => {
|
|
tabValue.value = tab;
|
|
setTimeout(()=>{
|
|
const ele = document.getElementById(to.hash.replace('#', ''));
|
|
ele?.scrollIntoView();
|
|
const ele2 = ele?.children[0].children[0];
|
|
ele2?.click()
|
|
},100)
|
|
}, 100 );
|
|
}
|
|
|
|
const removeAfterEach = router.afterEach(hashback);
|
|
|
|
onUnmounted(() => removeAfterEach());
|
|
|
|
const tabValue = ref<string>('api信息');
|
|
|
|
const prop = defineProps({
|
|
apiUrl: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
getApiFun: {
|
|
type: Function as PropType<getApiFunType>,
|
|
default: async (url: string) => (await fetch(url)).text(),
|
|
},
|
|
i18nFun: {
|
|
type: Function as PropType<TFunctionType>,
|
|
default: (s: string) => s,
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.lable {
|
|
font-size: 36px;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.title {
|
|
display: flex;
|
|
justify-content: left;
|
|
align-items: flex-start;
|
|
gap: 5px;
|
|
}
|
|
</style>
|