器材管理板块
添加器材管理导航
src\views\home\Home.vue
src\router\index.js
src\views\equipment\Equipment.vue
<template> <div> hello! </div> </template>
测试
搜索导航+分页查询
src\views\equipment\Equipment.vue
<template> <div> <!-- 导航 --> <el-form :inline="true" class="demo-form-inline"> <div style="float: left"> <label style="margin-right: 5px">器材名称: </label> <el-input v-model="name" placeholder="请输入器材名称" style="width: 40%" /> <el-button type="primary" style="margin-left: 20px" >查询</el-button> </div> <div> <el-button type="primary" style="float: right" >+添加器材</el-button> </div> </el-form> <!-- 分页查询 --> <div> <el-table :data="records" stripe style="width: 100%"> <el-table-column prop="name" label="器材名称" width="180"> </el-table-column> <el-table-column prop="img" label="图片" width="180"> </el-table-column> <el-table-column prop="number" label="数量" width="180"> </el-table-column> <el-table-column prop="comment" label="描述" width="180"> </el-table-column> <el-table-column prop="status" label="器材状态"> <template slot-scope="scope">{{ scope.row.status === 0 ? "禁用" : "启用" }}</template> </el-table-column> <el-table-column prop="updateTime" label="最后操作时间"></el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button type="text" @click="handleUpdateStu(scope.row)">修改</el-button> <el-button type="text" @click="handleStartOrStop(scope.row)">{{ scope.row.status === 0 ? "启用" : "禁用" }}</el-button> </template> </el-table-column> </el-table> </div> </div> </template> <script> export default { data() { return { name: '', //器材名称,对应上面的输入框 page: 1, //页码 pageSize: 10, // 每页记录数 total: 0, //总记录数 records: [] //当前页要展示的数据集合 } }, } </script>
src\views\equipment\Equipment.vue
<template> <div> <el-form :inline="true" :model="formInline" class="demo-form-inline"> <div style="float: left"> <label style="margin-right: 5px">学生姓名: </label> <el-input v-model="name" placeholder="请输入学生姓名" style="width: 40%" /> <el-button type="primary" style="margin-left: 20px" @click="pageQuery()">查询</el-button> </div> <div> <el-button type="primary" style="float: right" @click="handleAddStu">+添加学生</el-button> </div> </el-form> <br> <br> <br> <div> <el-table :data="records" stripe style="width: 100%"> <el-table-column prop="name" label="学生姓名" width="180"> </el-table-column> <el-table-column prop="username" label="账号" width="180"> </el-table-column> <el-table-column prop="phone" label="手机号"> </el-table-column> <el-table-column prop="status" label="账号状态"> <template slot-scope="scope">{{ scope.row.status === 0 ? "禁用" : "启用" }}</template> </el-table-column> <el-table-column prop="updateTime" label="最后操作时间"> </el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button type="text" @click="handleUpdateStu(scope.row)">修改</el-button> <el-button type="text" @click="handleStartOrStop(scope.row)">{{ scope.row.status === 0 ? "启用" : "禁用" }}</el-button> </template> </el-table-column> </el-table> </div> <br> <div> <el-pagination class="pageList" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination> </div> </div> </template> <script> // import request from '@/utils/request' import { page, startOrStopStatus } from '@/api/Student' export default { data() { return { name: '', //学生姓名,对应上面的输入框 page: 1, //页码 pageSize: 10, // 每页记录数 total: 0, //总记录数 records: [] //当前页要展示的数据集合 } }, created() { this.pageQuery() }, methods: { pageQuery() { //准备参数 const params = { page: this.page, pageSize: this.pageSize, name: this.name } /* request({ url: "/api/admin/student/page", // 请求地址 method: "get", // 请求方法 params: params, headers: { // 请求头 "Content-Type": "application/json", }, }) */ page(params) .then((res) => { //解析结果 if (res.data.code === 1) { this.total = res.data.data.total this.records = res.data.data.records } }).catch(err => { this.$router.push("/login"); }) }, //每页记录数发生变化时触发 handleSizeChange(pageSize) { this.pageSize = pageSize this.pageQuery() }, //page发生变化时触发 handleCurrentChange(page) { this.page = page this.pageQuery() }, //新增员工 handleAddStu() { this.$router.push('/student/addStudent') }, //启用禁用员工状态 handleStartOrStop(row) { //判断账号是否是管理员账号,不能更改管理员账号 if (row.username === 'admin') { this.$message.error("这是管理员账号,不允许更改!") return } this.$confirm('是否确认修改员工状态?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { const p = { id: row.id, status: !row.status ? 1 : 0 } startOrStopStatus(p) .then(res =>{ if(res.data.code === 1){ this.$message.success("状态修改成功!") this.pageQuery() } }) }) }, //修改编辑学生信息 handleUpdateStu(row){ if(row.username === 'admin'){ this.$message.error("这是管理员账号,不允许修改!!") return } //跳转到修改页面,通过地址栏传递参数 this.$router.push({ path: '/student/addStudent', query: {id: row.id}}) } } } </script>
src\api\Equipment.js
import request from '@/utils/request' /* 分页查询 */ export const pageEquipment = (params) => request({ 'url': '/api/admin/equipment/page', 'method': 'get', params: params })
新增器材
src\router\index.js
src\views\equipment\Equipment.vue
src\views\equipment\addEquipment.vue
<template> <div>hello</div> </template>
测试
完善表单
请求
src\api\Equipment.js
import request from '@/utils/request' /* 分页查询 */ export const pageEquipment = (params) => request({ 'url': '/api/admin/equipment/page', 'method': 'get', params: params }) /* 新增器材 */ export const addEquipment = (params) => request({ 'url': '/api/admin/equipment', 'method': 'post', data: params })
新增板块的界面
src\views\equipment\addEquipment.vue
<template> <div class="form-container"> <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form-item label="器材名称:" required prop="name"> <el-input v-model="ruleForm.name"></el-input> </el-form-item> <el-form-item label="数量:" required prop="number"> <el-input v-model="ruleForm.number"></el-input> </el-form-item> <el-form-item label="描述" prop="comment"> <el-input v-model="ruleForm.comment"></el-input> </el-form-item> <el-form-item label="器材图片:" prop="img"> <div class="img-upload-container"> <!-- 监听 update:imageUrl 事件并更新 ruleForm.img --> <img-upload @update:imageUrl="handleImageUrlUpdate" /> <!-- <img-upload :prop-image-url="ruleForm.img"></img-upload> --> <span class="img-upload-instructions">图片大小不超过2M<br>仅能上传 PNG JPEG JPG类型图片<br>建议上传200*200或300*300尺寸的图片</span> </div> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')">保存</el-button> <el-button @click="$router.push('/equipment');">返回</el-button> </el-form-item> </el-form> </div> </template> <script> import ImgUpload from '@/components/img-upload/img-upload.vue' import { addEquipment } from '@/api/Equipment' export default { components: { ImgUpload, }, data() { return { // imageUrl: '', ruleForm: { name: '', img: '', number: '', comment: '' }, rules: { name: [ { required: true, message: '请输入器材名称', trigger: 'blur' }], number: [ { required: true, message: '请输入器材数量', trigger: 'blur' }], }, } }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert(this.ruleForm.img) if (!this.ruleForm.img) return this.$message.error('套餐图片不能为空') addEquipment(this.ruleForm) .then((res) => { if (res.data.code === 1) { this.$message.success("添加成功!") this.$router.push('/equipment') } else { this.$message.error("res.data.msg") } }) } else { console.log('error submit!!'); return false; } }); }, handleImageUrlUpdate(newImageUrl) { alert(newImageUrl) this.ruleForm.img = newImageUrl; } }, } </script> <style scoped> .form-container { display: flex; justify-content: center; align-items: center; height: 70vh; /* 或者你想要的任何高度 */ width: 100%; max-width: 600px; /* 限制最大宽度以适应较小的屏幕 */ margin: 0 auto; /* 水平居中 */ padding: 20px; /* 内边距 */ background-color: #ffffff; /* 背景颜色 */ border-radius: 8px; /* 圆角 */ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 阴影效果 */ } /* 为提示文字设置样式 */ .img-upload-instructions { font-size: 12px; /* 根据需要调整字体大小 */ color: #666; /* 根据需要调整颜色 */ margin-bottom: 5px; /* 可选: 添加底部边距 */ } /* 为整个上传组件设置样式 */ .img-upload-container { display: flex; /* 使用Flex布局 */ align-items: center; /* 垂直居中 */ gap: 10px; /* 间距 */ } </style>
上传文件OSS的逻辑
src\components\img-upload\img-upload.vue
<template> <div class="upload-item"> <el-upload ref="uploadfiles" :accept="type" :class="{ borderNone: imageUrl }" class="avatar-uploader" action="/api/admin/common/upload" :show-file-list="false" :on-success="handleAvatarSuccess" :on-remove="handleRemove" :on-error="handleError" :before-upload="beforeAvatarUpload" :headers="headers"> <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon" /> <span v-if="imageUrl" class="el-upload-list__item-actions"> <span class="el-upload-span" @click.stop="oploadImgDel"> 删除图片 </span> <span class="el-upload-span"> 重新上传 </span> </span> </el-upload> <p class="upload-tips"> <slot /> </p> </div> </template> <script> import { getToken } from '@/utils/cookies' export default { name: 'UploadImage', props: { type: { type: String, default: '.jpg,.jpeg,.png' }, size: { type: Number, default: 2 }, propImageUrl: { type: String, default: '' } }, data() { return { headers: { token: getToken() }, imageUrl: '' }; }, methods: { handleRemove() { // 方法实现 }, oploadImgDel() { this.imageUrl = ''; this.$emit('imageChange', this.imageUrl); }, beforeAvatarUpload(file) { const isLt2M = file.size / 1024 / 1024 < this.size; if (!isLt2M) { this.$message({ message: `上传文件大小不能超过${this.size}M!`, type: 'error' }); return false; } }, handleError(err, file, fileList) { console.log(err, file, fileList, 'handleError'); this.$message({ message: '图片上传失败', type: 'error' }); }, handleAvatarSuccess(response) { this.imageUrl = `${response.data}`; // 发出一个事件,包含新的图片 URL this.$emit('update:imageUrl', this.imageUrl); } }, watch: { propImageUrl: function (val) { this.imageUrl = val; } } }; </script> <style lang='scss'> .borderNone { .el-upload { border: 1px solid #d9d9d9 !important; } } </style> <style scoped lang="scss"> .avatar-uploader .el-icon-plus:after { position: absolute; display: inline-block; content: ' ' !important; left: calc(50% - 20px); top: calc(50% - 40px); width: 40px; height: 40px; // background: url('./../../assets/icons/icon_upload@2x.png') center center no-repeat; background-size: 20px; } .el-upload-list__item-actions:hover .upload-icon { display: inline-block; } .el-icon-zoom-in:before { content: '\E626'; } .el-icon-delete:before { content: '\E612'; } .el-upload-list__item-actions:hover { opacity: 1; } .upload-item { .el-form-item__content { width: 500px !important; } display: flex; align-items: center; border: 1px solid #ccc; /* 添加边框*/ width: 200px; /* 设置宽度 */ height: 200px; /* 设置高度,使之与宽度相同 */ } .upload-tips { font-size: 12px; color: #666666; display: inline-block; line-height: 17px; margin-left: 36px; } .el-upload-list__item-actions { position: absolute; width: 100%; height: 100%; left: 0; top: 0; cursor: default; text-align: center; color: #fff; opacity: 0; font-size: 20px; background-color: rgba(0, 0, 0, 0.5); transition: opacity 0.3s; display: flex; justify-content: center; align-items: center; flex-direction: column; } .avatar-uploader .el-upload { border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; } .avatar-uploader { display: inline-block; } .avatar-uploader .el-upload:hover { border-color: #ffc200; } .el-upload-span { width: 100px; height: 30px; border: 1px solid #ffffff; border-radius: 4px; font-size: 14px; text-align: center; line-height: 30px; } .el-upload-span:first-child { margin-bottom: 20px; } .avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 200px; height: 160px; line-height: 160px; text-align: center; } .avatar { width: 200px; height: 160px; display: block; } </style>
上传oss图片文件时需要的jwt令牌获取
src\utils\cookies.js
import Cookies from 'js-cookie'; // 获取令牌 export const getToken = () => sessionStorage.getItem('jwtToken');
ps:如果出现模块找不到,不存在的时候,直接
npm install 模块
例如:
Module not found: Error: Can't resolve 'js-cookie' in 'D:\bishe\project\sems-front\src\utils'
解决方法:
这个错误表明你的项目无法找到js-cookie
模块,这意味着你可能还没有安装它或者路径配置有问题。js-cookie
是一个用于操作浏览器Cookies的小型JavaScript库。
解决方案
安装 js-cookie
确保你已经安装了js-cookie
。你可以通过运行以下命令来安装它:
npm install js-cookie --save
或者如果你使用的是Yarn:
yarn add js-cookie
测试:
ps:OSS折磨死我了,踩了无数的坑,全靠各种搜索资料,卡了我2天,呜呜呜,麻了,有什么不知道的真可以问我,呜呜呜,你们踩的坑我应该都踩过,麻了
未完。。。