feat: 新增linux文件上传成功后websocket通知

This commit is contained in:
meilin.huang
2021-11-11 15:56:02 +08:00
parent f6fb732911
commit 78d6c3d1a4
26 changed files with 379 additions and 150 deletions

27
base/ws/msg.go Normal file
View File

@@ -0,0 +1,27 @@
package ws
const SuccessMsgType = 1
const ErrorMsgType = 0
const InfoMsgType = 2
// websocket消息
type Msg struct {
Type int `json:"type"` // 消息类型
Title string `json:"title"` // 消息标题
Msg string `json:"msg"` // 消息内容
}
// 普通消息
func NewMsg(title, msg string) *Msg {
return &Msg{Type: InfoMsgType, Title: title, Msg: msg}
}
// 成功消息
func SuccessMsg(title, msg string) *Msg {
return &Msg{Type: SuccessMsgType, Title: title, Msg: msg}
}
// 错误消息
func ErrMsg(title, msg string) *Msg {
return &Msg{Type: ErrorMsgType, Title: title, Msg: msg}
}

32
base/ws/ws.go Normal file
View File

@@ -0,0 +1,32 @@
package ws
import (
"encoding/json"
"net/http"
"github.com/gorilla/websocket"
)
var Upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024 * 1024 * 10,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
var conns = make(map[uint64]*websocket.Conn, 100)
// 放置ws连接
func Put(userId uint64, conn *websocket.Conn) {
conns[userId] = conn
}
// 对指定用户发送消息
func SendMsg(userId uint64, msg *Msg) {
conn := conns[userId]
if conn != nil {
bytes, _ := json.Marshal(msg)
conn.WriteMessage(websocket.TextMessage, bytes)
}
}

View File

@@ -0,0 +1,47 @@
class SocketBuilder {
websocket: WebSocket;
constructor(url: string) {
if (typeof (WebSocket) === "undefined") {
throw new Error('不支持websocket');
}
if (!url) {
throw new Error('websocket url不能为空');
}
console.log(url)
this.websocket = new WebSocket(url);
}
static builder(url: string) {
return new SocketBuilder(url);
}
open(onopen: any) {
this.websocket.onopen = onopen;
return this;
}
error(onerror: any) {
this.websocket.onerror = onerror;
return this;
}
message(onmessage: any) {
this.websocket.onmessage = onmessage;
return this;
}
close(onclose: any) {
this.websocket.onclose = onclose;
return this;
}
build() {
return this.websocket;
}
}
export default SocketBuilder;

View File

@@ -0,0 +1,44 @@
import Config from './config'
import { ElNotification } from 'element-plus'
import SocketBuilder from './SocketBuilder';
import { getSession } from '@/common/utils/storage.ts';
export default {
/**
* 全局系统消息websocket
*/
sysMsgSocket() {
const token = getSession('token');
if (!token) {
return null;
}
return SocketBuilder.builder(`${Config.baseWsUrl}/sysmsg?token=${token}`)
.message((event: { data: string }) => {
const message = JSON.parse(event.data);
let mtype: string;
switch (message.type) {
case 0:
mtype = 'error';
break;
case 2:
mtype = 'info';
break;
case 1:
mtype = 'success';
break;
default:
mtype = 'info';
}
if (mtype == undefined) {
return;
}
ElNotification({
title: message.title,
message: message.msg,
type: mtype as any,
})
})
.open((event: any) => console.log(event)).build();
}
}

View File

@@ -8,6 +8,7 @@ import { NextLoading } from '@/common/utils/loading.ts';
import { dynamicRoutes, staticRoutes, pathMatch } from './route.ts' import { dynamicRoutes, staticRoutes, pathMatch } from './route.ts'
import { imports } from './imports'; import { imports } from './imports';
import openApi from '@/common/openApi'; import openApi from '@/common/openApi';
import sockets from '@/common/sockets';
// 添加静态路由 // 添加静态路由
const router = createRouter({ const router = createRouter({
@@ -203,6 +204,9 @@ if (!isRequestRoutes) {
initBackEndControlRoutesFun(); initBackEndControlRoutesFun();
} }
let SysWs: any;
// 路由加载前 // 路由加载前
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
NProgress.configure({ showSpinner: false }); NProgress.configure({ showSpinner: false });
@@ -223,10 +227,18 @@ router.beforeEach((to, from, next) => {
clearSession(); clearSession();
resetRoute(); resetRoute();
NProgress.done(); NProgress.done();
if (SysWs) {
SysWs.close();
SysWs = null;
}
} else if (token && to.path === '/login') { } else if (token && to.path === '/login') {
next('/'); next('/');
NProgress.done(); NProgress.done();
} else { } else {
if (!SysWs) {
SysWs = sockets.sysMsgSocket();
}
if (store.state.routesList.routesList.length > 0) next(); if (store.state.routesList.routesList.length > 0) next();
} }
} }

View File

@@ -93,9 +93,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { toRefs, reactive, onMounted, nextTick, computed, getCurrentInstance } from 'vue'; import { toRefs, reactive, onMounted, nextTick, computed } from 'vue';
import { useStore } from '@/store/index.ts'; import { useStore } from '@/store/index.ts';
import * as echarts from 'echarts'; // import * as echarts from 'echarts';
import { CountUp } from 'countup.js'; import { CountUp } from 'countup.js';
import { formatAxis } from '@/common/utils/formatTime.ts'; import { formatAxis } from '@/common/utils/formatTime.ts';
import { indexApi } from './api'; import { indexApi } from './api';
@@ -103,7 +103,7 @@ import { topCardItemList, environmentList, activitiesList } from './mock.ts';
export default { export default {
name: 'Home', name: 'Home',
setup() { setup() {
const { proxy } = getCurrentInstance() as any; // const { proxy } = getCurrentInstance() as any;
const store = useStore(); const store = useStore();
const state = reactive({ const state = reactive({
topCardItemList, topCardItemList,
@@ -146,104 +146,104 @@ export default {
}); });
}; };
// 实验室使用情况 // // 实验室使用情况
const initHomeLaboratory = () => { // const initHomeLaboratory = () => {
const myChart = echarts.init(proxy.$refs.homeLaboratoryRef); // const myChart = echarts.init(proxy.$refs.homeLaboratoryRef);
const option = { // const option = {
grid: { // grid: {
top: 50, // top: 50,
right: 20, // right: 20,
bottom: 30, // bottom: 30,
left: 30, // left: 30,
}, // },
tooltip: { // tooltip: {
trigger: 'axis', // trigger: 'axis',
}, // },
legend: { // legend: {
data: ['预购队列', '最新成交价'], // data: ['预购队列', '最新成交价'],
right: 13, // right: 13,
}, // },
xAxis: { // xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'], // data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
}, // },
yAxis: [ // yAxis: [
{ // {
type: 'value', // type: 'value',
name: '价格', // name: '价格',
}, // },
], // ],
series: [ // series: [
{ // {
name: '预购队列', // name: '预购队列',
type: 'bar', // type: 'bar',
data: [5, 20, 36, 10, 10, 20], // data: [5, 20, 36, 10, 10, 20],
}, // },
{ // {
name: '最新成交价', // name: '最新成交价',
type: 'line', // type: 'line',
data: [15, 20, 16, 20, 30, 8], // data: [15, 20, 16, 20, 30, 8],
}, // },
], // ],
}; // };
myChart.setOption(option); // myChart.setOption(option);
window.addEventListener('resize', () => { // window.addEventListener('resize', () => {
myChart.resize(); // myChart.resize();
}); // });
}; // };
// 履约超时预警 // // 履约超时预警
const initHomeOvertime = () => { // const initHomeOvertime = () => {
const myChart = echarts.init(proxy.$refs.homeOvertimeRef); // const myChart = echarts.init(proxy.$refs.homeOvertimeRef);
const option = { // const option = {
grid: { // grid: {
top: 50, // top: 50,
right: 20, // right: 20,
bottom: 30, // bottom: 30,
left: 30, // left: 30,
}, // },
tooltip: { // tooltip: {
trigger: 'axis', // trigger: 'axis',
}, // },
legend: { // legend: {
data: ['订单数量', '超时数量', '在线数量', '预警数量'], // data: ['订单数量', '超时数量', '在线数量', '预警数量'],
right: 13, // right: 13,
}, // },
xAxis: { // xAxis: {
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], // data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
}, // },
yAxis: [ // yAxis: [
{ // {
type: 'value', // type: 'value',
name: '数量', // name: '数量',
}, // },
], // ],
series: [ // series: [
{ // {
name: '订单数量', // name: '订单数量',
type: 'bar', // type: 'bar',
data: [5, 20, 36, 10, 10, 20, 11, 13, 10, 9, 17, 19], // data: [5, 20, 36, 10, 10, 20, 11, 13, 10, 9, 17, 19],
}, // },
{ // {
name: '超时数量', // name: '超时数量',
type: 'bar', // type: 'bar',
data: [15, 12, 26, 15, 11, 16, 31, 13, 5, 16, 13, 15], // data: [15, 12, 26, 15, 11, 16, 31, 13, 5, 16, 13, 15],
}, // },
{ // {
name: '在线数量', // name: '在线数量',
type: 'line', // type: 'line',
data: [15, 20, 16, 20, 30, 8, 16, 19, 12, 18, 19, 14], // data: [15, 20, 16, 20, 30, 8, 16, 19, 12, 18, 19, 14],
}, // },
{ // {
name: '预警数量', // name: '预警数量',
type: 'line', // type: 'line',
data: [10, 10, 13, 12, 15, 18, 19, 10, 12, 15, 11, 17], // data: [10, 10, 13, 12, 15, 18, 19, 10, 12, 15, 11, 17],
}, // },
], // ],
}; // };
myChart.setOption(option); // myChart.setOption(option);
window.addEventListener('resize', () => { // window.addEventListener('resize', () => {
myChart.resize(); // myChart.resize();
}); // });
}; // };
// 页面加载时 // 页面加载时
onMounted(() => { onMounted(() => {
initNumCountUp(); initNumCountUp();

View File

@@ -451,9 +451,7 @@ export default defineComponent({
}; };
const uploadSuccess = (res: any) => { const uploadSuccess = (res: any) => {
if (res.code == 200) { if (res.code !== 200) {
ElMessage.success('文件上传中...');
} else {
ElMessage.error(res.msg); ElMessage.error(res.msg);
} }
}; };

View File

@@ -217,6 +217,9 @@ export default {
if (type == 1) { if (type == 1) {
return '登录'; return '登录';
} }
if (type == 2) {
return '通知';
}
}; };
return { return {

View File

@@ -5,26 +5,18 @@ import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"
"mayfly-go/base/ginx" "mayfly-go/base/ginx"
"mayfly-go/base/utils" "mayfly-go/base/utils"
"mayfly-go/base/ws"
"mayfly-go/server/devops/api/form" "mayfly-go/server/devops/api/form"
"mayfly-go/server/devops/api/vo" "mayfly-go/server/devops/api/vo"
"mayfly-go/server/devops/application" "mayfly-go/server/devops/application"
"mayfly-go/server/devops/domain/entity" "mayfly-go/server/devops/domain/entity"
"mayfly-go/server/devops/infrastructure/machine" "mayfly-go/server/devops/infrastructure/machine"
"net/http"
"strconv" "strconv"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
var WsUpgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024 * 1024 * 10,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
type Machine struct { type Machine struct {
MachineApp application.Machine MachineApp application.Machine
} }
@@ -62,7 +54,7 @@ func (m *Machine) CloseCli(rc *ctx.ReqCtx) {
} }
func (m *Machine) WsSSH(g *gin.Context) { func (m *Machine) WsSSH(g *gin.Context) {
wsConn, err := WsUpgrader.Upgrade(g.Writer, g.Request, nil) wsConn, err := ws.Upgrader.Upgrade(g.Writer, g.Request, nil)
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
wsConn.WriteMessage(websocket.TextMessage, []byte(err.(error).Error())) wsConn.WriteMessage(websocket.TextMessage, []byte(err.(error).Error()))
@@ -79,9 +71,9 @@ func (m *Machine) WsSSH(g *gin.Context) {
panic(biz.NewBizErr("没有权限")) panic(biz.NewBizErr("没有权限"))
} }
// 演示环境禁止非admin用户执行 // 演示环境禁止非admin用户执行
if rc.LoginAccount.Username != "admin" { // if rc.LoginAccount.Username != "admin" {
panic(biz.NewBizErrCode(401, "非admin用户无权该操作")) // panic(biz.NewBizErrCode(401, "非admin用户无权该操作"))
} // }
cols := ginx.QueryInt(g, "cols", 80) cols := ginx.QueryInt(g, "cols", 80)
rows := ginx.QueryInt(g, "rows", 40) rows := ginx.QueryInt(g, "rows", 40)

View File

@@ -8,6 +8,7 @@ import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"
"mayfly-go/base/ginx" "mayfly-go/base/ginx"
"mayfly-go/base/utils" "mayfly-go/base/utils"
"mayfly-go/base/ws"
"mayfly-go/server/devops/api/form" "mayfly-go/server/devops/api/form"
"mayfly-go/server/devops/api/vo" "mayfly-go/server/devops/api/vo"
"mayfly-go/server/devops/application" "mayfly-go/server/devops/application"
@@ -121,10 +122,12 @@ func (m *MachineFile) UploadFile(rc *ctx.ReqCtx) {
path := g.PostForm("path") path := g.PostForm("path")
fileheader, err := g.FormFile("file") fileheader, err := g.FormFile("file")
biz.ErrIsNilAppendErr(err, "读取文件失败: %s") biz.ErrIsNilAppendErr(err, "读取文件失败: %s")
// 通知正在上传
ws.SendMsg(rc.LoginAccount.Id, ws.NewMsg("文件上传", "文件上传中..."))
file, _ := fileheader.Open() file, _ := fileheader.Open()
bytes, err := ioutil.ReadAll(file) bytes, _ := ioutil.ReadAll(file)
go m.MachineFileApp.UploadFile(fid, path, fileheader.Filename, bytes) go m.MachineFileApp.UploadFile(rc.LoginAccount, fid, path, fileheader.Filename, bytes)
rc.ReqParam = fmt.Sprintf("path: %s", path) rc.ReqParam = fmt.Sprintf("path: %s", path)
} }

View File

@@ -1,14 +1,17 @@
package application package application
import ( import (
"fmt"
"io" "io"
"io/fs" "io/fs"
"io/ioutil" "io/ioutil"
"mayfly-go/base/biz" "mayfly-go/base/biz"
"mayfly-go/base/model" "mayfly-go/base/model"
"mayfly-go/base/ws"
"mayfly-go/server/devops/domain/entity" "mayfly-go/server/devops/domain/entity"
"mayfly-go/server/devops/domain/repository" "mayfly-go/server/devops/domain/repository"
"mayfly-go/server/devops/infrastructure/persistence" "mayfly-go/server/devops/infrastructure/persistence"
sysApplication "mayfly-go/server/sys/application"
"os" "os"
"strings" "strings"
@@ -41,7 +44,7 @@ type MachineFile interface {
WriteFileContent(fileId uint64, path string, content []byte) WriteFileContent(fileId uint64, path string, content []byte)
// 文件上传 // 文件上传
UploadFile(fileId uint64, path, filename string, content []byte) UploadFile(la *model.LoginAccount, fileId uint64, path, filename string, content []byte)
// 移除文件 // 移除文件
RemoveFile(fileId uint64, path string) RemoveFile(fileId uint64, path string)
@@ -50,12 +53,14 @@ type MachineFile interface {
type machineFileAppImpl struct { type machineFileAppImpl struct {
machineFileRepo repository.MachineFile machineFileRepo repository.MachineFile
machineRepo repository.Machine machineRepo repository.Machine
msgApp sysApplication.Msg
} }
// 实现类单例 // 实现类单例
var MachineFileApp MachineFile = &machineFileAppImpl{ var MachineFileApp MachineFile = &machineFileAppImpl{
machineRepo: persistence.MachineDao, machineRepo: persistence.MachineDao,
machineFileRepo: persistence.MachineFileDao, machineFileRepo: persistence.MachineFileDao,
msgApp: sysApplication.MsgApp,
} }
// 分页获取机器脚本信息列表 // 分页获取机器脚本信息列表
@@ -133,7 +138,7 @@ func (m *machineFileAppImpl) WriteFileContent(fileId uint64, path string, conten
} }
// 上传文件 // 上传文件
func (m *machineFileAppImpl) UploadFile(fileId uint64, path, filename string, content []byte) { func (m *machineFileAppImpl) UploadFile(la *model.LoginAccount, fileId uint64, path, filename string, content []byte) {
path, machineId := m.checkAndReturnPathMid(fileId, path) path, machineId := m.checkAndReturnPathMid(fileId, path)
if !strings.HasSuffix(path, "/") { if !strings.HasSuffix(path, "/") {
path = path + "/" path = path + "/"
@@ -145,6 +150,9 @@ func (m *machineFileAppImpl) UploadFile(fileId uint64, path, filename string, co
defer createfile.Close() defer createfile.Close()
createfile.Write(content) createfile.Write(content)
// 保存消息并发送文件上传成功通知
m.msgApp.CreateAndSend(la, ws.SuccessMsg("文件上传", fmt.Sprintf("[%s]文件已成功上传至[%s]", filename, path)))
} }
// 删除文件 // 删除文件

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"
@@ -10,31 +10,31 @@ import (
func InitMachineRouter(router *gin.RouterGroup) { func InitMachineRouter(router *gin.RouterGroup) {
m := &api.Machine{MachineApp: application.MachineApp} m := &api.Machine{MachineApp: application.MachineApp}
db := router.Group("machines") machines := router.Group("machines")
{ {
db.GET("", func(c *gin.Context) { machines.GET("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.Machines) ctx.NewReqCtxWithGin(c).Handle(m.Machines)
}) })
saveMachine := ctx.NewLogInfo("保存机器信息") saveMachine := ctx.NewLogInfo("保存机器信息")
db.POST("", func(c *gin.Context) { machines.POST("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c). ctx.NewReqCtxWithGin(c).
WithLog(saveMachine). WithLog(saveMachine).
Handle(m.SaveMachine) Handle(m.SaveMachine)
}) })
delMachine := ctx.NewLogInfo("删除机器") delMachine := ctx.NewLogInfo("删除机器")
db.DELETE(":machineId", func(c *gin.Context) { machines.DELETE(":machineId", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c). ctx.NewReqCtxWithGin(c).
WithLog(delMachine). WithLog(delMachine).
Handle(m.DeleteMachine) Handle(m.DeleteMachine)
}) })
closeCli := ctx.NewLogInfo("关闭机器客户端") closeCli := ctx.NewLogInfo("关闭机器客户端")
db.DELETE(":machineId/close-cli", func(c *gin.Context) { machines.DELETE(":machineId/close-cli", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(closeCli).Handle(m.CloseCli) ctx.NewReqCtxWithGin(c).WithLog(closeCli).Handle(m.CloseCli)
}) })
db.GET(":machineId/terminal", m.WsSSH) machines.GET(":machineId/terminal", m.WsSSH)
} }
} }

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"
@@ -49,7 +49,7 @@ func InitProjectRouter(router *gin.RouterGroup) {
}) })
saveProjectEnvLog := ctx.NewLogInfo("新增项目环境信息") saveProjectEnvLog := ctx.NewLogInfo("新增项目环境信息")
savePeP := ctx.NewPermission("project:env:save") savePeP := ctx.NewPermission("project:env:add")
// 保存项目下的环境信息 // 保存项目下的环境信息
project.POST("/:projectId/envs", func(c *gin.Context) { project.POST("/:projectId/envs", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(saveProjectEnvLog). ctx.NewReqCtxWithGin(c).WithLog(saveProjectEnvLog).

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -53,6 +53,7 @@ func InitRouter() *gin.Engine {
sys_router.InitAccountRouter(api) // 注册account路由 sys_router.InitAccountRouter(api) // 注册account路由
sys_router.InitResourceRouter(api) sys_router.InitResourceRouter(api)
sys_router.InitRoleRouter(api) sys_router.InitRoleRouter(api)
sys_router.InitSystemRouter(api)
devops_router.InitProjectRouter(api) devops_router.InitProjectRouter(api)
devops_router.InitDbRouter(api) devops_router.InitDbRouter(api)

View File

@@ -6,8 +6,6 @@ import (
"mayfly-go/base/captcha" "mayfly-go/base/captcha"
"mayfly-go/base/ctx" "mayfly-go/base/ctx"
"mayfly-go/base/ginx" "mayfly-go/base/ginx"
"mayfly-go/base/global"
"mayfly-go/base/httpclient"
"mayfly-go/base/utils" "mayfly-go/base/utils"
"mayfly-go/server/sys/api/form" "mayfly-go/server/sys/api/form"
"mayfly-go/server/sys/api/vo" "mayfly-go/server/sys/api/vo"
@@ -89,16 +87,16 @@ func (a *Account) saveLogin(account *entity.Account, ip string) {
loginMsg.CreatorId = account.Id loginMsg.CreatorId = account.Id
a.MsgApp.Create(loginMsg) a.MsgApp.Create(loginMsg)
bodyMap, err := httpclient.NewRequest(fmt.Sprintf("http://ip-api.com/json/%s?lang=zh-CN", ip)).Get().BodyToMap() // bodyMap, err := httpclient.NewRequest(fmt.Sprintf("http://ip-api.com/json/%s?lang=zh-CN", ip)).Get().BodyToMap()
if err != nil { // if err != nil {
global.Log.Errorf("获取客户端ip地址信息失败%s", err.Error()) // global.Log.Errorf("获取客户端ip地址信息失败%s", err.Error())
return // return
} // }
if bodyMap["status"].(string) == "fail" { // if bodyMap["status"].(string) == "fail" {
return // return
} // }
msg := fmt.Sprintf("%s于%s-%s登录", account.Username, bodyMap["regionName"], bodyMap["city"]) // msg := fmt.Sprintf("%s于%s-%s登录", account.Username, bodyMap["regionName"], bodyMap["city"])
global.Log.Info(msg) // global.Log.Info(msg)
} }
// 获取个人账号信息 // 获取个人账号信息

36
server/sys/api/system.go Normal file
View File

@@ -0,0 +1,36 @@
package api
import (
"mayfly-go/base/biz"
"mayfly-go/base/ctx"
"mayfly-go/base/ws"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
type System struct {
}
// 连接websocket
func (s *System) ConnectWs(g *gin.Context) {
wsConn, err := ws.Upgrader.Upgrade(g.Writer, g.Request, nil)
defer func() {
if err := recover(); err != nil {
wsConn.WriteMessage(websocket.TextMessage, []byte(err.(error).Error()))
wsConn.Close()
}
}()
if err != nil {
panic(biz.NewBizErr("升级websocket失败"))
}
// 权限校验
rc := ctx.NewReqCtxWithGin(g)
if err = ctx.PermissionHandler(rc); err != nil {
panic(biz.NewBizErr("没有权限"))
}
// 登录账号信息
la := rc.LoginAccount
ws.Put(la.Id, wsConn)
}

View File

@@ -2,15 +2,20 @@ package application
import ( import (
"mayfly-go/base/model" "mayfly-go/base/model"
"mayfly-go/base/ws"
"mayfly-go/server/sys/domain/entity" "mayfly-go/server/sys/domain/entity"
"mayfly-go/server/sys/domain/repository" "mayfly-go/server/sys/domain/repository"
"mayfly-go/server/sys/infrastructure/persistence" "mayfly-go/server/sys/infrastructure/persistence"
"time"
) )
type Msg interface { type Msg interface {
GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Create(msg *entity.Msg) Create(msg *entity.Msg)
// 创建消息并通过ws发送
CreateAndSend(la *model.LoginAccount, msg *ws.Msg)
} }
type msgAppImpl struct { type msgAppImpl struct {
@@ -28,3 +33,10 @@ func (a *msgAppImpl) GetPageList(condition *entity.Msg, pageParam *model.PagePar
func (a *msgAppImpl) Create(msg *entity.Msg) { func (a *msgAppImpl) Create(msg *entity.Msg) {
a.msgRepo.Insert(msg) a.msgRepo.Insert(msg)
} }
func (a *msgAppImpl) CreateAndSend(la *model.LoginAccount, wmsg *ws.Msg) {
now := time.Now()
msg := &entity.Msg{Type: 2, Msg: wmsg.Msg, RecipientId: int64(la.Id), CreateTime: &now, CreatorId: la.Id, Creator: la.Username}
a.msgRepo.Insert(msg)
ws.SendMsg(la.Id, wmsg)
}

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -1,4 +1,4 @@
package routers package router
import ( import (
"mayfly-go/base/ctx" "mayfly-go/base/ctx"

View File

@@ -0,0 +1,16 @@
package router
import (
"mayfly-go/server/sys/api"
"github.com/gin-gonic/gin"
)
func InitSystemRouter(router *gin.RouterGroup) {
s := &api.System{}
sys := router.Group("sysmsg")
{
sys.GET("", s.ConnectWs)
}
}