系统架构设计

项目管理系统架构
├── 前端 (Vue 3 + Element Plus)
│   ├── 项目列表与详情
│   ├── 任务看板
│   ├── 团队管理
│   └── 数据统计
├── 后端 (Spring Boot 2.7+)
│   ├── 用户认证模块
│   ├── 项目管理模块
│   ├── 任务管理模块
│   └── 团队管理模块
└── 数据库 (MySQL 8.0)
    ├── 用户表
    ├── 项目表
    ├── 任务表
    └── 团队表

后端实现 (Spring Boot)

1. 项目结构与依赖

首先使用Spring Initializr创建项目,主要依赖:

  • Spring Web
  • Spring Data JPA
  • MySQL Driver
  • Spring Security
  • JJWT (JSON Web Token)

2. 数据库设计

使用AI工具生成数据库SQL脚本:

CREATE DATABASE project_management;
USE project_management;

-- 用户表
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    display_name VARCHAR(100),
    role ENUM('ADMIN', 'MANAGER', 'MEMBER') DEFAULT 'MEMBER',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 项目表
CREATE TABLE projects (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    description TEXT,
    status ENUM('PLANNING', 'IN_PROGRESS', 'ON_HOLD', 'COMPLETED') DEFAULT 'PLANNING',
    start_date DATE,
    end_date DATE,
    owner_id BIGINT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (owner_id) REFERENCES users(id)
);

-- 任务表
CREATE TABLE tasks (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    description TEXT,
    status ENUM('TODO', 'IN_PROGRESS', 'REVIEW', 'DONE') DEFAULT 'TODO',
    priority ENUM('LOW', 'MEDIUM', 'HIGH') DEFAULT 'MEDIUM',
    assignee_id BIGINT,
    project_id BIGINT NOT NULL,
    due_date DATE,
    estimated_hours INT,
    actual_hours INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (assignee_id) REFERENCES users(id),
    FOREIGN KEY (project_id) REFERENCES projects(id)
);

-- 项目成员关联表
CREATE TABLE project_members (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    project_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    role ENUM('OWNER', 'MANAGER', 'MEMBER') DEFAULT 'MEMBER',
    joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (project_id) REFERENCES projects(id),
    FOREIGN KEY (user_id) REFERENCES users(id),
    UNIQUE KEY unique_member (project_id, user_id)
);

3. 核心Java实体类

使用AI工具生成JPA实体类:

// User实体
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String username;
    
    @Column(nullable = false)
    private String password;
    
    @Column(nullable = false, unique = true)
    private String email;
    
    private String displayName;
    
    @Enumerated(EnumType.STRING)
    private UserRole role = UserRole.MEMBER;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
    
    public enum UserRole {
        ADMIN, MANAGER, MEMBER
    }
}

// Project实体
@Entity
@Table(name = "projects")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Project {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String name;
    
    private String description;
    
    @Enumerated(EnumType.STRING)
    private ProjectStatus status = ProjectStatus.PLANNING;
    
    private LocalDate startDate;
    private LocalDate endDate;
    
    @ManyToOne
    @JoinColumn(name = "owner_id", nullable = false)
    private User owner;
    
    @OneToMany(mappedBy = "project", cascade = CascadeType.ALL)
    private List<Task> tasks = new ArrayList<>();
    
    @OneToMany(mappedBy = "project", cascade = CascadeType.ALL)
    private List<ProjectMember> members = new ArrayList<>();
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
    
    public enum ProjectStatus {
        PLANNING, IN_PROGRESS, ON_HOLD, COMPLETED
    }
}

4. Spring Security配置

使用AI工具生成JWT认证配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .antMatchers("/api/projects/**").authenticated()
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        
        return http.build();
    }
    
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

5. RESTful API控制器

使用AI工具生成Project控制器:

@RestController
@RequestMapping("/api/projects")
public class ProjectController {
    
    @Autowired
    private ProjectService projectService;
    
    @GetMapping
    public ResponseEntity<List<ProjectDTO>> getUserProjects(
            @AuthenticationPrincipal User user,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        Page<ProjectDTO> projects = projectService.getUserProjects(user, page, size);
        return ResponseEntity.ok()
                .header("X-Total-Count", String.valueOf(projects.getTotalElements()))
                .body(projects.getContent());
    }
    
    @PostMapping
    public ResponseEntity<ProjectDTO> createProject(
            @RequestBody ProjectRequest request,
            @AuthenticationPrincipal User user) {
        ProjectDTO project = projectService.createProject(request, user);
        return ResponseEntity.status(HttpStatus.CREATED).body(project);
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<ProjectDTO> getProject(
            @PathVariable Long id,
            @AuthenticationPrincipal User user) {
        ProjectDTO project = projectService.getProject(id, user);
        return ResponseEntity.ok(project);
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<ProjectDTO> updateProject(
            @PathVariable Long id,
            @RequestBody ProjectRequest request,
            @AuthenticationPrincipal User user) {
        ProjectDTO project = projectService.updateProject(id, request, user);
        return ResponseEntity.ok(project);
    }
    
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteProject(
            @PathVariable Long id,
            @AuthenticationPrincipal User user) {
        projectService.deleteProject(id, user);
        return ResponseEntity.noContent().build();
    }
}

前端实现 (Vue 3)

1. 项目初始化与依赖

使用Vue CLI创建项目并安装依赖:

vue create project-management-frontend
cd project-management-frontend
npm install axios vue-router vuex element-plus

2. 路由配置

使用AI工具生成Vue Router配置:

import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
import Dashboard from '../views/Dashboard.vue'
import Projects from '../views/Projects.vue'
import ProjectDetail from '../views/ProjectDetail.vue'

const routes = [
  {
    path: '/',
    redirect: '/dashboard'
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: Dashboard,
    meta: { requiresAuth: true }
  },
  {
    path: '/projects',
    name: 'Projects',
    component: Projects,
    meta: { requiresAuth: true }
  },
  {
    path: '/projects/:id',
    name: 'ProjectDetail',
    component: ProjectDetail,
    meta: { requiresAuth: true }
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

// 导航守卫
router.beforeEach((to, from, next) => {
  const isAuthenticated = localStorage.getItem('authToken')
  
  if (to.meta.requiresAuth && !isAuthenticated) {
    next('/login')
  } else if (to.name === 'Login' && isAuthenticated) {
    next('/dashboard')
  } else {
    next()
  }
})

export default router

3. Vuex状态管理

使用AI工具生成Vuex store:

import { createStore } from 'vuex'
import axios from 'axios'

const API_BASE_URL = 'http://localhost:8080/api'

export default createStore({
  state: {
    user: null,
    token: localStorage.getItem('authToken') || null,
    projects: []
  },
  mutations: {
    setUser(state, user) {
      state.user = user
    },
    setToken(state, token) {
      state.token = token
      if (token) {
        localStorage.setItem('authToken', token)
        axios.defaults.headers.common['Authorization'] = `Bearer ${token}`
      } else {
        localStorage.removeItem('authToken')
        delete axios.defaults.headers.common['Authorization']
      }
    },
    setProjects(state, projects) {
      state.projects = projects
    },
    addProject(state, project) {
      state.projects.push(project)
    },
    updateProject(state, updatedProject) {
      const index = state.projects.findIndex(p => p.id === updatedProject.id)
      if (index !== -1) {
        state.projects.splice(index, 1, updatedProject)
      }
    }
  },
  actions: {
    async login({ commit }, credentials) {
      try {
        const response = await axios.post(`${API_BASE_URL}/auth/login`, credentials)
        commit('setToken', response.data.token)
        commit('setUser', response.data.user)
        return response.data
      } catch (error) {
        throw error.response.data
      }
    },
    async fetchProjects({ commit }) {
      try {
        const response = await axios.get(`${API_BASE_URL}/projects`)
        commit('setProjects', response.data)
        return response.data
      } catch (error) {
        throw error.response.data
      }
    },
    async createProject({ commit }, projectData) {
      try {
        const response = await axios.post(`${API_BASE_URL}/projects`, projectData)
        commit('addProject', response.data)
        return response.data
      } catch (error) {
        throw error.response.data
      }
    }
  },
  getters: {
    isAuthenticated: state => !!state.token,
    currentUser: state => state.user,
    allProjects: state => state.projects,
    projectById: state => id => state.projects.find(project => project.id === id)
  }
})

4. 项目列表组件

使用AI工具生成Projects.vue组件:

<template>
  <div class="projects-container">
    <div class="header">
      <h1>项目管理</h1>
      <el-button type="primary" @click="showCreateDialog = true">
        <i class="el-icon-plus"></i> 新建项目
      </el-button>
    </div>

    <el-table :data="projects" v-loading="loading">
      <el-table-column prop="name" label="项目名称" min-width="200">
        <template #default="scope">
          <router-link :to="`/projects/${scope.row.id}`" class="project-link">
            {{ scope.row.name }}
          </router-link>
        </template>
      </el-table-column>
      <el-table-column prop="status" label="状态" width="120">
        <template #default="scope">
          <el-tag :type="getStatusType(scope.row.status)">
            {{ getStatusText(scope.row.status) }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="startDate" label="开始日期" width="120">
        <template #default="scope">
          {{ formatDate(scope.row.startDate) }}
        </template>
      </el-table-column>
      <el-table-column prop="endDate" label="结束日期" width="120">
        <template #default="scope">
          {{ formatDate(scope.row.endDate) }}
        </template>
      </el-table-column>
      <el-table-column prop="owner.displayName" label="负责人" width="120"></el-table-column>
      <el-table-column label="操作" width="180">
        <template #default="scope">
          <el-button size="mini" @click="editProject(scope.row)">编辑</el-button>
          <el-button size="mini" type="danger" @click="deleteProject(scope.row.id)">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 创建项目对话框 -->
    <el-dialog title="新建项目" v-model="showCreateDialog" width="500px">
      <project-form 
        @submit="createProject" 
        @cancel="showCreateDialog = false">
      </project-form>
    </el-dialog>

    <!-- 编辑项目对话框 -->
    <el-dialog title="编辑项目" v-model="showEditDialog" width="500px">
      <project-form 
        :project="editingProject"
        @submit="updateProject" 
        @cancel="showEditDialog = false">
      </project-form>
    </el-dialog>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex'
import ProjectForm from '@/components/ProjectForm.vue'

export default {
  name: 'Projects',
  components: {
    ProjectForm
  },
  data() {
    return {
      loading: false,
      showCreateDialog: false,
      showEditDialog: false,
      editingProject: null
    }
  },
  computed: {
    ...mapState(['projects'])
  },
  async created() {
    this.loading = true
    try {
      await this.fetchProjects()
    } catch (error) {
      this.$message.error('获取项目列表失败')
    } finally {
      this.loading = false
    }
  },
  methods: {
    ...mapActions(['fetchProjects', 'createProject', 'updateProject', 'deleteProject']),
    getStatusType(status) {
      const statusMap = {
        'PLANNING': 'info',
        'IN_PROGRESS': 'primary',
        'ON_HOLD': 'warning',
        'COMPLETED': 'success'
      }
      return statusMap[status] || 'info'
    },
    getStatusText(status) {
      const statusTextMap = {
        'PLANNING': '规划中',
        'IN_PROGRESS': '进行中',
        'ON_HOLD': '已暂停',
        'COMPLETED': '已完成'
      }
      return statusTextMap[status] || status
    },
    formatDate(date) {
      if (!date) return '-'
      return new Date(date).toLocaleDateString()
    },
    editProject(project) {
      this.editingProject = { ...project }
      this.showEditDialog = true
    }
  }
}
</script>

<style scoped>
.projects-container {
  padding: 20px;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.project-link {
  color: #409EFF;
  text-decoration: none;
}

.project-link:hover {
  text-decoration: underline;
}
</style>

5. 项目表单组件

使用AI工具生成ProjectForm.vue组件:

<template>
  <el-form :model="form" :rules="rules" ref="projectForm" label-width="80px">
    <el-form-item label="项目名称" prop="name">
      <el-input v-model="form.name" placeholder="请输入项目名称"></el-input>
    </el-form-item>
    
    <el-form-item label="项目描述" prop="description">
      <el-input 
        type="textarea" 
        :rows="3" 
        v-model="form.description" 
        placeholder="请输入项目描述">
      </el-input>
    </el-form-item>
    
    <el-form-item label="状态" prop="status">
      <el-select v-model="form.status" placeholder="请选择状态">
        <el-option 
          v-for="status in statusOptions" 
          :key="status.value" 
          :label="status.label" 
          :value="status.value">
        </el-option>
      </el-select>
    </el-form-item>
    
    <el-form-item label="开始日期" prop="startDate">
      <el-date-picker 
        v-model="form.startDate" 
        type="date" 
        placeholder="选择开始日期">
      </el-date-picker>
    </el-form-item>
    
    <el-form-item label="结束日期" prop="endDate">
      <el-date-picker 
        v-model="form.endDate" 
        type="date" 
        placeholder="选择结束日期">
      </el-date-picker>
    </el-form-item>
    
    <el-form-item>
      <el-button type="primary" @click="submitForm">提交</el-button>
      <el-button @click="cancel">取消</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: 'ProjectForm',
  props: {
    project: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      form: {
        name: '',
        description: '',
        status: 'PLANNING',
        startDate: null,
        endDate: null
      },
      rules: {
        name: [
          { required: true, message: '请输入项目名称', trigger: 'blur' },
          { min: 2, max: 100, message: '长度在 2 到 100 个字符', trigger: 'blur' }
        ]
      },
      statusOptions: [
        { value: 'PLANNING', label: '规划中' },
        { value: 'IN_PROGRESS', label: '进行中' },
        { value: 'ON_HOLD', label: '已暂停' },
        { value: 'COMPLETED', label: '已完成' }
      ]
    }
  },
  watch: {
    project: {
      immediate: true,
      handler(newVal) {
        if (newVal) {
          this.form = { ...newVal }
        }
      }
    }
  },
  methods: {
    submitForm() {
      this.$refs.projectForm.validate((valid) => {
        if (valid) {
          this.$emit('submit', this.form)
        } else {
          return false
        }
      })
    },
    cancel() {
      this.$emit('cancel')
    }
  }
}
</script>

使用AI编程工具的提示词示例

在开发过程中,可以使用以下提示词来辅助AI编程工具生成代码:

  1. 生成数据库实体
    “使用Java Spring Boot创建一个Project实体类,包含id、名称、描述、状态、开始日期、结束日期、负责人等字段,使用JPA注解”

  2. 生成API控制器
    “创建一个Spring Boot REST控制器,实现项目的CRUD操作,包括分页查询和权限检查”

  3. 生成Vue组件
    “创建一个Vue 3组件,使用Element Plus显示项目列表表格,包含名称、状态、日期等列,并提供编辑和删除按钮”

  4. 生成表单验证
    “为项目创建表单添加验证规则,确保名称为必填且长度在2-100字符之间”

部署与运行

后端部署

  1. 配置MySQL数据库连接
  2. 使用Maven构建项目:mvn clean package
  3. 运行JAR文件:java -jar target/project-management.jar

前端部署

  1. 配置API基础URL
  2. 构建生产版本:npm run build
  3. 部署到Nginx或其它Web服务器

总结

通过使用AI编程工具,我们可以快速生成项目管理系统的基础代码框架。这个系统包含了用户认证、项目管理、任务管理等核心功能。AI工具帮助我们:

  1. 快速生成数据库设计和实体类
  2. 自动创建RESTful API控制器
  3. 生成前端Vue组件和状态管理代码
  4. 提供表单验证和用户界面设计

实际开发中,您可以根据具体需求进一步扩展功能,如添加文件上传、实时通知、甘特图视图、时间跟踪等高级功能。使用AI编程工具可以显著提高开发效率,减少重复性编码工作,让开发者更专注于业务逻辑和用户体验优化。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐