房地产行业数字档案馆系统:从零搭建到实战部署全指南

一、 系统架构与核心技术选型

一个稳定、可扩展的数字档案馆系统,其技术栈的选型至关重要。本系统采用前后端分离的微服务架构,确保高内聚、低耦合,便于后期维护与扩展。

1.1 后端技术栈

后端采用Spring Boot + MyBatis-Plus框架,数据库使用MySQL 8.0,全文检索与文档分析使用Elasticsearch 7.x,文件存储使用MinIO(兼容S3协议的对象存储)。

  • Spring Boot 2.7.x:提供快速启动和自动配置。
  • MyBatis-Plus 3.5.x:简化数据库操作,内置分页、代码生成器等实用功能。
  • MySQL 8.0:存储结构化数据,如档案元数据、用户信息、系统日志。
  • Elasticsearch 7.17.x:用于档案内容的全文检索、智能分类和数据分析。
  • MinIO:存储非结构化的档案文件(如扫描件、图片、视频),替代传统FTP或本地磁盘存储。

1.2 前端技术栈

前端使用Vue 3 + Element Plus,构建现代化、响应式的管理界面。

  • Vue 3 (Composition API):提供更好的逻辑复用和类型推断。
  • Element Plus:基于Vue 3的UI组件库,快速搭建后台界面。
  • Axios:处理HTTP请求。

二、 环境准备与基础服务部署

在开始编码前,需要先部署好所有依赖的中间件服务。请确保服务器(或本地开发机)已安装Docker和Docker Compose,这将极大简化部署过程。

2.1 使用Docker Compose一键启动基础服务

在服务器上创建一个名为docker-compose.yml的文件,内容如下:

```yaml version: '3.8' services: mysql: image: mysql:8.0 container_name: archive-mysql environment: MYSQL_ROOT_PASSWORD: YourStrongPassword123! MYSQL_DATABASE: digital_archive ports: - "3306:3306" volumes: - ./mysql_data:/var/lib/mysql command: --default-authentication-plugin=mysql_native_password elasticsearch: image: elasticsearch:7.17.9 container_name: archive-es environment: - discovery.type=single-node - ES_JAVA_OPTS=-Xms512m -Xmx512m - xpack.security.enabled=false ports: - "9200:9200" volumes: - ./es_data:/usr/share/elasticsearch/data minio: image: minio/minio container_name: archive-minio ports: - "9000:9000" - "9001:9001" environment: MINIO_ROOT_USER: admin MINIO_ROOT_PASSWORD: YourMinioPassword123! volumes: - ./minio_data:/data command: server /data --console-address ":9001" ```

保存文件后,在终端执行以下命令启动所有服务:

``` docker-compose up -d ```

执行docker ps命令检查三个容器(mysql, elasticsearch, minio)是否正常运行。

2.2 初始化MinIO存储桶

浏览器访问 http://你的服务器IP:9001,使用上面配置的用户名admin和密码YourMinioPassword123!登录MinIO管理控制台。

  1. 点击左侧菜单“Buckets”
  2. 点击“Create Bucket”按钮。
  3. 输入Bucket名称:real-estate-archive,点击创建。

三、 后端核心模块开发

我们将创建一个Spring Boot项目,并实现档案上传、元数据管理、全文检索三个核心模块。

3.1 项目初始化与依赖配置

使用Spring Initializr(https://start.spring.io)生成项目,依赖选择:Spring Web, MyBatis Framework, MySQL Driver, Lombok。

在生成的pom.xml中,手动添加以下依赖:

```xml com.baomidou mybatis-plus-boot-starter 3.5.3.1 io.minio minio 8.5.2 org.elasticsearch.client elasticsearch-rest-high-level-client 7.17.9 ```

3.2 配置文件

application.yml中配置所有连接信息:

```yaml server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/digital_archive?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: YourStrongPassword123! driver-class-name: com.mysql.cj.jdbc.Driver minio: endpoint: http://localhost:9000 accessKey: admin secretKey: YourMinioPassword123! bucketName: real-estate-archive elasticsearch: host: localhost port: 9200 ```

3.3 实现档案文件上传与存储

创建MinioService,封装文件上传、下载、删除等操作。

```java @Service public class MinioService { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.bucketName}") private String bucketName; private MinioClient minioClient; @PostConstruct public void init() { this.minioClient = MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } public String uploadFile(MultipartFile file, String objectName) throws Exception { // 检查存储桶是否存在,不存在则创建 boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } // 上传文件 minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build()); // 返回文件访问URL(生产环境需配置为域名或通过网关) return endpoint + "/" + bucketName + "/" + objectName; } } ```

创建ArchiveController,接收前端上传的档案文件,并调用MinioService保存。

```java @RestController @RequestMapping("/api/archive") public class ArchiveController { @Autowired private MinioService minioService; @Autowired private ArchiveService archiveService; @PostMapping("/upload") public ApiResult uploadArchive(@RequestParam("file") MultipartFile file, @RequestParam String projectName, @RequestParam String archiveType) throws Exception { // 1. 生成唯一文件名,防止覆盖 String originalFilename = file.getOriginalFilename(); String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")); String objectName = UUID.randomUUID().toString() + fileExtension; // 2. 上传到MinIO String fileUrl = minioService.uploadFile(file, objectName); // 3. 保存档案元数据到MySQL ArchiveEntity archive = new ArchiveEntity(); archive.setProjectName(projectName); archive.setArchiveType(archiveType); archive.setFileName(originalFilename); archive.setFileUrl(fileUrl); archive.setFileSize(file.getSize()); archiveService.save(archive); // 4. 异步提取文本内容并存入Elasticsearch(针对PDF、Word等) archiveService.asyncIndexContent(archive.getId(), file); return ApiResult.success("档案上传成功", archive.getId()); } } ```

3.4 实现档案全文检索

房地产行业数字档案馆系统:从零搭建到实战部署全指南

创建ElasticsearchService,用于将档案的文本内容(通过OCR或文档解析获得)索引到Elasticsearch。

```java @Service public class ElasticsearchService { private RestHighLevelClient client; @Value("${elasticsearch.host}") private String host; @Value("${elasticsearch.port}") private int port; @PostConstruct public void init() { client = new RestHighLevelClient( RestClient.builder(new HttpHost(host, port, "http")) ); } public void indexDocument(Long archiveId, String content, String projectName) throws IOException { IndexRequest request = new IndexRequest("archive_docs"); Map jsonMap = new HashMap<>(); jsonMap.put("id", archiveId); jsonMap.put("content", content); jsonMap.put("projectName", projectName); jsonMap.put("timestamp", new Date()); request.id(archiveId.toString()).source(jsonMap); client.index(request, RequestOptions.DEFAULT); } public List search(String keyword) throws IOException { SearchRequest searchRequest = new SearchRequest("archive_docs"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 使用match query进行全文检索,匹配content字段 sourceBuilder.query(QueryBuilders.matchQuery("content", keyword)); searchRequest.source(sourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); List resultIds = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { resultIds.add(Long.valueOf(hit.getId())); } return resultIds; } } ```

ArchiveService中,调用Tika等库解析上传的文档(如PDF、Word),提取纯文本,然后调用ElasticsearchService.indexDocument方法建立索引。

四、 前端管理界面开发

使用Vue CLI创建一个新项目,并安装Element Plus和Axios。

4.1 档案上传组件

创建ArchiveUpload.vue组件,提供表单用于上传档案。

```vue ```

4.2 档案检索组件

创建ArchiveSearch.vue组件,提供搜索框,调用后端检索接口并展示结果。

```vue ```

五、 系统部署与上线

开发完成后,需要将前后端应用部署到生产环境。

5.1 后端应用打包与部署

在后端项目根目录下,执行Maven打包命令:

``` mvn clean package -DskipTests ```

打包完成后,会在target目录下生成一个.jar文件。将其上传到服务器,使用以下命令启动:

``` nohup java -jar digital-archive-backend-1.0.0.jar --spring.profiles.active=prod > app.log 2>&1 & ```

注意:你需要创建一个application-prod.yml配置文件,将其中数据库、MinIO、Elasticsearch的连接地址改为生产服务器的内网IP或域名,切勿使用localhost

5.2 前端应用构建与部署

在前端项目根目录下,安装依赖并构建生产环境代码:

``` npm install npm run build ```

构建完成后,将dist目录下的所有文件,复制到Nginx或Apache的Web服务器目录下(例如/usr/share/nginx/html)。

配置Nginx,将API请求代理到后端服务:

``` server { listen 80; server_name your-domain.com; 你的域名 location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://localhost:8080; 后端服务地址 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ```

重启Nginx服务使配置生效:

``` sudo systemctl restart nginx ```

六、 关键问题排查与优化

6.1 文件上传失败

检查MinIO服务是否正常运行,网络是否通畅。检查后端应用的application-prod.yml中MinIO的endpoint配置是否正确(应为内网地址或可解析的域名)。检查服务器防火墙是否开放了MinIO的端口(默认9000)。

6.2 全文检索无结果

首先检查Elasticsearch服务状态,访问http://服务器IP:9200查看是否返回版本信息。然后检查后端日志,查看文档解析和索引过程是否报错。确保上传的文档(如PDF)不是扫描

AI咨询
热线电话

028-85154420

15388110056

全国售前咨询电话

扫码咨询
安答联动微信公众号二维码

微信扫码关注安答联动

申请试用
热线电话
申请试用

安答联动档案管理系统