mirror of
https://gitee.com/xiangheng/x_admin.git
synced 2025-09-26 20:21:19 +08:00
完善slow
This commit is contained in:
@@ -13,6 +13,21 @@
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<script src="/XErr.umd.js"></script>
|
||||
<script>
|
||||
const xErr = new XErr.XErr(
|
||||
{
|
||||
Dns: `${location.origin}/api`,
|
||||
Pid: 'e19e3be20de94f49b68fafb4c30668bc',
|
||||
Uid: ''
|
||||
},
|
||||
new XErr.XErrWeb({
|
||||
onloadTimeOut: 300
|
||||
})
|
||||
)
|
||||
xErr.SetUid(2) //设置用户ID
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="/src/styles/loading.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
3
admin/public/XErr.umd.js
Normal file
3
admin/public/XErr.umd.js
Normal file
File diff suppressed because one or more lines are too long
@@ -11,19 +11,18 @@ import ElementPlus from 'element-plus'
|
||||
|
||||
import VForm3 from 'vform3-builds' //引入VForm3库
|
||||
|
||||
import { XErr, XErrWeb } from '../../x_err_sdk/web/index'
|
||||
// { XErr, XErrWeb }
|
||||
const xErr = new XErr(
|
||||
{
|
||||
Dns: `${location.origin}/api`,
|
||||
Pid: 'e19e3be20de94f49b68fafb4c30668bc',
|
||||
Uid: ''
|
||||
},
|
||||
new XErrWeb({
|
||||
onloadTimeOut: 3000
|
||||
})
|
||||
)
|
||||
xErr.SetUid(1) //设置用户ID
|
||||
// import { Base, Web } from '../../x_err_sdk/web/index'
|
||||
// const xErr = new Base(
|
||||
// {
|
||||
// Dns: `${location.origin}/api`,
|
||||
// Pid: 'e19e3be20de94f49b68fafb4c30668bc',
|
||||
// Uid: ''
|
||||
// },
|
||||
// new Web({
|
||||
// onloadTimeOut: 300
|
||||
// })
|
||||
// )
|
||||
// xErr.SetUid(1) //设置用户ID
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(install)
|
||||
|
@@ -97,10 +97,12 @@ const code = computed(() => {
|
||||
new XErr(
|
||||
{
|
||||
Dns: '${location.origin}/api',
|
||||
Pid: ${formData.ProjectKey},
|
||||
Pid: '${formData.ProjectKey}',
|
||||
Uid: ''
|
||||
},
|
||||
new XErrWeb()
|
||||
new XErrWeb({
|
||||
onloadTimeOut: 3000
|
||||
})
|
||||
)`
|
||||
})
|
||||
const formRules = {
|
||||
|
@@ -9,16 +9,22 @@
|
||||
label-width="70px"
|
||||
label-position="left"
|
||||
>
|
||||
<el-form-item label="项目key" prop="ProjectKey" class="w-[280px]">
|
||||
<el-input v-model="queryParams.ProjectKey" />
|
||||
</el-form-item>
|
||||
<el-form-item label="sdk生成的客户端id" prop="ClientId" class="w-[280px]">
|
||||
<el-input v-model="queryParams.ClientId" />
|
||||
<el-form-item label="项目" prop="ProjectKey" class="w-[280px]">
|
||||
<el-select v-model="queryParams.ProjectKey" clearable>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option
|
||||
v-for="(item, index) in listAllData.monitor_project_listAll"
|
||||
:key="index"
|
||||
:label="item.ProjectName"
|
||||
:value="item.ProjectKey"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="用户id" prop="UserId" class="w-[280px]">
|
||||
<el-input v-model="queryParams.UserId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="CreateTime" class="w-[280px]">
|
||||
<el-form-item label="创建时间" prop="CreateTime" class="w-[420px]">
|
||||
<daterange-picker
|
||||
v-model:startTime="queryParams.CreateTimeStart"
|
||||
v-model:endTime="queryParams.CreateTimeEnd"
|
||||
@@ -32,13 +38,13 @@
|
||||
</el-card>
|
||||
<el-card class="!border-none mt-4" shadow="never">
|
||||
<div class="text-right">
|
||||
<el-button v-perms="['admin:monitor_slow:add']" type="primary" @click="handleAdd()">
|
||||
<!-- <el-button v-perms="['admin:monitor_slow:add']" type="primary" @click="handleAdd()">
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
新增
|
||||
</el-button>
|
||||
<upload
|
||||
</el-button> -->
|
||||
<!-- <upload
|
||||
v-perms="['admin:monitor_slow:ImportFile']"
|
||||
class="ml-3 mr-3"
|
||||
:url="monitor_slow_import_file"
|
||||
@@ -53,8 +59,8 @@
|
||||
</template>
|
||||
导入
|
||||
</el-button>
|
||||
</upload>
|
||||
<el-button
|
||||
</upload> -->
|
||||
<!-- <el-button
|
||||
v-perms="['admin:monitor_slow:ExportFile']"
|
||||
type="primary"
|
||||
@click="exportFile"
|
||||
@@ -63,7 +69,7 @@
|
||||
<icon name="el-icon-Download" />
|
||||
</template>
|
||||
导出
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
<el-button
|
||||
v-perms="['admin:monitor_slow:delBatch']"
|
||||
type="danger"
|
||||
@@ -81,22 +87,31 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="项目key" prop="ProjectKey" min-width="130" />
|
||||
<el-table-column label="sdk生成的客户端id" prop="ClientId" min-width="130" />
|
||||
<el-table-column label="用户id" prop="UserId" min-width="130" />
|
||||
<el-table-column label="URL地址" prop="Path" min-width="130" />
|
||||
<el-table-column label="时间" prop="Time" min-width="130" />
|
||||
<el-table-column label="创建时间" prop="CreateTime" min-width="130" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<el-table-column label="项目" prop="ProjectKey" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
<dict-value
|
||||
:options="listAllData.monitor_project_listAll"
|
||||
:value="row.ProjectKey"
|
||||
labelKey="ProjectName"
|
||||
valueKey="ProjectKey"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="用户id" prop="UserId" width="150" />
|
||||
<el-table-column label="URL地址" prop="Path" />
|
||||
<el-table-column label="时间(毫秒)" prop="Time" width="130" />
|
||||
<el-table-column label="创建时间" prop="CreateTime" width="180" />
|
||||
<el-table-column label="操作" width="80" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<!-- <el-button
|
||||
v-perms="['admin:monitor_slow:edit']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
<el-button
|
||||
v-perms="['admin:monitor_slow:del']"
|
||||
type="danger"
|
||||
@@ -116,16 +131,15 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, shallowRef, nextTick } from 'vue'
|
||||
import { ref, reactive, shallowRef } from 'vue'
|
||||
import {
|
||||
monitor_slow_delete,
|
||||
monitor_slow_delete_batch,
|
||||
monitor_slow_list,
|
||||
monitor_slow_import_file,
|
||||
monitor_slow_export_file
|
||||
monitor_slow_list
|
||||
} from '@/api/monitor/slow'
|
||||
import type { type_monitor_slow, type_monitor_slow_query } from '@/api/monitor/slow'
|
||||
|
||||
import { useListAllData } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import EditPopup from './edit.vue'
|
||||
@@ -148,19 +162,12 @@ const { pager, getLists, resetPage, resetParams } = usePaging<type_monitor_slow>
|
||||
fetchFun: monitor_slow_list,
|
||||
params: queryParams
|
||||
})
|
||||
const { listAllData } = useListAllData<{
|
||||
monitor_project_listAll: any[]
|
||||
}>({
|
||||
monitor_project_listAll: '/monitor_project/listAll'
|
||||
})
|
||||
|
||||
const handleAdd = async () => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('add')
|
||||
}
|
||||
|
||||
const handleEdit = async (data: any) => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('edit')
|
||||
editRef.value?.getDetail(data)
|
||||
}
|
||||
const multipleSelection = ref<type_monitor_slow[]>([])
|
||||
const handleSelectionChange = (val: type_monitor_slow[]) => {
|
||||
console.log(val)
|
||||
@@ -191,11 +198,5 @@ const deleteBatch = async () => {
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
const exportFile = async () => {
|
||||
try {
|
||||
await feedback.confirm('确定要导出?')
|
||||
await monitor_slow_export_file(queryParams)
|
||||
} catch (error) {}
|
||||
}
|
||||
getLists()
|
||||
</script>
|
||||
|
@@ -23,10 +23,12 @@ export default ({ mode }) => {
|
||||
// 依赖预构建,避免开发刷新
|
||||
include: ['@wangeditor/editor-for-vue', 'vuedraggable', 'vue-echarts', 'crypto-js']
|
||||
},
|
||||
|
||||
base: '/',
|
||||
build: {
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
external: ['XErr'],
|
||||
output: {
|
||||
manualChunks: {
|
||||
vue: ['vue'],
|
||||
|
@@ -13,6 +13,7 @@ import (
|
||||
"x_admin/core/response"
|
||||
"x_admin/util"
|
||||
"x_admin/util/excel2"
|
||||
"x_admin/util/img_util"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/sync/singleflight"
|
||||
@@ -141,28 +142,24 @@ func (hd *MonitorClientHandler) Add(c *gin.Context) {
|
||||
data, err := url.QueryUnescape(c.Query("data"))
|
||||
if err != nil {
|
||||
// response.CheckAndRespWithData(c, 0, err)
|
||||
c.Writer.WriteString("0")
|
||||
c.Data(200, "image/gif", img_util.EmptyGif())
|
||||
return
|
||||
}
|
||||
var addReq MonitorClientAddReq
|
||||
json.Unmarshal([]byte(data), &addReq)
|
||||
// if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) {
|
||||
// return
|
||||
// }
|
||||
|
||||
lastClient, err := MonitorClientService.DetailByClientId(*addReq.ClientId)
|
||||
|
||||
uaStr := c.GetHeader("user-agent")
|
||||
ip := c.ClientIP()
|
||||
|
||||
// createFlag := true
|
||||
if err == nil {
|
||||
last := lastClient.UserId + lastClient.Width.String() + lastClient.Height.String() + lastClient.Ip + lastClient.Ua
|
||||
newStr := *addReq.UserId + addReq.Width.String() + addReq.Height.String() + ip + uaStr
|
||||
if last == newStr {
|
||||
// 前后数据一样,不用创建新的数据
|
||||
fmt.Println("前后数据一样,不用创建新的数据")
|
||||
c.Writer.WriteString("0")
|
||||
c.Data(200, "image/gif", img_util.EmptyGif())
|
||||
// response.CheckAndRespWithData(c, 0, nil)
|
||||
return
|
||||
} else {
|
||||
@@ -188,10 +185,9 @@ func (hd *MonitorClientHandler) Add(c *gin.Context) {
|
||||
addReq.Province = ®ionInfo.Province
|
||||
}
|
||||
|
||||
createId, _ := MonitorClientService.Add(addReq)
|
||||
// response.CheckAndRespWithData(c, createId, e)
|
||||
// c.Value(createId)
|
||||
c.Writer.WriteString(strconv.Itoa(createId))
|
||||
MonitorClientService.Add(addReq)
|
||||
|
||||
c.Data(200, "image/gif", img_util.EmptyGif())
|
||||
}
|
||||
|
||||
// @Summary 监控-客户端信息删除
|
||||
|
@@ -1,11 +1,7 @@
|
||||
package monitor_error
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -15,6 +11,7 @@ import (
|
||||
"x_admin/core/response"
|
||||
"x_admin/util"
|
||||
"x_admin/util/excel2"
|
||||
"x_admin/util/img_util"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/sync/singleflight"
|
||||
@@ -111,7 +108,8 @@ func (hd *MonitorErrorHandler) Detail(c *gin.Context) {
|
||||
func (hd *MonitorErrorHandler) Add(c *gin.Context) {
|
||||
data, err := url.QueryUnescape(c.Query("data"))
|
||||
if err != nil {
|
||||
response.CheckAndRespWithData(c, 0, err)
|
||||
// response.CheckAndRespWithData(c, 0, err)
|
||||
c.Data(200, "image/gif", img_util.EmptyGif())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,35 +122,8 @@ func (hd *MonitorErrorHandler) Add(c *gin.Context) {
|
||||
for i := 0; i < len(addReq); i++ {
|
||||
MonitorErrorService.Add(addReq[i])
|
||||
}
|
||||
img := image.NewRGBA(image.Rect(0, 0, 1, 1))
|
||||
|
||||
// 设置像素颜色为黑色
|
||||
img.Set(0, 0, color.Black)
|
||||
|
||||
// 创建GIF动画
|
||||
g := &gif.GIF{
|
||||
Image: []*image.Paletted{imageToPaletted(img)},
|
||||
Delay: []int{0}, // 延迟时间,单位是10毫秒
|
||||
}
|
||||
var buffer bytes.Buffer
|
||||
|
||||
// 编码GIF到缓冲区
|
||||
err = gif.EncodeAll(&buffer, g)
|
||||
|
||||
// response.CheckAndRespWithData(c, g, nil)
|
||||
c.Data(200, "image/gif", buffer.Bytes())
|
||||
}
|
||||
|
||||
// 将image.Image转换为*image.Paletted
|
||||
func imageToPaletted(img image.Image) *image.Paletted {
|
||||
b := img.Bounds()
|
||||
pm := image.NewPaletted(b, color.Palette{color.Black})
|
||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
||||
for x := b.Min.X; x < b.Max.X; x++ {
|
||||
pm.Set(x, y, img.At(x, y))
|
||||
}
|
||||
}
|
||||
return pm
|
||||
c.Data(200, "image/gif", img_util.EmptyGif())
|
||||
}
|
||||
|
||||
// @Summary 监控-错误列删除
|
||||
|
@@ -1,38 +1,42 @@
|
||||
package monitor_slow
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"github.com/gin-gonic/gin"
|
||||
"x_admin/core/request"
|
||||
"x_admin/core/response"
|
||||
"x_admin/util"
|
||||
"x_admin/util/excel2"
|
||||
"x_admin/util/img_util"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
|
||||
type MonitorSlowHandler struct {
|
||||
requestGroup singleflight.Group
|
||||
}
|
||||
|
||||
// @Summary 监控-错误列列表
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param PageNo query int true "页码"
|
||||
// @Param PageSize query int true "每页数量"
|
||||
// @Param ProjectKey query string false "项目key"
|
||||
// @Param ClientId query string false "sdk生成的客户端id"
|
||||
// @Param UserId query string false "用户id"
|
||||
// @Param Path query string false "URL地址"
|
||||
// @Param Time query number false "时间"
|
||||
// @Param CreateTimeStart query string false "创建时间"
|
||||
// @Param CreateTimeEnd query string false "创建时间"
|
||||
//@Success 200 {object} response.Response{ data=response.PageResp{ lists=[]MonitorSlowResp}} "成功"
|
||||
//@Router /api/admin/monitor_slow/list [get]
|
||||
// @Summary 监控-错误列列表
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param PageNo query int true "页码"
|
||||
// @Param PageSize query int true "每页数量"
|
||||
// @Param ProjectKey query string false "项目key"
|
||||
// @Param ClientId query string false "sdk生成的客户端id"
|
||||
// @Param UserId query string false "用户id"
|
||||
// @Param Path query string false "URL地址"
|
||||
// @Param Time query number false "时间"
|
||||
// @Param CreateTimeStart query string false "创建时间"
|
||||
// @Param CreateTimeEnd query string false "创建时间"
|
||||
//
|
||||
// @Success 200 {object} response.Response{ data=response.PageResp{ lists=[]MonitorSlowResp}} "成功"
|
||||
// @Router /api/admin/monitor_slow/list [get]
|
||||
func (hd *MonitorSlowHandler) List(c *gin.Context) {
|
||||
var page request.PageReq
|
||||
var listReq MonitorSlowListReq
|
||||
@@ -46,18 +50,18 @@ func (hd *MonitorSlowHandler) List(c *gin.Context) {
|
||||
response.CheckAndRespWithData(c, res, err)
|
||||
}
|
||||
|
||||
// @Summary 监控-错误列列表-所有
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param ProjectKey query string false "项目key"
|
||||
// @Param ClientId query string false "sdk生成的客户端id"
|
||||
// @Param UserId query string false "用户id"
|
||||
// @Param Path query string false "URL地址"
|
||||
// @Param Time query number false "时间"
|
||||
// @Param CreateTimeStart query string false "创建时间"
|
||||
// @Param CreateTimeEnd query string false "创建时间"
|
||||
// @Success 200 {object} response.Response{ data=[]MonitorSlowResp} "成功"
|
||||
// @Router /api/admin/monitor_slow/listAll [get]
|
||||
// @Summary 监控-错误列列表-所有
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param ProjectKey query string false "项目key"
|
||||
// @Param ClientId query string false "sdk生成的客户端id"
|
||||
// @Param UserId query string false "用户id"
|
||||
// @Param Path query string false "URL地址"
|
||||
// @Param Time query number false "时间"
|
||||
// @Param CreateTimeStart query string false "创建时间"
|
||||
// @Param CreateTimeEnd query string false "创建时间"
|
||||
// @Success 200 {object} response.Response{ data=[]MonitorSlowResp} "成功"
|
||||
// @Router /api/admin/monitor_slow/listAll [get]
|
||||
func (hd *MonitorSlowHandler) ListAll(c *gin.Context) {
|
||||
var listReq MonitorSlowListReq
|
||||
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
|
||||
@@ -67,13 +71,13 @@ func (hd *MonitorSlowHandler) ListAll(c *gin.Context) {
|
||||
response.CheckAndRespWithData(c, res, err)
|
||||
}
|
||||
|
||||
// @Summary 监控-错误列详情
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param Id query number false "错误id"
|
||||
// @Success 200 {object} response.Response{ data=MonitorSlowResp} "成功"
|
||||
// @Router /api/admin/monitor_slow/detail [get]
|
||||
// @Summary 监控-错误列详情
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param Id query number false "错误id"
|
||||
// @Success 200 {object} response.Response{ data=MonitorSlowResp} "成功"
|
||||
// @Router /api/admin/monitor_slow/detail [get]
|
||||
func (hd *MonitorSlowHandler) Detail(c *gin.Context) {
|
||||
var detailReq MonitorSlowDetailReq
|
||||
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) {
|
||||
@@ -87,52 +91,58 @@ func (hd *MonitorSlowHandler) Detail(c *gin.Context) {
|
||||
response.CheckAndRespWithData(c, res, err)
|
||||
}
|
||||
|
||||
|
||||
// @Summary 监控-错误列新增
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param ProjectKey body string false "项目key"
|
||||
// @Param ClientId body string false "sdk生成的客户端id"
|
||||
// @Param UserId body string false "用户id"
|
||||
// @Param Path body string false "URL地址"
|
||||
// @Param Time body number false "时间"
|
||||
// @Success 200 {object} response.Response "成功"
|
||||
// @Router /api/admin/monitor_slow/add [post]
|
||||
// @Summary 监控-错误列新增
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param ProjectKey body string false "项目key"
|
||||
// @Param ClientId body string false "sdk生成的客户端id"
|
||||
// @Param UserId body string false "用户id"
|
||||
// @Param Path body string false "URL地址"
|
||||
// @Param Time body number false "时间"
|
||||
// @Success 200 {object} response.Response "成功"
|
||||
// @Router /api/admin/monitor_slow/add [post]
|
||||
func (hd *MonitorSlowHandler) Add(c *gin.Context) {
|
||||
var addReq MonitorSlowAddReq
|
||||
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) {
|
||||
data, err := url.QueryUnescape(c.Query("data"))
|
||||
if err != nil {
|
||||
c.Data(200, "image/gif", img_util.EmptyGif())
|
||||
return
|
||||
}
|
||||
createId, e := MonitorSlowService.Add(addReq)
|
||||
response.CheckAndRespWithData(c,createId, e)
|
||||
|
||||
var addReq MonitorSlowAddReq
|
||||
json.Unmarshal([]byte(data), &addReq)
|
||||
|
||||
MonitorSlowService.Add(addReq)
|
||||
c.Data(200, "image/gif", img_util.EmptyGif())
|
||||
}
|
||||
// @Summary 监控-错误列编辑
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param Id body number false "错误id"
|
||||
// @Param ProjectKey body string false "项目key"
|
||||
// @Param ClientId body string false "sdk生成的客户端id"
|
||||
// @Param UserId body string false "用户id"
|
||||
// @Param Path body string false "URL地址"
|
||||
// @Param Time body number false "时间"
|
||||
// @Success 200 {object} response.Response "成功"
|
||||
// @Router /api/admin/monitor_slow/edit [post]
|
||||
|
||||
// @Summary 监控-错误列编辑
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param Id body number false "错误id"
|
||||
// @Param ProjectKey body string false "项目key"
|
||||
// @Param ClientId body string false "sdk生成的客户端id"
|
||||
// @Param UserId body string false "用户id"
|
||||
// @Param Path body string false "URL地址"
|
||||
// @Param Time body number false "时间"
|
||||
// @Success 200 {object} response.Response "成功"
|
||||
// @Router /api/admin/monitor_slow/edit [post]
|
||||
func (hd *MonitorSlowHandler) Edit(c *gin.Context) {
|
||||
var editReq MonitorSlowEditReq
|
||||
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) {
|
||||
return
|
||||
}
|
||||
response.CheckAndRespWithData(c,editReq.Id, MonitorSlowService.Edit(editReq))
|
||||
response.CheckAndRespWithData(c, editReq.Id, MonitorSlowService.Edit(editReq))
|
||||
}
|
||||
// @Summary 监控-错误列删除
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param Id body number false "错误id"
|
||||
// @Success 200 {object} response.Response "成功"
|
||||
// @Router /api/admin/monitor_slow/del [post]
|
||||
|
||||
// @Summary 监控-错误列删除
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param Id body number false "错误id"
|
||||
// @Success 200 {object} response.Response "成功"
|
||||
// @Router /api/admin/monitor_slow/del [post]
|
||||
func (hd *MonitorSlowHandler) Del(c *gin.Context) {
|
||||
var delReq MonitorSlowDelReq
|
||||
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) {
|
||||
@@ -143,6 +153,7 @@ func (hd *MonitorSlowHandler) Del(c *gin.Context) {
|
||||
|
||||
// @Summary 监控-错误列删除-批量
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
//
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param Ids body string false "逗号分割的id"
|
||||
@@ -162,20 +173,18 @@ func (hd *MonitorSlowHandler) DelBatch(c *gin.Context) {
|
||||
response.CheckAndResp(c, MonitorSlowService.DelBatch(Ids))
|
||||
}
|
||||
|
||||
|
||||
|
||||
// @Summary 监控-错误列导出
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param ProjectKey query string false "项目key"
|
||||
// @Param ClientId query string false "sdk生成的客户端id"
|
||||
// @Param UserId query string false "用户id"
|
||||
// @Param Path query string false "URL地址"
|
||||
// @Param Time query number false "时间"
|
||||
// @Param CreateTimeStart query string false "创建时间"
|
||||
// @Param CreateTimeEnd query string false "创建时间"
|
||||
// @Router /api/admin/monitor_slow/ExportFile [get]
|
||||
// @Summary 监控-错误列导出
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Param Token header string true "token"
|
||||
// @Param ProjectKey query string false "项目key"
|
||||
// @Param ClientId query string false "sdk生成的客户端id"
|
||||
// @Param UserId query string false "用户id"
|
||||
// @Param Path query string false "URL地址"
|
||||
// @Param Time query number false "时间"
|
||||
// @Param CreateTimeStart query string false "创建时间"
|
||||
// @Param CreateTimeEnd query string false "创建时间"
|
||||
// @Router /api/admin/monitor_slow/ExportFile [get]
|
||||
func (hd *MonitorSlowHandler) ExportFile(c *gin.Context) {
|
||||
var listReq MonitorSlowListReq
|
||||
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
|
||||
@@ -186,18 +195,18 @@ func (hd *MonitorSlowHandler) ExportFile(c *gin.Context) {
|
||||
response.FailWithMsg(c, response.SystemError, "查询信息失败")
|
||||
return
|
||||
}
|
||||
f, err := excel2.Export(res,MonitorSlowService.GetExcelCol(), "Sheet1", "监控-错误列")
|
||||
f, err := excel2.Export(res, MonitorSlowService.GetExcelCol(), "Sheet1", "监控-错误列")
|
||||
if err != nil {
|
||||
response.FailWithMsg(c, response.SystemError, "导出失败")
|
||||
return
|
||||
}
|
||||
excel2.DownLoadExcel("监控-错误列" + time.Now().Format("20060102-150405"), c.Writer, f)
|
||||
excel2.DownLoadExcel("监控-错误列"+time.Now().Format("20060102-150405"), c.Writer, f)
|
||||
}
|
||||
|
||||
// @Summary 监控-错误列导入
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Router /api/admin/monitor_slow/ImportFile [post]
|
||||
// @Summary 监控-错误列导入
|
||||
// @Tags monitor_slow-监控-错误列
|
||||
// @Produce json
|
||||
// @Router /api/admin/monitor_slow/ImportFile [post]
|
||||
func (hd *MonitorSlowHandler) ImportFile(c *gin.Context) {
|
||||
file, _, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
@@ -206,7 +215,7 @@ func (hd *MonitorSlowHandler) ImportFile(c *gin.Context) {
|
||||
}
|
||||
defer file.Close()
|
||||
importList := []MonitorSlowResp{}
|
||||
err = excel2.GetExcelData(file, &importList,MonitorSlowService.GetExcelCol())
|
||||
err = excel2.GetExcelData(file, &importList, MonitorSlowService.GetExcelCol())
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
@@ -214,4 +223,4 @@ func (hd *MonitorSlowHandler) ImportFile(c *gin.Context) {
|
||||
|
||||
err = MonitorSlowService.ImportFile(importList)
|
||||
response.CheckAndResp(c, err)
|
||||
}
|
||||
}
|
||||
|
@@ -1,63 +1,61 @@
|
||||
package monitor_slow
|
||||
|
||||
import (
|
||||
"x_admin/core"
|
||||
|
||||
)
|
||||
|
||||
//MonitorSlowListReq 监控-错误列列表参数
|
||||
// MonitorSlowListReq 监控-错误列列表参数
|
||||
type MonitorSlowListReq struct {
|
||||
ProjectKey *string // 项目key
|
||||
ClientId *string // sdk生成的客户端id
|
||||
UserId *string // 用户id
|
||||
Path *string // URL地址
|
||||
Time *float64 // 时间
|
||||
CreateTimeStart *string // 开始创建时间
|
||||
CreateTimeEnd *string // 结束创建时间
|
||||
ProjectKey *string // 项目key
|
||||
ClientId *string // sdk生成的客户端id
|
||||
UserId *string // 用户id
|
||||
Path *string // URL地址
|
||||
Time *float64 // 时间
|
||||
CreateTimeStart *string // 开始创建时间
|
||||
CreateTimeEnd *string // 结束创建时间
|
||||
}
|
||||
|
||||
|
||||
|
||||
//MonitorSlowAddReq 监控-错误列新增参数
|
||||
// MonitorSlowAddReq 监控-错误列新增参数
|
||||
type MonitorSlowAddReq struct {
|
||||
ProjectKey *string // 项目key
|
||||
ClientId *string // sdk生成的客户端id
|
||||
UserId *string // 用户id
|
||||
Path *string // URL地址
|
||||
Time core.NullFloat // 时间
|
||||
ProjectKey *string // 项目key
|
||||
ClientId *string // sdk生成的客户端id
|
||||
UserId *string // 用户id
|
||||
Path *string // URL地址
|
||||
Time core.NullFloat // 时间
|
||||
}
|
||||
|
||||
//MonitorSlowEditReq 监控-错误列编辑参数
|
||||
// MonitorSlowEditReq 监控-错误列编辑参数
|
||||
type MonitorSlowEditReq struct {
|
||||
Id int // 错误id
|
||||
ProjectKey *string // 项目key
|
||||
ClientId *string // sdk生成的客户端id
|
||||
UserId *string // 用户id
|
||||
Path *string // URL地址
|
||||
Time core.NullFloat // 时间
|
||||
Id int // 错误id
|
||||
ProjectKey *string // 项目key
|
||||
ClientId *string // sdk生成的客户端id
|
||||
UserId *string // 用户id
|
||||
Path *string // URL地址
|
||||
Time core.NullFloat // 时间
|
||||
}
|
||||
|
||||
//MonitorSlowDetailReq 监控-错误列详情参数
|
||||
// MonitorSlowDetailReq 监控-错误列详情参数
|
||||
type MonitorSlowDetailReq struct {
|
||||
Id int // 错误id
|
||||
Id int // 错误id
|
||||
}
|
||||
|
||||
//MonitorSlowDelReq 监控-错误列删除参数
|
||||
// MonitorSlowDelReq 监控-错误列删除参数
|
||||
type MonitorSlowDelReq struct {
|
||||
Id int // 错误id
|
||||
Id int // 错误id
|
||||
}
|
||||
|
||||
//MonitorSlowDelReq 监控-错误列批量删除参数
|
||||
// MonitorSlowDelReq 监控-错误列批量删除参数
|
||||
type MonitorSlowDelBatchReq struct {
|
||||
Ids string
|
||||
}
|
||||
|
||||
//MonitorSlowResp 监控-错误列返回信息
|
||||
// MonitorSlowResp 监控-错误列返回信息
|
||||
type MonitorSlowResp struct {
|
||||
Id int // 错误id
|
||||
ProjectKey string // 项目key
|
||||
ClientId string // sdk生成的客户端id
|
||||
UserId string // 用户id
|
||||
Path string // URL地址
|
||||
Time core.NullFloat // 时间
|
||||
CreateTime core.NullTime // 创建时间
|
||||
Id int // 错误id
|
||||
ProjectKey string // 项目key
|
||||
ClientId string // sdk生成的客户端id
|
||||
UserId string // 用户id
|
||||
Path string // URL地址
|
||||
Time core.NullFloat // 时间
|
||||
CreateTime core.NullTime // 创建时间
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_sh
|
||||
// MonitorSlowRoute(rg)
|
||||
func MonitorSlowRoute(rg *gin.RouterGroup) {
|
||||
handle := monitor_slow.MonitorSlowHandler{}
|
||||
rg.POST("/monitor_slow/add", middleware.RecordLog("慢接口新增"), handle.Add)
|
||||
rg.GET("/monitor_slow/add", middleware.RecordLog("慢接口新增"), handle.Add)
|
||||
r := rg.Group("/", middleware.TokenAuth())
|
||||
r.GET("/monitor_slow/list", handle.List)
|
||||
r.GET("/monitor_slow/listAll", handle.ListAll)
|
||||
|
38
server/util/img_util/img_util.go
Normal file
38
server/util/img_util/img_util.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package img_util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
)
|
||||
|
||||
func EmptyGif() []byte {
|
||||
img := image.NewRGBA(image.Rect(0, 0, 1, 1))
|
||||
|
||||
// 设置像素颜色为黑色
|
||||
img.Set(0, 0, color.Black)
|
||||
|
||||
// 创建GIF动画
|
||||
g := &gif.GIF{
|
||||
Image: []*image.Paletted{imageToPaletted(img)},
|
||||
Delay: []int{0}, // 延迟时间,单位是10毫秒
|
||||
}
|
||||
var buffer bytes.Buffer
|
||||
|
||||
// 编码GIF到缓冲区
|
||||
gif.EncodeAll(&buffer, g)
|
||||
return buffer.Bytes()
|
||||
}
|
||||
|
||||
// 将image.Image转换为*image.Paletted
|
||||
func imageToPaletted(img image.Image) *image.Paletted {
|
||||
b := img.Bounds()
|
||||
pm := image.NewPaletted(b, color.Palette{color.Black})
|
||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
||||
for x := b.Min.X; x < b.Max.X; x++ {
|
||||
pm.Set(x, y, img.At(x, y))
|
||||
}
|
||||
}
|
||||
return pm
|
||||
}
|
@@ -2,21 +2,25 @@
|
||||
"name": "@adtkcn/x_err_sdk",
|
||||
"version": "1.0.0",
|
||||
"description": "错误监控sdk",
|
||||
"main": "dist/web/index.js",
|
||||
"main": "dist/web/XErr.umd.js",
|
||||
"private": false,
|
||||
"file": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "npm run build:web&&npm run build:ts",
|
||||
"build:web": "esbuild web/index.ts --bundle --sourcemap --minify --outfile=dist/web/index.js --format=esm --target=es2015",
|
||||
"build": "vite build&&npm run build:ts",
|
||||
"build:ts": "tsc --emitDeclarationOnly",
|
||||
"outdated": "pnpm outdated"
|
||||
},
|
||||
"keywords": ["x_err_sdk","X_admin"],
|
||||
"keywords": [
|
||||
"x_err_sdk",
|
||||
"X_admin"
|
||||
],
|
||||
"author": "adtkcn",
|
||||
"license": "ISC",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.3",
|
||||
"uuid": "^11.0.2",
|
||||
"esbuild": "^0.24.0"
|
||||
"vite": "^5.4.10"
|
||||
}
|
||||
}
|
||||
|
@@ -5,13 +5,20 @@ export type LogWithEnv = {
|
||||
ScreenWidth?: number;
|
||||
};
|
||||
export type LogWithError = {
|
||||
Type: "error"|"event"|"resources"|'click'|'historyChange'|'hashChange'|'onloadTime';
|
||||
Type: "error"|"event"|"resources"|'click';
|
||||
EventType: string;
|
||||
Path:string;
|
||||
Message?: string;
|
||||
Stack?: string;
|
||||
};
|
||||
|
||||
export type ISlow = {
|
||||
Type: "onloadTime"
|
||||
|
||||
Path:string;
|
||||
Time: number;
|
||||
};
|
||||
|
||||
|
||||
// 扩展必须实现的接口
|
||||
export interface IErrorEvent {
|
||||
@@ -23,4 +30,4 @@ export interface IErrorEvent {
|
||||
listen(callback: ListenCallbackFn): void;
|
||||
unListen(): void;
|
||||
}
|
||||
export type ListenCallbackFn = (params: LogWithError) => void;
|
||||
export type ListenCallbackFn = (params: LogWithError|ISlow) => void;
|
||||
|
21
x_err_sdk/vite.config.js
Normal file
21
x_err_sdk/vite.config.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: 'web/index.ts', // 库的入口文件
|
||||
name: 'XErr', // 库的名称
|
||||
fileName: (format) => `web/XErr.${format}.js`, // 输出文件名
|
||||
},
|
||||
rollupOptions: {
|
||||
// 外部化处理不想打包进库的依赖
|
||||
// external: ['vue'],
|
||||
output: {
|
||||
globals: {
|
||||
// vue: 'Vue'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { v1 as uuid_v1 } from "uuid";
|
||||
import type { LogWithError, IErrorEvent, LogWithEnv } from "../types";
|
||||
import type { LogWithError, IErrorEvent,ISlow, LogWithEnv } from "../types";
|
||||
|
||||
type Uid = string | number;
|
||||
|
||||
@@ -9,7 +9,7 @@ type Props = {
|
||||
Uid?: Uid; //用户标识
|
||||
};
|
||||
|
||||
class XLog {
|
||||
class Base {
|
||||
private Dns: string = "";
|
||||
private client_id: string = "";
|
||||
private Pid: string = "";
|
||||
@@ -38,17 +38,23 @@ class XLog {
|
||||
return;
|
||||
}
|
||||
if (props.Uid) {
|
||||
this.Uid = props.Uid;
|
||||
this.Uid = String(props.Uid);
|
||||
}
|
||||
this.setClientID();
|
||||
this.SetUid();
|
||||
this.getLocalMessage();
|
||||
|
||||
|
||||
// 监听错误
|
||||
platform.listen((params: LogWithError) => {
|
||||
platform.listen((params: LogWithError|ISlow) => {
|
||||
console.log("listenCallback", params);
|
||||
|
||||
this.Push(params);
|
||||
if(params.Type=='onloadTime'){
|
||||
let slow=params as ISlow;
|
||||
this.uploadSlow(slow);
|
||||
}else{
|
||||
this.Push(params);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.timer = setInterval(() => {
|
||||
@@ -59,8 +65,8 @@ class XLog {
|
||||
// 设置用户id
|
||||
public SetUid(uid?: Uid) {
|
||||
if (uid) {
|
||||
this.Uid = uid;
|
||||
this.platform?.setCache("x_err_uid", uid);
|
||||
this.Uid =String(uid) ;
|
||||
this.platform?.setCache("x_err_uid", this.Uid);
|
||||
|
||||
} else {
|
||||
const u_id = this.platform?.getCache("x_err_uid");
|
||||
@@ -127,6 +133,23 @@ class XLog {
|
||||
});
|
||||
} catch (error) {}
|
||||
}
|
||||
public uploadSlow=(envInfo: ISlow) =>{
|
||||
if (!this.Dns) return; //未设置Dns服务器不上传
|
||||
|
||||
try {
|
||||
this.platform
|
||||
?.upload(this.Dns + `/admin/monitor_slow/add`, {
|
||||
ProjectKey: this.Pid,
|
||||
ClientId: this.client_id,
|
||||
UserId: this.Uid,
|
||||
Path: envInfo.Path,
|
||||
Time: envInfo.Time,
|
||||
})
|
||||
.catch((err: any) => {
|
||||
// 上传失败
|
||||
});
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
public upload() {
|
||||
@@ -149,4 +172,4 @@ class XLog {
|
||||
this.platform?.unListen();
|
||||
}
|
||||
}
|
||||
export default XLog;
|
||||
export default Base;
|
@@ -1,6 +1,4 @@
|
||||
import XErr from "./err-entry"
|
||||
import XErrWeb from "./err-implement"
|
||||
import Base from "./base";
|
||||
import Web from "./web";
|
||||
|
||||
|
||||
export {XErr,XErrWeb}
|
||||
|
||||
export { Base, Web };
|
@@ -2,18 +2,18 @@ import type {
|
||||
LogWithError,
|
||||
LogWithEnv,
|
||||
ListenCallbackFn,
|
||||
IErrorEvent,
|
||||
IErrorEvent,ISlow
|
||||
} from "../types";
|
||||
|
||||
interface LoggerProps {
|
||||
// timeout:number
|
||||
onloadTimeOut?: number;
|
||||
}
|
||||
class Logger implements IErrorEvent {
|
||||
class Web implements IErrorEvent {
|
||||
props: LoggerProps;
|
||||
constructor(props?: LoggerProps) {
|
||||
this.props = {
|
||||
onloadTimeOut: 3000,
|
||||
onloadTimeOut: 5000,
|
||||
...props,
|
||||
};
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class Logger implements IErrorEvent {
|
||||
}
|
||||
return env;
|
||||
}
|
||||
private callback(err: LogWithError): void {}
|
||||
private callback(err: LogWithError|ISlow): void {}
|
||||
private listenError = (err: any) => {
|
||||
console.error([err]);
|
||||
let target = err.target;
|
||||
@@ -117,46 +117,8 @@ class Logger implements IErrorEvent {
|
||||
});
|
||||
}
|
||||
};
|
||||
// private listenClick = (e: Event) => {
|
||||
// let target = e.target as HTMLElement;
|
||||
// let tagName = target?.localName;
|
||||
// let name = [tagName];
|
||||
// if (target.id) {
|
||||
// name.push("#" + target.id);
|
||||
// }
|
||||
// target.classList.forEach((item) => {
|
||||
// name.push("." + item);
|
||||
// });
|
||||
// if (target.innerText) {
|
||||
// name.push(":" + target.innerText.slice(0, 20));
|
||||
// }
|
||||
// this.callback({
|
||||
// Type: "click",
|
||||
// EventType: "click",
|
||||
// Path: window.location.href,
|
||||
// Message: name.join(""),
|
||||
// Stack: "",
|
||||
// });
|
||||
// };
|
||||
// private listenHistoryRouterChange = () => {
|
||||
// this.callback({
|
||||
// Type: "historyChange",
|
||||
// EventType: "popstate",
|
||||
// Path: window.location.href,
|
||||
// Message: "",
|
||||
// Stack: "",
|
||||
// });
|
||||
// };
|
||||
// // 监听hash
|
||||
// private listenHashRouterChange = () => {
|
||||
// this.callback({
|
||||
// Type: "hashChange",
|
||||
// EventType: "hashChange",
|
||||
// Path: window.location.href,
|
||||
// Message: "",
|
||||
// Stack: "",
|
||||
// });
|
||||
// };
|
||||
|
||||
|
||||
private handleStack(stack: string): string {
|
||||
let newStack: string[] = [];
|
||||
if (stack) {
|
||||
@@ -186,10 +148,8 @@ class Logger implements IErrorEvent {
|
||||
// 页面加载时间5s以上
|
||||
this.callback({
|
||||
Type: "onloadTime",
|
||||
EventType: "onloadTime",
|
||||
Path: window.location.href,
|
||||
Message: "时间:" + parseFloat(onloadTime.toFixed(2)) + "ms",
|
||||
Stack: "",
|
||||
Time:onloadTime
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -216,4 +176,4 @@ class Logger implements IErrorEvent {
|
||||
}
|
||||
}
|
||||
|
||||
export default Logger;
|
||||
export default Web;
|
Reference in New Issue
Block a user