feat(.): Achieve the basis layout and features

This commit is contained in:
漩葵 2024-06-10 00:04:06 +08:00
parent 62b35f5647
commit c0879f1ec2
30 changed files with 9656 additions and 0 deletions

29
.gitignore vendored Normal file
View 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
View 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
View File

@ -0,0 +1,12 @@
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
<script setup lang="ts">
useHead({
//
// `%s`
titleTemplate: '%s - 免费的服务器'
})
</script>

View 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>

View 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>

View 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>

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

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
View 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
View File

@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

4
tsconfig.json Normal file
View File

@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}

View File

@ -0,0 +1,3 @@
export type Application = {
}

View File

View File

@ -0,0 +1,6 @@
export type NewsCover = {
key:number,
name: string
url: string
description: string
}

View 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
View File

@ -0,0 +1,2 @@
export { NewsCover } from './NewsCover'
export { StatusItem } from './StatusItem'

15
vueform.config.ts Normal file
View 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',
})

6123
yarn.lock Normal file

File diff suppressed because it is too large Load Diff