Merge branch 'dev' of github.com:engigu/baihu into dev

This commit is contained in:
engigu
2026-02-07 09:24:40 +08:00
69 changed files with 420 additions and 234 deletions
+47 -7
View File
@@ -6,7 +6,7 @@ on:
branches: branches:
- main - main
paths: paths:
- 'Dockerfile.base' - 'docker/Dockerfile.base'
env: env:
REGISTRY: ghcr.io REGISTRY: ghcr.io
@@ -17,9 +17,39 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
base_type: [debian, alpine, debian13]
platform: platform:
- linux/amd64 - linux/amd64
- linux/arm64 - linux/arm64
include:
- base_type: debian
platform: linux/arm/v7
dockerfile: docker/Dockerfile.base
tag_suffix: ""
- base_type: debian
platform: linux/amd64
dockerfile: docker/Dockerfile.base
tag_suffix: ""
- base_type: debian
platform: linux/arm64
dockerfile: docker/Dockerfile.base
tag_suffix: ""
- base_type: alpine
platform: linux/amd64
dockerfile: docker/Dockerfile.alpine.base
tag_suffix: "-alpine"
- base_type: alpine
platform: linux/arm64
dockerfile: docker/Dockerfile.alpine.base
tag_suffix: "-alpine"
- base_type: debian13
platform: linux/amd64
dockerfile: docker/Dockerfile.debian13.base
tag_suffix: "-debian13"
- base_type: debian13
platform: linux/arm64
dockerfile: docker/Dockerfile.debian13.base
tag_suffix: "-debian13"
permissions: permissions:
contents: read contents: read
@@ -33,7 +63,7 @@ jobs:
id: platform id: platform
run: | run: |
platform=${{ matrix.platform }} platform=${{ matrix.platform }}
echo "pair=${platform//\//-}" >> $GITHUB_OUTPUT echo "pair=${platform//\//-}-${{ matrix.base_type }}" >> $GITHUB_OUTPUT
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
@@ -55,14 +85,14 @@ jobs:
images: | images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=raw,value=base type=raw,value=base${{ matrix.tag_suffix }}
- name: Build and push by digest - name: Build and push by digest
id: build id: build
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./Dockerfile.base file: ${{ matrix.dockerfile }}
platforms: ${{ matrix.platform }} platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true outputs: type=image,name=${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
@@ -87,6 +117,16 @@ jobs:
merge: merge:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
strategy:
matrix:
base_type: [debian, alpine, debian13]
include:
- base_type: debian
tag: base
- base_type: alpine
tag: base-alpine
- base_type: debian13
tag: base-debian13
permissions: permissions:
contents: read contents: read
@@ -100,7 +140,7 @@ jobs:
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
path: /tmp/digests path: /tmp/digests
pattern: digests-* pattern: digests-*-${{ matrix.base_type }}
merge-multiple: true merge-multiple: true
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -120,7 +160,7 @@ jobs:
images: | images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=raw,value=base type=raw,value=${{ matrix.tag }}
- name: Create manifest list and push - name: Create manifest list and push
working-directory: /tmp/digests working-directory: /tmp/digests
@@ -130,4 +170,4 @@ jobs:
- name: Inspect image - name: Inspect image
run: | run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:base docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ matrix.tag }}
+26 -10
View File
@@ -12,6 +12,19 @@ env:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
base_type: [debian, alpine, debian13]
include:
- base_type: debian
base_tag: base
tag_suffix: ""
- base_type: alpine
base_tag: base-alpine
tag_suffix: "-alpine"
- base_type: debian13
base_tag: base-debian13
tag_suffix: "-debian13"
permissions: permissions:
contents: read contents: read
@@ -38,10 +51,9 @@ jobs:
images: | images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=semver,pattern={{version}}-amd64 type=raw,value=latest-amd64${{ matrix.tag_suffix }},enable={{is_default_branch}}
type=raw,value=latest-amd64,enable={{is_default_branch}} type=ref,event=branch,suffix=-amd64${{ matrix.tag_suffix }}
type=ref,event=branch,suffix=-amd64 type=sha,prefix={{branch}}-,suffix=-amd64${{ matrix.tag_suffix }}
type=sha,prefix={{branch}}-,suffix=-amd64
- name: Get build time - name: Get build time
id: build_time id: build_time
@@ -51,6 +63,7 @@ jobs:
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./docker/Dockerfile
platforms: linux/amd64 platforms: linux/amd64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
@@ -58,11 +71,13 @@ jobs:
build-args: | build-args: |
VERSION=${{ github.ref_name }} VERSION=${{ github.ref_name }}
BUILD_TIME=${{ steps.build_time.outputs.time }} BUILD_TIME=${{ steps.build_time.outputs.time }}
cache-from: type=gha,scope=linux-amd64 BASE_TAG=${{ matrix.base_tag }}
cache-to: type=gha,scope=linux-amd64,mode=max cache-from: type=gha,scope=linux-amd64-${{ matrix.base_type }}
cache-to: type=gha,scope=linux-amd64-${{ matrix.base_type }},mode=max
provenance: false provenance: false
- name: Deploy to Demo server - name: Deploy to Demo server
if: github.ref == 'refs/heads/main' && matrix.base_type == 'debian'
uses: appleboy/ssh-action@v1.2.0 uses: appleboy/ssh-action@v1.2.0
with: with:
host: ${{ secrets.DEPLOY_HOST }} host: ${{ secrets.DEPLOY_HOST }}
@@ -71,10 +86,11 @@ jobs:
port: ${{ secrets.DEPLOY_PORT }} port: ${{ secrets.DEPLOY_PORT }}
script: | script: |
cd ${{ secrets.DEPLOY_PATH }} cd ${{ secrets.DEPLOY_PATH }}
docker-compose pull docker-compose -f docker/docker-compose.yml pull
docker-compose up -d docker-compose -f docker/docker-compose.yml up -d
- name: Deploy to X server - name: Deploy to X server
if: github.ref == 'refs/heads/main' && matrix.base_type == 'debian'
uses: appleboy/ssh-action@v1.2.0 uses: appleboy/ssh-action@v1.2.0
with: with:
host: ${{ secrets.DEPLOY_HOST }} host: ${{ secrets.DEPLOY_HOST }}
@@ -83,5 +99,5 @@ jobs:
port: ${{ secrets.DEPLOY_PORT }} port: ${{ secrets.DEPLOY_PORT }}
script: | script: |
cd ${{ secrets.DEPLOY_X_PATH }} cd ${{ secrets.DEPLOY_X_PATH }}
docker-compose pull docker-compose -f docker/docker-compose.yml pull
docker-compose up -d docker-compose -f docker/docker-compose.yml up -d
+20 -4
View File
@@ -12,6 +12,19 @@ env:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
base_type: [debian, alpine, debian13]
include:
- base_type: debian
base_tag: base
tag_suffix: ""
- base_type: alpine
base_tag: base-alpine
tag_suffix: "-alpine"
- base_type: debian13
base_tag: base-debian13
tag_suffix: "-debian13"
permissions: permissions:
contents: read contents: read
@@ -38,8 +51,9 @@ jobs:
images: | images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=semver,pattern={{version}}-amd64 type=semver,pattern={{version}}-amd64${{ matrix.tag_suffix }}
type=raw,value=latest-amd64,enable={{is_default_branch}} type=raw,value=latest-amd64${{ matrix.tag_suffix }},enable={{is_default_branch}}
type=ref,event=branch,suffix=-amd64${{ matrix.tag_suffix }}
- name: Get build time - name: Get build time
id: build_time id: build_time
@@ -49,6 +63,7 @@ jobs:
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./docker/Dockerfile
platforms: linux/amd64 platforms: linux/amd64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
@@ -56,6 +71,7 @@ jobs:
build-args: | build-args: |
VERSION=${{ github.ref_name }} VERSION=${{ github.ref_name }}
BUILD_TIME=${{ steps.build_time.outputs.time }} BUILD_TIME=${{ steps.build_time.outputs.time }}
cache-from: type=gha,scope=linux-amd64 BASE_TAG=${{ matrix.base_tag }}
cache-to: type=gha,scope=linux-amd64,mode=max cache-from: type=gha,scope=linux-amd64-${{ matrix.base_type }}
cache-to: type=gha,scope=linux-amd64-${{ matrix.base_type }},mode=max
provenance: false provenance: false
+20 -4
View File
@@ -12,6 +12,19 @@ env:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
base_type: [debian, alpine, debian13]
include:
- base_type: debian
base_tag: base
tag_suffix: ""
- base_type: alpine
base_tag: base-alpine
tag_suffix: "-alpine"
- base_type: debian13
base_tag: base-debian13
tag_suffix: "-debian13"
permissions: permissions:
contents: read contents: read
@@ -41,8 +54,9 @@ jobs:
images: | images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=semver,pattern={{version}}-arm64 type=semver,pattern={{version}}-arm64${{ matrix.tag_suffix }}
type=raw,value=latest-arm64,enable={{is_default_branch}} type=raw,value=latest-arm64${{ matrix.tag_suffix }},enable={{is_default_branch}}
type=ref,event=branch,suffix=-arm64${{ matrix.tag_suffix }}
- name: Get build time - name: Get build time
id: build_time id: build_time
@@ -52,6 +66,7 @@ jobs:
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./docker/Dockerfile
platforms: linux/arm64 platforms: linux/arm64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
@@ -59,6 +74,7 @@ jobs:
build-args: | build-args: |
VERSION=${{ github.ref_name }} VERSION=${{ github.ref_name }}
BUILD_TIME=${{ steps.build_time.outputs.time }} BUILD_TIME=${{ steps.build_time.outputs.time }}
cache-from: type=gha,scope=linux-arm64 BASE_TAG=${{ matrix.base_tag }}
cache-to: type=gha,scope=linux-arm64,mode=max cache-from: type=gha,scope=linux-arm64-${{ matrix.base_type }}
cache-to: type=gha,scope=linux-arm64-${{ matrix.base_type }},mode=max
provenance: false provenance: false
+48 -5
View File
@@ -14,9 +14,39 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
base_type: [debian, alpine, debian13]
platform: platform:
- linux/amd64 - linux/amd64
- linux/arm64 - linux/arm64
include:
- base_type: debian
platform: linux/arm/v7
base_tag: base
tag_suffix: ""
- base_type: debian
platform: linux/amd64
base_tag: base
tag_suffix: ""
- base_type: debian
platform: linux/arm64
base_tag: base
tag_suffix: ""
- base_type: alpine
platform: linux/amd64
base_tag: base-alpine
tag_suffix: "-alpine"
- base_type: alpine
platform: linux/arm64
base_tag: base-alpine
tag_suffix: "-alpine"
- base_type: debian13
platform: linux/amd64
base_tag: base-debian13
tag_suffix: "-debian13"
- base_type: debian13
platform: linux/arm64
base_tag: base-debian13
tag_suffix: "-debian13"
permissions: permissions:
contents: read contents: read
@@ -30,7 +60,7 @@ jobs:
id: platform id: platform
run: | run: |
platform=${{ matrix.platform }} platform=${{ matrix.platform }}
echo "pair=${platform//\//-}" >> $GITHUB_OUTPUT echo "pair=${platform//\//-}-${{ matrix.base_type }}" >> $GITHUB_OUTPUT
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
@@ -61,10 +91,12 @@ jobs:
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./docker/Dockerfile
platforms: ${{ matrix.platform }} platforms: ${{ matrix.platform }}
build-args: | build-args: |
VERSION=${{ github.ref_name }} VERSION=${{ github.ref_name }}
BUILD_TIME=${{ steps.build_time.outputs.time }} BUILD_TIME=${{ steps.build_time.outputs.time }}
BASE_TAG=${{ matrix.base_tag }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true outputs: type=image,name=${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=${{ steps.platform.outputs.pair }} cache-from: type=gha,scope=${{ steps.platform.outputs.pair }}
@@ -88,6 +120,16 @@ jobs:
merge: merge:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
strategy:
matrix:
base_type: [debian, alpine, debian13]
include:
- base_type: debian
tag_suffix: ""
- base_type: alpine
tag_suffix: "-alpine"
- base_type: debian13
tag_suffix: "-debian13"
permissions: permissions:
contents: write contents: write
@@ -101,7 +143,7 @@ jobs:
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
path: /tmp/digests path: /tmp/digests
pattern: digests-* pattern: digests-*-${{ matrix.base_type }}
merge-multiple: true merge-multiple: true
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -121,8 +163,8 @@ jobs:
images: | images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=semver,pattern={{version}} type=semver,pattern={{version}}${{ matrix.tag_suffix }}
type=raw,value=latest type=raw,value=latest${{ matrix.tag_suffix }}
- name: Create manifest list and push - name: Create manifest list and push
working-directory: /tmp/digests working-directory: /tmp/digests
@@ -132,9 +174,10 @@ jobs:
- name: Inspect image - name: Inspect image
run: | run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}${{ matrix.tag_suffix }}
- name: Create GitHub Release - name: Create GitHub Release
if: matrix.base_type == 'debian'
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
tag_name: ${{ github.ref_name }} tag_name: ${{ github.ref_name }}
+1
View File
@@ -48,3 +48,4 @@ configs/config.local.json
__pycache__/ __pycache__/
# Misc # Misc
.stfolder
+3
View File
@@ -0,0 +1,3 @@
.git/
web/node_modules
web/dist
+4 -4
View File
@@ -6,7 +6,7 @@ GOGET=go get
GOMOD=go mod GOMOD=go mod
VERSION=$(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") VERSION=$(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
BUILD_TIME=$(shell date '+%Y/%m/%d %H:%M:%S') BUILD_TIME=$(shell date '+%Y/%m/%d %H:%M:%S')
LDFLAGS=-ldflags="-s -w -X 'baihu/internal/constant.Version=$(VERSION)' -X 'baihu/internal/constant.BuildTime=$(BUILD_TIME)'" LDFLAGS=-ldflags="-s -w -X 'github.com/engigu/baihu-panel/internal/constant.Version=$(VERSION)' -X 'github.com/engigu/baihu-panel/internal/constant.BuildTime=$(BUILD_TIME)'"
# Default target # Default target
all: build all: build
@@ -66,7 +66,7 @@ deps:
# Docker build # Docker build
docker-build: docker-build:
docker build -t $(BINARY) . docker build -t $(BINARY) -f docker/Dockerfile .
# Docker run # Docker run
docker-run: docker-run:
@@ -74,11 +74,11 @@ docker-run:
# Docker compose up # Docker compose up
docker-up: docker-up:
docker-compose up -d docker-compose -f docker/docker-compose.yml up -d
# Docker compose down # Docker compose down
docker-down: docker-down:
docker-compose down docker-compose -f docker/docker-compose.yml down
# Help # Help
help: help:
+10 -1
View File
@@ -1,7 +1,6 @@
# 白虎面板 # 白虎面板
[![Hits](https://hits.sh/github.com/engigu/baihu-panel.svg?view=today-total)](https://hits.sh/github.com/engigu/baihu-panel/) [![Hits](https://hits.sh/github.com/engigu/baihu-panel.svg?view=today-total)](https://hits.sh/github.com/engigu/baihu-panel/)
[![Image Tags](https://ghcr-badge.egpl.dev/engigu/baihu/tags?color=%2344cc11&ignore=latest%2Cmain*%2Cdev&n=3&label=docker+tags&trim=)](https://ghcr-badge.egpl.dev/engigu/baihu/tags)
![Latest Version](https://ghcr-badge.egpl.dev/engigu/baihu/latest_tag?color=%2344cc11&ignore=latest%2Cmain*&label=docker+version&trim=) ![Latest Version](https://ghcr-badge.egpl.dev/engigu/baihu/latest_tag?color=%2344cc11&ignore=latest%2Cmain*&label=docker+version&trim=)
![Image Size](https://ghcr-badge.egpl.dev/engigu/baihu/size?color=%2344cc11&tag=latest&label=docker+image&trim=) ![Image Size](https://ghcr-badge.egpl.dev/engigu/baihu/size?color=%2344cc11&tag=latest&label=docker+image&trim=)
![Image pulls](https://img.shields.io/badge/dynamic/json?url=https://ghcr-badge.elias.eu.org/api/engigu/baihu-panel/baihu&query=downloadCount&style=flat&label=docker%20pulls&color=44cc11) ![Image pulls](https://img.shields.io/badge/dynamic/json?url=https://ghcr-badge.elias.eu.org/api/engigu/baihu-panel/baihu&query=downloadCount&style=flat&label=docker%20pulls&color=44cc11)
@@ -10,6 +9,14 @@
演示站点(演示站点的服务器比较烂,见谅) [演示站点](https://baihu-demo-site.qwapi.eu.org/) 演示站点(演示站点的服务器比较烂,见谅) [演示站点](https://baihu-demo-site.qwapi.eu.org/)
## 更新日志 ☕
### 最近更新
**2026.02.06** - 整理 Docker 目录结构,增加 Alpine 及 Debian 13 (Trixie) 镜像支持
[查看完整更新日志](./CHANGELOG.md)
## 项目来由 ## 项目来由
多少和青龙面板有点关系,我自己也是青龙面板的使用者,但是现在的青龙面板性能我觉得有点难以接受。以我自己的使用(`机器1C2G`)为例,一个`python``requests`脚本每隔`30s`执行一次,有时候cpu执行的时候能跳变到`50%`以上。可以看看下面gif图片(如果不动,点击图片查看) 多少和青龙面板有点关系,我自己也是青龙面板的使用者,但是现在的青龙面板性能我觉得有点难以接受。以我自己的使用(`机器1C2G`)为例,一个`python``requests`脚本每隔`30s`执行一次,有时候cpu执行的时候能跳变到`50%`以上。可以看看下面gif图片(如果不动,点击图片查看)
@@ -24,6 +31,8 @@
![baihu.gif](https://f.pz.al/pzal/2025/12/24/f0d171f9a686d.gif) ![baihu.gif](https://f.pz.al/pzal/2025/12/24/f0d171f9a686d.gif)
如果项目有用,请帮忙点个star。
## 特色 ## 特色
- **轻量级:** docker/compose部署,无需复杂配置,开箱即用 - **轻量级:** docker/compose部署,无需复杂配置,开箱即用
+6 -4
View File
@@ -1,7 +1,8 @@
ARG BASE_TAG=base
# ================================ # ================================
# Stage 1: Build frontend # Stage 1: Build frontend
# ================================ # ================================
FROM node:20-alpine AS frontend-builder FROM --platform=$BUILDPLATFORM node:20-alpine AS frontend-builder
WORKDIR /app/web WORKDIR /app/web
@@ -59,7 +60,7 @@ COPY --from=frontend-builder /app/web/dist ./internal/static/dist
RUN VERSION_VAL=$(cat /build-info/version.txt) && \ RUN VERSION_VAL=$(cat /build-info/version.txt) && \
BUILD_TIME_VAL=$(cat /build-info/build_time.txt) && \ BUILD_TIME_VAL=$(cat /build-info/build_time.txt) && \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
go build -ldflags="-s -w -X baihu/internal/constant.Version=${VERSION_VAL} -X 'baihu/internal/constant.BuildTime=${BUILD_TIME_VAL}'" \ go build -ldflags="-s -w -X github.com/engigu/baihu-panel/internal/constant.Version=${VERSION_VAL} -X 'github.com/engigu/baihu-panel/internal/constant.BuildTime=${BUILD_TIME_VAL}'" \
-o baihu . -o baihu .
# ================================ # ================================
@@ -104,7 +105,8 @@ RUN VERSION_VAL=$(cat /build-info/version.txt) && \
# ================================ # ================================
# Stage 4: Final image # Stage 4: Final image
# ================================ # ================================
FROM ghcr.io/engigu/baihu:base ARG BASE_TAG
FROM ghcr.io/engigu/baihu:${BASE_TAG}
ENV TZ=Asia/Shanghai ENV TZ=Asia/Shanghai
ENV PATH="/app/envs/node/bin:/app/envs/python/bin:$PATH" ENV PATH="/app/envs/node/bin:/app/envs/python/bin:$PATH"
@@ -130,7 +132,7 @@ COPY --from=frontend-builder /app/web/dist ./internal/static/dist
# Copy configs and entrypoint # Copy configs and entrypoint
COPY --from=backend-builder /app/configs ./configs COPY --from=backend-builder /app/configs ./configs
COPY docker-entrypoint.sh . COPY docker/docker-entrypoint.sh .
# Copy sync.py to /opt # Copy sync.py to /opt
COPY custom/sync.py /opt/sync.py COPY custom/sync.py /opt/sync.py
+24
View File
@@ -0,0 +1,24 @@
FROM alpine:3.19
ENV TZ=Asia/Shanghai
ENV PATH="/app/envs/node/bin:/app/envs/python/bin:$PATH"
ENV NODE_PATH="/app/envs/node/lib/node_modules"
# 安装必要系统工具 + Node + Python
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
&& apk add --no-cache \
tzdata \
git \
gcc \
musl-dev \
curl \
wget \
vim \
nodejs \
npm \
python3 \
py3-pip \
htop \
&& cp /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo "${TZ}" > /etc/timezone \
&& rm -rf /var/cache/apk/*
+15
View File
@@ -0,0 +1,15 @@
FROM debian:trixie-slim
ENV TZ=Asia/Shanghai
ENV PATH="/app/envs/node/bin:/app/envs/python/bin:$PATH"
ENV NODE_PATH="/app/envs/node/lib/node_modules"
# 安装必要系统工具 + Node + Python
RUN sed -i 's@deb.debian.org@mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.list.d/debian.sources \
&& sed -i 's@security.debian.org@mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.list.d/debian.sources \
&& echo "${TZ}" > /etc/timezone \
&& ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
tzdata git gcc curl wget vim nodejs htop npm python3 python3-venv python3-pip \
&& rm -rf /var/lib/apt/lists/*
+3 -3
View File
@@ -1,4 +1,4 @@
module baihu module github.com/engigu/baihu-panel
go 1.24.0 go 1.24.0
@@ -11,8 +11,10 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang-jwt/jwt/v5 v5.3.0
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v3 v3.24.5
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
golang.org/x/text v0.32.0 golang.org/x/text v0.32.0
gopkg.in/ini.v1 v1.67.0
gorm.io/driver/mysql v1.6.0 gorm.io/driver/mysql v1.6.0
gorm.io/driver/postgres v1.6.0 gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.31.1 gorm.io/gorm v1.31.1
@@ -51,7 +53,6 @@ require (
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect github.com/tklauser/numcpus v0.6.1 // indirect
@@ -64,7 +65,6 @@ require (
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect golang.org/x/sys v0.39.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.22.5 // indirect modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect modernc.org/mathutil v1.5.0 // indirect
+6 -4
View File
@@ -41,9 +41,10 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
@@ -100,6 +101,8 @@ github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/i
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -111,8 +114,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -144,8 +148,6 @@ golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+5 -5
View File
@@ -4,11 +4,11 @@ import (
"fmt" "fmt"
"os" "os"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/router" "github.com/engigu/baihu-panel/internal/router"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+3 -3
View File
@@ -3,9 +3,9 @@ package cache
import ( import (
"sync" "sync"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
// siteCache 站点设置内存缓存 // siteCache 站点设置内存缓存
+6 -3
View File
@@ -18,9 +18,9 @@ type Sentence struct {
} }
var ( var (
lineCount int lineCount int
lineOffsets []int64 lineOffsets []int64
sentenceOnce sync.Once sentenceOnce sync.Once
) )
// initSentences 初始化:统计行数和记录每行偏移 // initSentences 初始化:统计行数和记录每行偏移
@@ -51,6 +51,9 @@ func GetRandomSentence() string {
if currentLine == targetLine { if currentLine == targetLine {
var s Sentence var s Sentence
if err := json.Unmarshal(scanner.Bytes(), &s); err == nil && s.Name != "" { if err := json.Unmarshal(scanner.Bytes(), &s); err == nil && s.Name != "" {
if s.From != "" {
return "\"" + s.Name + "\"—— " + s.From
}
return s.Name return s.Name
} }
break break
+4 -4
View File
@@ -1,10 +1,10 @@
package controllers package controllers
import ( import (
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"encoding/json" "encoding/json"
"net/http" "net/http"
"strconv" "strconv"
+4 -4
View File
@@ -3,10 +3,10 @@ package controllers
import ( import (
"strconv" "strconv"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/middleware" "github.com/engigu/baihu-panel/internal/middleware"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+5 -5
View File
@@ -4,11 +4,11 @@ import (
"sort" "sort"
"time" "time"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -4,9 +4,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+2 -2
View File
@@ -3,8 +3,8 @@ package controllers
import ( import (
"strconv" "strconv"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+2 -2
View File
@@ -3,8 +3,8 @@ package controllers
import ( import (
"strconv" "strconv"
"baihu/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+3 -3
View File
@@ -3,9 +3,9 @@ package controllers
import ( import (
"strconv" "strconv"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+2 -2
View File
@@ -3,8 +3,8 @@ package controllers
import ( import (
"strconv" "strconv"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+6 -6
View File
@@ -5,12 +5,12 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"fmt" "fmt"
"os" "os"
"time" "time"
+4 -4
View File
@@ -4,10 +4,10 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+2 -2
View File
@@ -10,8 +10,8 @@ import (
"sync" "sync"
"unicode/utf8" "unicode/utf8"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/creack/pty" "github.com/creack/pty"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"time" "time"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"github.com/glebarez/sqlite" "github.com/glebarez/sqlite"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
+2 -2
View File
@@ -1,8 +1,8 @@
package database package database
import ( import (
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
func Migrate() error { func Migrate() error {
+2 -2
View File
@@ -1,8 +1,8 @@
package middleware package middleware
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"time" "time"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"gorm.io/gorm" "gorm.io/gorm"
) )
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"time" "time"
) )
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"gorm.io/gorm" "gorm.io/gorm"
) )
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
) )
// LoginLog 登录日志 // LoginLog 登录日志
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
) )
// SendStats 任务执行统计 // SendStats 任务执行统计
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
) )
// Setting 系统设置 // Setting 系统设置
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"gorm.io/gorm" "gorm.io/gorm"
) )
+1 -1
View File
@@ -1,7 +1,7 @@
package models package models
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"gorm.io/gorm" "gorm.io/gorm"
) )
+4 -4
View File
@@ -1,10 +1,10 @@
package router package router
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/controllers" "github.com/engigu/baihu-panel/internal/controllers"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
) )
var cronService *tasks.CronService var cronService *tasks.CronService
+4 -4
View File
@@ -5,10 +5,10 @@ import (
"net/http" "net/http"
"strings" "strings"
"baihu/internal/controllers" "github.com/engigu/baihu-panel/internal/controllers"
"baihu/internal/middleware" "github.com/engigu/baihu-panel/internal/middleware"
"baihu/internal/services" "github.com/engigu/baihu-panel/internal/services"
"baihu/internal/static" "github.com/engigu/baihu-panel/internal/static"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+5 -5
View File
@@ -1,11 +1,11 @@
package services package services
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
+3 -3
View File
@@ -1,9 +1,9 @@
package services package services
import ( import (
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"encoding/json" "encoding/json"
"sync" "sync"
"time" "time"
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type BackupService struct { type BackupService struct {
+3 -3
View File
@@ -1,8 +1,8 @@
package services package services
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"os" "os"
"strconv" "strconv"
@@ -67,7 +67,7 @@ func LoadConfig(path string) (*AppConfig, error) {
Port: 3306, Port: 3306,
User: "root", User: "root",
Password: "", Password: "",
DBName: "baihu", DBName: "github.com/engigu/baihu-panel",
Path: constant.DefaultDBPath, Path: constant.DefaultDBPath,
TablePrefix: "baihu_", TablePrefix: "baihu_",
}, },
+3 -3
View File
@@ -5,9 +5,9 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type DependencyService struct{} type DependencyService struct{}
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type EnvService struct{} type EnvService struct{}
+1 -1
View File
@@ -1,7 +1,7 @@
package services package services
import ( import (
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
) )
type InitService struct { type InitService struct {
+2 -2
View File
@@ -1,8 +1,8 @@
package services package services
import ( import (
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type LoginLogService struct{} type LoginLogService struct{}
+2 -2
View File
@@ -1,8 +1,8 @@
package services package services
import ( import (
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type ScriptService struct{} type ScriptService struct{}
+2 -2
View File
@@ -3,8 +3,8 @@ package services
import ( import (
"time" "time"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type SendStatsService struct{} type SendStatsService struct{}
+4 -4
View File
@@ -1,10 +1,10 @@
package services package services
import ( import (
"baihu/internal/cache" "github.com/engigu/baihu-panel/internal/cache"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type SettingsService struct{} type SettingsService struct{}
+3 -3
View File
@@ -4,9 +4,9 @@ import (
"sync" "sync"
"time" "time"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"github.com/robfig/cron/v3" "github.com/robfig/cron/v3"
) )
+3 -3
View File
@@ -1,9 +1,9 @@
package tasks package tasks
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
@@ -1,11 +1,11 @@
package tasks package tasks
import ( import (
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
+4 -4
View File
@@ -1,10 +1,10 @@
package tasks package tasks
import ( import (
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
"baihu/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"encoding/json" "encoding/json"
"time" "time"
) )
+2 -2
View File
@@ -1,8 +1,8 @@
package tasks package tasks
import ( import (
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type TaskService struct{} type TaskService struct{}
+3 -3
View File
@@ -4,9 +4,9 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"baihu/internal/database" "github.com/engigu/baihu-panel/internal/database"
"baihu/internal/models" "github.com/engigu/baihu-panel/internal/models"
) )
type UserService struct{} type UserService struct{}
+2 -2
View File
@@ -3,8 +3,8 @@ package utils
import ( import (
"strconv" "strconv"
"baihu/internal/cache" "github.com/engigu/baihu-panel/internal/cache"
"baihu/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+1 -1
View File
@@ -1,6 +1,6 @@
package main package main
import "baihu/internal/bootstrap" import "github.com/engigu/baihu-panel/internal/bootstrap"
func main() { func main() {
bootstrap.New().Run() bootstrap.New().Run()
+21 -27
View File
@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { ref, onMounted, computed } from 'vue'
import { RouterLink, RouterView, useRoute } from 'vue-router' import { RouterLink, RouterView, useRoute } from 'vue-router'
import { resetAuthCache } from '@/router' import { resetAuthCache } from '@/router'
import { LayoutDashboard, ListTodo, FileCode, Settings, LogOut, ScrollText, Terminal, Variable, KeyRound, Package, Menu, X, Server } from 'lucide-vue-next' import { LayoutDashboard, ListTodo, FileCode, Settings, LogOut, ScrollText, Terminal, Variable, KeyRound, Package, Menu, X, Server } from 'lucide-vue-next'
@@ -46,6 +46,10 @@ const cachedSentence = loadSentenceFromCache()
const sentence = ref(cachedSentence || '欢迎使用白虎面板') const sentence = ref(cachedSentence || '欢迎使用白虎面板')
const { siteSettings, loadSettings } = useSiteSettings() const { siteSettings, loadSettings } = useSiteSettings()
const mobileMenuOpen = ref(false) const mobileMenuOpen = ref(false)
const sentenceContent = computed(() => {
const match = sentence.value.match(/^"(.+)"—— /)
return match ? match[1] : sentence.value
})
const navItems = [ const navItems = [
{ to: '/', icon: LayoutDashboard, label: '数据仪表', exact: true }, { to: '/', icon: LayoutDashboard, label: '数据仪表', exact: true },
@@ -101,19 +105,13 @@ onMounted(() => {
<template> <template>
<div class="flex h-screen bg-muted/40"> <div class="flex h-screen bg-muted/40">
<!-- Mobile Menu Overlay --> <!-- Mobile Menu Overlay -->
<div <div v-if="mobileMenuOpen" class="fixed inset-0 bg-black/50 z-40 lg:hidden" @click="mobileMenuOpen = false" />
v-if="mobileMenuOpen"
class="fixed inset-0 bg-black/50 z-40 lg:hidden"
@click="mobileMenuOpen = false"
/>
<!-- Sidebar --> <!-- Sidebar -->
<aside <aside :class="[
:class="[ 'fixed lg:static inset-y-0 left-0 z-50 w-44 border-r bg-background flex flex-col transform transition-transform duration-200 ease-in-out lg:transform-none',
'fixed lg:static inset-y-0 left-0 z-50 w-44 border-r bg-background flex flex-col transform transition-transform duration-200 ease-in-out lg:transform-none', mobileMenuOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'
mobileMenuOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0' ]">
]"
>
<div class="h-14 flex items-center justify-center px-4 font-semibold text-lg border-b relative"> <div class="h-14 flex items-center justify-center px-4 font-semibold text-lg border-b relative">
<span>{{ siteSettings.title }}</span> <span>{{ siteSettings.title }}</span>
<Button variant="ghost" size="icon" class="h-8 w-8 lg:hidden absolute right-2" @click="mobileMenuOpen = false"> <Button variant="ghost" size="icon" class="h-8 w-8 lg:hidden absolute right-2" @click="mobileMenuOpen = false">
@@ -121,25 +119,18 @@ onMounted(() => {
</Button> </Button>
</div> </div>
<nav class="flex-1 px-3 py-6 space-y-1 flex flex-col items-center"> <nav class="flex-1 px-3 py-6 space-y-1 flex flex-col items-center">
<RouterLink <RouterLink v-for="item in navItems" :key="item.to" :to="item.to" custom v-slot="{ navigate }">
v-for="item in navItems" <Button variant="ghost"
:key="item.to"
:to="item.to"
custom
v-slot="{ navigate }"
>
<Button
variant="ghost"
:class="['justify-start gap-3 h-9 px-3', isItemActive(item) && 'bg-accent text-accent-foreground']" :class="['justify-start gap-3 h-9 px-3', isItemActive(item) && 'bg-accent text-accent-foreground']"
@click="handleNavClick(navigate)" @click="handleNavClick(navigate)">
>
<component :is="item.icon" class="h-4 w-4" /> <component :is="item.icon" class="h-4 w-4" />
{{ item.label }} {{ item.label }}
</Button> </Button>
</RouterLink> </RouterLink>
</nav> </nav>
<div class="px-3 py-4 border-t flex justify-center"> <div class="px-3 py-4 border-t flex justify-center">
<Button variant="ghost" class="justify-start gap-3 h-9 px-3 text-muted-foreground hover:text-foreground" @click="logout"> <Button variant="ghost" class="justify-start gap-3 h-9 px-3 text-muted-foreground hover:text-foreground"
@click="logout">
<LogOut class="h-4 w-4" /> <LogOut class="h-4 w-4" />
退出登录 退出登录
</Button> </Button>
@@ -149,11 +140,14 @@ onMounted(() => {
<!-- Main Content --> <!-- Main Content -->
<main class="flex-1 overflow-auto w-full"> <main class="flex-1 overflow-auto w-full">
<div class="h-14 border-b bg-background flex items-center justify-between px-4 lg:px-6"> <div class="h-14 border-b bg-background flex items-center justify-between px-4 lg:px-6">
<div class="flex items-center gap-3"> <div class="flex items-center gap-3 flex-1 min-w-0">
<Button variant="ghost" size="icon" class="h-8 w-8 lg:hidden" @click="mobileMenuOpen = true"> <Button variant="ghost" size="icon" class="h-8 w-8 lg:hidden shrink-0" @click="mobileMenuOpen = true">
<Menu class="h-5 w-5" /> <Menu class="h-5 w-5" />
</Button> </Button>
<span class="text-sm text-muted-foreground truncate max-w-[200px] sm:max-w-none">{{ sentence }}</span> <span class="text-sm text-muted-foreground truncate" :title="sentence">
<span class="hidden sm:inline">{{ sentence }}</span>
<span class="sm:hidden">{{ sentenceContent }}</span>
</span>
</div> </div>
<ThemeToggle /> <ThemeToggle />
</div> </div>
+9 -5
View File
@@ -422,7 +422,7 @@ onMounted(async () => {
themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }) themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })
}, 500) }, 500)
}, 100) }, 100)
} catch {} } catch { }
}) })
onUnmounted(() => { onUnmounted(() => {
@@ -448,7 +448,8 @@ onUnmounted(() => {
</div> </div>
<div class="grid gap-4 grid-cols-2 sm:grid-cols-3 lg:grid-cols-6"> <div class="grid gap-4 grid-cols-2 sm:grid-cols-3 lg:grid-cols-6">
<Card v-for="item in statItems" :key="item.key" class="cursor-pointer hover:bg-accent/50 transition-colors" @click="navigateTo(item.route)"> <Card v-for="item in statItems" :key="item.key" class="cursor-pointer hover:bg-accent/50 transition-colors"
@click="navigateTo(item.route)">
<CardHeader class="flex flex-row items-center justify-between space-y-0 pb-2"> <CardHeader class="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle class="text-xs sm:text-sm font-medium">{{ item.label }}</CardTitle> <CardTitle class="text-xs sm:text-sm font-medium">{{ item.label }}</CardTitle>
<component :is="item.icon" class="h-4 w-4 text-muted-foreground" /> <component :is="item.icon" class="h-4 w-4 text-muted-foreground" />
@@ -467,7 +468,8 @@ onUnmounted(() => {
</CardHeader> </CardHeader>
<CardContent class="relative h-[300px]"> <CardContent class="relative h-[300px]">
<div id="stats-chart" class="w-full h-full"></div> <div id="stats-chart" class="w-full h-full"></div>
<div v-if="!chartsLoaded" class="absolute inset-0 flex items-center justify-center text-muted-foreground text-sm bg-card"> <div v-if="!chartsLoaded"
class="absolute inset-0 flex items-center justify-center text-muted-foreground text-sm bg-card">
加载中... 加载中...
</div> </div>
</CardContent> </CardContent>
@@ -480,10 +482,12 @@ onUnmounted(() => {
</CardHeader> </CardHeader>
<CardContent class="relative h-[300px]"> <CardContent class="relative h-[300px]">
<div id="pie-chart" class="w-full h-full"></div> <div id="pie-chart" class="w-full h-full"></div>
<div v-if="!chartsLoaded" class="absolute inset-0 flex items-center justify-center text-muted-foreground text-sm bg-card"> <div v-if="!chartsLoaded"
class="absolute inset-0 flex items-center justify-center text-muted-foreground text-sm bg-card">
加载中... 加载中...
</div> </div>
<div v-else-if="taskStats.length === 0" class="absolute inset-0 flex items-center justify-center text-muted-foreground text-sm bg-card"> <div v-else-if="taskStats.length === 0"
class="absolute inset-0 flex items-center justify-center text-muted-foreground text-sm bg-card">
暂无数据 暂无数据
</div> </div>
</CardContent> </CardContent>
+5 -7
View File
@@ -6,7 +6,6 @@ import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label' import { Label } from '@/components/ui/label'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { Badge } from '@/components/ui/badge'
import DirTreeSelect from '@/components/DirTreeSelect.vue' import DirTreeSelect from '@/components/DirTreeSelect.vue'
import { Plus, ChevronDown, X } from 'lucide-vue-next' import { Plus, ChevronDown, X } from 'lucide-vue-next'
import { api, type Task, type EnvVar, type Agent } from '@/api' import { api, type Task, type EnvVar, type Agent } from '@/api'
@@ -132,8 +131,7 @@ function addEnv(id: number) {
} }
function removeEnv(id: number) { function removeEnv(id: number) {
const idx = selectedEnvIds.value.indexOf(id) selectedEnvIds.value = selectedEnvIds.value.filter(envId => envId !== id)
if (idx !== -1) selectedEnvIds.value.splice(idx, 1)
} }
async function save() { async function save() {
@@ -266,10 +264,10 @@ async function save() {
</PopoverContent> </PopoverContent>
</Popover> </Popover>
<div v-if="selectedEnvs.length > 0" class="flex flex-wrap gap-1"> <div v-if="selectedEnvs.length > 0" class="flex flex-wrap gap-1">
<Badge v-for="env in selectedEnvs" :key="env.id" variant="secondary" class="gap-0.5 pr-0.5 text-xs h-5"> <div v-for="env in selectedEnvs" :key="env.id" class="inline-flex items-center gap-0.5 px-2 py-0.5 text-xs h-5 rounded-full bg-secondary text-secondary-foreground">
{{ env.name }} <span>{{ env.name }}</span>
<X class="h-2.5 w-2.5 cursor-pointer hover:text-destructive" @click.stop="removeEnv(env.id)" /> <X class="h-2.5 w-2.5 cursor-pointer hover:text-destructive" @click="removeEnv(env.id)" />
</Badge> </div>
</div> </div>
</div> </div>
</div> </div>