commit 1bbb2f79dc106fe644b14be3f661447a8e9d3424 Author: xiaji Date: Sun Feb 16 21:51:06 2025 +0800 第一个项目 diff --git a/check_live.sh b/check_live.sh new file mode 100644 index 0000000..bb2bb59 --- /dev/null +++ b/check_live.sh @@ -0,0 +1,15 @@ +#!/bin/bash +SERVER_IP="192.168.3.105" +USER="xiaji" + +ssh $USER@$SERVER_IP << 'EOF' +echo "=== 关键配置验证 ===" +echo "1. Socket文件权限:" +ls -l /home/xiaji/myproject/myproject.sock +echo -e "\n2. Nginx代理配置:" +sudo grep -A5 'location /' /etc/nginx/sites-available/family_rpa +echo -e "\n3. Gunicorn服务配置:" +sudo grep -E 'ExecStart|WorkingDirectory' /etc/systemd/system/family_rpa.service +echo -e "\n4. 实时错误日志:" +sudo tail -f /var/log/nginx/error.log +EOF diff --git a/check_status.sh b/check_status.sh new file mode 100644 index 0000000..d053e83 --- /dev/null +++ b/check_status.sh @@ -0,0 +1,23 @@ +#!/bin/bash +SERVER_IP="192.168.3.105" +USER="xiaji" + +echo "=== 网络连接检查 ===" +nc -zv $SERVER_IP 80 +nc -zv $SERVER_IP 8000 + +echo -e "\n=== 服务状态检查 ===" +ssh $USER@$SERVER_IP << 'EOF' +echo "## Nginx状态 ##" +sudo systemctl status nginx | head -n 5 + +echo -e "\n## Gunicorn服务状态 ##" +sudo systemctl status family_rpa.service | head -n 5 + +echo -e "\n## 端口监听情况 ##" +sudo netstat -tulpn | grep -E ':80|:8000' + +echo -e "\n## 最近错误日志 ##" +sudo tail -n 20 /var/log/nginx/error.log +sudo journalctl -u family_rpa.service --since "5 minutes ago" | tail -n 10 +EOF diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..d675b2b --- /dev/null +++ b/deploy.sh @@ -0,0 +1,40 @@ +#!/bin/bash +SERVER_IP="192.168.3.105" +USER="xiaji" +DEPLOY_DIR="/home/xiaji/deploy_$(date +%s)" +LOG_FILE="$DEPLOY_DIR/deploy.log" + +# 上传公钥 +ssh-copy-id -i ~/.ssh/id_rsa.pub $USER@$SERVER_IP + +# 执行远程部署 +ssh $USER@$SERVER_IP << EOF +set -e +sudo apt-get update +sudo apt-get install -y python3-pip python3-venv nginx + +mkdir -p $DEPLOY_DIR +tar -xzvf ~/family_rpa.tar.gz -C $DEPLOY_DIR + +python3 -m venv $DEPLOY_DIR/venv +source $DEPLOY_DIR/venv/bin/activate +pip install -r $DEPLOY_DIR/family_rpa/requirements.txt + +# 生产配置检查 +if ! grep -q "DEBUG = False" $DEPLOY_DIR/family_rpa/family_rpa/settings.py; then + echo "ERROR: 未检测到生产环境配置" | tee -a $LOG_FILE + exit 1 +fi + +# 迁移数据库 +python $DEPLOY_DIR/family_rpa/manage.py migrate +python $DEPLOY_DIR/family_rpa/manage.py collectstatic --noinput + +# 切换部署版本 +sudo systemctl stop family_rpa.service +sudo rm -rf /home/xiaji/myproject +mv $DEPLOY_DIR/family_rpa /home/xiaji/myproject +sudo systemctl start family_rpa.service + +echo "部署成功!访问地址:http://$SERVER_IP" | tee -a $LOG_FILE +EOF diff --git a/family_rpa.tar.gz b/family_rpa.tar.gz new file mode 100644 index 0000000..2f4615b Binary files /dev/null and b/family_rpa.tar.gz differ diff --git a/family_rpa/db.sqlite3 b/family_rpa/db.sqlite3 new file mode 100644 index 0000000..479f27d Binary files /dev/null and b/family_rpa/db.sqlite3 differ diff --git a/family_rpa/family_rpa.service b/family_rpa/family_rpa.service new file mode 100644 index 0000000..13a76e7 --- /dev/null +++ b/family_rpa/family_rpa.service @@ -0,0 +1,12 @@ +[Unit] +Description=Gunicorn instance to serve family_rpa +After=network.target + +[Service] +User=xiaji +Group=www-data +WorkingDirectory=/project/family_rpa +ExecStart=/project/family_rpa/venv/bin/gunicorn --workers 3 --bind unix:/project/family_rpa/family_rpa.sock family_rpa.wsgi:application + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/family_rpa/family_rpa/__init__.py b/family_rpa/family_rpa/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/family_rpa/family_rpa/__pycache__/__init__.cpython-313.pyc b/family_rpa/family_rpa/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..06565ca Binary files /dev/null and b/family_rpa/family_rpa/__pycache__/__init__.cpython-313.pyc differ diff --git a/family_rpa/family_rpa/__pycache__/settings.cpython-313.pyc b/family_rpa/family_rpa/__pycache__/settings.cpython-313.pyc new file mode 100644 index 0000000..006deee Binary files /dev/null and b/family_rpa/family_rpa/__pycache__/settings.cpython-313.pyc differ diff --git a/family_rpa/family_rpa/__pycache__/urls.cpython-313.pyc b/family_rpa/family_rpa/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000..9a1c724 Binary files /dev/null and b/family_rpa/family_rpa/__pycache__/urls.cpython-313.pyc differ diff --git a/family_rpa/family_rpa/__pycache__/wsgi.cpython-313.pyc b/family_rpa/family_rpa/__pycache__/wsgi.cpython-313.pyc new file mode 100644 index 0000000..e4b4a54 Binary files /dev/null and b/family_rpa/family_rpa/__pycache__/wsgi.cpython-313.pyc differ diff --git a/family_rpa/family_rpa/asgi.py b/family_rpa/family_rpa/asgi.py new file mode 100644 index 0000000..1d2457c --- /dev/null +++ b/family_rpa/family_rpa/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for family_rpa project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'family_rpa.settings') + +application = get_asgi_application() diff --git a/family_rpa/family_rpa/settings.py b/family_rpa/family_rpa/settings.py new file mode 100644 index 0000000..93444db --- /dev/null +++ b/family_rpa/family_rpa/settings.py @@ -0,0 +1,152 @@ +""" +Django settings for family_rpa project. + +Generated by 'django-admin startproject' using Django 5.1.4. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +import os +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-+&-sio8(2$n#^@367@&w(ld5z024&%mamr5z$pf3kx!m^l+rxs' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django_crontab', + 'main', +] + +CRONJOBS = [ + ('0 0 * * *', 'main.management.commands.cleanup_messages') +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'family_rpa.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'family_rpa.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = 'zh-hans' + +TIME_ZONE = 'Asia/Shanghai' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ + +STATIC_URL = 'static/' +STATICFILES_DIRS = [os.path.join(BASE_DIR, 'assets')] + +MEDIA_URL = 'media/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +LOGIN_REDIRECT_URL = 'admin:index' diff --git a/family_rpa/family_rpa/urls.py b/family_rpa/family_rpa/urls.py new file mode 100644 index 0000000..77ac0d0 --- /dev/null +++ b/family_rpa/family_rpa/urls.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('main.urls')), + path('accounts/', include('django.contrib.auth.urls')), +] diff --git a/family_rpa/family_rpa/wsgi.py b/family_rpa/family_rpa/wsgi.py new file mode 100644 index 0000000..baa1684 --- /dev/null +++ b/family_rpa/family_rpa/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for family_rpa project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'family_rpa.settings') + +application = get_wsgi_application() diff --git a/family_rpa/gunicorn_config.py b/family_rpa/gunicorn_config.py new file mode 100644 index 0000000..364a858 --- /dev/null +++ b/family_rpa/gunicorn_config.py @@ -0,0 +1,20 @@ +# 绑定的地址和端口 +bind = '127.0.0.1:8000' +# 工作进程数量,通常设置为 CPU 核心数的 2 倍 + 1 +workers = 3 +# 工作模式,使用异步的 gevent 模式 +worker_class = 'gevent' +# 每个工作进程处理的最大请求数,超过该数后工作进程会重启 +max_requests = 1000 +# 最大请求数的抖动值,避免所有工作进程同时重启 +max_requests_jitter = 50 +# 超时时间 +timeout = 30 +# 访问日志路径 +accesslog = '/var/log/gunicorn/access.log' +# 错误日志路径 +errorlog = '/var/log/gunicorn/error.log' +# 日志级别 +loglevel = 'info' +# 后台运行 +daemon = True \ No newline at end of file diff --git a/family_rpa/main/__init__.py b/family_rpa/main/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/family_rpa/main/__pycache__/__init__.cpython-313.pyc b/family_rpa/main/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..074abe5 Binary files /dev/null and b/family_rpa/main/__pycache__/__init__.cpython-313.pyc differ diff --git a/family_rpa/main/__pycache__/admin.cpython-313.pyc b/family_rpa/main/__pycache__/admin.cpython-313.pyc new file mode 100644 index 0000000..58bfca8 Binary files /dev/null and b/family_rpa/main/__pycache__/admin.cpython-313.pyc differ diff --git a/family_rpa/main/__pycache__/apps.cpython-313.pyc b/family_rpa/main/__pycache__/apps.cpython-313.pyc new file mode 100644 index 0000000..188d2d4 Binary files /dev/null and b/family_rpa/main/__pycache__/apps.cpython-313.pyc differ diff --git a/family_rpa/main/__pycache__/forms.cpython-313.pyc b/family_rpa/main/__pycache__/forms.cpython-313.pyc new file mode 100644 index 0000000..12c28df Binary files /dev/null and b/family_rpa/main/__pycache__/forms.cpython-313.pyc differ diff --git a/family_rpa/main/__pycache__/models.cpython-313.pyc b/family_rpa/main/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000..d37f666 Binary files /dev/null and b/family_rpa/main/__pycache__/models.cpython-313.pyc differ diff --git a/family_rpa/main/__pycache__/urls.cpython-313.pyc b/family_rpa/main/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000..bd0cdb2 Binary files /dev/null and b/family_rpa/main/__pycache__/urls.cpython-313.pyc differ diff --git a/family_rpa/main/__pycache__/views.cpython-313.pyc b/family_rpa/main/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000..963e8be Binary files /dev/null and b/family_rpa/main/__pycache__/views.cpython-313.pyc differ diff --git a/family_rpa/main/admin.py b/family_rpa/main/admin.py new file mode 100644 index 0000000..5c824a6 --- /dev/null +++ b/family_rpa/main/admin.py @@ -0,0 +1,16 @@ +from django.contrib import admin +from .models import File, Message + +@admin.register(File) +class FileAdmin(admin.ModelAdmin): + list_display = ('file', 'owner', 'created_at', 'is_public') + list_filter = ('is_public', 'created_at') + search_fields = ('file', 'description') + date_hierarchy = 'created_at' + +@admin.register(Message) +class MessageAdmin(admin.ModelAdmin): + list_display = ('author', 'content', 'created_at', 'ip_address') + list_filter = ('created_at', 'ip_address') + search_fields = ('author', 'content') + date_hierarchy = 'created_at' diff --git a/family_rpa/main/apps.py b/family_rpa/main/apps.py new file mode 100644 index 0000000..167f044 --- /dev/null +++ b/family_rpa/main/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MainConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'main' diff --git a/family_rpa/main/forms.py b/family_rpa/main/forms.py new file mode 100644 index 0000000..c6b3005 --- /dev/null +++ b/family_rpa/main/forms.py @@ -0,0 +1,18 @@ +from django import forms +from .models import File, Message + +class FileUploadForm(forms.ModelForm): + class Meta: + model = File + fields = ['file', 'description', 'is_public'] + widgets = { + 'description': forms.Textarea(attrs={'rows': 3}), + } + +class MessageForm(forms.ModelForm): + class Meta: + model = Message + fields = ['author', 'content'] + widgets = { + 'content': forms.Textarea(attrs={'rows': 5}), + } \ No newline at end of file diff --git a/family_rpa/main/management/commands/cleanup_messages.py b/family_rpa/main/management/commands/cleanup_messages.py new file mode 100644 index 0000000..9227469 --- /dev/null +++ b/family_rpa/main/management/commands/cleanup_messages.py @@ -0,0 +1,11 @@ +from django.core.management.base import BaseCommand +from django.utils import timezone +from ...models import Message + +class Command(BaseCommand): + help = 'Clean up messages older than 7 days' + + def handle(self, *args, **options): + one_week_ago = timezone.now() - timezone.timedelta(days=7) + deleted_count, _ = Message.objects.filter(created_at__lt=one_week_ago).delete() + self.stdout.write(self.style.SUCCESS(f'Successfully deleted {deleted_count} old messages')) \ No newline at end of file diff --git a/family_rpa/main/migrations/0001_initial.py b/family_rpa/main/migrations/0001_initial.py new file mode 100644 index 0000000..6a37cb0 --- /dev/null +++ b/family_rpa/main/migrations/0001_initial.py @@ -0,0 +1,41 @@ +# Generated by Django 5.1.4 on 2025-02-15 13:07 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Message', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('author', models.CharField(max_length=100)), + ('content', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('ip_address', models.GenericIPAddressField(blank=True, null=True)), + ], + options={ + 'ordering': ['-created_at'], + }, + ), + migrations.CreateModel( + name='File', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(upload_to='uploads/')), + ('description', models.TextField(blank=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('is_public', models.BooleanField(default=False)), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/family_rpa/main/migrations/0002_alter_file_owner.py b/family_rpa/main/migrations/0002_alter_file_owner.py new file mode 100644 index 0000000..aa12703 --- /dev/null +++ b/family_rpa/main/migrations/0002_alter_file_owner.py @@ -0,0 +1,21 @@ +# Generated by Django 5.1.4 on 2025-02-15 13:51 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterField( + model_name='file', + name='owner', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/family_rpa/main/migrations/__init__.py b/family_rpa/main/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/family_rpa/main/migrations/__pycache__/0001_initial.cpython-313.pyc b/family_rpa/main/migrations/__pycache__/0001_initial.cpython-313.pyc new file mode 100644 index 0000000..798bae4 Binary files /dev/null and b/family_rpa/main/migrations/__pycache__/0001_initial.cpython-313.pyc differ diff --git a/family_rpa/main/migrations/__pycache__/0002_alter_file_owner.cpython-313.pyc b/family_rpa/main/migrations/__pycache__/0002_alter_file_owner.cpython-313.pyc new file mode 100644 index 0000000..d486727 Binary files /dev/null and b/family_rpa/main/migrations/__pycache__/0002_alter_file_owner.cpython-313.pyc differ diff --git a/family_rpa/main/migrations/__pycache__/__init__.cpython-313.pyc b/family_rpa/main/migrations/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..fb20b76 Binary files /dev/null and b/family_rpa/main/migrations/__pycache__/__init__.cpython-313.pyc differ diff --git a/family_rpa/main/models.py b/family_rpa/main/models.py new file mode 100644 index 0000000..cb9262e --- /dev/null +++ b/family_rpa/main/models.py @@ -0,0 +1,25 @@ +from django.db import models +from django.utils import timezone +from django.contrib.auth.models import User + +class File(models.Model): + owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) + file = models.FileField(upload_to='uploads/') + description = models.TextField(blank=True) + created_at = models.DateTimeField(auto_now_add=True) + is_public = models.BooleanField(default=True) + + def __str__(self): + return self.file.name + +class Message(models.Model): + author = models.CharField(max_length=100) + content = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + ip_address = models.GenericIPAddressField(null=True, blank=True) + + def __str__(self): + return f"来自 {self.author} 的留言" + + class Meta: + ordering = ['-created_at'] diff --git a/family_rpa/main/tests.py b/family_rpa/main/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/family_rpa/main/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/family_rpa/main/urls.py b/family_rpa/main/urls.py new file mode 100644 index 0000000..d4e5cb6 --- /dev/null +++ b/family_rpa/main/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.home, name='home'), + path('upload/', views.upload_file, name='upload'), + path('delete//', views.delete_file, name='delete'), + path('message/', views.post_message, name='message'), +] \ No newline at end of file diff --git a/family_rpa/main/views.py b/family_rpa/main/views.py new file mode 100644 index 0000000..658ab68 --- /dev/null +++ b/family_rpa/main/views.py @@ -0,0 +1,53 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.http import HttpResponse +from django.utils import timezone +from django.core.files.storage import default_storage +from django.core.paginator import Paginator +from .models import File, Message +from .forms import FileUploadForm, MessageForm +from django.utils.timezone import timedelta + +def home(request): + # 获取最近一周的留言 + one_week_ago = timezone.now() - timedelta(days=7) + messages = Message.objects.filter(created_at__gte=one_week_ago).order_by('-created_at') + + # 获取公开文件 + files = File.objects.filter(is_public=True).order_by('-created_at') + + return render(request, 'main/home.html', { + 'messages': messages, + 'files': files + }) + +def upload_file(request): + if request.method == 'POST': + form = FileUploadForm(request.POST, request.FILES) + if form.is_valid(): + file = form.save(commit=False) + if request.user.is_authenticated: + file.owner = request.user + file.save() + return redirect('home') + else: + form = FileUploadForm() + return render(request, 'main/upload.html', {'form': form}) + +def delete_file(request, file_id): + file = get_object_or_404(File, id=file_id) + if request.user == file.owner: + file.file.delete() + file.delete() + return redirect('home') + +def post_message(request): + if request.method == 'POST': + form = MessageForm(request.POST) + if form.is_valid(): + message = form.save(commit=False) + message.ip_address = request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR')) + message.save() + return redirect('home') + else: + form = MessageForm() + return render(request, 'main/message.html', {'form': form}) diff --git a/family_rpa/manage.py b/family_rpa/manage.py new file mode 100644 index 0000000..b0df2da --- /dev/null +++ b/family_rpa/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'family_rpa.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build.7z b/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build.7z new file mode 100644 index 0000000..e57b3e4 Binary files /dev/null and b/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build.7z differ diff --git a/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build_7B7y4HU.7z b/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build_7B7y4HU.7z new file mode 100644 index 0000000..e57b3e4 Binary files /dev/null and b/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build_7B7y4HU.7z differ diff --git a/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build_MTh7y7l.7z b/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build_MTh7y7l.7z new file mode 100644 index 0000000..e57b3e4 Binary files /dev/null and b/family_rpa/media/uploads/ffmpeg-2025-02-13-git-19a2d26177-full_build_MTh7y7l.7z differ diff --git a/family_rpa/media/uploads/vac470lite.zip b/family_rpa/media/uploads/vac470lite.zip new file mode 100644 index 0000000..3e763d4 Binary files /dev/null and b/family_rpa/media/uploads/vac470lite.zip differ diff --git a/family_rpa/media/uploads/vac470lite_0dVajUD.zip b/family_rpa/media/uploads/vac470lite_0dVajUD.zip new file mode 100644 index 0000000..3e763d4 Binary files /dev/null and b/family_rpa/media/uploads/vac470lite_0dVajUD.zip differ diff --git a/family_rpa/media/uploads/vac470lite_Tr7wrZb.zip b/family_rpa/media/uploads/vac470lite_Tr7wrZb.zip new file mode 100644 index 0000000..3e763d4 Binary files /dev/null and b/family_rpa/media/uploads/vac470lite_Tr7wrZb.zip differ diff --git a/family_rpa/media/uploads/vac470lite_cct4sWa.zip b/family_rpa/media/uploads/vac470lite_cct4sWa.zip new file mode 100644 index 0000000..3e763d4 Binary files /dev/null and b/family_rpa/media/uploads/vac470lite_cct4sWa.zip differ diff --git a/family_rpa/nginx.config b/family_rpa/nginx.config new file mode 100644 index 0000000..0f6cbbf --- /dev/null +++ b/family_rpa/nginx.config @@ -0,0 +1,20 @@ +server { + listen 80; + server_name 192.168.3.105; + + location / { + proxy_pass http://unix:/project/family_rpa/family_rpa.sock; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /static/ { + alias /project/family_rpa/static/; + } + + location /media/ { + alias /project/family_rpa/media/; + } +} \ No newline at end of file diff --git a/family_rpa/requirements.txt b/family_rpa/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/family_rpa/static/output.css b/family_rpa/static/output.css new file mode 100644 index 0000000..92feceb --- /dev/null +++ b/family_rpa/static/output.css @@ -0,0 +1,107 @@ +/*! tailwindcss v4.0.6 | MIT License | https://tailwindcss.com */ +.static { + position: static; +} +.container { + width: 100%; +} +.mx-auto { + margin-inline: auto; +} +.block { + display: block; +} +.flex { + display: flex; +} +.grid { + display: grid; +} +.w-full { + width: 100%; +} +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} +.items-center { + align-items: center; +} +.justify-between { + justify-content: space-between; +} +.border { + border-style: var(--tw-border-style); + border-width: 1px; +} +.text-center { + text-align: center; +} +.filter { + filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); +} +.\[w\:۵qzg\] { + w: ۵qzg; +} +@layer base { + :root { + --color-primary: 79 70 229; + --color-secondary: 99 102 241; + --color-accent: 249 115 22; + --color-success: 16 185 129; + --color-warning: 245 158 11; + --color-error: 239 68 68; + --color-surface: 255 255 255; + --color-background: 249 250 251; + } + .dark { + --color-primary: 99 102 241; + --color-secondary: 129 140 248; + --color-accent: 249 115 22; + --color-success: 16 185 129; + --color-warning: 245 158 11; + --color-error: 239 68 68; + --color-surface: 31 41 55; + --color-background: 17 24 39; + } +} +@property --tw-border-style { + syntax: "*"; + inherits: false; + initial-value: solid; +} +@property --tw-blur { + syntax: "*"; + inherits: false; +} +@property --tw-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-invert { + syntax: "*"; + inherits: false; +} +@property --tw-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-sepia { + syntax: "*"; + inherits: false; +} diff --git a/family_rpa/tailwindcss-windows-x64.exe b/family_rpa/tailwindcss-windows-x64.exe new file mode 100644 index 0000000..c461cdc Binary files /dev/null and b/family_rpa/tailwindcss-windows-x64.exe differ diff --git a/family_rpa/templates/base.html b/family_rpa/templates/base.html new file mode 100644 index 0000000..2a25723 --- /dev/null +++ b/family_rpa/templates/base.html @@ -0,0 +1,49 @@ +{% load static %} + + + + + + 家庭RPA系统 + + + + + +
+ {% block content %} + {% endblock %} +
+ + + + \ No newline at end of file diff --git a/family_rpa/templates/main/home.html b/family_rpa/templates/main/home.html new file mode 100644 index 0000000..46ab495 --- /dev/null +++ b/family_rpa/templates/main/home.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+

最新留言

+ {% for message in messages %} +
+
+
+ {{ message.author }} + {{ message.created_at|date:"Y-m-d H:i" }} +
+

{{ message.content }}

+
+
+ {% endfor %} +
+ +
+

公开文件

+ {% for file in files %} +
+
+
+ + {{ file.file.name }} + + {{ file.created_at|date:"Y-m-d H:i" }} +
+

{{ file.description }}

+
+
+ {% endfor %} +
+
+{% endblock %} \ No newline at end of file diff --git a/family_rpa/templates/main/message.html b/family_rpa/templates/main/message.html new file mode 100644 index 0000000..0c4afbe --- /dev/null +++ b/family_rpa/templates/main/message.html @@ -0,0 +1,20 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+
+

发布留言

+
+ {% csrf_token %} +
+ {{ form.as_p }} +
+ +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/family_rpa/templates/main/upload.html b/family_rpa/templates/main/upload.html new file mode 100644 index 0000000..90eb09b --- /dev/null +++ b/family_rpa/templates/main/upload.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+
+

上传文件

+
+ {% csrf_token %} +
+
+ + {{ form.file }} +
+
+ + {{ form.description }} +
+
+ {{ form.is_public }} + +
+
+ +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/family_rpa/templates/registration/logged_out.html b/family_rpa/templates/registration/logged_out.html new file mode 100644 index 0000000..915e4ac --- /dev/null +++ b/family_rpa/templates/registration/logged_out.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+

已注销

+ +

您已成功注销。

+ + 重新登录 +
+
+
+{% endblock %} \ No newline at end of file diff --git a/family_rpa/templates/registration/login.html b/family_rpa/templates/registration/login.html new file mode 100644 index 0000000..61cb2ea --- /dev/null +++ b/family_rpa/templates/registration/login.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+

登录

+ + {% if form.errors %} +
+ 用户名或密码错误,请重试。 +
+ {% endif %} + +
+ {% csrf_token %} + +
+ + {{ form.username }} +
+ +
+ + {{ form.password }} +
+ + +
+ + +
+
+
+{% endblock %} \ No newline at end of file diff --git a/final_fix.sh b/final_fix.sh new file mode 100644 index 0000000..7a57375 --- /dev/null +++ b/final_fix.sh @@ -0,0 +1,25 @@ +#!/bin/bash +SERVER_IP="192.168.3.105" +USER="xiaji" + +ssh $USER@$SERVER_IP << 'EOF' +# 修复权限问题 +sudo chown xiaji:www-data /home/xiaji/myproject/myproject.sock +sudo chmod 660 /home/xiaji/myproject/myproject.sock + +# 确认配置有效性 +sudo nginx -t && sudo systemctl reload nginx +sudo systemctl daemon-reload +sudo systemctl restart family_rpa.service + +# 验证服务状态 +echo -e "\n=== 最终服务状态 ===" +sudo systemctl status family_rpa.service --no-pager | head -n 10 +sudo ss -nltp | grep -E ':80|.sock' + +# 开放防火墙 +sudo ufw allow 80/tcp +EOF + +# 本地验证 +curl -v --connect-timeout 10 http://$SERVER_IP diff --git a/final_validate.sh b/final_validate.sh new file mode 100644 index 0000000..de8e313 --- /dev/null +++ b/final_validate.sh @@ -0,0 +1,21 @@ +#!/bin/bash +SERVER_IP="192.168.3.105" +USER="xiaji" + +echo "=== 最终状态验证 ===" +ssh $USER@$SERVER_IP << 'EOF' +echo "1. 服务运行状态:" +sudo systemctl is-active family_rpa.service nginx + +echo -e "\n2. 端口监听情况:" +sudo netstat -tulpn | grep -E ':80|.sock' + +echo -e "\n3. 最新访问日志:" +sudo tail -n 5 /var/log/nginx/access.log + +echo -e "\n4. 资源使用情况:" +free -h && df -h +EOF + +echo -e "\n=== 本地访问测试 ===" +curl -sS -o /dev/null -w "HTTP状态码: %{http_code}\n响应时间: %{time_total}s\n" http://$SERVER_IP diff --git a/fix_services.sh b/fix_services.sh new file mode 100644 index 0000000..a5a1499 --- /dev/null +++ b/fix_services.sh @@ -0,0 +1,23 @@ +#!/bin/bash +SERVER_IP="192.168.3.105" +USER="xiaji" + +ssh $USER@$SERVER_IP << 'EOF' +# 修正Nginx配置 +sudo sed -i "s/proxy_pass http:\/\/127.0.0.1:8000;/proxy_pass http:\/\/unix:\/home\/xiaji\/myproject\/myproject.sock;/g" /etc/nginx/sites-available/family_rpa + +# 修正Gunicorn绑定方式 +sudo sed -i "s/--bind 0.0.0.0:8000/--bind unix:\/home\/xiaji\/myproject\/myproject.sock/g" /etc/systemd/system/family_rpa.service + +# 设置socket权限 +echo "UMASK=007" | sudo tee -a /etc/systemd/system/family_rpa.service +sudo systemctl daemon-reload + +# 重启服务 +sudo systemctl restart family_rpa.service +sudo systemctl restart nginx + +# 验证配置 +sudo nginx -t +sudo ss -alnpt | grep -E '80|.sock' +EOF diff --git a/full_diagnose.sh b/full_diagnose.sh new file mode 100644 index 0000000..8ec04fd --- /dev/null +++ b/full_diagnose.sh @@ -0,0 +1,30 @@ +#!/bin/bash +SERVER_IP="192.168.3.105" +USER="xiaji" + +echo "=== 服务状态深度检查 ===" +ssh $USER@$SERVER_IP << 'EOF' +echo "1. Gunicorn服务状态:" +sudo systemctl status family_rpa.service --no-pager + +echo -e "\n2. Nginx服务状态:" +sudo systemctl status nginx --no-pager + +echo -e "\n3. Socket文件检查:" +ls -l /home/xiaji/myproject/myproject.sock +stat /home/xiaji/myproject/myproject.sock + +echo -e "\n4. 进程关联验证:" +sudo lsof -U | grep myproject.sock + +echo -e "\n5. 权限配置检查:" +groups www-data +getent group www-data + +echo -e "\n6. 最新错误日志:" +sudo tail -30 /var/log/nginx/error.log +sudo journalctl -u family_rpa.service --since "5 minutes ago" --no-pager +EOF + +echo -e "\n=== 本地网络验证 ===" +curl -v --connect-timeout 10 http://$SERVER_IP diff --git a/tailwindcss-windows-x64.exe b/tailwindcss-windows-x64.exe new file mode 100644 index 0000000..c461cdc Binary files /dev/null and b/tailwindcss-windows-x64.exe differ diff --git a/upload_commands.txt b/upload_commands.txt new file mode 100644 index 0000000..d1985a8 --- /dev/null +++ b/upload_commands.txt @@ -0,0 +1,10 @@ +sudo rm -rf /project +sudo mkdir -p /project +sudo chown -R xiaji:xiaji /project +rsync -avz --progress family_rpa xiaji@192.168.3.105:/project/ +sudo cp /project/family_rpa/nginx.config /etc/nginx/sites-available/family_rpa +sudo cp /project/family_rpa/family_rpa.service /etc/systemd/system/ +sudo ln -sf /etc/nginx/sites-available/family_rpa /etc/nginx/sites-enabled/ +sudo systemctl daemon-reload +sudo systemctl restart nginx +sudo systemctl start family_rpa \ No newline at end of file