clean
This commit is contained in:
parent
b19f02df93
commit
0215825987
@ -1,11 +0,0 @@
|
||||
FROM python:3.11-alpine
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
RUN pip install --no-cache-dir fastapi uvicorn[standard]
|
||||
RUN apk add --no-cache supervisor curl bash
|
||||
COPY . .
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/
|
||||
EXPOSE 5050 5051
|
||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|
||||
@ -1,29 +0,0 @@
|
||||
# DMS Compliance Tool - Cross-Platform Version
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Windows:
|
||||
1. Run start.bat
|
||||
2. Access web interface
|
||||
3. Use stop.bat to stop
|
||||
|
||||
### Linux/macOS:
|
||||
1. chmod +x *.sh (or run ./set-permissions.sh)
|
||||
2. ./start.sh
|
||||
3. Access web interface
|
||||
4. ./stop.sh to stop
|
||||
|
||||
## Architecture
|
||||
- FastAPI Server: http://localhost:5050
|
||||
- History Viewer: http://localhost:5051
|
||||
- Dual service architecture with supervisor
|
||||
|
||||
## Management Commands
|
||||
Windows: start.bat, stop.bat, logs.bat
|
||||
Linux: start.sh, stop.sh, logs.sh
|
||||
|
||||
## Package Contents
|
||||
- docker-compose.yml: Service configuration (uses pre-built image)
|
||||
- Dockerfile: Container build instructions (for reference)
|
||||
- docker-image.tar: Pre-built Docker image (fast startup)
|
||||
- Cross-platform management scripts (auto-load image)
|
||||
@ -1,17 +0,0 @@
|
||||
services:
|
||||
dms-compliance:
|
||||
image: compliance-dms-windows:latest
|
||||
container_name: dms-compliance-tool
|
||||
ports:
|
||||
- "5050:5050"
|
||||
- "5051:5051"
|
||||
volumes:
|
||||
- ./uploads:/app/uploads
|
||||
- ./logs:/app/logs
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:5050/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,315 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import logging
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
from datetime import timedelta
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from flask import Flask, request, jsonify, send_from_directory, session, redirect, url_for, render_template, g, flash, get_flashed_messages, abort
|
||||
from flask_cors import CORS
|
||||
from functools import wraps
|
||||
import markdown
|
||||
|
||||
# --- PyInstaller Path Helpers ---
|
||||
# For data files that should persist outside the bundle (e.g., database, reports)
|
||||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
||||
# Running in a PyInstaller bundle
|
||||
APP_ROOT = os.path.dirname(sys.executable)
|
||||
else:
|
||||
# Running in a normal Python environment
|
||||
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
template_dir = os.path.join(APP_ROOT, 'templates')
|
||||
static_dir = os.path.join(APP_ROOT, 'static')
|
||||
app = Flask(__name__, static_folder=static_dir, template_folder=template_dir)
|
||||
CORS(app)
|
||||
|
||||
# --- 基本配置 ---
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DATABASE = os.path.join(APP_ROOT, 'users.db')
|
||||
REPORTS_DIR = os.path.join(APP_ROOT, 'test_reports')
|
||||
|
||||
app.config['SECRET_KEY'] = os.urandom(24)
|
||||
app.config['DATABASE'] = DATABASE
|
||||
app.config['REPORTS_DIR'] = REPORTS_DIR
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
|
||||
|
||||
os.makedirs(app.config['REPORTS_DIR'], exist_ok=True)
|
||||
|
||||
# --- 数据库 Schema 和辅助函数 (与 flask_app.py 相同) ---
|
||||
DB_SCHEMA = '''
|
||||
DROP TABLE IF EXISTS user;
|
||||
CREATE TABLE user (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
password_hash TEXT NOT NULL
|
||||
);
|
||||
'''
|
||||
|
||||
def get_db():
|
||||
db = getattr(g, '_database', None)
|
||||
if db is None:
|
||||
db = g._database = sqlite3.connect(app.config['DATABASE'])
|
||||
db.row_factory = sqlite3.Row
|
||||
return db
|
||||
|
||||
@app.teardown_appcontext
|
||||
def close_connection(exception):
|
||||
db = getattr(g, '_database', None)
|
||||
if db is not None:
|
||||
db.close()
|
||||
|
||||
def init_db(force_create=False):
|
||||
if force_create or not os.path.exists(app.config['DATABASE']):
|
||||
with app.app_context():
|
||||
db = get_db()
|
||||
db.cursor().executescript(DB_SCHEMA)
|
||||
db.commit()
|
||||
logger.info("数据库已初始化!")
|
||||
create_default_user()
|
||||
else:
|
||||
logger.info("数据库已存在。")
|
||||
|
||||
def create_default_user(username="admin", password="7#Xq9$Lm*2!Pw@5"):
|
||||
with app.app_context():
|
||||
db = get_db()
|
||||
user = db.execute('SELECT * FROM user WHERE username = ?', (username,)).fetchone()
|
||||
if user is None:
|
||||
db.execute("INSERT INTO user (username, password_hash) VALUES (?, ?)", (username, generate_password_hash(password)))
|
||||
db.commit()
|
||||
logger.info(f"已创建默认用户: {username}")
|
||||
else:
|
||||
logger.info(f"默认用户 {username} 已存在。")
|
||||
|
||||
@app.cli.command('init-db')
|
||||
def init_db_command():
|
||||
init_db(force_create=True)
|
||||
print("已初始化数据库。")
|
||||
|
||||
# --- 用户认证 (与 flask_app.py 相同) ---
|
||||
@app.route('/login', methods=('GET', 'POST'))
|
||||
def login():
|
||||
if g.user:
|
||||
return redirect(url_for('list_history'))
|
||||
if request.method == 'POST':
|
||||
username = request.form['username']
|
||||
password = request.form['password']
|
||||
db = get_db()
|
||||
error = None
|
||||
user = db.execute('SELECT * FROM user WHERE username = ?', (username,)).fetchone()
|
||||
if user is None:
|
||||
error = '用户名不存在。'
|
||||
elif not check_password_hash(user['password_hash'], password):
|
||||
error = '密码错误。'
|
||||
if error is None:
|
||||
session.clear()
|
||||
session['user_id'] = user['id']
|
||||
session['username'] = user['username']
|
||||
session.permanent = True
|
||||
return redirect(url_for('list_history'))
|
||||
flash(error)
|
||||
return render_template('login.html')
|
||||
|
||||
@app.route('/logout')
|
||||
def logout():
|
||||
session.clear()
|
||||
flash('您已成功登出。')
|
||||
return redirect(url_for('login'))
|
||||
|
||||
def login_required(view):
|
||||
@wraps(view)
|
||||
def wrapped_view(**kwargs):
|
||||
# if g.user is None:
|
||||
# return redirect(url_for('login'))
|
||||
return view(**kwargs)
|
||||
return wrapped_view
|
||||
|
||||
@app.before_request
|
||||
def load_logged_in_user():
|
||||
user_id = session.get('user_id')
|
||||
if user_id is None:
|
||||
g.user = None
|
||||
else:
|
||||
g.user = get_db().execute('SELECT * FROM user WHERE id = ?', (user_id,)).fetchone()
|
||||
|
||||
# --- LLM配置视图 ---
|
||||
CRITERIA_FILE_PATH = os.path.join(APP_ROOT, 'custom_testcases', 'llm', 'compliance_criteria.json')
|
||||
|
||||
@app.route('/llm-config', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def llm_config():
|
||||
criteria_for_template = []
|
||||
file_exists = os.path.exists(CRITERIA_FILE_PATH)
|
||||
|
||||
if request.method == 'POST':
|
||||
# 从表单获取所有名为'criteria'的输入项,作为一个列表
|
||||
criteria_list = request.form.getlist('criteria')
|
||||
# 过滤掉用户可能提交的空规则
|
||||
criteria_list = [item.strip() for item in criteria_list if item.strip()]
|
||||
|
||||
try:
|
||||
# 将规则列表格式化为美观的JSON并保存
|
||||
pretty_content = json.dumps(criteria_list, indent=2, ensure_ascii=False)
|
||||
with open(CRITERIA_FILE_PATH, 'w', encoding='utf-8') as f:
|
||||
f.write(pretty_content)
|
||||
flash('LLM合规性标准已成功保存!', 'success')
|
||||
except Exception as e:
|
||||
flash(f'保存文件时发生未知错误: {e}', 'error')
|
||||
|
||||
# 无论是GET还是POST请求后,都重新从文件中读取最新的规则列表用于显示
|
||||
if file_exists:
|
||||
try:
|
||||
with open(CRITERIA_FILE_PATH, 'r', encoding='utf-8') as f:
|
||||
criteria_for_template = json.load(f)
|
||||
# 确保文件内容确实是一个列表
|
||||
if not isinstance(criteria_for_template, list):
|
||||
flash('配置文件格式错误:内容应为JSON数组。已重置为空列表。', 'error')
|
||||
criteria_for_template = []
|
||||
except Exception as e:
|
||||
flash(f'读取配置文件时出错: {e}', 'error')
|
||||
criteria_for_template = []
|
||||
|
||||
# 准备一个用于页面展示的示例API信息
|
||||
example_api_info = {
|
||||
"path_template": "/api/dms/instance/v1/message/push/myschema/1.0",
|
||||
"method": "POST",
|
||||
"title": "数据推送接口",
|
||||
"description": "用于向系统推送标准格式的数据。",
|
||||
"schema_request_body": {"...": "... (此处为请求体Schema定义)"},
|
||||
"instance_url": "http://example.com/api/dms/instance/v1/message/push/myschema/1.0",
|
||||
"instance_request_headers": {"X-Tenant-ID": "tenant-001", "...": "..."},
|
||||
"instance_request_body": {"id": "123", "data": "example"},
|
||||
"instance_response_status": 200,
|
||||
"instance_response_body": {"code": 0, "message": "success", "data": True}
|
||||
}
|
||||
|
||||
return render_template('llm_config.html', criteria=criteria_for_template, file_exists=file_exists, example_api_info=json.dumps(example_api_info, indent=2, ensure_ascii=False))
|
||||
|
||||
# --- 文件下载路由 ---
|
||||
@app.route('/download/<path:run_id>/<path:filename>')
|
||||
@login_required
|
||||
def download_report(run_id, filename):
|
||||
"""安全地提供指定运行记录中的报告文件下载。"""
|
||||
# 清理输入,防止目录遍历攻击
|
||||
run_id_safe = Path(run_id).name
|
||||
filename_safe = Path(filename).name
|
||||
|
||||
reports_dir = Path(app.config['REPORTS_DIR']).resolve()
|
||||
run_dir = (reports_dir / run_id_safe).resolve()
|
||||
|
||||
# 安全检查:确保请求的目录是REPORTS_DIR的子目录
|
||||
if not run_dir.is_dir() or run_dir.parent != reports_dir:
|
||||
abort(404, "找不到指定的测试记录或权限不足。")
|
||||
|
||||
return send_from_directory(run_dir, filename_safe, as_attachment=True)
|
||||
|
||||
# --- 新增:PDF文件预览路由 ---
|
||||
@app.route('/view_pdf/<path:run_id>')
|
||||
@login_required
|
||||
def view_pdf_report(run_id):
|
||||
"""安全地提供PDF报告文件以内联方式查看。"""
|
||||
run_id_safe = Path(run_id).name
|
||||
filename_safe = "report_cn.pdf"
|
||||
|
||||
reports_dir = Path(app.config['REPORTS_DIR']).resolve()
|
||||
run_dir = (reports_dir / run_id_safe).resolve()
|
||||
|
||||
# 安全检查
|
||||
if not run_dir.is_dir() or run_dir.parent != reports_dir:
|
||||
abort(404, "找不到指定的测试记录或权限不足。")
|
||||
|
||||
pdf_path = run_dir / filename_safe
|
||||
if not pdf_path.exists():
|
||||
abort(404, "未找到PDF报告文件。")
|
||||
|
||||
return send_from_directory(run_dir, filename_safe)
|
||||
|
||||
# --- 历史记录视图 ---
|
||||
@app.route('/')
|
||||
@login_required
|
||||
def list_history():
|
||||
history = []
|
||||
reports_path = Path(app.config['REPORTS_DIR'])
|
||||
if not reports_path.is_dir():
|
||||
flash('报告目录不存在。')
|
||||
return render_template('history.html', history=[])
|
||||
|
||||
# 获取所有子目录(即测试运行记录)
|
||||
run_dirs = [d for d in reports_path.iterdir() if d.is_dir()]
|
||||
# 按名称(时间戳)降序排序
|
||||
run_dirs.sort(key=lambda x: x.name, reverse=True)
|
||||
|
||||
for run_dir in run_dirs:
|
||||
summary_path = run_dir / 'summary.json'
|
||||
details_path = run_dir / 'api_call_details.md'
|
||||
run_info = {'id': run_dir.name, 'summary': None, 'has_details': details_path.exists()}
|
||||
|
||||
if summary_path.exists():
|
||||
try:
|
||||
with open(summary_path, 'r', encoding='utf-8') as f:
|
||||
summary_data = json.load(f)
|
||||
run_info['summary'] = summary_data
|
||||
except (json.JSONDecodeError, IOError) as e:
|
||||
logger.error(f"无法读取或解析摘要文件 {summary_path}: {e}")
|
||||
run_info['summary'] = {'error': '无法加载摘要'}
|
||||
|
||||
history.append(run_info)
|
||||
|
||||
return render_template('history.html', history=history)
|
||||
|
||||
@app.route('/details/<run_id>')
|
||||
@login_required
|
||||
def show_details(run_id):
|
||||
run_id = Path(run_id).name # Sanitize input
|
||||
run_dir = Path(app.config['REPORTS_DIR']) / run_id
|
||||
|
||||
if not run_dir.is_dir():
|
||||
return "找不到指定的测试记录。", 404
|
||||
|
||||
summary_path = run_dir / 'summary.json'
|
||||
details_path = run_dir / 'api_call_details.md'
|
||||
pdf_path = run_dir / 'report_cn.pdf' # 新增PDF路径
|
||||
|
||||
summary_content = "{}"
|
||||
details_content = "### 未找到API调用详情报告"
|
||||
|
||||
has_pdf_report = pdf_path.exists() # 检查PDF是否存在
|
||||
has_md_report = details_path.exists() # 检查MD报告是否存在
|
||||
|
||||
if summary_path.exists():
|
||||
try:
|
||||
with open(summary_path, 'r', encoding='utf-8') as f:
|
||||
summary_data = json.load(f)
|
||||
summary_content = json.dumps(summary_data, indent=2, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
summary_content = f"加载摘要文件出错: {e}"
|
||||
|
||||
if has_md_report:
|
||||
try:
|
||||
with open(details_path, 'r', encoding='utf-8') as f:
|
||||
# 将Markdown转换为HTML
|
||||
details_content = markdown.markdown(f.read(), extensions=['fenced_code', 'tables', 'def_list', 'attr_list'])
|
||||
except Exception as e:
|
||||
details_content = f"加载详情文件出错: {e}"
|
||||
|
||||
return render_template('history_detail.html',
|
||||
run_id=run_id,
|
||||
summary_content=summary_content,
|
||||
details_content=details_content,
|
||||
has_pdf_report=has_pdf_report,
|
||||
has_md_report=has_md_report)
|
||||
|
||||
|
||||
# --- 根路径重定向 ---
|
||||
@app.route('/index')
|
||||
def index_redirect():
|
||||
return redirect(url_for('list_history'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 首次运行时确保数据库和用户存在
|
||||
init_db()
|
||||
# 使用5051端口避免与api_server.py冲突
|
||||
app.run(debug=True, host='0.0.0.0', port=5051)
|
||||
@ -1,22 +0,0 @@
|
||||
pydantic>=2.0.0,<3.0.0
|
||||
PyYAML>=6.0,<7.0
|
||||
jsonschema>=4.0.0,<5.0.0
|
||||
requests>=2.20.0,<3.0.0
|
||||
flask>=2.0.0,<3.0.0 # 用于模拟服务器
|
||||
numpy>=1.20.0,<2.0.0 # 用于数值计算
|
||||
|
||||
# 用于 OpenAPI/Swagger 解析 (可选, 如果输入解析器需要)
|
||||
openapi-spec-validator>=0.5.0,<0.6.0
|
||||
prance[osv]>=23.0.0,<24.0.0
|
||||
|
||||
# 用于 API Linting (可选, 如果规则库需要集成 Spectral-like 功能)
|
||||
# pyaml-env>=1.0.0,<2.0.0 # 如果 linting 规则是 yaml 且用到了环境变量
|
||||
|
||||
# 测试框架 (可选, 推荐)
|
||||
# pytest>=7.0.0,<8.0.0
|
||||
# pytest-cov>=4.0.0,<5.0.0
|
||||
# httpx>=0.20.0,<0.28.0 # for testing API calls
|
||||
|
||||
Flask-Cors>=3.0
|
||||
markdown
|
||||
reportlab>=3.6.0 # For PDF report generation
|
||||
@ -1,3 +0,0 @@
|
||||
#/bin/bash
|
||||
chmod +x *.sh
|
||||
echo "Permissions set for shell scripts"
|
||||
@ -1,10 +0,0 @@
|
||||
@echo off
|
||||
echo Starting DMS Compliance Tool...
|
||||
echo Loading pre-built Docker image...
|
||||
docker load -i docker-image.tar
|
||||
echo Starting services...
|
||||
docker compose up -d
|
||||
echo Services started
|
||||
echo FastAPI Server: http://localhost:5050
|
||||
echo History Viewer: http://localhost:5051
|
||||
pause
|
||||
@ -1,10 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
echo "Starting DMS Compliance Tool..."
|
||||
echo "Loading pre-built Docker image..."
|
||||
docker load -i docker-image.tar
|
||||
echo "Starting services..."
|
||||
docker compose up -d
|
||||
echo "Services started"
|
||||
echo "FastAPI Server: http://localhost:5050"
|
||||
echo "History Viewer: http://localhost:5051"
|
||||
@ -1,4 +0,0 @@
|
||||
@echo off
|
||||
docker compose down
|
||||
echo Services stopped.
|
||||
pause
|
||||
@ -1,5 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
echo "Stopping DMS Compliance Tool..."
|
||||
docker compose down
|
||||
echo "Services stopped."
|
||||
@ -1,20 +0,0 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/var/log/supervisor/supervisord.log
|
||||
user=root
|
||||
|
||||
[program:api_server]
|
||||
command=python -m uvicorn fastapi_server:app --host 0.0.0.0 --port 5050
|
||||
directory=/app
|
||||
autostart=true
|
||||
autorestart=true
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/log/supervisor/api_server.log
|
||||
|
||||
[program:history_viewer]
|
||||
command=python history_viewer.py
|
||||
directory=/app
|
||||
autostart=true
|
||||
autorestart=true
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/log/supervisor/history_viewer.log
|
||||
@ -1,139 +0,0 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
echo === Fix Existing FastAPI Package ===
|
||||
echo This script fixes the missing assets directory issue in existing packages
|
||||
echo.
|
||||
|
||||
REM Find the most recent package directory
|
||||
for /f "delims=" %%i in ('dir /b /ad /o-d dms-compliance-fastapi-amd64-windows-* 2^>nul') do (
|
||||
set "PACKAGE_DIR=%%i"
|
||||
goto :found
|
||||
)
|
||||
|
||||
echo [ERROR] No package directory found matching pattern: dms-compliance-fastapi-amd64-windows-*
|
||||
echo Please make sure you have a generated package directory.
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:found
|
||||
echo [INFO] Found package directory: %PACKAGE_DIR%
|
||||
echo.
|
||||
|
||||
REM Check if assets directory exists in current location
|
||||
if not exist "assets" (
|
||||
echo [ERROR] Assets directory not found in current location
|
||||
echo Please run this script from the same directory where you ran the build script
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [INFO] Assets directory found, proceeding with fix...
|
||||
echo.
|
||||
|
||||
REM Stop any running containers
|
||||
echo [INFO] Stopping any running containers...
|
||||
cd /d "%PACKAGE_DIR%"
|
||||
docker compose down >nul 2>&1
|
||||
cd /d ".."
|
||||
|
||||
REM Load the existing image to check if it exists
|
||||
echo [INFO] Checking existing Docker image...
|
||||
cd /d "%PACKAGE_DIR%"
|
||||
if exist "docker-image.tar" (
|
||||
docker load -i docker-image.tar >nul 2>&1
|
||||
echo [INFO] Existing image loaded
|
||||
) else (
|
||||
echo [WARNING] No docker-image.tar found
|
||||
)
|
||||
cd /d ".."
|
||||
|
||||
REM Create a new build directory with assets
|
||||
echo [INFO] Creating fixed build directory...
|
||||
set "FIX_DIR=%PACKAGE_DIR%-fixed"
|
||||
if exist "%FIX_DIR%" rmdir /s /q "%FIX_DIR%"
|
||||
mkdir "%FIX_DIR%"
|
||||
|
||||
REM Copy everything from the original package
|
||||
echo [INFO] Copying original package files...
|
||||
robocopy "%PACKAGE_DIR%" "%FIX_DIR%" /E /XF docker-image.tar >nul 2>&1
|
||||
|
||||
REM Copy the assets directory
|
||||
echo [INFO] Adding missing assets directory...
|
||||
robocopy "assets" "%FIX_DIR%\assets" /E >nul 2>&1
|
||||
|
||||
REM Copy other required files that might be missing
|
||||
if exist "ddms_compliance_suite" robocopy "ddms_compliance_suite" "%FIX_DIR%\ddms_compliance_suite" /E /XD __pycache__ /XF *.pyc >nul 2>&1
|
||||
if exist "custom_stages" robocopy "custom_stages" "%FIX_DIR%\custom_stages" /E /XD __pycache__ /XF *.pyc >nul 2>&1
|
||||
if exist "custom_testcases" robocopy "custom_testcases" "%FIX_DIR%\custom_testcases" /E /XD __pycache__ /XF *.pyc >nul 2>&1
|
||||
|
||||
REM Rebuild the Docker image
|
||||
echo [INFO] Rebuilding Docker image with assets...
|
||||
cd /d "%FIX_DIR%"
|
||||
|
||||
REM Check if Dockerfile exists
|
||||
if not exist "Dockerfile" (
|
||||
echo [ERROR] Dockerfile not found in package directory
|
||||
cd /d ".."
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [INFO] Building fixed Docker image...
|
||||
set DOCKER_SCOUT_NO_ANALYTICS=true
|
||||
set DOCKER_BUILDX_NO_DEFAULT_ATTESTATIONS=true
|
||||
|
||||
docker build -t compliance-dms-windows:latest . 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Docker build failed
|
||||
cd /d ".."
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [SUCCESS] Docker image rebuilt successfully!
|
||||
|
||||
REM Save the new image
|
||||
echo [INFO] Saving fixed Docker image...
|
||||
docker save compliance-dms-windows:latest -o docker-image.tar
|
||||
|
||||
REM Test the fixed image
|
||||
echo [INFO] Testing the fixed image...
|
||||
docker run --rm -d -p 5052:5050 --name test-fixed-container compliance-dms-windows:latest
|
||||
timeout /t 10 /nobreak >nul
|
||||
|
||||
REM Check if container is running and test the API
|
||||
docker ps | findstr test-fixed-container >nul
|
||||
if errorlevel 1 (
|
||||
echo [WARNING] Test container failed to start
|
||||
) else (
|
||||
echo [SUCCESS] Test container is running
|
||||
|
||||
REM Test if assets are accessible
|
||||
docker exec test-fixed-container ls -la /app/assets/doc/dms/ >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [WARNING] Assets directory not found in container
|
||||
) else (
|
||||
echo [SUCCESS] Assets directory found in container
|
||||
docker exec test-fixed-container cat /app/assets/doc/dms/domain.json | head -5
|
||||
)
|
||||
)
|
||||
|
||||
REM Clean up test container
|
||||
docker stop test-fixed-container >nul 2>&1
|
||||
docker rm test-fixed-container >nul 2>&1
|
||||
|
||||
cd /d ".."
|
||||
|
||||
echo.
|
||||
echo === Fix Complete ===
|
||||
echo [SUCCESS] Fixed package created: %FIX_DIR%
|
||||
echo.
|
||||
echo To use the fixed package:
|
||||
echo 1. cd %FIX_DIR%
|
||||
echo 2. start.bat
|
||||
echo 3. Test with: curl -X POST http://localhost:5050/run -H "Content-Type: application/json" -d "{\"mode\":\"dms\",\"base_url\":\"http://127.0.0.1:5001\"}"
|
||||
echo.
|
||||
echo The fixed package should now be able to find the assets/doc/dms/domain.json file.
|
||||
echo.
|
||||
pause
|
||||
@ -1,101 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 修复脚本行结束符问题
|
||||
# 将Windows格式的CRLF转换为Unix格式的LF
|
||||
|
||||
echo "=== 修复脚本行结束符工具 ==="
|
||||
echo ""
|
||||
|
||||
# 检查是否有dos2unix命令
|
||||
if command -v dos2unix &> /dev/null; then
|
||||
echo "[信息] 使用dos2unix工具修复行结束符"
|
||||
|
||||
# 修复原始脚本
|
||||
if [[ -f "create-compose-package-multiplatform.sh" ]]; then
|
||||
echo "[信息] 修复 create-compose-package-multiplatform.sh"
|
||||
dos2unix create-compose-package-multiplatform.sh
|
||||
chmod +x create-compose-package-multiplatform.sh
|
||||
fi
|
||||
|
||||
# 修复WSL版本脚本
|
||||
if [[ -f "create-compose-package-wsl.sh" ]]; then
|
||||
echo "[信息] 修复 create-compose-package-wsl.sh"
|
||||
dos2unix create-compose-package-wsl.sh
|
||||
chmod +x create-compose-package-wsl.sh
|
||||
fi
|
||||
|
||||
elif command -v sed &> /dev/null; then
|
||||
echo "[信息] 使用sed工具修复行结束符"
|
||||
|
||||
# 使用sed移除\r字符
|
||||
if [[ -f "create-compose-package-multiplatform.sh" ]]; then
|
||||
echo "[信息] 修复 create-compose-package-multiplatform.sh"
|
||||
sed -i 's/\r$//' create-compose-package-multiplatform.sh
|
||||
chmod +x create-compose-package-multiplatform.sh
|
||||
fi
|
||||
|
||||
if [[ -f "create-compose-package-wsl.sh" ]]; then
|
||||
echo "[信息] 修复 create-compose-package-wsl.sh"
|
||||
sed -i 's/\r$//' create-compose-package-wsl.sh
|
||||
chmod +x create-compose-package-wsl.sh
|
||||
fi
|
||||
|
||||
elif command -v tr &> /dev/null; then
|
||||
echo "[信息] 使用tr工具修复行结束符"
|
||||
|
||||
# 使用tr删除\r字符
|
||||
if [[ -f "create-compose-package-multiplatform.sh" ]]; then
|
||||
echo "[信息] 修复 create-compose-package-multiplatform.sh"
|
||||
tr -d '\r' < create-compose-package-multiplatform.sh > temp_file && mv temp_file create-compose-package-multiplatform.sh
|
||||
chmod +x create-compose-package-multiplatform.sh
|
||||
fi
|
||||
|
||||
if [[ -f "create-compose-package-wsl.sh" ]]; then
|
||||
echo "[信息] 修复 create-compose-package-wsl.sh"
|
||||
tr -d '\r' < create-compose-package-wsl.sh > temp_file && mv temp_file create-compose-package-wsl.sh
|
||||
chmod +x create-compose-package-wsl.sh
|
||||
fi
|
||||
|
||||
else
|
||||
echo "[警告] 未找到合适的工具来修复行结束符"
|
||||
echo "[提示] 请安装 dos2unix 工具: sudo apt-get install dos2unix"
|
||||
echo ""
|
||||
echo "或者手动运行以下命令:"
|
||||
echo "sed -i 's/\r$//' create-compose-package-multiplatform.sh"
|
||||
echo "sed -i 's/\r$//' create-compose-package-wsl.sh"
|
||||
echo "chmod +x *.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[成功] 行结束符修复完成"
|
||||
echo ""
|
||||
echo "现在可以运行以下脚本:"
|
||||
echo "- ./create-compose-package-multiplatform.sh (原始多平台版本)"
|
||||
echo "- ./create-compose-package-wsl.sh (WSL优化版本)"
|
||||
echo "- create-compose-package-windows.bat (Windows批处理版本)"
|
||||
echo ""
|
||||
|
||||
# 验证脚本是否可执行
|
||||
echo "=== 验证脚本 ==="
|
||||
for script in create-compose-package-multiplatform.sh create-compose-package-wsl.sh; do
|
||||
if [[ -f "$script" ]]; then
|
||||
if [[ -x "$script" ]]; then
|
||||
echo "[✓] $script 可执行"
|
||||
else
|
||||
echo "[✗] $script 不可执行"
|
||||
chmod +x "$script"
|
||||
echo "[修复] 已设置 $script 为可执行"
|
||||
fi
|
||||
|
||||
# 检查是否还有\r字符
|
||||
if grep -q $'\r' "$script" 2>/dev/null; then
|
||||
echo "[警告] $script 仍包含Windows行结束符"
|
||||
else
|
||||
echo "[✓] $script 行结束符正常"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "修复完成!"
|
||||
11
run-demo.sh
11
run-demo.sh
@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 自动运行演示脚本
|
||||
echo "=== 自动运行WSL演示脚本 ==="
|
||||
|
||||
# 使用expect或者直接传递输入
|
||||
{
|
||||
echo "1" # 选择FastAPI
|
||||
echo "0" # 自动检测平台
|
||||
echo "y" # 确认构建
|
||||
} | bash demo-wsl-script.sh
|
||||
Loading…
x
Reference in New Issue
Block a user