图书订阅管理系统——管理员管理用户
1.这是界面设计(可能有亿点丑,重在这个过程)
2.图片1
当用户点击用户管理时,将进入该页面,灵活使用less、以及阿里图标库,在路由层级上,这一页与4个模块作为同级,继承主页面的footer,
3.图片2
用户信息页,我通过竖向列表的形式进行展示,这是页面设计依旧是flex属性的灵活运用,组件逻辑如下:
练习这么些组件下来,已经养成了习惯:组件临时存储需要创建状态,这个组件比较简单,输入用户名,点击搜索,和数据库进行交互拿到数据返回,前端一接到数据就改变临时状态userInfo,交互统一的形式在上一节管理员管理书籍那里说过,再顺一次:
前端发送一个ajax请求(axios二次封装的)-----后端服务器通过监听端口,截取信息,通过后端注册的路由进行匹配-----调用后端XX服务的接口函数,处理数据并返回-----前端采用同步实现异步的形式 async。。。await与try。。。catch搭配,轻松获取后端返回数据,这就是大致的前后端数据处理过程。
import React, { useState } from 'react' import IconToFirstPage from '../../../../components/IconToFirstPage' import './style.less' import { Input } from 'antd'; import { reqSearchUser } from '../../../../api/index-ajax'; const { Search } = Input; export default function UserInfo() { const [userInfo, setUserInfo] = useState([]); const onSearch = async (value) => { console.log(value); try { const response = await reqSearchUser({ value: value }); console.log(response) setUserInfo(response.data.userInfo) } catch (error) { console.log("请求错误", error) } } return ( <div> <div className="userInfoHead"> <IconToFirstPage /> <div className="userInfoTitle"><span>用户信息</span></div> </div> <div className="manageUsersBody"> <div className='search-wrapper'> <div className="search"> <Search placeholder="请输入用户名,点击搜索" onSearch={onSearch} style={{ width: 250, }} /> </div> </div> </div> <div className="userInfoWrapper"> <div className='userInfoListTitle'> <div className="title"><span>类别</span></div> <div className="data"><span>数据</span></div> </div> { userInfo.length !== 0 ? userInfo.map((userInfoObj) => { return ( <div key={userInfoObj._id}> <div className="username"> <div className="title"><span>姓名</span></div> <div className="data"><span>{userInfoObj.username}</span></div> </div> <div className="password"> <div className="title"><span>密码</span></div> <div className="data"><span>{userInfoObj.password}</span></div> </div> <div className="jobNum"> <div className="title"><span>学工号</span></div> <div className="data"><span>{userInfoObj.jobnum}</span></div> </div> <div className="identify"> <div className="title"><span>身份</span></div> <div className="data"><span>{userInfoObj.identify}</span></div> </div> <div className="phone"> <div className="title"><span>联系方式</span></div> <div className="data"><span>{userInfoObj.phone}</span></div> </div> <div className="email"> <div className="title"><span>电子邮件</span></div> <div className="data"><span>{userInfoObj.email}</span></div> </div> </div> ) }):<div>暂时无数据</div> } </div> </div> ) }
4、图片3
申请列表页,主要是展示用户还在申请中的项目,需要完成用户订阅才能做,目下已经全部做完才总结这里的。它的业务逻辑是,把后端数据库里存储的用户订阅状态还在申请中订阅申请拿出来,放在前端,并进行拒绝或者同意操作。
本页,由于这些数据只是一个页面使用,并且需要不停刷新,我并没有进行本地缓存,节省本地也就是客户端localStorage资源(这个单词之前有拼错的莫介意哈)这一页的组件实现逻辑等同于3个图片2:点击按钮——发送请求(reqXXXXX)——后端处理——返回数据(ersponse)
import React, { useState } from 'react' import IconToFirstPage from '../../../../components/IconToFirstPage' import './style.less' import { Button } from 'antd' import { reqagreeSub, reqGetApplyList, reqrejectSub } from '../../../../api/index-ajax'; export default function ApplyList() { const [applyList, setapplyList] = useState([]); const toShift = async () => { let username = document.getElementsByClassName("username1")[0]; if(username.value==='') alert("您尚未填写您想查询的用户名,直接刷新将返回所有数据") try { const response = await reqGetApplyList({ value: username.value }); console.log(response) setapplyList(response.data.data) } catch (error) { console.log("请求错误", error) } } console.log(JSON.parse(localStorage.getItem('userInfo')).username) const rejectSub = async(oneApply)=>{ const response = await reqrejectSub({applyPerson:oneApply.applyPerson,applyBook:oneApply.applyBook,optionPerson:JSON.parse(localStorage.getItem('userInfo')).username}); console.log(response) alert(response.data.msg); } const agreeSub = async(oneApply)=>{ const response = await reqagreeSub({applyPerson:oneApply.applyPerson,applyBook:oneApply.applyBook,optionPerson:JSON.parse(localStorage.getItem('userInfo')).username}); console.log(response) alert(response.data.msg); } return ( <div> <div className="applyListHeader"> <IconToFirstPage /> <div className="applyListTitle"> <span>申请列表</span> </div> </div> <div className="applyListBody"> <div className="title-data"> <div className="applyListBodyTitle"> <div className="applyPerson"><span>申请人</span></div> <div className="applyBook"><span>申请书籍</span></div> <div className="applyBookTime"><span>申请时间</span></div> <div className="subStartTime"><span>订阅开始</span></div> <div className="subEndTime"><span>订阅结束</span></div> <div className="option"><span>操作</span></div> </div> <div className="applyListwrapper"> { applyList.length !== 0 ? applyList.map((oneApply) => { return ( <div className="applyListData" key={oneApply._id}> <div className="applyPerson"><span>{oneApply.applyPerson}</span></div> <div className="applyBook"><span>{oneApply.applyBook}</span></div> <div className="applyBookTime"><span>{oneApply.applyBookTime}</span></div> <div className="subStartTime"><span>{oneApply.subStartTime}</span></div> <div className="subEndTime"><span>{oneApply.subEndTime}</span></div> <div className="option"><Button type="primary" htmlType="submit" onClick={()=>agreeSub(oneApply)}>同意</Button><Button type="primary" htmlType="submit" onClick={()=>rejectSub(oneApply)}>拒绝</Button></div> </div> ) }) : <div>暂无数据</div> } </div> </div> </div> <div className="shift"> <input type="text" className='username1' placeholder='用户名: ' /> <Button type="primary" htmlType="submit" onClick={() => toShift()}> 刷新 </Button> </div> </div> ) }
5.图片4
订阅流水,管理员可以返回所有的订阅记录,也可以用户名筛选。不做本地缓存,管理员刷新,就会将数据显示。实现逻辑依旧和上面一样。
总结一下:
1.页面设计上的不足,我是一个人做,所以设计如此,这个是可以后天跟上的,进了公司,做的多了,自然就广阔了,主要是组件的灵活穿梭和信息传递;个人觉得本地localStorage应该慎用,存储一些即时性的数据、就算是缓存清理了,数据库里也能拿的数据,根据需要,有时候能减少访问数据库的频率,能提高性能。
2.这一节主要是点击按钮——发送请求(reqXXXXX)——后端处理——返回数据(ersponse),没有过复杂的逻辑。