egg知识点复习
2021-08-02 本文已影响0人
易路先登
1、头像上传
(1)、前端antd
import React from 'react'
import { Upload, message } from 'antd';
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
function beforeUpload(file) {
console.log('上传前')
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
}
class Avatar extends React.Component {
state = {
loading: false,
};
handleChange = info => {
console.log('handleChaneg',info)
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl =>
this.setState({
imageUrl,
loading: false,
}),
);
}
};
render() {
const { loading, imageUrl } = this.state;
const uploadButton = (
<div>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
<div style={{ marginTop: 8 }}>Upload</div>
</div>
);
return (
<Upload
name="avatar"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="/touxiang"
beforeUpload={beforeUpload}
onChange={this.handleChange}
>
{imageUrl ? <img src={imageUrl} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
</Upload>
);
}
}
export default Avatar
(2)、egg开启文件上传
// config.defult.js
config.multipart = {
mode: 'file'
};
(3)、接口
async touxiang(){
const { ctx } = this;
console.log(ctx.request.files,'-----')
let file = ctx.request.files[0]
let fileData = fs.readFileSync(file.filepath)
let imgpath = path.join(__dirname,'../public',file.filename)
console.log(imgpath,'+++')
fs.writeFileSync(imgpath,fileData)
ctx.body = {
"name": "xxx.png",
"status": "done",
"url": imgpath,
"thumbUrl":imgpath
}
}
2、分页
//service/booklist.js
//返回数据总数
async searchAll(pageSize,currentPage){
const results = await this.app.mysql.select('booklist');
return results.length
}
//全表查询带分页
async searchAll(pageSize,currentPage){
const results = await this.app.mysql.select('booklist',{
limit:pageSize,
offset:(currentPage-1)*pageSize
});
return results
}
3、用户鉴权(react)
路由配置表中区分根路由和异步路由
import Login from '../views/Login'
import List from '../views/List'
import Registry from '../views/Registry'
import Detail from '../views/Detail'
import ShangChuan from '../views/Shangchuan'
//根路由
export const rootRoutes = [
{
path:"/login",
component:Login,
roles:['teacher','student']
},
{
path:"/registry",
roles:['teacher','student'],
component:Registry
},
{
from:'/',
to:'/login'
}
]
//异步路由
export const asyncRoutes = [
{
path:"/login",
component:Login,
roles:['teacher','student']
},
{
path:"/list",
roles:['teacher','student'],
component:List
},
{
path:"/detail",
roles:['teacher'],
component:Detail
},
{
path:"/shangchuan",
roles:['teacher','student'],
component:ShangChuan
},
{
path:"/registry",
roles:['teacher','student'],
component:Registry
},
{
from:'/',
to:'/login'
}
]
登录接口端
//登录接口返回角色信息,根据该角色过滤redux仓库中的路由数组
store.dispatch({
type:'filteroute',
value:ress.data.role
})
redux中过滤路由
import { createStore } from 'redux'
import {rootRoutes,asyncRoutes} from '../route/router_config'
const initState = {
routes:rootRoutes
}
const store = createStore((state=initState,action)=>{
switch(action.type){
case 'filteroute':
return {...state,routes:fileroter(asyncRoutes,action.value)}
default:
return {...state}
}
})
function fileroter(routes,filterStr){
routes = routes.filter((item,index)=>{
let flag = item.roles&&item.roles.includes(filterStr)
if(flag&&item.children){
item.children = fileroter(item.children,filterStr)
}
return flag
})
return routes
}
export default store;
App.js
import React,{Component} from "react";
import RouterView from "./route/ViewRouter";
import store from './store/index'
class App extends Component {
state={
routes:store.getState().routes
}
componentDidMount(){
store.subscribe(()=>{
this.setState({
routes:store.getState().routes
})
})
}
render(){
return (
<div className="App">
<RouterView routes={ this.state.routes } />
</div>
);
}
}
export default App;
如此过滤所得动态路由只可在应用内进行跳转,在浏览器地址栏直接输入新增路由,无论有无权限都是不能直接访问的。
应用内跳转
const columns = [
{
title: '书名',
dataIndex: 'bookname',
key: 'bookname',
render:(text,record)=>{
return <button onClick={()=>{
if(this.isIncludesRoutes(this.state.routes,'/detail')){
this.props.history.push('/detail')
}else{
message.info('没有权限');
}
}}>{text}</button>
}
},
...
]
//判断一个路径是否在合法路由中
isIncludesRoutes=(routes,pathname)=>{
return !!(routes.filter((item,index)=>{
let flag;
if(item.children){
flag = this.isIncludesRoutes(item.children,pathname)
}
return flag?flag:item.path===pathname
}).length)
}
4、模糊搜索
//在userlist表中查询用户名中带o的用户
select * from userlist where username like '%o%';
5、条件筛选
async searchBytiaojian(params){//params即条件对象
const post = await this.app.mysql.get('booklist', params);
return post
}
6、多表联查
有老师表如下:

有学生表如下:

现在已知老师的名字叫赵六,请查询赵六的所有学生
select * from (select * from userlist where username='zhaoliu') u join studentlist on u.id = studentlist.teacher_id ;