本指南将基于主流的开源技术栈,实现一个可稳定运行、支持数据检索与公开的档案管理系统。
系统采用前后端分离架构,确保高可维护性。
以Ubuntu 22.04 LTS系统为例,进行基础环境配置。
更新系统并安装必要的系统工具:
``` sudo apt update && sudo apt upgrade -y sudo apt install -y curl wget git vim python3-pip python3-venv nginx ```安装并启动PostgreSQL数据库:
``` sudo apt install -y postgresql postgresql-contrib sudo systemctl start postgresql sudo systemctl enable postgresql ```创建数据库及用户:
``` sudo -u postgres psql -c "CREATE DATABASE archive_db;" sudo -u postgres psql -c "CREATE USER archive_user WITH PASSWORD 'YourStrongPassword123!';" sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE archive_db TO archive_user;" ```安装Elasticsearch(使用官方APT仓库):
``` wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list sudo apt update && sudo apt install -y elasticsearch sudo systemctl start elasticsearch sudo systemctl enable elasticsearch ```为项目创建独立的Python虚拟环境:
``` mkdir -p /opt/archive_project && cd /opt/archive_project python3 -m venv venv source venv/bin/activate ```安装Python依赖包:
``` pip install django==4.2 django-rest-framework psycopg2-binary django-elasticsearch-dsl django-cors-headers ```创建Django项目与应用:
``` django-admin startproject archive_backend . python manage.py startapp archive_core ```编辑 /opt/archive_project/archive_backend/settings.py 文件,关键配置如下:
``` 数据库配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'archive_db', 'USER': 'archive_user', 'PASSWORD': 'YourStrongPassword123!', 'HOST': 'localhost', 'PORT': '5432', } } Elasticsearch配置 ELASTICSEARCH_DSL = { 'default': { 'hosts': 'localhost:9200' }, } 静态文件与媒体文件路径 STATIC_URL = '/static/' STATIC_ROOT = '/var/www/archive/static/' MEDIA_URL = '/media/' MEDIA_ROOT = '/var/www/archive/media/' 安全设置(上线前必须修改) SECRET_KEY = 'django-insecure-your-very-long-secret-key-here-change-this' DEBUG = False ALLOWED_HOSTS = ['your-domain.com', 'server_ip_address'] 允许前端跨域请求 CORS_ALLOWED_ORIGINS = [ "http://localhost:8080", "https://your-domain.com", ] ```在 /opt/archive_project/archive_core/models.py 中定义档案核心模型:
``` from django.db import models class ArchiveCategory(models.Model): name = models.CharField(max_length=100, unique=True) code = models.CharField(max_length=20, unique=True) class PublicArchive(models.Model): STATUS_CHOICES = ( ('draft', '草稿'), ('reviewed', '已审核'), ('published', '已公开'), ) title = models.CharField(max_length=200) archive_number = models.CharField(max_length=50, unique=True) category = models.ForeignKey(ArchiveCategory, on_delete=models.PROTECT) content = models.TextField() attachment = models.FileField(upload_to='archive_files/%Y/%m/', blank=True) publish_date = models.DateField() is_public = models.BooleanField(default=False) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.title ```在 /opt/archive_project/archive_core/documents.py 中定义Elasticsearch搜索索引:
``` from django_elasticsearch_dsl import Document, fields from django_elasticsearch_dsl.registries import registry from .models import PublicArchive @registry.register_document class PublicArchiveDocument(Document): category = fields.TextField(attr='category.name') class Index: name = 'public_archives' settings = {'number_of_shards': 1, 'number_of_replicas': 0} class Django: model = PublicArchive fields = ['id', 'title', 'archive_number', 'content', 'publish_date', 'is_public'] ```执行数据库迁移并创建搜索索引:
``` python manage.py makemigrations python manage.py migrate python manage.py search_index --rebuild ```在服务器或本地开发机创建前端项目:
``` cd /opt npm create vue@latest archive_frontend 项目创建过程中,手动选择需要的功能:TypeScript, Router, Pinia cd archive_frontend npm install element-plus axios npm install ```创建档案列表页面组件 src/views/ArchiveList.vue:
```配置Vue Router,并将此组件映射到根路径。

在Django应用中创建 /opt/archive_project/archive_core/serializers.py:
``` from rest_framework import serializers from .models import PublicArchive, ArchiveCategory class ArchiveCategorySerializer(serializers.ModelSerializer): class Meta: model = ArchiveCategory fields = ['id', 'name', 'code'] class PublicArchiveSerializer(serializers.ModelSerializer): category = ArchiveCategorySerializer(read_only=True) class Meta: model = PublicArchive fields = ['id', 'title', 'archive_number', 'category', 'content', 'attachment', 'publish_date', 'is_public', 'created_at'] ```创建API视图 /opt/archive_project/archive_core/views.py:
``` from rest_framework import generics, filters from django_filters.rest_framework import DjangoFilterBackend from .models import PublicArchive from .serializers import PublicArchiveSerializer from .documents import PublicArchiveDocument from elasticsearch_dsl import Q class PublicArchiveListAPIView(generics.ListAPIView): serializer_class = PublicArchiveSerializer filter_backends = [DjangoFilterBackend, filters.SearchFilter] filterset_fields = ['category'] search_fields = ['title', 'content'] def get_queryset(self): queryset = PublicArchive.objects.filter(is_public=True, status='published') 处理Elasticsearch全文检索 search_query = self.request.query_params.get('search', None) if search_query: es_query = Q('multi_match', query=search_query, fields=['title', 'content']) search = PublicArchiveDocument.search().query(es_query) response = search.execute() archive_ids = [hit.id for hit in response] queryset = queryset.filter(id__in=archive_ids) return queryset.order_by('-publish_date') ```在 /opt/archive_project/archive_core/urls.py 中:
``` from django.urls import path from . import views urlpatterns = [ path('archives/', views.PublicArchiveListAPIView.as_view(), name='archive-list'), ] ```在项目主URL文件 archive_backend/urls.py 中引入:
``` from django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('archive_core.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ```在虚拟环境中安装Gunicorn:
``` pip install gunicorn ```创建Gunicorn系统服务文件 /etc/systemd/system/gunicorn_archive.service:
``` [Unit] Description=Gunicorn instance for Archive Project After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/opt/archive_project Environment="PATH=/opt/archive_project/venv/bin" ExecStart=/opt/archive_project/venv/bin/gunicorn --workers 3 --bind unix:/opt/archive_project/archive.sock archive_backend.wsgi:application [Install] WantedBy=multi-user.target ```启动并启用服务:
``` sudo systemctl start gunicorn_archive sudo systemctl enable gunicorn_archive ```创建Nginx站点配置文件 /etc/nginx/sites-available/archive:
``` server { listen 80; server_name your-domain.com www.your-domain.com; location / { root /opt/archive_frontend/dist; try_files $uri $uri/ /index.html; } location /api { include proxy_params; proxy_pass http://unix:/opt/archive_project/archive.sock; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; } location /media { alias /var/www/archive/media; expires 30d; } location /static { alias /var/www/archive/static; expires 365d; } } ```启用站点并重启Nginx:
``` sudo ln -s /etc/nginx/sites-available/archive /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx ```构建Vue生产版本:
``` cd /opt/archive_frontend npm run build ```将构建产物复制到Nginx配置的目录:
``` sudo cp -r dist/ /var/www/archive/ ```首先创建超级管理员账户:
``` python manage.py createsuperuser ```登录 http://your-domain.com/admin,在“档案核心”部分可以手动添加数据。
对于批量导入,创建数据导入脚本 import_archives.py:
``` import os import django import pandas as pd os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'archive_backend.settings') django.setup() from archive_core.models import PublicArchive, ArchiveCategory def import_from_csv(file_path): df = pd.read_csv(file_path) for _, row in df.iterrows(): 获取或创建分类 category, _ = ArchiveCategory.objects.get_or_create( name=row['category_name'], defaults={'code': row['category_code']} ) 创建档案记录 PublicArchive.objects.create( title=row['title'], archive_number=row['archive_number'], category=category, content=row['content'], publish_date=row['publish_date'], is_public=True, status='published' ) print(f"成功导入 {len(df)} 条记录") if __name__ == '__main__': import_from_csv('archives_data.csv') ```设置定时任务,每天凌晨同步数据到Elasticsearch:
创建脚本 /opt/archive_project/maintain_search_index.py:
``` from django.core.management import call_command if __name__ == '__main__': call_command('search_index', '--rebuild') ```添加Crontab任务:
``` crontab -e 添加以下行 0 2 cd /opt/archive_project && /opt/archive_project/venv/bin/python maintain_search_index.py >> /var/log/archive_index.log 2>&1 ```至此,一个完整的档案公开平台已部署完成。通过访问域名,用户可检索、查看公开档案。管理员可通过后台管理系统进行数据维护与发布。