东莞理工学院
《微信小程序应用开发》课程综合实践
项目名称:校园新闻网站
实训报告书
目录
1. 引言……………………………………………………………………………………………………………………1
1.1编写目的
1.2项目背景
1.3术语定义
2. 任务概述
2.1产品介绍
2.2产品目标
2.3产品用户
2.4技术要求
3. 功能需求
3.1移动端(前台)
3.2服务器端(后台)
3.3领域实体
4.非功能需求
5.业务流程
5.1移动端页面操作流程
5.2服务器端页面操作流程
6. 需求建模
6.1用例图
6.2用例描述
6.3活动图
7. 设计建摸
7.1类图
7.2顺序图
7.3带泳道的活动图
8. 数据库设计
8.1 ER图
8.2数据表
9. 实现建摸
9.1组件图
9.2包图
9.3部署图
10. 系统运行界面
10.1 移动端界面
10.2服务器端界面
11. 源代码
11.1小程序“列表”页代码
11.2小程序“详情”页代码
11.3小程序“新增”页代码
11.4小程序“修改”页代码
11.5小程序“删除”页代码
11.6服务器端“新增”记录接口代码
11.7服务器端“修改”记录接口代码
11.8服务器端“删除”记录接口代码
11.9服务器端“查询”记录列表接口代码
11.10服务器端“查询”记录详情接口代码
本报告书为校园新闻网站的设计及实现文档。该报告书便于开发人员、维护人员、用户之间的交流,便于他们理解项目的实现技术及功能体现。
本报告书的预期读者为用户、系统设计人员和编码人员;为开发人员、维护人员、用户之间提供共同的协议而创立基础,指导软件功能的实现。
本报告书全面、概括性地描述了校园新闻网站所要完成的工作,系统设计方案,实现路线。通过本报告书可以全面了解校园新闻网站所要完成的任务和所能达到的功能。
随着动态网站技术的发展,网站内容可以非常方便地维护,并及时体现在前端。前端既可以运行在电脑上,也可以运行在移动设备上。
微信小程序是一种开发移动端产品的新技术。它将网页实现技术HTML+XML +CSS+JavaScript进行改造,实现了轻量级网页开发技术。微信小程序基于WXML+WXSS+ JavaScript,WXML类似于XML,WXSS类似于CSS。因此,掌握了网页开发技术的人员很容易转岗到微信小程序的应用开发。
Java Servlet:在Web服务器端加载并运行的Java应用程序。
MySQL:一种关系数据库管理系统,基于结构化查询语言。
campusNews:本项目的数据库名字。
xinwenNews:本项目的数据表名字。
校园新闻网站是一种Web应用系统。客户通过手机浏览器,访问小程序,就可以增删查改新闻信息、观看新闻列表。
校园新闻网站分移动端操作和后台服务。
移动端操作主要包括:新闻列表,新闻详情,新闻增删改。
后台服务主要包括:基于Java Servlet的新闻的增删查改的接口。
本小程序操作用户:移动端用户。
1、基于JavaScritp语言和Java Servlet技术。JDK虚拟机,MySQL数据库,Web服务器Tomcat,数据库服务器Apache。
2、Win2000/XP/win7/win8/win2008 操作系统。
3、IE浏览器,Google Chrome浏览器,360浏览器等主流浏览器。
4、手机上的小程序。
表1 移动端的功能需求(主要阐述小程序页面对应的WXML、WXSS、JS)
功能类别 |
功能名称,标识符 |
描述 |
新闻列表 |
onShow: function (options) |
通过request向后端请求数据 |
dian:function(e) |
点击新闻列表的某一项可以跳转到对应详情页 |
|
新增新闻 |
chooseimage(e) |
选择图片上传的弹窗设定:本地上传或拍照上传 |
chooseWxImage: function (type) |
图片上传服务器,调用对应的api进行上传到服务器 |
|
toAddNews(e) |
新增新闻,把数据上传到后端 |
|
修改新闻 |
onLoad: function (options) |
采用生命周期函数,加载初始绑定数据 |
chooseimage(e) |
选择图片上传的弹窗设定:本地上传或拍照上传 |
|
chooseWxImage: function (type) |
图片上传服务器,调用对应的api进行上传到服务器 |
|
toUpdate(e) |
把修改的数据上传到后端 |
|
删除新闻 |
del:function(e) |
点击删除按钮,出现弹窗提醒是否删除 |
表2 服务器端的功能需求(主要阐述实现记录的增删查改的接口)
功能类别 |
功能名称,标识符 |
描述 |
查询 |
List |
查询新闻列表 |
New getNewsById(int id); |
查询新闻 |
|
增加 |
int addNews(New news); |
增加新闻 |
修改 |
int updateNews(New news); |
修改新闻 |
删除 |
int deleteNewsById(int id); |
删除新闻 |
1、新闻:id,标题,发布日期,照片,内容。
表3 非功能需求
需求类别 |
需求名称,标识符 |
描述 |
用户界面需求 |
Requirement UI.1 |
|
Requirement UI.2 |
||
约束条件需求 |
Requirement LC.1 |
|
Requirement LC.2 |
||
软硬件需求 |
Requirement SH.1 |
|
Requirement SH.2 |
6.2.1 “新闻列表”用例的用例描述
用例名称:新闻列表。
用例简述:该用例在用户打开小程序后,以列表的方式显示数据库中所有的新闻。
参与者:用户。
前置条件:用户打开小程序。
后置条件:如果该用例成功执行,显示数据库中的所有新闻数据,以列表方式显示。
主事件流如下:
(1)用户打开小程序。
(2)小程序读取数据库,数据库返回所有新闻数据。
(3)小程序以列表的形式显示新闻数据到界面。
6.2.2 “新闻详情”用例的用例描述
用例名称:新闻详情。
用例简述:用户点击列表中的一条新闻,跳转到该新闻的详细页。
参与者:用户。
前置条件:在使用该用例前,需要打开新闻列表。
后置条件:如果该用例成功执行,显示用户点击的新闻详细页。
主事件流:
6.2.3 “新增新闻”用例的用例描述
用例名称:新增新闻。
用例简述:该用例在管理员打开小程序后,在数据库中添加新的新闻。
参与者:管理员。
前置条件:管理员打开小程序。
后置条件:如果该用例成功执行,在数据库中新增一条新闻纪录。
主事件流如下:
6.2.4 “修改新闻”用例的用例描述
用例名称:修改新闻。
用例简述:该用例在管理员打开小程序后,在数据库中修改原有的新闻。
参与者:管理员。
前置条件:管理员打开小程序。
后置条件:如果该用例成功执行,在数据库中更新一条新闻纪录。
主事件流如下:
6.2.5 “删除新闻”用例的用例描述
用例名称:删除新闻。
用例简述:该用例在管理员打开小程序后,在数据库中删除新的新闻。
参与者:管理员。
前置条件:管理员打开小程序。
后置条件:如果该用例成功执行,在数据库中删除一条新闻纪录。
主事件流如下:
字段 |
类型 |
长度 |
类型 |
默认 |
id |
int |
主键 |
||
title |
varchar |
50 |
非空 |
|
img |
varchar |
128 |
非空 |
|
content |
varchar |
65535 |
非空 |
|
ctime |
timestamp |
数据更新时间 |
修改成功后通过后端success数据绑定呈现在前端界面。
点击删除图片右下角的×会进行删除确认
点击图片下方的修改按钮,会进入修改界面,并获得对应数据自动填充
// pages/list.js
Page({
/** * 页面的初始数据** */
data: {
id1: 1,
shuzu: []
},
/** * 生命周期函数--监听页面加载*** */
onShow: function (options) {
var that = this
wx.request({
url: 'http://localhost/news', //仅为示例,并非真实的接口地址
// data: {
// x: '',
// y: ''
// },
header: {
'content-type': 'application/json' // 默认值
},
success(res) {
console.log(res)
that.setData({
shuzu: res.data
})
}
})
},
dian: function (e) {
var a = e.target.id
console.log(a)
wx.navigateTo({
url: "/pages/detail/detail?id=" + a,
})
},
/*** 用户点击右上角分享*/
onShareAppMessage: function () {}
})
{{title}}
{{ctime}}
/* pages/list.wxss */
.body {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.view-flex{
background-color:beige;
display:flex;
flex-wrap:wrap;
flex-direction:row;
justify-content: space-between
}
.card{
height: 350rpx;
}
navigator {
overflow: hidden;
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
}
.list {
margin-top: 30rpx;
height: 20%;
width: 92%;
position: relative;
/* border: 1px solid black; */
border-radius: 15px;
overflow: hidden;
background-color: rgb(255, 255, 255);
box-shadow: 2px 2px 3px 1px rgba(0, 0, 0, .6);
}
.imgs {
width: 30%;
height: 21vh;
}
.imgs image {
margin-top: 30rpx;
display: block;
width: 200rpx;
height: 100%;
margin-left: 20rpx;
}
.infos {
display: flex;
width: 60%;
height: 21vh;
flex-direction: column;
margin-left: 6px;
}
.title {
margin-top: 30rpx;
display: block;
width:450rpx;
height: 200rpx;
font-size: 1.2em;
overflow: hidden;
text-align-last: left;
}
.date {
text-align: left;
width: 100%;
height: 100rpx;
font-size: 1em;
margin-top: 50rpx;
color: #aaa;
}
.loadMore {
text-align: center;
margin: 30px;
color: #aaa;
font-size: 16px
}
// pages/change/change.js
Page({
/**
* 页面的初始数据
*/
data: {
id: 1,
shuzu: [],
success: false,
img: '',
cTime: '',
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this
console.log(that.data)
that.setData({
id: options.id
})
wx.request({
url: 'http://localhost/news/' + that.data.id,
method: 'GET',
success(res) {
that.setData({
shuzu: res.data,
img: res.data.img,
// cTime:res.data.ctime
})
}
})
},
return_home: function (e) {
wx.switchTab({
url: '/pages/list/list',
})
},
})
{{shuzu.title}}
{{shuzu.ctime}}
{{shuzu.content}}
.warp {
height: 100%;
display: flex;
flex-direction: column;
padding: 20rpx;
font-size: 16px;
justify-content: center;
width: 700rpx;
padding-left: 40rpx;
}
.title {
text-align: center;
padding: 20rpx;
font-size: 20px;
}
.cTime {
padding-top: 10px;
text-align: center;
font-size: 14px;
color: #aaa;
}
.img {
text-align: center;
padding: 20rpx;
}
.img image {
width: 120px;
height: 120px;
}
.content {
text-indent: 2em;
width:650rpx;
}
.close {
margin-top: 30px;
width: 80%;
background-color: rgb(252, 126, 67);
color: white;
border-radius: 98rpx;
background: bg_red;
}
/* 按下变颜色 */
.hover {
top: 3rpx;
background: rgb(236, 179, 156);
}
// pages/addNews/addNews.js
Page({
data: {
shuzu: [],
success: false,
img: '',
},
return_home: function (e) {
var that = this
that.setData({
success: false
})
wx.switchTab({
url: '/pages/list/list',
})
},
getvalue(e) {
console.log(e.detail)
},
toAddNews(e) {
var that = this
console.log(e.detail.value.title)
wx.request({
url: 'http://localhost/news/',
data: {
title: e.detail.value.title,
content: e.detail.value.content,
img: that.data.img,
},
method: "POST",
success(res) {
console.log('success!')
that.setData({
success: true,
img: '',
})
}
})
},
chooseimage(e) {
var that = this;
wx.showActionSheet({
itemList: ['从相册选择', '拍照'],
itemColor: "#CED63A",
success: function (res) {
if (!res.cancel) {
if (res.tapIndex == 0) {
that.chooseWxImage('album')
} else if (res.tapIndex == 1) {
that.chooseWxImage('camera')
}
}
}
})
},
chooseWxImage: function (type) {
var that = this
wx.chooseImage({
sizeType: ['original', 'compressed'],
sourceType: [type],
count: 1,
success: function (res) {
console.log(res)
that.setData({
img: res.tempFilePaths[0],
})
}
})
},
})
添加新闻成功!
page {
background: #F0F0F0;
}
.row {
margin-top: 20rpx;
overflow: hidden;
line-height: 100rpx;
border-bottom: 1rpx solid #ccc;
margin-left: 20rpx;
margin-right: 20rpx;
color: #777;
background: #fff;
}
.info-input {
height: 400rpx;
margin-left: 50rpx;
color: #777;
float: left;
}
.info-input1 {
height: 100rpx;
margin-left: 50rpx;
color: #777;
font-weight: 800;
font-size: large;
float: left;
width: 420rpx;
}
.info-input2 {
height: 100rpx;
margin-left: 50rpx;
color: #777;
float: left;
width: 420rpx;
}
.button {
width: 200rpx;
height: 70rpx;
line-height: 70rpx;
font-size: 28rpx;
background: #33FF99;
float: left;
margin-left: 10rpx;
margin-top: 15rpx;
color: #FFFFFF;
}
.submit {
margin-top: 50rpx;
margin-left: 20rpx;
margin-right: 20rpx;
background: #00CCFF;
color: #FFFFFF;
}
.success {
background: #ffffff;
}
.cheer {
text-align: center;
line-height: 400rpx;
font-size: 60rpx;
position: relative;
}
.return {
margin: 20rpx;
}
/* border-radius: 98rpx;是控制按钮边变圆 */
.goodbutton {
margin-top: 30px;
width: 80%;
background-color: rgb(252, 126, 67);
color: white;
border-radius: 98rpx;
background: bg_red;
}
/* 按下变颜色 */
.hover {
top: 3rpx;
background: rgb(236, 179, 156);
}
// pages/change/change.js
Page({
/**
* 页面的初始数据
*/
data: {
id: 1,
shuzu: [],
success: false,
img: '',
cTime: '',
title: '',
content: '',
tempFilePaths:''
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this
console.log(that.data)
that.setData({
id: options.id
})
wx.request({
url: 'http://localhost/news/' + that.data.id,
method: 'GET',
success(res) {
that.setData({
shuzu: res.data,
img: res.data.img,
cTime: res.data.ctime,
title: res.data.title,
content: res.data.content
})
}
})
},
chooseimage(e) {
var that = this;
wx.showActionSheet({
itemList: ['从相册选择', '拍照'],
itemColor: "#CED63A",
success: function (res) {
if (!res.cancel) {
if (res.tapIndex == 0) {
that.chooseWxImage('album')
} else if (res.tapIndex == 1) {
that.chooseWxImage('camera')
}
}
}
})
},
chooseWxImage: function (type) {
var that = this
wx.chooseImage({
sizeType: ['original', 'compressed'],
sourceType: [type],
count: 1,
success: function (res) {
console.log(res)
that.setData({
img: res.tempFilePaths[0],
})
}
})
},
return_home: function (e) {
wx.switchTab({
url: '/pages/list/list',
})
},
toUpdate(e) {
var that = this
wx.request({
url: 'http://localhost/news/',
data: {
// title: e.detail.value.title,
id: that.data.id,
title: that.data.title,
cTime: that.data.ctime,
img: that.data.img,
content: that.data.content
// content: e.detail.value.content
},
method: "PUT",
success(res) {
console.log('success!')
console.log(e.detail)
that.setData({
success: true
})
}
})
},
handleInputTitle(e) {
this.setData({
title: e.detail.value
})
},
handleInputInfo(e) {
this.setData({
content: e.detail.value
})
}
})
修改新闻成功!
page {
background: #F0F0F0;
}
.row {
margin-top: 20rpx;
overflow: hidden;
line-height: 100rpx;
border-bottom: 1rpx solid #ccc;
margin-left: 20rpx;
margin-right: 20rpx;
color: #777;
background: #fff;
}
.info-input {
height: 650rpx;
margin-left: 20rpx;
margin-right: 20rpx;
color: #777;
float: left;
}
.info-input1 {
height: 200rpx;
margin-left: 50rpx;
margin-right: 20rpx;
color: #777;
font-weight: 800;
font-size: large;
float: left;
width: 600rpx;
}
.info-input2 {
height: 100rpx;
margin-left: 50rpx;
color: #777;
float: left;
width: 420rpx;
}
.button {
width: 200rpx;
height: 70rpx;
line-height: 70rpx;
font-size: 28rpx;
background: #33FF99;
float: left;
margin-left: 10rpx;
margin-top: 15rpx;
color: #FFFFFF;
}
.submit {
margin-top: 50rpx;
margin-left: 20rpx;
margin-right: 20rpx;
background: #00CCFF;
color: #FFFFFF;
}
.success {
background: #ffffff;
}
.cheer {
text-align: center;
line-height: 400rpx;
font-size: 60rpx;
position: relative;
}
.return {
margin: 20rpx;
}
/* border-radius: 98rpx;是控制按钮边变圆 */
.goodbutton {
margin-top: 30px;
width: 80%;
background-color: rgb(252, 126, 67);
color: white;
border-radius: 98rpx;
background: bg_red;
}
/* 按下变颜色 */
.hover {
top: 3rpx;
background: rgb(236, 179, 156);
}
// pages/oprateNews/operateNews.js
// pages/list.js
Page({
/** * 页面的初始数据** */
data: {
id1: 1,
shuzu: []
},
/** * 生命周期函数--监听页面显示*** */
onShow: function (options) {
var that = this
wx.request({
url: 'http://localhost/news/', //仅为示例,并非真实的接口地址
data: {
x: '',
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success(res) {
console.log(res)
that.setData({
shuzu: res.data
})
}
})
},
dian: function (e) {
var a = e.target.id
console.log(a)
wx.navigateTo({
url: "/pages/detail/detail?id=" + a,
})
},
change: function (e) {
var id = e.currentTarget.dataset.word
var that = this
console.log('修改文章' + id)
wx.navigateTo({
url: '/pages/change/change?id=' + id,
})
},
del: function (e) {
var id = e.currentTarget.dataset.word
var that = this
console.log('删除文章 ' + id)
wx.showModal({
title: '提示',
content: '是否确认删除',
cancelColor: 'cancelColor',
cancelText: '取消',
confirmColor: 'red',
confirmText: '删除',
success: function (res) {
if (res.cancel) console.log('取消删除操作')
else {
wx.request({
url: 'http://localhost/news/' + id,
method: "DELETE",
success: function (res) {
console.log('success!')
that.onShow()
}
})
}
}
})
},
showOperate(e) {
var id = e.currentTarget.dataset.word
console.log(id)
wx.showActionSheet({
itemList: ['修改', '删除'],
alertText: '你正在进行操作',
success(res) {
if (res.tapIndex == 0) {
console.log('修改文章' + id)
wx.navigateTo({
url: '/pages/change/change?id=' + id,
})
} else if (res.tapIndex == 1) {
var that = this
console.log('删除文章 ' + id)
wx.showModal({
title: '提示',
content: '是否确认删除',
cancelColor: 'cancelColor',
cancelText: '取消',
confirmColor: 'red',
confirmText: '删除',
success: function (res) {
if (res.cancel) console.log('取消删除操作')
else {
wx.request({
url: 'http://localhost/news/' + id,
method: "DELETE",
success: function (res) {
console.log('success!')
}
})
}
}
})
}
},
fail(res) {
console.log(res.errMsg)
}
})
},
/*** 用户点击右上角分享*/
onShareAppMessage: function () {}
})
{{title}}
{{cTime}}
.view-flex{
background-color:beige;
display:flex;
flex-wrap:wrap;
flex-direction:row;
justify-content: space-between;
margin-top: 20rpx;
}
.list{
position: relative;
width: 350rpx;
height: 600rpx;
border-radius: 15px;
overflow: hidden;
background-color: rgb(255, 255, 255);
box-shadow: 2px 2px 3px 1px rgba(0, 0, 0, .6);
margin-left: 20rpx;
margin-top: 20rpx;
}
.imgs{
width: 300rpx;
height: 300rpx;
align-items: center;
margin-left: 20rpx;
margin-top: 20rpx;
}
.in-img{
width: 300rpx;
height: 300rpx;
}
.infos{
width: 330rpx;
margin-top: 20rpx;
margin-left: 20rpx;
align-items: center;
height: 280rpx;
}
.title{
font-weight: 800;
overflow: hidden;
height: 200rpx;
}
.date{
font-size: smaller;
color: gray;
}
.delete{
position: absolute;
left: 280rpx;
top: 525rpx;
}
.setBtn{
position: absolute;
left: 200rpx;
top: 530rpx;
font-size: 10px;
background-color: lightsalmon;
color:white;
}
@Insert("insert into news values (#{id},#{title},#{img},#{content},#{cTime})")
int addNews(New news);
@Update("update news set title = #{title}, content = #{content}, img = #{img} where id = #{id}")
int updateNews(New news);
@Delete("delete from news where id = #{id}")
int deleteNewsById(int id);
@Select("select * from news")
List<New> getAllNewsList();
@Select("select * from news where id = #{id}")
New getNewsById(int id);