Skip to content

Commit

Permalink
Merge pull request #298 from lanrenwo/add_online_search
Browse files Browse the repository at this point in the history
新增在线用户的搜索和一键下线功能
  • Loading branch information
bjdgyc authored Feb 26, 2024
2 parents a650db8 + 096b6f8 commit 098f321
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 38 deletions.
42 changes: 24 additions & 18 deletions server/dbdata/user_act_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ import (
)

const (
UserAuthFail = 0 // 认证失败
UserAuthSuccess = 1 // 认证成功
UserConnected = 2 // 连线成功
UserLogout = 3 // 用户登出
UserLogoutLose = 0 // 用户掉线
UserLogoutBanner = 1 // 用户banner弹窗取消
UserLogoutClient = 2 // 用户主动登出
UserLogoutTimeout = 3 // 用户超时登出
UserLogoutAdmin = 4 // 账号被管理员踢下线
UserLogoutExpire = 5 // 账号过期被踢下线
UserIdleTimeout = 6 // 用户空闲链接超时
UserAuthFail = 0 // 认证失败
UserAuthSuccess = 1 // 认证成功
UserConnected = 2 // 连线成功
UserLogout = 3 // 用户登出
UserLogoutLose = 0 // 用户掉线
UserLogoutBanner = 1 // 用户banner弹窗取消
UserLogoutClient = 2 // 用户主动登出
UserLogoutTimeout = 3 // 用户超时登出
UserLogoutAdmin = 4 // 账号被管理员踢下线
UserLogoutExpire = 5 // 账号过期被踢下线
UserIdleTimeout = 6 // 用户空闲链接超时
UserLogoutOneAdmin = 7 // 账号被管理员一键下线

)

type UserActLogProcess struct {
Expand Down Expand Up @@ -57,13 +59,14 @@ var (
3: "AnyLink",
},
InfoOps: []string{ // 信息
UserLogoutLose: "用户掉线",
UserLogoutBanner: "用户取消弹窗/客户端发起的logout",
UserLogoutClient: "用户/客户端主动断开",
UserLogoutTimeout: "Session过期被踢下线",
UserLogoutAdmin: "账号被管理员踢下线",
UserLogoutExpire: "账号过期被踢下线",
UserIdleTimeout: "用户空闲链接超时",
UserLogoutLose: "用户掉线",
UserLogoutBanner: "用户取消弹窗/客户端发起的logout",
UserLogoutClient: "用户/客户端主动断开",
UserLogoutTimeout: "Session过期被踢下线",
UserLogoutAdmin: "账号被管理员踢下线",
UserLogoutExpire: "账号过期被踢下线",
UserIdleTimeout: "用户空闲链接超时",
UserLogoutOneAdmin: "账号被管理员一键下线",
},
}
)
Expand Down Expand Up @@ -126,6 +129,9 @@ func (ua *UserActLogProcess) GetStatusOpsWithTag() interface{} {
}

func (ua *UserActLogProcess) GetInfoOpsById(id uint8) string {
if int(id) >= len(ua.InfoOps) {
return "未知的信息类型"
}
return ua.InfoOps[id]
}

Expand Down
64 changes: 53 additions & 11 deletions server/sessdata/online.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"net"
"sort"
"strings"
"time"

"github.com/bjdgyc/anylink/pkg/utils"
Expand Down Expand Up @@ -42,33 +43,74 @@ func (o Onlines) Swap(i, j int) {
}

func OnlineSess() []Online {
return GetOnlineSess("", "", false)
}

/**
* @Description: GetOnlineSess
* @param search_cate 分类:用户名、登录组、MAC地址、IP地址、远端地址
* @param search_text 关键字,模糊搜索
* @param show_sleeper 是否显示休眠用户
* @return []Online
*/
func GetOnlineSess(search_cate string, search_text string, show_sleeper bool) []Online {
var datas Onlines
if strings.TrimSpace(search_text) == "" {
search_cate = ""
}
sessMux.Lock()
defer sessMux.Unlock()
for _, v := range sessions {
v.mux.Lock()
if v.IsActive {
cSess := v.CSess
if cSess == nil {
cSess = &ConnSession{}
}
// 选择需要比较的字符串
var compareText string
switch search_cate {
case "username":
compareText = v.Username
case "group":
compareText = v.Group
case "mac_addr":
compareText = v.MacAddr
case "ip":
if cSess != nil {
compareText = cSess.IpAddr.String()
}
case "remote_addr":
if cSess != nil {
compareText = cSess.RemoteAddr
}
}
if search_cate != "" && !strings.Contains(compareText, search_text) {
v.mux.Unlock()
continue
}

if show_sleeper || v.IsActive {
val := Online{
Token: v.Token,
Ip: v.CSess.IpAddr,
Ip: cSess.IpAddr,
Username: v.Username,
Group: v.Group,
MacAddr: v.MacAddr,
UniqueMac: v.UniqueMac,
RemoteAddr: v.CSess.RemoteAddr,
TunName: v.CSess.IfName,
Mtu: v.CSess.Mtu,
Client: v.CSess.Client,
BandwidthUp: utils.HumanByte(v.CSess.BandwidthUpPeriod.Load()) + "/s",
BandwidthDown: utils.HumanByte(v.CSess.BandwidthDownPeriod.Load()) + "/s",
BandwidthUpAll: utils.HumanByte(v.CSess.BandwidthUpAll.Load()),
BandwidthDownAll: utils.HumanByte(v.CSess.BandwidthDownAll.Load()),
RemoteAddr: cSess.RemoteAddr,
TunName: cSess.IfName,
Mtu: cSess.Mtu,
Client: cSess.Client,
BandwidthUp: utils.HumanByte(cSess.BandwidthUpPeriod.Load()) + "/s",
BandwidthDown: utils.HumanByte(cSess.BandwidthDownPeriod.Load()) + "/s",
BandwidthUpAll: utils.HumanByte(cSess.BandwidthUpAll.Load()),
BandwidthDownAll: utils.HumanByte(cSess.BandwidthDownAll.Load()),
LastLogin: v.LastLogin,
}
datas = append(datas, val)
}
v.mux.Unlock()
}
sessMux.Unlock()
sort.Sort(&datas)
return datas
}
7 changes: 5 additions & 2 deletions server/sessdata/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ func CloseSess(token string, code ...uint8) {
sess.CSess.Close()
return
}
AddUserActLogBySess(sess)
AddUserActLogBySess(sess, code...)
}

func CloseCSess(token string) {
Expand Down Expand Up @@ -501,7 +501,7 @@ func AddUserActLog(cs *ConnSession) {
dbdata.UserActLogIns.Add(ua, cs.UserAgent)
}

func AddUserActLogBySess(sess *Session) {
func AddUserActLogBySess(sess *Session, code ...uint8) {
ua := dbdata.UserActLog{
Username: sess.Username,
GroupName: sess.Group,
Expand All @@ -512,5 +512,8 @@ func AddUserActLogBySess(sess *Session) {
Status: dbdata.UserLogout,
}
ua.Info = dbdata.UserActLogIns.GetInfoOpsById(dbdata.UserLogoutBanner)
if len(code) > 0 {
ua.Info = dbdata.UserActLogIns.GetInfoOpsById(code[0])
}
dbdata.UserActLogIns.Add(ua, sess.UserAgent)
}
124 changes: 117 additions & 7 deletions web/src/pages/user/Online.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,59 @@
<template>
<div>
<el-card>
<el-form :inline="true">
<el-form-item>
<el-select
v-model="searchCate"
style="width: 86px;"
@change="handleSearch">
<el-option
label="用户名"
value="username">
</el-option>
<el-option
label="登录组"
value="group">
</el-option>
<el-option
label="MAC地址"
value="mac_addr">
</el-option>
<el-option
label="IP地址"
value="ip">
</el-option>
<el-option
label="远端地址"
value="remote_addr">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-input
v-model="searchText"
placeholder="请输入搜索内容"
@input="handleSearch">
</el-input>
</el-form-item>
<el-form-item>
显示休眠用户:
<el-switch
v-model="showSleeper"
@change="handleSearch">
</el-switch>
</el-form-item>
<el-form-item>
<el-button
class="extra-small-button"
type="danger"
size="mini"
:loading="loadingOneOffline"
@click="handleOneOffline">
一键下线
</el-button>
</el-form>

<el-table
ref="multipleTable"
:data="tableData"
Expand All @@ -20,14 +73,14 @@

<el-table-column
prop="group"
label="登陆组">
label="登录组">
</el-table-column>

<el-table-column
prop="mac_addr"
label="MAC地址">
</el-table-column>

<el-table-column
prop="unique_mac"
label="唯一MAC">
Expand Down Expand Up @@ -67,7 +120,6 @@
</el-table-column>

<el-table-column
prop="status"
label="实时 上行/下行"
width="220">
<template slot-scope="scope">
Expand All @@ -77,7 +129,6 @@
</el-table-column>

<el-table-column
prop="status"
label="总量 上行/下行"
width="200">
<template slot-scope="scope">
Expand All @@ -88,7 +139,7 @@

<el-table-column
prop="last_login"
label="登陆时间"
label="登录时间"
:formatter="tableDateFormat">
</el-table-column>

Expand All @@ -99,6 +150,7 @@
<el-button
size="mini"
type="primary"
v-if="scope.row.remote_addr !== ''"
@click="handleReline(scope.row)">重连
</el-button>

Expand All @@ -123,6 +175,7 @@

<script>
import axios from "axios";
import { MessageBox } from 'element-ui';
export default {
name: "Online",
Expand All @@ -147,6 +200,10 @@ export default {
data() {
return {
tableData: [],
searchCate: 'username',
searchText: '',
showSleeper: false,
loadingOneOffline: false,
}
},
methods: {
Expand Down Expand Up @@ -185,8 +242,43 @@ export default {
handleEdit(a, row) {
console.log(a, row)
},
handleOneOffline() {
if (this.tableData === null || this.tableData.length === 0) {
this.$message.error('错误:当前在线用户表为空,无法执行一键下线操作!');
return;
}
MessageBox.confirm('当前搜索条件下的所有用户将会“下线”,你确定执行吗?', '危险', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'danger'
}).then(() => {
try {
this.loadingOneOffline = true;
this.getData();
this.$message.success('操作成功');
this.loadingOneOffline = false;
// 清空当前表格
this.tableData = [];
} catch (error) {
this.loadingOneOffline = false;
this.$message.error('操作失败');
}
});
},
handleSearch() {
this.getData();
},
getData() {
axios.get('/user/online').then(resp => {
axios.get('/user/online',
{
params: {
search_cate: this.searchCate,
search_text: this.searchText,
show_sleeper: this.showSleeper,
one_offline: this.loadingOneOffline
}
}
).then(resp => {
var data = resp.data.data
console.log(data);
this.tableData = data.datas;
Expand All @@ -201,5 +293,23 @@ export default {
</script>

<style scoped>
/deep/ .el-form .el-form-item__label,
/deep/ .el-form .el-form-item__content,
/deep/ .el-form .el-input,
/deep/ .el-form .el-select,
/deep/ .el-form .el-button,
/deep/ .el-form .el-select-dropdown__item {
font-size: 11px;
}
.el-select-dropdown .el-select-dropdown__item {
font-size: 11px;
padding: 0 10px;
}
/deep/ .el-input__inner{
height: 30px;
padding: 0 10px;
}
.extra-small-button {
padding: 5px 10px;
}
</style>

0 comments on commit 098f321

Please sign in to comment.