写在前面:
为公共事业做贡献,做了个开源版本:scratch.lite
开源版本带MySQL后台服务器,功能:注册、登录、保存作品、分享、修改作品名称、保存作品缩略图。
有兴趣的朋友可以去下载参考:lite: 一个轻量级的Scratch编程分享平台:注册登录、作品创作、作品管理、素材管理、用户管理,作品点赞、收藏、分享。
Scratch二次开发的纯技术交流QQ群:115224892/914159821
原始scratch-GUI版本中,并无登录功能,但为scratch-www版本留了接口,由于使用的是react框架,初学者可能会被绕晕。
下面就简单说说如何实现这个功能。
一、登录相关的核心源代码
1、session.js
登录状态文件,需要新加到/src/reducers目录下,内容如下:
const SET_SESSION = 'session/SET_SESSION';
//登录状态
const initialState = {
userid: 0,
username: '',
nickname: '',
avatar: ''
};
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case SET_SESSION:
return Object.assign({}, state, action.session);
}
return state;
};
const setSession = session => ({type: SET_SESSION,session: session});
export {
reducer as default,
initialState as initializedSession,
setSession
};
2、session.js
与服务器通信部分,放在/src/lib目录下,文件名本人与上面的状态文件保持了一致。
(本人把作品保存部分的通信接口也写到了这个文件中,后续会专门写一篇关于保存作品的部分,那里会用到。)
function miniFetch(resolve, reject, uri, params){
var opts = {
headers:{
'Accept':'application/json,text/plain,*/*',/* 格式限制:json、文本、其他格式 */
'Content-Type':'application/x-www-form-urlencoded'/* 请求内容类型 */
},
method:'post'
}
if (params){
if (params.headers) {opts['headers'] = Object.assign(opts['headers'], params.headers)}
if (params.method) {opts["method"] = params.method}
if (params.body) {opts["body"] = params.body}
}
fetch(uri, opts)
.then(response=>{
var body = response.json();
if(response.status == 200){
return resolve(body);
}
return reject(body)
})
.catch(err=>reject(err))
};
//登录一:首页打开Scratch时,自动获取一次用户登录信息
module.exports.requestSession = (resolve, reject) => (
miniFetch(resolve, reject, '/user/getSession')
);
//登录二:提交账号、密码进行登录
module.exports.requestLogin = (resolve, reject, data) => (
miniFetch(resolve, reject, '/user/login', {body:data})
);
//退出:提交账号,退出登录状态
module.exports.requestLogout = (resolve, reject, data) => (
miniFetch(resolve, reject, '/user/logout', {body:data})
);
//获取项目源代码
module.exports.requestProject = (resolve, reject, projectId) => (
miniFetch(resolve, reject, `/scratch/project/${projectId}`)
);
//保存标题
module.exports.requestSaveProjectTitle = (resolve, reject, projectId, projectTitle) => {
miniFetch(resolve, reject, '/scratch/saveProjcetTitle', {body:`id=${projectId}&title=${projectTitle}`})
};
//保存缩略图
module.exports.requestSaveProjectThumbnail = (resolve, reject, projectId, thumbnailBlob) => {
miniFetch(resolve, reject, `/scratch/thumbnail/${projectId}`, {body:thumbnailBlob, headers:{'Content-Type': 'image/png'}})
};
//保存分享
module.exports.requestShareProject = (resolve, reject, projectId) => {
miniFetch(resolve, reject, `/scratch/shareProject/${projectId}`)
};
二、登录流程
可以在两个地方检查并设置登录信息:
1、第一次打开编辑器时主动检测;
2、用户手动点击登录时触发式被动检测。
第一次主动自动检测,本人选择放在了启动部分:/scr/playground/index.jsx文件中
//在此判断浏览器是否支持
//实例化虚拟机会导致不受支持的浏览器出错,先判断浏览器是否支持Scratch
if (supportedBrowser()) {
//获取session
const {requestSession} = require('../lib/session');
new Promise((resolve, reject) => {
requestSession(resolve, reject);
}).then(session => {
if (typeof session === 'undefined'){ return runScratch({}); }
return runScratch(session);
}, err => {
return runScratch({});
});
} else {
alert("抱歉,浏览器不支持。我们建议您使用Chrome内核的浏览器!");
}
function runScratch(session) {
if (process.env.NODE_ENV === 'production' && typeof window === 'object') {
window.onbeforeunload = () => true;//在即将离开当前页面(刷新或关闭)时执行 JavaScript
}
GUI.setAppElement(appTarget);
const WrappedGui = compose(AppStateHOC,HashParserHOC)(GUI);
/**
_session=:用户的登录信息,在app-state-hoc.jsx中使用即可,不需要继续后传
*/
ReactDOM.render(<WrappedGui _session={session} />, appTarget);
};
被动登录检测部分,在用户填写用户名与密码并点击登录后,触发。本人放在了menu-bar.jsx文件中:
handleRenderLogin () {//登录操作
return (
<Login
onLogIn={(formData, restoreStateInLoginComponent) => {
new Promise((resolve, reject) => {
requestLogin(resolve, reject,formData);
}).then(
body => {
if (body.status=="OK"){
this.props.onSetSession(body);
this.props.onRequestCloseAccount()//关闭登录后弹出账号菜单
} else {
alert(body.status);//提示用户登录不成功的原因
restoreStateInLoginComponent()
}
},
err => {
restoreStateInLoginComponent()
}
);
}}
/>
);
}
handleLogout () { //退出账号登录状态
new Promise((resolve, reject) => {
requestLogout(resolve, reject,`id=${this.props.userid}`);
}).then(
body => {
this.props.onSetSession(initializedSession);
//this.props.onRequestCloseAccount()//关闭登录菜单
},
err => {}
);
}
三、登录界面部分
本人参考了scratch www 版本,做了个简单的小登录窗口,只贴个登录前及登录后的图吧,源代码就不放了。
如果本文章对您有帮助,请不吝点个赞再走!!!Bailee 了个Bye!!!