feat(rdp): 新增 RDP 远程桌面/SMB/账单同步能力 + 清理编译产物
主要变更: - RDP 远程桌面:新增 backend/pkg/rdp(RDP 引擎 + credssp/display/rle/trace)、 backend/controller/rdp*(连接/凭证/文件/会话/实时)、frontend RDP 组件与 API - Windows SMB 文件传输:backend/pkg/winsmb - 云账单同步:backend/pkg/billingsync + billing_sync/aliyun_billing,前端账单详情 - Agent CLI Kubernetes 工具:kubernetes_action/get、pod_execute/logs - 服务器导入助手:server_import_helpers、ImportCredentialSettings - 国际化与组件重构(cloud/deploy/monitor/server/system 等多模块) - 清理编译产物二进制:移除 backend/server、backend/agent/bin/aiops-agent-* - .gitignore:新增 backend/agent/ 与 .cache/(避免 334MB go-build 缓存误入库) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
777d9e4e71
commit
76ec9387f0
202 files changed
+16555
-2543
No files matched your search
@@ -0,0 +1,145 @@
|
||||
package display
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"image"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
)
|
||||
|
||||
// Bitmap 表示协议层解码后的 BGRA/RGB565 小块,display 只负责合成和输出 // Logan.Li
|
||||
type Bitmap struct {
|
||||
X int
|
||||
Y int
|
||||
Width int
|
||||
Height int
|
||||
BitsPerPixel int
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Frame 表示一次合成后的脏区域输出 // Logan.Li
|
||||
type Frame struct {
|
||||
X int
|
||||
Y int
|
||||
Width int
|
||||
Height int
|
||||
Image string
|
||||
RGBA []byte
|
||||
}
|
||||
|
||||
// Framebuffer 借鉴 Guacamole/bring 的 display/layer 思路,在后端维护完整画布 // Logan.Li
|
||||
type Framebuffer struct {
|
||||
width int
|
||||
height int
|
||||
img *image.RGBA
|
||||
dirty image.Rectangle
|
||||
}
|
||||
|
||||
// NewFramebuffer 创建固定尺寸远端画布,所有 RDP 更新先合成到这里 // Logan.Li
|
||||
func NewFramebuffer(width, height int) *Framebuffer {
|
||||
if width <= 0 {
|
||||
width = 1280
|
||||
}
|
||||
if height <= 0 {
|
||||
height = 800
|
||||
}
|
||||
return &Framebuffer{
|
||||
width: width,
|
||||
height: height,
|
||||
img: image.NewRGBA(image.Rect(0, 0, width, height)),
|
||||
}
|
||||
}
|
||||
|
||||
// Draw 合成一个 bitmap 小块,并扩大脏矩形 // Logan.Li
|
||||
func (f *Framebuffer) Draw(b Bitmap) {
|
||||
if b.Width <= 0 || b.Height <= 0 || len(b.Data) == 0 {
|
||||
return
|
||||
}
|
||||
dstRect := image.Rect(b.X, b.Y, b.X+b.Width, b.Y+b.Height).Intersect(f.img.Bounds())
|
||||
if dstRect.Empty() {
|
||||
return
|
||||
}
|
||||
src := bitmapToRGBA(b)
|
||||
srcPoint := image.Pt(dstRect.Min.X-b.X, dstRect.Min.Y-b.Y)
|
||||
draw.Draw(f.img, dstRect, src, srcPoint, draw.Src)
|
||||
if f.dirty.Empty() {
|
||||
f.dirty = dstRect
|
||||
} else {
|
||||
f.dirty = f.dirty.Union(dstRect)
|
||||
}
|
||||
}
|
||||
|
||||
// Flush 输出当前脏区域 PNG,并清空脏矩形 // Logan.Li
|
||||
func (f *Framebuffer) Flush() (Frame, bool) {
|
||||
frame, ok := f.FlushRGBA()
|
||||
if !ok {
|
||||
return Frame{}, false
|
||||
}
|
||||
img := image.NewRGBA(image.Rect(0, 0, frame.Width, frame.Height))
|
||||
copy(img.Pix, frame.RGBA)
|
||||
var buf bytes.Buffer
|
||||
if err := png.Encode(&buf, img); err != nil {
|
||||
return Frame{}, false
|
||||
}
|
||||
frame.Image = "data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||
return frame, true
|
||||
}
|
||||
|
||||
// FlushRGBA 输出当前脏区域原始 RGBA,避免实时 RDP 路径重复 PNG/base64 编解码。 // Logan.Li
|
||||
func (f *Framebuffer) FlushRGBA() (Frame, bool) {
|
||||
if f.dirty.Empty() {
|
||||
return Frame{}, false
|
||||
}
|
||||
rect := f.dirty.Intersect(f.img.Bounds())
|
||||
f.dirty = image.Rectangle{}
|
||||
if rect.Empty() {
|
||||
return Frame{}, false
|
||||
}
|
||||
crop := image.NewRGBA(image.Rect(0, 0, rect.Dx(), rect.Dy()))
|
||||
draw.Draw(crop, crop.Bounds(), f.img, rect.Min, draw.Src)
|
||||
return Frame{
|
||||
X: rect.Min.X,
|
||||
Y: rect.Min.Y,
|
||||
Width: rect.Dx(),
|
||||
Height: rect.Dy(),
|
||||
RGBA: append([]byte(nil), crop.Pix...),
|
||||
}, true
|
||||
}
|
||||
|
||||
func bitmapToRGBA(b Bitmap) *image.RGBA {
|
||||
img := image.NewRGBA(image.Rect(0, 0, b.Width, b.Height))
|
||||
pix := img.Pix
|
||||
switch b.BitsPerPixel {
|
||||
case 1, 2:
|
||||
n := b.Width * b.Height
|
||||
for i := 0; i < n && i*2+1 < len(b.Data); i++ {
|
||||
// grdp 的 RLE 输出 16bpp 使用大端 RGB565,按小端会导致蓝紫/绿色偏色。 // Logan.Li
|
||||
c := binary.BigEndian.Uint16(b.Data[i*2 : i*2+2])
|
||||
r := uint8((c >> 11) & 0x1F)
|
||||
g := uint8((c >> 5) & 0x3F)
|
||||
bl := uint8(c & 0x1F)
|
||||
off := i * 4
|
||||
pix[off] = (r << 3) | (r >> 2)
|
||||
pix[off+1] = (g << 2) | (g >> 4)
|
||||
pix[off+2] = (bl << 3) | (bl >> 2)
|
||||
pix[off+3] = 0xFF
|
||||
}
|
||||
default:
|
||||
stride := b.BitsPerPixel
|
||||
n := b.Width * b.Height
|
||||
for i := 0; i < n; i++ {
|
||||
s := i * stride
|
||||
if s+2 >= len(b.Data) {
|
||||
break
|
||||
}
|
||||
off := i * 4
|
||||
pix[off] = b.Data[s+2]
|
||||
pix[off+1] = b.Data[s+1]
|
||||
pix[off+2] = b.Data[s]
|
||||
pix[off+3] = 0xFF
|
||||
}
|
||||
}
|
||||
return img
|
||||
}
|
||||
Reference in new issue
Block a user