feat(.): Achieve the basis layout and features
This commit is contained in:
parent
62b35f5647
commit
c0879f1ec2
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
# Nuxt dev/build outputs
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
demo.tar.gz
|
||||
FreePS.service
|
||||
run
|
||||
.vscode
|
||||
prisma/migrations
|
||||
prisma/SQLite
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.fleet
|
||||
.idea
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
75
README.md
Normal file
75
README.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Nuxt 3 Minimal Starter
|
||||
|
||||
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install the dependencies:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm run dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm run build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm run preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
12
app.vue
Normal file
12
app.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
// 作为字符串,
|
||||
// 其中`%s`会被标题替换
|
||||
titleTemplate: '%s - 免费的服务器'
|
||||
})
|
||||
</script>
|
13
components/Default/Footer.vue
Normal file
13
components/Default/Footer.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template slot-scope>
|
||||
<el-row>
|
||||
<el-col :span="8"></el-col>
|
||||
<el-col class="copyright" :span="8">Copyright© BrianLing</el-col>
|
||||
<el-col :span="8"></el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.copyright{
|
||||
text-align:center;
|
||||
}
|
||||
</style>
|
53
components/Default/Header.vue
Normal file
53
components/Default/Header.vue
Normal file
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<client-only>
|
||||
<el-menu
|
||||
:default-active="activeIndex"
|
||||
mode="horizontal"
|
||||
:ellipsis="false"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-menu-item index="/">
|
||||
<img
|
||||
style="width: 50px;"
|
||||
src="/logo.svg"
|
||||
alt="Element logo"
|
||||
/>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/apply">立即申请</el-menu-item>
|
||||
<el-menu-item index="/about">关于我们</el-menu-item>
|
||||
<el-menu-item index="/status" disabled>设备监控</el-menu-item>
|
||||
<el-sub-menu index="/area" disabled>
|
||||
<template #title>区域服务</template>
|
||||
<!-- <el-menu-item index="/area/ln1">辽宁一区</el-menu-item>
|
||||
<el-menu-item index="/area/ln2">辽宁二区</el-menu-item>
|
||||
<el-menu-item index="/area/jx1">江西一区</el-menu-item>
|
||||
<el-sub-menu index="/area/jx2">
|
||||
<template #title>江西二区</template>
|
||||
<el-menu-item index="/area/jx2/gpu">GPU服务器</el-menu-item>
|
||||
<el-menu-item index="/area/jx2/web">网页服务器</el-menu-item>
|
||||
<el-menu-item index="/area/jx2/game">游戏服务器</el-menu-item>
|
||||
</el-sub-menu> -->
|
||||
</el-sub-menu>
|
||||
<el-menu-item index="/forum" disabled>论坛</el-menu-item>
|
||||
<el-menu-item index="/host" disabled>托管</el-menu-item>
|
||||
<div class="flex-grow" />
|
||||
<el-menu-item index="/login">登录</el-menu-item>
|
||||
<el-menu-item index="register">注册</el-menu-item>
|
||||
</el-menu>
|
||||
</client-only>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
const activeIndex = ref('1')
|
||||
const handleSelect = (key: string, keyPath: string[]) => {
|
||||
console.log(key, keyPath)
|
||||
navigateTo(key)
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
</style>
|
49
components/Index/News/Carouel.vue
Normal file
49
components/Index/News/Carouel.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template slot-scope>
|
||||
<el-carousel height="300px" motion-blur>
|
||||
<el-carousel-item class="newsShow" v-for="news in newsCovers" :key="news.key" :label="news.name" v-on:click="navigateTo(news.url)">
|
||||
<el-image>
|
||||
<template #placeholder>
|
||||
<ElText type="info">加载中...</ElText>
|
||||
</template>
|
||||
<template #error>
|
||||
<el-icon size="200"><ElIcon-picture /></el-icon>
|
||||
</template>
|
||||
</el-image>
|
||||
<h6>{{news.description}}</h6>
|
||||
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ElText } from 'element-plus'
|
||||
import type { NewsCover } from '~/types/NewsShow';
|
||||
|
||||
const newsCovers:NewsCover[] = [
|
||||
{
|
||||
key:1,
|
||||
name:'Test1',
|
||||
url:'/apply',
|
||||
description:'测试一'
|
||||
},
|
||||
{
|
||||
key:2,
|
||||
name:'Test2',
|
||||
url:'/apply',
|
||||
description:'测试二'
|
||||
},
|
||||
{
|
||||
key:3,
|
||||
name:'Test3',
|
||||
url:'/status',
|
||||
description:'测试三'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
<style>
|
||||
.newsShow {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
77
components/Index/News/Status.vue
Normal file
77
components/Index/News/Status.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<ElRow>
|
||||
<ElCol v-for="item in statusItems" :span="24/cols">
|
||||
<el-statistic style="text-align: center;" :value="item.value">
|
||||
<template #title>
|
||||
<div style="display: inline-flex; align-items: center;text-align: center;">
|
||||
{{ item.name }}
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="item.tips"
|
||||
placement="top"
|
||||
>
|
||||
<el-icon style="margin-left: 4px" :size="12">
|
||||
<ElIcon-warning />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #suffix> {{ item.unit }}</template>
|
||||
</el-statistic>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { StatusItem } from '~/types/NewsShow';
|
||||
|
||||
const cols=3//显示的列数
|
||||
|
||||
const statusItems:StatusItem[] = [
|
||||
{
|
||||
name:'服务器数量',
|
||||
value: 1000,
|
||||
unit:'台',
|
||||
tips:'截至2024'
|
||||
},{
|
||||
name:'用户人数',
|
||||
value: 99,
|
||||
unit:'人',
|
||||
tips:'截至2024'
|
||||
}, {
|
||||
name:'剩余存储',
|
||||
value: 90,
|
||||
unit:'%',
|
||||
tips:'截至2024'
|
||||
},{
|
||||
name:'服务器数量',
|
||||
value: 1000,
|
||||
unit:'台',
|
||||
tips:'截至2024'
|
||||
},{
|
||||
name:'用户人数',
|
||||
value: 99,
|
||||
unit:'人',
|
||||
tips:'截至2024'
|
||||
}, {
|
||||
name:'剩余存储',
|
||||
value: 90,
|
||||
unit:'%',
|
||||
tips:'截至2024'
|
||||
},{
|
||||
name:'服务器数量',
|
||||
value: 1000,
|
||||
unit:'台',
|
||||
tips:'截至2024'
|
||||
},{
|
||||
name:'用户人数',
|
||||
value: 99,
|
||||
unit:'人',
|
||||
tips:'截至2024'
|
||||
}, {
|
||||
name:'剩余存储',
|
||||
value: 90,
|
||||
unit:'%',
|
||||
tips:'截至2024'
|
||||
}
|
||||
]
|
||||
</script>
|
24
layouts/default.vue
Normal file
24
layouts/default.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="common-layout">
|
||||
<el-container>
|
||||
<el-header>
|
||||
<DefaultHeader/>
|
||||
</el-header>
|
||||
|
||||
<el-main>
|
||||
<slot />
|
||||
</el-main>
|
||||
|
||||
<el-footer>
|
||||
<DefaultFooter/>
|
||||
</el-footer>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
|
||||
useHead({
|
||||
meta: [{ property: 'title', content: `应用名称 - ${route.meta.title}` }]
|
||||
})
|
||||
</script>
|
8
nuxt.config.ts
Normal file
8
nuxt.config.ts
Normal file
@ -0,0 +1,8 @@
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
devtools: { enabled: true },
|
||||
modules: [
|
||||
"@element-plus/nuxt",
|
||||
'@vueform/nuxt'
|
||||
],
|
||||
})
|
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "FreePs",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/nuxt": "^1.0.9",
|
||||
"@prisma/client": "5.15.0",
|
||||
"@vueform/nuxt": "^1.6.0",
|
||||
"@vueform/plugin-mask": "^1.0.5",
|
||||
"element-plus": "^2.7.4",
|
||||
"nuxt": "^3.11.2",
|
||||
"prisma": "^5.15.0",
|
||||
"typescript": "^5.4.5",
|
||||
"vue": "^3.4.27",
|
||||
"vue-router": "^4.3.2"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
15
pages/about/index.vue
Normal file
15
pages/about/index.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<!--关于我们页面-->
|
||||
<Head>
|
||||
<Title>关于我们</Title>
|
||||
<Meta name="description"/>
|
||||
</Head>
|
||||
<div>
|
||||
<el-text class="mx-1" type="primary" >
|
||||
Primary
|
||||
</el-text>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
70
pages/apply/index.vue
Normal file
70
pages/apply/index.vue
Normal file
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<!--立即申请页面-->
|
||||
<Head>
|
||||
<Title>立即申请</Title>
|
||||
<Meta name="description"/>
|
||||
</Head>
|
||||
<div style="width:50%;margin:auto;" :style="{
|
||||
boxShadow: `var(--el-box-shadow-dark)`,
|
||||
}">
|
||||
<ClientOnly >
|
||||
<Vueform view="tabs" style="padding:20px" >
|
||||
<TextElement name="username" label="昵称" placeholder="昵称" :columns="{ container: 4, label: 3, wrapper: 12 }"/>
|
||||
<PhoneElement name="phone" allow-incomplete unmask default="+86" :include="['cn']" label="手机号" placeholder="+86" :columns="{ container: 12, label: 1, wrapper: 3 }" />
|
||||
<TextElement name="code" label="验证码" placeholder="xxxxxx" :columns="{ container: 3, label: 4, wrapper: 12 }" />
|
||||
<ButtonElement name="button" :columns="{ container: 2, label: 3, wrapper: 12 }" button-label="发送验证码"/>
|
||||
<SelectElement
|
||||
name="select"
|
||||
default="辽宁一区"
|
||||
label="地区"
|
||||
:native="false"
|
||||
:items="[
|
||||
'辽宁一区',
|
||||
'辽宁二区',
|
||||
'江西一区',
|
||||
]"
|
||||
:columns="{ container: 4, label: 3, wrapper: 12 }"
|
||||
/>
|
||||
<RadiogroupElement
|
||||
default="2 Core"
|
||||
label="CPU核心数"
|
||||
name="cpu"
|
||||
:items="['2 Core', '4 Core', '6 Core','More']"
|
||||
view="tabs"
|
||||
/>
|
||||
<RadiogroupElement
|
||||
default="2 GB"
|
||||
label="RAM容量"
|
||||
name="ram"
|
||||
:items="['2 GB', '4 GB', '6 GB','More']"
|
||||
view="tabs"
|
||||
/>
|
||||
|
||||
<SliderElement
|
||||
name="hhd"
|
||||
label="磁盘容量"
|
||||
:default="5"
|
||||
:min="1"
|
||||
:max="40"
|
||||
:format="(v: number) => v > 1 ? `${Math.round(v)} GB` : '1 GB'"
|
||||
:add-classes="{
|
||||
ElementLayout: {
|
||||
innerWrapper: 'mt-12'
|
||||
}
|
||||
}"
|
||||
/>
|
||||
|
||||
<EditorElement
|
||||
name="usage"
|
||||
label="用途说明"
|
||||
rules="required|max:500"
|
||||
/>
|
||||
|
||||
<ButtonElement name="submit" button-label="提交申请" align="center" size="lg" submits/>
|
||||
</Vueform>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import PhoneElemen from '@vueform/vueform'
|
||||
</script>
|
15
pages/area/index.vue
Normal file
15
pages/area/index.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<!--区域服务页面-->
|
||||
<Head>
|
||||
<Title>区域服务</Title>
|
||||
<Meta name="description"/>
|
||||
</Head>
|
||||
<div>
|
||||
<el-text class="mx-1" type="primary" >
|
||||
Primary
|
||||
</el-text>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
14
pages/index.vue
Normal file
14
pages/index.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<template slot-scope><!--主页面-->
|
||||
<Head>
|
||||
<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>
|
15
pages/login/index.vue
Normal file
15
pages/login/index.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<!--登录界面-->
|
||||
<Head>
|
||||
<Title>登录界面</Title>
|
||||
<Meta name="description"/>
|
||||
</Head>
|
||||
<div>
|
||||
<el-text class="mx-1" type="primary" >
|
||||
Primary
|
||||
</el-text>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
15
pages/register/index.vue
Normal file
15
pages/register/index.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<!--注册页面-->
|
||||
<Head>
|
||||
<Title>注册页面</Title>
|
||||
<Meta name="description"/>
|
||||
</Head>
|
||||
<div>
|
||||
<el-text class="mx-1" type="primary" >
|
||||
Primary
|
||||
</el-text>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
15
pages/status/index.vue
Normal file
15
pages/status/index.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<!--设备监控页面-->
|
||||
<Head>
|
||||
<Title>设备状态</Title>
|
||||
<Meta name="description" :content="title" />
|
||||
</Head>
|
||||
<div>
|
||||
<el-text class="mx-1" type="primary" >
|
||||
Primary
|
||||
</el-text>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
32
prisma/schema.prisma
Normal file
32
prisma/schema.prisma
Normal file
@ -0,0 +1,32 @@
|
||||
// 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"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
phone String @unique
|
||||
username String?
|
||||
password String
|
||||
applications Application[]
|
||||
}
|
||||
|
||||
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
|
||||
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
2931
public/logo.svg
Normal file
2931
public/logo.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 220 KiB |
7
server/api/test/index.ts
Normal file
7
server/api/test/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const db = new PrismaClient()
|
||||
|
||||
export default defineEventHandler((event) => {
|
||||
return 'Hello World!'
|
||||
})
|
3
server/tsconfig.json
Normal file
3
server/tsconfig.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../.nuxt/tsconfig.server.json"
|
||||
}
|
4
tsconfig.json
Normal file
4
tsconfig.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
}
|
3
types/Application/Application.ts
Normal file
3
types/Application/Application.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export type Application = {
|
||||
|
||||
}
|
0
types/Application/idnex.ts
Normal file
0
types/Application/idnex.ts
Normal file
6
types/NewsShow/NewsCover.ts
Normal file
6
types/NewsShow/NewsCover.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type NewsCover = {
|
||||
key:number,
|
||||
name: string
|
||||
url: string
|
||||
description: string
|
||||
}
|
6
types/NewsShow/StatusItem.ts
Normal file
6
types/NewsShow/StatusItem.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type StatusItem = {
|
||||
name:string
|
||||
value:number
|
||||
unit?:string
|
||||
tips:string
|
||||
}
|
2
types/NewsShow/index.d.ts
vendored
Normal file
2
types/NewsShow/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export { NewsCover } from './NewsCover'
|
||||
export { StatusItem } from './StatusItem'
|
15
vueform.config.ts
Normal file
15
vueform.config.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// vueform.config.(js|ts)
|
||||
|
||||
import en from '@vueform/vueform/locales/en'
|
||||
import zh_CN from '@vueform/vueform/locales/zh_CN'
|
||||
import vueform from '@vueform/vueform/dist/vueform'
|
||||
import { defineConfig } from '@vueform/vueform'
|
||||
|
||||
// You might place these anywhere else in your project
|
||||
import '@vueform/vueform/dist/vueform.css';
|
||||
|
||||
export default defineConfig({
|
||||
theme: vueform,
|
||||
locales: { zh_CN,en },
|
||||
locale: 'zh_CN',
|
||||
})
|
Loading…
Reference in New Issue
Block a user