v2.4: 响应式布局 + 借款按钮优化
- 所有页面添加响应式CSS,支持手机/电脑自适应 - index.html: 导航栏active状态、表单、统计、借款列表响应式 - analysis.html: 图表、统计卡片响应式 - admin.html: 表格、搜索栏响应式 - reset-password.html: 登录卡片响应式 - 修复导航栏active类:analysis.html的分析标签高亮 - 非本人借款:隐藏修改按钮,快速还款改为快速查看 - 修复main.py重复函数 - 添加debt-manager.sh管理脚本
This commit is contained in:
321
debt-manager.sh
Executable file
321
debt-manager.sh
Executable file
@@ -0,0 +1,321 @@
|
||||
#!/bin/bash
|
||||
# ============================================
|
||||
# 债务管理系统 - 管理脚本 v2.3
|
||||
# ============================================
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
INSTALL_DIR="/opt/debt-manager"
|
||||
|
||||
show_logo() {
|
||||
clear
|
||||
echo -e "${CYAN}"
|
||||
echo "╔══════════════════════════════════════════════╗"
|
||||
echo "║ 债务管理系统 Debt Manager ║"
|
||||
echo "║ 个人/小团队债务管理平台 ║"
|
||||
echo "║ 版本: v2.3 ║"
|
||||
echo "╚══════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
detect_arch() {
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64|amd64) ARCH_NAME="x86" ;;
|
||||
aarch64|arm64) ARCH_NAME="arm64" ;;
|
||||
*) echo -e "${RED}不支持的架构: $ARCH${NC}"; return 1 ;;
|
||||
esac
|
||||
echo -e "${CYAN}架构: $ARCH_NAME${NC}"
|
||||
}
|
||||
|
||||
check_docker() {
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "${RED}请先安装 Docker${NC}"; exit 1
|
||||
fi
|
||||
if ! docker compose version &> /dev/null; then
|
||||
echo -e "${RED}请先安装 Docker Compose${NC}"; exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
gen_password() { openssl rand -hex 16; }
|
||||
|
||||
get_script_dir() {
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ]; do
|
||||
DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
||||
SOURCE="$(readlink "$SOURCE")"
|
||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
|
||||
done
|
||||
cd -P "$(dirname "$SOURCE")" && pwd
|
||||
}
|
||||
|
||||
# 检查镜像是否存在
|
||||
check_images_exist() {
|
||||
local backend_image="debt-manager-backend:${ARCH_NAME}"
|
||||
local frontend_image="debt-manager-frontend:${ARCH_NAME}"
|
||||
local postgres_image="postgres:15-alpine"
|
||||
|
||||
local backend_exists=$(docker image inspect "$backend_image" 2>/dev/null && echo "yes" || echo "no")
|
||||
local frontend_exists=$(docker image inspect "$frontend_image" 2>/dev/null && echo "yes" || echo "no")
|
||||
local postgres_exists=$(docker image inspect "$postgres_image" 2>/dev/null && echo "yes" || echo "no")
|
||||
|
||||
if [ "$backend_exists" = "yes" ] && [ "$frontend_exists" = "yes" ] && [ "$postgres_exists" = "yes" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 加载镜像(如果不存在)
|
||||
load_images_if_needed() {
|
||||
local script_dir="$1"
|
||||
|
||||
if check_images_exist; then
|
||||
echo -e "${GREEN}镜像已存在,跳过加载${NC}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo -e "${CYAN}加载镜像...${NC}"
|
||||
local loaded=0
|
||||
|
||||
for f in "$script_dir/deploy/"*-${ARCH_NAME}.tar.gz "$script_dir/deploy/postgres"*.tar.gz; do
|
||||
if [ -f "$f" ]; then
|
||||
local img_name=$(basename "$f" .tar.gz)
|
||||
if docker image inspect "$img_name" &>/dev/null; then
|
||||
echo -e " ${GREEN}✓${NC} $img_name (已存在)"
|
||||
else
|
||||
echo -e " 加载 $img_name ..."
|
||||
docker load < "$f" 2>/dev/null && loaded=$((loaded+1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $loaded -gt 0 ]; then
|
||||
echo -e "${GREEN}加载了 $loaded 个镜像${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 验证所有容器运行状态
|
||||
verify_containers() {
|
||||
echo -e "${CYAN}验证容器状态...${NC}"
|
||||
local all_up=true
|
||||
|
||||
for svc in db backend frontend; do
|
||||
local status=$(docker compose ps --format '{{.Status}}' --filter "name=$svc" 2>/dev/null)
|
||||
if echo "$status" | grep -q "Up"; then
|
||||
echo -e " ${GREEN}✓${NC} $svc: 运行中"
|
||||
else
|
||||
echo -e " ${RED}✗${NC} $svc: 未运行 ($status)"
|
||||
all_up=false
|
||||
fi
|
||||
done
|
||||
|
||||
if $all_up; then
|
||||
echo -e "${GREEN}所有容器运行正常${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}部分容器未正常运行${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
show_menu() {
|
||||
echo -e "${YELLOW}请选择操作:${NC}"
|
||||
echo ""
|
||||
echo " 1) 安装系统"
|
||||
echo " 2) 更新系统"
|
||||
echo " 3) 卸载系统"
|
||||
echo " 4) 重置系统"
|
||||
echo " 5) 查看状态"
|
||||
echo " 0) 退出"
|
||||
echo ""
|
||||
read -p "请输入选项 [0-5]: " choice
|
||||
}
|
||||
|
||||
install_system() {
|
||||
echo -e "${CYAN}═══ 安装债务管理系统 ═══${NC}"
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
echo -e "${YELLOW}系统已安装,是否覆盖? (y/N)${NC}"
|
||||
read -p "> " confirm
|
||||
[ "$confirm" != "y" ] && return
|
||||
cd "$INSTALL_DIR" && docker compose down 2>/dev/null || true
|
||||
fi
|
||||
|
||||
detect_arch || return
|
||||
SCRIPT_DIR="$(get_script_dir)"
|
||||
mkdir -p "$INSTALL_DIR" && cd "$INSTALL_DIR"
|
||||
|
||||
# 复制 docker-compose 文件
|
||||
if [ -f "$SCRIPT_DIR/deploy/docker-compose.${ARCH_NAME}.yml" ]; then
|
||||
cp "$SCRIPT_DIR/deploy/docker-compose.${ARCH_NAME}.yml" docker-compose.yml
|
||||
elif [ -f "$SCRIPT_DIR/docker-compose.yml" ]; then
|
||||
cp "$SCRIPT_DIR/docker-compose.yml" docker-compose.yml
|
||||
else
|
||||
echo -e "${RED}找不到 docker-compose 配置文件${NC}"; return 1
|
||||
fi
|
||||
|
||||
# 复制镜像文件
|
||||
if [ -d "$SCRIPT_DIR/deploy" ]; then
|
||||
for f in "$SCRIPT_DIR/deploy/"*-${ARCH_NAME}.tar.gz "$SCRIPT_DIR/deploy/postgres"*.tar.gz; do
|
||||
[ -f "$f" ] && cp "$f" .
|
||||
done
|
||||
fi
|
||||
[ -f "$SCRIPT_DIR/restore.sh" ] && cp "$SCRIPT_DIR/restore.sh" . && chmod +x restore.sh
|
||||
|
||||
# 生成密钥
|
||||
DB_PASS=$(gen_password)
|
||||
SECRET=$(gen_password)
|
||||
cat > .env << EOF
|
||||
POSTGRES_DB=debt_manager
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=$DB_PASS
|
||||
DATABASE_URL=postgresql+asyncpg://postgres:$DB_PASS@db:5432/debt_manager
|
||||
SECRET_KEY=$SECRET
|
||||
EOF
|
||||
|
||||
# 检查并加载镜像
|
||||
load_images_if_needed "$SCRIPT_DIR"
|
||||
|
||||
# 启动
|
||||
echo -e "${CYAN}启动服务...${NC}"
|
||||
docker compose up -d
|
||||
echo -e "${CYAN}等待服务启动...${NC}"
|
||||
sleep 10
|
||||
|
||||
# 验证容器
|
||||
if verify_containers; then
|
||||
IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo "localhost")
|
||||
echo ""
|
||||
echo -e "${GREEN}═══ 安装成功! ═══${NC}"
|
||||
echo -e " 前台: ${CYAN}http://$IP:806${NC}"
|
||||
echo -e " 后台: ${CYAN}http://$IP:806/admin.html${NC}"
|
||||
echo -e " 管理员: ${CYAN}admin / admin123${NC}"
|
||||
echo -e " ${YELLOW}请立即修改默认密码!${NC}"
|
||||
else
|
||||
echo -e "${RED}启动失败,查看日志:${NC}"
|
||||
docker compose logs --tail=30
|
||||
fi
|
||||
}
|
||||
|
||||
update_system() {
|
||||
echo -e "${CYAN}═══ 更新债务管理系统 ═══${NC}"
|
||||
[ ! -d "$INSTALL_DIR" ] && { echo -e "${YELLOW}系统未安装${NC}"; return; }
|
||||
|
||||
cd "$INSTALL_DIR"
|
||||
detect_arch || return
|
||||
SCRIPT_DIR="$(get_script_dir)"
|
||||
|
||||
# 备份
|
||||
echo -e "${CYAN}备份数据库...${NC}"
|
||||
docker compose exec -T db pg_dump -U postgres debt_manager > "backup_$(date +%Y%m%d_%H%M%S).sql" 2>/dev/null || true
|
||||
echo -e "${GREEN}备份完成${NC}"
|
||||
|
||||
# 更新文件
|
||||
[ -f "$SCRIPT_DIR/deploy/docker-compose.${ARCH_NAME}.yml" ] && cp "$SCRIPT_DIR/deploy/docker-compose.${ARCH_NAME}.yml" docker-compose.yml
|
||||
if [ -d "$SCRIPT_DIR/deploy" ]; then
|
||||
for f in "$SCRIPT_DIR/deploy/"*-${ARCH_NAME}.tar.gz "$SCRIPT_DIR/deploy/postgres"*.tar.gz; do
|
||||
[ -f "$f" ] && cp "$f" .
|
||||
done
|
||||
fi
|
||||
|
||||
# 检查并加载新镜像
|
||||
load_images_if_needed "$SCRIPT_DIR"
|
||||
|
||||
echo -e "${CYAN}重启服务...${NC}"
|
||||
docker compose down && docker compose up -d
|
||||
echo -e "${CYAN}等待服务启动...${NC}"
|
||||
sleep 8
|
||||
|
||||
if verify_containers; then
|
||||
echo -e "${GREEN}更新完成!${NC}"
|
||||
else
|
||||
echo -e "${RED}更新失败,查看日志:${NC}"
|
||||
docker compose logs --tail=30
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_system() {
|
||||
echo -e "${CYAN}═══ 卸载债务管理系统 ═══${NC}"
|
||||
[ ! -d "$INSTALL_DIR" ] && { echo -e "${YELLOW}系统未安装${NC}"; return; }
|
||||
|
||||
echo -e "${RED}警告: 将删除所有数据,包括数据库!${NC}"
|
||||
read -p "输入 YES 确认: " confirm
|
||||
[ "$confirm" != "YES" ] && { echo -e "${RED}已取消${NC}"; return; }
|
||||
|
||||
cd "$INSTALL_DIR" && docker compose down -v 2>/dev/null || true
|
||||
rm -rf "$INSTALL_DIR"
|
||||
echo -e "${GREEN}卸载完成${NC}"
|
||||
}
|
||||
|
||||
reset_system() {
|
||||
echo -e "${CYAN}═══ 重置债务管理系统 ═══${NC}"
|
||||
[ ! -d "$INSTALL_DIR" ] && { echo -e "${RED}系统未安装${NC}"; return; }
|
||||
|
||||
echo -e "${RED}警告: 将清空所有数据!${NC}"
|
||||
read -p "输入 YES 确认: " confirm
|
||||
[ "$confirm" != "YES" ] && { echo -e "${RED}已取消${NC}"; return; }
|
||||
|
||||
cd "$INSTALL_DIR"
|
||||
echo -e "${CYAN}备份数据...${NC}"
|
||||
docker compose exec -T db pg_dump -U postgres debt_manager > "pre_reset_$(date +%Y%m%d_%H%M%S).sql" 2>/dev/null || true
|
||||
|
||||
docker compose down -v 2>/dev/null || true
|
||||
docker volume rm debt-manager_pgdata 2>/dev/null || true
|
||||
|
||||
DB_PASS=$(gen_password)
|
||||
SECRET=$(gen_password)
|
||||
cat > .env << EOF
|
||||
POSTGRES_DB=debt_manager
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=$DB_PASS
|
||||
DATABASE_URL=postgresql+asyncpg://postgres:$DB_PASS@db:5432/debt_manager
|
||||
SECRET_KEY=$SECRET
|
||||
EOF
|
||||
|
||||
docker compose up -d
|
||||
echo -e "${CYAN}等待服务启动...${NC}"
|
||||
sleep 10
|
||||
|
||||
if verify_containers; then
|
||||
echo -e "${GREEN}重置完成!${NC}"
|
||||
echo -e " 管理员: ${CYAN}admin / admin123${NC}"
|
||||
else
|
||||
echo -e "${RED}重置失败,查看日志:${NC}"
|
||||
docker compose logs --tail=30
|
||||
fi
|
||||
}
|
||||
|
||||
show_status() {
|
||||
[ ! -d "$INSTALL_DIR" ] && { echo -e "${YELLOW}系统未安装${NC}"; return; }
|
||||
cd "$INSTALL_DIR"
|
||||
echo -e "${CYAN}═══ 服务状态 ═══${NC}"
|
||||
docker compose ps
|
||||
echo ""
|
||||
echo -e "${CYAN}磁盘使用:${NC}"
|
||||
du -sh "$INSTALL_DIR" 2>/dev/null || true
|
||||
}
|
||||
|
||||
main() {
|
||||
show_logo
|
||||
check_docker
|
||||
while true; do
|
||||
show_menu
|
||||
case $choice in
|
||||
1) install_system ;;
|
||||
2) update_system ;;
|
||||
3) uninstall_system ;;
|
||||
4) reset_system ;;
|
||||
5) show_status ;;
|
||||
0) echo -e "${GREEN}再见!${NC}"; exit 0 ;;
|
||||
*) echo -e "${RED}无效选项${NC}" ;;
|
||||
esac
|
||||
echo ""
|
||||
read -p "按回车继续..." _
|
||||
done
|
||||
}
|
||||
|
||||
main
|
||||
Reference in New Issue
Block a user