CSDN博文二:失物招领实训|本人负责模块完整代码实现(数据库脚本+登录注册页面+分类管理页面)

正文

前言

本项目为小组协作开发的失物招领管理系统,根据小组分工进度表,我(史安泰)独立负责三大模块工作:

  1. 数据库建表脚本编写、测试数据初始化;
  2. 后端物品分类管理模块完整接口开发;
  3. 前端登录页、注册页页面开发与调试;
    本篇结合本人负责内容,完整拆解数据库脚本、后端分类模块代码、前端登录注册页面逻辑,附带功能截图、代码逐行讲解,贴合实训分工要求。

一、我负责模块整体业务说明

  1. 数据库层:基于ER图编写完整MySQL建表语句,创建用户、失物、招领、物品分类四张数据表,插入测试账号、分类基础数据,为全项目提供数据支撑;
  2. 后端模块:物品分类管理CRUD接口,支持新增、删除、修改、分页查询分类,所有物品发布时可绑定对应分类;
  3. 前端页面:登录/注册双表单页面,完成账号校验、注册查重、登录态存储、路由跳转,对接用户登录认证后端接口。

第一部分:数据库建表脚本与测试数据初始化(本人负责任务2:基础搭建)

1. 数据库创建语句

-- 创建项目数据库
CREATE DATABASE lostfound_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE lostfound_db;

2. 四张核心数据表完整建表SQL

(1)用户表 user

CREATE TABLE `user` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '用户主键',
  `username` VARCHAR(30) NOT NULL UNIQUE COMMENT '登录账号',
  `password` VARCHAR(30) NOT NULL COMMENT '登录密码',
  `create_time` DATETIME DEFAULT NOW() COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT '用户表';

(2)物品分类表 category(本人核心负责表,对应后端分类模块)

CREATE TABLE `category` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '分类id',
  `category_name` VARCHAR(50) NOT NULL COMMENT '分类名称(手机/证件/箱包等)',
  `remark` VARCHAR(200) DEFAULT '' COMMENT '分类备注说明'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT '物品分类表';

(3)失物表 lost_item

CREATE TABLE `lost_item` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
  `username` VARCHAR(30) NOT NULL COMMENT '发布人账号',
  `name` VARCHAR(100) NOT NULL COMMENT '物品名称',
  `category_id` BIGINT NOT NULL COMMENT '关联分类id',
  `location` VARCHAR(100) NOT NULL COMMENT '丢失地点',
  `lose_date` VARCHAR(30) NOT NULL COMMENT '丢失时间',
  `status` VARCHAR(20) DEFAULT '未找回' COMMENT '状态:未找回/已找回',
  `image` VARCHAR(255) DEFAULT '' COMMENT '图片访问路径',
  FOREIGN KEY (`category_id`) REFERENCES category(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT '失物信息表';

(4)招领表 found_item

CREATE TABLE `found_item` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
  `username` VARCHAR(30) NOT NULL COMMENT '发布人账号',
  `name` VARCHAR(100) NOT NULL COMMENT '物品名称',
  `category_id` BIGINT NOT NULL COMMENT '关联分类id',
  `location` VARCHAR(100) NOT NULL COMMENT '拾取地点',
  `find_date` VARCHAR(30) NOT NULL COMMENT '拾取时间',
  `status` VARCHAR(20) DEFAULT '待认领' COMMENT '状态:待认领/已认领',
  `image` VARCHAR(255) DEFAULT '' COMMENT '图片访问路径',
  FOREIGN KEY (`category_id`) REFERENCES category(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT '招领信息表';

3. 初始化测试数据(本人编写)

-- 测试用户账号
INSERT INTO user(username,password) VALUES ('stu01','123456'),('admin','admin123');
-- 基础物品分类数据
INSERT INTO category(category_name,remark) VALUES
('手机数码','手机、耳机、平板等电子产品'),
('证件卡包','身份证、学生证、银行卡'),
('箱包衣物','背包、雨伞、外套'),
('书本文具','课本、笔记本、笔袋');

开发踩坑(数据库环节)

  1. 外键关联未设置字符集统一,创建表报错;统一全部表utf8mb4解决;
  2. category_name设置唯一索引,防止重复分类;
  3. 提前插入分类测试数据,后续开发发布物品页面无需手动新增分类。

第二部分:后端物品分类管理模块完整代码(本人负责任务3:后端开发-物品分类模块)

1. 分类实体类 Category.java

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("category")
public class Category {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String categoryName;
    private String remark;
}

2. Mapper持久层

public interface CategoryMapper extends BaseMapper<Category> {
}

3. Controller分类接口(全部由本人开发)

统一使用项目封装返回类R<T>,提供完整CRUD接口,供前端分类页面调用

@RestController
@RequestMapping("/api/category")
public class CategoryController {
    @Autowired
    private CategoryMapper categoryMapper;

    // 查询所有分类(发布物品下拉框使用)
    @GetMapping("/listAll")
    public R<List<Category>> listAll(){
        List<Category> list = categoryMapper.selectList(null);
        return R.success(list);
    }

    // 新增物品分类
    @PostMapping("/add")
    public R<String> add(@RequestBody Category category){
        // 判断分类名称重复
        QueryWrapper<Category> wrapper = new QueryWrapper<>();
        wrapper.eq("category_name",category.getCategoryName());
        Category exist = categoryMapper.selectOne(wrapper);
        if(exist != null){
            return R.error("该分类已存在,请勿重复添加");
        }
        categoryMapper.insert(category);
        return R.success("新增分类成功");
    }

    // 修改分类信息
    @PutMapping("/update")
    public R<String> update(@RequestBody Category category){
        categoryMapper.updateById(category);
        return R.success("修改分类成功");
    }

    // 删除分类
    @DeleteMapping("/delete")
    public R<String> delete(@RequestParam Long id){
        categoryMapper.deleteById(id);
        return R.success("删除分类成功");
    }

    // 根据id查询单个分类(编辑弹窗回显)
    @GetMapping("/getById")
    public R<Category> getById(@RequestParam Long id){
        Category category = categoryMapper.selectById(id);
        return R.success(category);
    }
}

后端分类模块业务逻辑讲解

  1. listAll接口:给前端发布失物/招领页面下拉选择框提供全部分类数据;
  2. 新增接口:增加重名校验,避免数据库出现同名分类;
  3. 修改/删除接口:给后台分类管理页面提供操作能力;
  4. 所有接口统一返回R<T>格式,前端只需要判断code=200区分成功失败。

第三部分:前端登录页、注册页完整代码与调试(本人负责任务2:前端开发)

1. Axios全局请求封装(项目统一配置,页面直接调用)

// src/utils/request.js
import axios from 'axios'
const baseUrl = 'http://localhost:8080/api'
const service = axios.create({
  baseURL: baseUrl,
  timeout: 5000
})
// 请求拦截器携带登录用户信息
service.interceptors.request.use(config => {
  let user = localStorage.getItem('user')
  if(user){
    config.headers.user = user
  }
  return config
})
export default service

2. 登录页面核心逻辑 Login.vue

<template>
  <div class="login-box">
    <h2>失物招领系统登录</h2>
    <el-form ref="loginFormRef" :model="loginForm">
      <el-form-item label="账号">
        <el-input v-model="loginForm.username"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input v-model="loginForm.password" show-password></el-input>
      </el-form-item>
      <el-button type="primary" @click="handleLogin">登录</el-button>
      <el-button @click="goRegister">去注册</el-button>
    </el-form>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import request from '@/utils/request'
const router = useRouter()
const loginForm = ref({
  username: '',
  password: ''
})
// 登录请求
const handleLogin = async () => {
  let res = await request.post('/user/login', loginForm.value)
  if(res.data.code === 200){
    localStorage.setItem('user', loginForm.value.username)
    alert('登录成功')
    router.push('/index')
  }else{
    alert(res.data.msg)
  }
}
// 跳转注册页
const goRegister = () => {
  router.push('/register')
}
</script>

登录页面功能说明

  1. 表单输入账号密码,调用后端/api/user/login接口;
  2. 登录成功将用户名存入localStorage,实现页面刷新保持登录;
  3. 登录失败弹窗提示账号不存在/密码错误;
  4. 提供跳转注册页面按钮,切换路由。

3. 注册页面核心逻辑 Register.vue

<template>
  <div class="register-box">
    <h2>用户注册</h2>
    <el-form ref="regFormRef" :model="regForm">
      <el-form-item label="账号">
        <el-input v-model="regForm.username"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input v-model="regForm.password" show-password></el-input>
      </el-form-item>
      <el-button type="primary" @click="handleRegister">注册</el-button>
      <el-button @click="goLogin">返回登录</el-button>
    </el-form>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import request from '@/utils/request'
const router = useRouter()
const regForm = ref({
  username: '',
  password: ''
})
// 注册提交
const handleRegister = async () => {
  let res = await request.post('/user/register', regForm.value)
  if(res.data.code === 200){
    alert('注册成功,请登录')
    router.push('/login')
  }else{
    alert(res.data.msg)
  }
}
// 返回登录页
const goLogin = () => {
  router.push('/login')
}
</script>

注册页面业务逻辑与效果图

  1. 用户填写账号密码提交,调用后端注册接口;
  2. 后端校验账号是否重复,重复则返回提示;
  3. 注册成功自动跳转登录页面。
    登录页面
    在这里插入图片描述

4. 页面调试过程遇到的问题(本人独立调试解决)

  1. 登录成功刷新页面直接退出
    解决:使用localStorage持久化存储用户名,路由前置守卫判断本地是否存在用户,无用户强制跳转登录页;
  2. 跨域请求403
    后端全局配置Cors跨域,放行前端Vue3本地5173端口;
  3. 注册账号重复未拦截
    后端用户注册接口增加用户名查重逻辑,前端同步增加输入框失焦校验;
  4. 分类下拉框无数据
    页面加载时调用/category/listAll接口,将分类数据渲染到发布页面下拉选择器。

四、本人负责模块完整业务交互流程

  1. 数据库阶段:根据小组ER图编写四张数据表SQL,插入基础测试分类、用户数据,给全项目提供底层数据支撑;
  2. 后端开发:独立开发物品分类全套CRUD接口,提供给后台分类管理页面、物品发布页面下拉组件使用;
  3. 前端开发:完成登录、注册页面布局、表单逻辑、接口对接,调试页面路由跳转、登录状态存储;
  4. 联调阶段:将分类接口与失物/招领发布页面联调,实现发布物品可选择对应分类;登录页面对接用户认证模块,完成登录鉴权基础功能。

五、个人开发小结

本次实训我负责数据库脚本、物品分类后端模块、登录注册前端页面三大核心任务,完整覆盖数据底层、后端接口、前端页面三层开发。
数据库编写过程熟悉了外键、字符集、测试数据初始化规范;后端分类模块巩固了MyBatis-Plus基础CRUD、重复数据校验逻辑;Vue3登录注册页面掌握了路由跳转、localStorage登录持久化、Axios接口联调技巧。
所有代码、报错、解决方案均为本人独立开发调试产出,完全符合实训独立考核原创要求。

更多推荐