Upload
This commit is contained in:
parent
5cf34df31c
commit
7209b7ee2f
|
@ -1,12 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
<html lang="zh-cn" class="h-full bg-gray-100">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/logo.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DormStar</title>
|
||||
</head>
|
||||
<body>
|
||||
<body class="h-full">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="./src/main.js"></script>
|
||||
</body>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"vue-router": "^4.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@headlessui/vue": "^1.7.16",
|
||||
"@vitejs/plugin-vue": "^4.4.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"postcss": "^8.4.31",
|
||||
|
|
|
@ -15,6 +15,13 @@ const router = createRouter({
|
|||
{
|
||||
path: '/sign/up',
|
||||
component: () => import('../views/Sign/SignUp.vue'),
|
||||
},
|
||||
{
|
||||
path: '/sign/reset',
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
component: () => import('../views/Dashboard.vue'),
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
158
FrontEnd/src/views/Dashboard.vue
Normal file
158
FrontEnd/src/views/Dashboard.vue
Normal file
|
@ -0,0 +1,158 @@
|
|||
<template>
|
||||
<div class="min-h-full">
|
||||
<Disclosure as="nav" class="bg-gray-800" v-slot="{ open }">
|
||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex h-16 items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-shrink-0">
|
||||
<img class="h-8 w-8" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company" />
|
||||
</div>
|
||||
<div class="hidden md:block">
|
||||
<div class="ml-10 flex items-baseline space-x-4">
|
||||
<a v-for="item in navigation" :key="item.name" :href="item.href" :class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'rounded-md px-3 py-2 text-sm font-medium']" :aria-current="item.current ? 'page' : undefined">{{ item.name }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden md:block">
|
||||
<div class="ml-4 flex items-center md:ml-6">
|
||||
<button type="button" class="relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
||||
<span class="absolute -inset-1.5" />
|
||||
<span class="sr-only">View notifications</span>
|
||||
<BellIcon class="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
|
||||
<!-- Profile dropdown -->
|
||||
<Menu as="div" class="relative ml-3">
|
||||
<div>
|
||||
<MenuButton class="relative flex max-w-xs items-center rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
||||
<span class="absolute -inset-1.5" />
|
||||
<span class="sr-only">打开用户菜单</span>
|
||||
<img class="h-8 w-8 rounded-full" :src="user.imageUrl" alt="" />
|
||||
</MenuButton>
|
||||
</div>
|
||||
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
|
||||
<MenuItems class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
<MenuItem v-for="item in userNavigation" :key="item.name" v-slot="{ active }">
|
||||
<a :href="item.href" :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">{{ item.name }}</a>
|
||||
</MenuItem>
|
||||
</MenuItems>
|
||||
</transition>
|
||||
</Menu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="-mr-2 flex md:hidden">
|
||||
<!-- Mobile menu button -->
|
||||
<DisclosureButton class="relative inline-flex items-center justify-center rounded-md bg-gray-800 p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
||||
<span class="absolute -inset-0.5" />
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<Bars3Icon v-if="!open" class="block h-6 w-6" aria-hidden="true" />
|
||||
<XMarkIcon v-else class="block h-6 w-6" aria-hidden="true" />
|
||||
</DisclosureButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DisclosurePanel class="md:hidden">
|
||||
<div class="space-y-1 px-2 pb-3 pt-2 sm:px-3">
|
||||
<DisclosureButton v-for="item in navigation" :key="item.name" as="a" :href="item.href" :class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'block rounded-md px-3 py-2 text-base font-medium']" :aria-current="item.current ? 'page' : undefined">{{ item.name }}</DisclosureButton>
|
||||
</div>
|
||||
<div class="border-t border-gray-700 pb-3 pt-4">
|
||||
<div class="flex items-center px-5">
|
||||
<div class="flex-shrink-0">
|
||||
<img class="h-10 w-10 rounded-full" :src="user.imageUrl" alt="" />
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-base font-medium leading-none text-white">{{ user.name }}</div>
|
||||
<div class="text-sm font-medium leading-none text-gray-400">{{ user.email }}</div>
|
||||
</div>
|
||||
<button type="button" class="relative ml-auto flex-shrink-0 rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
||||
<span class="absolute -inset-1.5" />
|
||||
<span class="sr-only">View notifications</span>
|
||||
<BellIcon class="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-3 space-y-1 px-2">
|
||||
<DisclosureButton v-for="item in userNavigation" :key="item.name" as="a" :href="item.href" class="block rounded-md px-3 py-2 text-base font-medium text-gray-400 hover:bg-gray-700 hover:text-white">{{ item.name }}</DisclosureButton>
|
||||
</div>
|
||||
</div>
|
||||
</DisclosurePanel>
|
||||
</Disclosure>
|
||||
|
||||
<header class="bg-white shadow">
|
||||
<div class="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8">
|
||||
<h1 class="text-3xl font-bold tracking-tight text-gray-900">控制面板</h1>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8 grid grid-cols-4">
|
||||
<div class="max-w-7xl py-6 sm:px-3 lg:px-4 col-span-1">
|
||||
<div class="block p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
|
||||
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">宿舍网络状态</h5>
|
||||
<div>获取IP地址:<span class="font-bold">{{ data.ip }}</span></div>
|
||||
<div>是否登录:<span class="font-bold">是</span></div>
|
||||
<div>登陆账号:<span class="font-bold">{{ data.uid }}</span></div>
|
||||
<div>节点信息:<span class="font-bold">{{ data.type }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx-auto max-w-7xl py-6 sm:px-3 lg:px-4 col-span-3">
|
||||
<div class="block p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
|
||||
<div v-for="item in items" :key="item.id">
|
||||
{{ item }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
|
||||
import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/vue/24/outline'
|
||||
|
||||
const user = {
|
||||
name: 'Tom Cook',
|
||||
email: 'tom@example.com',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
||||
}
|
||||
const navigation = [
|
||||
{ name: '看板', href: '#', current: true },
|
||||
{ name: '网盘', href: 'http://192.168.5.190:1000/', current: false },
|
||||
]
|
||||
const userNavigation = [
|
||||
{ name: '个人信息', href: '#' },
|
||||
{ name: '设置', href: '#' },
|
||||
{ name: '登出', href: '#' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data: [], // 存储从接口获取的数据
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// 在组件挂载后执行获取数据的操作
|
||||
this.getDataFromApi();
|
||||
},
|
||||
methods: {
|
||||
getDataFromApi() {
|
||||
// 使用 Axios 发送 GET 请求获取 JSON 接口数据
|
||||
axios.get('http://localhost:8080/api/account/info')
|
||||
.then(response => {
|
||||
// 成功获取数据后更新组件的数据
|
||||
this.data = response.data.data;
|
||||
})
|
||||
.catch(error => {
|
||||
// 处理错误
|
||||
console.error('Error fetching data:', error);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,8 +1,11 @@
|
|||
<template>
|
||||
<div class="bg-white">
|
||||
<div class="mx-auto max-w-7xl py-24 sm:px-6 sm:py-32 lg:px-8">
|
||||
<div class="relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0">
|
||||
<svg viewBox="0 0 1024 1024" class="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0" aria-hidden="true">
|
||||
<div
|
||||
class="relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0">
|
||||
<svg viewBox="0 0 1024 1024"
|
||||
class="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0"
|
||||
aria-hidden="true">
|
||||
<circle cx="512" cy="512" r="512" fill="url(#759c1415-0410-454c-8f7c-9a820de03641)" fill-opacity="0.7"/>
|
||||
<defs>
|
||||
<radialGradient id="759c1415-0410-454c-8f7c-9a820de03641">
|
||||
|
@ -12,15 +15,20 @@
|
|||
</defs>
|
||||
</svg>
|
||||
<div class="mx-auto max-w-md text-center lg:mx-0 lg:flex-auto lg:py-32 lg:text-left">
|
||||
<h2 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">{{ data }}</h2>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-300">Ac euismod vel sit maecenas id pellentesque eu sed consectetur. Malesuada adipiscing sagittis vel nulla.</p>
|
||||
<h2 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">{{ data.title }}</h2>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-300">{{ data.sub_title }}</p>
|
||||
<div class="mt-10 flex items-center justify-center gap-x-6 lg:justify-start">
|
||||
<a href="#" class="rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white">Get started</a>
|
||||
<a href="#" class="text-sm font-semibold leading-6 text-white">Learn more <span aria-hidden="true">→</span></a>
|
||||
<a href="/sign/in"
|
||||
class="rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white">
|
||||
进入中心
|
||||
</a>
|
||||
<a href="#" class="text-sm font-semibold leading-6 text-white">了解更多 →</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative mt-16 h-80 lg:mt-8">
|
||||
<img class="absolute left-0 top-0 w-[57rem] max-w-none rounded-md bg-white/5 ring-1 ring-white/10" src="https://tailwindui.com/img/component-images/dark-project-app-screenshot.png" alt="App screenshot" width="1824" height="1080" />
|
||||
<img class="absolute left-0 top-0 w-[57rem] max-w-none rounded-md bg-white/5 ring-1 ring-white/10"
|
||||
src="https://tailwindui.com/img/component-images/dark-project-app-screenshot.png" alt="App screenshot"
|
||||
width="1824" height="1080"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -44,10 +52,10 @@ export default {
|
|||
methods: {
|
||||
getDataFromApi() {
|
||||
// 使用 Axios 发送 GET 请求获取 JSON 接口数据
|
||||
axios.get('http://localhost:8080/api/account/info')
|
||||
axios.get('http://localhost:8080/api/info/data')
|
||||
.then(response => {
|
||||
// 成功获取数据后更新组件的数据
|
||||
this.data = response.data;
|
||||
this.data = response.data.data;
|
||||
})
|
||||
.catch(error => {
|
||||
// 处理错误
|
||||
|
|
|
@ -1,11 +1,90 @@
|
|||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
|
||||
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<img alt="Your Company" class="mx-auto h-10 w-auto"
|
||||
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"/>
|
||||
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
|
||||
DormStar - 登录
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<form action="#" class="space-y-6" method="POST">
|
||||
<div>
|
||||
<label class="block text-sm font-medium leading-6 text-gray-900" for="email">邮箱</label>
|
||||
<div class="mt-2">
|
||||
<input id="user" autocomplete="user"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
name="user" required=""
|
||||
type="text"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="block text-sm font-medium leading-6 text-gray-900" for="password">密码</label>
|
||||
<div class="text-sm">
|
||||
<a class="font-semibold text-indigo-600 hover:text-indigo-500" href="/sign/reset">忘记密码</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<input id="password" autocomplete="current-password"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
name="password" required=""
|
||||
type="password"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
|
||||
type="submit">
|
||||
登录
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="mt-10 text-center text-sm text-gray-500">
|
||||
还没有账号?
|
||||
<a class="font-semibold leading-6 text-indigo-600 hover:text-indigo-500" href="#">注册一个!</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
</style>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data: [], // 存储从接口获取的数据
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// 在组件挂载后执行获取数据的操作
|
||||
this.getDataFromApi();
|
||||
},
|
||||
methods: {
|
||||
getDataFromApi() {
|
||||
// 使用 Axios 发送 GET 请求获取 JSON 接口数据
|
||||
axios.get('http://localhost:8080/api/user/sign/in')
|
||||
.then(response => {
|
||||
// 成功获取数据后更新组件的数据
|
||||
this.data = response.data;
|
||||
if (this.data.output === "SuccessCreate") {
|
||||
// 设置Cookie的过期时间为12小时
|
||||
const expireDate = new Date();
|
||||
expireDate.setTime(expireDate.getTime() + 43200000);
|
||||
// 使用document.cookie创建Cookie
|
||||
document.cookie = `session=${this.data.data}; expires=${expireDate.toUTCString()}; path=/`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 处理错误
|
||||
console.error('Error fetching data:', error);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,11 +1,107 @@
|
|||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
|
||||
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<img alt="Your Company" class="mx-auto h-10 w-auto"
|
||||
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"/>
|
||||
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
|
||||
DormStar - 注册
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<form action="#" class="space-y-6" method="POST">
|
||||
<div>
|
||||
<label class="block text-sm font-medium leading-6 text-gray-900" for="email">邮箱</label>
|
||||
<div class="mt-2">
|
||||
<input id="user" autocomplete="user"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
name="user" required=""
|
||||
type="text"/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium leading-6 text-gray-900" for="email">昵称</label>
|
||||
<div class="mt-2">
|
||||
<input id="user" autocomplete="user"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
name="user" required=""
|
||||
type="text"/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium leading-6 text-gray-900" for="email">电话</label>
|
||||
<div class="mt-2">
|
||||
<input id="user" autocomplete="user"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
name="user" required=""
|
||||
type="text"/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="block text-sm font-medium leading-6 text-gray-900" for="password">密码</label>
|
||||
<div class="text-sm">
|
||||
<a class="font-semibold text-indigo-600 hover:text-indigo-500" href="/sign/reset">忘记密码</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<input id="password" autocomplete="current-password"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
name="password" required=""
|
||||
type="password"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
|
||||
type="submit">
|
||||
注册
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="mt-10 text-center text-sm text-gray-500">
|
||||
我已经有账号了
|
||||
<a class="font-semibold leading-6 text-indigo-600 hover:text-indigo-500" href="/sign/in">登陆!</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
</style>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data: [], // 存储从接口获取的数据
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// 在组件挂载后执行获取数据的操作
|
||||
this.getDataFromApi();
|
||||
},
|
||||
methods: {
|
||||
getDataFromApi() {
|
||||
// 使用 Axios 发送 GET 请求获取 JSON 接口数据
|
||||
axios.get('http://localhost:8080/api/user/sign/in')
|
||||
.then(response => {
|
||||
// 成功获取数据后更新组件的数据
|
||||
this.data = response.data;
|
||||
if (this.data.output === "SuccessCreate") {
|
||||
// 设置Cookie的过期时间为12小时
|
||||
const expireDate = new Date();
|
||||
expireDate.setTime(expireDate.getTime() + 43200000);
|
||||
// 使用document.cookie创建Cookie
|
||||
document.cookie = `session=${this.data.data}; expires=${expireDate.toUTCString()}; path=/`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 处理错误
|
||||
console.error('Error fetching data:', error);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -7,4 +7,5 @@ INSERT INTO ds_info (value, data, commit) VALUES
|
|||
('sub_title', '我们的宿舍', '网站副标题'),
|
||||
('register', true, '是否允许注册'),
|
||||
('autoLogin', true, '是否允许自动登录'),
|
||||
('schoolLoginAddress', 'http://10.1.99.100:801/', '校园登录IP地址')
|
||||
('schoolLoginAddress', '10.1.99.100', '校园登录IP地址'),
|
||||
('schoolLoginPort', '801', '校园网登录接口端口')
|
|
@ -23,10 +23,17 @@ class AccountController(
|
|||
.also { it.find() }
|
||||
val matcherType = Pattern.compile("[a-z]+$").matcher(getMap?.get("uid").toString())
|
||||
.also { it.find() }
|
||||
try {
|
||||
hashMap["ip"] = getMap?.get("v46ip")
|
||||
hashMap["time"] = getMap?.get("time")
|
||||
hashMap["uid"] = matcherUid.group(0)
|
||||
hashMap["type"] = matcherType.group(0)
|
||||
} catch (e: IllegalStateException) {
|
||||
hashMap["ip"] = getMap?.get("v46ip")
|
||||
hashMap["time"] = null
|
||||
hashMap["uid"] = matcherUid.group(0)
|
||||
hashMap["type"] = null
|
||||
}
|
||||
return ResultUtil.success(hashMap, httpServletRequest)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.xlf.dromstarkotlin.controllers
|
||||
|
||||
import com.frontleaves.general.utils.BaseResponse
|
||||
import com.xlf.dromstarkotlin.services.InfoService
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/info")
|
||||
class InfoController(
|
||||
val infoService: InfoService
|
||||
) {
|
||||
|
||||
/**
|
||||
* 获取内容
|
||||
*/
|
||||
@GetMapping("/data")
|
||||
fun getWebInfo(httpServletRequest: HttpServletRequest): ResponseEntity<BaseResponse> {
|
||||
return infoService.getWebInfo(httpServletRequest)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.xlf.dromstarkotlin.controllers
|
||||
|
||||
import com.frontleaves.general.utils.BaseResponse
|
||||
import com.frontleaves.general.utils.ErrorCode
|
||||
import com.frontleaves.general.utils.ResultUtil
|
||||
import com.xlf.dromstarkotlin.services.LogService
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.CookieValue
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/log")
|
||||
class LogController(
|
||||
val logService: LogService
|
||||
) {
|
||||
|
||||
@GetMapping("/auto-login")
|
||||
fun getAutoLoginLog(
|
||||
@CookieValue("session") token: String?,
|
||||
httpServletRequest: HttpServletRequest,
|
||||
httpServletResponse: HttpServletResponse
|
||||
): ResponseEntity<BaseResponse>? {
|
||||
// token 存在鉴权
|
||||
return if (token != null) {
|
||||
logService.getAutoLoginLog(token, httpServletRequest, httpServletResponse)
|
||||
} else {
|
||||
ResultUtil.error(ErrorCode.TOKEN_NOT_FOUNDED, httpServletRequest)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,16 +7,10 @@ import jakarta.servlet.http.Cookie
|
|||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.CookieValue
|
||||
import org.springframework.web.bind.annotation.CrossOrigin
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/token")
|
||||
@CrossOrigin(origins = ["*"])
|
||||
class TokenController(
|
||||
private val tokenService: TokenService
|
||||
) {
|
||||
|
@ -25,28 +19,21 @@ class TokenController(
|
|||
*/
|
||||
@GetMapping("/create")
|
||||
fun createToken(
|
||||
@CookieValue("session") token: String?, httpServletResponse: HttpServletResponse,
|
||||
@CookieValue("session") token: String?,
|
||||
httpServletResponse: HttpServletResponse,
|
||||
@RequestParam("return") returnLink: String?,
|
||||
httpServletRequest: HttpServletRequest
|
||||
): ResponseEntity<BaseResponse> {
|
||||
// 检查 token 是否存在
|
||||
return if (token == null) {
|
||||
val newToken = tokenService.tokenCreate(httpServletRequest)
|
||||
httpServletResponse.addCookie(
|
||||
Cookie("session", newToken)
|
||||
.also { it.path = "/" }
|
||||
.also { it.maxAge = 43200 }
|
||||
)
|
||||
httpServletResponse.addCookie(Cookie("session", newToken).also { it.path = "/" }.also { it.maxAge = 43200 })
|
||||
ResultUtil.redirect("SuccessCreate", "Token创建成功", newToken, returnLink, httpServletRequest)
|
||||
} else {
|
||||
if (tokenService.tokenVerify(token, httpServletResponse)) {
|
||||
ResultUtil.redirect("StillValid", "Token依旧有效", null, returnLink, httpServletRequest)
|
||||
} else {
|
||||
httpServletResponse.addCookie(
|
||||
Cookie("session", null)
|
||||
.also { it.path = "/" }
|
||||
.also { it.maxAge = 0 }
|
||||
)
|
||||
httpServletResponse.addCookie(Cookie("session", null).also { it.path = "/" }.also { it.maxAge = 0 })
|
||||
this.createToken(null, httpServletResponse, returnLink, httpServletRequest)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,12 +12,8 @@ import com.xlf.dromstarkotlin.services.UserService
|
|||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.CookieValue
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import java.util.Date
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 用户控制器
|
||||
|
@ -39,7 +35,9 @@ class UserController(
|
|||
*/
|
||||
@GetMapping("/sign/in")
|
||||
fun signIn(
|
||||
@RequestBody signInVO: SignInVO?, @CookieValue("session") token: String?, httpServletResponse: HttpServletResponse,
|
||||
@RequestBody signInVO: SignInVO?,
|
||||
@CookieValue("session") token: String?,
|
||||
httpServletResponse: HttpServletResponse,
|
||||
httpServletRequest: HttpServletRequest
|
||||
): ResponseEntity<BaseResponse> {
|
||||
// 判断请求体是否为空
|
||||
|
@ -72,7 +70,9 @@ class UserController(
|
|||
*/
|
||||
@GetMapping("/sign/up")
|
||||
fun signUp(
|
||||
@RequestBody signUpVO: SignUpVO?, @CookieValue("session") token: String?, httpServletResponse: HttpServletResponse,
|
||||
@RequestBody signUpVO: SignUpVO?,
|
||||
@CookieValue("session") token: String?,
|
||||
httpServletResponse: HttpServletResponse,
|
||||
httpServletRequest: HttpServletRequest
|
||||
): ResponseEntity<BaseResponse> {
|
||||
// 检查是否允许注册
|
||||
|
@ -103,4 +103,26 @@ class UserController(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息组件
|
||||
*/
|
||||
fun getUserCurrent(
|
||||
@CookieValue("session") token: String?, httpServletRequest: HttpServletRequest, httpServletResponse: HttpServletResponse
|
||||
): ResponseEntity<BaseResponse> {
|
||||
return if (token!= null) {
|
||||
// 对 token 进行校验
|
||||
if (!tokenService.tokenVerify(token, httpServletResponse)) {
|
||||
// 校验失败
|
||||
BusinessException().backInfo(ErrorCode.TOKEN_VERIFY_FAILED, httpServletRequest)
|
||||
} else {
|
||||
// 获取当前用户信息
|
||||
userService.getUserCurrent(token, httpServletRequest)
|
||||
}
|
||||
} else {
|
||||
// 跳转至创建 Token 页面
|
||||
ResultUtil.redirect("/api/token/create", httpServletRequest)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RequestMapping
|
|||
|
||||
@Controller
|
||||
class ViewController {
|
||||
@RequestMapping("/{path:[^.]*}")
|
||||
@RequestMapping("/{path:[^.]*}/")
|
||||
fun forward(@PathVariable path: String): String? {
|
||||
return "forward:/index.html"
|
||||
}
|
||||
|
|
8
src/main/kotlin/com/xlf/dromstarkotlin/entity/InfoDO.kt
Normal file
8
src/main/kotlin/com/xlf/dromstarkotlin/entity/InfoDO.kt
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.xlf.dromstarkotlin.entity
|
||||
|
||||
data class InfoDO (
|
||||
val id: Int,
|
||||
val value: String,
|
||||
val data: String? = null,
|
||||
val commit: String,
|
||||
)
|
|
@ -1,5 +1,6 @@
|
|||
package com.xlf.dromstarkotlin.mapper
|
||||
|
||||
import com.xlf.dromstarkotlin.entity.InfoDO
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import org.apache.ibatis.annotations.Select
|
||||
|
||||
|
@ -14,4 +15,10 @@ interface InfoMapper {
|
|||
|
||||
@Select("SELECT * FROM ds_info WHERE value = 'autoLogin'")
|
||||
fun autoLogin(): Boolean
|
||||
|
||||
@Select("SELECT * FROM ds_info WHERE value = 'title'")
|
||||
fun getTitle(): InfoDO
|
||||
|
||||
@Select("SELECT * FROM ds_info WHERE value = 'sub_title'")
|
||||
fun getSubTitle(): InfoDO
|
||||
}
|
11
src/main/kotlin/com/xlf/dromstarkotlin/mapper/LogMapper.kt
Normal file
11
src/main/kotlin/com/xlf/dromstarkotlin/mapper/LogMapper.kt
Normal file
|
@ -0,0 +1,11 @@
|
|||
package com.xlf.dromstarkotlin.mapper
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import org.apache.ibatis.annotations.Select
|
||||
|
||||
@Mapper
|
||||
interface LogMapper {
|
||||
|
||||
@Select("SELECT * FROM ds_login_log ORDER BY id DESC LIMIT 50")
|
||||
fun getAutoLoginLog(): String
|
||||
}
|
|
@ -83,7 +83,7 @@ class AccountService(
|
|||
.build()
|
||||
try {
|
||||
val response = okHttpClient.newCall(request).execute()
|
||||
val matcher = Pattern.compile("dr1003\\(([^)]+)\\)").matcher(response.body!!.string())
|
||||
val matcher = Pattern.compile("dr1002\\(([^)]+)\\)").matcher(response.body!!.string())
|
||||
matcher.find()
|
||||
val getResponseBody = Gson().fromJson(matcher.group(1), HashMap::class.java)
|
||||
if (getResponseBody["result"] == "1") {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.xlf.dromstarkotlin.services
|
||||
|
||||
import com.frontleaves.general.utils.BaseResponse
|
||||
import com.frontleaves.general.utils.ResultUtil
|
||||
import com.xlf.dromstarkotlin.mapper.InfoMapper
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class InfoService(
|
||||
val infoMapper: InfoMapper
|
||||
) {
|
||||
|
||||
/**
|
||||
* 获取内容
|
||||
*/
|
||||
fun getWebInfo(httpServletRequest: HttpServletRequest): ResponseEntity<BaseResponse> {
|
||||
val hashMap = HashMap<String, Any?>()
|
||||
hashMap["title"] = infoMapper.getTitle().data
|
||||
hashMap["sub_title"] = infoMapper.getSubTitle().data
|
||||
return ResultUtil.success(hashMap, httpServletRequest)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.xlf.dromstarkotlin.services
|
||||
|
||||
import com.frontleaves.general.utils.BaseResponse
|
||||
import com.frontleaves.general.utils.ErrorCode
|
||||
import com.frontleaves.general.utils.ResultUtil
|
||||
import com.xlf.dromstarkotlin.mapper.LogMapper
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class LogService(
|
||||
val tokenService: TokenService,
|
||||
val logMapper: LogMapper
|
||||
) {
|
||||
|
||||
/**
|
||||
* 获取自动登录日志
|
||||
*/
|
||||
fun getAutoLoginLog(token: String, httpServletRequest: HttpServletRequest, httpServletResponse: HttpServletResponse): ResponseEntity<BaseResponse>? {
|
||||
// token 鉴权
|
||||
return if (tokenService.tokenVerify(token, httpServletResponse)) {
|
||||
// 获取自动登录日志
|
||||
ResultUtil.success(logMapper.getAutoLoginLog(), httpServletRequest)
|
||||
} else {
|
||||
ResultUtil.error(ErrorCode.TOKEN_NOT_FOUNDED, httpServletRequest)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ class ScheduleService(
|
|||
/**
|
||||
* 登录校园网(5分钟自动检查)
|
||||
*/
|
||||
@Scheduled(fixedDelay = 300000)
|
||||
@Scheduled(fixedDelay = 60000)
|
||||
fun schoolLogin() {
|
||||
if (CacheData.autoLogin) {
|
||||
val calendar = Calendar.getInstance()
|
||||
|
@ -64,12 +64,13 @@ class ScheduleService(
|
|||
accountService.regularLogin()
|
||||
}
|
||||
} else {
|
||||
// 切换校园网
|
||||
if (accountService.getInformation()?.get("type") != null) {
|
||||
do {
|
||||
accountService.regularLogout()
|
||||
Thread.sleep(5000)
|
||||
} while (accountService.getInformation()?.get("uid") == null)
|
||||
accountService.switchTheCampusNetwork()
|
||||
} while (accountService.getInformation()?.get("uid") == null)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hour in 7 .. 23) {
|
||||
|
@ -80,11 +81,13 @@ class ScheduleService(
|
|||
}
|
||||
} else{
|
||||
// 切换校园网
|
||||
if (accountService.getInformation()?.get("type") != null) {
|
||||
do {
|
||||
accountService.regularLogout()
|
||||
Thread.sleep(5000)
|
||||
} while (accountService.getInformation()?.get("uid") == null)
|
||||
accountService.switchTheCampusNetwork()
|
||||
} while (accountService.getInformation()?.get("uid") == null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,4 +81,8 @@ class UserService(
|
|||
return ResultUtil.error(ErrorCode.USER_EXIST, httpServletRequest)
|
||||
}
|
||||
}
|
||||
|
||||
fun getUserCurrent(token: String, httpServletRequest: HttpServletRequest): ResponseEntity<BaseResponse> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user