feat(Auth): Compete auth-middleware
This commit is contained in:
parent
07143e2048
commit
d167cb7265
11
composables/user.ts
Normal file
11
composables/user.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export async function getUserId() {
|
||||
const auth = useCookie("auth");
|
||||
return await $fetch("/api/user/auth", {
|
||||
method: "GET",
|
||||
query: {
|
||||
auth: auth.value,
|
||||
},
|
||||
}).then((res: number) => {
|
||||
return res;
|
||||
});
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
if ((await getUserId()) != 1) {
|
||||
ElMessage("禁止访问");
|
||||
return navigateTo("/", { replace: true });
|
||||
}
|
||||
});
|
@ -4,24 +4,24 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
ElMessage("未登录或cookie未开启");
|
||||
return navigateTo("/user/login", { replace: true });
|
||||
} else {
|
||||
const { data: result } = await useFetch("/api/user/auth", {
|
||||
const result = await $fetch("/api/user/auth", {
|
||||
method: "post",
|
||||
body: {
|
||||
auth: auth.value,
|
||||
},
|
||||
});
|
||||
if (!result.value?.login && to.path !== "/user/test") {
|
||||
if (result.value?.code == 0) {
|
||||
if (!result.login && to.path !== "/user/test") {
|
||||
if (result.code == 0) {
|
||||
ElMessage("未登录");
|
||||
} else if (result.value?.code == 2) {
|
||||
} else if (result.code == 2) {
|
||||
ElMessage("登录超时,请重新登录");
|
||||
auth.value = undefined;
|
||||
} else {
|
||||
ElMessage(result.value?.code);
|
||||
ElMessage("error" + result.code);
|
||||
}
|
||||
return navigateTo("/user/login");
|
||||
} else {
|
||||
console.log(auth.value);
|
||||
//console.log(auth.value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -5,26 +5,26 @@
|
||||
</Head>
|
||||
<client-only>
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="appid" label="AppID" width="180" />
|
||||
<el-table-column prop="name" label="申请人" width="180" />
|
||||
<el-table-column prop="phone" label="手机号" width="180" />
|
||||
<el-table-column prop="id" label="AppID" width="180" />
|
||||
<el-table-column prop="applicant" label="申请人" width="180" />
|
||||
<el-table-column prop="area" label="地区" width="180" />
|
||||
<el-table-column label="配置" width="300">
|
||||
<template #default="scope">
|
||||
<el-icon color="blue"><ElIcon-Cpu /></el-icon>
|
||||
{{ scope.row.resource.cpu }} Core
|
||||
{{ scope.row.cpu }} Core
|
||||
<el-icon color="green"><ElIcon-Stopwatch /></el-icon
|
||||
>{{ scope.row.resource.ram }} GB
|
||||
>{{ scope.row.ram }} GB
|
||||
<el-icon color="gray"><ElIcon-Memo /></el-icon>
|
||||
{{ scope.row.resource.disk }} GB
|
||||
{{ scope.row.disk }} GB
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="usage" label="用途" width="360" />
|
||||
<el-table-column prop="desc" label="用途" width="360" />
|
||||
<el-table-column label="状态" width="300">
|
||||
<template #default="scope">
|
||||
<el-icon :color="scope.row.apply ? 'green' : 'orange'"
|
||||
<el-icon :color="scope.row.deploy ? 'green' : 'orange'"
|
||||
><ElIcon-Stamp
|
||||
/></el-icon>
|
||||
{{ scope.row.apply ? "通过" : "待审核" }}
|
||||
{{ scope.row.deploy ? "通过" : "待审核" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
@ -49,30 +49,7 @@
|
||||
</client-only>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
const tableData = [
|
||||
{
|
||||
appid: "1",
|
||||
name: "漩葵",
|
||||
phone: 1922949224,
|
||||
usage: "用于开展服务",
|
||||
resource: {
|
||||
cpu: 1,
|
||||
ram: 2,
|
||||
disk: 10,
|
||||
},
|
||||
apply: false,
|
||||
},
|
||||
{
|
||||
appid: "2",
|
||||
name: "BrianLing",
|
||||
phone: 1922949224,
|
||||
usage: "用于开展服务",
|
||||
resource: {
|
||||
cpu: 1,
|
||||
ram: 2,
|
||||
disk: 10,
|
||||
},
|
||||
apply: true,
|
||||
},
|
||||
];
|
||||
import type { Application } from "~/types/Application";
|
||||
const data: Application[] = await $fetch("/api/admin/applications");
|
||||
const tableData = ref(data);
|
||||
</script>
|
||||
|
@ -12,6 +12,7 @@
|
||||
>
|
||||
<ClientOnly>
|
||||
<Vueform
|
||||
@success="AppSuccess"
|
||||
endpoint="/api/test"
|
||||
method="POST"
|
||||
view="tabs"
|
||||
@ -28,49 +29,67 @@
|
||||
label="项目名称"
|
||||
placeholder="项目名称"
|
||||
:columns="{ container: 4, label: 4, wrapper: 12 }"
|
||||
rules="required"
|
||||
:rules="['required', isCreate]"
|
||||
/>
|
||||
<SelectElement
|
||||
name="select"
|
||||
default="辽宁一区"
|
||||
name="area"
|
||||
default="1"
|
||||
label="地区"
|
||||
:native="false"
|
||||
:items="['辽宁一区', '辽宁二区', '江西一区']"
|
||||
:items="{ 1: '辽宁一区', 2: '辽宁二区', 3: '江西一区' }"
|
||||
:columns="{ container: 4, label: 3, wrapper: 12 }"
|
||||
rules="required"
|
||||
/>
|
||||
<RadiogroupElement
|
||||
default="2 Core"
|
||||
default="2"
|
||||
label="CPU核心数"
|
||||
name="cpu"
|
||||
:items="['2 Core', '4 Core', '6 Core', 'More']"
|
||||
:items="{ 2: '2 Core', 4: '4 Core', 6: '6 Core', 10: 'More' }"
|
||||
view="tabs"
|
||||
/>
|
||||
<RadiogroupElement
|
||||
default="2 GB"
|
||||
default="2"
|
||||
label="RAM容量"
|
||||
name="ram"
|
||||
:items="['2 GB', '4 GB', '6 GB', 'More']"
|
||||
:items="{ 2: '2 GB', 4: '4 GB', 6: '6 GB', 10: 'More' }"
|
||||
view="tabs"
|
||||
/>
|
||||
|
||||
<SliderElement
|
||||
sync
|
||||
name="disk"
|
||||
label="磁盘容量"
|
||||
:default="5"
|
||||
:min="1"
|
||||
:max="40"
|
||||
:format="(v: number) => v > 1 ? `${Math.round(v)} GB` : '1 GB'"
|
||||
:columns="{ container: 12, label: 12, wrapper: 12 }"
|
||||
:add-classes="{
|
||||
ElementLayout: {
|
||||
innerWrapper: 'mt-12',
|
||||
},
|
||||
}"
|
||||
/>
|
||||
|
||||
<EditorElement name="usage" label="用途说明" rules="required|max:500" />
|
||||
|
||||
<EditorElement
|
||||
name="desc"
|
||||
label="用途说明"
|
||||
rules="required|max:500"
|
||||
:hide-tools="['attach']"
|
||||
/>
|
||||
<StaticElement
|
||||
label="人机验证"
|
||||
name="static"
|
||||
:columns="{ container: 12, label: 12, wrapper: 12 }"
|
||||
>
|
||||
<DefaultSilderVerify
|
||||
@success="sliderHandleSuccess"
|
||||
@failed="sliderHandleError"
|
||||
/>
|
||||
</StaticElement>
|
||||
<HiddenElement :default="uid" name="uid" />
|
||||
<HiddenElement :default="auth" name="auth" />
|
||||
<ButtonElement
|
||||
:disabled="isBot"
|
||||
name="submit"
|
||||
button-label="提交申请"
|
||||
align="center"
|
||||
@ -82,9 +101,43 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import PhoneElemen from "@vueform/vueform";
|
||||
import { Validator } from "@vueform/vueform";
|
||||
definePageMeta({
|
||||
middleware: ["auth"],
|
||||
});
|
||||
const uid: number = await getUserId();
|
||||
const isBot = ref(true);
|
||||
const auth = useCookie("auth");
|
||||
function sliderHandleSuccess() {
|
||||
ElMessage({ message: "人机验证已通过", type: "success" });
|
||||
isBot.value = false;
|
||||
}
|
||||
function sliderHandleError() {
|
||||
ElMessage({ message: "人机验证未通过", type: "warning" });
|
||||
}
|
||||
const isCreate = class extends Validator {
|
||||
get msg() {
|
||||
return "项目名已存在";
|
||||
}
|
||||
check(value: string) {
|
||||
if (value == "") {
|
||||
return 0;
|
||||
}
|
||||
return $fetch("/api/application", {
|
||||
method: "POST",
|
||||
body: { name: value },
|
||||
}).then((res) => {
|
||||
return res.name;
|
||||
});
|
||||
}
|
||||
};
|
||||
const form = ref();
|
||||
function AppSuccess(response: { data: { code: number; msg: string } }) {
|
||||
if (response.data.code) {
|
||||
ElMessage({ message: response.data.msg, type: "success" });
|
||||
navigateTo("/");
|
||||
} else {
|
||||
ElMessage({ message: response.data.msg, type: "warning" });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -4,10 +4,12 @@
|
||||
<Title>FreePotato Server</Title>
|
||||
<Meta name="description" content="免费服务器~" />
|
||||
</Head>
|
||||
|
||||
<ElRow :gutter="10" align="middle" style="height: 900px">
|
||||
<ElCol :span="24"><IndexNewsCarouel /></ElCol>
|
||||
<ElCol :span="24"><IndexNewsStatus /></ElCol>
|
||||
</ElRow>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
const a = await getUserId();
|
||||
console.info(a);
|
||||
</script>
|
||||
|
@ -1,11 +1,63 @@
|
||||
<template>
|
||||
<Head>
|
||||
<Title>用户信息</Title>
|
||||
<Title>个人界面</Title>
|
||||
<Meta name="description" />
|
||||
</Head>
|
||||
<client-only>
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="id" label="AppID" width="180" />
|
||||
<el-table-column prop="applicant" label="申请人" width="180" />
|
||||
<el-table-column prop="area" label="地区" width="180" />
|
||||
<el-table-column label="配置" width="300">
|
||||
<template #default="scope">
|
||||
<el-icon color="blue"><ElIcon-Cpu /></el-icon>
|
||||
{{ scope.row.cpu }} Core
|
||||
<el-icon color="green"><ElIcon-Stopwatch /></el-icon
|
||||
>{{ scope.row.ram }} GB
|
||||
<el-icon color="gray"><ElIcon-Memo /></el-icon>
|
||||
{{ scope.row.disk }} GB
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="desc" label="用途" width="360" />
|
||||
<el-table-column label="状态" width="300">
|
||||
<template #default="scope">
|
||||
<el-icon :color="scope.row.deploy ? 'green' : 'orange'"
|
||||
><ElIcon-Stamp
|
||||
/></el-icon>
|
||||
{{ scope.row.deploy ? "通过" : "待审核" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
size="small"
|
||||
type="success"
|
||||
@click="ElMessage({ message: '查看', type: 'success' })"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="ElMessage({ message: '取消', type: 'warning' })"
|
||||
>
|
||||
取消
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</client-only>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import type { Application } from "~/types/Application";
|
||||
definePageMeta({
|
||||
middleware: ["auth"],
|
||||
});
|
||||
const data: Application[] = await $fetch("/api/user/application", {
|
||||
method: "POST",
|
||||
body: {
|
||||
uid: await getUserId(),
|
||||
},
|
||||
});
|
||||
const tableData = ref(data);
|
||||
</script>
|
||||
|
113
prisma/test.prisma
Normal file
113
prisma/test.prisma
Normal file
@ -0,0 +1,113 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
binaryTargets = ["native", "debian-openssl-3.0.x"]
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
phone String @unique
|
||||
username String?
|
||||
password String
|
||||
applications Application[]
|
||||
loginlogs Loginlogs[]
|
||||
Vm Vm[]
|
||||
}
|
||||
|
||||
model Adminer {
|
||||
id Int @id @default(autoincrement())
|
||||
adminId Int
|
||||
}
|
||||
|
||||
model Application {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
area String
|
||||
cpu Int
|
||||
ram Int
|
||||
disk Int
|
||||
desc String
|
||||
deploy Boolean @default(false)
|
||||
applicant User @relation(fields: [applicantId], references: [id])
|
||||
applicantId Int
|
||||
}
|
||||
model Register {
|
||||
id Int @id @default(autoincrement())
|
||||
phone String
|
||||
deadline DateTime
|
||||
code String
|
||||
}
|
||||
model Loginlogs {
|
||||
id Int @id @default(autoincrement())
|
||||
outtime DateTime
|
||||
ip String
|
||||
loginer User @relation(fields: [userid], references: [id])
|
||||
userid Int
|
||||
token String @unique
|
||||
}
|
||||
//Config
|
||||
model Web {
|
||||
ConfigId Int @id
|
||||
ConfigName String
|
||||
ConfigValue String
|
||||
}
|
||||
model Cluster {
|
||||
ClusterId Int @id
|
||||
Name String
|
||||
Ip String
|
||||
Username String
|
||||
Password String
|
||||
Gateway String
|
||||
Resource String
|
||||
Status String
|
||||
Nodes Node[]
|
||||
}
|
||||
model Node {
|
||||
NodeId Int @id
|
||||
Cluster Cluster @relation(fields: [ClusterId], references: [ClusterId])
|
||||
ClusterId Int
|
||||
Resource String
|
||||
Status String
|
||||
Vms Vm[]
|
||||
}
|
||||
model Template {
|
||||
TemplateId Int @id @default(autoincrement())
|
||||
OS String
|
||||
Type String
|
||||
Path String
|
||||
Cpu String
|
||||
Ram String
|
||||
Disk String
|
||||
Ports String
|
||||
Vm Vm[]
|
||||
}
|
||||
//datasource
|
||||
model Ip {
|
||||
Adress String @id
|
||||
Vmid Int
|
||||
Vm Vm @relation(fields: [Vmid], references: [Vmid])
|
||||
}
|
||||
model Port {
|
||||
Port Int @id
|
||||
Vmid Int
|
||||
Vm Vm @relation(fields: [Vmid], references: [Vmid])
|
||||
}
|
||||
model Vm {
|
||||
Vmid Int @id @default(autoincrement())
|
||||
NodeId Int
|
||||
Node Node @relation(fields: [NodeId], references: [NodeId])
|
||||
TemplateId Int
|
||||
Template Template @relation(fields: [TemplateId], references: [TemplateId])
|
||||
UserId Int
|
||||
User User @relation(fields: [UserId], references: [id])
|
||||
Ip Ip[]
|
||||
SshPort Int
|
||||
Ports Port[]
|
||||
}
|
51
server/api/admin/applications.ts
Normal file
51
server/api/admin/applications.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import type { Application } from "~/types/Application";
|
||||
const db = new PrismaClient();
|
||||
type app = {
|
||||
applicant: {
|
||||
username: string | null;
|
||||
};
|
||||
} & {
|
||||
id: number;
|
||||
name: string;
|
||||
area: string;
|
||||
cpu: number;
|
||||
ram: number;
|
||||
disk: number;
|
||||
desc: string;
|
||||
deploy: boolean;
|
||||
applicantId: number;
|
||||
};
|
||||
function formatApplication(raw: app[]): Application[] {
|
||||
var logs: Application[] = [];
|
||||
raw.forEach((element: app) => {
|
||||
logs.push({
|
||||
id: element.id,
|
||||
area: element.area,
|
||||
name: element.name,
|
||||
applicant: element.applicant.username || "none",
|
||||
cpu: element.cpu,
|
||||
ram: element.ram,
|
||||
disk: element.disk,
|
||||
desc: element.desc,
|
||||
deploy: element.deploy,
|
||||
});
|
||||
});
|
||||
return logs;
|
||||
}
|
||||
export default defineEventHandler(async (event) => {
|
||||
const applications = await db.application.findMany({
|
||||
orderBy: {
|
||||
id: "desc", // 'asc' 表示升序,'desc' 表示降序
|
||||
},
|
||||
include: {
|
||||
applicant: {
|
||||
select: {
|
||||
username: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await db.$disconnect();
|
||||
return formatApplication(applications);
|
||||
});
|
6
server/api/application/create.post.ts
Normal file
6
server/api/application/create.post.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
const db = new PrismaClient();
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
return body;
|
||||
});
|
15
server/api/application/index.ts
Normal file
15
server/api/application/index.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
const db = new PrismaClient();
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
const res = {
|
||||
name:
|
||||
(await db.application.findFirst({
|
||||
where: {
|
||||
name: body.name,
|
||||
},
|
||||
})) == null,
|
||||
};
|
||||
await db.$disconnect();
|
||||
return res;
|
||||
});
|
@ -1,7 +1,66 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const db = new PrismaClient();
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body: {
|
||||
name: string;
|
||||
area: string;
|
||||
cpu: string;
|
||||
ram: string;
|
||||
disk: string;
|
||||
desc: string;
|
||||
uid: string;
|
||||
auth: string;
|
||||
} = await readBody(event);
|
||||
const isAuth: { login: boolean; code: number } = await $fetch(
|
||||
"/api/user/auth",
|
||||
{
|
||||
method: "POST",
|
||||
body: {
|
||||
auth: body.auth,
|
||||
},
|
||||
}
|
||||
);
|
||||
if (isAuth.login) {
|
||||
await db.application.create({
|
||||
data: {
|
||||
name: body.name,
|
||||
area: body.area,
|
||||
cpu: parseInt(body.cpu),
|
||||
ram: parseInt(body.ram),
|
||||
disk: parseInt(body.disk),
|
||||
desc: body.desc,
|
||||
applicantId: parseInt(body.uid),
|
||||
},
|
||||
});
|
||||
|
||||
export default defineEventHandler((event) => {
|
||||
return event;
|
||||
await db.$disconnect();
|
||||
return {
|
||||
code: 1,
|
||||
msg: "申请提交成功",
|
||||
};
|
||||
} else {
|
||||
if (isAuth.code == 0) {
|
||||
console.error(isAuth);
|
||||
console.error(JSON.stringify(body));
|
||||
return {
|
||||
code: 0,
|
||||
msg: "未登录",
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
code: 0,
|
||||
msg: "登陆超时",
|
||||
};
|
||||
}
|
||||
}
|
||||
return body;
|
||||
});
|
||||
|
||||
/* { name: '1231',
|
||||
area: '1',
|
||||
cpu: '2',
|
||||
ram: '2',
|
||||
disk: '5',
|
||||
desc: '<div>12313</div>',
|
||||
uid: '1',
|
||||
auth: 'a19705902b2ba12fbe52930b34802ab1' } */
|
||||
|
55
server/api/user/application.post.ts
Normal file
55
server/api/user/application.post.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import type { Application } from "~/types/Application";
|
||||
const db = new PrismaClient();
|
||||
type app = {
|
||||
applicant: {
|
||||
username: string | null;
|
||||
};
|
||||
} & {
|
||||
id: number;
|
||||
name: string;
|
||||
area: string;
|
||||
cpu: number;
|
||||
ram: number;
|
||||
disk: number;
|
||||
desc: string;
|
||||
deploy: boolean;
|
||||
applicantId: number;
|
||||
};
|
||||
function formatApplication(raw: app[]): Application[] {
|
||||
var logs: Application[] = [];
|
||||
raw.forEach((element: app) => {
|
||||
logs.push({
|
||||
id: element.id,
|
||||
area: element.area,
|
||||
name: element.name,
|
||||
applicant: element.applicant.username || "none",
|
||||
cpu: element.cpu,
|
||||
ram: element.ram,
|
||||
disk: element.disk,
|
||||
desc: element.desc,
|
||||
deploy: element.deploy,
|
||||
});
|
||||
});
|
||||
return logs;
|
||||
}
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
const applications = await db.application.findMany({
|
||||
where: {
|
||||
applicantId: body.uid,
|
||||
},
|
||||
orderBy: {
|
||||
id: "desc", // 'asc' 表示升序,'desc' 表示降序
|
||||
},
|
||||
include: {
|
||||
applicant: {
|
||||
select: {
|
||||
username: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await db.$disconnect();
|
||||
return formatApplication(applications);
|
||||
});
|
23
server/api/user/auth.get.ts
Normal file
23
server/api/user/auth.get.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const db = new PrismaClient();
|
||||
export default defineEventHandler(async (event) => {
|
||||
const query: { auth: string } = getQuery(event);
|
||||
let userid: number = 0;
|
||||
userid = await db.loginlogs
|
||||
.findFirst({
|
||||
where: { token: query.auth },
|
||||
select: {
|
||||
userid: true,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (res != null) {
|
||||
return res.userid;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
//console.info(userid);
|
||||
return userid;
|
||||
});
|
@ -4,7 +4,7 @@ const db = new PrismaClient();
|
||||
|
||||
async function auth(auth: string) {
|
||||
const res = await db.loginlogs.findFirst({
|
||||
where: { token: auth.toString() },
|
||||
where: { token: auth },
|
||||
});
|
||||
//return JSON.stringify((await res).values)
|
||||
if (res == null) {
|
||||
|
@ -1,9 +1,11 @@
|
||||
export type Application = {
|
||||
name: string
|
||||
area: string
|
||||
cpu: number
|
||||
ram: number
|
||||
disk: number
|
||||
usage: string
|
||||
applicantId: number
|
||||
}
|
||||
id: number;
|
||||
name: string;
|
||||
area: string;
|
||||
cpu: number;
|
||||
ram: number;
|
||||
disk: number;
|
||||
desc: string;
|
||||
applicant: string;
|
||||
deploy: boolean;
|
||||
};
|
||||
|
1
types/Application/index.d.ts
vendored
Normal file
1
types/Application/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export { Application } from "./Application.ts";
|
Loading…
Reference in New Issue
Block a user