pangu-user-platform/docs/05-模块技术方案/学校管理/完整开发计划_Day3-Day7.md

27 KiB
Raw Permalink Blame History

学校管理模块 - 完整开发计划 (Day 3-7)


📋 项目概览

当前进度: 70% (后端95%完成)
剩余工作: 前端开发、数据权限、接口联调、测试验收
预计完成时间: Day 7 (2026-02-06)
**开发团队 | pangu


🎯 整体目标

完成学校管理模块的所有剩余开发任务,包括:

  1. 后端开发 (已完成95%)
  2. 前端开发 (0% → 100%)
  3. 数据权限 (0% → 100%)
  4. 接口联调 (0% → 100%)
  5. 测试验收 (20% → 100%)

📅 Day 3: 前端基础框架 (8小时)

任务清单

FE-SCH-01: 创建主页面框架 (2h)

目标文件:

  • frontend/src/views/school/index.vue

实现内容:

<template>
  <div class="school-management">
    <!-- 左侧区域树 -->
    <div class="left-panel">
      <RegionTree @node-click="handleRegionClick" />
    </div>
    
    <!-- 右侧学校树和操作 -->
    <div class="right-panel">
      <!-- 搜索栏 -->
      <div class="search-bar">
        <el-input placeholder="搜索学校" />
        <el-button type="primary">新增学校</el-button>
      </div>
      
      <!-- 学校树 -->
      <SchoolTree :region-id="selectedRegionId" />
    </div>
  </div>
</template>

验收标准:

  • 左右分栏布局完成
  • 响应式设计
  • 基础样式美观

FE-SCH-02: RegionTree组件 (2h)

目标文件:

  • frontend/src/components/school/RegionTree.vue

实现内容:

<template>
  <div class="region-tree">
    <el-tree
      :data="regionData"
      :props="treeProps"
      node-key="regionId"
      highlight-current
      @node-click="handleNodeClick"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      regionData: [],
      treeProps: {
        label: 'regionName',
        children: 'children'
      }
    }
  },
  mounted() {
    this.loadRegionTree()
  },
  methods: {
    async loadRegionTree() {
      // 调用区域树接口
      const res = await this.$api.region.getTree()
      this.regionData = res.data
    },
    handleNodeClick(node) {
      this.$emit('node-click', node.regionId)
    }
  }
}
</script>

验收标准:

  • 区域树正确展示
  • 节点点击事件触发
  • 高亮选中状态

FE-SCH-03: SchoolTree组件 (4h)

目标文件:

  • frontend/src/components/school/SchoolTree.vue

实现内容:

<template>
  <div class="school-tree">
    <el-table
      :data="treeData"
      row-key="id"
      :tree-props="{children: 'children'}"
      border
    >
      <el-table-column prop="name" label="名称" width="300" />
      <el-table-column prop="code" label="编码" width="150" />
      <el-table-column prop="type" label="类型" width="100">
        <template #default="scope">
          <el-tag v-if="scope.row.type === 'school'" type="primary">学校</el-tag>
          <el-tag v-else-if="scope.row.type === 'grade'" type="success">年级</el-tag>
          <el-tag v-else type="info">班级</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="status" label="状态" width="80">
        <template #default="scope">
          <el-tag v-if="scope.row.status === '0'" type="success">正常</el-tag>
          <el-tag v-else type="danger">停用</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="300" fixed="right">
        <template #default="scope">
          <!-- 学校操作 -->
          <template v-if="scope.row.type === 'school'">
            <el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button size="small" @click="handleBindGrade(scope.row)">挂载年级</el-button>
            <el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
          </template>
          
          <!-- 年级操作 -->
          <template v-else-if="scope.row.type === 'grade'">
            <el-button size="small" @click="handleBindClass(scope.row)">挂载班级</el-button>
            <el-button size="small" type="danger" @click="handleDeleteGrade(scope.row)">删除</el-button>
          </template>
          
          <!-- 班级操作 -->
          <template v-else>
            <el-button size="small" type="danger" @click="handleDeleteClass(scope.row)">删除</el-button>
          </template>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  props: {
    regionId: {
      type: Number,
      default: null
    }
  },
  data() {
    return {
      treeData: []
    }
  },
  watch: {
    regionId: {
      handler(val) {
        if (val) {
          this.loadSchoolTree()
        }
      },
      immediate: true
    }
  },
  methods: {
    async loadSchoolTree() {
      const res = await this.$api.school.getTree(this.regionId)
      this.treeData = res.data
    },
    handleEdit(row) {
      this.$emit('edit', row)
    },
    handleBindGrade(row) {
      this.$emit('bind-grade', row)
    },
    handleBindClass(row) {
      this.$emit('bind-class', row)
    },
    async handleDelete(row) {
      await this.$confirm('确认删除该学校吗?')
      await this.$api.school.delete(row.schoolId)
      this.$message.success('删除成功')
      this.loadSchoolTree()
    },
    async handleDeleteGrade(row) {
      await this.$confirm('确认删除该年级吗?')
      await this.$api.school.deleteGrade(row.schoolGradeId)
      this.$message.success('删除成功')
      this.loadSchoolTree()
    },
    async handleDeleteClass(row) {
      await this.$confirm('确认删除该班级吗?')
      await this.$api.school.deleteClass(row.schoolClassId)
      this.$message.success('删除成功')
      this.loadSchoolTree()
    }
  }
}
</script>

验收标准:

  • 树形表格正确展示
  • 三级树结构完整
  • 操作按钮功能正常
  • 删除操作有确认提示

📅 Day 4: 前端弹窗与API (8小时)

任务清单

FE-SCH-04: 学校编辑弹窗 (3h)

目标文件:

  • frontend/src/components/school/SchoolDialog.vue

实现内容:

<template>
  <el-dialog
    :title="isEdit ? '编辑学校' : '新增学校'"
    v-model="visible"
    width="600px"
  >
    <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
      <el-form-item label="学校名称" prop="schoolName">
        <el-input v-model="form.schoolName" placeholder="请输入学校名称" />
      </el-form-item>
      
      <el-form-item label="学校类型" prop="schoolType">
        <el-select v-model="form.schoolType" placeholder="请选择学校类型">
          <el-option label="小学" value="01" />
          <el-option label="初中" value="02" />
          <el-option label="高中" value="03" />
          <el-option label="完全中学" value="04" />
          <el-option label="其他" value="99" />
        </el-select>
      </el-form-item>
      
      <el-form-item label="所属区域" prop="regionId">
        <el-cascader
          v-model="form.regionId"
          :options="regionOptions"
          :props="cascaderProps"
          placeholder="请选择所属区域"
        />
      </el-form-item>
      
      <el-form-item label="详细地址" prop="address">
        <el-input v-model="form.address" type="textarea" />
      </el-form-item>
      
      <el-form-item label="联系人" prop="contactPerson">
        <el-input v-model="form.contactPerson" />
      </el-form-item>
      
      <el-form-item label="联系电话" prop="contactPhone">
        <el-input v-model="form.contactPhone" />
      </el-form-item>
      
      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="form.status">
          <el-radio label="0">正常</el-radio>
          <el-radio label="1">停用</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>
    
    <template #footer>
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="handleSubmit">确定</el-button>
    </template>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      visible: false,
      isEdit: false,
      form: {
        schoolName: '',
        schoolType: '',
        regionId: null,
        address: '',
        contactPerson: '',
        contactPhone: '',
        status: '0'
      },
      rules: {
        schoolName: [
          { required: true, message: '请输入学校名称', trigger: 'blur' }
        ],
        schoolType: [
          { required: true, message: '请选择学校类型', trigger: 'change' }
        ],
        regionId: [
          { required: true, message: '请选择所属区域', trigger: 'change' }
        ],
        contactPhone: [
          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
        ]
      },
      regionOptions: [],
      cascaderProps: {
        label: 'regionName',
        value: 'regionId',
        children: 'children'
      }
    }
  },
  methods: {
    open(row) {
      this.visible = true
      this.isEdit = !!row
      if (row) {
        this.form = { ...row }
      } else {
        this.resetForm()
      }
      this.loadRegionOptions()
    },
    async loadRegionOptions() {
      const res = await this.$api.region.getTree()
      this.regionOptions = res.data
    },
    resetForm() {
      this.form = {
        schoolName: '',
        schoolType: '',
        regionId: null,
        address: '',
        contactPerson: '',
        contactPhone: '',
        status: '0'
      }
    },
    async handleSubmit() {
      await this.$refs.formRef.validate()
      
      if (this.isEdit) {
        await this.$api.school.update(this.form)
        this.$message.success('修改成功')
      } else {
        await this.$api.school.create(this.form)
        this.$message.success('新增成功')
      }
      
      this.visible = false
      this.$emit('success')
    }
  }
}
</script>

验收标准:

  • 表单字段完整
  • 表单验证正确
  • 新增/编辑功能正常
  • 区域级联选择器正常

FE-SCH-05: 年级挂载弹窗 (2h)

目标文件:

  • frontend/src/components/school/BindGradeDialog.vue

实现内容:

<template>
  <el-dialog title="挂载年级" v-model="visible" width="500px">
    <el-checkbox-group v-model="selectedGrades">
      <el-checkbox
        v-for="grade in gradeList"
        :key="grade.gradeId"
        :label="grade.gradeId"
      >
        {{ grade.gradeName }}
      </el-checkbox>
    </el-checkbox-group>
    
    <template #footer>
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="handleSubmit">确定</el-button>
    </template>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      visible: false,
      schoolId: null,
      gradeList: [],
      selectedGrades: []
    }
  },
  methods: {
    async open(schoolId) {
      this.visible = true
      this.schoolId = schoolId
      await this.loadGradeList()
    },
    async loadGradeList() {
      const res = await this.$api.grade.getList()
      this.gradeList = res.data
    },
    async handleSubmit() {
      if (this.selectedGrades.length === 0) {
        this.$message.warning('请至少选择一个年级')
        return
      }
      
      await this.$api.school.bindGrades({
        schoolId: this.schoolId,
        gradeIds: this.selectedGrades
      })
      
      this.$message.success('挂载成功')
      this.visible = false
      this.$emit('success')
    }
  }
}
</script>

验收标准:

  • 年级列表正确展示
  • 多选功能正常
  • 挂载接口调用成功

FE-SCH-06: 班级挂载弹窗 (2h)

目标文件:

  • frontend/src/components/school/BindClassDialog.vue

实现内容:

<template>
  <el-dialog title="挂载班级" v-model="visible" width="500px">
    <el-checkbox-group v-model="selectedClasses">
      <el-checkbox
        v-for="cls in classList"
        :key="cls.classId"
        :label="cls.classId"
      >
        {{ cls.className }}
      </el-checkbox>
    </el-checkbox-group>
    
    <template #footer>
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="handleSubmit">确定</el-button>
    </template>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      visible: false,
      schoolGradeId: null,
      classList: [],
      selectedClasses: []
    }
  },
  methods: {
    async open(schoolGradeId) {
      this.visible = true
      this.schoolGradeId = schoolGradeId
      await this.loadClassList()
    },
    async loadClassList() {
      const res = await this.$api.class.getList()
      this.classList = res.data
    },
    async handleSubmit() {
      if (this.selectedClasses.length === 0) {
        this.$message.warning('请至少选择一个班级')
        return
      }
      
      await this.$api.school.bindClasses({
        schoolGradeId: this.schoolGradeId,
        classIds: this.selectedClasses
      })
      
      this.$message.success('挂载成功')
      this.visible = false
      this.$emit('success')
    }
  }
}
</script>

验收标准:

  • 班级列表正确展示
  • 多选功能正常
  • 挂载接口调用成功

FE-SCH-07: API封装 (1h)

目标文件:

  • frontend/src/api/school.js

实现内容:

import request from '@/utils/request'

export default {
  // 获取学校树
  getTree(regionId) {
    return request({
      url: '/api/school/tree',
      method: 'get',
      params: { regionId }
    })
  },
  
  // 获取学校列表(分页)
  getList(query) {
    return request({
      url: '/api/school/list',
      method: 'get',
      params: query
    })
  },
  
  // 获取学校详情
  getDetail(schoolId) {
    return request({
      url: `/api/school/${schoolId}`,
      method: 'get'
    })
  },
  
  // 新增学校
  create(data) {
    return request({
      url: '/api/school',
      method: 'post',
      data
    })
  },
  
  // 修改学校
  update(data) {
    return request({
      url: '/api/school',
      method: 'put',
      data
    })
  },
  
  // 删除学校
  delete(schoolId) {
    return request({
      url: `/api/school/${schoolId}`,
      method: 'delete'
    })
  },
  
  // 挂载年级
  bindGrades(data) {
    return request({
      url: '/api/school/bindGrades',
      method: 'post',
      data
    })
  },
  
  // 挂载班级
  bindClasses(data) {
    return request({
      url: '/api/school/bindClasses',
      method: 'post',
      data
    })
  },
  
  // 删除学校年级
  deleteGrade(schoolGradeId) {
    return request({
      url: `/api/school/grade/${schoolGradeId}`,
      method: 'delete'
    })
  },
  
  // 删除学校班级
  deleteClass(schoolClassId) {
    return request({
      url: `/api/school/class/${schoolClassId}`,
      method: 'delete'
    })
  }
}

验收标准:

  • 所有接口封装完成
  • 请求参数正确
  • 响应处理正确

📅 Day 5: 数据权限与联调 (8小时)

任务清单

BE-SCH-12: 数据权限控制 (3h)

目标: 实现分公司用户只能看到自己区域的学校数据

修改文件:

  • SchoolServiceImpl.java
  • SchoolMapper.xml

实现步骤:

  1. 在Service方法上添加@DataScope注解
@Override
@DataScope(deptAlias = "s", userAlias = "s")
public List<SchoolVO> selectSchoolList(SchoolQueryDTO query) {
    return schoolMapper.selectSchoolList(query);
}
  1. 在Mapper XML中添加数据权限SQL片段
<sql id="dataScopeFilter">
    <!-- 数据权限过滤 -->
    ${params.dataScope}
</sql>

<select id="selectSchoolList" resultMap="SchoolVOResult">
    <include refid="selectSchoolVo"/>
    <where>
        <if test="regionId != null">
            AND s.region_id = #{regionId}
        </if>
        <if test="schoolName != null and schoolName != ''">
            AND s.school_name LIKE CONCAT('%', #{schoolName}, '%')
        </if>
        <if test="status != null and status != ''">
            AND s.status = #{status}
        </if>
        <!-- 数据权限 -->
        <include refid="dataScopeFilter"/>
    </where>
    ORDER BY s.create_time DESC
</select>
  1. 配置用户-区域关联关系
-- 在用户表中关联区域ID
-- 或通过角色-区域关联表实现

验收标准:

  • 管理员可以看到所有学校
  • 分公司用户只能看到自己区域的学校
  • 数据权限不影响性能

BE-SCH-14: 接口联调与Bug修复 (3h)

测试清单:

  1. 学校CRUD测试

    • 新增学校
    • 修改学校
    • 删除学校
    • 查询学校列表
    • 查询学校详情
    • 查询学校树
  2. 年级挂载测试

    • 挂载年级
    • 重复挂载(去重)
    • 删除年级
    • 删除有班级的年级(应失败)
  3. 班级挂载测试

    • 挂载班级
    • 重复挂载(去重)
    • 删除班级
  4. 数据权限测试

    • 管理员权限
    • 分公司用户权限

Bug修复流程

  1. 记录Bug现象
  2. 定位Bug原因
  3. 修复Bug
  4. 回归测试
  5. 更新文档

验收标准:

  • 所有接口测试通过
  • 发现的Bug全部修复
  • 无遗留问题

FE-SCH-08: 主页面逻辑整合 (2h)

目标文件:

  • frontend/src/views/school/index.vue

实现内容:

<template>
  <div class="school-management">
    <div class="left-panel">
      <RegionTree @node-click="handleRegionClick" />
    </div>
    
    <div class="right-panel">
      <div class="search-bar">
        <el-input
          v-model="searchKeyword"
          placeholder="搜索学校"
          @keyup.enter="handleSearch"
        />
        <el-button type="primary" @click="handleAdd">新增学校</el-button>
      </div>
      
      <SchoolTree
        ref="schoolTree"
        :region-id="selectedRegionId"
        @edit="handleEdit"
        @bind-grade="handleBindGrade"
        @bind-class="handleBindClass"
      />
    </div>
    
    <!-- 弹窗 -->
    <SchoolDialog ref="schoolDialog" @success="refreshTree" />
    <BindGradeDialog ref="bindGradeDialog" @success="refreshTree" />
    <BindClassDialog ref="bindClassDialog" @success="refreshTree" />
  </div>
</template>

<script>
import RegionTree from '@/components/school/RegionTree.vue'
import SchoolTree from '@/components/school/SchoolTree.vue'
import SchoolDialog from '@/components/school/SchoolDialog.vue'
import BindGradeDialog from '@/components/school/BindGradeDialog.vue'
import BindClassDialog from '@/components/school/BindClassDialog.vue'

export default {
  components: {
    RegionTree,
    SchoolTree,
    SchoolDialog,
    BindGradeDialog,
    BindClassDialog
  },
  data() {
    return {
      selectedRegionId: null,
      searchKeyword: ''
    }
  },
  methods: {
    handleRegionClick(regionId) {
      this.selectedRegionId = regionId
    },
    handleAdd() {
      this.$refs.schoolDialog.open()
    },
    handleEdit(row) {
      this.$refs.schoolDialog.open(row)
    },
    handleBindGrade(row) {
      this.$refs.bindGradeDialog.open(row.schoolId)
    },
    handleBindClass(row) {
      this.$refs.bindClassDialog.open(row.schoolGradeId)
    },
    handleSearch() {
      this.$refs.schoolTree.search(this.searchKeyword)
    },
    refreshTree() {
      this.$refs.schoolTree.loadSchoolTree()
    }
  }
}
</script>

<style scoped>
.school-management {
  display: flex;
  height: calc(100vh - 120px);
}

.left-panel {
  width: 300px;
  border-right: 1px solid #dcdfe6;
  padding: 20px;
  overflow-y: auto;
}

.right-panel {
  flex: 1;
  padding: 20px;
  display: flex;
  flex-direction: column;
}

.search-bar {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.search-bar .el-input {
  flex: 1;
}
</style>

验收标准:

  • 所有组件正确集成
  • 事件传递正常
  • 页面交互流畅
  • 样式美观

📅 Day 6: 样式优化与测试 (8小时)

任务清单

FE-SCH-09: 样式优化 (3h)

优化内容:

  1. 响应式布局

    • 适配不同屏幕尺寸
    • 移动端友好
  2. 交互优化

    • 加载状态提示
    • 操作反馈动画
    • 错误提示优化
  3. 视觉优化

    • 统一配色方案
    • 图标美化
    • 间距调整

验收标准:

  • 页面美观大方
  • 交互流畅自然
  • 响应式效果良好

TEST-01: 接口测试 (2h)

测试工具: Postman

测试用例:

接口 方法 测试场景 预期结果
/api/school/tree GET 查询学校树 返回树形结构
/api/school/list GET 查询学校列表 返回分页数据
/api/school/{id} GET 查询学校详情 返回学校信息
/api/school POST 新增学校 返回成功
/api/school PUT 修改学校 返回成功
/api/school/{id} DELETE 删除学校 返回成功
/api/school/bindGrades POST 挂载年级 返回成功
/api/school/bindClasses POST 挂载班级 返回成功
/api/school/grade/{id} DELETE 删除年级 返回成功
/api/school/class/{id} DELETE 删除班级 返回成功

验收标准:

  • 所有接口测试通过
  • 响应时间 < 500ms
  • 错误处理正确

TEST-02: 功能测试 (2h)

测试场景:

  1. 学校管理流程

    • 新增学校 → 查看 → 编辑 → 删除
  2. 年级管理流程

    • 挂载年级 → 查看 → 删除
  3. 班级管理流程

    • 挂载班级 → 查看 → 删除
  4. 数据权限验证

    • 管理员登录 → 查看所有学校
    • 分公司用户登录 → 只看到自己区域
  5. 异常场景测试

    • 删除有子级的学校 → 提示错误
    • 重复挂载年级 → 自动去重
    • 必填项为空 → 提示错误

验收标准:

  • 所有功能正常
  • 异常处理正确
  • 用户体验良好

TEST-03: 集成测试 (1h)

测试内容:

  1. 前后端集成

    • 接口调用正常
    • 数据展示正确
    • 操作反馈及时
  2. 数据一致性

    • 新增后立即可见
    • 修改后立即更新
    • 删除后立即消失
  3. 性能测试

    • 页面加载时间 < 2s
    • 树形数据渲染流畅
    • 批量操作不卡顿

验收标准:

  • 集成测试全部通过
  • 性能指标达标
  • 无遗留问题

📅 Day 7: 文档完善与最终验收 (4小时)

任务清单

DOC-01: API文档生成 (1h)

工具: Swagger

内容:

  • 接口列表
  • 请求参数说明
  • 响应格式说明
  • 错误码说明

DOC-02: 用户手册 (1h)

目标文件:

  • docs/05-模块技术方案/学校管理/用户手册.md

内容:

  1. 功能介绍
  2. 操作指南
  3. 常见问题
  4. 注意事项

DOC-03: 开发总结报告 (1h)

目标文件:

  • docs/05-模块技术方案/学校管理/最终开发总结报告.md

内容:

  1. 项目概述
  2. 完成情况统计
  3. 技术亮点总结
  4. 遇到的问题与解决方案
  5. 经验教训
  6. 后续优化建议

FINAL: 最终验收准备 (1h)

准备内容:

  1. 代码检查

    • 代码编译通过
    • 无Lint错误
    • 注释完整
  2. 功能演示

    • 准备演示数据
    • 准备演示流程
    • 准备演示环境
  3. 文档整理

    • 所有文档齐全
    • 文档格式统一
    • 文档内容准确
  4. 交付清单

    • 源代码
    • 数据库脚本
    • 技术文档
    • 用户手册
    • 测试报告

📊 工时统计

阶段 任务数 计划工时 预计完成日期
Day 3 3 8h 2026-02-01
Day 4 4 8h 2026-02-02
Day 5 3 8h 2026-02-03
Day 6 3 8h 2026-02-04
Day 7 4 4h 2026-02-05
总计 17 36h -

累计工时含Day 1-2 16.4h + 36h = 52.4h
原计划工时: 53.5h
预计提前: 1.1h


🎯 验收标准

功能验收

  • 所有功能点实现完整
  • 业务流程正确
  • 数据权限生效
  • 异常处理完善

性能验收

  • 页面加载时间 < 2s
  • 接口响应时间 < 500ms
  • 树形数据渲染流畅
  • 批量操作不卡顿

质量验收

  • 代码编译通过
  • 单元测试通过
  • 集成测试通过
  • 代码规范符合标准
  • 注释完整清晰

文档验收

  • 技术方案文档完整
  • API文档齐全
  • 用户手册清晰
  • 测试报告详细

🚀 执行策略

开发顺序

Day 3: 前端框架 → 基础组件
Day 4: 弹窗组件 → API封装
Day 5: 数据权限 → 接口联调
Day 6: 样式优化 → 功能测试
Day 7: 文档完善 → 最终验收

质量保证

  1. 每日编译检查 - 确保代码无错误
  2. 每日功能测试 - 确保新功能正常
  3. 每日代码审查 - 确保代码质量
  4. 每日进度更新 - 确保进度可控

风险控制

风险 应对措施
前端组件开发延期 简化UI先实现核心功能
数据权限实现困难 参考现有模块,复用框架
接口联调发现Bug 预留缓冲时间,及时修复
性能不达标 优化SQL增加缓存

📞 沟通机制

进度汇报

  • 每日下班前 - 更新开发进度文档
  • 遇到阻塞 - 立即反馈
  • 完成里程碑 - 提交阶段性成果

问题升级

  • 技术问题 - 先自行研究30分钟未解决则求助
  • 需求问题 - 立即与产品确认
  • 环境问题 - 联系运维解决

最终交付物清单

代码

  • 后端代码Entity、Mapper、Service、Controller
  • 前端代码页面、组件、API
  • 单元测试代码

数据库

  • 建表SQL脚本
  • 初始化数据SQL
  • 索引优化SQL

文档

  • 技术方案文档
  • API接口文档
  • 用户操作手册
  • 开发总结报告
  • 测试报告

其他

  • 开发进度记录
  • Bug修复记录
  • 代码审查记录

🎊 预期成果

完成后,学校管理模块将具备:

  1. 完整的CRUD功能 - 学校、年级、班级的增删改查
  2. 灵活的树形展示 - 三级树形结构,清晰直观
  3. 严格的数据权限 - 分公司用户只能看自己的数据
  4. 完善的数据校验 - 多层校验,保证数据完整性
  5. 优秀的用户体验 - 界面美观,交互流畅
  6. 高质量的代码 - 规范、清晰、易维护
  7. 完整的测试覆盖 - 单元测试、集成测试全覆盖
  8. 齐全的文档资料 - 技术文档、用户手册一应俱全

🎯 目标7天内完成学校管理模块的完整开发交付高质量的产品


计划制定时间2026-01-31 22:00
计划执行时间2026-02-01 至 2026-02-05
制定人pangu