diff --git a/前端/.eslintrc.js b/前端/.eslintrc.js
new file mode 100644
index 0000000..115cc02
--- /dev/null
+++ b/前端/.eslintrc.js
@@ -0,0 +1,31 @@
+/*
+ * Eslint config file
+ * Documentation: https://eslint.org/docs/user-guide/configuring/
+ * Install the Eslint extension before using this feature.
+ */
+module.exports = {
+ env: {
+ es6: true,
+ browser: true,
+ node: true,
+ },
+ ecmaFeatures: {
+ modules: true,
+ },
+ parserOptions: {
+ ecmaVersion: 2018,
+ sourceType: 'module',
+ },
+ globals: {
+ wx: true,
+ App: true,
+ Page: true,
+ getCurrentPages: true,
+ getApp: true,
+ Component: true,
+ requirePlugin: true,
+ requireMiniProgram: true,
+ },
+ // extends: 'eslint:recommended',
+ rules: {},
+}
diff --git a/前端/.gitignore b/前端/.gitignore
new file mode 100644
index 0000000..14ea590
--- /dev/null
+++ b/前端/.gitignore
@@ -0,0 +1,14 @@
+# Windows
+[Dd]esktop.ini
+Thumbs.db
+$RECYCLE.BIN/
+
+# macOS
+.DS_Store
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+
+# Node.js
+node_modules/
diff --git a/前端/app.js b/前端/app.js
new file mode 100644
index 0000000..1ed57c4
--- /dev/null
+++ b/前端/app.js
@@ -0,0 +1,19 @@
+// app.js
+App({
+ onLaunch() {
+ // 展示本地存储能力
+ const logs = wx.getStorageSync('logs') || []
+ logs.unshift(Date.now())
+ wx.setStorageSync('logs', logs)
+
+ // 登录
+ wx.login({
+ success: res => {
+ // 发送 res.code 到后台换取 openId, sessionKey, unionId
+ }
+ })
+ },
+ globalData: {
+ userInfo: null
+ }
+})
diff --git a/前端/app.json b/前端/app.json
new file mode 100644
index 0000000..e1d58d9
--- /dev/null
+++ b/前端/app.json
@@ -0,0 +1,22 @@
+{
+ "pages": [
+ "pages/welcome/welcome",
+ "pages/call_roll/call_roll",
+ "pages/function/function",
+ "pages/class_manage/class_manage",
+ "pages/add_stu/add_stu",
+ "pages/class_message/class_message",
+ "pages/record/record",
+ "pages/index/index",
+ "pages/logs/logs"
+ ],
+ "window": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "Weixin",
+ "navigationBarBackgroundColor": "#ffffff"
+ },
+ "style": "v2",
+ "componentFramework": "glass-easel",
+ "sitemapLocation": "sitemap.json",
+ "lazyCodeLoading": "requiredComponents"
+}
\ No newline at end of file
diff --git a/前端/app.wxss b/前端/app.wxss
new file mode 100644
index 0000000..75f4fde
--- /dev/null
+++ b/前端/app.wxss
@@ -0,0 +1 @@
+/**app.wxss**/
diff --git a/前端/pages/add_stu/add_stu.js b/前端/pages/add_stu/add_stu.js
new file mode 100644
index 0000000..69b5b81
--- /dev/null
+++ b/前端/pages/add_stu/add_stu.js
@@ -0,0 +1,157 @@
+// pages/addStudent/addStudent.js
+Page({
+ data: {
+ className:"K班",
+ input: "",
+ students:[
+
+ ]
+ },
+
+ onLoad: function(options) {
+ console.log(options);
+ // options 参数包含了从上一个页面传递过来的数据
+ const receivedClassName = options.className; // 获取传递过来的 className,默认为空字符串
+
+ // 更新页面的数据
+ this.setData({
+ className: receivedClassName // 将接收到的 className 赋值给页面的 data 属性
+ });
+ console.log(this.data.className);
+ },
+
+ //获取输入框内容
+ onInput: function(e) {
+ console.log(e.detail.value)
+ this.setData({
+ input: e.detail.value//保存输入
+ });
+ },
+
+ // Excel文件导入
+ importExcel: function() {
+ const that = this;
+ wx.chooseMessageFile({
+ count: 1, // 默认为1,设置选择文件的数量
+ type: 'file',
+ extension: ['xlsx'], // 指定文件的后缀名
+ success(res) {
+ const tempFiles = res.tempFiles; // 临时文件路径
+ const filePath = tempFiles[0].path; // 获取文件的路径
+ console.log(tempFiles);
+ that.readExcel(filePath); // 读取文件内容
+ },
+ fail(err) {
+ console.error('选择文件失败:', err);
+ }
+ });
+ },
+
+ // 读取Excel文件内容
+ readExcel(filePath) {
+ // 可以使用微信小程序的API或将文件上传到服务器解析
+ const that = this;
+ wx.uploadFile({
+ url: 'http://192.168.152.1:8090/excel/import', // 你的服务器上传地址
+ filePath: filePath,
+ name: 'file',
+ success: uploadRes => {
+ // 假设服务器返回解析后的 JSON 数据
+ const data = JSON.parse(uploadRes.data);
+ that.addStudents(data.students);
+ },
+ fail: uploadErr => {
+ console.error('文件上传失败:', uploadErr);
+ }
+ });
+ },
+
+ // 将解析后的学生数据添加到现有数组中
+ addStudents(newStudents) {
+ const currentStudents = this.data.students;
+ const allStudents = currentStudents.concat(newStudents); // 合并数组
+ this.setData({
+ students: allStudents
+ });
+ },
+
+ //点击输入框提示可以输入
+ focus: function(){
+ wx.showToast({
+ title: '可以开始输入了',
+ icon: 'none',
+ duration: 2000
+ });
+ },
+
+ cantNull: function(){
+ wx.showToast({
+ title: '输入框不可为空',
+ icon: 'none',
+ duration: 2000
+ });
+ },
+
+ addProcess: function(){
+ if(this.data.input != ""){
+ //分割字符串为数组
+ let firstArray = this.data.input.split("|");
+ console.log(firstArray);
+ let secondArray = firstArray.map(str => str.split(" "));
+ console.log(secondArray)
+ //遍历secondArray
+ secondArray.forEach(subArray => {
+ // 结构法从子数组中提取id和name
+ //等同于 const id = subArray[0]; const name = subArray[1];
+ const { [0]: id, [1]: name } = subArray;
+
+ // 创建一个新的对象来存储这些信息
+ const newStu = {
+ id: id,
+ name: name,
+ point: 10,
+ clazz: this.data.className,
+ };
+ const isDuplicate = this.data.students.some(stu => stu.id === id);
+ if(!isDuplicate){
+ // 将新对象发送到后端服务器
+ const classstu = newStu;
+ //classstu.className = this.data.className;//此时 classstu = {id:"102201",name:"Jhon", className:`${this.data.className}` }
+ wx.request({
+ url: 'http://192.168.152.1:8090/student/set',
+ method: 'POST', // 请求方法,通常是POST用于发送数据
+ header: {
+ 'Content-Type': 'application/json' // 设置请求头,指定数据格式为JSON
+ },
+ data: newStu, // 要发送的数据,这里直接传入对象,wx.request会自动将其转换为JSON字符串(后端接收json字符串)
+ success: function(res) {
+ // 处理后端返回的响应
+ console.log('请求成功', res.data);
+ // 根据需要更新小程序页面的数据或执行其他操作
+ },
+ fail: function(err) {
+ // 处理请求失败的情况
+ console.error('请求失败', err);
+ // 可以向用户显示错误信息或执行其他错误处理操作
+ }
+ });
+ // 将新对象添加到data.stu数组中
+ this.setData({
+ ['students[' + this.data.students.length + ']']: newStu //直接将新对象加在数组后面
+ });
+ } else {
+ console.log('id重复:${id}');
+ }
+ })
+ console.log(this.data.students);
+ } else {
+ this.cantNull();
+ }
+ },
+
+ goToclass_manage: function(){
+ wx.navigateTo({
+ url: '/pages/class_manage/class_manage'
+ });
+ }
+});
\ No newline at end of file
diff --git a/前端/pages/add_stu/add_stu.json b/前端/pages/add_stu/add_stu.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/前端/pages/add_stu/add_stu.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/前端/pages/add_stu/add_stu.wxml b/前端/pages/add_stu/add_stu.wxml
new file mode 100644
index 0000000..8676f44
--- /dev/null
+++ b/前端/pages/add_stu/add_stu.wxml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ (添加学生学号 姓名用“|”隔开)
+
+
+
+
+
\ No newline at end of file
diff --git a/前端/pages/add_stu/add_stu.wxss b/前端/pages/add_stu/add_stu.wxss
new file mode 100644
index 0000000..747a827
--- /dev/null
+++ b/前端/pages/add_stu/add_stu.wxss
@@ -0,0 +1,111 @@
+/* pages/add_stu/add_stu.wxss */
+page{
+ width: 100%;
+ height: 100%;
+}
+
+.bg {
+ width: 100%;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+
+.bg image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.container {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ padding: 0 0;
+ position: relative;
+}
+
+.header {
+ position: absolute;
+ top: 20rpx;
+ left: 20rpx;
+ font-size: 60rpx;
+ font-weight: bold;
+ color: rgb(0, 0, 0);
+}
+.tip {
+ position: absolute;
+ top:100rpx;
+ left: 20rpx;
+ font-size: 40rpx;
+ font-weight: bold;
+ color: rgb(0, 0, 0);
+}
+
+.stu_textarea {
+ position: absolute;
+ border: 5rpx solid rgb(252, 252, 252);
+ top: 180rpx;
+ left: 72rpx;
+ width: 80%;
+ box-sizing: border-box;
+ font-size: 40rpx;
+ height: 300rpx;
+ color: black;
+}
+
+.add {
+ position: absolute;
+ left: 200rpx;
+ top: 525rpx;
+ display: inline-block;
+ padding: 10rpx 50rpx; /* 调整内边距以改变按钮大小 */
+ font-size: 40rpx;
+ color: rgba(0, 0, 0, 1);
+ background-color: #ffae0060; /* 按钮背景色 */
+ border: none;
+ border-radius: 100rpx; /* 初始设置为圆角矩形 */
+ text-align: center;
+ text-decoration: none;
+ overflow: hidden; /* 隐藏超出按钮范围的内容 */
+}
+.add:before {
+ left: -10rpx; /* 圆形部分在按钮左侧的位置 */
+}
+
+.add:after {
+ right: -10px; /* 圆形部分在按钮右侧的位置 */
+}
+
+.add:hover {
+ background-color: #00b30f3d; /* 鼠标悬停时按钮的背景色 */
+}
+
+.add:hover:before,
+.add:hover:after {
+ background-color: #00b31e5e; /* 鼠标悬停时圆形部分的背景色 */
+}
+
+.excel {
+ background-color: rgba(255, 166, 0, 0.486);
+ position: absolute;
+ padding: 0 0;
+ margin: 0 0;
+ width: 600rpx;
+ top: 800rpx;
+ left: 200rpx;
+ font-size: 60rpx;
+}
+
+.return {
+ position: absolute;
+ width: 200rpx;
+ height: 100rpx;
+ bottom: 100rpx;
+ right: 100rpx;
+ font-size: 60rpx;
+ background-color: rgba(255, 0, 0, 0.384);
+}
\ No newline at end of file
diff --git a/前端/pages/call_roll/call_roll.js b/前端/pages/call_roll/call_roll.js
new file mode 100644
index 0000000..6eb7325
--- /dev/null
+++ b/前端/pages/call_roll/call_roll.js
@@ -0,0 +1,179 @@
+// pages/call_roll/call_roll.js
+Page({
+
+ /**
+ * 页面的初始数据
+ */
+ data: {
+ className: "",
+ students:[
+ {
+ id: "102201",
+ name: "Jhon",
+ point: 3
+ },
+ {
+ id: "102202",
+ name: "Kun",
+ point: 2
+ },
+ {
+ id: "102203",
+ name: "Tom",
+ point: 2
+ },
+ ],
+ rolling: false, // 控制是否滚动
+ currentStudentIndex: 0, // 当前选中学生索引
+ currentStudentName: "开始点名", // 当前显示的学生名称
+ rollInterval: null, // 随机点名的定时器
+ point: 1, // 设置的积分
+ },
+ onLoad: function (options) {
+ clearInterval(this.data.rollInterval);//清除定时器,防止内存泄漏
+ console.log(options);
+ // options 参数包含了从上一个页面传递过来的数据
+ const receivedClassName = options.className; // 获取传递过来的 className,默认为空字符串
+ // 更新页面的数据
+ this.setData({
+ className: receivedClassName // 将接收到的 className 赋值给页面的 data 属性
+ });
+
+ // const url = `https://your-backend-server.com/api/students?className=${this.data.className}`
+ //根据className向后端请求数据
+ wx.request({
+ url: `http://192.168.152.1:8090/student/${this.data.className}`,
+ method: 'GET',
+ success: function(res) {
+ // 后端返回的数据格式如下:
+ // {
+ // students: [
+ // { id: "102201", name: "Jhon", point: 3 },
+ // { id: "102202", name: "Kun", point: 2 },
+ // { id: "102203", name: "Tom", point: 1 }
+ // ]
+ // }
+ if (res.statusCode === 200 && Array.isArray(res.data)) {
+ // 使用setData方法更新data内的students数组
+ this.setData({
+ students: res.data
+ });
+ } else {
+ console.error('请求成功但数据格式不正确或数据不是数组');
+ }
+ }.bind(this), // 注意这里使用.bind(this)来确保this指向当前页面实例
+ fail: function(err) {
+ console.error('请求失败', err);
+ }
+ });
+ },
+
+ setPoint: function(e) {
+ const value = e.detail.value;
+ // 简单的正则表达式验证,允许负号和数字
+ if (/^-?\d+(\.\d+)?$/.test(value)) {
+ this.setData({
+ point: value //string类型
+ });
+ } else {
+ // 如果输入无效,可以重置输入框的内容或显示提示
+ wx.showToast({
+ title: '请输入有效的数字',
+ icon: 'none'
+ });
+ }
+ },
+
+ // 切换随机点名
+ toggleRoll: function() {
+ const { rolling, students, point } = this.data;
+ if (!rolling) {
+ this.setData({
+ currentStudentName: students[0].name, // 设置初始显示的学生名称
+ });
+ }
+ const newRolling = !rolling;
+ if (newRolling) {
+ this.startRoll();
+ } else {
+ console.log(this.data.currentStudentName)
+ clearInterval(this.data.rollInterval);
+ }
+ this.setData({
+ rolling: newRolling
+ });
+ },
+
+ // 开始随机点名
+ startRoll: function() {
+ const { students, point } = this.data;
+ let { currentStudentIndex } = this.data;
+ const rollInterval = setInterval(() => {
+ const totalPoints = students.reduce((acc, student) => acc + student.point, 0);
+ let randomPoint = Math.random() * totalPoints;
+ let sum = 0;
+ for (let i = 0; i < students.length; i++) {
+ sum += students[i].point;
+ if (randomPoint < sum) {
+ currentStudentIndex = i;
+ break;
+ }
+ }
+ this.setData({
+ currentStudentIndex,
+ currentStudentName: students[currentStudentIndex].name
+ });
+ }, 100); // 每100毫秒更新一次
+ this.setData({
+ rollInterval
+ });
+ },
+
+ confirmPoint: function() {
+ const Point = parseInt(this.data.point);
+ const id = this.data.students[this.data.currentStudentIndex].id;
+ let finalPoint = this.data.students[this.data.currentStudentIndex].point + Point;
+ if(finalPoint % 13 === 0){
+ finalPoint += 1; //积分等于13的整数倍加一分
+ wx.showToast({
+ title: '恭喜您触发彩蛋,积分额外+1',
+ icon: '/pages/images/eggs.png'
+ });
+ }
+ // this.data.students[this.data.currentStudentIndex].point += point; 不会重新渲染视图
+ this.setData({
+ ['students[' + this.data.currentStudentIndex + '].point']: finalPoint //会重新更新并渲染视图
+ });
+ const newStu = this.data.students[this.data.currentStudentIndex];
+ //发送请求更新后端数据
+ console.log(newStu);
+ wx.request({
+ url: 'http://192.168.152.1:8090/student/update',
+ method: 'PUT',
+ data: {
+ point: newStu.point,
+ name: newStu.name //只发送修改对象
+ },
+ header: {
+ 'Content-Type': 'application/json' // 设置请求头,指定数据格式为JSON
+ },
+ success: function(res) {
+ // 处理后端返回的响应
+ console.log('发送成功', res.data);
+ // 根据需要更新小程序页面的数据或执行其他操作
+ },
+ fail: function(err) {
+ // 处理请求失败的情况
+ console.error('发送失败', err);
+ // 可以向用户显示错误信息或执行其他错误处理操作
+ }
+ });
+ },
+
+
+ goTofunction:function(){
+ wx.navigateTo({
+ url: '/pages/function/function',
+ });
+ },
+})
\ No newline at end of file
diff --git a/前端/pages/call_roll/call_roll.json b/前端/pages/call_roll/call_roll.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/前端/pages/call_roll/call_roll.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/前端/pages/call_roll/call_roll.wxml b/前端/pages/call_roll/call_roll.wxml
new file mode 100644
index 0000000..774e6cb
--- /dev/null
+++ b/前端/pages/call_roll/call_roll.wxml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ {{currentStudentName}}
+
+
+ {{name}}
+
+
+
+ 积分设置:
+
+
+
+
\ No newline at end of file
diff --git a/前端/pages/call_roll/call_roll.wxss b/前端/pages/call_roll/call_roll.wxss
new file mode 100644
index 0000000..e2a7427
--- /dev/null
+++ b/前端/pages/call_roll/call_roll.wxss
@@ -0,0 +1,113 @@
+/* pages/call_roll/call_roll.wxss */
+.bg {
+ width: 100%;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+
+.bg image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.container {
+ width: 100%;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ padding: 0 0;
+ position: relative;
+}
+
+
+.student-list {
+ top: 400rpx;
+ left: 220rpx;
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+}
+
+.student-list button{
+ position: absolute;
+ top: 100rpx;
+ background-color: rgba(234, 0, 255, 0.171);
+}
+
+.student-item {
+ margin-bottom: 20rpx;
+ opacity: 0.5; /* 默认透明度 */
+}
+
+.selected {
+ opacity: 1; /* 选中的透明度 */
+ font-weight: bold;
+}
+
+.student-name {
+ position: absolute;
+ top: 100rpx;
+ left: 220rpx;
+ font-size: 80rpx;
+ text-align: center;
+ margin: 20rpx 0;
+ font-weight: bold;
+}
+
+.tip {
+ font-size: 40rpx;
+ position: absolute;
+ top: 623rpx;
+ left: 200rpx;
+}
+
+.number {
+ height: 100rpx;
+ font-size: 40rpx;
+ position: absolute;
+ top: 600rpx;
+ left: 400rpx;
+}
+
+.confirmPoint {
+ position: absolute;
+ top: 700rpx;
+ left: 220rpx;
+ background-color: rgba(222, 184, 135, 0.699);
+}
+
+.return {
+ position: absolute;
+ right: 10rpx;
+ bottom: 40rpx;
+ display: inline-block;
+ padding: 10rpx 50rpx; /* 调整内边距以改变按钮大小 */
+ font-size: 40rpx;
+ color: rgba(0, 0, 0, 1);
+ background-color: #ffae00; /* 按钮背景色 */
+ border: none;
+ border-radius: 100rpx; /* 初始设置为圆角矩形 */
+ text-align: center;
+ text-decoration: none;
+ overflow: hidden; /* 隐藏超出按钮范围的内容 */
+}
+.return:before {
+ left: -10rpx; /* 圆形部分在按钮左侧的位置 */
+}
+
+.return:after {
+ right: -10px; /* 圆形部分在按钮右侧的位置 */
+}
+
+.return:hover {
+ background-color: #b30000; /* 鼠标悬停时按钮的背景色 */
+}
+
+.return:hover:before,
+.return:hover:after {
+ background-color: #b30000; /* 鼠标悬停时圆形部分的背景色 */
+}
\ No newline at end of file
diff --git a/前端/pages/classSelector/classSelector.js b/前端/pages/classSelector/classSelector.js
new file mode 100644
index 0000000..0adf8c5
--- /dev/null
+++ b/前端/pages/classSelector/classSelector.js
@@ -0,0 +1,37 @@
+Component({
+ properties: {
+ visible: {
+ type: Boolean,
+ value: false
+ },
+ classList: {
+ type: Array,
+ value: []
+ }
+ },
+ data: {
+ selectedClassName: ''
+ },
+ methods: {
+ selectClass(e) {
+ this.setData({
+ selectedClassName: e.currentTarget.dataset.name
+ });
+ },
+ confirmSelection() {
+ if (this.data.selectedClassName) {
+ this.triggerEvent('confirm', { className: this.data.selectedClassName });
+ this.setData({ visible: false }); // 隐藏弹窗
+ } else {
+ wx.showToast({
+ title: '请选择班级',
+ icon: 'none'
+ });
+ }
+ },
+ cancelSelection() {
+ this.setData({ visible: false }); // 隐藏弹窗
+ this.triggerEvent('cancel'); // 可选:触发取消事件
+ }
+ }
+});
\ No newline at end of file
diff --git a/前端/pages/classSelector/classSelector.json b/前端/pages/classSelector/classSelector.json
new file mode 100644
index 0000000..e8cfaaf
--- /dev/null
+++ b/前端/pages/classSelector/classSelector.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/前端/pages/classSelector/classSelector.wxml b/前端/pages/classSelector/classSelector.wxml
new file mode 100644
index 0000000..75a1021
--- /dev/null
+++ b/前端/pages/classSelector/classSelector.wxml
@@ -0,0 +1,13 @@
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/前端/pages/classSelector/classSelector.wxss b/前端/pages/classSelector/classSelector.wxss
new file mode 100644
index 0000000..7ec248c
--- /dev/null
+++ b/前端/pages/classSelector/classSelector.wxss
@@ -0,0 +1,33 @@
+/* 添加适当的样式来定位和美化弹窗 */
+.class-selector-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.class-selector {
+ background: white;
+ padding: 20px;
+ border-radius: 10px;
+ /* 其他样式 */
+}
+
+.class-item {
+ /* 班级项的默认样式 */
+ margin: 10rpx;
+ padding: 10rpx;
+ border-bottom: 1px solid rgb(21, 255, 0);
+}
+
+.class-item.selected {
+ /* 选中后的样式 */
+ background-color: #007aff; /* 例如,蓝色背景 */
+ color: white; /* 白色文字 */
+}
+
diff --git a/前端/pages/class_manage/class_manage.js b/前端/pages/class_manage/class_manage.js
new file mode 100644
index 0000000..a638c81
--- /dev/null
+++ b/前端/pages/class_manage/class_manage.js
@@ -0,0 +1,266 @@
+// pages/classManagement/classManagement.js
+Page({
+ data: {
+ index: -1, //创建索引,知道此时选中哪个班级
+ showModal1: false, // 控制弹窗显示
+ showModal2: false,
+ showElement: false,
+ className: "", // 绑定输入框的值
+ classList: [
+ { name: '班级1' ,id:1},
+ { name: '班级2' ,id:2},
+ { name: '班级3' ,id:3}
+ ]
+ },
+
+ onLoad: function(options) {
+ // 发起网络请求以获取classList数据
+ wx.request({
+ url: 'http://192.168.152.1:8090/clazz/list', // 请替换为你的实际后端接口地址
+ method: 'GET', // 根据你的后端接口要求选择请求方法
+ success: (res) => {
+ // 请求成功的回调函数
+ if (res.statusCode === 200) {
+ try {
+ // 后端返回的数据格式{ "data": [{ "name": "" }, ...] }
+ // 小程序 SDK 会自动解析 JSON 字符串为对象,所以这里直接使用 res.data
+ const responseData = {
+ data:res.data
+ }
+ if (Array.isArray(responseData.data)) {
+ // 如果返回的数据中包含data数组,则将其赋值给classList
+ this.setData({
+ classList: responseData.data
+ });
+ } else {
+ // 如果返回的数据格式不正确,则输出错误信息
+ console.error('返回的数据格式不正确,期望包含data数组', responseData);
+ }
+ } catch (error) {
+ // 如果解析JSON时出错,则输出错误信息
+ console.error('解析JSON数据时出错', error);
+ }
+ } else {
+ // 如果请求失败(状态码不是200),则输出错误信息
+ console.error('请求失败,状态码:', res.statusCode);
+ }
+ },
+ fail: (err) => {
+ // 请求失败的回调函数
+ console.error('请求出错', err);
+ }
+ });
+ },
+
+ showElement: function() {
+ this.setData({
+ showElement: !this.data.showElement // 切换showElement的值
+ });
+ },
+
+ // 显示弹窗
+ showModal1: function() {
+ this.setData({
+ showModal1: true
+ });
+ },
+
+ // 隐藏弹窗
+ hideModal1: function() {
+ this.setData({
+ showModal1: false
+ });
+ },
+
+ // 输入班级名称
+ inputChange: function(e) {
+ this.setData({
+ className: e.detail.value
+ });
+ },
+
+ // 添加班级
+ addClass: function() {
+ if (this.data.className.trim() === "") {
+ wx.showToast({
+ title: '班级名称不能为空',
+ icon: 'none'
+ });
+ return;
+ }
+ //将班级名称加入后端
+ wx.request({
+ url: 'http://192.168.152.1:8090/clazz/save',
+ method: 'POST',
+ data:{
+ name: this.data.className
+ },
+ success: function(res) {
+ // 处理后端返回的响应
+ console.log('添加成功', res.data);
+ // 根据需要更新小程序页面的数据或执行其他操作
+ },
+ fail: function(err) {
+ // 处理请求失败的情况
+ console.error('添加失败', err);
+ // 可以向用户显示错误信息或执行其他错误处理操作
+ }
+ })
+ // 将班级名称添加到页面的列表中
+ const newClassList = this.data.classList.concat({ name: this.data.className });
+ this.setData({
+ classList: newClassList, // 更新班级列表
+ className: "", // 清空输入框
+ showModal1: false // 隐藏弹窗
+ });
+ wx.showToast({
+ title: '班级添加成功',
+ icon: 'success'
+ });
+ },
+
+ goToadd_stu:function(){
+ const Name = this.data.classList[this.data.index].name
+ const queryString = `className=${Name}`;
+ wx.navigateTo({
+ url: `/pages/add_stu/add_stu?${queryString}`,//构造包含数据的url
+ success: function(res) {
+ // 跳转成功的回调
+ },
+ fail: function(err) {
+ // 跳转失败的回调
+ console.error('跳转失败', err);
+ }
+ });
+ },
+
+ goToclass_message:function(){
+ const Name = this.data.classList[this.data.index].name
+ const queryString = `className=${Name}`;
+ wx.navigateTo({
+ url: `/pages/class_message/class_message?${queryString}`,//构造包含数据的url
+ success: function(res) {
+ // 跳转成功的回调
+ },
+ fail: function(err) {
+ // 跳转失败的回调
+ console.error('跳转失败', err);
+ }
+ })
+ },
+
+ showAndGet: function(event) {
+ //显示元素
+ this.showElement();
+ // 从事件对象中获取data-index属性的值
+ const index = event.currentTarget.dataset.index;
+ // 成功获取console.log(index);
+ this.setData({
+ index: index
+ });
+ },
+
+ delete_class: function(){
+ //将删除班级传入后端
+ //取得要删除的班级名字
+ const className = this.data.classList[this.data.index];
+ const nameUsingDot = `${className.name}`;
+ console.log(nameUsingDot);
+ // const url = `https://your-backend-server.com/api/classes/className=${className}`;
+ wx.request({
+ url: `http://192.168.152.1:8090/clazz/${nameUsingDot}`,
+ method: 'DELETE', // 使用DELETE方法请求删除资源
+ header: {
+ 'Content-Type': 'application/json', // 根据后端要求设置请求头
+ // 如果后端需要身份验证,您可能还需要在这里添加Authorization头
+ },
+ success: function(res) {
+ // 处理后端返回的响应
+ if (res.statusCode === 200 || res.statusCode === 204) { // 200表示成功,204表示成功且无内容返回
+ console.log('班级删除成功');
+ // 根据需要执行后续操作,如更新页面上的班级列表等
+ } else {
+ console.error('班级删除失败,状态码:', res.statusCode);
+ // 可以向用户显示错误信息或执行其他错误处理操作
+ }
+ },
+ fail: function(err) {
+ // 处理请求失败的情况
+ console.error('请求失败', err);
+ // 可以向用户显示错误信息或执行其他错误处理操作
+ }
+ });
+
+ //删除自己页面内的数据
+ // const newClassList = this.data.classList.splice(this.data.index, 1);
+ this.data.classList.splice(this.data.index, 1);
+ this.setData({
+ classList: this.data.classList, // 更新班级列表
+ className: "", // 清空输入框
+ showModal1: false, // 隐藏弹窗
+ showElement: false,
+ index: -1
+ });
+ console.log(this.data.classList);
+ },
+
+
+
+ change_name:function(){
+ if (this.data.className.trim() === "") {
+ wx.showToast({
+ title: '班级名称不能为空',
+ icon: 'none'
+ });
+ return;
+ }
+ //记录原名字
+ const id = this.data.classList[this.data.index].id
+ //记录要修改名字*
+ const name = this.data.className;
+ console.log(id);
+ console.log(name);
+ wx.request({
+ url: `http://192.168.152.1:8090/clazz/update`,
+ method: 'PUT',
+ data: {
+ id: id,
+ name: name
+ },
+
+ success(res) {
+ // 处理后端返回的成功响应
+ console.log('班级名字更新成功', res.data);
+ },
+ fail(err) {
+ // 处理请求失败的情况
+ console.error('更新班级名字失败', err);
+ }
+ })
+
+ // 班级名称修改页面的列表中
+ this.data.classList[this.data.index].name = this.data.className;
+ this.setData({
+ classList: this.data.classList, // 更新班级列表
+ className: "", // 清空输入框
+ showModal2: false // 隐藏弹窗
+ });
+ wx.showToast({
+ title: '班级修改成功',
+ icon: 'success'
+ });
+ },
+
+ showModal2: function() {
+ this.setData({
+ showModal2: true
+ });
+ },
+
+ // 隐藏弹窗
+ hideModal2: function() {
+ this.setData({
+ showModal2: false
+ });
+ },
+});
\ No newline at end of file
diff --git a/前端/pages/class_manage/class_manage.json b/前端/pages/class_manage/class_manage.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/前端/pages/class_manage/class_manage.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/前端/pages/class_manage/class_manage.wxml b/前端/pages/class_manage/class_manage.wxml
new file mode 100644
index 0000000..6ea2300
--- /dev/null
+++ b/前端/pages/class_manage/class_manage.wxml
@@ -0,0 +1,31 @@
+
+
+
+
+
+ 班级列表
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/前端/pages/class_manage/class_manage.wxss b/前端/pages/class_manage/class_manage.wxss
new file mode 100644
index 0000000..6f11993
--- /dev/null
+++ b/前端/pages/class_manage/class_manage.wxss
@@ -0,0 +1,139 @@
+/* pages/class_manage/class_manage.wxss */
+/* page覆盖全页面 */
+page{
+ width: 100%;
+ height: 100%;
+}
+
+.bg {
+ width: 100%;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+
+.bg image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.container {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ padding: 0 0;
+ position: relative;
+}
+
+.class_list {
+ position: absolute;
+ top: 20rpx;
+ left: 10rpx;
+ font-size: 65rpx;
+ font-weight: bold;
+}
+
+
+.add {
+ position: absolute;
+ right: 10rpx;
+ top: 30rpx;
+ display: inline-block;
+ padding: 10rpx 50rpx; /* 调整内边距以改变按钮大小 */
+ font-size: 40rpx;
+ color: rgba(0, 0, 0, 1);
+ background-color: #ffae00; /* 按钮背景色 */
+ border: none;
+ border-radius: 100rpx; /* 初始设置为圆角矩形 */
+ text-align: center;
+ text-decoration: none;
+ overflow: hidden; /* 隐藏超出按钮范围的内容 */
+}
+.add:before {
+ left: -10rpx; /* 圆形部分在按钮左侧的位置 */
+}
+
+.add:after {
+ right: -10px; /* 圆形部分在按钮右侧的位置 */
+}
+
+.add:hover {
+ background-color: #b30000; /* 鼠标悬停时按钮的背景色 */
+}
+
+.add:hover:before,
+.add:hover:after {
+ background-color: #b30000; /* 鼠标悬停时圆形部分的背景色 */
+}
+
+.modal-input {
+ margin: 50rpx;
+}
+
+.first_modal {
+ border: 1rpx solid #ccc;
+ padding: 0rpx;
+ border-radius: 5rpx;
+ width: 100%;
+ box-sizing: border-box;
+ height: 100rpx;
+ font-size: 40rpx;
+}
+
+.list {
+ width: 100%;
+ position: absolute;
+ top: 120rpx;
+ display: flex;
+ flex-direction: column;
+}
+
+.class_item {
+ width: 100%;
+ padding: 20rpx;
+ background-color: #ffffff34;
+ margin-bottom: 5rpx;
+ border-radius: 5rpx;
+ display: flex;
+ flex-direction: row;
+}
+.class_item text {
+ font-size: 50rpx;
+ font-weight: bold;
+}
+
+.class_item image {
+ width: 40rpx;
+ height: 40rpx;
+ object-fit: cover;
+ position: absolute;
+ right: 20rpx;
+ margin: 13rpx;
+}
+
+.hide {
+ width: 100%;
+ height: 500rpx;
+ position: absolute;
+ bottom: 40rpx;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.hide_item {
+ width: 600rpx;
+ margin: 10rpx 0;
+ padding: 10rpx;
+ font-size: 55rpx;
+ /* transition: font-style 0.3s; */
+ background-color: transparent;
+ color: rgb(255, 255, 255);
+}
+.hide_item:hover {
+ font-style: italic;
+}
diff --git a/前端/pages/class_message/class_message.js b/前端/pages/class_message/class_message.js
new file mode 100644
index 0000000..70f68d2
--- /dev/null
+++ b/前端/pages/class_message/class_message.js
@@ -0,0 +1,66 @@
+Page({
+ data:{
+ className: "",
+ students:[
+ ]
+ },
+ onLoad: function(options) {
+ console.log(options);
+ // options 参数包含了从上一个页面传递过来的数据
+ const receivedClassName = options.className; // 获取传递过来的 className,默认为空字符串
+ // 更新页面的数据
+ this.setData({
+ className: receivedClassName // 将接收到的 className 赋值给页面的 data 属性
+
+ });
+
+ // const url = `https://your-backend-server.com/api/students?className=${this.data.className}`
+ //根据className向后端请求数据
+ wx.request({
+ url: `http://192.168.152.1:8090/student/${this.data.className}`,
+ method: 'GET',
+ success: function(res) {
+ console.log(res.data)
+ // 后端返回的数据格式如下:
+ // {
+ // students: [
+ // { id: "102201", name: "Jhon" },
+ // { id: "102202", name: "Kun" },
+ // { id: "102203", name: "Tom" }
+ // ]
+ // }
+
+ // const formattedData = {
+ // students: res.data.map(data => ({
+ // id: data.id,
+ // name: data.name,
+ // point: data.point,
+ // clazz: data.clazz
+ // }))
+ // };
+ if (res.statusCode === 200) {
+ // 使用setData方法更新data内的students数组
+
+ // this.setData({
+ // students: formattedData
+ // });
+ this.setData({
+ students: res.data,
+ });
+
+ } else {
+ console.error('请求成功但数据格式不正确或数据不是数组');
+ }
+ }.bind(this), // 注意这里使用.bind(this)来确保this指向当前页面实例
+ fail: function(err) {
+ console.error('请求失败', err);
+ }
+ });
+
+
+ console.log(this.data.className);
+ },
+
+
+
+});
\ No newline at end of file
diff --git a/前端/pages/class_message/class_message.json b/前端/pages/class_message/class_message.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/前端/pages/class_message/class_message.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/前端/pages/class_message/class_message.wxml b/前端/pages/class_message/class_message.wxml
new file mode 100644
index 0000000..1e2aaf0
--- /dev/null
+++ b/前端/pages/class_message/class_message.wxml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ {{item.id}}
+ {{item.name}}
+
+
\ No newline at end of file
diff --git a/前端/pages/class_message/class_message.wxss b/前端/pages/class_message/class_message.wxss
new file mode 100644
index 0000000..f99a11c
--- /dev/null
+++ b/前端/pages/class_message/class_message.wxss
@@ -0,0 +1,38 @@
+/* pages/class_message/class_message.wxss */
+.bg {
+ width: 100%;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+
+.bg image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.container {
+ width: 100%;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ padding: 0 0;
+ position: relative;
+}
+
+.stu_list {
+ font-size: 60rpx;
+}
+.stu_list .id {
+ position: relative;
+ left: 50rpx;
+}
+
+.stu_list .name {
+ position: relative;
+ left: 150rpx;
+}
+
diff --git a/前端/pages/function/function.js b/前端/pages/function/function.js
new file mode 100644
index 0000000..8b9e34e
--- /dev/null
+++ b/前端/pages/function/function.js
@@ -0,0 +1,119 @@
+// pages/function/function.js
+Page({
+ data: {
+ classSelectorVisible1: false, //随机点名
+ classSelectorVisible2: false, //积分记录
+ classList: [
+ { name: "班级一" },
+ { name: "班级二" },
+ { name: "班级三" },
+ ],
+ // ... 其他数据
+ },
+
+ //加载页面classList(可以与class_manage的接口复用)
+ onLoad: function(options) {
+ // 发起网络请求以获取classList数据
+ wx.request({
+ url: 'http://192.168.152.1:8090/clazz/list', // 请替换为你的实际后端接口地址
+ method: 'GET', // 根据你的后端接口要求选择请求方法
+ success: (res) => {
+ // 请求成功的回调函数
+ if (res.statusCode === 200) {
+
+ try {
+ // 后端返回的数据格式{ "data": [{ "name": "" }, ...] }
+ // 小程序 SDK 会自动解析 JSON 字符串为对象,所以这里直接使用 res.data
+ const responseData = {
+ data:res.data
+ }
+ if (Array.isArray(responseData.data)) {
+ // 如果返回的数据中包含data数组,则将其赋值给classList
+ this.setData({
+ classList: responseData.data
+ });
+ } else {
+ // 如果返回的数据格式不正确,则输出错误信息
+ console.error('返回的数据格式不正确,期望包含data数组', responseData);
+ }
+ } catch (error) {
+ // 如果解析JSON时出错,则输出错误信息
+ console.error('解析JSON数据时出错', error);
+ }
+ } else {
+ // 如果请求失败(状态码不是200),则输出错误信息
+ console.error('请求失败,状态码:', res.statusCode);
+ }
+ },
+ fail: (err) => {
+ // 请求失败的回调函数
+ console.error('请求出错', err);
+ }
+ });
+ },
+
+
+ // 班级管理
+ goToclass_manage: function() {
+ wx.navigateTo({
+ url: '/pages/class_manage/class_manage'
+ });
+ },
+ // 随机点名
+ goTocall_roll: function() {
+ this.setData({ classSelectorVisible1: true });
+ },
+ // 考勤管理
+ goTorecord: function() {
+ this.setData({ classSelectorVisible2: true });
+ },
+
+
+ //随机点名
+ handleClassConfirm1(e) {
+ const className = e.detail.className;
+ // 这里可以处理选择后的逻辑,比如跳转到录音页面并传递 className
+ console.log(className)
+ this.setData({ classSelectorVisible: false }); // 隐藏弹窗
+ const queryString = `className=${className}`;
+
+ wx.navigateTo({
+ url: `/pages/call_roll/call_roll?${queryString}`,//构造包含数据的url
+ success: function(res) {
+ // 跳转成功的回调
+ },
+ fail: function(err) {
+ // 跳转失败的回调
+ console.error('跳转失败', err);
+ }
+ })
+ },
+ handleClassCancel1() {
+ this.setData({ classSelectorVisible: false }); // 隐藏弹窗
+ // 可选:处理取消选择的逻辑
+ },
+
+ //积分记录
+ handleClassConfirm2(e) {
+ const className = e.detail.className;
+ // 这里可以处理选择后的逻辑,比如跳转到录音页面并传递 className
+ console.log(className)
+ this.setData({ classSelectorVisible: false }); // 隐藏弹窗
+ //传参给记录页面
+ const queryString = `className=${className}`;
+ wx.navigateTo({
+ url: `/pages/record/record?${queryString}`,//构造包含数据的url
+ success: function(res) {
+ // 跳转成功的回调
+ },
+ fail: function(err) {
+ // 跳转失败的回调
+ console.error('跳转失败', err);
+ }
+ })
+ },
+ handleClassCancel2() {
+ this.setData({ classSelectorVisible: false }); // 隐藏弹窗
+ // 可选:处理取消选择的逻辑
+ },
+});
\ No newline at end of file
diff --git a/前端/pages/function/function.json b/前端/pages/function/function.json
new file mode 100644
index 0000000..a662dbd
--- /dev/null
+++ b/前端/pages/function/function.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {"class-selector" :"/pages/classSelector/classSelector"}
+}
\ No newline at end of file
diff --git a/前端/pages/function/function.wxml b/前端/pages/function/function.wxml
new file mode 100644
index 0000000..afb56df
--- /dev/null
+++ b/前端/pages/function/function.wxml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+ 首
+ 页
+
+
+
+
\ No newline at end of file
diff --git a/前端/pages/function/function.wxss b/前端/pages/function/function.wxss
new file mode 100644
index 0000000..a845090
--- /dev/null
+++ b/前端/pages/function/function.wxss
@@ -0,0 +1,70 @@
+/* pages/function/function.wxss */
+/* pages/function/function.wxss */
+page{
+ width: 100%;
+ height: 100%;
+}
+
+.bg {
+ width: 100%;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+
+.bg image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.container {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ /* 把默认的padding: 200rpx 0;改掉 */
+ padding: 0 0;
+ position: relative;
+}
+
+.text {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ top: 20rpx;
+ left: 40rpx;
+}
+
+.title {
+ /* 设置字体粗细 */
+ font-weight: bold;
+ padding: 10rpx 0;
+ font-size: 80rpx;
+}
+
+.menu {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ top: 300rpx;
+}
+
+.menu-item {
+ margin: 10rpx 0;
+ padding: 10rpx;
+ font-size: 65rpx;
+ /* transition: font-style 0.3s; */
+ background-color: transparent;
+ /* 相对定位 */
+ position: relative;
+ right: 210rpx;
+}
+
+.menu-item:hover {
+ font-style: italic;
+}
\ No newline at end of file
diff --git a/前端/pages/images/add_stu.png b/前端/pages/images/add_stu.png
new file mode 100644
index 0000000..8455e8c
Binary files /dev/null and b/前端/pages/images/add_stu.png differ
diff --git a/前端/pages/images/arrow_icon.png b/前端/pages/images/arrow_icon.png
new file mode 100644
index 0000000..42c9369
Binary files /dev/null and b/前端/pages/images/arrow_icon.png differ
diff --git a/前端/pages/images/call_roll.png b/前端/pages/images/call_roll.png
new file mode 100644
index 0000000..97fcdfd
Binary files /dev/null and b/前端/pages/images/call_roll.png differ
diff --git a/前端/pages/images/class_manage.png b/前端/pages/images/class_manage.png
new file mode 100644
index 0000000..82ab0e1
Binary files /dev/null and b/前端/pages/images/class_manage.png differ
diff --git a/前端/pages/images/class_message.png b/前端/pages/images/class_message.png
new file mode 100644
index 0000000..af968d8
Binary files /dev/null and b/前端/pages/images/class_message.png differ
diff --git a/前端/pages/images/eggs.png b/前端/pages/images/eggs.png
new file mode 100644
index 0000000..5bae949
Binary files /dev/null and b/前端/pages/images/eggs.png differ
diff --git a/前端/pages/images/function.png b/前端/pages/images/function.png
new file mode 100644
index 0000000..e260ff8
Binary files /dev/null and b/前端/pages/images/function.png differ
diff --git a/前端/pages/images/record.png b/前端/pages/images/record.png
new file mode 100644
index 0000000..7032480
Binary files /dev/null and b/前端/pages/images/record.png differ
diff --git a/前端/pages/images/welcome.png b/前端/pages/images/welcome.png
new file mode 100644
index 0000000..f7f58c9
Binary files /dev/null and b/前端/pages/images/welcome.png differ
diff --git a/前端/pages/index/index.js b/前端/pages/index/index.js
new file mode 100644
index 0000000..a8d6aa5
--- /dev/null
+++ b/前端/pages/index/index.js
@@ -0,0 +1,49 @@
+// index.js
+const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
+
+Page({
+ data: {
+ motto: 'Hello World',
+ userInfo: {
+ avatarUrl: defaultAvatarUrl,
+ nickName: '',
+ },
+ hasUserInfo: false,
+ canIUseGetUserProfile: wx.canIUse('getUserProfile'),
+ canIUseNicknameComp: wx.canIUse('input.type.nickname'),
+ },
+ bindViewTap() {
+ wx.navigateTo({
+ url: '../logs/logs'
+ })
+ },
+ onChooseAvatar(e) {
+ const { avatarUrl } = e.detail
+ const { nickName } = this.data.userInfo
+ this.setData({
+ "userInfo.avatarUrl": avatarUrl,
+ hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
+ })
+ },
+ onInputChange(e) {
+ const nickName = e.detail.value
+ const { avatarUrl } = this.data.userInfo
+ this.setData({
+ "userInfo.nickName": nickName,
+ hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
+ })
+ },
+ getUserProfile(e) {
+ // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
+ wx.getUserProfile({
+ desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
+ success: (res) => {
+ console.log(res)
+ this.setData({
+ userInfo: res.userInfo,
+ hasUserInfo: true
+ })
+ }
+ })
+ },
+})
diff --git a/前端/pages/index/index.json b/前端/pages/index/index.json
new file mode 100644
index 0000000..b55b5a2
--- /dev/null
+++ b/前端/pages/index/index.json
@@ -0,0 +1,4 @@
+{
+ "usingComponents": {
+ }
+}
\ No newline at end of file
diff --git a/前端/pages/index/index.wxml b/前端/pages/index/index.wxml
new file mode 100644
index 0000000..0721ba0
--- /dev/null
+++ b/前端/pages/index/index.wxml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+ 昵称
+
+
+
+
+
+ 请使用2.10.4及以上版本基础库
+
+
+
+ {{userInfo.nickName}}
+
+
+
+ {{motto}}
+
+
+
diff --git a/前端/pages/index/index.wxss b/前端/pages/index/index.wxss
new file mode 100644
index 0000000..1ebed4b
--- /dev/null
+++ b/前端/pages/index/index.wxss
@@ -0,0 +1,62 @@
+/**index.wxss**/
+page {
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+.scrollarea {
+ flex: 1;
+ overflow-y: hidden;
+}
+
+.userinfo {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ color: #aaa;
+ width: 80%;
+}
+
+.userinfo-avatar {
+ overflow: hidden;
+ width: 128rpx;
+ height: 128rpx;
+ margin: 20rpx;
+ border-radius: 50%;
+}
+
+.usermotto {
+ margin-top: 200px;
+}
+
+.avatar-wrapper {
+ padding: 0;
+ width: 56px !important;
+ border-radius: 8px;
+ margin-top: 40px;
+ margin-bottom: 40px;
+}
+
+.avatar {
+ display: block;
+ width: 56px;
+ height: 56px;
+}
+
+.nickname-wrapper {
+ display: flex;
+ width: 100%;
+ padding: 16px;
+ box-sizing: border-box;
+ border-top: .5px solid rgba(0, 0, 0, 0.1);
+ border-bottom: .5px solid rgba(0, 0, 0, 0.1);
+ color: black;
+}
+
+.nickname-label {
+ width: 105px;
+}
+
+.nickname-input {
+ flex: 1;
+}
diff --git a/前端/pages/logs/logs.js b/前端/pages/logs/logs.js
new file mode 100644
index 0000000..85f6aac
--- /dev/null
+++ b/前端/pages/logs/logs.js
@@ -0,0 +1,18 @@
+// logs.js
+const util = require('../../utils/util.js')
+
+Page({
+ data: {
+ logs: []
+ },
+ onLoad() {
+ this.setData({
+ logs: (wx.getStorageSync('logs') || []).map(log => {
+ return {
+ date: util.formatTime(new Date(log)),
+ timeStamp: log
+ }
+ })
+ })
+ }
+})
diff --git a/前端/pages/logs/logs.json b/前端/pages/logs/logs.json
new file mode 100644
index 0000000..b55b5a2
--- /dev/null
+++ b/前端/pages/logs/logs.json
@@ -0,0 +1,4 @@
+{
+ "usingComponents": {
+ }
+}
\ No newline at end of file
diff --git a/前端/pages/logs/logs.wxml b/前端/pages/logs/logs.wxml
new file mode 100644
index 0000000..85cf1bf
--- /dev/null
+++ b/前端/pages/logs/logs.wxml
@@ -0,0 +1,6 @@
+
+
+
+ {{index + 1}}. {{log.date}}
+
+
diff --git a/前端/pages/logs/logs.wxss b/前端/pages/logs/logs.wxss
new file mode 100644
index 0000000..33f9d9e
--- /dev/null
+++ b/前端/pages/logs/logs.wxss
@@ -0,0 +1,16 @@
+page {
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+.scrollarea {
+ flex: 1;
+ overflow-y: hidden;
+}
+.log-item {
+ margin-top: 20rpx;
+ text-align: center;
+}
+.log-item:last-child {
+ padding-bottom: env(safe-area-inset-bottom);
+}
diff --git a/前端/pages/record/record.js b/前端/pages/record/record.js
new file mode 100644
index 0000000..c0d5f1d
--- /dev/null
+++ b/前端/pages/record/record.js
@@ -0,0 +1,66 @@
+// pages/record/record.js
+Page({
+
+ /**
+ * 页面的初始数据
+ */
+ data: {
+ className: "K班",
+ students: [
+ {
+ id: "102201",
+ name: "Jhon",
+ point: 3
+ },
+ {
+ id: "102202",
+ name: "Kun",
+ point: 2
+ },
+ {
+ id: "102202",
+ name: "Tom",
+ point: 2
+ },
+ ]
+ },
+
+ onLoad: function(options) {
+ console.log(options);
+ // options 参数包含了从上一个页面传递过来的数据
+ const receivedClassName = options.className; // 获取传递过来的 className,默认为空字符串
+ // 更新页面的数据
+ this.setData({
+ className: receivedClassName // 将接收到的 className 赋值给页面的 data 属性
+ });
+
+ // const url = `https://your-backend-server.com/api/students?className=${this.data.className}`
+ //根据className向后端请求数据
+ wx.request({
+ url: `http://192.168.152.1:8090/student/${this.data.className}`,
+ method: 'GET',
+ success: function(res) {
+ // 后端返回的数据格式如下:
+ // {
+ // students: [
+ // { id: "102201", name: "Jhon", point: 3 },
+ // { id: "102202", name: "Kun", point: 2 },
+ // { id: "102203", name: "Tom", point: 1 }
+ // ]
+ // }
+ if (res.statusCode === 200 && Array.isArray(res.data)) {
+ // 使用setData方法更新data内的students数组
+ this.setData({
+ students: res.data
+ });
+ } else {
+ console.error('请求成功但数据格式不正确或数据不是数组');
+ }
+ }.bind(this), // 注意这里使用.bind(this)来确保this指向当前页面实例
+ fail: function(err) {
+ console.error('请求失败', err);
+ }
+ });
+ },
+
+})
\ No newline at end of file
diff --git a/前端/pages/record/record.json b/前端/pages/record/record.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/前端/pages/record/record.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/前端/pages/record/record.wxml b/前端/pages/record/record.wxml
new file mode 100644
index 0000000..69a296c
--- /dev/null
+++ b/前端/pages/record/record.wxml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ 出勤状况
+
+ {{item.id}}
+ {{item.name}}
+ 积分数:{{item.point}}
+
+
\ No newline at end of file
diff --git a/前端/pages/record/record.wxss b/前端/pages/record/record.wxss
new file mode 100644
index 0000000..bc5d254
--- /dev/null
+++ b/前端/pages/record/record.wxss
@@ -0,0 +1,49 @@
+/* pages/record/record.wxss */
+.bg {
+ width: 100%;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: -1;
+}
+
+.bg image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.container {
+ width: 100%;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ padding: 0 0;
+ position: relative;
+}
+
+.title {
+ font-size: 80rpx;
+ font-weight: bold;
+ margin: 80rpx;
+}
+
+.stu_list {
+ font-size: 40rpx;
+}
+.stu_list .id {
+ position: relative;
+ left: 50rpx;
+}
+
+.stu_list .name {
+ position: relative;
+ left: 120rpx;
+}
+
+.stu_list .point {
+ position: absolute;
+ left: 500rpx;
+}
+
diff --git a/前端/pages/welcome/welcome.js b/前端/pages/welcome/welcome.js
new file mode 100644
index 0000000..33436fe
--- /dev/null
+++ b/前端/pages/welcome/welcome.js
@@ -0,0 +1,9 @@
+// pages/welcome/welcome.js
+Page({
+ // 跳转到功能页面的函数
+ goToFunction: function() {
+ wx.navigateTo({
+ url: '/pages/function/function' // 跳转function页面
+ });
+ }
+});
\ No newline at end of file
diff --git a/前端/pages/welcome/welcome.json b/前端/pages/welcome/welcome.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/前端/pages/welcome/welcome.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/前端/pages/welcome/welcome.wxml b/前端/pages/welcome/welcome.wxml
new file mode 100644
index 0000000..ad8ae50
--- /dev/null
+++ b/前端/pages/welcome/welcome.wxml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/前端/pages/welcome/welcome.wxss b/前端/pages/welcome/welcome.wxss
new file mode 100644
index 0000000..a10ee27
--- /dev/null
+++ b/前端/pages/welcome/welcome.wxss
@@ -0,0 +1,21 @@
+/* pages/index/index.wxss */
+page{
+ width: 100%;
+ height: 100%;
+}
+
+.page-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%; /* 宽度100% */
+ height: 100%; /* 高度100% */
+ padding: 0;
+ margin: 0;
+}
+
+.background-image {
+ width: 100%; /* 宽度100% */
+ height: 100%; /* 高度100% */
+}
diff --git a/前端/project.config.json b/前端/project.config.json
new file mode 100644
index 0000000..73cc8c4
--- /dev/null
+++ b/前端/project.config.json
@@ -0,0 +1,28 @@
+{
+ "compileType": "miniprogram",
+ "libVersion": "trial",
+ "packOptions": {
+ "ignore": [],
+ "include": []
+ },
+ "setting": {
+ "coverView": true,
+ "es6": true,
+ "postcss": true,
+ "minified": true,
+ "enhance": true,
+ "showShadowRootInWxmlPanel": true,
+ "packNpmRelationList": [],
+ "babelSetting": {
+ "ignore": [],
+ "disablePlugins": [],
+ "outputPath": ""
+ }
+ },
+ "condition": {},
+ "editorSetting": {
+ "tabIndent": "auto",
+ "tabSize": 2
+ },
+ "appid": "wx008217ca2c2b30d3"
+}
\ No newline at end of file
diff --git a/前端/project.private.config.json b/前端/project.private.config.json
new file mode 100644
index 0000000..5e0c528
--- /dev/null
+++ b/前端/project.private.config.json
@@ -0,0 +1,8 @@
+{
+ "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
+ "projectname": "user",
+ "setting": {
+ "compileHotReLoad": true,
+ "urlCheck": false
+ }
+}
\ No newline at end of file
diff --git a/前端/sitemap.json b/前端/sitemap.json
new file mode 100644
index 0000000..ca02add
--- /dev/null
+++ b/前端/sitemap.json
@@ -0,0 +1,7 @@
+{
+ "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
+ "rules": [{
+ "action": "allow",
+ "page": "*"
+ }]
+}
\ No newline at end of file
diff --git a/前端/utils/util.js b/前端/utils/util.js
new file mode 100644
index 0000000..764bc2c
--- /dev/null
+++ b/前端/utils/util.js
@@ -0,0 +1,19 @@
+const formatTime = date => {
+ const year = date.getFullYear()
+ const month = date.getMonth() + 1
+ const day = date.getDate()
+ const hour = date.getHours()
+ const minute = date.getMinutes()
+ const second = date.getSeconds()
+
+ return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
+}
+
+const formatNumber = n => {
+ n = n.toString()
+ return n[1] ? n : `0${n}`
+}
+
+module.exports = {
+ formatTime
+}
diff --git a/后端/pom.xml b/后端/pom.xml
new file mode 100644
index 0000000..d13c284
--- /dev/null
+++ b/后端/pom.xml
@@ -0,0 +1,121 @@
+
+
+ 4.0.0
+ com
+ demo
+ 0.0.1-SNAPSHOT
+ demo
+ demo
+
+ 1.8
+ UTF-8
+ UTF-8
+ 2.6.13
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.2.2
+
+
+
+ cn.hutool
+ hutool-all
+ 5.8.18
+
+
+ org.apache.poi
+ poi-ooxml
+ 5.2.3
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.apache.poi
+ poi
+ 5.2.3
+
+
+
+ org.apache.poi
+ poi-ooxml
+ 5.2.3
+
+
+
+
+ commons-io
+ commons-io
+ 2.11.0
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ 1.8
+ UTF-8
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
+ com.demo.DemoApplication
+ true
+
+
+
+ repackage
+
+ repackage
+
+
+
+
+
+
+
+
diff --git a/后端/src/main/java/com/demo/DemoApplication.java b/后端/src/main/java/com/demo/DemoApplication.java
new file mode 100644
index 0000000..0b8bb6d
--- /dev/null
+++ b/后端/src/main/java/com/demo/DemoApplication.java
@@ -0,0 +1,16 @@
+package com.demo;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@MapperScan("com.demo.mapper")
+
+public class DemoApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+
+}
diff --git a/后端/src/main/java/com/demo/controller/ClazzController.java b/后端/src/main/java/com/demo/controller/ClazzController.java
new file mode 100644
index 0000000..099e04a
--- /dev/null
+++ b/后端/src/main/java/com/demo/controller/ClazzController.java
@@ -0,0 +1,40 @@
+package com.demo.controller;
+
+import com.demo.entity.Clazz;
+import com.demo.entity.Student;
+import com.demo.mapper.ClazzMapper;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@RestController
+@RequestMapping("/clazz")
+public class ClazzController {
+ @Resource
+ ClazzMapper clazzMapper;
+
+ @PostMapping("/save")
+ public String addClazz(@RequestBody Clazz clazz){
+ clazzMapper.save(clazz);
+ return "success";
+ }
+ @GetMapping("/list")
+ public List getClazz(){
+ return clazzMapper.findAll();
+ }
+ @DeleteMapping("/{name}")
+ public String deleteClazz(@PathVariable("name") String name){
+ clazzMapper.deleteByname(name);
+ return "success";
+ }
+ @PutMapping("/update")
+ public String updateClazz(@RequestBody Clazz clazz){
+ clazzMapper.updateById(clazz);
+ return "success";
+ }
+
+}
diff --git a/后端/src/main/java/com/demo/controller/ExcelController.java b/后端/src/main/java/com/demo/controller/ExcelController.java
new file mode 100644
index 0000000..4e076fc
--- /dev/null
+++ b/后端/src/main/java/com/demo/controller/ExcelController.java
@@ -0,0 +1,28 @@
+package com.demo.controller;
+
+import cn.hutool.poi.excel.ExcelReader;
+import cn.hutool.poi.excel.ExcelUtil;
+import com.demo.entity.Student;
+import com.demo.mapper.StudentMapper;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.io.InputStream;
+import java.nio.channels.MulticastChannel;
+import java.util.List;
+
+@RestController
+@RequestMapping("/excel")
+@CrossOrigin(origins = "*")
+public class ExcelController {
+ @Resource
+ private StudentMapper studentMapper;
+ @PostMapping("/import")
+ public void imp(@RequestBody MultipartFile file)throws Exception{
+ InputStream inputStream = file.getInputStream();
+ ExcelReader reader = ExcelUtil.getReader(inputStream);
+ List students = reader.readAll(Student.class);
+ studentMapper.batchInsert(students);
+ }
+}
diff --git a/后端/src/main/java/com/demo/controller/StudentController.java b/后端/src/main/java/com/demo/controller/StudentController.java
new file mode 100644
index 0000000..6e74bcb
--- /dev/null
+++ b/后端/src/main/java/com/demo/controller/StudentController.java
@@ -0,0 +1,40 @@
+package com.demo.controller;
+
+import com.demo.entity.Clazz;
+import com.demo.entity.Student;
+import com.demo.mapper.StudentMapper;
+import lombok.SneakyThrows;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@RestController
+@RequestMapping("/student")
+public class StudentController {
+ @Resource
+ StudentMapper studentMapper;
+ @GetMapping
+ public List getStudent(){
+ return studentMapper.findAll();
+ }
+ @PostMapping("/set")
+ public String addStudent(@RequestBody Student student){
+ studentMapper.save(student);
+ return "success";
+ }
+ @GetMapping("/{clazz}")
+ public List getStudent1(@PathVariable("clazz") String clazz){
+
+ return studentMapper.findByclazz(clazz);
+ }
+ @PutMapping("/update")
+ public String updateStudent(@RequestBody Student student){
+ studentMapper.updateByname(student);
+ return "success";
+ }
+
+
+
+}
diff --git a/后端/src/main/java/com/demo/entity/Clazz.java b/后端/src/main/java/com/demo/entity/Clazz.java
new file mode 100644
index 0000000..10ec305
--- /dev/null
+++ b/后端/src/main/java/com/demo/entity/Clazz.java
@@ -0,0 +1,9 @@
+package com.demo.entity;
+
+import lombok.Data;
+
+@Data
+public class Clazz {
+ private String name;
+ private int id;
+}
diff --git a/后端/src/main/java/com/demo/entity/Student.java b/后端/src/main/java/com/demo/entity/Student.java
new file mode 100644
index 0000000..5889cba
--- /dev/null
+++ b/后端/src/main/java/com/demo/entity/Student.java
@@ -0,0 +1,16 @@
+package com.demo.entity;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Student {
+ private String id;
+ private String name;
+ private int point;
+ private String clazz;
+}
diff --git a/后端/src/main/java/com/demo/mapper/ClazzMapper.java b/后端/src/main/java/com/demo/mapper/ClazzMapper.java
new file mode 100644
index 0000000..ed1e5de
--- /dev/null
+++ b/后端/src/main/java/com/demo/mapper/ClazzMapper.java
@@ -0,0 +1,25 @@
+package com.demo.mapper;
+
+import com.demo.entity.Clazz;
+import com.demo.entity.Student;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.PathVariable;
+
+import java.util.List;
+
+public interface ClazzMapper {
+ @Select("select * from classes")
+ List findAll();
+ @Insert("INSERT INTO classes (name) VALUES (#{name});")
+ @Transactional
+ void save(Clazz clazz);
+ @Delete("delete from classes where name = #{name}")
+ void deleteByname(String name);
+ @Update("update classes set name = #{name} where id = #{id}")
+ @Transactional
+ void updateById(Clazz clazz);
+}
diff --git a/后端/src/main/java/com/demo/mapper/StudentMapper.java b/后端/src/main/java/com/demo/mapper/StudentMapper.java
new file mode 100644
index 0000000..3e1fd72
--- /dev/null
+++ b/后端/src/main/java/com/demo/mapper/StudentMapper.java
@@ -0,0 +1,38 @@
+package com.demo.mapper;
+
+import com.demo.entity.Clazz;
+import com.demo.entity.Student;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+public interface StudentMapper {
+ @Select("select * from students")
+ List findAll();
+
+ @Insert("INSERT INTO students (`id`, `name`, `point`, `clazz`) VALUES (#{id},#{name},#{point},#{clazz});")
+ @Transactional
+ void save(Student student);
+
+ @Select("select * from students where clazz = #{clazz}")
+ List findByclazz(String clazz);
+
+ @Update("update students set point = #{point} where name = #{name}")
+ @Transactional
+ void updateByname(Student student);
+
+ @Insert({
+ ""
+ })
+ void batchInsert(@Param("list") List list);
+
+}
\ No newline at end of file
diff --git a/后端/src/main/resources/application.yml b/后端/src/main/resources/application.yml
new file mode 100644
index 0000000..a32cc6e
--- /dev/null
+++ b/后端/src/main/resources/application.yml
@@ -0,0 +1,8 @@
+server:
+ port: 8090
+spring:
+ datasource:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
+ username: root
+ password: 123456
\ No newline at end of file
diff --git a/后端/src/test/java/com/demo/DemoApplicationTests.java b/后端/src/test/java/com/demo/DemoApplicationTests.java
new file mode 100644
index 0000000..72afc81
--- /dev/null
+++ b/后端/src/test/java/com/demo/DemoApplicationTests.java
@@ -0,0 +1,13 @@
+package com.demo;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class DemoApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}