This commit is contained in:
筱锋xiao_lfeng 2023-12-03 00:30:12 +08:00
parent 5cf34df31c
commit 7209b7ee2f
Signed by: XiaoLFeng
GPG Key ID: F693AA12AABBFA87
24 changed files with 674 additions and 162 deletions

View File

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

View File

@ -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",

View File

@ -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'),
}
]
})

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

View File

@ -1,26 +1,34 @@
<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">
<circle cx="512" cy="512" r="512" fill="url(#759c1415-0410-454c-8f7c-9a820de03641)" fill-opacity="0.7" />
<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">
<stop stop-color="#7775D6" />
<stop offset="1" stop-color="#E935C1" />
<stop stop-color="#7775D6"/>
<stop offset="1" stop-color="#E935C1"/>
</radialGradient>
</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 => {
//

View File

@ -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") {
// Cookie12
const expireDate = new Date();
expireDate.setTime(expireDate.getTime() + 43200000);
// 使document.cookieCookie
document.cookie = `session=${this.data.data}; expires=${expireDate.toUTCString()}; path=/`;
}
})
.catch(error => {
//
console.error('Error fetching data:', error);
});
},
},
};
</script>

View File

@ -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") {
// Cookie12
const expireDate = new Date();
expireDate.setTime(expireDate.getTime() + 43200000);
// 使document.cookieCookie
document.cookie = `session=${this.data.data}; expires=${expireDate.toUTCString()}; path=/`;
}
})
.catch(error => {
//
console.error('Error fetching data:', error);
});
},
},
};
</script>

View File

@ -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', '校园网登录接口端口')

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}
}

View File

@ -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"
}

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

View File

@ -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
}

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

View File

@ -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") {

View File

@ -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)
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}
}
}

View File

@ -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")
}
}