karword项目开发日志

该程序是一个卡片式树的综合多人辅助开发平台,内置功能,可视为迷你飞书

项目概述

开发一个面向团队的知识管理协作平台,核心功能包括:

  • 卡片式文档管理系统
  • 可视化图表编辑(流程图/结构图/甘特图)
  • 实时团队协作
  • 集成通讯功能

技术架构

前端技术栈

模块 技术选型 备注
框架 React 18 + TypeScript 使用Vite构建工具
状态管理 Redux Toolkit 配合RTK Query处理API
UI组件库 Ant Design 5.x 企业级UI组件
富文本编辑器 Tiptap 基于ProseMirror的现代编辑器
图表渲染 Mermaid + ECharts Mermaid用于流程图/时序图
实时协作 Socket.IO Client 与后端WebSocket通信
拖拽交互 react-dnd 卡片和图表元素拖拽

后端技术栈

模块 技术选型 备注
主框架 Spring Boot 3.x Java 17+
数据库 PostgreSQL 15 关系型数据库
ORM Spring Data JPA 配合Hibernate
缓存 Redis 7 会话缓存和频繁访问数据
实时通讯 WebSocket (STOMP) 通过Spring Messaging实现
文件存储 MinIO 自托管对象存储
搜索 Elasticsearch 8.x 全文检索功能
安全 Spring Security + JWT OAuth2.0备用方案

以上为明确使用的技术栈,本篇日志为第一部分,暨搭建Karwork项目的基础框架,包括Spring Boot后端和React前端。

整体过程可以视为
Spring Boot后端搭建–>React前端搭建–>前后端连接(本项目不提前连接)

Spring Boot后端搭建

1. 创建Spring Boot项目

  1. 打开IntelliJ IDEA,点击”New Project”
  2. 选择”Spring Initializr”
  3. 配置项目信息:
    • Name: karwork-backend
    • Location: 选择你的项目目录
    • Type: Maven
    • Language: Java
    • Group: com.karwork
    • Artifact: karwork-backend
    • Package name: com.karwork
    • Java: 选择17或更高版本

以上的是可选条目,告知详细操作过程

2. 添加依赖

选择以下依赖:

  • Spring Web
  • Spring Data JPA
  • PostgreSQL Driver
  • Lombok
  • Spring Security
  • Spring Boot DevTools

点击”Create”完成项目创建。

3. 配置数据库

数据库需要提前配置,注意以下字段的’password=yourpassword’和’username=postgres’字段更改,检查5432端口是否被占用

我会标记出所在项目的文件夹位置,帮助项目构建

  1. src/main/resources/application.properties中添加:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 开发环境配置
    spring.datasource.url=jdbc:postgresql://localhost:5432/karwork
    spring.datasource.username=postgres
    spring.datasource.password=yourpassword
    spring.datasource.driver-class-name=org.postgresql.Driver

    # JPA配置
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.format_sql=true

    # 开发时关闭安全验证
    spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

4. 创建基础包结构

src/main/java/com/karwork下创建以下包:

  • config
  • controller
  • service
  • repository
  • model
  • dto
  • exception
  • websocket

以上均为文件名,自行创建,也可以使用指令创建

5. 创建基础实体类

model包中创建User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.karwork.model;

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.GenericGenerator;

import java.time.LocalDateTime;
import java.util.UUID;

@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
@Column(updatable = false, nullable = false)
private UUID userId;

@Column(nullable = false, unique = true)
private String username;

@Column(nullable = false, unique = true)
private String email;

@Column(nullable = false)
private String passwordHash;

@Column(nullable = false, updatable = false)
private LocalDateTime createdAt = LocalDateTime.now();
}

6. 创建Repository接口

repository包中创建UserRepository.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.karwork.repository;

import com.karwork.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;
import java.util.UUID;

@Repository
public interface UserRepository extends JpaRepository<User, UUID> {
Optional<User> findByUsername(String username);
Optional<User> findByEmail(String email);
}

7. 创建基础Controller

controller包中创建AuthController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.karwork.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/auth")
public class AuthController {

@GetMapping("/status")
public String status() {
return "Auth service is running";
}
}

8. 运行项目

  1. 确保PostgreSQL已安装并运行
  2. 创建名为karwork的数据库
  3. 右键点击KarworkBackendApplication.java -> Run
  4. 访问http://localhost:8080/api/auth/status测试

React前端搭建

1. 创建React项目

  1. 打开终端,导航到你的项目目录
  2. 运行命令:
    1
    2
    3
    npm create vite@latest karwork-frontend -- --template react-ts
    cd karwork-frontend
    npm install

2. 安装必要依赖

1
2
npm install @reduxjs/toolkit react-redux axios antd @ant-design/icons react-router-dom socket.io-client react-dnd react-dnd-html5-backend
npm install --save-dev @types/react @types/react-dom @types/react-router-dom

3. 配置项目结构

按照以下结构组织你的前端项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
karwork-frontend/
├── public/
├── src/
│ ├── api/
│ ├── assets/
│ ├── components/
│ ├── features/
│ │ ├── auth/
│ │ ├── editor/
│ │ ├── diagram/
│ │ └── chat/
│ ├── hooks/
│ ├── stores/
│ ├── types/
│ ├── utils/
│ ├── App.tsx
│ ├── main.tsx
│ └── vite-env.d.ts

4. 创建基础Redux Store

stores文件夹中创建store.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { configureStore } from '@reduxjs/toolkit';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';

export const store = configureStore({
reducer: {
// 这里添加你的reducer
},
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

5. 创建基础布局

components文件夹中创建Layout.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { Layout as AntdLayout, Menu } from 'antd';
import { Outlet } from 'react-router-dom';

const { Header, Content } = AntdLayout;

export const Layout = () => {
return (
<AntdLayout style={{ minHeight: '100vh' }}>
<Header>
<div style={{ color: 'white' }}>Karwork</div>
</Header>
<Content style={{ padding: '24px' }}>
<Outlet />
</Content>
</AntdLayout>
);
};

6. 配置路由

修改App.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { Layout } from './components/Layout';
import { HomePage } from './features/auth/HomePage';

function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<HomePage />} />
</Route>
</Routes>
</BrowserRouter>
);
}

export default App;

7. 创建首页

features/auth中创建HomePage.tsx

1
2
3
4
5
6
7
export const HomePage = () => {
return (
<div>
<h1>Welcome to Karwork</h1>
</div>
);
};

8. 配置API客户端

api文件夹中创建client.ts

1
2
3
4
5
6
import axios from 'axios';

export const apiClient = axios.create({
baseURL: 'http://localhost:8080/api',
withCredentials: true,
});

9. 运行前端项目

1
npm run dev

访问http://localhost:5173测试

到此为止基本已完成前后端的框架构建,以下是可能遇见的问题

1.时刻校验准备项目结构清单

这是项目标准化的重要工作,这个项目本身就是在简化这个过程,一定时刻确认项目结构清单

2.清理依赖,用到的时候再启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<dependencies>
<!-- Web核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 数据访问(保留JPA或MyBatis任选其一) -->
<!-- 选项1:使用JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- 选项2:使用MyBatis(注释掉JPA) -->
<!--
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
-->

<!-- 数据库驱动(只保留你实际使用的) -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 如果使用MySQL,注释掉PostgreSQL -->
<!--
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
-->

<!-- 开发工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

防止xml文件污染,适当截取

3.确认包扫描路径找到,必要时请使用标签标注

所遇到的问题,我之后会单独拉一个页面来展示