个人团队的比赛项目,仅供学习交流使用
一、项目基本介绍
1. 项目简介
一款基于微信小程序的轻量化笔记工具,旨在帮助用户通过记录每日心情和事件,更好地管理情绪和生活。用户可以根据日期和心情分类(如开心、平静、难过等)记录笔记,并随时查看历史记录。同时,项目还包含一个后台运营端小程序,用于数据统计、用户行为分析、用户反馈收集与回复,为运营决策提供支持。代码已上传至GitHub
2. 技术栈
微信小程序原生开发(JS、WXML、WXSS)、SpringBoot、MySQL、RESTful API、Postman接口测试、Axure
3. 项目功能
(1)用户端
微信授权登录
主界面:该功能模块主要包括显示日历、显示笔记、删除单条笔记。
-
显示日历:日历供用户选择查看日期,当日总体心情为日期小角标,用户点击日期即可在页面下方显示该日笔记。
-
显示笔记:底部笔记栏呈现所选日按修改时间进行排序的笔记(默认为当日),若无笔记出现"今日还未写笔记噢!"提示。
-
删除单条笔记:右滑笔记出现删除按钮,并弹出提示框。
个人中心:该功能模块主要包括反馈、分享、我的信箱与退出登录。
-
反馈:用户在反馈渠道提出意见。
-
分享:将小程序转发给微信好友。
-
我的信箱:管理员向用户下发通知,用户在我的信箱查看
-
退出登录:退出登录后再次登录需要再次授权。
笔记记录:该功能模块主要功能包括心情选择和写笔记。
-
心情选择:用户可在心情图案列表中选择本条笔记记录时的心情;若本条笔记为当日第二条及以上,自动弹出当日总体心情选择界面;在日历上方可以改变总体心情,若没有选择总体心情则会出现"今日还未选择总体心情哦"提示。
-
写/修改笔记:用户可自由进行笔记记录或修改笔记内容及此条笔记心情。
-
(2)开发者端
微信授权与密钥登陆
官方通知:发布官方通知下发到每一个用户
反馈回执:针对不同用户的返回发送回执
二、项目代码分析
1. 项目代码架构
前端小程序项目结构(以用户端为例)
后端Java项目结构
2.前端代码分析(以用户端主页面为例)
main.js
const util = require('../../utils/util.js')
var app = getApp()
Page({
data: {
avatarUrl: "/images/头像.png",
nickName: '未登录',
date: null,
daymood: '今日还未选心情',
moodList: new Array(),
noteList: new Array(),
noteisHave: false,
year: 0,
month: 0,
head: ['日', '一', '二', '三', '四', '五', '六'],
dateArr: [],
isToday: 0,
pickToday: 0,
isTodayWeek: false,
todayIndex: 0,
nottoday: false,
havenote:'今日还未写笔记哦!'
},
onShow() {
let date = new Date();
let now = new Date();
let year = now.getFullYear();
let month = now.getMonth() + 1;
console.log(0)
this.dateInit();
this.setData({
year: year,
month: month,
isToday: '' + year + '-' + month + '-' + now.getDate(),
avatarUrl: app.globalData.avatarUrl,
nickName: app.globalData.nickName,
date: util.formatDate(date)
})
console.log(3)
this.daymoodinit(util.formatYearDate(now)[0]);
console.log(5)
this.noteinit(util.formatYearDate(now)[0]);
},
noteinit(date) {
var that = this
//请求获取笔记列表
wx.request({
url: app.globalData.url + '/getNoteList',
data: {
uid: wx.getStorageSync('uid'),
date: date
},
header: {
'content-type': 'application/json'
},
success(res) {
console.log(6)
//获取后端传入的笔记列表
var notelist = res.data.noteList
//如果笔记列表不为空
if (notelist) {
//创建微信小程序存储数组值的变量
var noteList = new Array();
//创建构造函数note
function Note(nid, context, time, mood) {
this.nid = nid;
this.context = context;
this.time = time;
this.mood = mood;
}
//遍历后端传来的值,将其加到我的数据中
for (var i = 0; i < notelist.length; i++) {
//对心情处理
notelist[i].mood = '/images/' + notelist[i].mood + '.png';
//赋值
var note = new Note(notelist[i].nid, notelist[i].context+'...', notelist[i].time, notelist[i].mood)
noteList[i] = note
}
//设置值
that.setData({
//笔记列表
noteList: noteList,
noteisHave: true
})
}
}
})
},
daymoodinit(date) {
var that = this
wx.request({
//获取某日的总体心情
url: app.globalData.url + '/gDateMood',
data: {
uid: wx.getStorageSync('uid'),
date: date
},
header: {
'content-type': 'application/json'
},
success(res) {
console.log(4)
if (res.data.daymood) {
if (date == util.formatYearDate(new Date())) {
that.setData({
daymood: '今日心情:' + res.data.daymood
})
} else {
that.setData({
daymood: '该日心情:' + res.data.daymood
})
}
} else {
if (date == util.formatYearDate(new Date())) {
that.setData({
daymood: '今日还未选心情'
})
} else {
that.setData({
daymood: '该日未记录心情'
})
}
}
}
//为测试所用,正式直接删掉
// fail() {
// that.setData({
// daymood: '今日心情:开心'
// })
// }
})
},
backnow() {
var date = {
date: util.formatYearDate(new Date()).toString()
}
this.date(date)
//自动展示为当前月份的日历页面
this.dateInit()
this.setData({
nottoday: false
})
},
date(e) {
//判断是从组件传的值(即点击日期)还是从函数传的值(即点击回到今日)
if (e.date) {
var date = e.date
} else {
var date = e.currentTarget.dataset.date
}
//转换日期
var dates = date.split("-")
var month = dates[1]
var day = dates[2]
var thisdate = month + '月' + day + '日'
if(date == util.formatYearDate(new Date())){
this.setData({
noteisHave: false,
pickToday: date,
date: thisdate,
nottoday: false,
havenote:'今日还未写笔记哦!'
})
}else{
this.setData({
noteisHave: false,
pickToday: date,
date: thisdate,
nottoday: true,
havenote:'该日还未写笔记哦!'
})
}
//修改页面总体心情
this.daymoodinit(date)
//向后端请求日期下的笔记列表
this.noteinit(date)
},
add() {
wx.navigateTo({
url: '/pages/notemood/notemood'
})
},
daymood() {
wx.showModal({
title: '只能修改今日总体心情',
content: '确认要修改吗?',
success(res) {
if (res.confirm) {
wx.navigateTo({
url: '/pages/daymood/daymood'
})
}
}
})
},
mine() {
wx.navigateTo({
url: '/pages/mine/mine',
})
},
changenote(e) {
//需向后端传入标识,表示是第一次进入修改笔记页面,目的为保证渲染层的正确
var note = e.currentTarget.dataset.note
var nid = note.nid
var time = note.time
var mood = note.mood
wx.redirectTo({
url: '/pages/note/note?mood=' + mood + '&nid=' + nid + '&time=' + time + '&flag=1',
})
},
dateInit: function (setYear, setMonth) {
//全部时间的月份都是按0~11基准,显示月份才+1
let dateArr = []; //需要遍历的日历数组数据
let arrLen = 0; //dateArr的数组长度
let now = setYear ? new Date(setYear, setMonth) : new Date();
let year = setYear || now.getFullYear();
let nextYear = 0;
let month = setMonth || now.getMonth(); //没有+1方便后面计算当月总天数
let nextMonth = (month + 1) > 11 ? 1 : (month + 1);
let startWeek = new Date(year + ',' + (month + 1) + ',' + 1).getDay(); //目标月1号对应的星期
let dayNums = new Date(year, nextMonth, 0).getDate(); //获取目标月有多少天
let obj = {};
let num = 0;
if (month + 1 > 11) {
nextYear = year + 1;
dayNums = new Date(nextYear, nextMonth, 0).getDate();
}
var that = this
console.log(1)
//得到当月心情表从后端
wx.request({
url: app.globalData.url + '/selectAllMood',
data: {
uid: wx.getStorageSync('uid'),
year: year,
month: month + 1
},
header: {
'content-type': 'application/json'
},
success(res) {
console.log(2)
if (!res.data) {
wx.showToast({
title: '日期超出可用范围咯!',
icon: 'none',
duration: 2000 //持续的时间
})
} else {
that.setData({
moodList: res.data.moodList,
year: year,
month: month + 1
})
arrLen = startWeek + dayNums;
for (let i = 0; i < arrLen; i++) {
if (i >= startWeek) {
num = i - startWeek + 1;
obj = {
isToday: '' + year + '-' + (month + 1) + '-' + num,
dateNum: num,
weight: 5,
mood: '/images/' + that.data.moodList[num - 1] + '色.png'
}
} else {
obj = {};
}
dateArr[i] = obj;
}
that.setData({
dateArr: dateArr
})
let nowDate = new Date();
let nowYear = nowDate.getFullYear();
let nowMonth = nowDate.getMonth() + 1;
let nowWeek = nowDate.getDay();
let getYear = setYear || nowYear;
let getMonth = setMonth >= 0 ? (setMonth + 1) : nowMonth;
if (nowYear == getYear && nowMonth == getMonth) {
that.setData({
isTodayWeek: true,
todayIndex: nowWeek
})
} else {
that.setData({
isTodayWeek: false,
todayIndex: -1
})
}
}
}
//为测试所用,正式直接删掉
// fail() {
// arrLen = startWeek + dayNums;
// for (let i = 0; i < arrLen; i++) {
// if (i >= startWeek) {
// num = i - startWeek + 1;
// obj = {
// isToday: '' + year + '-' + (month + 1) + '-' + num,
// dateNum: num,
// weight: 5,
// mood: '/images/' + that.data.moodList[num - 1] + '色.png'
// }
// } else {
// obj = {};
// }
// dateArr[i] = obj;
// }
// that.setData({
// dateArr: dateArr
// })
// let nowDate = new Date();
// let nowYear = nowDate.getFullYear();
// let nowMonth = nowDate.getMonth() + 1;
// let nowWeek = nowDate.getDay();
// let getYear = setYear || nowYear;
// let getMonth = setMonth >= 0 ? (setMonth + 1) : nowMonth;
// if (nowYear == getYear && nowMonth == getMonth) {
// that.setData({
// isTodayWeek: true,
// todayIndex: nowWeek
// })
// } else {
// that.setData({
// isTodayWeek: false,
// todayIndex: -1
// })
// }
// }
})
},
lastMonth: function () {
//全部时间的月份都是按0~11基准,显示月份才+1
let year = this.data.month - 2 < 0 ? this.data.year - 1 : this.data.year;
let month = this.data.month - 2 < 0 ? 11 : this.data.month - 2;
this.dateInit(year, month);
},
nextMonth: function () {
//全部时间的月份都是按0~11基准,显示月份才+1
let year = this.data.month > 11 ? this.data.year + 1 : this.data.year;
let month = this.data.month > 11 ? 0 : this.data.month;
this.dateInit(year, month);
},
/**
* 设置movable-view位移
*/
setXmove: function (productIndex, xmove) {
let noteList = this.data.noteList
noteList[productIndex].xmove = xmove
this.setData({
noteList: noteList
})
},
/**
* 处理movable-view移动事件
*/
handleMovableChange: function (e) {
if (e.detail.source === 'friction') {
if (e.detail.x < -30) {
this.showDeleteButton(e)
} else {
this.hideDeleteButton(e)
}
} else if (e.detail.source === 'out-of-bounds' && e.detail.x === 0) {
this.hideDeleteButton(e)
}
},
/**
* 显示删除按钮
*/
showDeleteButton: function (e) {
let productIndex = e.currentTarget.dataset.productindex
this.setXmove(productIndex, -65)
},
/**
* 隐藏删除按钮
*/
hideDeleteButton: function (e) {
let productIndex = e.currentTarget.dataset.productindex
this.setXmove(productIndex, 0)
},
/**
* 处理touchstart事件
*/
handleTouchStart(e) {
this.startX = e.touches[0].pageX
},
/**
* 处理touchend事件
*/
handleTouchEnd(e) {
if (e.changedTouches[0].pageX < this.startX && e.changedTouches[0].pageX - this.startX <= -30) {
this.showDeleteButton(e)
} else if (e.changedTouches[0].pageX > this.startX && e.changedTouches[0].pageX - this.startX < 30) {
this.showDeleteButton(e)
} else {
this.hideDeleteButton(e)
}
},
/**
* 删除产品
*/
handleDeleteProduct: function ({
currentTarget: {
dataset: {
nid
}
}
}) {
var that = this
wx.showModal({
title: '删除该条笔记',
content: '确认要删除吗?',
success(res) {
if (res.confirm) {
wx.request({
//传入nid请求删除
url: app.globalData.url + '/deleteNote',
data: {
nid: nid
},
header: {
'content-type': 'application/json'
},
success() {
let noteList = that.data.noteList
let productIndex = noteList.findIndex(item => item.nid === nid)
noteList.splice(productIndex, 1)
that.setData({
noteList
})
if (noteList[productIndex]) {
that.setXmove(productIndex, 0)
}
if(!that.data.noteList[0]){
that.setData({
noteisHave: false,
})
}
},
fail() {
wx.showToast({
title: '删除失败!',
icon: 'none',
duration: 2000 //持续的时间
})
}
})
}
}
})
},
})
data是初始化
onshow是登录后要展示的,要对当日心情进行初始化,要对当日笔记进行初始化
noteinit要根据用户的uid和date访问后端(app.globalData.url这个是后端服务器地址),获取到笔记信息后渲染到页面上,也就是重设data里面的值
daymoodinit也是一样
backnow是什么,里面要对当月的日历进行展示,还要在日历上展示当日的总体心情角标
里面要dateInit,也是从后端获取数据
后续的方法也是点击主页上的一个按钮,需要进行的操作,有点到某一日、修改总体心情、修改笔记等,比如修改笔记,就用wx.redirectTo进行了页面跳转,需要页面间传递的数据也要在跳转的时候传递;比如修改总体心情,使用的则是navigateTo,这是为啥,还有showModal就是在上层创建新窗口吗;比如date就是点击某一日,获得该日的笔记信息和总体心情,于是要noteinit和daymoodinit;后续还有滑动删除笔记事件
- 数据初始化(data)
在data
中,我们定义了页面初始化时需要使用的各种变量。这些变量包括用户的头像、昵称、日期、心情、笔记列表等。这些数据将在页面加载时被初始化,并在用户与页面交互时动态更新。
- avatarUrl:用户的头像URL,默认值为
/images/头像.png
。 - nickName:用户的昵称,默认值为
未登录
。 - date:当前日期,初始值为
null
。 - daymood:当日的心情状态,默认值为
今日还未选心情
。 - moodList:心情列表,用于存储用户在不同日期的总体心情。
- noteList:笔记列表,用于存储用户在不同日期的笔记内容。
- noteisHave:标识当前日期是否有笔记,初始值为
false
。 - year和month:当前年份和月份,用于日历展示。
- head:日历表头的星期几标识。
- dateArr:日历数组,用于展示当前月份的日期和心情角标。
- isToday:标识当前日期是否为今天。
- pickToday:用户选择的日期。
- isTodayWeek:标识当前日期是否在本周。
- todayIndex:今天在日历中的索引。
- nottoday:标识用户选择的日期是否为今天。
- havenote:提示用户当前日期是否有笔记。
- 页面展示逻辑(onShow)
onShow
是微信小程序的生命周期函数,当页面显示时触发。在这个函数中,我们主要做了以下几件事:
- 获取当前日期:通过
new Date()
获取当前日期,并提取年份和月份。 - 初始化日历:调用
dateInit
函数,初始化当前月份的日历数据。 - 设置页面数据:将当前日期、用户头像、昵称等信息设置到页面的
data
中。 - 初始化当日心情和笔记:调用
daymoodinit
和noteinit
函数,分别获取并展示当日的心情和笔记。
- 笔记初始化(noteinit)
noteinit
函数用于根据用户的uid
和date
从后端获取笔记列表,并将获取到的笔记数据渲染到页面上。
- 请求笔记列表:通过
wx.request
向后端发送请求,获取指定日期的笔记列表。 - 处理笔记数据:如果笔记列表不为空,遍历列表并将每条笔记的数据存储到
noteList
中。 - 更新页面数据:将处理后的笔记列表设置到页面的
data
中,并更新noteisHave
状态。
- 当日心情初始化(daymoodinit)
daymoodinit
函数用于获取并展示用户当日的总体心情。
- 请求当日心情:通过
wx.request
向后端发送请求,获取指定日期的总体心情。 - 更新页面数据:根据获取到的心情数据,更新页面中的
daymood
状态。
- 返回今日(backnow)
backnow
函数用于将页面重置为当前日期的状态。
- 重置日期:将页面日期重置为当前日期。
- 初始化日历:调用
dateInit
函数,重新初始化当前月份的日历数据。 - 更新页面数据:将
nottoday
状态设置为false
,表示当前日期为今天。
- 选择日期(date)
date
函数用于处理用户选择日期的操作。
- 获取选择的日期:根据用户点击的日期或从函数传入的日期,获取用户选择的日期。
- 更新页面数据:将选择的日期设置到页面的
data
中,并更新noteisHave
和nottoday
状态。 - 初始化心情和笔记:调用
daymoodinit
和noteinit
函数,获取并展示选择日期的心情和笔记。
- 添加笔记(add)
add
函数用于跳转到添加笔记页面。
- 页面跳转:使用
wx.navigateTo
跳转到/pages/notemood/notemood
页面。
- 修改总体心情(daymood)
daymood
函数用于处理用户修改总体心情的操作。
- 弹出确认框:使用
wx.showModal
弹出确认框,询问用户是否确认修改总体心情。 - 页面跳转:如果用户确认,使用
wx.navigateTo
跳转到/pages/daymood/daymood
页面。
- 个人中心(mine)
mine
函数用于跳转到个人中心页面。
- 页面跳转:使用
wx.navigateTo
跳转到/pages/mine/mine
页面。
- 修改笔记(changenote)
changenote
函数用于处理用户修改笔记的操作。
- 获取笔记信息:从用户点击的笔记中获取笔记的
nid
、time
和mood
信息。 - 页面跳转:使用
wx.redirectTo
跳转到/pages/note/note
页面,并传递笔记的相关信息。
- 日历初始化(dateInit)
dateInit
函数用于初始化当前月份的日历数据。
- 获取当前月份的天数和起始星期:通过
new Date()
获取当前月份的天数和1号对应的星期。 - 请求当月心情数据:通过
wx.request
向后端发送请求,获取当前月份的心情数据。 - 更新页面数据:将获取到的心情数据设置到页面的
data
中,并生成日历数组dateArr
。
- 滑动删除笔记
滑动删除笔记功能通过handleMovableChange
、handleTouchStart
、handleTouchEnd
等函数实现。
- 显示删除按钮:当用户向左滑动笔记时,显示删除按钮。
- 隐藏删除按钮:当用户向右滑动或滑动距离不足时,隐藏删除按钮。
- 删除笔记:当用户点击删除按钮时,弹出确认框,确认后通过
wx.request
向后端发送删除请求,并更新页面数据。
main.wxml
<view class="data">
<view class="circle" bindtap="mine">
<image src="{{avatarUrl}}" class="head"></image>
</view>
<view class="date-mood">
<text class="date">{{date}}</text>
<text class="mood" bindtap="daymood">{{daymood}}</text>
</view>
<view class="backnow">
<image src="/images/今日.png" class="backnowimg" bindtap="backnow" wx:if="{{nottoday}}"></image>
</view>
<image src="/images/添加.png" class="add" bindtap="add"></image>
</view>
<view class="calendar">
<view class='wrap'>
<view>
<view class='date-show'>
<view class='lt-arrow' bindtap='lastMonth'>
<image src='/images/左箭头.png' mode='aspectFit'></image>
</view>
{{year}}年{{month}}月
<view class='rt-arrow' bindtap='nextMonth'>
<image src='/images/右箭头.png' mode='aspectFit'></image>
</view>
</view>
</view>
<view class='header'>
<view wx:for='{{head}}' class='{{(index == todayIndex) && isTodayWeek ? "weekMark" : ""}}'>{{item}}<view></view>
</view>
</view>
<view class='date-box'>
<view wx:for='{{dateArr}}'
class='{{isToday == item.isToday ? "nowDay" : (pickToday == item.isToday ? "pickDay" : "")}}'
data-date='{{item.isToday}}' bindtap="date">
<view class="sort">
<view class="minimoodview">
<image src="{{item.mood}}" class="minimood"></image>
</view>
<view class='date-head'>
<view>{{item.dateNum}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="nonote" wx:if="{{!noteisHave}}">
<image src="/images/铃铛.png" class="bell"></image>
<view class="empty">{{havenote}}</view>
</view>
<view wx:else>
<view class="product-list">
<view class="product-item" wx:for="{{noteList}}" wx:for-index="index" wx:key="{{item.nid}}">
<movable-area data-note="{{item}}" bindtap="changenote">
<movable-view out-of-bounds="true" direction="horizontal" x="{{item.xmove}}" inertia="true"
data-productIndex="{{index}}" bindtouchstart="handleTouchStart" bindtouchend="handleTouchEnd"
bindchange="handleMovableChange">
<view class="product-item-wrap">
<view class="expression">
<image src="{{item.mood}}" class="expressionimg"></image>
</view>
<view class="product-movable-item">
<view class="product-movable-item-name">{{item.time}}</view>
<view class="product-movable-item-code">{{item.context}}</view>
</view>
</view>
<view class="blank"></view>
</movable-view>
</movable-area>
<view class="delete-btn" data-nid="{{item.nid}}" bindtap="handleDeleteProduct">
<image src="/images/删除.png" class="delete"></image>
</view>
</view>
</view>
</view>
- 顶部用户信息与操作区域
- 用户头像:通过
<image>
组件展示用户头像,点击头像触发mine
函数,跳转到个人中心页面。 - 日期与心情:显示当前日期和当日心情,点击心情文本触发
daymood
函数,允许用户修改当日心情。 - 返回今日按钮:如果用户选择的日期不是今天,显示“返回今日”图标,点击触发
backnow
函数,重置为当前日期。 - 添加笔记按钮:点击“添加”图标触发
add
函数,跳转到添加笔记页面。
- 日历区域
- 日历头部:显示当前年份和月份,左右箭头分别触发
lastMonth
和nextMonth
函数,用于切换月份。 - 星期表头:显示星期几,当前星期会高亮显示。
- 日期展示:展示当前月份的日期,每个日期块显示日期数字和对应的心情图标。点击日期块触发
date
函数,加载该日期的笔记和心情。
- 笔记展示区域
- 无笔记提示:如果当前日期没有笔记,显示提示信息(如“今日还未写笔记哦!”)和一个铃铛图标。
- 笔记列表:如果有笔记,展示笔记列表。每条笔记包含心情图标、时间和内容。笔记支持左右滑动,滑动后显示删除按钮。
- 滑动删除:通过
movable-view
实现滑动功能,滑动到一定距离后显示删除按钮,点击删除按钮触发handleDeleteProduct
函数,删除对应笔记。 - 点击笔记:点击笔记内容触发
changenote
函数,跳转到修改笔记页面。
- 滑动删除:通过
3. 后端代码分析
以主页逻辑业务为例
UserDateController.java
package st.nuc.edu.cn.mood_note.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import st.nuc.edu.cn.mood_note.entity.UserDate;
import st.nuc.edu.cn.mood_note.service.UserDateService;
@RestController
public class UserDateController {
@Autowired
UserDateService userDateService;
@RequestMapping("/gDateMood")
public Object gDateMood(String uid, String date) {
return userDateService.gDateMood(uid, date);
}
@RequestMapping("/mixOperate")
public void mixOperate(UserDate userDate) {
userDateService.mixOperate(userDate);
}
@RequestMapping("/selectAllMood")
public Object selectAllMood(String uid, String year, String month) {
return userDateService.selectAllMood(uid, year, month);
}
}
UserDateController
是处理主页相关请求的控制器,主要包含以下接口:
- gDateMood:根据用户ID和日期,获取某日的总体心情。
- mixOperate:处理用户心情的插入或更新操作。
- selectAllMood:根据用户ID、年份和月份,获取该月的所有心情数据。
这些接口通过调用UserDateService
中的方法,完成具体的业务逻辑。
UserDateServiceImpl.java
package st.nuc.edu.cn.mood_note.service.impl;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import st.nuc.edu.cn.mood_note.entity.UserDate;
import st.nuc.edu.cn.mood_note.mapper.UserDateMapper;
import st.nuc.edu.cn.mood_note.service.UserDateService;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@Component
public class UserDateServiceImpl implements UserDateService {
@Autowired
UserDateMapper userDateMapper;
@Override
public Object gDateMood(String uid, String date) {
UserDate userDate = userDateMapper.gDateMood(uid, date);
if (userDate != null) {
JSONObject object = new JSONObject();
object.put("daymood",userDate.getDateMood());
return object;
} else {
return null;
}
}
@Override
public boolean mixOperate(UserDate userDate) {
UserDate userDate1 = userDateMapper.gDateMood(userDate.getUid(), userDate.getDate());
if (userDate1 == null) {
return userDateMapper.insert(userDate);
} else {
return userDateMapper.update(userDate);
}
}
@Override
public Object selectAllMood(String uid, String year, String month) {
int month1 = Integer.parseInt(month);
String s = null;
if ((month1>0)&&(month1<10)) {
s = "0" + month1;
} else {
s = month;
}
List<UserDate> userDateList = userDateMapper.gAllDateMood(uid, year, s);
if(!userDateList.isEmpty()) {
List<String> moodList = new ArrayList();
JSONObject object = new JSONObject();
for (UserDate userDate : userDateList) {
if (userDate.getDateMood() == null) {
moodList.add(null);
} else {
moodList.add(userDate.getDateMood());
}
}
object.put("moodList", moodList);
return object;
}
return null;
}
}
UserDateServiceImpl
是UserDateService
接口的实现类,主要功能如下:
- gDateMood:通过
UserDateMapper
查询某日的心情数据,如果存在则返回心情信息,否则返回null
。 - mixOperate:根据用户ID和日期,判断是插入新心情数据还是更新已有数据。
- selectAllMood:查询某月的所有心情数据,并将其封装为
JSON
格式返回。如果某日没有心情数据,则对应位置为null
。
UserDateMapper.java
package st.nuc.edu.cn.mood_note.mapper;
import org.apache.ibatis.annotations.*;
import st.nuc.edu.cn.mood_note.entity.UserDate;
import java.util.List;
@Mapper
public interface UserDateMapper {
@Select("select * from user_date where uid = #{uid} and date = #{date}")
UserDate gDateMood(@Param("uid")String uid, @Param("date")String date);
List<UserDate> gAllDateMood(@Param("uid")String uid, @Param("year")String year, @Param("month")String month);
@Insert("insert into user_date (uid,date,date_mood) values (#{uid},#{date},#{dateMood})")
boolean insert(UserDate userDate);
@Update("update user_date set date_mood=#{dateMood} where uid = #{uid} and date = #{date}")
boolean update(UserDate userDate);
}
UserDateMapper
是MyBatis的Mapper接口,定义了与数据库交互的方法:
- gDateMood:根据用户ID和日期,查询某日的心情数据。
- gAllDateMood:根据用户ID、年份和月份,查询该月的所有心情数据。
- insert:插入新的心情数据。
- update:更新已有的心情数据。
UserDateMapper.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="st.nuc.edu.cn.mood_note.mapper.UserDateMapper">
<select id="gAllDateMood" resultType="userDate">
SELECT a.uid,date.date,a.date_mood FROM date LEFT JOIN (SELECT * FROM user_date WHERE uid = #{uid}) a ON date.date=a.date where date.date LIKE '${year}_${month}%';
</select>
</mapper>
UserDateMapper.xml
是MyBatis的映射文件,定义了gAllDateMood
方法的SQL查询逻辑。通过左连接查询date
表和user_date
表,获取某月的所有心情数据。
application.yaml
mybatis:
type-aliases-package: st.nuc.edu.cn.mood_note.entity
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
datasource:
url: jdbc:mysql://localhost:3306/mood_note?useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
server:
port:8080
application.yaml
是Spring Boot的配置文件,主要配置了:
- MyBatis:指定实体类包路径、Mapper文件路径、日志实现等。
- 数据源:配置MySQL数据库的连接信息,包括URL、用户名、密码等。
- 服务器端口:设置服务端口为
8080
。
三、数据库设计
1. 表结构
1.用户表(用户)
- uid:用户ID,主键,类型为
varchar(50)
。 - opend:用户开放ID,类型为
varchar(255)
。
2.用户日期表(用户日期)
- uid:用户ID,外键,关联用户表,类型为
varchar(50)
。 - date:日期,外键,关联日期表,类型为
date
。 - date_mod:用户在该日期的总体心情,类型为
varchar(10)
。
3.登记表(登记)
- uid:用户ID,主键,类型为
int
。 - uid:用户ID,外键,关联用户表,类型为
varchar(50)
。 - date:日期,外键,关联日期表,类型为
date
。 - ncontext:笔记内容,类型为
varchar(8000)
。 - ntine:笔记时间,类型为
time
。 - mod:笔记心情,类型为
varchar(5)
。
4.反馈表(反馈)
- fid:反馈ID,主键,类型为
int
。 - uid:用户ID,外键,关联用户表,类型为
varchar(50)
。 - context:反馈内容,类型为
varchar(500)
。 - lz_read:是否已读,类型为
varchar(10)
。 - rcontext:回复内容,类型为
varchar(500)
。 - rdate:回复日期,类型为
date
。 - date:反馈日期,外键,关联日期表,类型为
date
。
5.日期表(日期)
- date:日期,主键,类型为
date
。
6.管理员表(管理员)
- aid:管理员ID,主键,类型为
int
。 - opend:管理员开放ID,类型为
varchar(255)
。 - password:管理员密码,类型为
varchar(255)
。
7.官方通知表(官方通知)
- aid:管理员ID,主键,类型为
int
。 - date:通知日期,类型为
date
。 - context:通知内容,类型为
varchar(500)
。 - lz_read:是否已读,类型为
varchar(10)
。