基于微信小程序的实验室预约系统的设计与开发

个人介绍

hello hello~ ,这里是 code袁~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
在这里插入图片描述
🦁作者简介:一名喜欢分享和记录学习的在校大学生
💥个人主页:code袁
💥 个人QQ:2647996100
🐯 个人wechat:code8896

专栏导航

code袁系列专栏导航
1.毕业设计课程设计:本专栏分享一些毕业设计的源码以及项目成果。🥰🥰🥰
2.小程序>微信小程序开发:本专栏从基础到入门的一系开发流程,并且分享了自己在开发中遇到的一系列问题。🤹🤹🤹
3.vue开发系列全程线路:本专栏分享自己的vue的学习历程。

非常期待和您一起在这个小小的互联网世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨ 

在这里插入图片描述

文章目录

        • 个人介绍
        • 专栏导航
        • 1、前言介绍
        • 2、开发技术简介
        • 3、系统功能图
        • 4、功能实现
        • 5、库表设计
        • 6、性能测试
        • 7、关键代码
        • 8、源码获取
      • 🎉写在最后

1、前言介绍

伴随着信息技术与互联网技术的不断发展,校园也进到了一个新的信息化时代,传统管理技术性没法高效率、容易地管理体育场预约信息内容。为了实现时代的发展必须,提升实验室预约高效率,各种各样实验室预约体系应时而生,实验室预约管理系统的实现是信息内容时代浪潮时代的产物之一。一切系统都要遵循系统设计的基本流程。它还需要通过市场调查、需求分析报告、汇总设计、详尽设计以及测试,根据Node语言表达设计,完成实验室预约管理系统。该系统根据B/S,即所谓的电脑浏览器/网络服务器方式,运用Node技术,前端采用uniapp小程序>微信小程序等技术实现,选用MySQL作为数据库。
实验室预约管理系统采用前后端分离的方式来实现,前端Vue、Element组件编写前端代码为主、其特点可以实时渲染加载数据,不用像以前传统的页面,写完要重新启动项目才能加载数据。系统还采用的File文件组件上传和预览图片等,以及前端利用了第三方富文本编辑器框架技术实现了实验室详情介绍和系统公告等模块。这样比传统文本框只能填写文字又来更好更直观的页面呈现方式。不仅可以上传文字,还可以直接复制网页图片文字等。实现动态渲染页面样式和内容等。

2、开发技术简介

本节介绍场馆预约平台用到的一些技术和开发环境的简介,用到开发技术主要包括:
(1)前端用到Element UI组件库、Vue框架和小程序>微信小程序
(2)后端用到Node
(3)包管理器Npm
(4)中间件Express
(5)数据库MySQL
系统开发环境主要是:前端开发工具Vscode,Hbuilder、操作系统Win10、CPU i5-9300H、内存8G。
在这里插入图片描述

3、系统功能图

实验室预约系统主要由客户端(小程序>微信小程序和安卓手机App)和Web管理端(基于Web服务器Apache Tomcat,MySQL数据库)这两个子系统组成。这两个子系统之间通过Htpp的request请求和response响应以json形式的数据交互,共同实现了实验室预约平台的功能。
客户服务端主要包括三大主要的功能模块:登录、预约和扫码签到模块。Web管理端主要包括三大主要的功能模块:用户、动态和预约模块。这六大模块还有相应的子模块,通过对子模块的实现来实现整个客户端的功能。如图4-3所示。

在这里插入图片描述

4、功能实现

系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。下图就是管理员登录页面。
在这里插入图片描述

该界面实现对实验室的添加、删除、修改等一系列功能

在这里插入图片描述

该界面实现对实验室的动态的添加、删除、修改等一系列操作

在这里插入图片描述
在这里插入图片描述

实验室预约的流程:当用户选择自己需要的预约的项目后,则需要用户选择合法的日期并且本系统的合法日期为当前日期的下一天的六天合法日期。当用户进入预约详情页面时用户可以选择预约的时间和地点。预约按钮点击后会判断用户是否登录以及是否重复预约等。若预约信息合法则同request的库生成对应订单的二维码并将预约信息存入到数据库中

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、库表设计

程序设计是离不开对应数据库的设计操作的,这样的做法就是减少数据对程序的依赖性,所以数据库的设计也是需要花费大量的日常时间来进行设计的,在设计中对程序开发需要存储的数据信息进行实体划分,先确认实体,然后设计实体的属性等操作,这种设计就是数据库设计里面不能少的必须有的E-R模型设计。为了降低程序设计的对应的数据库设计难度,开发人员也可以使用相应的工具来进行E-R模型设计,现在市面上设计E-R模型的工具有PowerDesigner建模工具,Navicat制作工具,还有微软的Visio绘图工具。为了简便起见,本程序在设计E-R模型的时候,就选用了微软的Visio这款功能强大,操作便利的绘图工具。

1.预约实体及其附属图

在这里插入图片描述
2.管理员实体及其附属图

在这里插入图片描述
3.实验室实体及其附属图

在这里插入图片描述

6、性能测试

单元测试是软件开发中的一种测试方法,用于测试代码中的最小可测试单元(通常是函数或方法),以验证其行为是否符合预期[15]。单元测试可以检测代码中的缺陷和错误,及时发现和修复代码问题,提高代码的质量和稳定性,也可以帮助开发人员快速定位问题,并提供反馈和调试信息,提高开发效率和效果。总之,单元测试是软件开发中非常重要的一环,可以帮助开发人员提高代码质量和效率,提高软件产品的质量和稳定性。

1.from base.data_read import ReadData
2.from base.response import method_post
3.import pytest

4.# ====测试数据读取====
5.def data_read():
6.    # 1. 将yaml文件读取
7.    data_dict = ReadData('data.yaml').read_data()
8.    # 2. 从字典中取数据  url  accounts
9.    url = data_dict['test_user_login']['url']
10.    accounts = data_dict['test_user_login']['accounts']
11.    # 3. 返回数据 供测试用例调用
12.    return url, accounts
13.
14.
15.class TestLogin():
16.    @pytest.mark.parametrize('url', [data_read()[0]])
17.    @pytest.mark.parametrize('accounts', data_read()[1])
18.    def test_login(self, url, accounts):
19.        # 1. 注意这里的account是列表格式
20.        print('\n>>>', type(accounts))
21.        print(accounts)
22.        # 2. 发请求
23.        response = method_post(url, json=accounts)
24.        # 3. 判断是否请求成功
25.        assert response.status_code == 200
26.        # 4. 根据返回的code判断是否登录成功
27.        code = response.json().get('code')
28.        print(response.json())
29.        assert code == 0, '登录失败!'
30.# =============测试结果==============
31.========= 1 failed, 1 passed in 11.81s ==========
7、关键代码
//index.js
//获取应用实例
const app = getApp()
const {login} =require('../../api/login')
Page({
  data: {
    phone: '',
    password: '',
    clientHeight:'',
    array: ['学生', '教师', ],
    index: 0,
  },
  onLoad(){
    var that=this
    wx.getSystemInfo({ 
      success: function (res) { 
        console.log(res.windowHeight)
          that.setData({ 
              clientHeight:res.windowHeight
        }); 
      } 
    }) 
  },
  bindType: function (e) {
    this.setData({
      index: e.detail.value
});
  },
  //协议
  goxieyi(){
   wx.navigateTo({
     url: '/pages/oppoint/oppoint',
   })
  },
  //获取输入款内容
  phone(e){
   this.setData({
     phone:e.detail.value
   })
  },
  password(e){
    this.setData({
      password:e.detail.value
    })
  },
  //登录事件
  goadmin(){
    let flag = false  //表示账户是否存在,false为初始值
    if(this.data.phone=='')
    {
      wx.showToast({
        icon:'none',
        title: '账号不能为空',
      })
    }else if(this.data.password==''){
      wx.showToast({
        icon:'none',
        title: '密码不能为空',
      })
    }else{
      let data={
        phone:this.data.phone,
        password:this.data.password,
        isadmin:this.data.index
      }
     login(data).then(res=>{
       console.log('55',res.data[0])
       wx.setStorageSync('userInfo', res.data[0])
       //添加登录状态
       wx.setStorageSync('statusLogin', true)
       wx.showToast({
        title: res.msg,
        icon:'none'
      })
       if(res.msg=="登录成功"){
        wx.switchTab({
            url: '../my/my',
          })
       }
     })
    }
  },
  register(){
    wx.navigateTo({
      url: './register',
    })
  }
})
 

<template>
  <div class="messge">
    <el-dialog title="提示" :visible.sync="dialogVisible" width="40%">
      <!-- 弹窗信息 -->
      <el-form
        ref="form"
        :model="form"
        :rules="rules"
        :inline="true"
        :before-close="handleClose"
        label-width="80px"
      >
        <el-form-item label="名称" prop="name">
          <el-input v-model="form.name" placeholder="实验室名称"></el-input>
        </el-form-item>
        <el-form-item label="开放时间" prop="openTime">
          <el-input
            v-model="form.openTime"
            placeholder="实验室开发时间"
          ></el-input>
        </el-form-item>
        <el-form-item label="地址" prop="address">
          <el-input v-model="form.address" placeholder="实验室地址"></el-input>
        </el-form-item>
        <el-form-item label="简介" prop="desc">
          <el-input v-model="form.desc" placeholder="实验室简介"></el-input>
        </el-form-item>
        <el-form-item label="负责人" prop="id">
          <el-select v-model="form.adminId" placeholder="请选择">
            <span></span>
            <el-option
              v-for="item in options"
              :key="item.id"
              :label="item.username"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="实验室logo">
          <commonUpload></commonUpload>
        </el-form-item>
      </el-form>
      <!-- 表单提交 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancle">取 消</el-button>
        <el-button type="primary" @click="submit">确 定</el-button>
      </span>
    </el-dialog>

    <div class="manage-hander">
      <!-- 添加按钮 -->
      <el-button type="primary" @click="handleAdd">+ 新增</el-button>
    </div>
    <!-- 表格 -->
    <div class="common-table">
      <el-table :data="tableData" stripe height="90%" style="width: 100%">
        <el-table-column prop="name" label="实验室名称"> </el-table-column>
        <el-table-column prop="openTime" label="实验室开放时间">
        </el-table-column>
        <el-table-column prop="address" label="实验室地址"> </el-table-column>
        <el-table-column prop="logo" label="logo">
          <template slot-scope="scope">
            <el-image
              style="width: 150px; height: 100px"
              :src="scope.row.logo"
              :preview-src-list="[scope.row.logo]"
            >
            </el-image>
          </template>
        </el-table-column>
        <el-form-item label="简介" prop="desc">
          <el-input v-model="form.desc" placeholder="实验室简介"></el-input>
        </el-form-item>
        <el-table-column label="负责人" prop="adminId">
          <template slot-scope="scope">
            <span v-for="item in options" :key="item.id">
              <span v-if="scope.row.adminId === item.id">
                {{ item.username }}
              </span>
            </span>
          </template>
        </el-table-column>
        <el-table-column prop="addr" label="操作">
          <template slot-scope="scope">
            <el-button
              type="primary "
              size="mini"
              @click="handleEdit(scope.row)"
              >编辑</el-button
            >
            <el-button
              type="danger"
              size="mini"
              @click="handleDelete(scope.row)"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页组件 -->
      <el-pagination
        class="page"
        layout="prev, pager, next"
        :total="total"
        @current-change="handlePage"
      >
      </el-pagination>
    </div>
  </div>
</template>

<script>
import commonUpload from "@/components/commonUpload.vue";
import { getPlace, addPlace, deletePlace, updatePlace } from "@/api/index";
import { allAdmin } from "@/api/reservation";
export default {
  name: "User",
  data() {
    return {
      dialogVisible: false,
      // 表单字段
      form: {
        name: "",
        openTime: "",
        address: "",
        logo: "",
        adminId: "",
        desc: "",
      },
      // 表單校驗
      rules: {
        name: [{ required: true, message: "请输入实验室名称" }],
        openTime: [{ required: true, message: "请输入实验室开发时间" }],
        address: [{ required: true, message: "请输入实验室地址" }],
        desc: [{ required: true, message: "请输入实验室简介" }],
      },
      options: [
        {
          id: "",
          username: "",
        },
      ],
      // 表单数据
      tableData: [],
      total: 0, //页面的总条数
      modelType: 0, //0表示是新增的弹窗 ,1表示的是编辑
      userFrom: {
        username: "",
      },
    };
  },
  components: {
    commonUpload,
  },
  methods: {
    // 提交
    submit() {
      if (this.modelType == 0) {
        this.$refs.form.validate((value) => {
          // 校验为真
          if (value) {
            console.log("value", this.form);
            this.form.logo = this.$store.state.upload.imgUrl;
            addPlace(this.form).then((res) => {
              // console.log(res);
              this.$message.success("添加成功");
            });
            this.$refs.form.resetFields();
            this.dialogVisible = false;
            this.getList();
          }
        });
      } else {
        this.$refs.form.validate((value) => {
          // 校验为真
          if (value) {
            console.log("value", this.form);
            updatePlace(this.form).then((res) => {
              // console.log(res);
              this.$message.success("修改成功");
            });
            this.$refs.form.resetFields();
            this.dialogVisible = false;
            this.getList();
          }
        });
      }
    },
    handle(e) {
      console.log();
      // let id = res.id;
      this.$confirm("要修改用户权限吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then((res) => {
        privalUser(e).then((res1) => {
          console.log(res1.data.data);
          this.$message.success(res1.data.data.msg);
        });
      });
    },
    // 关闭弹窗
    handleClose() {
      this.$refs.form.resetFields();
      this.dialogVisible = false;
    },
    // 点击取消按钮
    cancle() {
      this.handleClose();
    },
    // 表单的编辑
    handleEdit(res) {
      this.modelType = 1;
      this.dialogVisible = true;
      // 注意到对当前的数据进行深度拷贝
      this.form = JSON.parse(JSON.stringify(res));
    },
    //表单的删除
    handleDelete(res) {
      // let id = res.id;
      this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          // 调用删除接口
          var that = this;
          deletePlace(res).then((res) => {
            that.$message({
              type: "success",
              message: res.data.data.msg,
            });
          });
          this.getList();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    // 新增数
    handleAdd() {
      (this.modelType = 0), (this.dialogVisible = true);
      this.form = {};
    },
    getOpstions() {
      allAdmin().then((res) => {
        this.options = res.data.data.data;
      });
    },
    // 查询数据
    handleSearch() {
      searchUser(this.userFrom).then((res) => {
        console.log(res.data.data);
        this.tableData = res.data.data.data;
        // this.getList();
      });
    },
    //分页
    handlePage(val) {
      console.log(val);
    },
    // 获取数据
    getList() {
      // 采用封装的api接口方法
      getPlace().then((res) => {
        console.log("11", res.data.data.data);
        this.tableData = res.data.data.data;
      });
    },
  },
  // 挂载
  mounted() {
    this.getList();
    this.getOpstions();
  },
};
</script>

<style lang="less">
.messge {
  height: 90%;
  .common-table {
    position: relative;
    height: calc(100% - 62px);
    .page {
      position: absolute;
      bottom: 0;
      right: 20px;
    }
  }
  .manage-hander {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
}
.el-table .cell {
  img {
    height: 50rpx;
  }
}
</style>

8、源码获取

大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻

🎉写在最后

🍻伙伴们,如果你已经看到了这里,觉得这篇文章有帮助到你的话不妨点赞👍或 Star ✨支持一下哦!手动码字,如有错误,欢迎在评论区指正💬~

你的支持就是我更新的最大动力💪~
在这里插入图片描述


http://www.niftyadmin.cn/n/5471370.html

相关文章

计组第三版书例题

基础知识过一下 存储器与CPU的连接主要通过数据总线、地址总线和控制总线实现。CPU首先向存储器发送地址信号&#xff0c;然后发出读写控制信号&#xff0c;最后在数据总线上进行数据的读写操作 。这种连接方式确保了CPU能够正确地访问和控制存储器中的数据。 https://blog.cs…

Splunk Attack Range:一款针对Splunk安全的模拟测试环境创建工具

关于Splunk Attack Range Splunk Attack Range是一款针对Splunk安全的模拟测试环境创建工具&#xff0c;该工具完全开源&#xff0c;目前由Splunk威胁研究团队负责维护。 该工具能够帮助广大研究人员构建模拟攻击测试所用的本地或云端环境&#xff0c;并将数据转发至Splunk实例…

Qt文本搜索

效果&#xff1a; 按下ctrlf跳出搜索框&#xff0c;然后支持搜索next或者previous。支持搜索下一步和上一步。 嵌入框的实现 #ifndef POPFINDBOX_H #define POPFINDBOX_H#include <QWidget>class QLineEdit; class QPushButton; class PopFindBox : public QWidget {Q_O…

src挖掘技巧总结分享

src挖洞技术分享 src推荐刚入门的新手首选公益src如漏洞盒子、补天src&#xff0c;因为漏洞盒子收录范围广&#xff0c;只要是国内的站点都收入&#xff0c;相比其它src平台挖掘难度非常适合新手。后续可以尝试先从一些小的src厂商入手。 首先是熟能生巧&#xff0c;我一开始挖…

基于深度学习的电动自行车头盔佩戴检测系统

文章目录 1. 文档说明2. 运行环境说明2.1 硬件配置2.2 软件配置2.3 程序依赖库 3. 基本环境配置3.1 软件安装3.1.1 集成开发环境安装与配置3.1.2 数据库安装与配置3.1.3 编程语言安装3.1.4 CUDA和cuDNN安装与配置3.1.5 机器学习库安装 3.2 依赖库安装 4. 运行程序资源下载地 1.…

notepad++主题One Dark

<?xml version"1.0" encoding"Windows-1252" ?> <!--// # Style Name: One Dark for Notepad (Npp-1-Dark) # Author: https://60ss.github.io # Description: A close replica of the Atom "One Dark" syntax theme in Notepad. # L…

LeetCode-热题100:2. 两数相加

题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都…

windows更新驱动导致Linux虚拟机网卡找不到

windows更新驱动导致Linux虚拟机网卡找不到 1、现象2、解决过程3、参考 1、现象 原先虚拟机配置了静态IP&#xff0c;更新windows驱动后xshell连接不上这台虚拟机&#xff08;其他几台也是&#xff09;。 2、解决过程 service network restart出现一下报错&#xff1a; Rest…