Skip to content

Commit 098f321

Browse files
authored
Merge pull request #298 from lanrenwo/add_online_search
新增在线用户的搜索和一键下线功能
2 parents a650db8 + 096b6f8 commit 098f321

File tree

4 files changed

+199
-38
lines changed

4 files changed

+199
-38
lines changed

server/dbdata/user_act_log.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@ import (
1212
)
1313

1414
const (
15-
UserAuthFail = 0 // 认证失败
16-
UserAuthSuccess = 1 // 认证成功
17-
UserConnected = 2 // 连线成功
18-
UserLogout = 3 // 用户登出
19-
UserLogoutLose = 0 // 用户掉线
20-
UserLogoutBanner = 1 // 用户banner弹窗取消
21-
UserLogoutClient = 2 // 用户主动登出
22-
UserLogoutTimeout = 3 // 用户超时登出
23-
UserLogoutAdmin = 4 // 账号被管理员踢下线
24-
UserLogoutExpire = 5 // 账号过期被踢下线
25-
UserIdleTimeout = 6 // 用户空闲链接超时
15+
UserAuthFail = 0 // 认证失败
16+
UserAuthSuccess = 1 // 认证成功
17+
UserConnected = 2 // 连线成功
18+
UserLogout = 3 // 用户登出
19+
UserLogoutLose = 0 // 用户掉线
20+
UserLogoutBanner = 1 // 用户banner弹窗取消
21+
UserLogoutClient = 2 // 用户主动登出
22+
UserLogoutTimeout = 3 // 用户超时登出
23+
UserLogoutAdmin = 4 // 账号被管理员踢下线
24+
UserLogoutExpire = 5 // 账号过期被踢下线
25+
UserIdleTimeout = 6 // 用户空闲链接超时
26+
UserLogoutOneAdmin = 7 // 账号被管理员一键下线
27+
2628
)
2729

2830
type UserActLogProcess struct {
@@ -57,13 +59,14 @@ var (
5759
3: "AnyLink",
5860
},
5961
InfoOps: []string{ // 信息
60-
UserLogoutLose: "用户掉线",
61-
UserLogoutBanner: "用户取消弹窗/客户端发起的logout",
62-
UserLogoutClient: "用户/客户端主动断开",
63-
UserLogoutTimeout: "Session过期被踢下线",
64-
UserLogoutAdmin: "账号被管理员踢下线",
65-
UserLogoutExpire: "账号过期被踢下线",
66-
UserIdleTimeout: "用户空闲链接超时",
62+
UserLogoutLose: "用户掉线",
63+
UserLogoutBanner: "用户取消弹窗/客户端发起的logout",
64+
UserLogoutClient: "用户/客户端主动断开",
65+
UserLogoutTimeout: "Session过期被踢下线",
66+
UserLogoutAdmin: "账号被管理员踢下线",
67+
UserLogoutExpire: "账号过期被踢下线",
68+
UserIdleTimeout: "用户空闲链接超时",
69+
UserLogoutOneAdmin: "账号被管理员一键下线",
6770
},
6871
}
6972
)
@@ -126,6 +129,9 @@ func (ua *UserActLogProcess) GetStatusOpsWithTag() interface{} {
126129
}
127130

128131
func (ua *UserActLogProcess) GetInfoOpsById(id uint8) string {
132+
if int(id) >= len(ua.InfoOps) {
133+
return "未知的信息类型"
134+
}
129135
return ua.InfoOps[id]
130136
}
131137

server/sessdata/online.go

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"net"
66
"sort"
7+
"strings"
78
"time"
89

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

4445
func OnlineSess() []Online {
46+
return GetOnlineSess("", "", false)
47+
}
48+
49+
/**
50+
* @Description: GetOnlineSess
51+
* @param search_cate 分类:用户名、登录组、MAC地址、IP地址、远端地址
52+
* @param search_text 关键字,模糊搜索
53+
* @param show_sleeper 是否显示休眠用户
54+
* @return []Online
55+
*/
56+
func GetOnlineSess(search_cate string, search_text string, show_sleeper bool) []Online {
4557
var datas Onlines
58+
if strings.TrimSpace(search_text) == "" {
59+
search_cate = ""
60+
}
4661
sessMux.Lock()
62+
defer sessMux.Unlock()
4763
for _, v := range sessions {
4864
v.mux.Lock()
49-
if v.IsActive {
65+
cSess := v.CSess
66+
if cSess == nil {
67+
cSess = &ConnSession{}
68+
}
69+
// 选择需要比较的字符串
70+
var compareText string
71+
switch search_cate {
72+
case "username":
73+
compareText = v.Username
74+
case "group":
75+
compareText = v.Group
76+
case "mac_addr":
77+
compareText = v.MacAddr
78+
case "ip":
79+
if cSess != nil {
80+
compareText = cSess.IpAddr.String()
81+
}
82+
case "remote_addr":
83+
if cSess != nil {
84+
compareText = cSess.RemoteAddr
85+
}
86+
}
87+
if search_cate != "" && !strings.Contains(compareText, search_text) {
88+
v.mux.Unlock()
89+
continue
90+
}
91+
92+
if show_sleeper || v.IsActive {
5093
val := Online{
5194
Token: v.Token,
52-
Ip: v.CSess.IpAddr,
95+
Ip: cSess.IpAddr,
5396
Username: v.Username,
5497
Group: v.Group,
5598
MacAddr: v.MacAddr,
5699
UniqueMac: v.UniqueMac,
57-
RemoteAddr: v.CSess.RemoteAddr,
58-
TunName: v.CSess.IfName,
59-
Mtu: v.CSess.Mtu,
60-
Client: v.CSess.Client,
61-
BandwidthUp: utils.HumanByte(v.CSess.BandwidthUpPeriod.Load()) + "/s",
62-
BandwidthDown: utils.HumanByte(v.CSess.BandwidthDownPeriod.Load()) + "/s",
63-
BandwidthUpAll: utils.HumanByte(v.CSess.BandwidthUpAll.Load()),
64-
BandwidthDownAll: utils.HumanByte(v.CSess.BandwidthDownAll.Load()),
100+
RemoteAddr: cSess.RemoteAddr,
101+
TunName: cSess.IfName,
102+
Mtu: cSess.Mtu,
103+
Client: cSess.Client,
104+
BandwidthUp: utils.HumanByte(cSess.BandwidthUpPeriod.Load()) + "/s",
105+
BandwidthDown: utils.HumanByte(cSess.BandwidthDownPeriod.Load()) + "/s",
106+
BandwidthUpAll: utils.HumanByte(cSess.BandwidthUpAll.Load()),
107+
BandwidthDownAll: utils.HumanByte(cSess.BandwidthDownAll.Load()),
65108
LastLogin: v.LastLogin,
66109
}
67110
datas = append(datas, val)
68111
}
69112
v.mux.Unlock()
70113
}
71-
sessMux.Unlock()
72114
sort.Sort(&datas)
73115
return datas
74116
}

server/sessdata/session.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ func CloseSess(token string, code ...uint8) {
464464
sess.CSess.Close()
465465
return
466466
}
467-
AddUserActLogBySess(sess)
467+
AddUserActLogBySess(sess, code...)
468468
}
469469

470470
func CloseCSess(token string) {
@@ -501,7 +501,7 @@ func AddUserActLog(cs *ConnSession) {
501501
dbdata.UserActLogIns.Add(ua, cs.UserAgent)
502502
}
503503

504-
func AddUserActLogBySess(sess *Session) {
504+
func AddUserActLogBySess(sess *Session, code ...uint8) {
505505
ua := dbdata.UserActLog{
506506
Username: sess.Username,
507507
GroupName: sess.Group,
@@ -512,5 +512,8 @@ func AddUserActLogBySess(sess *Session) {
512512
Status: dbdata.UserLogout,
513513
}
514514
ua.Info = dbdata.UserActLogIns.GetInfoOpsById(dbdata.UserLogoutBanner)
515+
if len(code) > 0 {
516+
ua.Info = dbdata.UserActLogIns.GetInfoOpsById(code[0])
517+
}
515518
dbdata.UserActLogIns.Add(ua, sess.UserAgent)
516519
}

web/src/pages/user/Online.vue

Lines changed: 117 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,59 @@
11
<template>
22
<div>
33
<el-card>
4+
<el-form :inline="true">
5+
<el-form-item>
6+
<el-select
7+
v-model="searchCate"
8+
style="width: 86px;"
9+
@change="handleSearch">
10+
<el-option
11+
label="用户名"
12+
value="username">
13+
</el-option>
14+
<el-option
15+
label="登录组"
16+
value="group">
17+
</el-option>
18+
<el-option
19+
label="MAC地址"
20+
value="mac_addr">
21+
</el-option>
22+
<el-option
23+
label="IP地址"
24+
value="ip">
25+
</el-option>
26+
<el-option
27+
label="远端地址"
28+
value="remote_addr">
29+
</el-option>
30+
</el-select>
31+
</el-form-item>
32+
<el-form-item>
33+
<el-input
34+
v-model="searchText"
35+
placeholder="请输入搜索内容"
36+
@input="handleSearch">
37+
</el-input>
38+
</el-form-item>
39+
<el-form-item>
40+
显示休眠用户:
41+
<el-switch
42+
v-model="showSleeper"
43+
@change="handleSearch">
44+
</el-switch>
45+
</el-form-item>
46+
<el-form-item>
47+
<el-button
48+
class="extra-small-button"
49+
type="danger"
50+
size="mini"
51+
:loading="loadingOneOffline"
52+
@click="handleOneOffline">
53+
一键下线
54+
</el-button>
55+
</el-form>
56+
457
<el-table
558
ref="multipleTable"
659
:data="tableData"
@@ -20,14 +73,14 @@
2073

2174
<el-table-column
2275
prop="group"
23-
label="登陆组">
76+
label="登录组">
2477
</el-table-column>
2578

2679
<el-table-column
2780
prop="mac_addr"
2881
label="MAC地址">
2982
</el-table-column>
30-
83+
3184
<el-table-column
3285
prop="unique_mac"
3386
label="唯一MAC">
@@ -67,7 +120,6 @@
67120
</el-table-column>
68121

69122
<el-table-column
70-
prop="status"
71123
label="实时 上行/下行"
72124
width="220">
73125
<template slot-scope="scope">
@@ -77,7 +129,6 @@
77129
</el-table-column>
78130

79131
<el-table-column
80-
prop="status"
81132
label="总量 上行/下行"
82133
width="200">
83134
<template slot-scope="scope">
@@ -88,7 +139,7 @@
88139

89140
<el-table-column
90141
prop="last_login"
91-
label="登陆时间"
142+
label="登录时间"
92143
:formatter="tableDateFormat">
93144
</el-table-column>
94145

@@ -99,6 +150,7 @@
99150
<el-button
100151
size="mini"
101152
type="primary"
153+
v-if="scope.row.remote_addr !== ''"
102154
@click="handleReline(scope.row)">重连
103155
</el-button>
104156

@@ -123,6 +175,7 @@
123175

124176
<script>
125177
import axios from "axios";
178+
import { MessageBox } from 'element-ui';
126179
127180
export default {
128181
name: "Online",
@@ -147,6 +200,10 @@ export default {
147200
data() {
148201
return {
149202
tableData: [],
203+
searchCate: 'username',
204+
searchText: '',
205+
showSleeper: false,
206+
loadingOneOffline: false,
150207
}
151208
},
152209
methods: {
@@ -185,8 +242,43 @@ export default {
185242
handleEdit(a, row) {
186243
console.log(a, row)
187244
},
245+
handleOneOffline() {
246+
if (this.tableData === null || this.tableData.length === 0) {
247+
this.$message.error('错误:当前在线用户表为空,无法执行一键下线操作!');
248+
return;
249+
}
250+
MessageBox.confirm('当前搜索条件下的所有用户将会“下线”,你确定执行吗?', '危险', {
251+
confirmButtonText: '确定',
252+
cancelButtonText: '取消',
253+
type: 'danger'
254+
}).then(() => {
255+
try {
256+
this.loadingOneOffline = true;
257+
this.getData();
258+
this.$message.success('操作成功');
259+
this.loadingOneOffline = false;
260+
// 清空当前表格
261+
this.tableData = [];
262+
} catch (error) {
263+
this.loadingOneOffline = false;
264+
this.$message.error('操作失败');
265+
}
266+
});
267+
},
268+
handleSearch() {
269+
this.getData();
270+
},
188271
getData() {
189-
axios.get('/user/online').then(resp => {
272+
axios.get('/user/online',
273+
{
274+
params: {
275+
search_cate: this.searchCate,
276+
search_text: this.searchText,
277+
show_sleeper: this.showSleeper,
278+
one_offline: this.loadingOneOffline
279+
}
280+
}
281+
).then(resp => {
190282
var data = resp.data.data
191283
console.log(data);
192284
this.tableData = data.datas;
@@ -201,5 +293,23 @@ export default {
201293
</script>
202294

203295
<style scoped>
204-
296+
/deep/ .el-form .el-form-item__label,
297+
/deep/ .el-form .el-form-item__content,
298+
/deep/ .el-form .el-input,
299+
/deep/ .el-form .el-select,
300+
/deep/ .el-form .el-button,
301+
/deep/ .el-form .el-select-dropdown__item {
302+
font-size: 11px;
303+
}
304+
.el-select-dropdown .el-select-dropdown__item {
305+
font-size: 11px;
306+
padding: 0 10px;
307+
}
308+
/deep/ .el-input__inner{
309+
height: 30px;
310+
padding: 0 10px;
311+
}
312+
.extra-small-button {
313+
padding: 5px 10px;
314+
}
205315
</style>

0 commit comments

Comments
 (0)