diff --git a/ejs/projects.ejs b/ejs/projects.ejs index 5808dab..d5d9049 100644 --- a/ejs/projects.ejs +++ b/ejs/projects.ejs @@ -122,8 +122,11 @@

+
-
+ + + Copyright© Mixly Team @ BNU, CHINA diff --git a/icons/store.svg b/icons/store.svg new file mode 100644 index 0000000..c727aca --- /dev/null +++ b/icons/store.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/store/.gitignore b/img/store/.gitignore new file mode 100644 index 0000000..e28792d --- /dev/null +++ b/img/store/.gitignore @@ -0,0 +1,8 @@ +*.txt +*.png +*.bmp +*.jpg +*.jpeg +*.gif +*.svg +*.ico \ No newline at end of file diff --git a/js/projects.js b/js/projects.js index 44e70c8..40b351b 100644 --- a/js/projects.js +++ b/js/projects.js @@ -809,6 +809,7 @@ function view_project(projectName, projectType) { $("#accordionSidebar").remove() $("#sidebarToggleTop").remove() $("#connect_span").removeAttr("hidden") + $("#storage_space").removeAttr("hidden") init_layout() $("#projMode").click(function() { if (globalProjectType != PROJ_MODE) { @@ -4202,4 +4203,117 @@ setInterval(function(){ save_layout(false, true) isChanged = false } -}, 30000) \ No newline at end of file +}, 30000) + + +function open_storage(){ + var editForm = $('
') + editForm.append($('
')) + editForm.append($('

所有发送到/storage主题下的消息和图片会被自动保存

')) + var messagesContainer = $('
') + var sync_stor = function(){ + messagesContainer.empty() + var sampleMessages = [ + ] + $.getJSON('getImgStore', { + 'projectName': globalProjectName + }, function(res) { + if(res.length==0) + { + messagesContainer.append($('
暂无存储
')) + } + for (let ri = 0; ri < res.length; ri++) { + { + let url = "img/store/" + globalUserName + "/" + globalProjectName + "/" + res[ri] + if (url.endsWith('.txt')) { + sampleMessages.push({ type: 'text', content: url }) + } else{ + sampleMessages.push({ type: 'image', content: url }) + } + } + } + for(let ji = 0; ji < sampleMessages.length; ji++) { + let msg = sampleMessages[ji] + let messageBox = $('
') + + if (msg.type === 'text') { + $.ajax({ + url: msg.content, + success: function(res) { + messageBox.append($('
').text(res)) + // Add timestamp (sample) + let timeStamp = parseInt(msg.content.split("/")[msg.content.split("/").length - 1].split(".")[0]) + let timeString = new Date(timeStamp).toLocaleString() + let btdiv = $('
') + btdiv.append("" + timeString +"") + let deletebtn = $('
') + deletebtn.click(function(){ + $.getJSON('deleteImgStore', { + 'projectName': globalProjectName, + 'filename': msg.content.split("/")[msg.content.split("/").length - 1] + }, function(){ + sync_stor() + }) + }) + btdiv.append(deletebtn) + messageBox.append(btdiv) + } + }) + } else if (msg.type === 'image') { + messageBox.append($('
')) + // Add timestamp (sample) + let timeStamp = parseInt(msg.content.split("/")[msg.content.split("/").length - 1].split(".")[0]) + let timeString = new Date(timeStamp).toLocaleString() + let btdiv = $('
') + btdiv.append("" + timeString +"") + let viewbtn = $('') + viewbtn.click(function(){ + // 全屏显示图片,点击任意退出 + let fullDialog = dialog({ + content: $('
')[0], + cancel: true, + cancelValue: '关闭' + }) + fullDialog.showModal() + + }) + let deletebtn = $('') + deletebtn.click(function(){ + $.getJSON('deleteImgStore', { + 'projectName': globalProjectName, + 'filename': msg.content.split("/")[msg.content.split("/").length - 1] + }, function(){ + sync_stor() + }) + }) + btdiv.append(viewbtn) + btdiv.append(deletebtn) + messageBox.append(btdiv) + } + messagesContainer.prepend(messageBox) + } + }) + } + editForm.append(messagesContainer) + sync_stor() + client.on('message', function(topic, msg) { + if(topic.split("/")[2] == "storage") + sync_stor() + }) + // Bottom section + var bottomDiv = $('
') + var cancelEdit = $('') + bottomDiv.append(cancelEdit) + editForm.append(bottomDiv) + + var modifyDia = dialog({ + content: editForm[0], + cancel: false + }) + + cancelEdit.click(function() { + modifyDia.close().remove() + }) + + modifyDia.showModal() +} \ No newline at end of file diff --git a/mixio.js b/mixio.js index b4e75c3..3914146 100644 --- a/mixio.js +++ b/mixio.js @@ -830,6 +830,30 @@ var mixioServer = async function() { var topic = packet.topic.split('/') var payload = String(packet.payload) if (topic.length == 3) { + if(topic[2] == 'storage') { + // 判断是否是base64, 开头为data:image/***;base64, ***可以为png,bmp,jpg,jpeg,gif,svg,ico + const allowFormats = ['png', 'bmp', 'jpg', 'jpeg', 'gif', 'svg', 'ico']; + const base64Reg = /^data:image\/(\w+);base64,/; + const match = payload.match(base64Reg); + if (match && allowFormats.includes(match[1])) { + // 是base64 + const format = match[1]; + const timeStamp = Date.now(); + const fileName = `${timeStamp}.${format}`; + const filePath = path.join(__dirname, 'img', 'store', topic[0], topic[1], fileName); + const base64Data = payload.replace(base64Reg, ''); + const buffer = Buffer.from(base64Data, 'base64'); + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + fs.writeFileSync(filePath, buffer); + } else { + // 全部明文存为txt + const timeStamp = Date.now(); + const fileName = `${timeStamp}.txt`; + const filePath = path.join(__dirname, 'img', 'store', topic[0], topic[1], fileName); + fs.mkdirSync(path.dirname(filePath), { recursive: true}); + fs.writeFileSync(filePath, payload); + } + } if (topic[2] == 'b640a0ce465fa2a4150c36b305c1c11b') { if (STORAGE_ENGINE == "sqlite") db.run("insert or ignore into devices (userName, clientid) values (?,?)", [topic[0], payload]) @@ -1323,6 +1347,61 @@ var mixioServer = async function() { res.redirect('/') }) + app.get('/getImgStore', function(req, res) { + if (req.session.userName && req.query.projectName){ + var projectName = req.query.projectName + // img/store/username/projectName + var imgStorePath = path.join(__dirname, 'img', 'store', req.session.userName, projectName) + // 文件名发送列表 + fs.readdir(imgStorePath, function(err, files) { + res.send(files || []) + }) + } else + res.redirect('/') + }) + + app.get('/clearImgStore', function(req, res) { + if (req.session.userName && req.query.projectName){ + var projectName = req.query.projectName + // img/store/username/projectName + var imgStorePath = path.join(__dirname, 'img', 'store', req.session.userName, projectName) + // 清空文件 + fs.readdir(imgStorePath, function(err, files) { + files.forEach(function(file) { + fs.unlink(path.join(imgStorePath, file), function(err) { + if (err) { + console.log(err) + } + }) + }) + }) + res.send({ + "status": "success" + }) + } else + res.redirect('/') + }) + + app.get('/deleteImgStore', function(req, res) { + if (req.session.userName && req.query.projectName && req.query.filename){ + var projectName = req.query.projectName + var filename = req.query.filename + // img/store/username/projectName + var imgStorePath = path.join(__dirname, 'img', 'store', req.session.userName, projectName) + // 删除文件 + fs.unlink(path.join(imgStorePath, filename), function(err) { + if (err) { + console.log(err) + } + }) + res.send({ + "status": "success" + } + ) + } else + res.redirect('/') + }) + app.get('/projects', function(req, res) { if (req.session.userName) { ejs.renderFile(__dirname + '/ejs/projects.ejs', {