mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-18 17:26:38 +08:00
refactor: user login log list for admin is ready
This commit is contained in:
parent
feff1684c4
commit
0e6606e469
@ -8,9 +8,10 @@ import (
|
||||
"chatplus/store/vo"
|
||||
"chatplus/utils"
|
||||
"chatplus/utils/resp"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ApiKeyHandler struct {
|
||||
@ -61,7 +62,7 @@ func (h *ApiKeyHandler) Save(c *gin.Context) {
|
||||
|
||||
func (h *ApiKeyHandler) List(c *gin.Context) {
|
||||
userId := h.GetInt(c, "user_id", -1)
|
||||
query := h.db.Debug().Session(&gorm.Session{})
|
||||
query := h.db.Session(&gorm.Session{})
|
||||
if userId >= 0 {
|
||||
query = query.Where("user_id", userId)
|
||||
}
|
||||
|
@ -118,6 +118,32 @@ func (h *UserHandler) Remove(c *gin.Context) {
|
||||
resp.SUCCESS(c)
|
||||
}
|
||||
|
||||
func (h *UserHandler) LoginLog(c *gin.Context) {
|
||||
page := h.GetInt(c, "page", 1)
|
||||
pageSize := h.GetInt(c, "page_size", 20)
|
||||
var total int64
|
||||
h.db.Model(&model.UserLoginLog{}).Count(&total)
|
||||
offset := (page - 1) * pageSize
|
||||
var items []model.UserLoginLog
|
||||
res := h.db.Offset(offset).Limit(pageSize).Find(&items)
|
||||
if res.Error != nil {
|
||||
resp.ERROR(c, "获取数据失败")
|
||||
return
|
||||
}
|
||||
var logs []vo.UserLoginLog
|
||||
for _, v := range items {
|
||||
var log vo.UserLoginLog
|
||||
err := utils.CopyObject(v, &log)
|
||||
if err == nil {
|
||||
log.Id = v.Id
|
||||
log.CreatedAt = v.CreatedAt.Unix()
|
||||
logs = append(logs, log)
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, vo.NewPage(total, page, pageSize, logs))
|
||||
}
|
||||
|
||||
func (h *UserHandler) InitUser(c *gin.Context) {
|
||||
var users []model.User
|
||||
h.db.Find(&users)
|
||||
|
@ -137,6 +137,7 @@ func main() {
|
||||
group.GET("list", h.List)
|
||||
group.POST("update", h.Update)
|
||||
group.GET("remove", h.Remove)
|
||||
group.GET("loginLog", h.LoginLog)
|
||||
group.GET("test", h.InitUser)
|
||||
}),
|
||||
fx.Invoke(func(s *core.AppServer, h *admin.ChatRoleHandler) {
|
||||
|
9
api/go/store/vo/user_login_log.go
Normal file
9
api/go/store/vo/user_login_log.go
Normal file
@ -0,0 +1,9 @@
|
||||
package vo
|
||||
|
||||
type UserLoginLog struct {
|
||||
BaseVo
|
||||
UserId uint `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
LoginIp string `json:"login_ip"`
|
||||
LoginAddress string `json:"login_address"`
|
||||
}
|
@ -87,6 +87,9 @@
|
||||
<el-tab-pane label="API KEY" name="apikey" v-if="arrayContains(tabs, 'apikey')">
|
||||
<api-key v-if="curTab==='apikey'"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="登录日志" name="loginLog" v-if="arrayContains(tabs, 'loginLog')">
|
||||
<login-log v-if="curTab==='loginLog'"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
@ -108,10 +111,10 @@ import {httpGet} from "@/utils/http";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {useRouter} from "vue-router";
|
||||
import ApiKey from "@/views/admin/ApiKey.vue";
|
||||
import LoginLog from "@/views/admin/LoginLog.vue";
|
||||
|
||||
const title = ref('Chat-Plus 控制台')
|
||||
const logo = ref('images/logo.png')
|
||||
const user = ref({})
|
||||
const navs = ref([
|
||||
{
|
||||
id: 1,
|
||||
@ -136,6 +139,12 @@ const navs = ref([
|
||||
title: 'API KEY',
|
||||
tab: 'apikey',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: '登录日志',
|
||||
tab: 'loginLog',
|
||||
active: false,
|
||||
}
|
||||
])
|
||||
const tabs = ref([])
|
||||
@ -155,22 +164,22 @@ const nodeListPaddingLeft = computed(() => {
|
||||
})
|
||||
const router = useRouter()
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("resize", function () {
|
||||
winHeight.value = window.innerHeight
|
||||
})
|
||||
|
||||
// 获取会话信息
|
||||
httpGet("/api/admin/session").catch(() => {
|
||||
router.push('/admin/login')
|
||||
})
|
||||
|
||||
// 获取会话信息
|
||||
httpGet("/api/admin/session").then(() => {
|
||||
// 加载系统配置
|
||||
httpGet('/api/admin/config/get?key=system').then(res => {
|
||||
title.value = res.data['admin_title'];
|
||||
}).catch(e => {
|
||||
ElMessage.error("加载系统配置失败: " + e.message)
|
||||
})
|
||||
}).catch(() => {
|
||||
router.push('/admin/login')
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("resize", function () {
|
||||
winHeight.value = window.innerHeight
|
||||
})
|
||||
})
|
||||
|
||||
const logout = function () {
|
||||
@ -354,3 +363,12 @@ $borderColor = #4676d0;
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="stylus">
|
||||
.pagination {
|
||||
padding 20px;
|
||||
display flex
|
||||
justify-content center
|
||||
width 100%
|
||||
}
|
||||
</style>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="list" v-loading="loading">
|
||||
<el-row class="opt-box">
|
||||
<el-button type="primary" @click="add">
|
||||
<el-button type="primary" @click="add" size="small">
|
||||
<el-icon>
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
新增角色
|
||||
新增
|
||||
</el-button>
|
||||
</el-row>
|
||||
|
||||
@ -150,6 +150,8 @@ const remove = function (row) {
|
||||
|
||||
.opt-box {
|
||||
padding-bottom: 10px;
|
||||
display flex;
|
||||
justify-content end
|
||||
|
||||
.el-icon {
|
||||
margin-right: 5px;
|
||||
|
92
web/src/views/admin/LoginLog.vue
Normal file
92
web/src/views/admin/LoginLog.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="list" v-loading="loading">
|
||||
<el-row>
|
||||
<el-table :data="items" :row-key="row => row.id">
|
||||
<el-table-column label="用户名" prop="username"/>
|
||||
<el-table-column label="登录IP" prop="login_ip"/>
|
||||
<el-table-column label="登录地址" prop="login_address"/>
|
||||
<el-table-column label="登录时间">
|
||||
<template #default="scope">
|
||||
<span>{{ dateFormat(scope.row['created_at']) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-popconfirm title="确定要删除当前记录吗?" @confirm="remove(scope.row)">
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
|
||||
<div class="pagination">
|
||||
<el-pagination v-if="total > 0" background
|
||||
layout="prev, pager, next"
|
||||
:hide-on-single-page="true"
|
||||
v-model:current-page="page"
|
||||
v-model:page-size="pageSize"
|
||||
@current-change="fetchList(page, pageSize)"
|
||||
:total="total"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import {httpGet} from "@/utils/http";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {dateFormat} from "@/utils/libs";
|
||||
|
||||
// 用户登录日志
|
||||
const items = ref([])
|
||||
const loading = ref(true)
|
||||
const total = ref(0)
|
||||
const page = ref(0)
|
||||
const pageSize = ref(0)
|
||||
|
||||
onMounted(() => {
|
||||
fetchList(1, 15)
|
||||
})
|
||||
|
||||
// 获取数据
|
||||
const fetchList = function (_page, _pageSize) {
|
||||
console.log(_page, _pageSize)
|
||||
httpGet(`/api/admin/user/loginLog?page=${_page}&page_size=${_pageSize}`).then((res) => {
|
||||
if (res.data) {
|
||||
items.value = res.data.items
|
||||
total.value = res.data.total
|
||||
page.value = res.data.page
|
||||
pageSize.value = res.data.page_size
|
||||
}
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
ElMessage.error("获取数据失败");
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.list {
|
||||
|
||||
.opt-box {
|
||||
padding-bottom: 10px;
|
||||
display flex;
|
||||
justify-content end
|
||||
|
||||
.el-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-select {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="role-list">
|
||||
<el-row class="opt-box">
|
||||
<el-button type="primary" @click="addRole">
|
||||
<el-button type="primary" @click="addRole" size="small">
|
||||
<el-icon>
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
新增角色
|
||||
新增
|
||||
</el-button>
|
||||
</el-row>
|
||||
|
||||
@ -292,6 +292,8 @@ const removeContext = function (index) {
|
||||
.role-list {
|
||||
.opt-box {
|
||||
padding-bottom: 10px;
|
||||
display flex;
|
||||
justify-content end
|
||||
|
||||
.el-icon {
|
||||
margin-right 5px;
|
||||
|
@ -39,7 +39,7 @@
|
||||
:hide-on-single-page="true"
|
||||
v-model:current-page="users.page"
|
||||
v-model:page-size="users.page_size"
|
||||
@update:current-change="fetchUserList(users.page, users.page_size)"
|
||||
@current-change="fetchUserList(users.page, users.page_size)"
|
||||
:total="users.total"/>
|
||||
|
||||
</div>
|
||||
@ -126,7 +126,7 @@ const loading = ref(true)
|
||||
const userEditFormRef = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
fetchUserList(1, 20)
|
||||
fetchUserList(1, 10)
|
||||
// 获取角色列表
|
||||
httpGet('/api/admin/role/list').then((res) => {
|
||||
roles.value = res.data;
|
||||
@ -219,13 +219,6 @@ const handleSelectionChange = function (rows) {
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
padding-top 20px;
|
||||
display flex
|
||||
justify-content center
|
||||
width 100%
|
||||
}
|
||||
|
||||
.el-select {
|
||||
width: 100%
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user