fix: 完成Vue组件语法修复和大屏告警V2集成
修复内容: - 修复客户配置页面Vue组件JSX语法错误 - 统一script标签语言类型,避免编译冲突 - 将JSX render函数转换为标准h函数调用 - 集成大屏告警V2 API路由和服务层 技术改进: - Vue组件渲染函数标准化 - 添加告警统计和确认功能API - 完善实时告警数据展示 - 增强系统稳定性和可维护性
This commit is contained in:
@@ -0,0 +1,587 @@
|
||||
# 灵境万象Docker镜像源代码保护方案
|
||||
|
||||
## 项目概述
|
||||
|
||||
灵境万象健康管理系统是一个基于微服务架构的企业级健康监测平台,包含多个服务组件:
|
||||
- **ljwx-boot**: Spring Boot后端API服务
|
||||
- **ljwx-admin**: Vue3前端管理界面
|
||||
- **ljwx-bigscreen**: Python Flask告警处理引擎
|
||||
- **ljwx-watch**: 设备数据采集服务
|
||||
|
||||
本方案基于项目实际架构,结合Docker安全最佳实践,设计了多层防护的源代码保护策略。
|
||||
|
||||
## 当前架构分析
|
||||
|
||||
### 现有构建流程
|
||||
```bash
|
||||
# 当前构建脚本: build-and-push.sh
|
||||
LOCAL_BUILD=true PLATFORMS=linux/amd64 PUSH_TO_REGISTRY=false ./build-and-push.sh boot
|
||||
LOCAL_BUILD=true PLATFORMS=linux/amd64 PUSH_TO_REGISTRY=false ./build-and-push.sh admin
|
||||
LOCAL_BUILD=true PLATFORMS=linux/amd64 PUSH_TO_REGISTRY=false ./build-and-push.sh bigscreen
|
||||
```
|
||||
|
||||
### 现有Dockerfile分析
|
||||
项目采用了不同的构建策略:
|
||||
|
||||
**ljwx-boot (Java服务)**:
|
||||
```dockerfile
|
||||
# 直接使用预构建JAR包 - 安全性较高
|
||||
FROM eclipse-temurin:21-jre-alpine
|
||||
COPY ljwx-boot/ljwx-boot-admin/target/*.jar app.jar
|
||||
```
|
||||
|
||||
**ljwx-admin (Vue3前端)**:
|
||||
```dockerfile
|
||||
# 使用预构建dist目录 - 源码已编译混淆
|
||||
FROM nginx:alpine
|
||||
COPY ljwx-admin/dist /usr/share/nginx/html
|
||||
```
|
||||
|
||||
**ljwx-bigscreen (Python服务)**:
|
||||
```dockerfile
|
||||
# 多阶段构建但仍包含源码 - 需要加强保护
|
||||
FROM python:3.12-slim
|
||||
COPY . .
|
||||
```
|
||||
|
||||
## 综合保护策略
|
||||
|
||||
### 1. 分层保护架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 构建时保护层 │
|
||||
│ • 多阶段构建移除源码 • 代码混淆编译 • 秘钥安全注入 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 镜像级保护层 │
|
||||
│ • 最小化基础镜像 • 文件权限控制 • 镜像签名验证 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 运行时保护层 │
|
||||
│ • 非特权用户运行 • 只读文件系统 • 安全选项配置 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 存储传输保护层 │
|
||||
│ • 私有镜像仓库 • 传输加密 • 访问控制 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. 服务特定保护方案
|
||||
|
||||
#### 2.1 ljwx-boot (Spring Boot) - 增强保护
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile.boot.secure
|
||||
# 阶段1: 构建和混淆
|
||||
FROM eclipse-temurin:21-jdk AS builder
|
||||
WORKDIR /app
|
||||
COPY ljwx-boot/pom.xml ljwx-boot/ljwx-boot-admin/pom.xml ./
|
||||
COPY ljwx-boot/ljwx-boot-admin/src ./src
|
||||
RUN mvn clean package -DskipTests
|
||||
|
||||
# 可选:添加代码混淆
|
||||
FROM eclipse-temurin:21-jdk AS obfuscator
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/target/*.jar app.jar
|
||||
# 使用ProGuard或其他混淆工具
|
||||
RUN java -jar proguard.jar @proguard-config.txt
|
||||
|
||||
# 阶段2: 安全运行环境
|
||||
FROM eclipse-temurin:21-jre-alpine AS production
|
||||
RUN addgroup -g 1001 -S appgroup && \
|
||||
adduser -u 1001 -S appuser -G appgroup
|
||||
USER appuser
|
||||
WORKDIR /home/appuser
|
||||
COPY --from=obfuscator /app/app.jar ./app.jar
|
||||
EXPOSE 9998
|
||||
CMD ["java", "-Xms256m", "-Xmx512m", "-jar", "app.jar"]
|
||||
```
|
||||
|
||||
#### 2.2 ljwx-admin (Vue3) - 增强混淆
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile.admin.secure
|
||||
# 阶段1: 构建和混淆
|
||||
FROM node:18 AS builder
|
||||
WORKDIR /app
|
||||
COPY ljwx-admin/package*.json ./
|
||||
RUN npm ci --only=production
|
||||
|
||||
COPY ljwx-admin/src ./src
|
||||
COPY ljwx-admin/public ./public
|
||||
COPY ljwx-admin/vite.config.ts ljwx-admin/tsconfig.json ./
|
||||
|
||||
# 启用源码混淆和压缩
|
||||
RUN npm run build
|
||||
|
||||
# 阶段2: 进一步混淆JavaScript
|
||||
FROM node:18 AS obfuscator
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/dist ./dist
|
||||
RUN npm install -g javascript-obfuscator
|
||||
RUN find dist -name "*.js" -exec javascript-obfuscator {} \
|
||||
--output {} --compact true --control-flow-flattening true \
|
||||
--dead-code-injection true --string-array true \;
|
||||
|
||||
# 阶段3: 生产运行环境
|
||||
FROM nginx:alpine AS production
|
||||
RUN addgroup -g 1001 -S nginx_group && \
|
||||
adduser -u 1001 -S nginx_user -G nginx_group
|
||||
COPY --from=obfuscator --chown=nginx_user:nginx_group /app/dist /usr/share/nginx/html
|
||||
COPY ljwx-admin/nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
USER nginx_user
|
||||
EXPOSE 80
|
||||
```
|
||||
|
||||
#### 2.3 ljwx-bigscreen (Python) - 代码加密保护
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile.bigscreen.secure
|
||||
# 阶段1: 构建和依赖安装
|
||||
FROM python:3.12-slim AS builder
|
||||
WORKDIR /app
|
||||
COPY ljwx-bigscreen/bigscreen/requirements-docker.txt .
|
||||
RUN pip install --user -r requirements-docker.txt
|
||||
|
||||
# 阶段2: 代码编译保护
|
||||
FROM python:3.12-slim AS compiler
|
||||
WORKDIR /app
|
||||
COPY --from=builder /root/.local /root/.local
|
||||
COPY ljwx-bigscreen/bigscreen/ .
|
||||
|
||||
# Python代码编译为字节码
|
||||
RUN python -m compileall -b .
|
||||
RUN find . -name "*.py" -not -name "run.py" -delete
|
||||
RUN find . -name "__pycache__" -exec mv {}/*.pyc {}/.. \; -exec rmdir {} \;
|
||||
|
||||
# 阶段3: 最小化生产环境
|
||||
FROM python:3.12-alpine AS production
|
||||
WORKDIR /app
|
||||
RUN addgroup -g 1001 -S appgroup && \
|
||||
adduser -u 1001 -S appuser -G appgroup
|
||||
COPY --from=builder /root/.local /home/appuser/.local
|
||||
COPY --from=compiler --chown=appuser:appgroup /app .
|
||||
USER appuser
|
||||
ENV PATH=/home/appuser/.local/bin:$PATH
|
||||
EXPOSE 8001
|
||||
CMD ["python3", "run.py"]
|
||||
```
|
||||
|
||||
### 3. 安全构建脚本
|
||||
|
||||
创建 `build-secure.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 安全构建脚本
|
||||
set -e
|
||||
|
||||
echo "🔒 启动安全构建流程..."
|
||||
|
||||
# 构建配置
|
||||
REGISTRY="crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx"
|
||||
VERSION="1.2.16-secure"
|
||||
BUILDER_NAME="secure-builder"
|
||||
|
||||
# 初始化安全构建器
|
||||
docker buildx create --name $BUILDER_NAME --use || docker buildx use $BUILDER_NAME
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
# 构建安全镜像
|
||||
build_secure_image() {
|
||||
local service=$1
|
||||
echo "🔨 构建安全镜像: $service"
|
||||
|
||||
docker buildx build --platform linux/amd64,linux/arm64 \
|
||||
--file "Dockerfile.${service}.secure" \
|
||||
--tag "$REGISTRY/ljwx-$service:$VERSION" \
|
||||
--tag "$REGISTRY/ljwx-$service:secure" \
|
||||
--push \
|
||||
.
|
||||
|
||||
echo "✅ $service 安全镜像构建完成"
|
||||
}
|
||||
|
||||
# 构建所有安全镜像
|
||||
build_secure_image "boot"
|
||||
build_secure_image "admin"
|
||||
build_secure_image "bigscreen"
|
||||
|
||||
# 镜像签名
|
||||
sign_images() {
|
||||
echo "🔐 开始镜像签名..."
|
||||
|
||||
# 使用Cosign签名
|
||||
if command -v cosign >/dev/null 2>&1; then
|
||||
for service in boot admin bigscreen; do
|
||||
cosign sign --key cosign.key "$REGISTRY/ljwx-$service:$VERSION"
|
||||
done
|
||||
echo "✅ 镜像签名完成"
|
||||
else
|
||||
echo "⚠️ 未安装cosign,跳过镜像签名"
|
||||
fi
|
||||
}
|
||||
|
||||
sign_images
|
||||
|
||||
echo "🎉 安全构建流程完成!"
|
||||
```
|
||||
|
||||
### 4. 安全配置
|
||||
|
||||
#### 4.1 Docker Compose安全配置
|
||||
|
||||
创建 `docker-compose.secure.yml`:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
ljwx-boot:
|
||||
image: ${REGISTRY}/ljwx-boot:${VERSION}
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /home/appuser/logs
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- NET_BIND_SERVICE
|
||||
user: "1001:1001"
|
||||
networks:
|
||||
- internal
|
||||
volumes:
|
||||
- boot_logs:/home/appuser/logs:rw
|
||||
|
||||
ljwx-admin:
|
||||
image: ${REGISTRY}/ljwx-admin:${VERSION}
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /var/cache/nginx
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- SETUID
|
||||
- SETGID
|
||||
user: "1001:1001"
|
||||
networks:
|
||||
- internal
|
||||
- external
|
||||
ports:
|
||||
- "80:80"
|
||||
|
||||
ljwx-bigscreen:
|
||||
image: ${REGISTRY}/ljwx-bigscreen:${VERSION}
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /home/appuser/logs
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
user: "1001:1001"
|
||||
networks:
|
||||
- internal
|
||||
|
||||
networks:
|
||||
internal:
|
||||
driver: bridge
|
||||
internal: true
|
||||
external:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
boot_logs:
|
||||
admin_logs:
|
||||
bigscreen_logs:
|
||||
```
|
||||
|
||||
#### 4.2 环境变量安全管理
|
||||
|
||||
```bash
|
||||
# .env.secure
|
||||
REGISTRY=crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx
|
||||
VERSION=1.2.16-secure
|
||||
|
||||
# 数据库连接 - 使用Docker Secrets
|
||||
MYSQL_HOST_FILE=/run/secrets/mysql_host
|
||||
MYSQL_PASSWORD_FILE=/run/secrets/mysql_password
|
||||
|
||||
# Redis连接 - 使用Docker Secrets
|
||||
REDIS_PASSWORD_FILE=/run/secrets/redis_password
|
||||
|
||||
# 微信配置 - 使用Docker Secrets
|
||||
WECHAT_APP_SECRET_FILE=/run/secrets/wechat_app_secret
|
||||
```
|
||||
|
||||
### 5. 持续集成安全管道
|
||||
|
||||
创建 `.github/workflows/secure-build.yml`:
|
||||
|
||||
```yaml
|
||||
name: 安全镜像构建
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'ljwx-**/**'
|
||||
- 'Dockerfile.*.secure'
|
||||
|
||||
jobs:
|
||||
security-scan:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: 代码安全扫描
|
||||
uses: securecodewarrior/github-action-add-sarif@v1
|
||||
with:
|
||||
sarif-file: 'security-scan-results.sarif'
|
||||
|
||||
secure-build:
|
||||
needs: security-scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: 设置Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: 登录阿里云容器镜像服务
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com
|
||||
username: ${{ secrets.ALIYUN_USERNAME }}
|
||||
password: ${{ secrets.ALIYUN_PASSWORD }}
|
||||
|
||||
- name: 构建安全镜像
|
||||
run: |
|
||||
chmod +x build-secure.sh
|
||||
./build-secure.sh
|
||||
|
||||
- name: 镜像漏洞扫描
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: '${{ env.REGISTRY }}/ljwx-boot:${{ env.VERSION }}'
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
|
||||
- name: 上传扫描结果
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
```
|
||||
|
||||
### 6. 镜像仓库安全配置
|
||||
|
||||
#### 6.1 阿里云容器镜像服务配置
|
||||
|
||||
```bash
|
||||
# 镜像仓库安全策略
|
||||
# 1. 启用镜像扫描
|
||||
aliyun cr SetInstanceScanConfig --InstanceId xxx --ScanLevel High
|
||||
|
||||
# 2. 设置访问控制
|
||||
aliyun cr CreateRepoAuth --RepoNamespace ljwx --RepoName ljwx-boot --AuthRole readonly
|
||||
|
||||
# 3. 配置Webhook通知
|
||||
aliyun cr CreateRepoWebhook --RepoNamespace ljwx --WebhookUrl https://your-webhook.com
|
||||
```
|
||||
|
||||
#### 6.2 私有镜像拉取配置
|
||||
|
||||
```yaml
|
||||
# kubernetes-secrets.yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: aliyun-registry-secret
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
data:
|
||||
.dockerconfigjson: |
|
||||
{
|
||||
"auths": {
|
||||
"crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com": {
|
||||
"username": "brunogao",
|
||||
"password": "admin123",
|
||||
"auth": "YnJ1bm9nYW86YWRtaW4xMjM="
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. 运行时监控与告警
|
||||
|
||||
#### 7.1 容器运行时安全监控
|
||||
|
||||
```yaml
|
||||
# falco-rules.yaml
|
||||
- rule: 检测容器中的敏感文件访问
|
||||
desc: 监控容器中对敏感配置文件的访问
|
||||
condition: >
|
||||
open_read and container and
|
||||
fd.filename in (/app/config.py, /app/.env, /home/appuser/.ssh/id_rsa)
|
||||
output: >
|
||||
容器中检测到敏感文件访问
|
||||
(user=%user.name container=%container.name file=%fd.name)
|
||||
priority: WARNING
|
||||
|
||||
- rule: 检测异常网络连接
|
||||
desc: 监控容器的异常出站连接
|
||||
condition: >
|
||||
outbound and container and
|
||||
not fd.sip in (mysql_ips, redis_ips, allowed_external_ips)
|
||||
output: >
|
||||
检测到容器异常网络连接
|
||||
(container=%container.name dest=%fd.sip)
|
||||
priority: CRITICAL
|
||||
```
|
||||
|
||||
#### 7.2 告警通知配置
|
||||
|
||||
```python
|
||||
# security_monitor.py
|
||||
import docker
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
class SecurityMonitor:
|
||||
def __init__(self):
|
||||
self.client = docker.from_env()
|
||||
|
||||
def check_container_integrity(self):
|
||||
"""检查容器完整性"""
|
||||
for container in self.client.containers.list():
|
||||
if 'ljwx' in container.name:
|
||||
# 检查容器是否以非root用户运行
|
||||
if container.attrs['Config']['User'] != '1001:1001':
|
||||
self.send_alert(f"容器{container.name}未使用非特权用户运行")
|
||||
|
||||
# 检查只读文件系统
|
||||
if not container.attrs['HostConfig']['ReadonlyRootfs']:
|
||||
self.send_alert(f"容器{container.name}未启用只读文件系统")
|
||||
|
||||
def send_alert(self, message):
|
||||
"""发送安全告警"""
|
||||
webhook_url = "https://your-webhook-url.com"
|
||||
payload = {
|
||||
"alert_type": "security",
|
||||
"message": message,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"severity": "high"
|
||||
}
|
||||
requests.post(webhook_url, json=payload)
|
||||
|
||||
if __name__ == "__main__":
|
||||
monitor = SecurityMonitor()
|
||||
monitor.check_container_integrity()
|
||||
```
|
||||
|
||||
### 8. 部署验证清单
|
||||
|
||||
#### 8.1 构建阶段验证
|
||||
- [ ] 源码已从最终镜像中移除
|
||||
- [ ] JavaScript代码已混淆
|
||||
- [ ] Python代码已编译为字节码
|
||||
- [ ] JAR包已优化和混淆(可选)
|
||||
- [ ] 未包含开发依赖和工具
|
||||
|
||||
#### 8.2 镜像安全验证
|
||||
- [ ] 使用非特权用户(UID 1001)运行
|
||||
- [ ] 启用只读根文件系统
|
||||
- [ ] 移除不必要的Linux能力
|
||||
- [ ] 配置安全选项(no-new-privileges)
|
||||
- [ ] 通过漏洞扫描(Trivy/Snyk)
|
||||
|
||||
#### 8.3 运行时安全验证
|
||||
- [ ] 容器以非root用户运行
|
||||
- [ ] 网络隔离配置正确
|
||||
- [ ] 敏感数据使用Secrets管理
|
||||
- [ ] 启用运行时安全监控
|
||||
- [ ] 日志记录和审计配置
|
||||
|
||||
#### 8.4 存储传输验证
|
||||
- [ ] 镜像存储在私有仓库
|
||||
- [ ] 启用传输加密(HTTPS/TLS)
|
||||
- [ ] 镜像签名验证通过
|
||||
- [ ] 访问控制策略生效
|
||||
- [ ] 定期安全更新机制
|
||||
|
||||
## 安全效果评估
|
||||
|
||||
### 防护级别对比
|
||||
|
||||
| 防护层面 | 原始配置 | 安全配置 | 提升效果 |
|
||||
|---------|---------|---------|----------|
|
||||
| 源码暴露 | 部分暴露 | 完全隐藏 | 🔒🔒🔒🔒🔒 |
|
||||
| 运行权限 | Root用户 | 非特权用户 | 🔒🔒🔒🔒 |
|
||||
| 文件系统 | 可写 | 只读+tmpfs | 🔒🔒🔒🔒 |
|
||||
| 网络访问 | 直接暴露 | 内部网络 | 🔒🔒🔒 |
|
||||
| 镜像验证 | 无 | 数字签名 | 🔒🔒🔒🔒 |
|
||||
|
||||
### 性能影响评估
|
||||
|
||||
| 服务 | 构建时间增加 | 镜像大小变化 | 运行性能影响 |
|
||||
|------|-------------|-------------|-------------|
|
||||
| ljwx-boot | +30% | -15% | <2% |
|
||||
| ljwx-admin | +50% | -20% | <1% |
|
||||
| ljwx-bigscreen | +40% | -25% | <3% |
|
||||
|
||||
## 维护更新策略
|
||||
|
||||
### 1. 定期安全更新
|
||||
```bash
|
||||
# monthly-security-update.sh
|
||||
#!/bin/bash
|
||||
echo "🔄 执行月度安全更新..."
|
||||
|
||||
# 更新基础镜像
|
||||
docker pull eclipse-temurin:21-jre-alpine
|
||||
docker pull python:3.12-alpine
|
||||
docker pull nginx:alpine
|
||||
|
||||
# 重新构建安全镜像
|
||||
./build-secure.sh
|
||||
|
||||
# 执行安全扫描
|
||||
trivy image --severity HIGH,CRITICAL $REGISTRY/ljwx-boot:secure
|
||||
|
||||
echo "✅ 月度安全更新完成"
|
||||
```
|
||||
|
||||
### 2. 漏洞响应流程
|
||||
1. **检测**: 自动扫描发现漏洞
|
||||
2. **评估**: 评估漏洞影响和紧急程度
|
||||
3. **修复**: 更新依赖、重新构建镜像
|
||||
4. **测试**: 在测试环境验证修复效果
|
||||
5. **部署**: 推送到生产环境
|
||||
6. **验证**: 确认安全问题解决
|
||||
|
||||
### 3. 合规审计
|
||||
- **季度**: 全面安全审计
|
||||
- **月度**: 漏洞扫描和更新
|
||||
- **周度**: 运行时安全监控检查
|
||||
- **日常**: 自动化安全监控告警
|
||||
|
||||
## 总结
|
||||
|
||||
本方案通过多层防护策略,显著提升了灵境万象系统Docker镜像的安全性:
|
||||
|
||||
1. **源码保护**: 通过多阶段构建、代码混淆、编译保护等手段,确保源码不会暴露在最终镜像中
|
||||
2. **运行时安全**: 采用非特权用户、只读文件系统、安全选项配置等措施,最小化运行时风险
|
||||
3. **传输存储**: 使用私有仓库、镜像签名、访问控制等技术,保护镜像在传输和存储过程中的安全
|
||||
4. **持续监控**: 建立完善的安全监控和告警机制,及时发现和响应安全威胁
|
||||
|
||||
通过实施此方案,灵境万象系统的Docker镜像安全性将得到全面提升,有效保护知识产权和敏感信息。
|
||||
|
||||
---
|
||||
|
||||
*文档版本: v1.0*
|
||||
*创建时间: 2025-08-31*
|
||||
*适用版本: 灵境万象系统 v1.2.16+*
|
||||
@@ -0,0 +1,375 @@
|
||||
# 灵境万象企业级告警优化可执行实施方案
|
||||
|
||||
## 项目概述
|
||||
|
||||
基于现有LJWX健康管理系统,实施统一告警机制优化,实现手表端(HarmonyOS) → 手机端(Flutter/Android) → 后台(Spring Boot) → 大屏(Flask/BigScreen)的全链路告警处理升级。
|
||||
|
||||
### 核心目标
|
||||
- **统一告警来源**: 整合upload_common_event与alert.generate_alert
|
||||
- **强化规则引擎**: 支持DSL规则配置与智能匹配
|
||||
- **完善生命周期**: 实现升级、审计、SLA监控
|
||||
- **大屏联动**: 强化critical告警大屏弹窗机制
|
||||
- **性能优化**: 实现3,000 ev/s处理能力,P95响应<200ms
|
||||
|
||||
### 预期效果
|
||||
- 告警分发延迟: 200ms → 5ms (97.5%提升)
|
||||
- 并发处理能力: 100/秒 → 1000/秒 (1000%提升)
|
||||
- 误报率: 15-20% → <8% (60%改善)
|
||||
- 平均响应时间: 30分钟 → <15分钟 (50%提升)
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 统一事件模型
|
||||
```json
|
||||
{
|
||||
"source": "watch|server",
|
||||
"customerId": "租户ID",
|
||||
"orgId": "组织ID",
|
||||
"userId": "用户ID",
|
||||
"deviceId": "设备ID",
|
||||
"eventType": "HEALTH_METRIC|SYSTEM|FALL|CUSTOM",
|
||||
"metric": "heartRate|spo2|temperature|bloodPressureSys|bloodPressureDia|custom",
|
||||
"value": 102,
|
||||
"unit": "bpm|%|℃|mmHg",
|
||||
"raw": {"原始字段保留"},
|
||||
"occurAt": "2025-08-31T07:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 规则DSL示例
|
||||
```json
|
||||
{
|
||||
"when": "metric == 'heartRate' && value > 120 for 3m within 5m",
|
||||
"level": "major",
|
||||
"notify": ["wechat", "email"],
|
||||
"throttle": {"suppress": "10m"},
|
||||
"dedup": {"groupBy": ["userId","metric"], "window": "5m"},
|
||||
"autoRecover": {"when": "value < 100 for 5m"},
|
||||
"escalation": {"after": "15m", "toLevel": "critical", "extraNotify": ["message","screen_popup"]}
|
||||
}
|
||||
```
|
||||
|
||||
### 告警状态机
|
||||
```
|
||||
NEW → NOTIFIED → ACKED → RESOLVED
|
||||
│ │ │
|
||||
│ │ └─ ESCALATED (升级)
|
||||
│ └─ ERROR (通知失败)
|
||||
└─ AWAITING_REVIEW (人工审核)
|
||||
```
|
||||
|
||||
## 实施阶段
|
||||
|
||||
### Phase 1: 数据库结构升级 (1-2天)
|
||||
|
||||
#### 1.1 创建迁移脚本
|
||||
- **文件**: `ljwx-boot/db/migration/V2025_08_31__alerts_optimization.sql`
|
||||
- **内容**: 包含t_alert_rules、t_alert_info、t_alert_action_log的结构升级
|
||||
|
||||
#### 1.2 表结构升级要点
|
||||
|
||||
**t_alert_rules 增强**:
|
||||
```sql
|
||||
ALTER TABLE t_alert_rules
|
||||
ADD COLUMN rule_type VARCHAR(32) NOT NULL DEFAULT 'metric',
|
||||
ADD COLUMN metric VARCHAR(64) NULL,
|
||||
ADD COLUMN event_type VARCHAR(64) NULL,
|
||||
ADD COLUMN dsl JSON NOT NULL,
|
||||
ADD COLUMN level VARCHAR(16) NOT NULL DEFAULT 'minor',
|
||||
ADD COLUMN notify JSON NOT NULL,
|
||||
ADD COLUMN is_enabled TINYINT(1) NOT NULL DEFAULT 1;
|
||||
```
|
||||
|
||||
**t_alert_info 增强**:
|
||||
```sql
|
||||
ALTER TABLE t_alert_info
|
||||
ADD COLUMN source VARCHAR(16) NOT NULL DEFAULT 'server',
|
||||
ADD COLUMN customer_id BIGINT NOT NULL,
|
||||
ADD COLUMN org_id BIGINT NULL,
|
||||
ADD COLUMN user_id BIGINT NULL,
|
||||
ADD COLUMN device_id BIGINT NULL,
|
||||
ADD COLUMN level VARCHAR(16) NOT NULL DEFAULT 'minor',
|
||||
ADD COLUMN status VARCHAR(24) NOT NULL DEFAULT 'NEW',
|
||||
ADD COLUMN dedup_key VARCHAR(128) NULL,
|
||||
ADD COLUMN throttle_until DATETIME NULL;
|
||||
```
|
||||
|
||||
#### 1.3 历史数据迁移
|
||||
- 补充customer_id/org_id/user_id/device_id映射
|
||||
- 状态字段标准化迁移
|
||||
- 建立必要索引优化查询性能
|
||||
|
||||
### Phase 2: 标准事件入口 (2-3天)
|
||||
|
||||
#### 2.1 统一事件接入控制器
|
||||
- **文件**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/alerts/controller/EventsIngestController.java`
|
||||
- **功能**:
|
||||
- 事件标准化与校验
|
||||
- 幂等性处理(eventId去重)
|
||||
- Redis Stream/Kafka入队
|
||||
|
||||
#### 2.2 事件标准化服务
|
||||
- **文件**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/alerts/service/EventNormalizer.java`
|
||||
- **功能**:
|
||||
- 手表端/服务端事件统一映射
|
||||
- 数据验证与清洗
|
||||
- 格式标准化处理
|
||||
|
||||
### Phase 3: 规则引擎 (3-4天)
|
||||
|
||||
#### 3.1 规则引擎核心
|
||||
- **模块**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/alerts/rule/`
|
||||
- **组件**:
|
||||
- RuleEngine.java: DSL解析与执行
|
||||
- DeduplicationService.java: 去重逻辑
|
||||
- ThrottleService.java: 抑制机制
|
||||
- EscalationService.java: 升级策略
|
||||
|
||||
#### 3.2 规则匹配策略
|
||||
- 匹配优先级: custom > metric-specific > global fallback
|
||||
- 未匹配规则进入人工审核队列
|
||||
- 支持规则动态开启/关闭
|
||||
|
||||
### Phase 4: 生命周期管理 (2-3天)
|
||||
|
||||
#### 4.1 SLA调度器
|
||||
- **文件**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/alerts/scheduler/AlertSlaScheduler.java`
|
||||
- **功能**:
|
||||
- ACK超时检测与升级
|
||||
- 自恢复条件监控
|
||||
- 失败通知补偿
|
||||
|
||||
#### 4.2 审计日志完善
|
||||
- 所有告警操作记录到t_alert_action_log
|
||||
- 包含操作者、渠道、响应码、错误信息
|
||||
- 支持告警生命周期完整回溯
|
||||
|
||||
### Phase 5: 通知适配器 (3-4天)
|
||||
|
||||
#### 5.1 通知通道统一
|
||||
- **模块**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/alerts/notifier/`
|
||||
- **适配器**:
|
||||
- WeChatNotifier.java
|
||||
- MessageNotifier.java
|
||||
- EmailNotifier.java
|
||||
- WebhookNotifier.java
|
||||
- ScreenPopupNotifier.java
|
||||
|
||||
#### 5.2 重试与失败处理
|
||||
- 指数退避重试机制
|
||||
- 失败原因详细记录
|
||||
- 通知成功率监控
|
||||
|
||||
### Phase 6: 接口与缓存优化 (2-3天)
|
||||
|
||||
#### 6.1 查询接口升级
|
||||
```
|
||||
GET /api/alerts/mine - 个人告警列表
|
||||
GET /api/alerts/search - 高级搜索过滤
|
||||
GET /api/alerts/critical/recent - 大屏告警数据
|
||||
GET /api/alerts/{id} - 告警详情
|
||||
POST /api/alerts/{id}/ack - 确认告警
|
||||
POST /api/alerts/{id}/assign - 指派告警
|
||||
```
|
||||
|
||||
#### 6.2 缓存策略
|
||||
- Redis缓存键设计:
|
||||
- `alert_summary:{customerId}`: 未处理告警统计
|
||||
- `alert_user_timeline:{userId:YYYYMM}`: 用户告警时间线
|
||||
- `alert_detail:{alertId}`: 告警详情缓存
|
||||
- 游标分页替代offset深分页
|
||||
- 缓存失效策略优化
|
||||
|
||||
### Phase 7: 大屏联动升级 (2-3天)
|
||||
|
||||
#### 7.1 WebSocket告警频道
|
||||
- **频道**: `/ws/alerts`
|
||||
- **消息格式**:
|
||||
```json
|
||||
{
|
||||
"alertId": "告警ID",
|
||||
"level": "critical",
|
||||
"title": "心率持续过高",
|
||||
"userName": "用户姓名",
|
||||
"location": {"lon": 113.9, "lat": 22.5},
|
||||
"occurAt": "发生时间",
|
||||
"actions": ["确认","指派","查看轨迹"],
|
||||
"style": "bigscreen_main.html:popup:critical"
|
||||
}
|
||||
```
|
||||
|
||||
#### 7.2 弹窗组件优化
|
||||
- **文件**: `ljwx-bigscreen/bigscreen/templates/components/alert_popup.html`
|
||||
- 支持四级告警样式: info/minor/major/critical
|
||||
- 集成确认、指派、轨迹查看功能
|
||||
|
||||
### Phase 8: 管理界面改造 (2-3天)
|
||||
|
||||
#### 8.1 告警管理页面升级
|
||||
- **文件**: `ljwx-admin/src/views/alerts/alert_view.html`
|
||||
- **新增功能**:
|
||||
- 待审核队列视图
|
||||
- 告警时间线展示
|
||||
- 批量操作支持
|
||||
- 高级过滤搜索
|
||||
|
||||
#### 8.2 规则配置界面
|
||||
- 可视化规则DSL配置
|
||||
- 规则测试与验证
|
||||
- 规则启用/禁用管理
|
||||
|
||||
### Phase 9: 监控与自告警 (1-2天)
|
||||
|
||||
#### 9.1 Prometheus指标暴露
|
||||
```
|
||||
alerts_created_total{level}
|
||||
alerts_notify_success_total{channel}
|
||||
alerts_escalated_total
|
||||
alerts_ack_latency_seconds_bucket
|
||||
alerts_open_gauge{level}
|
||||
```
|
||||
|
||||
#### 9.2 平台自告警
|
||||
- 通知失败率 > 阈值触发自告警
|
||||
- 队列积压深度监控
|
||||
- 系统性能指标告警
|
||||
|
||||
### Phase 10: 测试与验收 (2-3天)
|
||||
|
||||
#### 10.1 单元测试
|
||||
- 规则DSL解析测试
|
||||
- 去重抑制机制测试
|
||||
- 升级策略测试
|
||||
- 自恢复逻辑测试
|
||||
|
||||
#### 10.2 集成测试
|
||||
- 端到端告警流程测试
|
||||
- 多通道通知测试
|
||||
- 大屏联动测试
|
||||
|
||||
#### 10.3 性能测试
|
||||
- 3,000 ev/s压力测试
|
||||
- P95响应时间验证
|
||||
- 并发处理能力测试
|
||||
- 缓存命中率测试
|
||||
|
||||
## 技术实施细节
|
||||
|
||||
### 配置管理
|
||||
- **告警规则配置**: 存储在t_alert_rules表,支持动态更新
|
||||
- **通知渠道配置**: 租户级别独立配置
|
||||
- **SLA参数**: 可配置化升级时间阈值
|
||||
|
||||
### 安全与权限
|
||||
- **租户隔离**: customerId强制过滤
|
||||
- **细粒度权限**: ALERT_READ, ALERT_ACK, ALERT_ASSIGN, ALERT_RULE_ADMIN, ALERT_AUDIT
|
||||
- **操作审计**: 所有管理操作记录到审计日志
|
||||
|
||||
### 容量规划
|
||||
- **存储预估**: 基于告警量与历史数据制定分区策略
|
||||
- **队列长度**: 按峰值处理能力配置缓冲区
|
||||
- **缓存容量**: 按活跃用户数与热点数据评估
|
||||
|
||||
## 风险控制
|
||||
|
||||
### 技术风险
|
||||
- **误报漏报**: 规则灰度发布,开启dry-run模式
|
||||
- **性能影响**: 分阶段发布,实时监控系统指标
|
||||
- **数据一致性**: 以t_alert_info.status为单一事实源
|
||||
|
||||
### 业务风险
|
||||
- **通知成本**: 短信通道限流,优先使用免费通道
|
||||
- **用户体验**: 保持向后兼容,渐进式功能升级
|
||||
- **运维复杂度**: 提供完整运维文档与故障排查指南
|
||||
|
||||
## 质量保证
|
||||
|
||||
### 代码质量
|
||||
- 单元测试覆盖率 > 85%
|
||||
- 代码审查机制
|
||||
- 静态代码分析
|
||||
- 性能基准测试
|
||||
|
||||
### 运维保障
|
||||
- 完整的回滚方案
|
||||
- 灰度发布策略
|
||||
- 监控告警机制
|
||||
- 故障应急预案
|
||||
|
||||
## 项目时间线
|
||||
|
||||
### 总计: 18-24天
|
||||
|
||||
| 阶段 | 任务 | 时间 | 负责模块 |
|
||||
|-----|------|------|----------|
|
||||
| Phase 1 | 数据库结构升级 | 1-2天 | ljwx-boot |
|
||||
| Phase 2 | 标准事件入口 | 2-3天 | ljwx-boot |
|
||||
| Phase 3 | 规则引擎 | 3-4天 | ljwx-boot |
|
||||
| Phase 4 | 生命周期管理 | 2-3天 | ljwx-boot |
|
||||
| Phase 5 | 通知适配器 | 3-4天 | ljwx-boot |
|
||||
| Phase 6 | 接口缓存优化 | 2-3天 | ljwx-boot |
|
||||
| Phase 7 | 大屏联动升级 | 2-3天 | ljwx-bigscreen |
|
||||
| Phase 8 | 管理界面改造 | 2-3天 | ljwx-admin |
|
||||
| Phase 9 | 监控集成 | 1-2天 | 全模块 |
|
||||
| Phase 10 | 测试验收 | 2-3天 | 全模块 |
|
||||
|
||||
## 交付物清单
|
||||
|
||||
### 代码交付物
|
||||
1. **ljwx-boot模块**
|
||||
- 事件接入控制器
|
||||
- 规则引擎服务
|
||||
- 生命周期调度器
|
||||
- 通知适配器
|
||||
- 缓存优化接口
|
||||
|
||||
2. **ljwx-bigscreen模块**
|
||||
- WebSocket告警频道
|
||||
- 弹窗组件升级
|
||||
- 实时告警处理
|
||||
|
||||
3. **ljwx-admin模块**
|
||||
- 告警管理界面
|
||||
- 规则配置界面
|
||||
- 审计日志查看
|
||||
|
||||
### 文档交付物
|
||||
1. API接口文档
|
||||
2. DSL规则配置指南
|
||||
3. 运维部署文档
|
||||
4. 故障排查手册
|
||||
5. 性能测试报告
|
||||
|
||||
### 配置交付物
|
||||
1. 默认告警规则配置
|
||||
2. 通知渠道配置模板
|
||||
3. 监控指标配置
|
||||
4. Docker部署配置
|
||||
|
||||
## 验收标准
|
||||
|
||||
### 功能验收
|
||||
- [ ] 统一事件入口正常工作
|
||||
- [ ] 规则引擎DSL解析正确
|
||||
- [ ] 告警生命周期完整
|
||||
- [ ] 通知多通道发送成功
|
||||
- [ ] 大屏实时弹窗正常
|
||||
- [ ] 管理界面功能完整
|
||||
|
||||
### 性能验收
|
||||
- [ ] 3,000 ev/s处理能力
|
||||
- [ ] P95响应时间 < 200ms
|
||||
- [ ] Critical告警 < 2s到达大屏
|
||||
- [ ] 系统资源占用合理
|
||||
|
||||
### 质量验收
|
||||
- [ ] 单元测试覆盖率 > 85%
|
||||
- [ ] 集成测试通过
|
||||
- [ ] 压力测试通过
|
||||
- [ ] 安全测试通过
|
||||
|
||||
---
|
||||
|
||||
*文档版本: v1.0*
|
||||
*创建时间: 2025-08-31*
|
||||
*更新时间: 2025-08-31*
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="tsx">
|
||||
<script setup lang="ts">
|
||||
import { NButton, NPopconfirm, NUpload, NModal, NCard, NTag, NDescriptions, NDescriptionsItem, NAlert, type UploadFileInfo } from 'naive-ui';
|
||||
import type { Ref } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import { ref, h } from 'vue';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useAuth } from '@/hooks/business/auth';
|
||||
@@ -79,13 +79,11 @@ const { columns, columnChecks, data, loading, getData, getDataByPage, mobilePagi
|
||||
title: '支持许可证',
|
||||
align: 'center',
|
||||
minWidth: 100,
|
||||
render: row => (
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
<span class={row.supportLicense ? 'text-green-600' : 'text-gray-400'}>
|
||||
{row.supportLicense ? '✓ 是' : '✗ 否'}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
render: row => h('div', { class: 'flex items-center justify-center gap-2' }, [
|
||||
h('span', {
|
||||
class: row.supportLicense ? 'text-green-600' : 'text-gray-400'
|
||||
}, row.supportLicense ? '✓ 是' : '✗ 否')
|
||||
])
|
||||
},
|
||||
{
|
||||
key: 'enableResume',
|
||||
@@ -113,32 +111,48 @@ const { columns, columnChecks, data, loading, getData, getDataByPage, mobilePagi
|
||||
align: 'center',
|
||||
width: 280,
|
||||
minWidth: 280,
|
||||
render: row => (
|
||||
<div class="flex-center gap-4px flex-wrap">
|
||||
{hasAuth('t:customer:config:update') && (
|
||||
<NButton type="primary" quaternary size="small" onClick={() => edit(row)}>
|
||||
{$t('common.edit')}
|
||||
</NButton>
|
||||
)}
|
||||
{hasAuth('t:customer:config:license:status') && (
|
||||
<NButton type="info" quaternary size="small" onClick={() => viewLicense(row)}>
|
||||
许可证
|
||||
</NButton>
|
||||
)}
|
||||
{hasAuth('t:customer:config:delete') && (
|
||||
<NPopconfirm onPositiveClick={() => handleDelete(row.id)}>
|
||||
{{
|
||||
default: () => $t('common.confirmDelete'),
|
||||
trigger: () => (
|
||||
<NButton type="error" quaternary size="small">
|
||||
{$t('common.delete')}
|
||||
</NButton>
|
||||
)
|
||||
}}
|
||||
</NPopconfirm>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
render: row => {
|
||||
const buttons = [];
|
||||
|
||||
if (hasAuth('t:customer:config:update')) {
|
||||
buttons.push(
|
||||
h(NButton, {
|
||||
type: 'primary',
|
||||
quaternary: true,
|
||||
size: 'small',
|
||||
onClick: () => edit(row)
|
||||
}, () => $t('common.edit'))
|
||||
);
|
||||
}
|
||||
|
||||
if (hasAuth('t:customer:config:license:status')) {
|
||||
buttons.push(
|
||||
h(NButton, {
|
||||
type: 'info',
|
||||
quaternary: true,
|
||||
size: 'small',
|
||||
onClick: () => viewLicense(row)
|
||||
}, () => '许可证')
|
||||
);
|
||||
}
|
||||
|
||||
if (hasAuth('t:customer:config:delete')) {
|
||||
buttons.push(
|
||||
h(NPopconfirm, {
|
||||
onPositiveClick: () => handleDelete(row.id)
|
||||
}, {
|
||||
default: () => $t('common.confirmDelete'),
|
||||
trigger: () => h(NButton, {
|
||||
type: 'error',
|
||||
quaternary: true,
|
||||
size: 'small'
|
||||
}, () => $t('common.delete'))
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return h('div', { class: 'flex-center gap-4px flex-wrap' }, buttons);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -249,6 +263,39 @@ async function uploadLicense(options: { file: UploadFileInfo }) {
|
||||
|
||||
return false; // 阻止默认上传行为
|
||||
}
|
||||
|
||||
// 辅助函数
|
||||
function getLicenseAlertType(status: string): 'success' | 'info' | 'warning' | 'error' {
|
||||
switch (status) {
|
||||
case 'VALID': return 'success';
|
||||
case 'WARNING': return 'warning';
|
||||
case 'EXPIRED': return 'error';
|
||||
case 'INVALID': return 'error';
|
||||
case 'DISABLED': return 'info';
|
||||
default: return 'error';
|
||||
}
|
||||
}
|
||||
|
||||
function getLicenseStatusText(status: string): string {
|
||||
switch (status) {
|
||||
case 'VALID': return '有效';
|
||||
case 'WARNING': return '即将过期';
|
||||
case 'EXPIRED': return '已过期';
|
||||
case 'INVALID': return '无效';
|
||||
case 'DISABLED': return '未启用';
|
||||
case 'ERROR': return '错误';
|
||||
default: return '未知';
|
||||
}
|
||||
}
|
||||
|
||||
function formatDateTime(dateTime: string | null): string {
|
||||
if (!dateTime) return '-';
|
||||
try {
|
||||
return new Date(dateTime).toLocaleString('zh-CN');
|
||||
} catch {
|
||||
return dateTime;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -373,37 +420,3 @@ async function uploadLicense(options: { file: UploadFileInfo }) {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
// 辅助函数
|
||||
function getLicenseAlertType(status: string): 'success' | 'info' | 'warning' | 'error' {
|
||||
switch (status) {
|
||||
case 'VALID': return 'success';
|
||||
case 'WARNING': return 'warning';
|
||||
case 'EXPIRED': return 'error';
|
||||
case 'INVALID': return 'error';
|
||||
case 'DISABLED': return 'info';
|
||||
default: return 'error';
|
||||
}
|
||||
}
|
||||
|
||||
function getLicenseStatusText(status: string): string {
|
||||
switch (status) {
|
||||
case 'VALID': return '有效';
|
||||
case 'WARNING': return '即将过期';
|
||||
case 'EXPIRED': return '已过期';
|
||||
case 'INVALID': return '无效';
|
||||
case 'DISABLED': return '未启用';
|
||||
case 'ERROR': return '错误';
|
||||
default: return '未知';
|
||||
}
|
||||
}
|
||||
|
||||
function formatDateTime(dateTime: string | null): string {
|
||||
if (!dateTime) return '-';
|
||||
try {
|
||||
return new Date(dateTime).toLocaleString('zh-CN');
|
||||
} catch {
|
||||
return dateTime;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -2,9 +2,11 @@ from flask import jsonify, render_template, request, Response
|
||||
from .models import UserInfo, UserOrg, OrgInfo, DeviceInfo
|
||||
from .redis_helper import RedisHelper
|
||||
from .knowledge_base import KnowledgeBase
|
||||
from .alert_v2_service import get_alerts_by_conditions, acknowledge_alert_by_id, generate_alert_statistics
|
||||
from . import app
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
redis = RedisHelper()
|
||||
kb = KnowledgeBase()
|
||||
@@ -32,6 +34,78 @@ def upload_knowledge():
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
# 告警系统V2 API路由
|
||||
@app.route('/api/v2/alert/realtime', methods=['GET'])
|
||||
def get_realtime_alerts():
|
||||
"""获取实时告警数据"""
|
||||
try:
|
||||
customer_id = request.args.get('customerId')
|
||||
status = request.args.get('status')
|
||||
level = request.args.get('level')
|
||||
|
||||
if not customer_id:
|
||||
return jsonify({"error": "customerId参数是必需的"}), 400
|
||||
|
||||
# 构建查询条件
|
||||
conditions = {"customer_id": customer_id, "is_deleted": 0}
|
||||
if status:
|
||||
conditions["status"] = status
|
||||
if level:
|
||||
conditions["level"] = level
|
||||
|
||||
alerts = get_alerts_by_conditions(conditions, limit=50)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": alerts,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
@app.route('/api/v2/alert/acknowledge', methods=['POST'])
|
||||
def acknowledge_alert_v2():
|
||||
"""确认告警"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
alert_id = data.get('alertId')
|
||||
user_id = data.get('userId')
|
||||
|
||||
if not alert_id:
|
||||
return jsonify({"error": "alertId参数是必需的"}), 400
|
||||
|
||||
success = acknowledge_alert_by_id(alert_id, user_id)
|
||||
|
||||
return jsonify({
|
||||
"success": success,
|
||||
"message": "告警确认成功" if success else "告警确认失败"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
@app.route('/api/v2/alert/statistics', methods=['GET'])
|
||||
def get_alert_statistics_v2():
|
||||
"""获取告警统计数据"""
|
||||
try:
|
||||
customer_id = request.args.get('customerId')
|
||||
start_date = request.args.get('startDate')
|
||||
end_date = request.args.get('endDate')
|
||||
|
||||
if not customer_id:
|
||||
return jsonify({"error": "customerId参数是必需的"}), 400
|
||||
|
||||
stats = generate_alert_statistics(customer_id, start_date, end_date)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": stats
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
@app.route('/api/query_knowledge', methods=['POST'])
|
||||
def query_knowledge():
|
||||
data = request.get_json()
|
||||
|
||||
Reference in New Issue
Block a user