diff --git a/.gitignore b/.gitignore index f1636d89..dcd008da 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,5 @@ mvnw /react-ui/docs /react-ui/types/tsconfig.tsbuildinfo /react-ui/storybook-static -/react-ui/.storybook/scripts /react-ui/dist.zip /react-ui/@alita/* diff --git a/react-ui/.storybook/scripts/build-image-deploy-tui.sh b/react-ui/.storybook/scripts/build-image-deploy-tui.sh new file mode 100755 index 00000000..36d29a0f --- /dev/null +++ b/react-ui/.storybook/scripts/build-image-deploy-tui.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +set -e + +# 配置项(可根据你实际情况修改) +SERVER_USER=root +SERVER_IP=172.20.32.197 +CONTAINER_NAME=storybook +PORT=6007 +IMAGE_NAME=storybook-app +IMAGE_TAG=latest +TAR_FILE=${IMAGE_NAME}.tar.gz + +function banner() { +cat << "EOF" +╭────────────────────────────╮ +│ 🚀 Storybook 部署助手 │ +╰────────────────────────────╯ +EOF +} + +function build_storybook() { + echo "🛠️ 构建 Storybook..." + npm run build-storybook || { echo "❌ 构建失败"; return 1; } + + echo "📄 拷贝 docs 到构建目录..." + mkdir -p storybook-static/docs + cp -r ../docs/* storybook-static/docs/ 2>/dev/null || true +} + +function build_and_export_image() { + echo "🐳 构建镜像(linux/amd64)..." + docker buildx build --platform linux/amd64 -t ${IMAGE_NAME}:${IMAGE_TAG} --load . + + echo "📦 导出镜像..." + docker save ${IMAGE_NAME}:${IMAGE_TAG} | gzip > ${TAR_FILE} +} + +function upload_and_deploy() { + echo "📤 上传镜像..." + scp ${TAR_FILE} ${SERVER_USER}@${SERVER_IP}:~/ + + echo "🚀 部署到服务器 ${SERVER_IP}..." + ssh ${SERVER_USER}@${SERVER_IP} << EOF + docker stop ${CONTAINER_NAME} 2>/dev/null || true + docker rm ${CONTAINER_NAME} 2>/dev/null || true + gunzip -c ${TAR_FILE} | docker load + docker run -d --name ${CONTAINER_NAME} -p ${PORT}:80 ${IMAGE_NAME}:${IMAGE_TAG} +EOF + + echo "🎉 成功部署!访问地址:http://${SERVER_IP}:${PORT}" +} + +function all_in_one() { + build_storybook + build_and_export_image + upload_and_deploy +} + +function menu() { + banner + echo "请选择操作:" + select opt in "构建 Storybook" "构建并导出镜像" "上传并部署镜像" "一键完成全部流程(推荐)" "退出"; do + case $REPLY in + 1) build_storybook ;; + 2) build_and_export_image ;; + 3) upload_and_deploy ;; + 4) all_in_one ;; + 5) echo "👋 再见!"; break ;; + *) echo "❗ 无效选项,请重新输入。" ;; + esac + echo "" + banner + echo "请选择操作:" + done +} + +menu \ No newline at end of file diff --git a/react-ui/.storybook/scripts/build-image-deploy.sh b/react-ui/.storybook/scripts/build-image-deploy.sh new file mode 100644 index 00000000..3e47de97 --- /dev/null +++ b/react-ui/.storybook/scripts/build-image-deploy.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -e + +# === 配置项 === +SERVER_USER=root # 服务器用户名 +SERVER_IP=172.20.32.197 # 服务器 IP +CONTAINER_NAME=storybook-app +PORT=6007 # 修改端口以避开已用的 6006 +IMAGE_NAME=storybook-app +IMAGE_TAG=latest +TAR_FILE=${IMAGE_NAME}.tar.gz + +start_time=$(date +%s) + +# === 出错时提示音 === +function on_error { + echo "❌ 脚本执行失败!" + if command -v afplay &>/dev/null; then + afplay /System/Library/Sounds/Funk.aiff + elif command -v paplay &>/dev/null; then + paplay /usr/share/sounds/freedesktop/stereo/dialog-error.oga + fi + exit 1 +} +trap on_error ERR + +# === Step 1: 构建 TypeDoc === +echo "📚 1. 构建本地 TypeDoc..." +npm run docs + +# === Step 2: 构建 Storybook === +echo "🛠️ 构建 Storybook..." +npm run build-storybook + +# === Step 3: 使用 buildx 构建 amd64 镜像 === +echo "🐳 构建 Docker 镜像(平台 linux/amd64)..." +docker buildx build \ + --platform linux/amd64 \ + -t ${IMAGE_NAME}:${IMAGE_TAG} \ + --load . + +# === Step 4: 导出镜像为 tar.gz === +echo "📦 导出并压缩镜像..." +docker save ${IMAGE_NAME}:${IMAGE_TAG} | gzip > ${TAR_FILE} + +# === Step 5: 上传压缩包到服务器 === +echo "📤 上传压缩包到服务器 ${SERVER_IP}..." +scp ${TAR_FILE} ${SERVER_USER}@${SERVER_IP}:~/ + +# === Step 6: SSH 远程部署容器 === +echo "🚀 登录服务器并部署容器..." +ssh ${SERVER_USER}@${SERVER_IP} << EOF + docker stop ${CONTAINER_NAME} 2>/dev/null || true + docker rm ${CONTAINER_NAME} 2>/dev/null || true + gunzip -c ${TAR_FILE} | docker load + docker run -d --name ${CONTAINER_NAME} -p ${PORT}:80 ${IMAGE_NAME}:${IMAGE_TAG} +EOF + +end_time=$(date +%s) +duration=$((end_time - start_time)) + +echo "✅ 部署完成,耗时 ${duration} 秒!访问地址:http://${SERVER_IP}:${PORT}" + +# === 成功提示音 === +if command -v afplay &>/dev/null; then + afplay /System/Library/Sounds/Glass.aiff +elif command -v paplay &>/dev/null; then + paplay /usr/share/sounds/freedesktop/stereo/complete.oga +fi \ No newline at end of file diff --git a/react-ui/.storybook/scripts/tui-deploy-gum.sh b/react-ui/.storybook/scripts/tui-deploy-gum.sh new file mode 100644 index 00000000..2bf5afca --- /dev/null +++ b/react-ui/.storybook/scripts/tui-deploy-gum.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +set -e + +# 配置项 +SERVER_USER=your-user +SERVER_IP=172.20.32.197 +CONTAINER_NAME=storybook +PORT=6007 +IMAGE_NAME=storybook-app +IMAGE_TAG=latest +TAR_FILE=${IMAGE_NAME}.tar.gz + +# 使用 gum 显示标题 +function banner() { + gum style --foreground 202 "🚀 Storybook 部署助手" +} + +# 构建 Storybook +function build_storybook() { + gum style "🛠️ 构建 Storybook..." + npm run build-storybook || { gum style "❌ 构建失败"; return 1; } + gum style "📄 拷贝 docs 到构建目录..." + mkdir -p storybook-static/docs + cp -r ../docs/* storybook-static/docs/ 2>/dev/null || true +} + +# 构建并导出镜像 +function build_and_export_image() { + gum style "🐳 构建镜像(linux/amd64)..." + docker buildx build --platform linux/amd64 -t ${IMAGE_NAME}:${IMAGE_TAG} --load . + + gum style "📦 导出镜像..." + docker save ${IMAGE_NAME}:${IMAGE_TAG} | gzip > ${TAR_FILE} +} + +# 上传并部署到服务器 +function upload_and_deploy() { + gum style "📤 上传镜像..." + scp ${TAR_FILE} ${SERVER_USER}@${SERVER_IP}:~/ + + gum style "🚀 部署到服务器 ${SERVER_IP}..." + ssh ${SERVER_USER}@${SERVER_IP} << EOF + docker stop ${CONTAINER_NAME} 2>/dev/null || true + docker rm ${CONTAINER_NAME} 2>/dev/null || true + gunzip -c ${TAR_FILE} | docker load + docker run -d --name ${CONTAINER_NAME} -p ${PORT}:80 ${IMAGE_NAME}:${IMAGE_TAG} +EOF + + gum style "🎉 成功部署!访问地址:http://${SERVER_IP}:${PORT}" +} + +# 一键完成流程 +function all_in_one() { + build_storybook + build_and_export_image + upload_and_deploy +} + +# 使用 gum 创建交互菜单 +function menu() { + banner + gum choose --header "请选择操作:" \ + "构建 Storybook" \ + "构建并导出镜像" \ + "上传并部署镜像" \ + "一键完成全部流程(推荐)" \ + "退出" | { + case $? in + 0) build_storybook ;; + 1) build_and_export_image ;; + 2) upload_and_deploy ;; + 3) all_in_one ;; + 4) gum style "👋 再见!"; exit 0 ;; + esac + } +} + +# 启动菜单 +menu \ No newline at end of file diff --git a/react-ui/.storybook/scripts/upload-deploy.sh b/react-ui/.storybook/scripts/upload-deploy.sh new file mode 100755 index 00000000..28ddc570 --- /dev/null +++ b/react-ui/.storybook/scripts/upload-deploy.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# 配置项(你可以改成自己的) +SERVER_USER=root # 服务器用户名 +SERVER_IP=172.20.32.197 # 你的服务器 IP 地址 +REMOTE_DIR=/var/storybook/ # 服务器上存放静态文件的目录 +CONTAINER_NAME=storybook # Docker 容器名 +PORT=6006 # 暴露的端口 + +# Step 1: 构建 TypeDoc +echo "📦 构建本地 TypeDoc..." +npm run docs + +# Step 2: 构建 Storybook +echo "📦 构建本地 Storybook..." +npm run storybook-build + +# Step 3: 上传到服务器 +echo "📤 上传静态文件到服务器 ${SERVER_IP}..." +scp -r storybook-static/* ${SERVER_USER}@${SERVER_IP}:${REMOTE_DIR} + +# Step 4: 在服务器上重启 Docker 容器 +echo "🚀 远程重启 Docker 容器..." +ssh ${SERVER_USER}@${SERVER_IP} << EOF + docker stop ${CONTAINER_NAME} || true + docker rm ${CONTAINER_NAME} || true + docker run -d \ + -p ${PORT}:80 \ + --name ${CONTAINER_NAME} \ + -v ${REMOTE_DIR}:/usr/share/nginx/html:ro \ + nginx +EOF + +echo "✅ 部署完成!你现在可以访问:http://${SERVER_IP}:${PORT}" \ No newline at end of file diff --git a/react-ui/package.json b/react-ui/package.json index a990a54f..7b0f345a 100644 --- a/react-ui/package.json +++ b/react-ui/package.json @@ -43,6 +43,7 @@ "storybook": "storybook dev -p 6006", "storybook-build": "storybook build", "storybook-deploy": "./.storybook/scripts/upload-deploy.sh", + "storybook-build-image": "./.storybook/scripts/build-image-deploy.sh", "storybook-docs": "storybook dev --docs", "storybook-docs-build": "storybook build --docs", "test": "jest",