本文主要讲解如何实现失物招领在uniapp+springboot中的实现,其中前端包括v-model,uni-request的简单使用,后端包括增删改查+模糊查询等接口实现。
编译器:idea+Hbuilder
运行器:微信开发者工具
流程如下:构思=>制作数据表=>配置springboot基础设置+uniapp的css样式和template结构=>后端实体类、mapper接口、mapper.xml、service、serviceimpl实体类、Controller控制层=>postman测试接口是否好用=>前端利用uni.request调用接口=>测试。
代码如下(示例):
-- 创建 stype 表
CREATE TABLE stype (
sid INT PRIMARY KEY, -- 物品类型ID
sname VARCHAR(255) -- 物品类型名称
);
-- 创建 lost 表
CREATE TABLE lost (
id INT PRIMARY KEY, -- 失物ID
uid INT, -- 用户ID
lostType INT, -- 所属商品类型ID
lostName VARCHAR(255), -- 失物名称
losttime DATETIME, -- 失物时间
lostphone VARCHAR(20), -- 联系电话
detail TEXT, -- 失物详情
FOREIGN KEY (lostType) REFERENCES stype(sid) -- 外键关联到 stype 表的 sid 字段
);
首先创建两个数据表,一个用于存储用户失物的具体数据,另一个用于装物品类型。
pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.shop</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<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>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project> <!--在build中配置resources,来防止我们资源导出失败的问题!-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties/
**/ *.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties/
**/ *.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
注:springboot版本最好设置3.0以下版本,不然可能后续会有问题。
除了必需的springboot之外,还需要lombok,虽然它的安全性低,但是它会省去实体类中的get、set方法,可以用@Data代替,还需要引入mysql、mybatis等插件,这里就不细说了。
maven配置:
点击file=>setting=>搜索框搜索maven,把里面的Maven home directory、User settings file和Local repository配置成自己的,如果电脑没有maven也可以不配置用本地的,
Maven下载地址:https://maven.apache.org/download.cgi
可以通过自己画图来做,也可以通过花瓣等UI库中找自己喜欢的样式来制作,在做样式的过程中可能会用到图标,这里推荐阿里巴巴图标库,免费还比较全面,下载即用。地址放下面了。
https://www.iconfont.cn/
下面放一下我做的两个样式图
因为只是想练习功能调用和实现,所以样式后续可以再调整。
实体层
package com.shop.demo.pojo;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigInteger;
import java.util.Date;
@Data
public class lost {
private Integer id;
private Integer uid;
private Integer lostType;
private String sname;
private String lostName;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date losttime; // 使用java.util.Date类型
private BigInteger lostphone;
private String detail;
private String lostlocation;
}
mapper接口
package com.shop.demo.mapper;
import com.shop.demo.pojo.lost;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface lostmapper {
// 全部查询
public List<lost> lostquery();
// 增加失物
public int lostadd(lost ll);
// 删除失物
public int lostdel(int id);
// 根据名字查询
public List<lost> lostqueryByName(String lostName);
// 修改自己发布的物品
public int lostupdata(lost l);
// 根据id查询
public List<lost> lostqueryById(int uid);
}
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shop.demo.mapper.lostmapper">
<update id="lostupdata">
update lost set id=#{id}, lostType=#{lostType},lostName=#{lostName},losttime=#{losttime},lostphone=#{lostphone},detail=#{detail},lostlocation=#{lostlocation} where id=#{id}
</update>
<delete id="lostdel" parameterType="int">
delete from lost where id=#{id}
</delete>
<insert id="lostadd" parameterType="com.shop.demo.pojo.lost">
INSERT INTO lost(id, uid, lostType, lostName, losttime, lostphone, detail,lostlocation)
VALUES (#{id}, #{uid}, #{lostType}, #{lostName}, #{losttime}, #{lostphone}, #{detail},#{lostlocation})
</insert>
<select id="lostquery" resultType="com.shop.demo.pojo.lost">
SELECT lost.id, lost.uid, stype.sname, lost.lostName, lost.losttime, lost.lostphone, lost.detail,lost.lostlocation
FROM lost JOIN stype ON lost.lostType = stype.sid
</select>
<select id="lostqueryByName" resultType="com.shop.demo.pojo.lost">
select * from lost where 1=1
<if test="lostName!=null and lostName!=''">
and lostName like concat('%',#{lostName},'%') </if>
</select>
<select id="lostqueryById" resultType="com.shop.demo.pojo.lost">
select lost.* from lost, user where lost.uid=user.id
</select>
</mapper>
service层
package com.shop.demo.service;
import com.shop.demo.pojo.lost;
import java.util.List;
public interface lostservice {
List<lost> lostquery();
int lostadd(lost ll);
int lostdel(int id);
List<lost> lostqueryByName(String lostName);
int lostupdata(lost l);
List<lost> lostqueryById(int uid);
}
service实体类
package com.shop.demo.service;
import com.shop.demo.mapper.lostmapper;
import com.shop.demo.pojo.lost;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class lostserviceimpl implements lostservice {
@Autowired
lostmapper l;
@Override
public List<lost> lostquery(){
return l.lostquery();
}
@Override
public int lostadd(lost ll){
return l.lostadd(ll);
}
@Override
public int lostdel(int id){return l.lostdel(id);}
@Override
public List<lost> lostqueryByName(String lostName)
{
return l.lostqueryByName(lostName);
}
@Override
public int lostupdata(lost ll)
{
return l.lostupdata(ll);
}
@Override
public List<lost> lostqueryById(int uid)
{
return l.lostqueryById(uid);
}
}
controller控制层
package com.shop.demo.controller;
import com.shop.demo.pojo.lost;
import com.shop.demo.service.lostservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@ResponseBody
public class lostController {
@Autowired
lostservice l;
@RequestMapping("hello")
public String hello()
{
return "数据库中没有该条件下的数据";
}
@RequestMapping("lostquery")
public List<lost> lostquery()
{
return l.lostquery();
}
@RequestMapping("lostadd")
public int lostadd(lost ll){
return l.lostadd(ll);
}
@RequestMapping("lostdel")
public int lostdel(int id) {return l.lostdel(id);}
@RequestMapping("lostqueryByName")
public List<lost> lostqueryByName(String lostName)
{
return l.lostqueryByName(lostName);
}
@RequestMapping("lostupdata")
public int lostupdata(lost ll)
{
return l.lostupdata(ll);
}
@RequestMapping("lostqueryById")
public List<lost> lostqueryById(int uid)
{
return l.lostqueryById(uid);
}
}
这里就不赘述了,放下postman官网,如有需要可自行下载。
https://www.postman.com/
主要用到的是uni.request和v-model
uni.request语法格式
uni.request({
url: '接口地址',
header: {
'请求头': 'application/x-www-form-urlencoded'
},
method: '方法名',
data: {
调用接口数据名称: this.实际在页面中的数据名
},
成功的回调函数
success: (res) => {
console.log(res)
uni.showToast({
title: '删除成功',
duration: 3000
})
}
})
v-model主要应用于表单,可以实现双向绑定。
删改查、模糊查询前端代码:
<template>
<view class="page">
<!-- 搜索框 -->
<view class="search-box">
<input type="text" v-model="queryByName" placeholder="请输入关键字" />
<image src="../../static/取消.png" @click="notlostquery" style="width:30px;height:30px;" class="quxiao">
</image><button @click="lostqueryByName" class="button_">搜索</button>
</view>
<!-- 推荐失物 -->
<h2 class="title_body">最近失物</h2>
<view v-if="index<4" v-for="(item, index) in LostList" :key="item.id" class="body_type"
@tap="body_detail(item)">
<p style="font-size:17px;font-weight:bold;margin:10px;">物品名:{{ item.lostName }}</p>
<p style="float:left;">时间:{{item.losttime}}</p>
<p style="float:left;">丢失地点:{{item.lostlocation}}</p>
</view>
<!-- 我的失物 -->
<view>
<h2 class="title_body">我的发布</h2>
<view class="body_type" v-for="(item, index) in mylostList" :key="index">
<p style="font-size:17px;font-weight:bold;">{{ item.lostName }}</p>
<p>{{ item.losttime }}</p>
<text @click="lostdel(item.id)" style="font-weight:bold;">删除||</text>
<text @click="lostupdata(item.id)" style="font-weight:bold;">更新</text>
</view>
</view>
<view v-show="updataflag" class="updata" style="text-align: center;">
<view style="font-size:30px;margin-bottom: 10px;;">失物更新</view>
<view style="text-align: left;">
<input type="text" v-model="lostName" placeholder="请输入物品名" />
<input type="number" v-model="lostType" placeholder="请输入物品类型" />
<input type="number" v-model="lostphone" placeholder="请输入联系方式" />
<input type="text" v-model="losttime" placeholder="丢失时间:yyyy-mm-dd" />
<input type="text" v-model="lostlocation" placeholder="请输入丢失地点" />
<input type="text" v-model="detail" placeholder="备注" />
</view>
<button style="float: left;width:45%;margin-right:20px;" @tap="upquxiao">取消</button>
<button style="float:left;width:45%;" @tap="upsub">提交</button>
</view>
</view>
</template>
<script>
import {
vShow
} from "vue";
export default {
mounted() {
this.lostquery()
this.lostqueryById()
},
data() {
return {
queryByName: "",
LostList: [],
mylostList: [],
lostDelId: null,
id: null,
updataflag: false,
lostName: "",
lostType: null,
losttime: "",
lostphone: null,
lostlocation: "",
detail: ""
};
},
methods: {
body_detail(item) {
uni.showModal({
title: "具体内容",
content: "丢失物品:" + item.lostName + "丢失类型:" + item.sname + "\n" + "丢失时间:" + item.losttime +
"\n联系方式:" + item
.lostphone + "\n备注:" + item.detail,
showCancel: false,
confirmText: "已查阅"
})
},
lostqueryById() {
uni.request({
url: 'http://localhost:8080/lostqueryById',
data: {
uid: 1
},
success: (res) => {
console.log(res.data)
this.mylostList = res.data
for (let i = 0; i < this.mylostList.length; i++) {
this.mylostList[i].losttime = this.mylostList[i].losttime.substring(0, 10)
console.log(this.mylostList[i].losttime)
}
}
})
},
lostqueryByName() {
uni.request({
url: 'http://localhost:8080/lostqueryByName',
data: {
lostName: this.queryByName
},
success: (res) => {
console.log(res.data)
this.LostList = res.data
for (let i = 0; i < this.LostList.length; i++) {
this.LostList[i].losttime = this.LostList[i].losttime.substring(0, 10)
console.log(this.LostList[i].losttime)
}
}
})
},
lostquery() {
uni.request({
url: 'http://localhost:8080/lostquery',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success: (res) => {
console.log(res.data)
this.LostList = res.data
for (let i = 0; i < this.LostList.length; i++) {
this.LostList[i].losttime = this.LostList[i].losttime.substring(0, 10)
console.log(this.LostList[i].losttime)
}
}
})
},
lostdel(id) {
console.log(id)
this.lostDelId = id
uni.request({
url: 'http://localhost:8080/lostdel',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
method: 'PUT',
data: {
id: this.lostDelId
},
success: (res) => {
console.log(res)
uni.showToast({
title: '删除成功',
duration: 3000
})
}
})
this.lostquery()
},
lostupdata(id) {
this.id = id
this.updataflag = !this.updataflag
},
upquxiao() {
this.updataflag = !this.updataflag
this.id=null,
this.lostName="",
this.lostType=null,
this.losttime="",
this.phone=null,
this.detail="",
this.lostlocation=""
this.lostquery()
},
upsub() {
this.updataflag = !this.updataflag
console.log(this.id)
console.log(this.lostType)
uni.request({
url: 'http://localhost:8080/lostupdata',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
method: 'POST',
data: {
id:this.id,
lostType: this.lostType,
lostName: this.lostName,
losttime: this.losttime,
lostphone: this.lostphone,
detail: this.detail,
lostlocation: this.lostlocation
},
success: (res) => {
console.log(res)
this.lostquery()
this.lostName-"",
this.id=null,
this.lostType=null,
this.losttime="",
this.phone=null,
this.detail="",
this.lostlocation=""
},
})
},
notlostquery() {
this.queryByName = ""
this.lostqueryByName()
}
}
};
</script>
<style>
page {
background: #e8e8e8;
}
.title_body {
font-size: 25px;
font-weight: bold;
}
.page {
padding: 20px;
}
.body_type {
background-color: white;
text-align: center;
height: auto;
display: inline-block;
width: 43.5%;
padding: 5px;
margin: 5px;
border-radius: 10px;
}
input {
margin-left: 30px;
width: 200px;
border: 1px solid gray;
padding: 7px;
display: inline-block;
margin-right: 5px;
}
.quxiao {
position: absolute;
left: 15px;
top: 25px;
}
.button_ {
background: linear-gradient(to bottom, #4097e8, #48c3e8);
color: white;
border-radius: 10px;
line-height: 40px;
width: 80px;
height: 40px;
display: inline-block;
}
.updata {
position: fixed;
bottom: 0;
background-color: white;
margin-right: 20px;
}
uni-modal .uni-modal__bd {
white-space: pre-wrap;
}
</style>
增加前端代码:
<template>
<form class="form">
<view class="form-group">
<label for="studentId">*学号</label>
<input type="number" id="studentId" name="studentId" v-model="uid" placeholder="请输入您的学号" required>
</view>
<view class="form-group">
<label for="name">*丢失物品名</label>
<input type="text" id="name" name="name" v-model="lostName" placeholder="请输入丢失物品名" required>
</view>
<view class="form-group">
<label>丢失物品类型</label>
<view class="radio-group">
<radio-group name="lostType">
<label v-for="(item,index) in lostType" @tap="queryType(item.id)">
<radio value="value" /><text>{{item.name}}</text>
</label>
</radio-group>
</view>
</view>
<view class="form-group">
<label for="name">丢失地点</label>
<input type="text" id="location" name="location" v-model="lostlocation" placeholder="请输入丢失物品名" required>
</view>
<view class="form-group">
<label for="date">丢失日期</label>
<input type="text" id="datename" name="datename" v-model="losttime" placeholder="格式:yyyy-mm-dd" required>
</view>
<view class="form-group">
<label for="phone">*联系方式</label>
<input type="tel" id="phone" name="phone" v-model="lostphone" placeholder="请输入您的手机号码" pattern="[0-9]{11}" required>
</view>
<view class="form-group">
<label for="remark">备注</label>
<textarea id="remark" name="remark" v-model="detail"></textarea>
</view>
<button type="submit" class="btn-submit" @click="sub">提交</button>
</form>
</template>
<script>
export default {
data() {
return {
lostType:[
{id:"1",name:"生活用品"},
{id:"2",name:"学习用品"},
{id:"3",name:"电子产品"},
{id:"4",name:"其他"},
],
querytype:null,
uid:null,
lostName:"",
losttime:"",
lostphone:null,
detail:"",
lostlocation:""
}
},
methods: {
queryType(id){
this.querytype=id
console.log(this.querytype)
},
sub(){
if (this.querytype != "" && this.lostName != "" && this.losttime != "" && this.lostphone != null) {
uni.request({
url:'http://localhost:8080/lostadd',
method:'POST',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
data:{
uid:this.uid,
lostType:this.querytype,
lostName:this.lostName,
lostphone:this.lostphone,
losttime:this.losttime,
detail:this.detail,
lostlocation:this.lostlocation
},
success: (res) => {
console.log(res.data)
uni.redirectTo({
url:'/pages/life/life'
})
}
})
}
else{
uni.showModal({
content:"带*数据为必填项",
showCancel:false,
confirmText:"确认"
})
}
}
}
}
</script>
<style scoped>
.form {
max-width: 500px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
}
.form-group {
margin-bottom: 10px;
}
label {
display: block;
font-weight: bold;
margin-bottom: 5px;
}
input[type="text"],
input[type="number"],
input[type="tel"],
textarea {
width: 90%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 3px;
}
.radio-group {
display: flex;
flex-wrap: wrap;
}
.radio-group label {
display: inline-block;
margin-right: 20px;
}
.datetime-picker {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 3px;
font-size: 16px;
}
.btn-submit {
display: block;
width: 100%;
padding: 10px;
background-color: #007aff;
color: #fff;
border: none;
border-radius: 3px;
cursor: pointer;
}
</style>
完整的代码会放在我的资源里面,需要可自取。
总共做了一周,零零散散的时间,因为在事先没有做详细的需求调研和需求分析,这对后续的制作造成一些困难,最终是想做一个校园微社区,而失物招领是它的一个功能,希望看到这篇文章的各位能获得一点帮助。
进窄门,行远路,见微光。