【新增】插件git同步模块,用于同步项目内容,加速项目开发

【调整】前端暗色问题
This commit is contained in:
chudong
2025-05-14 16:50:56 +08:00
parent dc43da936b
commit e6947ec5c4
215 changed files with 19918 additions and 9710 deletions

View File

@@ -0,0 +1,589 @@
#!/bin/bash
# ===================================================
# 项目编译处理脚本 - build-operations.sh
# 用于处理项目编译、工作区选择和编译结果检查
# ===================================================
# 依赖文件操作脚本的函数
source "$(dirname "$0")/file-operations.sh"
# 检查依赖
check_dependencies() {
local deps=("pnpm" "git")
local missing_deps=()
# 检查基本依赖
for dep in "${deps[@]}"; do
if ! command -v "$dep" &> /dev/null; then
missing_deps+=("$dep")
fi
done
# 检查 yq
if ! command -v yq &> /dev/null; then
log_error "未安装 yq这是必需的依赖"
log_info "请按照以下步骤安装 yq"
case "$(uname -s)" in
"Darwin")
log_info "1. 使用 Homebrew 安装:"
log_info " brew install yq"
;;
"Linux")
log_info "1. 使用包管理器安装:"
log_info " # Ubuntu/Debian"
log_info " sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64"
log_info " sudo chmod a+x /usr/local/bin/yq"
log_info " # CentOS/RHEL"
log_info " sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64"
log_info " sudo chmod a+x /usr/local/bin/yq"
;;
"MINGW"*|"MSYS"*)
log_info "1. 使用 Chocolatey 安装:"
log_info " choco install yq"
;;
esac
log_info "2. 安装完成后重新运行此脚本"
exit 1
fi
# 检查其他缺失的依赖
if [[ ${#missing_deps[@]} -gt 0 ]]; then
log_error "未找到必要的依赖: ${missing_deps[*]}"
exit 1
fi
}
# 检测操作系统
detect_os() {
case "$(uname -s)" in
"Darwin")
OS="macos"
;;
"Linux")
OS="linux"
;;
"MINGW"*|"MSYS"*)
OS="windows"
;;
*)
log_error "不支持的操作系统"
exit 1
;;
esac
log_info "检测到操作系统: $OS"
}
# 解析工作区
parse_workspaces() {
if [[ ! -f "$PROJECT_ROOT/pnpm-workspace.yaml" ]]; then
log_error "未找到工作区配置文件"
return 1
fi
# 检查 apps 目录
if [[ ! -d "$PROJECT_ROOT/apps" ]]; then
log_error "未找到 apps 目录"
return 1
fi
# 扫描 apps 目录下的子目录作为工作区
local workspaces=()
for dir in "$PROJECT_ROOT/apps"/*/; do
if [[ -d "$dir" ]]; then
local rel_path="${dir#$PROJECT_ROOT/apps/}"
rel_path="${rel_path%/}"
workspaces+=("$rel_path")
fi
done
# 检查是否找到工作区
if [[ ${#workspaces[@]} -eq 0 ]]; then
log_error "未在 apps 目录下找到任何工作区"
return 1
fi
# 初始化选择
local selected_index=0
local max_index=$((${#workspaces[@]}-1))
# 设置当前步骤
CURRENT_STEP=1
# 显示工作区列表
while true; do
# 显示步骤状态
show_steps
# 打印工作区列表
printf "%s%s选择当前项目工作区%s\n\n" "${BOLD}" "${CYAN}" "${NC}"
for i in "${!workspaces[@]}"; do
if [[ $i -eq $selected_index ]]; then
printf "%s%s %s%s\n" \
"${BOLD}" "${GREEN}" "${workspaces[$i]}" "${NC}"
else
printf " %s%s%s\n" \
"${DIM}" "${workspaces[$i]}" "${NC}"
fi
done
# 显示操作提示
printf "\n%s%s使用上下箭头选择回车确认q键退出%s\n" \
"${BOLD}" "${CYAN}" "${NC}"
# 读取用户输入 - 统一处理方式
local key_pressed=""
local key
read -r -n 1 key
# 获取ASCII码用于调试
if [[ -z "$key" ]]; then
[[ "$DEBUG_MODE" == "true" ]] && printf "空字符,可能是回车键\n"
key_pressed="ENTER" # 空字符通常是回车键
else
[[ "$DEBUG_MODE" == "true" ]] && printf "按键ASCII码: %d\n" "'$key"
# 处理其他按键
case "$key" in
$'\x1b') # ESC 序列,包括方向键
read -r -n 2 seq
[[ "$DEBUG_MODE" == "true" ]] && printf "ESC序列: %s\n" "$seq"
case "$seq" in
"[A") key_pressed="UP" ;; # 上箭头
"[B") key_pressed="DOWN" ;; # 下箭头
*) key_pressed="ESC" ;; # 其他ESC序列
esac
;;
"q"|"Q") # q键退出
key_pressed="QUIT"
;;
*) # 其他按键忽略
key_pressed="OTHER"
;;
esac
fi
# 调试信息
[[ "$DEBUG_MODE" == "true" ]] && log_debug "按键被解析为: $key_pressed"
# 处理操作
case "$key_pressed" in
"UP") # 上箭头
if [[ $selected_index -gt 0 ]]; then
selected_index=$((selected_index-1))
else
# 如果已经是第一项,跳到最后一项
selected_index=$max_index
fi
;;
"DOWN") # 下箭头
if [[ $selected_index -lt $max_index ]]; then
selected_index=$((selected_index+1))
else
# 如果已经是最后一项,回到第一项
selected_index=0
fi
;;
"ENTER") # 回车
SELECTED_WORKSPACE="${workspaces[$selected_index]}"
STEP_WORKSPACE="$SELECTED_WORKSPACE"
CURRENT_STEP=2
return 0
;;
"QUIT") # 退出
log_error "操作已取消"
return 1
;;
esac
done
}
# 显示步骤状态
show_steps() {
clear
printf "\n%s%s项目同步向导%s\n\n" "${BOLD}" "${MAGENTA}" "${NC}"
# 定义灰色文本样式,用于未到达的步骤
local GRAY="${DIM}"
# 步骤一:选择工作区
if [[ $CURRENT_STEP -eq 1 ]]; then
printf "%s%s▶ 第一步:选择工作区%s\n" "${BOLD}" "${GREEN}" "${NC}"
elif [[ $CURRENT_STEP -gt 1 ]]; then
printf "%s%s✓ 第一步:选择工作区%s %s- %s%s%s\n" \
"${DIM}" "${GREEN}" "${NC}" \
"${DIM}" "${CYAN}" "$STEP_WORKSPACE" "${NC}"
else
printf "%s%s○ 第一步:选择工作区%s\n" "${GRAY}" "${GRAY}" "${NC}"
fi
# 步骤二选择Git仓库
if [[ $CURRENT_STEP -eq 2 ]]; then
printf "%s%s▶ 第二步选择Git仓库%s\n" "${BOLD}" "${GREEN}" "${NC}"
elif [[ $CURRENT_STEP -gt 2 ]]; then
printf "%s%s✓ 第二步选择Git仓库%s %s- %s%s%s\n" \
"${DIM}" "${GREEN}" "${NC}" \
"${DIM}" "${CYAN}" "$STEP_GIT_REPOS" "${NC}"
else
printf "%s%s○ 第二步选择Git仓库%s\n" "${GRAY}" "${GRAY}" "${NC}"
fi
# 步骤三:选择同步方式
if [[ $CURRENT_STEP -eq 3 ]]; then
printf "%s%s▶ 第三步:选择同步方式%s\n" "${BOLD}" "${GREEN}" "${NC}"
elif [[ $CURRENT_STEP -gt 3 ]]; then
printf "%s%s✓ 第三步:选择同步方式%s %s- %s%s%s\n" \
"${DIM}" "${GREEN}" "${NC}" \
"${DIM}" "${CYAN}" "$STEP_SYNC_MODE" "${NC}"
else
printf "%s%s○ 第三步:选择同步方式%s\n" "${GRAY}" "${GRAY}" "${NC}"
fi
# 步骤四:执行同步
if [[ $CURRENT_STEP -eq 4 ]]; then
printf "%s%s▶ 第四步:执行同步%s\n" "${BOLD}" "${GREEN}" "${NC}"
elif [[ $CURRENT_STEP -gt 4 ]]; then
printf "%s%s✓ 第四步:执行同步%s\n" "${DIM}" "${GREEN}" "${NC}"
else
printf "%s%s○ 第四步:执行同步%s\n" "${GRAY}" "${GRAY}" "${NC}"
fi
# 分隔线
printf "\n"
show_separator
printf "\n"
}
# 编译执行模块
build_workspace() {
log_info "开始编译工作区: $SELECTED_WORKSPACE"
# 切换到项目根目录
cd "$PROJECT_ROOT" || {
log_error "无法切换到项目根目录"
return 1
}
# 执行编译命令
log_info "执行编译命令: pnpm build --filter $SELECTED_WORKSPACE"
if pnpm build --filter "$SELECTED_WORKSPACE"; then
log_info "编译成功"
return 0
else
log_error "编译失败"
return 1
fi
}
# 检查编译结果
check_build_result() {
local workspace_path="$PROJECT_ROOT/apps/$SELECTED_WORKSPACE"
local dist_path="$workspace_path/dist"
if [[ ! -d "$dist_path" ]]; then
log_error "未找到编译输出目录: $dist_path"
return 1
fi
if [[ -z "$(ls -A "$dist_path")" ]]; then
log_error "编译输出目录为空"
return 1
fi
log_info "编译结果检查通过"
return 0
}
# 并行编译功能
parallel_build_workspaces() {
local workspaces=("$@")
local pids=()
local results=()
# 检查参数
if [[ ${#workspaces[@]} -eq 0 ]]; then
log_error "未指定工作区"
return 1
fi
log_info "开始并行编译 ${#workspaces[@]} 个工作区..."
# 为每个工作区启动编译进程
for workspace in "${workspaces[@]}"; do
(
log_info "开始编译工作区: $workspace"
if pnpm build --filter "$workspace"; then
echo "$workspace|success" > "/tmp/build_${workspace}.result"
else
echo "$workspace|failed" > "/tmp/build_${workspace}.result"
fi
) &
pids+=($!)
done
# 等待所有编译进程完成
for pid in "${pids[@]}"; do
wait "$pid" || {
log_error "编译进程异常退出"
return 1
}
done
# 收集编译结果
local success=true
for workspace in "${workspaces[@]}"; do
if [[ -f "/tmp/build_${workspace}.result" ]]; then
local result=$(cat "/tmp/build_${workspace}.result")
local status=$(echo "$result" | cut -d'|' -f2)
if [[ "$status" == "failed" ]]; then
log_error "工作区 $workspace 编译失败"
success=false
else
log_info "工作区 $workspace 编译成功"
fi
rm -f "/tmp/build_${workspace}.result"
else
log_error "工作区 $workspace 编译结果文件丢失"
success=false
fi
done
if [[ "$success" == "true" ]]; then
log_info "所有工作区编译完成"
return 0
else
log_error "部分工作区编译失败"
return 1
fi
}
# 显示选项列表
show_option_list() {
local title="$1"
shift
local selected_index="${!#}" # 取最后一个参数
local items=("${@:1:$(($#-1))}") # 除最后一个参数外的所有参数
local padding=2 # 选中标识的宽度
# 显示标题
show_title "$title"
printf "%s%s%s\n" "${DIM}" "使用方向键选择回车确认q 退出" "${NC}"
show_separator
# 显示列表
for i in "${!items[@]}"; do
if [[ $i -eq $selected_index ]]; then
# 选中项:使用固定宽度的选中标识
printf "%s%s%s%*s%s%s%s\n" \
"${BOLD}" "${CYAN}" "" \
"$padding" "" \
"${GREEN}" "${items[$i]}" "${NC}"
else
# 未选中项:使用相同的缩进保持对齐
printf "%*s%s%s%s\n" \
"$((padding + 1))" "" \
"${DIM}" "${items[$i]}" "${NC}"
fi
done
show_separator
}
# 显示多选列表
show_multi_select_list() {
local title="$1"
shift
local items=()
local i=0
# 收集所有项目,直到遇到特殊标记 "--INDICES--"
while [[ $i -lt $# && "$1" != "--INDICES--" ]]; do
items+=("$1")
shift
((i++))
done
shift # 跳过 "--INDICES--" 标记
local selected_indices=($@) # 剩余的参数都是选中的索引
local selected_index="${selected_indices[0]}" # 第一个是当前光标位置
# 移除当前索引,只保留选中项索引
selected_indices=("${selected_indices[@]:1}")
local padding=2 # 选中标识的宽度
# 显示标题
show_title "$title"
printf "%s%s%s\n" "${DIM}" "使用数字键1选中/0取消回车确认q 退出" "${NC}"
show_separator
# 显示列表
for i in "${!items[@]}"; do
# 检查当前索引是否在选中列表中
local is_selected=false
for sel_idx in "${selected_indices[@]}"; do
if [[ $i -eq $sel_idx ]]; then
is_selected=true
break
fi
done
if [[ $i -eq $selected_index ]]; then
# 当前光标位置项 - 使用青色箭头标识
if [[ "$is_selected" == "true" ]]; then
# 选中项 - 绿色文本,带复选框
printf "%s%s%s%*s%s%s%s\n" \
"${BOLD}" "${CYAN}" "" \
"$padding" "" \
"${GREEN}" "[✓] ${items[$i]}" "${NC}"
else
# 未选中项 - 灰色文本,不带复选框
printf "%s%s%s%*s%s%s%s\n" \
"${BOLD}" "${CYAN}" "" \
"$padding" "" \
"${DIM}" "[ ] ${items[$i]}" "${NC}"
fi
else
# 非当前光标位置项
if [[ "$is_selected" == "true" ]]; then
# 选中项 - 绿色文本,带复选框
printf "%*s%s%s%s\n" \
"$((padding + 1))" "" \
"${GREEN}" "[✓] ${items[$i]}" "${NC}"
else
# 未选中项 - 灰色文本,不带复选框
printf "%*s%s%s%s\n" \
"$((padding + 1))" "" \
"${DIM}" "[ ] ${items[$i]}" "${NC}"
fi
fi
done
show_separator
}
# 显示帮助信息
show_help() {
show_title "使用帮助"
printf "%s%s用法:%s %s [选项]\n\n" "${BOLD}" "${GREEN}" "${NC}" "$0"
printf "%s%s选项:%s\n" "${BOLD}" "${BLUE}" "${NC}"
printf " %s-w, --workspace%s WORKSPACE %s指定工作区%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
printf " %s-t, --target%s DIR %s指定目标 Git 仓库路径%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
printf " %s-b, --branch%s BRANCH %s指定分支名称%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
printf " %s-s, --sync-structure%s %s同步项目结构%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
printf " %s-p, --parallel%s %s并行编译%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
printf " %s-d, --dry-run%s %s干运行模式%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
printf " %s--debug%s %s调试模式显示详细日志%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
printf " %s-h, --help%s %s显示帮助信息%s\n" "${GREEN}" "${NC}" "${CYAN}" "${NC}"
show_separator
}
# 命令行参数解析
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
-w|--workspace)
SELECTED_WORKSPACE="$2"
shift 2
;;
-t|--target)
TARGET_GIT_DIR="$2"
shift 2
;;
-b|--branch)
BRANCH="$2"
shift 2
;;
-s|--sync-structure)
SYNC_STRUCTURE=true
shift
;;
-p|--parallel)
PARALLEL_BUILD=true
shift
;;
-d|--dry-run)
DRY_RUN=true
shift
;;
--debug)
DEBUG_MODE=true
shift
;;
-h|--help)
show_help
exit 0
;;
*)
log_error "未知参数: $1"
show_help
exit 1
;;
esac
done
}
# 初始化插件目录
init_plugins() {
if [[ -z "$PLUGINS_DIR" ]]; then
log_error "插件目录未初始化,请确保已找到项目根目录"
return 1
fi
if [[ ! -d "$PLUGINS_DIR" ]]; then
mkdir -p "$PLUGINS_DIR" || {
log_error "创建插件目录失败: $PLUGINS_DIR"
return 1
}
log_info "已创建插件目录: $PLUGINS_DIR"
fi
}
# 加载插件
load_plugins() {
if [[ -z "$PLUGINS_DIR" ]]; then
log_error "插件目录未初始化,请确保已找到项目根目录"
return 1
fi
if [[ -d "$PLUGINS_DIR" ]]; then
for plugin in "$PLUGINS_DIR"/*.sh; do
if [[ -f "$plugin" ]]; then
if ! source "$plugin"; then
log_error "加载插件失败: $(basename "$plugin")"
continue
fi
log_info "已加载插件: $(basename "$plugin")"
fi
done
fi
}
# 插件钩子函数
run_hook() {
local hook_name="$1"
shift
# 检查是否存在对应的钩子函数
if declare -F "hook_${hook_name}" > /dev/null; then
"hook_${hook_name}" "$@"
fi
}
# 导出函数
export -f check_dependencies
export -f detect_os
export -f parse_workspaces
export -f show_steps
export -f build_workspace
export -f check_build_result
export -f parallel_build_workspaces
export -f show_option_list
export -f show_multi_select_list
export -f show_help
export -f parse_args
export -f init_plugins
export -f load_plugins
export -f run_hook