From 7826befe8eddcc97b059fcb0d37aac638b74fd59 Mon Sep 17 00:00:00 2001
From: Jay
Date: Fri, 5 May 2017 17:24:45 +0800
Subject: [PATCH] add del event, add download event, add download event video
---
app.js | 43 +++++++++++++++++---
includes/language/zh.json | 1 +
package.json | 1 +
route/api/ipcam.js | 32 +++++++++++++++
src/components/AdminPage/IPCam/EventModal.js | 36 ++++++++++++++--
src/components/AdminPage/IPCam/IPCamModal.js | 4 +-
src/components/AdminPage/IPCam/index.js | 22 ++++++++--
7 files changed, 125 insertions(+), 14 deletions(-)
diff --git a/app.js b/app.js
index 835a54e..d073571 100644
--- a/app.js
+++ b/app.js
@@ -9,6 +9,7 @@ const config = require('./config');
const so = require('./includes/storeObject');
const exec = require('child_process').exec;
const fs = require('fs');
+const archiver = require('archiver');
const app = express();
@@ -63,13 +64,13 @@ app.get('/camevent', (req, res) => {
res.send({ ip });
});
})
-app.get('/viewcamimg/:dir/:img', async(req, res) => {
+app.get(['/viewcamimg/:dir/:file', '/dlcamvideo/:dir/:file'], async(req, res) => {
let dir = req.params.dir;
- let img = req.params.img;
- if (!dir || !img) return res.sendStatus(404);
+ let file = req.params.file;
+ if (!dir || !file) return res.sendStatus(404);
try {
let stat = await new Promise((resolve, reject) => {
- fs.stat(path.resolve(config.cmdpath.ipcamsave, dir, img), (err, stats) => {
+ fs.stat(path.resolve(config.cmdpath.ipcamsave, dir, file), (err, stats) => {
if (err) return reject(err);
return resolve(stats);
})
@@ -78,7 +79,39 @@ app.get('/viewcamimg/:dir/:img', async(req, res) => {
} catch (e) {
return res.sendStatus(404);
}
- res.sendfile(path.resolve(config.cmdpath.ipcamsave, dir, img))
+ res.sendfile(path.resolve(config.cmdpath.ipcamsave, dir, file))
+})
+app.get('/dlevent/:dir', async(req, res) => {
+ let dir = req.params.dir;
+ if (!dir) return res.sendStatus(404);
+ let list = [];
+ try {
+ let stat = await new Promise((resolve, reject) => {
+ fs.stat(path.resolve(config.cmdpath.ipcamsave, dir), (err, stats) => {
+ if (err) return reject(err);
+ return resolve(stats);
+ })
+ });
+ if (!stat.isDirectory()) return res.sendStatus(404);
+ list = await new Promise((resolve, reject) => {
+ fs.readdir(path.resolve(config.cmdpath.ipcamsave, dir), (err, fis) => {
+ if (err) return reject(err);
+ return resolve(fis);
+ })
+ })
+ } catch (e) {
+ return res.sendStatus(404);
+ }
+ res.writeHead(200, {
+ 'Content-Type': 'application/zip',
+ 'Content-disposition': 'attachment; filename=cam_event.zip'
+ });
+ let zip = archiver('zip', { store: true });
+ zip.pipe(res);
+ for (let i of list) {
+ zip.file(path.resolve(config.cmdpath.ipcamsave, dir, i), { name: i })
+ }
+ zip.finalize();
})
app.get('/servcmd', (req, res) => {
diff --git a/includes/language/zh.json b/includes/language/zh.json
index e2bd22c..d1b2cce 100644
--- a/includes/language/zh.json
+++ b/includes/language/zh.json
@@ -72,6 +72,7 @@
"ERR0070": "IPCam 裝置已達上限",
"ERR0071": "無此裝置資料",
"ERR0072": "目錄資訊取得失敗",
+ "ERR0073": "目錄輸入錯誤",
"ERR7000": "命令執行失敗",
diff --git a/package.json b/package.json
index 895c07f..1d68337 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"author": "",
"license": "MIT",
"dependencies": {
+ "archiver": "^1.3.0",
"body-parser": "^1.16.1",
"cookie-parser": "^1.4.3",
"cors": "^2.8.1",
diff --git a/route/api/ipcam.js b/route/api/ipcam.js
index 80d8356..60daa35 100644
--- a/route/api/ipcam.js
+++ b/route/api/ipcam.js
@@ -285,6 +285,38 @@ router
}
return n();
})
+ .post('/delevent', async(req, res, n) => {
+ if (!config.permission.ipcam) return n('ERR9000');
+ if (!tool.checkPermission(req)) return n('ERR9000');
+ let arr = req.body;
+ if (!arr.data) return n('ERR0000');
+ if (!arr.data.dir) return n('ERR0073');
+
+ let rp = config.cmdpath.ipcamsave;
+ let dp = path.resolve(rp, arr.data.dir);
+ try {
+ let stat = await new Promise((resolve, reject) => {
+ fs.stat(dp, (err, stats) => {
+ if (err) return reject(err);
+ return resolve(stats);
+ });
+ });
+ if (dp.split(' ')[0] == '/') return n('ERR0073');
+ await new Promise((resolve, reject) => {
+ exec(`rm -rf ${dp}`, (err, sout, serr) => {
+ if (err) return reject(err);
+ return resolve(null);
+ })
+ })
+ } catch (e) {
+ return rt.err(res, e, n, 'ERR0072');
+ }
+
+ res.api_res = {
+ record: []
+ }
+ return n();
+ })
.all('*', rt.send);
module.exports = router;
\ No newline at end of file
diff --git a/src/components/AdminPage/IPCam/EventModal.js b/src/components/AdminPage/IPCam/EventModal.js
index 5fbbb47..1f91af7 100644
--- a/src/components/AdminPage/IPCam/EventModal.js
+++ b/src/components/AdminPage/IPCam/EventModal.js
@@ -1,9 +1,9 @@
import React from 'react';
-import { Modal, Grid, List, Menu, Icon } from 'semantic-ui-react';
+import { Modal, Grid, List, Menu, Icon, Message } from 'semantic-ui-react';
import {convertTime} from '../../../tools';
import ImgGrid from './EvtImgGrid';
-const EventModal = ({ i18n, open, name, list, sel, closeEventModal, changeSelectEvent,refreshEvt }) => {
+const EventModal = ({ i18n, open, name, list, sel, closeEventModal, changeSelectEvent,refreshEvt, delEvent }) => {
return (
{closeEventModal()}} size="fullscreen">
@@ -26,8 +26,17 @@ const EventModal = ({ i18n, open, name, list, sel, closeEventModal, changeSelect
let n = t.name;
let time = n.split('-')[1];
return (
- {changeSelectEvent(idx)}}>
- {convertTime(time, true)}
+
+ {changeSelectEvent(idx)}}
+ style={{cursor: "pointer"}}>{convertTime(time, true)}
+ {window.open(`/dlevent/${t.name}`, '_blank')}}/>
+ {delEvent(t.name)}}/>
)})
}
@@ -36,6 +45,25 @@ const EventModal = ({ i18n, open, name, list, sel, closeEventModal, changeSelect
+ {
+ sel != -1 && list[sel].files.video.length > 0 ? (
+
+ 影片下載
+
+ {
+ list[sel].files.video.map((t, idx) => {
+
+ return (
+
+ )
+ })
+ }
+
+
+ ) :null
+ }
{
sel != -1 ?
(
diff --git a/src/components/AdminPage/IPCam/IPCamModal.js b/src/components/AdminPage/IPCam/IPCamModal.js
index 2ca7357..d3aa4f2 100644
--- a/src/components/AdminPage/IPCam/IPCamModal.js
+++ b/src/components/AdminPage/IPCam/IPCamModal.js
@@ -46,10 +46,10 @@ const IPCamModal = ({ i18n, open, type, data, closeModal, submitModal }) => {
-
+
-
+
diff --git a/src/components/AdminPage/IPCam/index.js b/src/components/AdminPage/IPCam/index.js
index 2a1f3be..f2122da 100644
--- a/src/components/AdminPage/IPCam/index.js
+++ b/src/components/AdminPage/IPCam/index.js
@@ -77,8 +77,8 @@ class IPCamPage extends React.Component {
submitModal = (type, data = {}) => {
let {toggleLoading,showDialog} = this.props;
if(type == 1 && !data.id) return showDialog('資料讀取錯誤');
- if(!data.maxevents || data.maxevents < 1 || data.maxevents > 5) return showDialog('事件數量請介於1-5間');
- if(!data.maximg || data.maximg < 1 || data.maximg > 10) return showDialog('圖片數量請介於1-5間');
+ if(!data.maxevents || data.maxevents < 1 || data.maxevents > 10) return showDialog('事件數量請介於1-5間');
+ if(!data.maximg || data.maximg < 1 || data.maximg > 20) return showDialog('圖片數量請介於1-5間');
if(!data.name) return showDialog('請輸入名稱');
if(!data.ip) return showDialog('請輸入IP');
if(!data.model) return showDialog('請選擇型號');
@@ -146,6 +146,21 @@ class IPCamPage extends React.Component {
})
}
+ delEvent = (dir) => {
+ if(!dir) return ;
+ let {callConfirm, toggleLoading, showDialog} = this.props;
+ callConfirm('確定刪除這筆事件?', ()=>{
+ toggleLoading(1);
+ fetch('/api/ipcam/delevent', getRequest({dir}))
+ .then(response=>response.json())
+ .then(json => {
+ toggleLoading(0);
+ if(json.status != 1) return showDialog(json.message);
+ this.getEvents(-1);
+ })
+ })
+ }
+
render() {
let {i18n} = this.props;
return (
@@ -197,7 +212,8 @@ class IPCamPage extends React.Component {
name={this.state.evt.name}
refreshEvt={this.getEvents}
closeEventModal={this.closeEventModal}
- changeSelectEvent={this.changeSelectEvent} />
+ changeSelectEvent={this.changeSelectEvent}
+ delEvent={this.delEvent} />
)
}