Compare commits
80 Commits
main
...
release_0.
Author | SHA1 | Date |
---|---|---|
殷伟文 | 89d485d276 | 2 years ago |
yuan_yi | a033e13a2e | 2 years ago |
yuan_yi | ddc013104d | 2 years ago |
yuan_yi | c61d69a720 | 2 years ago |
yuan_yi | 79d4f26ec1 | 2 years ago |
deartibers | a1c20552b1 | 2 years ago |
deartibers | 38f9bf91da | 2 years ago |
wenlele | 70080015d7 | 2 years ago |
yuan_yi | 64fa1bc28c | 2 years ago |
yuan_yi | 1efb405f19 | 2 years ago |
yuan_yi | 974455267e | 2 years ago |
deartibers | 20daa99a47 | 2 years ago |
yuan_yi | 54737dba51 | 2 years ago |
yuan_yi | 9dc3554c7d | 2 years ago |
wenlele | 99b8aca186 | 3 years ago |
wenlele | dc0136a212 | 3 years ago |
wenlele | 70d75b164a | 3 years ago |
wenlele | 1d6877ce2d | 3 years ago |
wenlele | 068ccda661 | 3 years ago |
deartibers | 47a80141b0 | 3 years ago |
deartibers | b4f2dc62e3 | 3 years ago |
yuan_yi | 224bc45174 | 3 years ago |
yuan_yi | 9e8de3ff47 | 3 years ago |
yuan_yi | caa85094bd | 3 years ago |
yuan_yi | d1be1ce22d | 3 years ago |
yuan_yi | 0c1b8f8d99 | 3 years ago |
deartibers | 25c88dea6b | 3 years ago |
wenlele | f1f3a17be3 | 3 years ago |
wenlele | 870afbcd47 | 3 years ago |
deartibers | ee8881a661 | 3 years ago |
wenlele | b9ac39955c | 3 years ago |
wenlele | c23c764238 | 3 years ago |
deartibers | 981dc894c4 | 3 years ago |
yuan_yi | 37779c29b9 | 3 years ago |
yuan_yi | 255466ef39 | 3 years ago |
yuan_yi | 12be6e0ba6 | 3 years ago |
yuan_yi | 29de0083a4 | 3 years ago |
yuan_yi | 685f65affd | 3 years ago |
wenlele | 2bee6dc9a3 | 3 years ago |
wenlele | 7113aaf672 | 3 years ago |
deartibers | a45a0a9a50 | 3 years ago |
deartibers | c3a82d8979 | 3 years ago |
yuan_yi | 4168be60d7 | 3 years ago |
yuan_yi | 8c4cffa8b5 | 3 years ago |
yuan_yi | 068c0a6e50 | 3 years ago |
deartibers | bdbd43ef73 | 3 years ago |
deartibers | b1d1b4bfb5 | 3 years ago |
wenlele | 525d99c736 | 3 years ago |
yuan_yi | 90b6c11a3f | 3 years ago |
yuan_yi | 6f23175395 | 3 years ago |
yuan_yi | 3e898f7a3e | 3 years ago |
yuan_yi | 85b64e95c4 | 3 years ago |
yuan_yi | d18dfa9c30 | 3 years ago |
deartibers | 27594bada8 | 3 years ago |
wenlele | 5744fe52b8 | 3 years ago |
wenlele | 6c712920c8 | 3 years ago |
wenlele | b6ed892275 | 3 years ago |
deartibers | 1aad3c3bef | 3 years ago |
wenlele | 3f5742570b | 3 years ago |
deartibers | 00610e8c2a | 3 years ago |
deartibers | 1ebc1f15ae | 3 years ago |
yuan_yi | f1c3748571 | 3 years ago |
yuan_yi | c494dce09e | 3 years ago |
deartibers | 72f2e341b4 | 3 years ago |
yuan_yi | 07f13a617f | 3 years ago |
yuan_yi | d192b64407 | 3 years ago |
yuan_yi | 333330d9c3 | 3 years ago |
yuan_yi | b122c1e11c | 3 years ago |
yuan_yi | 06648ff786 | 3 years ago |
deartibers | 33b42ed889 | 3 years ago |
wenlele | a8f7b63cac | 3 years ago |
wenlele | 29a904dce8 | 3 years ago |
wenlele | 911e502bf4 | 3 years ago |
wenlele | 6e92a71354 | 3 years ago |
deartibers | 67c41bd4d9 | 3 years ago |
deartibers | 15420f0c96 | 3 years ago |
deartibers | 26390a2a81 | 3 years ago |
yuan_yi | 40a022484b | 3 years ago |
yuan_yi | 05e60fb524 | 3 years ago |
yuan_yi | 052d73e231 | 3 years ago |
@ -1,189 +0,0 @@ |
|||
'use strict'; |
|||
const Hex = require('crypto-js/enc-hex'); |
|||
const MD5 = require('crypto-js/md5'); |
|||
const moment = require('moment'); |
|||
const uuid = require('uuid'); |
|||
|
|||
async function login(ctx, next) { |
|||
const transaction = await ctx.fs.dc.orm.transaction(); |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const params = ctx.request.body; |
|||
let password = Hex.stringify(MD5(params.password)); |
|||
|
|||
const userRes = await models.User.findOne({ |
|||
where: { |
|||
username: params.username, |
|||
password: password, |
|||
delete: false, |
|||
}, |
|||
attributes: { exclude: ['password'] }, |
|||
include: [{ |
|||
attributes: ["resourceId"], |
|||
model: models.UserResource |
|||
}] |
|||
}); |
|||
|
|||
if (!userRes) { |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
"message": "账号或密码错误" |
|||
} |
|||
} else if (!userRes.enable) { |
|||
ctx.status = 400; |
|||
ctx.body = { message: "该用户已被禁用" } |
|||
} else { |
|||
const token = uuid.v4(); |
|||
|
|||
let userRslt = Object.assign(userRes.dataValues, { |
|||
authorized: true, |
|||
token: token, |
|||
userResources: userRes.userResources.map(r => r.resourceId), |
|||
}); |
|||
|
|||
await models.UserToken.create({ |
|||
token: token, |
|||
userInfo: userRslt, |
|||
expired: moment().add(30, 'days').format() |
|||
}); |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = userRslt; |
|||
} |
|||
await transaction.commit(); |
|||
} catch (error) { |
|||
await transaction.rollback(); |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
"message": "登录失败" |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 微信小程序登录 |
|||
* @@requires.body {phone-手机号, password-密码} ctx |
|||
*/ |
|||
async function wxLogin(ctx, next) { |
|||
const transaction = await ctx.fs.dc.orm.transaction(); |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const params = ctx.request.body; |
|||
let password = Hex.stringify(MD5(params.password)); |
|||
const userRes = await models.User.findOne({ |
|||
where: { |
|||
phone: params.phone, |
|||
password: password, |
|||
delete: false, |
|||
}, |
|||
attributes: { exclude: ['password'] } |
|||
}); |
|||
if (!userRes) { |
|||
ctx.status = 400; |
|||
ctx.body = { message: "手机号或密码错误" } |
|||
} else if (!userRes.enable) { |
|||
ctx.status = 400; |
|||
ctx.body = { message: "该用户已被禁用" } |
|||
} else { |
|||
const token = uuid.v4(); |
|||
//获取用户关注区域信息
|
|||
const departmentRes = await models.Department.findOne({ where: { id: userRes.departmentId } }); |
|||
let attentionRegion = departmentRes; |
|||
while (attentionRegion.dependence && attentionRegion.type != 1) { |
|||
const departmentParent = await models.Department.findOne({ where: { id: attentionRegion.dependence } }); |
|||
attentionRegion = { |
|||
...departmentParent.dataValues, |
|||
nextRegin: attentionRegion |
|||
} |
|||
} |
|||
//获取用户权限信息
|
|||
const resourceRes = await models.UserResource.findAll({ |
|||
where: { |
|||
userId: userRes.id |
|||
}, |
|||
include: [{ |
|||
model: models.Resource, |
|||
attributes: ['code', 'name'], |
|||
}], |
|||
attributes: [] |
|||
}); |
|||
let userRslt = Object.assign({ |
|||
authorized: true, |
|||
token: token, |
|||
...userRes.dataValues |
|||
}); |
|||
await models.UserToken.create({ |
|||
token: token, |
|||
userInfo: userRslt, |
|||
expired: moment().add(30, 'day').format('YYYY-MM-DD HH:mm:ss') |
|||
}, { transaction: transaction }); |
|||
ctx.status = 200; |
|||
ctx.body = Object.assign({ |
|||
...userRslt, |
|||
userRegionType: departmentRes.type,//1-市级,2-区县级,3-乡镇级,4-村级
|
|||
attentionRegion: attentionRegion, |
|||
resources: resourceRes.map(r => r.resource) |
|||
}); |
|||
} |
|||
await transaction.commit(); |
|||
} catch (error) { |
|||
await transaction.rollback(); |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
"message": "登录失败" |
|||
} |
|||
} |
|||
} |
|||
|
|||
async function logout(ctx) { |
|||
try { |
|||
const { token, code } = ctx.request.body; |
|||
const models = ctx.fs.dc.models; |
|||
|
|||
await models.UserToken.destroy({ |
|||
where: { |
|||
token: token, |
|||
}, |
|||
}); |
|||
|
|||
ctx.status = 204; |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
"message": "登出失败" |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 微信小程序登出 |
|||
* @request.body {token-用户登录Token} ctx |
|||
*/ |
|||
async function wxLogout(ctx) { |
|||
try { |
|||
const { token } = ctx.request.body; |
|||
const models = ctx.fs.dc.models; |
|||
await models.UserToken.destroy({ |
|||
where: { |
|||
token: token, |
|||
}, |
|||
}); |
|||
ctx.status = 204; |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
"message": "登出失败" |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
login, |
|||
wxLogin, |
|||
logout, |
|||
wxLogout |
|||
}; |
@ -0,0 +1,159 @@ |
|||
'use strict'; |
|||
|
|||
async function getCameraProject (ctx, next) { |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const { limit, page, orderBy, orderDirection, keyword, abilityId, type, venderId } = ctx.query |
|||
const { userId, token } = ctx.fs.api |
|||
|
|||
let findOption = { |
|||
attributes: { exclude: ['delete', 'recycleTime',] }, |
|||
where: { |
|||
createUserId: userId, |
|||
recycleTime: null, |
|||
delete: false |
|||
}, |
|||
order: [ |
|||
[orderBy || 'id', orderDirection || 'DESC'] |
|||
], |
|||
include: [{ |
|||
model: models.CameraAbility |
|||
}, { |
|||
model: models.CameraKind |
|||
}] |
|||
} |
|||
if (limit) { |
|||
findOption.limit = limit |
|||
} |
|||
if (page && limit) { |
|||
findOption.offset = page * limit |
|||
} |
|||
if (keyword) { |
|||
findOption.where.$or = [{ |
|||
name: { $like: `%${keyword}%` } |
|||
}, { |
|||
serialNo: { $like: `%${keyword}%` } |
|||
}] |
|||
} |
|||
if (type) { |
|||
findOption.where.type = type |
|||
} |
|||
if (abilityId) { |
|||
findOption.where.abilityId = abilityId |
|||
} |
|||
if (venderId) { |
|||
findOption.where.venderId = venderId |
|||
} |
|||
|
|||
const cameraRes = await models.Camera.findAll(findOption) |
|||
const total = await models.Camera.count({ |
|||
where: findOption.where |
|||
}) |
|||
|
|||
// 查在安心云绑定的数据
|
|||
const cameraIds = cameraRes.map(c => { |
|||
return c.dataValues.id |
|||
}) |
|||
const axbindCameraRes = await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } }) |
|||
|
|||
for (let { dataValues: camera } of cameraRes) { |
|||
const corBindCamera = axbindCameraRes.find(b => b.cameraId == camera.id) |
|||
if (corBindCamera) { |
|||
camera.station = corBindCamera.stations |
|||
} else { |
|||
camera.station = [] |
|||
} |
|||
} |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = { |
|||
total: total, |
|||
data: cameraRes |
|||
} |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
async function getCamera (ctx) { |
|||
try { |
|||
const { models } = ctx.fs.dc; |
|||
const { cameraId } = ctx.query |
|||
|
|||
const cameraRes = await models.Camera.findAll({ |
|||
attributes: { exclude: ['delete', 'recycleTime',] }, |
|||
where: { |
|||
id: { $in: cameraId.split(',') } |
|||
}, |
|||
include: [{ |
|||
model: models.CameraAbility |
|||
}, { |
|||
model: models.CameraKind |
|||
}, { |
|||
model: models.Vender |
|||
}] |
|||
}) |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = cameraRes |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
async function banned (ctx) { |
|||
try { |
|||
const { models } = ctx.fs.dc; |
|||
const data = ctx.request.body; |
|||
|
|||
// 向视频服务发送通知
|
|||
|
|||
// 库记录
|
|||
await models.Camera.update({ |
|||
forbidden: data.forbidden |
|||
}, { |
|||
where: { |
|||
id: data.cameraId |
|||
} |
|||
}) |
|||
|
|||
ctx.status = 204; |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
async function del (ctx) { |
|||
try { |
|||
const { models } = ctx.fs.dc; |
|||
const { cameraId } = ctx.query |
|||
const { token } = ctx.fs.api |
|||
|
|||
await models.cameraId.destroy({ |
|||
where: { |
|||
id: cameraId |
|||
} |
|||
}) |
|||
|
|||
await ctx.app.fs.axyRequest.delete('vcmp/camera/project', { query: { token, cameraId: cameraId.join(',') } }) |
|||
|
|||
ctx.status = 204; |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
getCameraProject, |
|||
getCamera, |
|||
banned, |
|||
del, |
|||
}; |
@ -0,0 +1,135 @@ |
|||
'use strict'; |
|||
const moment = require('moment') |
|||
|
|||
async function edit (ctx, next) { |
|||
const transaction = await ctx.fs.dc.orm.transaction(); |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const { userId } = ctx.fs.api |
|||
const data = ctx.request.body; |
|||
|
|||
// 或取其他服务信息
|
|||
const nvrData = { |
|||
channelCount: 8, |
|||
port: 8080, |
|||
} |
|||
|
|||
if (data.id) { |
|||
// 修改
|
|||
const storageData = Object.assign({}, data, nvrData) |
|||
await models.Nvr.update(storageData, { |
|||
where: { |
|||
id: data.id |
|||
}, |
|||
transaction |
|||
}) |
|||
} else { |
|||
// 添加
|
|||
const storageData = Object.assign({}, data, nvrData, { |
|||
createTime: moment().format(), |
|||
createUserId: userId, |
|||
delete: false, |
|||
}) |
|||
await models.Nvr.create(storageData, { transaction }) |
|||
} |
|||
|
|||
await transaction.commit(); |
|||
ctx.status = 204; |
|||
} catch (error) { |
|||
await transaction.rollback(); |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
async function get (ctx) { |
|||
const models = ctx.fs.dc.models; |
|||
try { |
|||
const { userId, token } = ctx.fs.api |
|||
const { limit, page, orderBy, orderDirection, keyword, venderId } = ctx.query |
|||
let findOption = { |
|||
attributes: { exclude: ['delete'] }, |
|||
where: { |
|||
createUserId: userId, |
|||
delete: false, |
|||
}, |
|||
order: [ |
|||
[orderBy || 'id', orderDirection || 'DESC'] |
|||
] |
|||
} |
|||
if (limit) { |
|||
findOption.limit = limit |
|||
} |
|||
if (page && limit) { |
|||
findOption.offset = page * limit |
|||
} |
|||
if (keyword) { |
|||
findOption.where.name = { $like: `%${keyword}%` } |
|||
} |
|||
if (venderId) { |
|||
findOption.where.venderId = venderId |
|||
} |
|||
|
|||
const res = await models.Nvr.findAll(findOption) |
|||
const total = await models.Nvr.count({ |
|||
where: findOption.where |
|||
}) |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = { |
|||
total: total, |
|||
data: res |
|||
} |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
async function del (ctx, next) { |
|||
const transaction = await ctx.fs.dc.orm.transaction(); |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const { userId, token } = ctx.fs.api |
|||
const { nvrId } = ctx.params |
|||
|
|||
await models.Nvr.destroy({ |
|||
where: { |
|||
id: nvrId |
|||
}, |
|||
transaction |
|||
}) |
|||
|
|||
const cameraRes = await models.Camera.findAll({ |
|||
where: { |
|||
nvrId |
|||
} |
|||
}) |
|||
|
|||
const cameraIds = cameraRes.map(c => c.id) |
|||
|
|||
await models.Camera.destroy({ |
|||
where: { |
|||
nvrId, |
|||
} |
|||
}) |
|||
|
|||
await ctx.app.fs.axyRequest.delete('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } }) |
|||
|
|||
await transaction.commit(); |
|||
ctx.status = 204; |
|||
} catch (error) { |
|||
await transaction.rollback(); |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
edit, |
|||
get, |
|||
del, |
|||
}; |
@ -0,0 +1,23 @@ |
|||
'use strict'; |
|||
|
|||
async function get (ctx) { |
|||
const models = ctx.fs.dc.models; |
|||
try { |
|||
const res = await models.Vender.findAll({ |
|||
order: [ |
|||
['id', 'ASC'] |
|||
] |
|||
}) |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = res |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = {} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
get, |
|||
}; |
@ -1,36 +1,39 @@ |
|||
'use strict'; |
|||
|
|||
const routes = require('./routes'); |
|||
const redisConnect = require('./service/redis') |
|||
const socketConect = require('./service/socket') |
|||
const paasRequest = require('./service/paasRequest'); |
|||
const authenticator = require('./middlewares/authenticator'); |
|||
// const apiLog = require('./middlewares/api-log');
|
|||
const businessRest = require('./middlewares/business-rest'); |
|||
|
|||
module.exports.entry = function (app, router, opts) { |
|||
app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.'); |
|||
app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.'); |
|||
|
|||
app.fs.api = app.fs.api || {}; |
|||
app.fs.api.authAttr = app.fs.api.authAttr || {}; |
|||
app.fs.api.logAttr = app.fs.api.logAttr || {}; |
|||
app.fs.api = app.fs.api || {}; |
|||
app.fs.api.authAttr = app.fs.api.authAttr || {}; |
|||
app.fs.api.logAttr = app.fs.api.logAttr || {}; |
|||
|
|||
router.use(authenticator(app, opts)); |
|||
router.use(businessRest(app, router, opts)); |
|||
// router.use(apiLog(app, opts));
|
|||
// 顺序固定 ↓
|
|||
redisConnect(app, opts) |
|||
socketConect(app, opts) |
|||
|
|||
router = routes(app, router, opts); |
|||
// 实例其他平台请求方法
|
|||
paasRequest(app, opts) |
|||
|
|||
router.use(authenticator(app, opts)); |
|||
|
|||
// 日志记录
|
|||
// router.use(apiLog(app, opts));
|
|||
|
|||
router = routes(app, router, opts); |
|||
}; |
|||
|
|||
module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Sequelize, models: {} }
|
|||
require('./models/user')(dc); |
|||
require('./models/user_token')(dc); |
|||
require('./models/department')(dc); |
|||
require('./models/resource')(dc); |
|||
require('./models/user_resource')(dc); |
|||
require('./models/places')(dc); |
|||
require('./models/user_placeSecurityRecord')(dc); |
|||
require('./models/report_type')(dc); |
|||
require('./models/report_downManage')(dc); |
|||
require('./models/department')(dc); |
|||
require('./models/report_configition')(dc); |
|||
require('./models/report_collection')(dc); |
|||
require('./models/report_rectify')(dc); |
|||
require('./models/camera_ability')(dc); |
|||
require('./models/camera_kind')(dc); |
|||
require('./models/camera')(dc); |
|||
require('./models/nvr')(dc); |
|||
require('./models/vender')(dc); |
|||
require('./models/ax_project')(dc); |
|||
}; |
|||
|
@ -1,50 +0,0 @@ |
|||
'use strict'; |
|||
|
|||
const request = require('superagent'); |
|||
const buildUrl = (url,token) => { |
|||
let connector = url.indexOf('?') === -1 ? '?' : '&'; |
|||
return `${url}${connector}token=${token}`; |
|||
}; |
|||
|
|||
function factory(app, router, opts) { |
|||
return async function (ctx, next) { |
|||
|
|||
const token = ctx.fs.api.token; |
|||
|
|||
//console.log(username,password)
|
|||
const req = { |
|||
get: (url, query) => { |
|||
return request |
|||
.get(buildUrl(url,token)) |
|||
.query(query) |
|||
}, |
|||
post: (url, data, query) => { |
|||
return request |
|||
.post(buildUrl(url,token)) |
|||
.query(query) |
|||
//.set('Content-Type', 'application/json')
|
|||
.send(data); |
|||
}, |
|||
|
|||
put: (url, data) => { |
|||
return request |
|||
.put(buildUrl(url,token)) |
|||
//.set('Content-Type', 'application/json')
|
|||
.send(data); |
|||
}, |
|||
|
|||
delete: (url) => { |
|||
return request |
|||
.del(buildUrl(url,token)) |
|||
}, |
|||
}; |
|||
|
|||
app.business = app.business || {}; |
|||
app.business.request = req; |
|||
|
|||
await next(); |
|||
}; |
|||
} |
|||
|
|||
module.exports = factory; |
|||
|
@ -0,0 +1,40 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const AxProject = sequelize.define("axProject", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: false, |
|||
unique: "ax_project_id_uindex" |
|||
}, |
|||
name: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "name", |
|||
autoIncrement: false |
|||
} |
|||
}, { |
|||
tableName: "ax_project", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
|
|||
const Nvr = dc.models.Nvr; |
|||
|
|||
// Nvr.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
|
|||
// User.hasMany(Nvr, { foreignKey: 'userId', sourceKey: 'id' });
|
|||
|
|||
dc.models.AxProject = AxProject; |
|||
return AxProject; |
|||
}; |
@ -0,0 +1,266 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const Camera = sequelize.define("camera", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: true, |
|||
unique: "camera_id_uindex" |
|||
}, |
|||
type: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: "设备类型:yingshi - 萤石;nvr - NVR摄像头;ipc - IPC 网络摄像头;cascade - 级联摄像头", |
|||
primaryKey: false, |
|||
field: "type", |
|||
autoIncrement: false |
|||
}, |
|||
name: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "设备名称/安装位置", |
|||
primaryKey: false, |
|||
field: "name", |
|||
autoIncrement: false |
|||
}, |
|||
channelName: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "通道名称", |
|||
primaryKey: false, |
|||
field: "channel_name", |
|||
autoIncrement: false |
|||
}, |
|||
externalDomain: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "外域名称", |
|||
primaryKey: false, |
|||
field: "external_domain", |
|||
autoIncrement: false |
|||
}, |
|||
rtmp: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "rtmp", |
|||
autoIncrement: false |
|||
}, |
|||
serialNo: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "设备编号", |
|||
primaryKey: false, |
|||
field: "serial_no", |
|||
autoIncrement: false |
|||
}, |
|||
cloudControl: { |
|||
type: DataTypes.BOOLEAN, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "云台控制", |
|||
primaryKey: false, |
|||
field: "cloud_control", |
|||
autoIncrement: false |
|||
}, |
|||
highDefinition: { |
|||
type: DataTypes.BOOLEAN, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "高清支持", |
|||
primaryKey: false, |
|||
field: "high_definition", |
|||
autoIncrement: false |
|||
}, |
|||
voice: { |
|||
type: DataTypes.BOOLEAN, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "语音对讲支持", |
|||
primaryKey: false, |
|||
field: "voice", |
|||
autoIncrement: false |
|||
}, |
|||
memoryCard: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "内存卡容量", |
|||
primaryKey: false, |
|||
field: "memory_card", |
|||
autoIncrement: false |
|||
}, |
|||
venderId: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "设备厂商id", |
|||
primaryKey: false, |
|||
field: "vender_id", |
|||
autoIncrement: false, |
|||
references: { |
|||
key: "id", |
|||
model: "vender" |
|||
} |
|||
}, |
|||
cascadeType: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "级联方式:up - 上级联;down - 下级联", |
|||
primaryKey: false, |
|||
field: "cascade_type", |
|||
autoIncrement: false |
|||
}, |
|||
sip: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "sip", |
|||
autoIncrement: false |
|||
}, |
|||
longitude: { |
|||
type: DataTypes.DOUBLE, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "经度", |
|||
primaryKey: false, |
|||
field: "longitude", |
|||
autoIncrement: false |
|||
}, |
|||
latitude: { |
|||
type: DataTypes.DOUBLE, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "维度", |
|||
primaryKey: false, |
|||
field: "latitude", |
|||
autoIncrement: false |
|||
}, |
|||
forbidden: { |
|||
type: DataTypes.BOOLEAN, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: "是否禁用", |
|||
primaryKey: false, |
|||
field: "forbidden", |
|||
autoIncrement: false |
|||
}, |
|||
createTime: { |
|||
type: DataTypes.DATE, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "create_time", |
|||
autoIncrement: false |
|||
}, |
|||
recycleTime: { |
|||
type: DataTypes.DATE, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "放入回收站时间", |
|||
primaryKey: false, |
|||
field: "recycle_time", |
|||
autoIncrement: false |
|||
}, |
|||
delete: { |
|||
type: DataTypes.BOOLEAN, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: "是否彻底删除", |
|||
primaryKey: false, |
|||
field: "delete", |
|||
autoIncrement: false |
|||
}, |
|||
createUserId: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "create_user_id", |
|||
autoIncrement: false |
|||
}, |
|||
nvrId: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "nvr_id", |
|||
autoIncrement: false, |
|||
references: { |
|||
key: "id", |
|||
model: "nvr" |
|||
} |
|||
}, |
|||
model: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "型号", |
|||
primaryKey: false, |
|||
field: "model", |
|||
autoIncrement: false |
|||
}, |
|||
kindId: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "kind_id", |
|||
autoIncrement: false, |
|||
references: { |
|||
key: "id", |
|||
model: "cameraKind" |
|||
} |
|||
}, |
|||
abilityId: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "ability_id", |
|||
autoIncrement: false, |
|||
references: { |
|||
key: "id", |
|||
model: "cameraAbility" |
|||
} |
|||
} |
|||
}, { |
|||
tableName: "camera", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
dc.models.Camera = Camera; |
|||
|
|||
const CameraKind = dc.models.CameraKind; |
|||
Camera.belongsTo(CameraKind, { foreignKey: 'kindId', targetKey: 'id' }); |
|||
CameraKind.hasMany(Camera, { foreignKey: 'kindId', sourceKey: 'id' }); |
|||
|
|||
const CameraAbility = dc.models.CameraAbility; |
|||
Camera.belongsTo(CameraAbility, { foreignKey: 'abilityId', targetKey: 'id' }); |
|||
CameraAbility.hasMany(Camera, { foreignKey: 'abilityId', sourceKey: 'id' }); |
|||
|
|||
return Camera; |
|||
}; |
@ -0,0 +1,34 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const CameraAbility = sequelize.define("cameraAbility", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: false, |
|||
unique: "camera_ability_id_uindex" |
|||
}, |
|||
ability: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "ability", |
|||
autoIncrement: false |
|||
} |
|||
}, { |
|||
tableName: "camera_ability", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
dc.models.CameraAbility = CameraAbility; |
|||
return CameraAbility; |
|||
}; |
@ -0,0 +1,34 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const CameraKind = sequelize.define("cameraKind", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: false, |
|||
unique: "camera_kind_id_uindex" |
|||
}, |
|||
kind: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "kind", |
|||
autoIncrement: false |
|||
} |
|||
}, { |
|||
tableName: "camera_kind", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
dc.models.CameraKind = CameraKind; |
|||
return CameraKind; |
|||
}; |
@ -0,0 +1,40 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const Vender = sequelize.define("vender", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: true, |
|||
unique: "vender_id_uindex" |
|||
}, |
|||
name: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "name", |
|||
autoIncrement: false |
|||
} |
|||
}, { |
|||
tableName: "vender", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
|
|||
const Camera = dc.models.Camera; |
|||
Camera.belongsTo(Vender, { foreignKey: 'venderId', targetKey: 'id' }); |
|||
Vender.hasMany(Camera, { foreignKey: 'venderId', sourceKey: 'id' }); |
|||
|
|||
dc.models.Vender = Vender; |
|||
|
|||
return Vender; |
|||
}; |
@ -1,32 +0,0 @@ |
|||
'use strict'; |
|||
|
|||
const auth = require('../../controllers/auth'); |
|||
|
|||
module.exports = function (app, router, opts) { |
|||
/** |
|||
* @api {Post} login 登录. |
|||
* @apiVersion 1.0.0 |
|||
* @apiGroup Auth |
|||
*/ |
|||
app.fs.api.logAttr['POST/login'] = { content: '登录', visible: true }; |
|||
router.post('/login', auth.login); |
|||
|
|||
/** |
|||
* @api {POST} wxLogin 微信小程序登录.(使用手机号、密码登录) |
|||
* @apiVersion 1.0.0 |
|||
* @apiGroup Auth |
|||
*/ |
|||
app.fs.api.logAttr['POST/wxLogin'] = { content: '微信小程序登录', visible: true }; |
|||
router.post('/wxLogin', auth.wxLogin); |
|||
|
|||
app.fs.api.logAttr['PUT/logout'] = { content: '登出', visible: false }; |
|||
router.put('/logout', auth.logout); |
|||
|
|||
/** |
|||
* @api {PUT} wxLogout 微信小程序登出 |
|||
* @apiVersion 1.0.0 |
|||
* @apiGroup Auth |
|||
*/ |
|||
app.fs.api.logAttr['PUT/wxLogout'] = { content: '登出', visible: false }; |
|||
router.put('/wxLogout', auth.wxLogout); |
|||
}; |
@ -0,0 +1,17 @@ |
|||
'use strict'; |
|||
|
|||
const camera = require('../../controllers/camera'); |
|||
|
|||
module.exports = function (app, router, opts) { |
|||
app.fs.api.logAttr['GET/camera/project'] = { content: '获取摄像头列表及项目绑定信息', visible: false }; |
|||
router.get('/camera/project', camera.getCameraProject); |
|||
|
|||
app.fs.api.logAttr['GET/camera'] = { content: '获取摄像头信息', visible: false }; |
|||
router.get('/camera', camera.getCamera); |
|||
|
|||
app.fs.api.logAttr['PUT/camera/banned'] = { content: '禁用摄像头', visible: false }; |
|||
router.put('/camera/banned', camera.banned); |
|||
|
|||
app.fs.api.logAttr['DEL/camera'] = { content: '删除摄像头', visible: false }; |
|||
router.delete('/camera', camera.del); |
|||
}; |
@ -0,0 +1,14 @@ |
|||
'use strict'; |
|||
|
|||
const nvr = require('../../controllers/nvr'); |
|||
|
|||
module.exports = function (app, router, opts) { |
|||
app.fs.api.logAttr['POST/nvr'] = { content: '添加/修改nvr', visible: false }; |
|||
router.post('/nvr', nvr.edit); |
|||
|
|||
app.fs.api.logAttr['GET/nvr'] = { content: '获取nvr', visible: false }; |
|||
router.get('/nvr', nvr.get); |
|||
|
|||
app.fs.api.logAttr['DEL/nvr'] = { content: '删除nvr', visible: false }; |
|||
router.del('/nvr/:nvrId', nvr.del); |
|||
}; |
@ -0,0 +1,8 @@ |
|||
'use strict'; |
|||
|
|||
const vender = require('../../controllers/vender'); |
|||
|
|||
module.exports = function (app, router, opts) { |
|||
app.fs.api.logAttr['GET/vender'] = { content: '获取设备厂商', visible: false }; |
|||
router.get('/vender', vender.get); |
|||
}; |
@ -0,0 +1,66 @@ |
|||
'use strict'; |
|||
const request = require('superagent') |
|||
|
|||
class paasRequest { |
|||
constructor(root, { query = {} } = {}) { |
|||
this.root = root; |
|||
this.query = query |
|||
} |
|||
|
|||
#buildUrl = (url) => { |
|||
return `${this.root}/${url}`; |
|||
} |
|||
|
|||
#resultHandler = (resolve, reject) => { |
|||
return (err, res) => { |
|||
if (err) { |
|||
reject(err); |
|||
} else { |
|||
resolve(res.body); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
get = (url, { query = {}, header = {} } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.get(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
|
|||
post = (url, { data = {}, query = {}, header = {} } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.post(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
|
|||
put = (url, { data = {}, header = {}, query = {}, } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.put(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
|
|||
delete = (url, { header = {}, query = {} } = {}) => { |
|||
return new Promise((resolve, reject) => { |
|||
request.delete(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); |
|||
}) |
|||
} |
|||
} |
|||
|
|||
function factory (app, opts) { |
|||
if (opts.pssaRequest) { |
|||
try { |
|||
for (let r of opts.pssaRequest) { |
|||
if (r.name && r.root) { |
|||
app.fs[r.name] = new paasRequest(r.root, { ...(r.params || {}) }) |
|||
} else { |
|||
throw 'opts.pssaRequest 参数错误!' |
|||
} |
|||
} |
|||
} catch (error) { |
|||
console.error(error) |
|||
process.exit(-1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = factory; |
@ -0,0 +1,28 @@ |
|||
'use strict'; |
|||
// https://github.com/luin/ioredis
|
|||
const redis = require("ioredis") |
|||
|
|||
module.exports = async function factory (app, opts) { |
|||
let client = new redis(opts.redis.port, opts.redis.host); |
|||
|
|||
client.on("error", function (err) { |
|||
app.fs.logger.error('info', '[FS-AUTH-REDIS]', 'redis connect error.'); |
|||
console.error("Error :", err); |
|||
process.exit(-1); |
|||
}); |
|||
|
|||
client.on('connect', function () { |
|||
console.log(`redis connect success ${opts.redis.host + ':' + opts.redis.port}`); |
|||
}) |
|||
|
|||
// 自定义方法
|
|||
async function hdelall (key) { |
|||
const obj = await client.hgetall(key); |
|||
await client.hdel(key, Object.keys(obj)) |
|||
} |
|||
|
|||
app.redis = client |
|||
app.redisTools = { |
|||
hdelall, |
|||
} |
|||
} |
@ -0,0 +1,25 @@ |
|||
'use strict'; |
|||
|
|||
module.exports = async function factory (app, opts) { |
|||
|
|||
app.socket.on('connection', async (socket) => { |
|||
console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已连接:' + socket.id); |
|||
socket.on('disconnecting', async (reason) => { |
|||
console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已断开连接:' + reason); |
|||
}) |
|||
}) |
|||
|
|||
// 使用测试 保持链接
|
|||
// setInterval(async () => {
|
|||
// // const { connected } = app.socket.sockets
|
|||
// // const roomId = 'ROOM_' + Math.random()
|
|||
// // if (connected) {
|
|||
// // for (let c in connected) {
|
|||
// // connected[c].join(roomId)
|
|||
// // }
|
|||
// // app.socket.to(roomId).emit('TEST', { someProperty: `【星域 ROOM:${roomId}】呼叫自然选择号!!!`, })
|
|||
// // }
|
|||
|
|||
// app.socket.emit('TEST', { someProperty: '【广播】呼叫青铜时代号!!!', })
|
|||
// }, 1000)
|
|||
} |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"recommendations": [ |
|||
"formulahendry.code-runner" |
|||
] |
|||
} |
After Width: | Height: | Size: 350 B |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 712 B |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 169 B |
After Width: | Height: | Size: 354 B |
After Width: | Height: | Size: 226 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 481 B |
After Width: | Height: | Size: 1.9 MiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 283 KiB |
After Width: | Height: | Size: 538 B |
After Width: | Height: | Size: 434 B |
After Width: | Height: | Size: 258 B |
After Width: | Height: | Size: 453 B |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 945 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 853 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 125 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 549 B |
After Width: | Height: | Size: 5.0 KiB |
@ -0,0 +1,9 @@ |
|||
'use strict'; |
|||
|
|||
import * as global from './global' |
|||
import * as socket from './webSocket'; |
|||
|
|||
export default { |
|||
...global, |
|||
...socket, |
|||
}; |
@ -0,0 +1,33 @@ |
|||
'use strict'; |
|||
import io from 'socket.io-client'; |
|||
|
|||
export const INIT_WEB_SOCKET = 'INIT_WEB_SOCKET' |
|||
export function initWebSocket ({ ioUrl, token }) { |
|||
if (!ioUrl) { |
|||
ioUrl = localStorage.getItem('apiRoot') |
|||
} |
|||
if (!token) { |
|||
const user = sessionStorage.getItem('user') |
|||
if (user) { |
|||
token = JSON.parse(user).token |
|||
} |
|||
} |
|||
if (!ioUrl || !token) { |
|||
return { |
|||
type: '', |
|||
} |
|||
} |
|||
return dispatch => { |
|||
const socket = io(ioUrl, { |
|||
query: { |
|||
token: token |
|||
}, |
|||
}); |
|||
dispatch({ |
|||
type: INIT_WEB_SOCKET, |
|||
payload: { |
|||
socket: socket |
|||
} |
|||
}) |
|||
} |
|||
} |
@ -1,43 +1,85 @@ |
|||
'use strict'; |
|||
import React from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { Nav } from '@douyinfe/semi-ui'; |
|||
"use strict"; |
|||
import React from "react"; |
|||
import { connect } from "react-redux"; |
|||
import { Nav, Avatar, Dropdown } from "@douyinfe/semi-ui"; |
|||
|
|||
const Header = props => { |
|||
const { dispatch, history, user, actions } = props |
|||
const Header = (props) => { |
|||
const { dispatch, history, user, actions, socket } = props; |
|||
|
|||
return ( |
|||
<div style={{ position: 'relative', height: 60, minWidth: 520 }}> |
|||
<div style={{ float: 'left', paddingLeft: 32, fontSize: 16 }}> |
|||
<div style={{ |
|||
lineHeight: '60px', display: 'inline-block', fontSize: 20, textShadow: '0 4px 3px rgba(0, 0, 0, 0.2)', |
|||
userSelect: 'none' |
|||
}}> |
|||
飞尚物联 |
|||
</div> |
|||
</div> |
|||
<div id="nav" style={{ float: 'right' }}> |
|||
<Nav mode={'horizontal'} onClick={({ itemKey }) => { |
|||
if (itemKey == 'logout') { |
|||
dispatch(actions.auth.logout(user)); |
|||
history.push(`/signin`); |
|||
} |
|||
}}> |
|||
<Nav.Sub itemKey={'user'} text={<div style={{ display: 'inline-block' }}>{user.displayName}</div>}> |
|||
<Nav.Item itemKey={'logout'} text={'退出'} /> |
|||
</Nav.Sub> |
|||
</Nav> |
|||
</div> |
|||
</div> |
|||
) |
|||
return ( |
|||
<> |
|||
<Nav |
|||
mode={"horizontal"} |
|||
onClick={({ itemKey }) => { |
|||
if (itemKey == "logout") { |
|||
dispatch(actions.auth.logout(user)); |
|||
if (socket) { |
|||
socket.disconnect(); |
|||
} |
|||
history.push(`/signin`); |
|||
} |
|||
}} |
|||
style={{ |
|||
height: 60, |
|||
minWidth: 520, |
|||
background: "url(/assets/images/background/header.png)", |
|||
backgroundSize: "100% 100%", |
|||
color: "white", |
|||
}} |
|||
header={{ |
|||
logo: ( |
|||
<img |
|||
src="/assets/images/background/logo.png" |
|||
style={{ display: "inline-block", width: 280, height: 52}} |
|||
/> |
|||
), |
|||
text: "", |
|||
}} |
|||
footer={ |
|||
<Nav.Sub |
|||
itemKey={"user"} |
|||
text={ |
|||
<div |
|||
style={{ |
|||
marginLeft: 20, |
|||
display: "inline-block", |
|||
color: "white", |
|||
}} |
|||
> |
|||
<img |
|||
src="/assets/images/background/notice.png" |
|||
style={{ |
|||
display: "inline-block", |
|||
width: 18, |
|||
height: 18, |
|||
position: "relative", |
|||
top: 6, |
|||
left: -10, |
|||
}} |
|||
/> |
|||
|
|||
<Avatar size="small" color="light-blue" style={{ margin: 4 }}> |
|||
<img src="/assets/images/avatar/6.png" /> |
|||
</Avatar> |
|||
{user && user.namePresent} |
|||
</div> |
|||
} |
|||
> |
|||
<Nav.Item itemKey={"logout"} text={"退出"} /> |
|||
</Nav.Sub> |
|||
} |
|||
/> |
|||
</> |
|||
); |
|||
}; |
|||
|
|||
function mapStateToProps (state) { |
|||
const { global, auth } = state; |
|||
return { |
|||
actions: global.actions, |
|||
user: auth.user |
|||
}; |
|||
function mapStateToProps(state) { |
|||
const { global, auth, webSocket } = state; |
|||
return { |
|||
actions: global.actions, |
|||
user: auth.user, |
|||
socket: webSocket.socket, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(Header); |
|||
export default connect(mapStateToProps)(Header); |
|||
|
@ -0,0 +1,21 @@ |
|||
'use strict'; |
|||
import * as actionTypes from '../actions/webSocket'; |
|||
import Immutable from 'immutable'; |
|||
|
|||
const initState = { |
|||
socket: null, |
|||
}; |
|||
|
|||
function webSocket (state = initState, action) { |
|||
const payload = action.payload; |
|||
switch (action.type) { |
|||
case actionTypes.INIT_WEB_SOCKET: |
|||
return Immutable.fromJS(state).merge({ |
|||
socket: payload.socket, |
|||
}).toJS(); |
|||
default: |
|||
return state; |
|||
} |
|||
} |
|||
|
|||
export default webSocket; |
@ -0,0 +1,7 @@ |
|||
input:-webkit-autofill{ |
|||
-webkit-text-fill-color:black !important; |
|||
-webkit-box-shadow: 0 0 0px 1000px transparent inset !important; |
|||
box-shadow: 0 0 0px 1000px transparent inset !important; |
|||
background-color:transparent; |
|||
transition: background-color 50000s ease-in-out 0s; |
|||
} |
@ -0,0 +1,7 @@ |
|||
'use strict'; |
|||
|
|||
import * as nvr from './nvr' |
|||
|
|||
export default { |
|||
...nvr |
|||
} |
@ -0,0 +1,64 @@ |
|||
"use strict"; |
|||
|
|||
import { basicAction } from "@peace/utils"; |
|||
import { ApiTable } from "$utils"; |
|||
|
|||
export function getMembers(orgId) { |
|||
return (dispatch) => |
|||
basicAction({ |
|||
type: "get", |
|||
dispatch: dispatch, |
|||
actionType: "GET_MEMBERS", |
|||
url: `${ApiTable.getEnterprisesMembers.replace("{enterpriseId}", orgId)}`, |
|||
msg: { error: "获取用户列表失败" }, |
|||
reducer: { name: "members" }, |
|||
}); |
|||
} |
|||
|
|||
export function getNvr(query) { |
|||
return (dispatch) => |
|||
basicAction({ |
|||
type: "get", |
|||
dispatch: dispatch, |
|||
actionType: "GET_NVR", |
|||
query: query, |
|||
url: `${ApiTable.getNvr}`, |
|||
msg: { option: "获取nvr列表信息" }, |
|||
reducer: { name: "equipmentWarehouseNvr" }, |
|||
}); |
|||
} |
|||
export function delNvr(orgId) { |
|||
return (dispatch) => |
|||
basicAction({ |
|||
type: "del", |
|||
dispatch: dispatch, |
|||
actionType: "DEL_NVR", |
|||
url: `${ApiTable.delNvr.replace("{nvrId}", orgId)}`, |
|||
msg: { option: "删除NVR" }, |
|||
reducer: { name: "" }, |
|||
}); |
|||
} |
|||
export function addchangeNvr(data) { |
|||
return (dispatch) => |
|||
basicAction({ |
|||
type: "post", |
|||
dispatch: dispatch, |
|||
data, |
|||
actionType: "ADD_CHANGE_NVR", |
|||
msg: { option: "添加/修改" }, |
|||
url: `${ApiTable.nvr}`, |
|||
}); |
|||
} |
|||
|
|||
export function getVender() { |
|||
//获取设备厂商
|
|||
return (dispatch) => |
|||
basicAction({ |
|||
type: "get", |
|||
dispatch: dispatch, |
|||
actionType: "GET_VENDER", |
|||
url: `${ApiTable.getVender}`, |
|||
msg: { error: "获取设备厂商失败" }, |
|||
reducer: { name: "vender" }, |
|||
}); |
|||
} |
@ -0,0 +1,262 @@ |
|||
import React, { useState ,useRef,useEffect} from 'react' |
|||
import { connect } from "react-redux"; |
|||
import { Modal,Spin } from '@douyinfe/semi-ui'; |
|||
import { IconChevronLeft,IconChevronRight } from '@douyinfe/semi-icons'; |
|||
import FluoriteCamera from "./fluoriteCamera"; |
|||
import NvrCamera from './nvrCamera'; |
|||
import IpcCamera from './ipcCamera'; |
|||
import CascadeCamera from './cascadeCamera'; |
|||
import "./cameraModal.less"; |
|||
function cameraModal(props){ |
|||
const {modalName,visible,close}=props |
|||
const fluoriteRef = useRef(); |
|||
const ipcRef = useRef(); |
|||
const cascadeRef = useRef(); |
|||
const [isloading,setloading] = useState(false);//是否显示loading |
|||
const [loadingTip,setloadingTip] = useState('获取中...请稍后...');//loading tip的值 |
|||
const [okText,setokText] = useState('确定')//ok弹框text 右边 |
|||
const [cancelText,setcancelText] = useState('取消')//取消弹框text 左边 |
|||
const opts ={//添加完成确认后通知 |
|||
title:'Hi', |
|||
content:'添加成功', |
|||
duration:3 |
|||
} |
|||
const [clickNum,setclickNum] = useState(1);//点击的第几个 |
|||
const cameraList=[//循环摄像头列表 |
|||
{ |
|||
id:1, |
|||
img:'/assets/images/background/ysy.png', |
|||
title:'萤石云平台摄像头', |
|||
text:'通过萤石云平台rtmp地址配置完成推流的平台摄像头。' |
|||
},{ |
|||
id:2, |
|||
img:'/assets/images/background/nvr.png', |
|||
title:'NVR摄像头', |
|||
text:'通过连接NVR(网络硬盘录像机)进行视频流推送的摄像头' |
|||
},{ |
|||
id:3, |
|||
img:'/assets/images/background/ipc.png', |
|||
title:'IPC网络摄像头', |
|||
text:'通过网络与监控设备直连完成视频流推送的摄像头设备' |
|||
},{ |
|||
id:4, |
|||
img:'/assets/images/background/cascade.png', |
|||
title:'级联摄像头', |
|||
text:'通过GB/T28181协议级联的平台摄像头,常用于平台对接推送' |
|||
}, |
|||
] |
|||
const [showcameraList,setcameraList]=useState(cameraList.slice(0,3));//轮播图 |
|||
function handleOk() {//点击弹框确定 右边按钮 |
|||
if(clickNum==1){ |
|||
console.log('1111111111111'); |
|||
}else if(clickNum==2){ |
|||
console.log('22222222222222'); |
|||
}else if(clickNum==3){ |
|||
console.log('33333333333333'); |
|||
}else if(clickNum==4){ |
|||
console.log('44444444444444'); |
|||
} |
|||
// Notification.success(opts) |
|||
// close(); |
|||
} |
|||
function handleAfterClose(){//在关闭之后 |
|||
|
|||
} |
|||
function handleCancel() {//点击弹框取消 左边按钮 |
|||
close(); |
|||
} |
|||
function handleChoose(id){//选择摄像头接入类型 |
|||
setclickNum(id); |
|||
} |
|||
function turnLift(){//轮播图向左 |
|||
setcameraList(cameraList.slice(0,3)) |
|||
} |
|||
function turnRight(){//轮播图向右 |
|||
setcameraList(cameraList.slice(1,4)) |
|||
} |
|||
function onReset(){ |
|||
if(clickNum==1){ |
|||
fluoriteRef.current.resetFluoriteCamera() |
|||
}else if(clickNum==3){ |
|||
ipcRef.current.resetIpcCamera() |
|||
}else if(clickNum==4){ |
|||
|
|||
} |
|||
} |
|||
function toTest(){ |
|||
if(clickNum==1){ |
|||
fluoriteRef.current.fluoriteCameraForm().then(values=>{//表单校验成功 |
|||
console.log('111111111',values); |
|||
}) |
|||
.catch(errors=>{//表单校验失败 |
|||
console.log('errors',errors); |
|||
}) |
|||
}else if(clickNum==3){ |
|||
ipcRef.current.ipcCameraForm().then(values=>{//表单校验成功 |
|||
console.log('111111111',values); |
|||
}) |
|||
.catch(errors=>{//表单校验失败 |
|||
console.log('errors',errors); |
|||
}) |
|||
}else if(clickNum==4){ |
|||
cascadeRef.current.cascadeCameraForm() |
|||
.then(values=>{//表单校验成功 |
|||
let chooseList=[] |
|||
let nvrCameraList=[{ |
|||
id:10, |
|||
name:'南昌县1', |
|||
number:'111111111111111111', |
|||
support:false, |
|||
change:false, |
|||
},{ |
|||
id:20, |
|||
name:'南昌县2', |
|||
number:'222222222222222222', |
|||
support:false, |
|||
change:false, |
|||
},{ |
|||
id:30, |
|||
name:'南昌县3', |
|||
number:'333333333333333333', |
|||
support:false, |
|||
change:false, |
|||
},{ |
|||
id:40, |
|||
name:'南昌县4', |
|||
number:'444444444444444444', |
|||
support:false, |
|||
change:false, |
|||
}] |
|||
cascadeRef.current.setNVRcameraList(nvrCameraList) |
|||
for (let index = 0; index < nvrCameraList.length; index++) { |
|||
chooseList.push(nvrCameraList[index].id) |
|||
} |
|||
cascadeRef.current.setNvrCheckList(chooseList) |
|||
cascadeRef.current.setIsAllChoose(true) |
|||
}) |
|||
.catch(errors=>{//表单校验失败 |
|||
console.log('errors',errors); |
|||
}) |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<> |
|||
<Modal |
|||
title={modalName=='add'?'添加摄像头':'修改摄像头'} |
|||
okText={okText} |
|||
cancelText={cancelText} //取消按钮 |
|||
visible={visible} |
|||
onOk={handleOk} |
|||
width={921} |
|||
afterClose={handleAfterClose} |
|||
onCancel={handleCancel} |
|||
> |
|||
<Spin tip={loadingTip} spinning={isloading}> |
|||
<div style={{marginLeft:'-24px',marginRight:'-24px',marginTop:8}}> |
|||
<div style={{marginLeft:29,color:'#1859C1',fontSize:14,fontWeight:500}}>接入类型</div> |
|||
<div style={{marginTop:5,display:'flex',alignItems:'center',justifyContent:'space-between'}}> |
|||
<IconChevronLeft |
|||
style={{color:'rgba(0, 0, 0, 0.45)',fontSize:16,marginLeft:29,cursor: "pointer",}} |
|||
onClick={turnLift}/> |
|||
<div |
|||
style={{display:'flex',alignItems:'center',height:146}}> |
|||
{showcameraList.map((item,index)=>( |
|||
<div |
|||
key={item.id} |
|||
style={{ |
|||
width:266, |
|||
height:146, |
|||
marginRight:12, |
|||
border:clickNum===item.id?'1px solid #1859C1':'1px solid #F9F9F9', |
|||
borderRadius:3, |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
alignItems: 'center', |
|||
cursor: "pointer", |
|||
position: 'relative'}} |
|||
onClick={()=>handleChoose(item.id)}> |
|||
<div |
|||
style={{marginTop:5, |
|||
height:65, |
|||
width:116, |
|||
display: 'flex', |
|||
justifyContent: 'center', |
|||
alignItems: 'center'}}> |
|||
<img |
|||
src={item.img} |
|||
alt="设置" |
|||
/> |
|||
</div> |
|||
<div style={{marginTop:2,fontSize:14,color:'rgba(0, 0, 0, 0.85)',}}>{item.title}</div> |
|||
<div style={{width:210,height:34,marginTop:9,fontSize:12,color:'rgba(0, 0, 0, 0.45)',textAlign:'center'}}>{item.text}</div> |
|||
{clickNum===item.id?<div style={{ position: 'absolute', top: '-3px', right: '-5px'}}> |
|||
<img src="/assets/images/background/topchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</div> |
|||
))} |
|||
</div> |
|||
<IconChevronRight |
|||
style={{color:'rgba(0, 0, 0, 0.45)',fontSize:16,marginRight:18,cursor: "pointer",}} |
|||
onClick={turnRight}/> |
|||
</div> |
|||
</div> |
|||
<div style={{height:30,marginLeft:'-24px',marginRight:'-24px',marginTop:48,display:'flex',alignItems: 'center',justifyContent: 'space-between'}}> |
|||
<div style={{marginLeft:29,color:'#1859C1',fontSize:14,fontWeight:500}}>配置属性</div> |
|||
{clickNum!==2?<div style={{display:'flex',marginRight:43,}}> |
|||
<div style={{ |
|||
height:30, |
|||
width:64, |
|||
border:'1px solid #D9D9D9', |
|||
borderRadius: '3px', |
|||
color:'rgba(0, 0, 0, 0.65)', |
|||
display:'flex', |
|||
justifyContent: 'center', |
|||
alignItems: 'center', |
|||
cursor: "pointer", |
|||
marginRight:16 |
|||
}} onClick={onReset}> |
|||
<img src="/assets/images/background/Reset.png" alt="1" style={{marginRight:4}}/> |
|||
重置 |
|||
</div> |
|||
<div style={{ |
|||
height:30, |
|||
width:64, |
|||
border:'1px solid #1859C1', |
|||
borderRadius: '3px', |
|||
color:'#1859C1', |
|||
display:'flex', |
|||
justifyContent: 'center', |
|||
alignItems: 'center', |
|||
cursor: "pointer", |
|||
}} onClick={toTest}> |
|||
<img src="/assets/images/background/test.png" alt="1" style={{marginRight:4}} /> |
|||
测试 |
|||
</div> |
|||
</div>:''} |
|||
</div> |
|||
<div> |
|||
{clickNum==1? |
|||
<FluoriteCamera cRef={fluoriteRef}/> |
|||
:clickNum==2? |
|||
<NvrCamera/> |
|||
:clickNum==3? |
|||
<IpcCamera aRef={ipcRef} /> |
|||
:<CascadeCamera dRef={cascadeRef}/>} |
|||
</div> |
|||
</Spin> |
|||
</Modal> |
|||
</> |
|||
); |
|||
} |
|||
function mapStateToProps(state) { |
|||
const { auth, global, members } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(cameraModal); |
@ -0,0 +1,9 @@ |
|||
.semi-radio-cardRadioGroup_checked .cloud{ |
|||
color: #1859C1; |
|||
} |
|||
.semi-radio-cardRadioGroup_checked .voice{ |
|||
color: #1859C1; |
|||
} |
|||
.semi-radio-cardRadioGroup_checked .switching{ |
|||
color: #1859C1; |
|||
} |
@ -0,0 +1,192 @@ |
|||
import React, { useState ,useRef,useEffect,useImperativeHandle} from 'react' |
|||
import { connect } from "react-redux"; |
|||
import { Form,Row,Col,CheckboxGroup, Checkbox,Radio,Input } from '@douyinfe/semi-ui'; |
|||
import { IconEdit,IconPlayCircle } from '@douyinfe/semi-icons'; |
|||
import "./cameraModal.less"; |
|||
function cascadeCamera({dRef}){ |
|||
const form = useRef(); |
|||
const [memoryList,setMemoryList] = useState([ |
|||
{ |
|||
id:1, |
|||
value:'8g' |
|||
},{ |
|||
id:2, |
|||
value:'16g' |
|||
},{ |
|||
id:3, |
|||
value:'32g' |
|||
},{ |
|||
id:4, |
|||
value:'64g' |
|||
},{ |
|||
id:5, |
|||
value:'128g' |
|||
},{ |
|||
id:6, |
|||
value:'256g' |
|||
},{ |
|||
id:7, |
|||
value:'>256g' |
|||
} |
|||
])//内存卡列表 |
|||
const [nvrCheckList, setNvrCheckList] = useState([]);//nvr视频流多选 |
|||
const [NVRcameraList,setNVRcameraList]=useState([])//nvr视频流列表 |
|||
const [isAllChoose,setIsAllChoose]=useState(false)//全选 |
|||
const [equipmentNum,setEquipmentNum]=useState('')//nvr视频编号 |
|||
function NvrChangeName(e,index){//nvr摄像头视频流获取修改名称 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].change=true |
|||
setNVRcameraList(NvrchangeList) |
|||
e.stopPropagation() |
|||
} |
|||
function nvronBlur(index){//nvr摄像头名称修改失去焦点 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].change=false |
|||
setNVRcameraList(NvrchangeList) |
|||
} |
|||
function inputchange(e,index){//nvr摄像头名称修改 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].name=e |
|||
setNVRcameraList(NvrchangeList) |
|||
} |
|||
function toggle(e,index){//nvr云台支持 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].support=e.target.checked |
|||
setNVRcameraList(NvrchangeList) |
|||
e.stopPropagation() |
|||
} |
|||
function allChoose(e){//全选/全不选 |
|||
let chooseList=[] |
|||
if(NVRcameraList.length==nvrCheckList.length){ |
|||
setNvrCheckList([]) |
|||
setIsAllChoose(false) |
|||
} |
|||
else{ |
|||
for (let index = 0; index < NVRcameraList.length; index++) { |
|||
chooseList.push(NVRcameraList[index].id) |
|||
} |
|||
setNvrCheckList(chooseList) |
|||
setIsAllChoose(true) |
|||
} |
|||
} |
|||
function playVideo(e) {//nvr播放视频 |
|||
console.log('22222222222222222'); |
|||
e.stopPropagation() |
|||
} |
|||
useImperativeHandle(dRef,() => ({//传给父组件方法 |
|||
//子组件暴露给父组件的方法 |
|||
cascadeCameraForm : form.current.validate, |
|||
resetCascadeCamera : form.current.reset, |
|||
setNVRcameraList : setNVRcameraList, |
|||
setNvrCheckList : setNvrCheckList, |
|||
setIsAllChoose : setIsAllChoose, |
|||
})) |
|||
return ( |
|||
<> |
|||
<Form |
|||
allowEmpty |
|||
labelPosition='left' |
|||
labelAlign='left' |
|||
labelWidth= '115px' |
|||
onValueChange={values=>{console.log(values);setEquipmentNum(values.equipmentNum)}} |
|||
getFormApi={formApi => form.current = formApi}> |
|||
<Row> |
|||
<Col span={12}> |
|||
<Form.Input field='foreignDomainName' label='外域名称:' initValue={''} placeholder='请输入外域名称' style={{ width:307 }} |
|||
rules={[ |
|||
{ required: true, message: '请输入外域名称' } |
|||
]}/> |
|||
</Col> |
|||
<Col span={12}> |
|||
<Form.Select label="级联方式:" field='cascadeMode' placeholder='请选择级联方式' style={{ width:307 }} |
|||
rules={[ |
|||
{ required: true, message: '请选择输入级联方式' } |
|||
]}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
</Col> |
|||
<Col span={12}> |
|||
<Form.Select label="SIP编号:" field='sipNum' placeholder='请选择SIP编号' style={{ width:307 }} |
|||
rules={[ |
|||
{ required: true, message: '请选择SIP编号' } |
|||
]}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
</Col> |
|||
<Col span={24}> |
|||
{NVRcameraList.length>0?<div style={{display: 'flex',alignItems: 'center',justifyContent: 'flex-end',marginRight:19}}> |
|||
<Radio |
|||
checked={isAllChoose} |
|||
mode="advanced" |
|||
onChange={e=>allChoose(e)} |
|||
aria-label="全选"> |
|||
全选 |
|||
</Radio> |
|||
</div>:''} |
|||
</Col> |
|||
</Row> |
|||
<Row> |
|||
<CheckboxGroup type='pureCard' direction='vertical' aria-label="视频流获取" |
|||
value={nvrCheckList} |
|||
onChange={(nvrCheck) => { |
|||
setNvrCheckList(nvrCheck); |
|||
console.log('11111111111',nvrCheck); |
|||
if(NVRcameraList.length==nvrCheck.length){ |
|||
setIsAllChoose(true) |
|||
} |
|||
else{ |
|||
setIsAllChoose(false) |
|||
} |
|||
}}> |
|||
{NVRcameraList.length>0?NVRcameraList.map((item,index)=>( |
|||
<Col key={index} span={12} style={{display:'flex',justifyContent:'center',marginTop:12}}> |
|||
<Checkbox value={item.id} |
|||
extra={ |
|||
<div> |
|||
<div style={{display:'flex',alignItems:'center',justifyContent:'space-between',height:30}}> |
|||
<div>通道名称:{item.change?<Input autofocus style={{width:100}} value={item.name} onChange={e=>inputchange(e,index)} onBlur={()=>nvronBlur(index)}></Input>:item.name}</div> |
|||
<div style={{display:'flex',alignItems:'center'}}> |
|||
<IconEdit |
|||
style={{fontSize:16,marginLeft:18,cursor: "pointer",color:'#1859C1'}} |
|||
onClick={e=>NvrChangeName(e,index)}/> |
|||
</div> |
|||
</div> |
|||
<div style={{marginTop:8,width:246}}>设备编号:{item.number}</div> |
|||
<div style={{marginTop:12,display:'flex',justifyContent:'space-between',alignItems:'center'}}> |
|||
<IconPlayCircle size='extra-large' style={{color:'#1859C1',}} onClick={e=>playVideo(e)}/> |
|||
<Radio |
|||
checked={item.support} |
|||
mode="advanced" |
|||
onChange={e=>toggle(e,index)} |
|||
aria-label="单选" |
|||
> |
|||
云台支持 |
|||
</Radio> |
|||
</div> |
|||
</div> |
|||
} |
|||
style={{width:280,border:'1px solid #F9F9F9',}}> |
|||
</Checkbox> |
|||
</Col> |
|||
)):''} |
|||
</CheckboxGroup> |
|||
</Row> |
|||
</Form> |
|||
</> |
|||
); |
|||
} |
|||
function mapStateToProps(state) { |
|||
const { auth, global, members } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(cascadeCamera); |
@ -0,0 +1,262 @@ |
|||
import React, { useState ,useRef,useEffect,useImperativeHandle} from 'react' |
|||
import { connect } from "react-redux"; |
|||
import { Form,Row,Col} from '@douyinfe/semi-ui'; |
|||
import "./cameraModal.less"; |
|||
function fluoriteCamera({cRef}){ |
|||
const { TextArea } = Form; |
|||
const form = useRef(); |
|||
const [cloud,setcloud] = useState('')//云台支持 |
|||
const [voice,setvoice] = useState('')//语音支持 |
|||
const [switching,setSwitching] = useState('')//高清切换 |
|||
const [memoryList,setMemoryList] = useState([ |
|||
{ |
|||
id:1, |
|||
value:'8g' |
|||
},{ |
|||
id:2, |
|||
value:'16g' |
|||
},{ |
|||
id:3, |
|||
value:'32g' |
|||
},{ |
|||
id:4, |
|||
value:'64g' |
|||
},{ |
|||
id:5, |
|||
value:'128g' |
|||
},{ |
|||
id:6, |
|||
value:'256g' |
|||
},{ |
|||
id:7, |
|||
value:'>256g' |
|||
} |
|||
])//内存卡列表 |
|||
function handleLocation(){//高德经纬度 |
|||
window.open('https://lbs.amap.com/tools/picker','_blank') |
|||
} |
|||
function positionForm(val){//安装位置校验 |
|||
let zz = /^(-?\d+)(\.\d+)?$/ |
|||
if(!val){ |
|||
return '请输入或拾取高德经纬度坐标' |
|||
} |
|||
else if(val.split(',').length!=2){ |
|||
return '请输入格式为116.354169,39.835452的经纬度坐标' |
|||
} |
|||
else if(!zz.test(val.split(',')[0])){ |
|||
return '只能填写数字' |
|||
} |
|||
else if(!zz.test(val.split(',')[1])){ |
|||
return '只能填写数字' |
|||
} |
|||
else{ |
|||
return '' |
|||
} |
|||
} |
|||
useImperativeHandle(cRef,() => ({//传给父组件方法 |
|||
//子组件暴露给父组件的方法 |
|||
fluoriteCameraForm : form.current.validate, |
|||
resetFluoriteCamera : form.current.reset |
|||
})) |
|||
return ( |
|||
<> |
|||
<Form |
|||
labelPosition='left' |
|||
labelAlign='left' |
|||
labelWidth= '115px' |
|||
onValueChange={values=>console.log(values)} |
|||
getFormApi={formApi => form.current = formApi}> |
|||
<Row> |
|||
<Col span={12}> |
|||
{/* 设备名称 */} |
|||
<Form.Input field='UserName' label='设备名称:' initValue={''} placeholder='请输入设备名称、常用项目或位置定义' style={{ width:307 }} |
|||
rules={[ |
|||
{ required: true, message: '请输入设备名称' } |
|||
]}/> |
|||
{/* 高清切换 */} |
|||
<Form.RadioGroup |
|||
label="高清切换:" |
|||
field='hdSwitching' |
|||
type='pureCard' |
|||
direction='horizontal' |
|||
style={{padding:0,paddingTop:1,paddingBottom:1}} |
|||
rules={[ |
|||
{ required: true, message: '请选择高清切换' } |
|||
]} |
|||
onChange={(checked) => { |
|||
console.log(checked.target.value); |
|||
if(checked.target.value=='yes'){ |
|||
setSwitching('yes') |
|||
} |
|||
else{ |
|||
setSwitching('no') |
|||
} |
|||
}}> |
|||
<Form.Radio value="yes" style={{width:58,height:30,padding:0,margin:0,background:'#F9F9F9'}}> |
|||
<div className='switching' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
支持 |
|||
</div> |
|||
{switching=='yes'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
<Form.Radio value="no" style={{width:58,height:30,padding:0,margin:0,marginLeft:18,background:'#F9F9F9'}}> |
|||
<div className='switching' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
不支持 |
|||
</div> |
|||
{switching=='no'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
</Form.RadioGroup> |
|||
{/* 安装位置 */} |
|||
<div style={{display:'flex'}}> |
|||
<Form.Input field='Use11rName1312' label='安装位置:' placeholder='请输入或拾取高德经纬度坐标' style={{ width:270 }} |
|||
validate={positionForm} |
|||
rules={[ |
|||
{ required: true, message: '请输入或拾取高德经纬度坐标' } |
|||
]}/> |
|||
<div style={{ |
|||
width:32, |
|||
height:32, |
|||
background:"#1859C1", |
|||
marginLeft:4, |
|||
display:'flex', |
|||
justifyContent: 'center', |
|||
alignItems: 'center', |
|||
cursor: "pointer", |
|||
marginTop:12, |
|||
borderRadius: 3+'px'}} |
|||
onClick={handleLocation}> |
|||
<img src="../../../assets/images/background/location.png" width={16} height={20}/> |
|||
</div> |
|||
</div> |
|||
{/* 设备类型 */} |
|||
<div style={{display:'flex',}}> |
|||
<div> |
|||
<Form.Select label="设备类型:" field='business23' placeholder='请选择摄像头类型' style={{ width:160 }} |
|||
rules={[ |
|||
{ required: true, message: '请选择摄像头类型' } |
|||
]}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
</div> |
|||
<div style={{marginLeft:7}}> |
|||
<Form.Select noLabel='true' field='business244' placeholder='请选择能力' style={{ width:140 }} |
|||
rules={[ |
|||
{ required: true, message: '请选择能力' } |
|||
]}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
</div> |
|||
</div> |
|||
</Col> |
|||
<Col span={12}> |
|||
{/* 云台支持 */} |
|||
<Form.RadioGroup |
|||
label="云台支持:" |
|||
field='role' |
|||
type='pureCard' |
|||
direction='horizontal' |
|||
style={{padding:0,paddingTop:1,paddingBottom:1}} |
|||
rules={[ |
|||
{ required: true, message: '请选择云台支持' } |
|||
]} |
|||
onChange={(checked) => { |
|||
console.log(checked.target.value); |
|||
if(checked.target.value=='yes'){ |
|||
setcloud('yes') |
|||
} |
|||
else{ |
|||
setcloud('no') |
|||
} |
|||
}}> |
|||
<Form.Radio value="yes" style={{width:58,height:30,padding:0,margin:0,background:'#F9F9F9'}}> |
|||
<div className='cloud' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
支持 |
|||
</div> |
|||
{cloud=='yes'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
<Form.Radio value="no" style={{width:58,height:30,padding:0,margin:0,marginLeft:18,background:'#F9F9F9'}}> |
|||
<div className='cloud' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
不支持 |
|||
</div> |
|||
{cloud=='no'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
</Form.RadioGroup> |
|||
{/* 内存 */} |
|||
<div style={{display:'flex'}}> |
|||
<Form.Select label="内存:" field='business2' placeholder='未安装' style={{ width:92 }}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
{/* 语音支持 */} |
|||
<div style={{marginLeft:18}}> |
|||
<Form.RadioGroup |
|||
labelWidth= '76px' |
|||
label="语音支持:" |
|||
field='role2' |
|||
type='pureCard' |
|||
direction='horizontal' |
|||
style={{padding:0,paddingTop:1,paddingBottom:1}} |
|||
onChange={(checked) => { |
|||
console.log(checked.target.value); |
|||
if(checked.target.value=='yes'){ |
|||
setvoice('yes') |
|||
} |
|||
else{ |
|||
setvoice('no') |
|||
} |
|||
}}> |
|||
<Form.Radio value="yes" style={{width:58,height:30,padding:0,margin:0,background:'#F9F9F9'}}> |
|||
<div className='voice' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
支持 |
|||
</div> |
|||
{voice=='yes'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
<Form.Radio value="no" style={{width:58,height:30,padding:0,margin:0,marginLeft:18,background:'#F9F9F9'}}> |
|||
<div className='voice' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
不支持 |
|||
</div> |
|||
{voice=='no'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
</Form.RadioGroup> |
|||
</div> |
|||
</div> |
|||
{/* RTMP地址接入 */} |
|||
<TextArea |
|||
style={{ width:320, height: 90 }} |
|||
field='description' |
|||
label='RTMP地址接入:' |
|||
placeholder='请输入RTMP地址接入' |
|||
/> |
|||
</Col> |
|||
</Row> |
|||
</Form> |
|||
</> |
|||
); |
|||
} |
|||
function mapStateToProps(state) { |
|||
const { auth, global, members } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(fluoriteCamera); |
@ -0,0 +1,224 @@ |
|||
import React, { useState ,useRef,useEffect,useImperativeHandle} from 'react' |
|||
import { connect } from "react-redux"; |
|||
import { Form,Row,Col } from '@douyinfe/semi-ui'; |
|||
import "./cameraModal.less"; |
|||
function ipcCamera({aRef}){ |
|||
const { TextArea } = Form; |
|||
const form = useRef(); |
|||
const [cloud,setcloud] = useState('')//云台支持 |
|||
const [voice,setvoice] = useState('')//语音支持 |
|||
const [memoryList,setMemoryList] = useState([ |
|||
{ |
|||
id:1, |
|||
value:'8g' |
|||
},{ |
|||
id:2, |
|||
value:'16g' |
|||
},{ |
|||
id:3, |
|||
value:'32g' |
|||
},{ |
|||
id:4, |
|||
value:'64g' |
|||
},{ |
|||
id:5, |
|||
value:'128g' |
|||
},{ |
|||
id:6, |
|||
value:'256g' |
|||
},{ |
|||
id:7, |
|||
value:'>256g' |
|||
} |
|||
])//内存卡列表 |
|||
function handleLocation(){//高德经纬度 |
|||
window.open('https://lbs.amap.com/tools/picker','_blank') |
|||
} |
|||
function positionForm(val){//安装位置校验 |
|||
let zz = /^(-?\d+)(\.\d+)?$/ |
|||
if(!val){ |
|||
return '请输入或拾取高德经纬度坐标' |
|||
} |
|||
else if(val.split(',').length!=2){ |
|||
return '请输入格式为116.354169,39.835452的经纬度坐标' |
|||
} |
|||
else if(!zz.test(val.split(',')[0])){ |
|||
return '只能填写数字' |
|||
} |
|||
else if(!zz.test(val.split(',')[1])){ |
|||
return '只能填写数字' |
|||
} |
|||
else{ |
|||
return '' |
|||
} |
|||
} |
|||
useImperativeHandle(aRef,() => ({//传给父组件方法 |
|||
//子组件暴露给父组件的方法 |
|||
ipcCameraForm : form.current.validate, |
|||
resetIpcCamera : form.current.reset |
|||
})) |
|||
return ( |
|||
<> |
|||
<Form |
|||
labelPosition='left' |
|||
labelAlign='left' |
|||
labelWidth= '115px' |
|||
onValueChange={values=>console.log(values)} |
|||
getFormApi={formApi => form.current = formApi}> |
|||
<Row> |
|||
<Col span={12}> |
|||
<Form.Input field='UserName' label='设备名称:' initValue={''} placeholder='请输入设备名称、常用项目或位置定义' style={{ width:307 }} |
|||
rules={[ |
|||
{ required: true, message: '请输入设备名称' } |
|||
]}/> |
|||
<Form.Input field='Use11rName11' label='设备厂家:' placeholder='请选择设备厂家' style={{ width:307 }}/> |
|||
<div style={{display:'flex'}}> |
|||
<Form.Input field='Use11rName1312' label='安装位置:' placeholder='请输入或拾取高德经纬度坐标' style={{ width:270 }} |
|||
validate={positionForm} |
|||
rules={[ |
|||
{ required: true, message: '请输入或拾取高德经纬度坐标' } |
|||
]}/> |
|||
<div style={{ |
|||
width:32, |
|||
height:32, |
|||
background:"#1859C1", |
|||
marginLeft:4, |
|||
display:'flex', |
|||
justifyContent: 'center', |
|||
alignItems: 'center', |
|||
cursor: "pointer", |
|||
marginTop:12, |
|||
borderRadius: 3+'px'}} |
|||
onClick={handleLocation}> |
|||
<img src="../../../assets/images/background/location.png" width={16} height={20}/> |
|||
</div> |
|||
</div> |
|||
<div> |
|||
<Form.Input field='UserName11' label='设备编号接入:' initValue={''} placeholder='请输入设备编号' style={{ width:307 }}/> |
|||
</div> |
|||
</Col> |
|||
<Col span={12}> |
|||
<Form.RadioGroup |
|||
label="云台支持:" |
|||
field='role' |
|||
type='pureCard' |
|||
direction='horizontal' |
|||
style={{padding:0,paddingTop:1,paddingBottom:1}} |
|||
rules={[ |
|||
{ required: true, message: '请选择云台支持' } |
|||
]} |
|||
onChange={(checked) => { |
|||
console.log(checked.target.value); |
|||
if(checked.target.value=='yes'){ |
|||
setcloud('yes') |
|||
} |
|||
else{ |
|||
setcloud('no') |
|||
} |
|||
}}> |
|||
<Form.Radio value="yes" style={{width:58,height:30,padding:0,margin:0,background:'#F9F9F9'}}> |
|||
<div className='cloud' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
支持 |
|||
</div> |
|||
{cloud=='yes'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
<Form.Radio value="no" style={{width:58,height:30,padding:0,margin:0,marginLeft:18,background:'#F9F9F9'}}> |
|||
<div className='cloud' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
不支持 |
|||
</div> |
|||
{cloud=='no'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
</Form.RadioGroup> |
|||
<div style={{display:'flex'}}> |
|||
<Form.Select label="内存:" field='business2' placeholder='未安装' style={{ width:92 }}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
<div style={{marginLeft:18}}> |
|||
<Form.RadioGroup |
|||
labelWidth= '76px' |
|||
label="语音支持:" |
|||
field='role2' |
|||
type='pureCard' |
|||
direction='horizontal' |
|||
style={{padding:0}} |
|||
onChange={(checked) => { |
|||
console.log(checked.target.value); |
|||
if(checked.target.value=='yes'){ |
|||
setvoice('yes') |
|||
} |
|||
else{ |
|||
setvoice('no') |
|||
} |
|||
}}> |
|||
<Form.Radio value="yes" style={{width:58,height:30,padding:0,margin:0,background:'#F9F9F9'}}> |
|||
<div className='voice' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
支持 |
|||
</div> |
|||
{voice=='yes'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
<Form.Radio value="no" style={{width:58,height:30,padding:0,margin:0,marginLeft:18,background:'#F9F9F9'}}> |
|||
<div className='voice' style={{width:58,height:30,textAlign:'center',lineHeight:'30px'}}> |
|||
不支持 |
|||
</div> |
|||
{voice=='no'?<div style={{position: 'absolute', top: '-2px', right: '-1px'}}> |
|||
<img src="/assets/images/background/formchoose.png" alt="1" /> |
|||
</div>:''} |
|||
</Form.Radio> |
|||
</Form.RadioGroup> |
|||
</div> |
|||
</div> |
|||
<TextArea |
|||
style={{ width:320, height: 90 }} |
|||
field='description' |
|||
label='RTMP地址接入:' |
|||
placeholder='请输入RTMP地址接入' |
|||
/> |
|||
</Col> |
|||
<Col span={18}> |
|||
<div style={{display:'flex',}}> |
|||
<div> |
|||
<Form.Select label="设备类型:" field='business23' placeholder='请选择摄像头类型' style={{ width:160 }} |
|||
rules={[ |
|||
{ required: true, message: '请选择摄像头类型' } |
|||
]}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
</div> |
|||
<div style={{marginLeft:7}}> |
|||
<Form.Select noLabel='true' field='business244' placeholder='请选择能力' style={{ width:140 }} |
|||
rules={[ |
|||
{ required: true, message: '请选择能力' } |
|||
]}> |
|||
{memoryList.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.value}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
</div> |
|||
</div> |
|||
</Col> |
|||
</Row> |
|||
</Form> |
|||
</> |
|||
); |
|||
} |
|||
function mapStateToProps(state) { |
|||
const { auth, global, members } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(ipcCamera); |
@ -0,0 +1,182 @@ |
|||
import React, { useState ,useRef,useEffect,useImperativeHandle} from 'react' |
|||
import { connect } from "react-redux"; |
|||
import { Form,Row,Col,Button,CheckboxGroup, Checkbox,Radio,Input } from '@douyinfe/semi-ui'; |
|||
import { IconEdit,IconPlayCircle } from '@douyinfe/semi-icons'; |
|||
import "./cameraModal.less"; |
|||
function nvrCamera({cRef}){ |
|||
const form = useRef(); |
|||
const [nvrCheckList, setNvrCheckList] = useState([]);//nvr视频流多选 |
|||
const [NVRcameraList,setNVRcameraList]=useState([])//nvr视频流列表 |
|||
const [isAllChoose,setIsAllChoose]=useState(false)//全选 |
|||
const [equipmentNum,setEquipmentNum]=useState('')//nvr视频编号 |
|||
function NvrChangeName(e,index){//nvr摄像头视频流获取修改名称 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].change=true |
|||
setNVRcameraList(NvrchangeList) |
|||
e.stopPropagation() |
|||
} |
|||
function nvronBlur(index){//nvr摄像头名称修改失去焦点 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].change=false |
|||
setNVRcameraList(NvrchangeList) |
|||
} |
|||
function inputchange(e,index){//nvr摄像头名称修改 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].name=e |
|||
setNVRcameraList(NvrchangeList) |
|||
} |
|||
function toggle(e,index){//nvr云台支持 |
|||
let NvrchangeList = JSON.parse(JSON.stringify(NVRcameraList)) |
|||
NvrchangeList[index].support=e.target.checked |
|||
setNVRcameraList(NvrchangeList) |
|||
e.stopPropagation() |
|||
} |
|||
function getVideoList(){ |
|||
form.current.validate().then(values=>{//表单校验成功 |
|||
let chooseList=[] |
|||
let nvrCameraList=[{ |
|||
id:10, |
|||
name:'南昌县1', |
|||
number:'111111111111111111', |
|||
support:false, |
|||
change:false, |
|||
},{ |
|||
id:20, |
|||
name:'南昌县2', |
|||
number:'222222222222222222', |
|||
support:false, |
|||
change:false, |
|||
},{ |
|||
id:30, |
|||
name:'南昌县3', |
|||
number:'333333333333333333', |
|||
support:false, |
|||
change:false, |
|||
},{ |
|||
id:40, |
|||
name:'南昌县4', |
|||
number:'444444444444444444', |
|||
support:false, |
|||
change:false, |
|||
}] |
|||
setNVRcameraList(nvrCameraList) |
|||
for (let index = 0; index < nvrCameraList.length; index++) { |
|||
chooseList.push(nvrCameraList[index].id) |
|||
} |
|||
setNvrCheckList(chooseList) |
|||
setIsAllChoose(true) |
|||
}) |
|||
.catch(errors=>{//表单校验失败 |
|||
console.log('errors',errors); |
|||
}) |
|||
} |
|||
function allChoose(e){//全选/全不选 |
|||
let chooseList=[] |
|||
if(NVRcameraList.length==nvrCheckList.length){ |
|||
setNvrCheckList([]) |
|||
setIsAllChoose(false) |
|||
} |
|||
else{ |
|||
for (let index = 0; index < NVRcameraList.length; index++) { |
|||
chooseList.push(NVRcameraList[index].id) |
|||
} |
|||
setNvrCheckList(chooseList) |
|||
setIsAllChoose(true) |
|||
} |
|||
} |
|||
function playVideo(e) {//nvr播放视频 |
|||
console.log('22222222222222222'); |
|||
e.stopPropagation() |
|||
} |
|||
// useImperativeHandle(cRef,() => ({//传给父组件方法 |
|||
// //aa即为子组件暴露给父组件的方法 |
|||
// getDate : form.current.validate, |
|||
// // resetFluoriteCamera : form.current.reset |
|||
// })) |
|||
return ( |
|||
<> |
|||
<Form |
|||
allowEmpty |
|||
labelPosition='left' |
|||
labelAlign='left' |
|||
labelWidth= '115px' |
|||
onValueChange={values=>{setEquipmentNum(values.equipmentNum)}} |
|||
getFormApi={formApi => form.current = formApi}> |
|||
<div style={{display:'flex'}}> |
|||
<Form.Input field='equipmentNum' maxLength='39' label='设备编号:' initValue={''} placeholder='请输入设备编号' style={{ width:307 }} |
|||
rules={[ |
|||
{ required: true, message: '请输入设备编号' }, |
|||
{ pattern: '^[A-Za-z0-9]+$', message: '只能输入数字或者字母' } |
|||
]}/> |
|||
<Button disabled={!equipmentNum.length>0} theme='solid' type='primary' onClick={()=>{getVideoList()}} style={{ marginLeft: 8,marginTop:12 }}>视频流获取</Button> |
|||
{NVRcameraList.length>0?<div style={{display: 'flex',alignItems: 'center',marginLeft: 211}}> |
|||
<Radio |
|||
checked={isAllChoose} |
|||
mode="advanced" |
|||
onChange={e=>allChoose(e)} |
|||
aria-label="全选"> |
|||
全选 |
|||
</Radio> |
|||
</div>:''} |
|||
</div> |
|||
<Row> |
|||
<CheckboxGroup type='pureCard' direction='vertical' aria-label="视频流获取" |
|||
value={nvrCheckList} |
|||
onChange={(nvrCheck) => { |
|||
setNvrCheckList(nvrCheck); |
|||
// console.log('11111111111',nvrCheck); |
|||
if(NVRcameraList.length==nvrCheck.length){ |
|||
setIsAllChoose(true) |
|||
} |
|||
else{ |
|||
setIsAllChoose(false) |
|||
} |
|||
}}> |
|||
{NVRcameraList.length>0?NVRcameraList.map((item,index)=>( |
|||
<Col key={index} span={12} style={{display:'flex',justifyContent:'center',marginTop:12}}> |
|||
<Checkbox value={item.id} |
|||
extra={ |
|||
<div> |
|||
<div style={{display:'flex',alignItems:'center',justifyContent:'space-between',height:30}}> |
|||
<div>通道名称:{item.change?<Input autofocus style={{width:100}} value={item.name} onChange={e=>inputchange(e,index)} onBlur={()=>nvronBlur(index)}></Input>:item.name}</div> |
|||
<div style={{display:'flex',alignItems:'center'}}> |
|||
<IconEdit |
|||
style={{fontSize:16,marginLeft:18,cursor: "pointer",color:'#1859C1'}} |
|||
onClick={e=>NvrChangeName(e,index)}/> |
|||
</div> |
|||
</div> |
|||
<div style={{marginTop:8,width:246}}>设备编号:{item.number}</div> |
|||
<div style={{marginTop:12,display:'flex',justifyContent:'space-between',alignItems:'center'}}> |
|||
<IconPlayCircle size='extra-large' style={{color:'#1859C1',}} onClick={e=>playVideo(e)}/> |
|||
<Radio |
|||
checked={item.support} |
|||
mode="advanced" |
|||
onChange={e=>toggle(e,index)} |
|||
aria-label="单选" |
|||
> |
|||
云台支持 |
|||
</Radio> |
|||
</div> |
|||
</div> |
|||
} |
|||
style={{width:280,border:'1px solid #F9F9F9',}}> |
|||
</Checkbox> |
|||
</Col> |
|||
)):''} |
|||
</CheckboxGroup> |
|||
</Row> |
|||
</Form> |
|||
</> |
|||
); |
|||
} |
|||
function mapStateToProps(state) { |
|||
const { auth, global, members } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(nvrCamera); |
@ -0,0 +1,198 @@ |
|||
import React, { useState ,useRef} from 'react' |
|||
import { connect } from "react-redux"; |
|||
import { Modal,Form,Row,Col,Spin,Notification } from '@douyinfe/semi-ui'; |
|||
import { IconTickCircle } from '@douyinfe/semi-icons'; |
|||
function nvrModal(props){ |
|||
const {modalName}=props |
|||
const { dispatch, actions, user, loading,vender,close } = props; |
|||
const nvrData = props.nvrData||{}//修改时传来的值 |
|||
const form = useRef(); |
|||
const [visible, setVisible] = useState(false);//是否显示弹框 |
|||
const [isloading,setloading] = useState(false);//是否显示loading |
|||
const [loadingTip,setloadingTip] = useState('获取中...请稍后...');//loading tip的值 |
|||
const [step,setstep] = useState(0)//第几步 |
|||
const [okText,setokText] = useState('测试校验')//ok弹框text 右边 |
|||
const [cancelText,setcancelText] = useState('取消')//取消弹框text 左边 |
|||
const [formObj,setformObj] = useState()//接口入参 |
|||
const opts ={//添加完成确认后通知 |
|||
title:'Hi', |
|||
content:'添加成功', |
|||
duration:3 |
|||
} |
|||
function showDialog() {//打开弹框 |
|||
setVisible(true); |
|||
} |
|||
function positionForm(val){ |
|||
let zz = /^(-?\d+)(\.\d+)?$/ |
|||
if(!val){ |
|||
return '请输入或拾取高德经纬度坐标' |
|||
} |
|||
else if(val.split(',').length!=2){ |
|||
return '请输入格式为116.354169,39.835452的经纬度坐标' |
|||
} |
|||
else if(!zz.test(val.split(',')[0])){ |
|||
return '只能填写数字' |
|||
} |
|||
else if(!zz.test(val.split(',')[1])){ |
|||
return '只能填写数字' |
|||
} |
|||
else{ |
|||
return '' |
|||
} |
|||
} |
|||
function handleOk() {//点击弹框确定 右边按钮 |
|||
if(step==0){ |
|||
form.current.validate() |
|||
.then(values=>{//表单校验成功 |
|||
let valuesObj=JSON.parse(JSON.stringify(values)) |
|||
valuesObj.longitude=values.position.split(',')[0] |
|||
valuesObj.latitude=values.position.split(',')[1] |
|||
delete valuesObj.position |
|||
if(nvrData.id){ |
|||
valuesObj.id=nvrData.id |
|||
} |
|||
setformObj(valuesObj) |
|||
setloading(true); |
|||
setTimeout(() => { |
|||
setloadingTip('...接受成功') |
|||
setTimeout(()=>{ |
|||
setloadingTip('已完成') |
|||
setTimeout(() => { |
|||
setstep(1); |
|||
setokText('确认'); |
|||
setcancelText('上一步'); |
|||
setloading(false); |
|||
}, 2000); |
|||
}, 2000) |
|||
}, 2000); |
|||
}) |
|||
.catch(errors=>{//表单校验失败 |
|||
console.log('errors',errors); |
|||
}) |
|||
} |
|||
else{ |
|||
dispatch(actions.equipmentWarehouse.addchangeNvr(formObj)).then(res => { |
|||
Notification.success(opts) |
|||
setVisible(false); |
|||
close(); |
|||
}) |
|||
} |
|||
} |
|||
function handleAfterClose(){//在关闭之后 |
|||
setstep(0); |
|||
setokText('测试校验'); |
|||
setcancelText('取消'); |
|||
} |
|||
function handleCancel() {//点击弹框取消 左边按钮 |
|||
if(step==0){ |
|||
setVisible(false); |
|||
} |
|||
else{ |
|||
setstep(0); |
|||
setokText('测试校验'); |
|||
setcancelText('取消'); |
|||
} |
|||
} |
|||
function handleLocation(){//高德经纬度 |
|||
window.open('https://lbs.amap.com/tools/picker','_blank') |
|||
} |
|||
return ( |
|||
<> |
|||
<div onClick={showDialog}>{modalName=='add'?'添加NVR':'修改'}</div> |
|||
<Modal |
|||
title={modalName=='add'?'添加NVR':'修改NVR'} |
|||
okText={okText} |
|||
cancelText={cancelText} //取消按钮 |
|||
visible={visible} |
|||
onOk={handleOk} |
|||
width={607} |
|||
afterClose={handleAfterClose} |
|||
onCancel={handleCancel} |
|||
> |
|||
<Spin tip={loadingTip} spinning={isloading}> |
|||
{step==0?<div style={{paddingLeft:16}}> |
|||
<Form |
|||
allowEmpty |
|||
labelPosition='left' |
|||
labelAlign='left' |
|||
labelWidth= '90px' |
|||
onValueChange={values=>console.log(values)} |
|||
getFormApi={formApi => form.current = formApi}> |
|||
<Row> |
|||
<Col span={12}> |
|||
<Form.Input maxLength='39' field='serialNo' label='设备编号:' initValue={nvrData.serialNo||''} placeholder='请输入设备编号' style={{ width:149 }} |
|||
rules={[ |
|||
{ required: true, message: '请输入设备编号' } |
|||
]}/> |
|||
</Col> |
|||
<Col span={12}> |
|||
<Form.Input maxLength='15' field='regionCode' label='行政区区码:' initValue={nvrData.regionCode||''} placeholder='请输入行政区区码' style={{ width:149 }}/> |
|||
</Col> |
|||
<Col span={24}> |
|||
<Form.Input maxLength='36' field='name' label='设备名称:' initValue={nvrData.name||''} placeholder='请输入设备名称、常用项目或位置定义' style={{ width:421 }} |
|||
rules={[ |
|||
{ required: true, message: '请输入设备名称、常用项目或位置定义' } |
|||
]}/> |
|||
</Col> |
|||
<Col span={24}> |
|||
<Form.Select label="设备厂家:" field='venderId' initValue={nvrData.venderId||null} placeholder='请选择设备厂家' style={{ width: 421 }} |
|||
rules={[ |
|||
{ required: true, message: '请选择设备厂家' } |
|||
]}> |
|||
{vender.map((item,index)=>( |
|||
<Form.Select.Option key={index} value={item.id}>{item.name}</Form.Select.Option> |
|||
))} |
|||
</Form.Select> |
|||
</Col> |
|||
<Col span={24} style={{display:'flex'}}> |
|||
<Form.Input maxLength='39' field='position' label='安装位置:' initValue={nvrData.longitude&&nvrData.latitude?nvrData.longitude+','+nvrData.latitude:''} placeholder='请输入或拾取高德经纬度坐标' style={{ width:386 }} |
|||
validate={positionForm} |
|||
rules={[ |
|||
{ required: true, message: '请输入或拾取高德经纬度坐标' } |
|||
]}/> |
|||
<div style={{ |
|||
width:32, |
|||
height:32, |
|||
background:"#1859C1", |
|||
marginLeft:4, |
|||
display:'flex', |
|||
justifyContent: 'center', |
|||
alignItems: 'center', |
|||
cursor: "pointer", |
|||
marginTop:12, |
|||
borderRadius: 3+'px'}} |
|||
onClick={handleLocation}> |
|||
<img src="../../../assets/images/background/location.png" width={16} height={20}/> |
|||
</div> |
|||
</Col> |
|||
</Row> |
|||
</Form> |
|||
</div> |
|||
://下一步 |
|||
<div style={{height:224}}> |
|||
<div style={{paddingTop:50,display: 'flex', justifyContent: 'center'}}> |
|||
<IconTickCircle style={{color:'#04B234',fontSize:60}}/> |
|||
</div> |
|||
<div style={{marginTop:20,display: 'flex', justifyContent: 'center'}}> |
|||
已完成NVR设备测试和校验,是否确认添加? |
|||
</div> |
|||
</div> |
|||
} |
|||
</Spin> |
|||
</Modal> |
|||
</> |
|||
); |
|||
} |
|||
|
|||
function mapStateToProps(state) { |
|||
const { auth, global, members,vender } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
vender:vender.data||[],//设备厂家 |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(nvrModal); |
@ -0,0 +1,196 @@ |
|||
import React, { useState, useEffect } from "react"; |
|||
import { |
|||
Modal, |
|||
CheckboxGroup, |
|||
Checkbox, |
|||
TabPane, |
|||
Tabs, |
|||
} from "@douyinfe/semi-ui"; |
|||
|
|||
function Setup(props) { |
|||
const { |
|||
dispatch, |
|||
actions, |
|||
user, |
|||
loading, |
|||
visible, |
|||
close, |
|||
SETUPS, |
|||
CAMERAS, |
|||
cameraSetup, |
|||
} = props; |
|||
const [check, setCheck] = useState([]); |
|||
const checkboxcss = { width: "25%", height: 16, margin: "0 0 20px 0" }; |
|||
|
|||
useEffect(() => { |
|||
//获取是否勾选信息 |
|||
const nvrItem = localStorage.getItem(SETUPS); |
|||
const cameraItem = localStorage.getItem(CAMERAS); |
|||
if (cameraSetup) { |
|||
setCheck(cameraItem ? JSON.parse(cameraItem) : []); |
|||
} else { |
|||
setCheck(nvrItem ? JSON.parse(nvrItem) : []); |
|||
} |
|||
ischeck(); |
|||
}, []); |
|||
|
|||
const equipmentNVR = [ |
|||
{ name: "设备厂家", value: "a" }, |
|||
{ name: "添加账号", value: "b" }, |
|||
{ name: "通道数", value: "c" }, |
|||
{ name: "端口", value: "d" }, |
|||
{ name: "设备状态", value: "e" }, |
|||
{ name: "创建时间", value: "f" }, |
|||
]; |
|||
const projectNVR = [ |
|||
{ name: "项目名称", value: "g" }, |
|||
{ name: "things名称", value: "h" }, |
|||
{ name: "things数量", value: "i" }, |
|||
]; |
|||
const equipmentCamera = [ |
|||
{ name: "设备厂家", value: "manufactor" }, |
|||
{ name: "接入类型", value: "type" }, |
|||
{ name: "设备状态", value: "state" }, |
|||
{ name: "云台支持", value: "support" }, |
|||
{ name: "内存卡信息", value: "memoryCard" }, |
|||
{ name: "设备创建时间", value: "time" }, |
|||
{ name: "设备添加账号", value: "account" }, |
|||
]; |
|||
const projectCamera = [ |
|||
{ name: "项目名称", value: "name" }, |
|||
{ name: "pcode", value: "pcode" }, |
|||
{ name: "结构物", value: "structure" }, |
|||
{ name: "测点", value: "measuringPoint" }, |
|||
{ name: "监测因素", value: "factor" }, |
|||
]; |
|||
|
|||
function ischeck(value) { |
|||
if (check.length >= 8) { |
|||
if (check.includes(value)) { |
|||
return false; |
|||
} else { |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<Modal |
|||
title={ |
|||
<div> |
|||
表格属性设置 |
|||
<span |
|||
style={{ |
|||
width: 50, |
|||
lineHeight: "19px", |
|||
display: "inline-block", |
|||
|
|||
color: "white", |
|||
textAlign: "center", |
|||
marginLeft: 6, |
|||
background: |
|||
check.length == 8 |
|||
? "rgba(40, 123, 255, 1)" |
|||
: "rgba(176, 176, 176, 1)", |
|||
}} |
|||
> |
|||
{check.length}/8 |
|||
</span> |
|||
</div> |
|||
} |
|||
visible={visible} |
|||
style={{ width: 600 }} |
|||
onOk={() => { |
|||
cameraSetup |
|||
? localStorage.setItem(CAMERAS, JSON.stringify(check)) |
|||
: localStorage.setItem(SETUPS, JSON.stringify(check)); |
|||
close(); |
|||
}} |
|||
onCancel={() => { |
|||
close(); |
|||
}} |
|||
> |
|||
<CheckboxGroup |
|||
style={{ width: "100%", fontSize: 14 }} |
|||
key="primary1" |
|||
direction="horizontal" |
|||
defaultValue={check} |
|||
aria-label="表格属性设置" |
|||
onChange={(check) => { |
|||
setCheck(check); |
|||
ischeck(); |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
width: 550, |
|||
border: "1px solid #EAEAEA", |
|||
padding: "0px 5px", |
|||
borderRadius: 4, |
|||
marginBottom: "20px", |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
borderBottom: "1px solid #EAEAEA", |
|||
marginLeft: "10px", |
|||
padding: "8px 0px", |
|||
}} |
|||
> |
|||
设备信息 |
|||
</div> |
|||
<div style={{ padding: "15px 12px", width: 530 }}> |
|||
{(cameraSetup ? equipmentCamera : equipmentNVR).map((item) => { |
|||
return ( |
|||
<Checkbox |
|||
key={item.value} |
|||
value={item.value} |
|||
style={checkboxcss} |
|||
disabled={ischeck(item.value)} |
|||
> |
|||
{item.name} |
|||
</Checkbox> |
|||
); |
|||
})} |
|||
</div> |
|||
</div> |
|||
|
|||
<div |
|||
style={{ |
|||
width: 550, |
|||
border: "1px solid #EAEAEA", |
|||
padding: "0px 5px", |
|||
borderRadius: 4, |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
borderBottom: "1px solid #EAEAEA", |
|||
|
|||
marginLeft: "10px", |
|||
padding: "8px 0px", |
|||
}} |
|||
> |
|||
项目信息 |
|||
</div> |
|||
<div style={{ padding: "15px 12px", width: 530 }}> |
|||
{(cameraSetup ? projectCamera : projectNVR).map((item) => { |
|||
return ( |
|||
<Checkbox |
|||
key={item.value} |
|||
value={item.value} |
|||
style={checkboxcss} |
|||
disabled={ischeck(item.value)} |
|||
> |
|||
{item.name} |
|||
</Checkbox> |
|||
); |
|||
})} |
|||
</div> |
|||
</div> |
|||
</CheckboxGroup> |
|||
</Modal> |
|||
); |
|||
} |
|||
|
|||
export default Setup; |
@ -0,0 +1,468 @@ |
|||
import React, { useState, useEffect } from "react"; |
|||
import { SideSheet, Tabs, TabPane, Button } from "@douyinfe/semi-ui"; |
|||
import copy from "copy-to-clipboard"; |
|||
|
|||
function SideSheets(props) { |
|||
const { |
|||
dispatch, |
|||
actions, |
|||
user, |
|||
loading, |
|||
visible, |
|||
close, |
|||
SETUPS, |
|||
cameraSetup, |
|||
} = props; |
|||
const [clickStyle, setclickStyle] = useState(); |
|||
const list = [ |
|||
{ |
|||
name: "项目名称", |
|||
a: "南昌县智慧环保", |
|||
b: "南昌县智慧环保", |
|||
c: "南昌市市政隧道综合管理 哦哦哦哦哦 哦哦哦哦 哦哦哦哦 哦哦哦哦哦哦哦哦哦 哦", |
|||
d: "C", |
|||
}, |
|||
{ name: "关联结构物", a: "a", b: "B", c: "C", d: "C" }, |
|||
{ name: "关联测点", a: "a", b: "B", c: "C", d: "C" }, |
|||
{ name: "关联监测因素", a: "a", b: "B", c: "C", d: "C" }, |
|||
]; |
|||
const information = { |
|||
nvr: [ |
|||
{ |
|||
name: "基础信息", |
|||
basics: [ |
|||
{ name: "设备名称:", value: "消火栓呼呼呼呼" }, |
|||
{ name: "设备编号:", value: "D50F2049010B" }, |
|||
{ name: "接入方式:", value: "NJBJ858G68H" }, |
|||
{ name: "厂商:", value: "哇哇哇哇哇" }, |
|||
{ name: "添加账号:", value: "Superadmin" }, |
|||
{ name: "添加时间:", value: "2022-09-09" }, |
|||
{ |
|||
name: "行政区别:", |
|||
value: "江西省-南昌市-南昌县", |
|||
difference: "difference", |
|||
}, |
|||
{ |
|||
name: "设备安装位置:", |
|||
value: "江西省南昌县小蓝经开区江西飞尚科技有限公司", |
|||
difference: "line", |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
name: "接入信息", |
|||
access: [ |
|||
{ name: "SIP服务编号:", value: "1111111111" }, |
|||
{ name: "SIP域:", value: "KGU876J87" }, |
|||
{ name: "SIP端口号:", value: "KGU876J87" }, |
|||
{ name: "通道数量:", value: "16通道" }, |
|||
{ name: "心跳周期:", value: "3600s" }, |
|||
{ name: "最大心跳次数:", value: "3次" }, |
|||
{ name: "注册密码:", value: "**********" }, |
|||
{ name: "注册有效期::", value: "3600s" }, |
|||
{ name: "接入识别模块:", value: "sssss" }, |
|||
], |
|||
}, |
|||
{ |
|||
name: "摄像头信息", |
|||
CameraInformation: [ |
|||
{ |
|||
name: "通道1", |
|||
value1: "145641201564-1", |
|||
value2: "哦哦哦我我我喔噢喔喔我", |
|||
}, |
|||
{ |
|||
name: "通道2", |
|||
value1: "145641201564-2", |
|||
value2: "哦哦哦哦哦噢噢欧欧哦", |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
camera: [ |
|||
{ |
|||
name: "基础信息", |
|||
basics: [ |
|||
{ name: "设备名称:", value: "消火栓呼呼呼呼" }, |
|||
{ name: "SIP编号/设备编号:", value: "D50F2049010B" }, |
|||
{ name: "接入方式:", value: "NJBJ858G68H" }, |
|||
{ name: "厂商:", value: "哇哇哇哇哇" }, |
|||
{ name: "添加账号:", value: "Superadmin" }, |
|||
{ name: "添加时间:", value: "2022-09-09" }, |
|||
{ |
|||
name: "设备安装位置:", |
|||
value: "江西省南昌县小蓝经开区江西飞尚科技有限公司", |
|||
difference: "line", |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
name: "复制直播地址", |
|||
liveBroadcast: [ |
|||
{ name: "HLS地址", value: "" }, |
|||
{ name: "FLV地址", value: "" }, |
|||
{ name: "RTMP地址", value: "" }, |
|||
{ name: "EZOPEN地址", value: "" }, |
|||
{ name: "ONVIF地址", value: "" }, |
|||
], |
|||
}, |
|||
{ |
|||
name: "复制回收地址", |
|||
recovery: [ |
|||
{ name: "云储存地址", value: "" }, |
|||
{ name: "本地储存地址", value: "" }, |
|||
], |
|||
}, |
|||
], |
|||
}; |
|||
const styles = { |
|||
width: 180, |
|||
height: 64, |
|||
textAlign: "center", |
|||
background: "url(/assets/images/background/backGround.png)", |
|||
backgroundSize: "100% 100%", |
|||
padding: "12px 17px 12px 17px", |
|||
margin: "30px 0 0 10px", |
|||
lineHeight: "24px", |
|||
overflow: "hidden", |
|||
textOverflow: "ellipsis", |
|||
display: "-webkit-box", |
|||
WebkitLineClamp: "2", |
|||
WebkitBoxOrient: "vertical", |
|||
zIndex: 5, |
|||
}; |
|||
|
|||
useEffect(() => {}, []); |
|||
|
|||
return ( |
|||
<SideSheet |
|||
visible={visible} |
|||
title={cameraSetup ? "污水管理出出口" : "智慧设备NVR"} |
|||
style={{ background: "#F9FBFF" }} |
|||
size="large" |
|||
onCancel={() => { |
|||
close(); |
|||
}} |
|||
> |
|||
<Tabs type="line"> |
|||
<TabPane tab="项目信息" itemKey="1"> |
|||
<div style={{ display: "flex", justifyContent: "space-evenly" }}> |
|||
{list.map((item, index) => { |
|||
return ( |
|||
<div |
|||
key={item.name} |
|||
style={{ |
|||
width: 200, |
|||
margin: "12px 8px", |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
lineHeight: "32px", |
|||
background: "#1859C1", |
|||
color: "#FFFFFF", |
|||
borderRadius: 3, |
|||
textAlign: "center", |
|||
}} |
|||
> |
|||
<img |
|||
src={`/assets/images/background/projectIcon${index}.png`} |
|||
style={{ marginRight: 10 }} |
|||
/> |
|||
{item.name} |
|||
</div> |
|||
<div style={styles}>{item.a}</div> |
|||
<div style={styles}>{item.b}</div> |
|||
<div style={styles}>{item.c}</div> |
|||
<div style={styles}>{item.d}</div> |
|||
</div> |
|||
); |
|||
})} |
|||
</div> |
|||
</TabPane> |
|||
<TabPane tab="设备信息" itemKey="2"> |
|||
{(cameraSetup ? information.camera : information.nvr).map( |
|||
(item, index) => { |
|||
let str = []; |
|||
if (index > 0) { |
|||
str.push( |
|||
<img |
|||
src="/assets/images/background/straightline.png" |
|||
key={"img" + index} |
|||
alt="无法显示" |
|||
style={{ width: 872, display: "block", marginTop: 24 }} |
|||
/> |
|||
); |
|||
} |
|||
str.push( |
|||
<div |
|||
key={"name" + index} |
|||
style={{ |
|||
fontWeight: "600", |
|||
color: "#1859C1", |
|||
margin: "15px 0 12px 40px", |
|||
}} |
|||
> |
|||
{item.name} |
|||
{cameraSetup ? ( |
|||
index == 1 ? ( |
|||
<div |
|||
style={{ |
|||
display: "inline-block", |
|||
float: "right", |
|||
marginRight: 20, |
|||
}} |
|||
> |
|||
<Button style={{ marginRight: 20 }} theme="solid"> |
|||
高清 |
|||
</Button> |
|||
<Button>标清</Button> |
|||
</div> |
|||
) : ( |
|||
"" |
|||
) |
|||
) : ( |
|||
"" |
|||
)} |
|||
</div> |
|||
); |
|||
//基础信息 |
|||
if (index == 0) { |
|||
item.basics.map((item, index) => { |
|||
if (item.difference == "line") { |
|||
str.push( |
|||
<div key={"basics" + index} style={{ marginTop: 14 }}> |
|||
<span |
|||
style={{ |
|||
width: 150, |
|||
display: "inline-block", |
|||
textAlign: "right", |
|||
fontWeight: "600", |
|||
color: "rgba(0, 0, 0, 0.45)", |
|||
}} |
|||
> |
|||
{item.name} |
|||
</span> |
|||
<span style={{ fontWeight: "600", color: " #34383E" }}> |
|||
{item.value} |
|||
</span> |
|||
</div> |
|||
); |
|||
} else { |
|||
str.push( |
|||
<div |
|||
key={"basics" + index} |
|||
style={{ |
|||
width: "50%", |
|||
display: "inline-block", |
|||
marginTop: 20, |
|||
}} |
|||
> |
|||
<span |
|||
style={{ |
|||
width: 150, |
|||
display: "inline-block", |
|||
textAlign: "right", |
|||
fontWeight: "600", |
|||
color: "rgba(0, 0, 0, 0.45)", |
|||
}} |
|||
> |
|||
{item.name} |
|||
</span> |
|||
<span style={{ fontWeight: "600", color: " #34383E" }}> |
|||
{item.value} |
|||
</span> |
|||
</div> |
|||
); |
|||
} |
|||
return str; |
|||
}); |
|||
} |
|||
//接入信息/复制直播地址 |
|||
if (index == 1) { |
|||
(cameraSetup ? item.liveBroadcast : item.access).map( |
|||
(item, index) => { |
|||
if (cameraSetup) { |
|||
str.push( |
|||
<div |
|||
key={"liveBroadcast" + index} |
|||
style={{ |
|||
width: 120, |
|||
height: 130, |
|||
display: "inline-block", |
|||
borderRadius: 4, |
|||
border: "1px solid #D9D9D9", |
|||
margin: "20px 0 0 40px", |
|||
textAlign: "center", |
|||
color: clickStyle == item.name ? "white" : "", |
|||
background: |
|||
clickStyle == item.name ? "#1859C1" : "", |
|||
}} |
|||
onClick={() => { |
|||
copy(item.name); |
|||
// alert("复制成功"); |
|||
setclickStyle(item.name); |
|||
}} |
|||
> |
|||
<img |
|||
src={`/assets/images/background/${ |
|||
clickStyle == item.name |
|||
? "sewage_camera2" |
|||
: "sewage_camera1" |
|||
}.png`} |
|||
style={{ margin: "20px 0 8px 0" }} |
|||
/> |
|||
<div> |
|||
{item.name} |
|||
<img |
|||
src={`/assets/images/background/${ |
|||
clickStyle == item.name ? "copy2" : "copy1" |
|||
}.png`} |
|||
style={{ |
|||
paddingBottom: 10, |
|||
display: "inline-block", |
|||
width: 10, |
|||
height: 20, |
|||
}} |
|||
/> |
|||
</div> |
|||
</div> |
|||
); |
|||
} else { |
|||
str.push( |
|||
<div |
|||
key={"access" + index} |
|||
style={{ |
|||
width: "50%", |
|||
display: "inline-block", |
|||
marginTop: 20, |
|||
}} |
|||
> |
|||
<span |
|||
style={{ |
|||
width: 150, |
|||
display: "inline-block", |
|||
textAlign: "right", |
|||
fontWeight: "600", |
|||
color: "rgba(0, 0, 0, 0.45)", |
|||
}} |
|||
> |
|||
{item.name} |
|||
</span> |
|||
<span |
|||
style={{ fontWeight: "600", color: " #34383E" }} |
|||
> |
|||
{item.value} |
|||
</span> |
|||
</div> |
|||
); |
|||
} |
|||
return str; |
|||
} |
|||
); |
|||
} |
|||
//摄像头信息/复制回收地址 |
|||
if (index == 2) { |
|||
(cameraSetup ? item.recovery : item.CameraInformation).map( |
|||
(item, index) => { |
|||
if (cameraSetup) { |
|||
str.push( |
|||
<div |
|||
key={"liveBroadcast" + index} |
|||
style={{ |
|||
width: 120, |
|||
height: 130, |
|||
display: "inline-block", |
|||
borderRadius: 4, |
|||
border: "1px solid #D9D9D9", |
|||
margin: "20px 0 0 40px", |
|||
textAlign: "center", |
|||
color: clickStyle == item.name ? "white" : "", |
|||
background: |
|||
clickStyle == item.name ? "#1859C1" : "", |
|||
}} |
|||
onClick={() => { |
|||
copy(item.name); |
|||
// alert("复制成功"); |
|||
setclickStyle(item.name); |
|||
}} |
|||
> |
|||
<img |
|||
src={`/assets/images/background/${ |
|||
clickStyle == item.name ? "store2" : "store1" |
|||
}.png`} |
|||
style={{ margin: "20px 0 8px 0" }} |
|||
/> |
|||
<div> |
|||
{item.name} |
|||
<img |
|||
src={`/assets/images/background/${ |
|||
clickStyle == item.name ? "copy2" : "copy1" |
|||
}.png`} |
|||
style={{ |
|||
paddingBottom: 10, |
|||
display: "inline-block", |
|||
width: 10, |
|||
height: 20, |
|||
}} |
|||
/> |
|||
</div> |
|||
</div> |
|||
); |
|||
} else { |
|||
str.push( |
|||
<div |
|||
key={"access" + index} |
|||
style={{ |
|||
width: "40%", |
|||
display: "inline-block", |
|||
borderRadius: 4, |
|||
border: "1px solid rgba(151, 151, 151, 0.2)", |
|||
margin: "16px 0 0 36px", |
|||
color: "rgba(0, 0, 0, 0.85)", |
|||
fontWeight: "600", |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
padding: "8px 10px", |
|||
borderBottom: |
|||
"1px solid rgba(151, 151, 151, 0.2)", |
|||
}} |
|||
> |
|||
<img |
|||
src={`/assets/images/background/camera.png`} |
|||
style={{ marginRight: 10 }} |
|||
/> |
|||
<div |
|||
style={{ |
|||
display: "inline-block", |
|||
}} |
|||
> |
|||
{item.name} |
|||
</div> |
|||
</div> |
|||
<p style={{ margin: "16px 0 0 30px " }}> |
|||
{item.value1} |
|||
</p> |
|||
<p style={{ margin: "16px 0 20px 30px " }}> |
|||
{item.value2} |
|||
</p> |
|||
</div> |
|||
); |
|||
} |
|||
return str; |
|||
} |
|||
); |
|||
} |
|||
|
|||
return str; |
|||
} |
|||
)} |
|||
</TabPane> |
|||
</Tabs> |
|||
</SideSheet> |
|||
); |
|||
} |
|||
|
|||
export default SideSheets; |
@ -0,0 +1,542 @@ |
|||
import React, { useState, useEffect, useRef } from "react"; |
|||
import { connect } from "react-redux"; |
|||
import { Button, Form, Input, Row, Table, Pagination } from "@douyinfe/semi-ui"; |
|||
import "../style.less"; |
|||
import CameraModal from "../components/cameraModal"; |
|||
import NvrModal from "../components/nvrModal"; |
|||
import Setup from "../components/setup"; |
|||
import SideSheets from "../components/sideSheet"; |
|||
|
|||
const CameraHeader = (props) => { |
|||
const { dispatch, actions, user, loading, equipmentWarehouseNvr } = props; |
|||
const [cameraModal, setCameraModal] = useState(false); |
|||
const [modalName, setModalName] = useState(""); |
|||
const [setup, setSetup] = useState(false); |
|||
const [sideSheet, setSideSheet] = useState(false); |
|||
const [cameraSetup, setcameraSetup] = useState(false); |
|||
const [setupp, setSetupp] = useState([]); |
|||
const [venderList, setvenderList] = useState([]); //厂商信息 |
|||
const [query, setQuery] = useState({ limit: 10, page: 0 }); |
|||
const { equipmentWarehouse } = actions; |
|||
const api = useRef(); |
|||
const CAMERAS = "cameras"; |
|||
|
|||
useEffect(() => { |
|||
dispatch(actions.equipmentWarehouse.getVender()).then((res) => { |
|||
setvenderList(res.payload.data); |
|||
}); |
|||
//初始化表格显示设置 |
|||
localStorage.getItem(CAMERAS) == null |
|||
? localStorage.setItem( |
|||
CAMERAS, |
|||
JSON.stringify(["state", "type", "manufactor"]) |
|||
) |
|||
: ""; |
|||
attribute(); |
|||
}, []); |
|||
|
|||
useEffect(() => { |
|||
equipmentGetNvr(); |
|||
}, [query]); |
|||
|
|||
function equipmentGetNvr() { |
|||
dispatch(equipmentWarehouse.getNvr(query)); |
|||
} |
|||
const columns = [ |
|||
{ |
|||
title: "序号", |
|||
render: (text, record, index) => { |
|||
return index + 1; |
|||
}, |
|||
}, |
|||
{ |
|||
title: "设备名称", |
|||
dataIndex: "name", |
|||
render: (text, record, index) => { |
|||
return ( |
|||
<div> |
|||
<span |
|||
style={{ |
|||
backgroundColor: record.avatarBg, |
|||
width: "10px", |
|||
height: "10px", |
|||
borderRadius: "50%", |
|||
display: "inline-block", |
|||
marginRight: "10px", |
|||
}} |
|||
/> |
|||
{record.name} |
|||
</div> |
|||
); |
|||
}, |
|||
}, |
|||
|
|||
{ |
|||
title: "操作", |
|||
width: "20%", |
|||
dataIndex: "", |
|||
render: (_, row) => { |
|||
// console.log(row); |
|||
return ( |
|||
<div style={{ display: "flex" }}> |
|||
<Button theme="borderless"> |
|||
<NvrModal |
|||
nvrData={row} |
|||
modalName="revise" |
|||
venderList={venderList} |
|||
close={() => { |
|||
equipmentGetNvr(); |
|||
}} |
|||
/> |
|||
</Button> |
|||
<Button |
|||
theme="borderless" |
|||
onClick={() => { |
|||
setSideSheet(true); |
|||
setcameraSetup(true); |
|||
}} |
|||
> |
|||
查看 |
|||
</Button> |
|||
<Button theme="borderless">播放</Button> |
|||
<Button theme="borderless">禁用</Button> |
|||
<Button |
|||
theme="borderless" |
|||
onClick={() => { |
|||
dispatch(equipmentWarehouse.delNvr(row.id)); |
|||
equipmentGetNvr(); |
|||
}} |
|||
> |
|||
删除 |
|||
</Button> |
|||
</div> |
|||
); |
|||
}, |
|||
}, |
|||
]; |
|||
|
|||
//获取表格属性设置 |
|||
function attribute() { |
|||
const arr = localStorage.getItem(CAMERAS) |
|||
? JSON.parse(localStorage.getItem(CAMERAS)) |
|||
: []; |
|||
|
|||
const column = [ |
|||
{ |
|||
title: "设备厂家", |
|||
dataIndex: "venderId", |
|||
key: "manufactor", |
|||
}, |
|||
{ |
|||
title: "接入类型", |
|||
dataIndex: "createUserId", |
|||
key: "type", |
|||
}, |
|||
{ |
|||
title: "设备状态", |
|||
dataIndex: "channelCount", |
|||
key: "state", |
|||
}, |
|||
{ |
|||
title: "云台支持", |
|||
dataIndex: "port", |
|||
key: "support", |
|||
}, |
|||
{ |
|||
title: "内存卡信息", |
|||
dataIndex: "size", |
|||
key: "memoryCard", |
|||
}, |
|||
{ |
|||
title: "设备创建时间", |
|||
dataIndex: "createTime", |
|||
key: "time", |
|||
}, |
|||
{ |
|||
title: "设备添加账号", |
|||
dataIndex: "size", |
|||
key: "account", |
|||
}, |
|||
{ |
|||
title: "项目名称", |
|||
dataIndex: "updateTime", |
|||
key: "name", |
|||
}, |
|||
{ |
|||
title: "pcode", |
|||
dataIndex: "updateTime", |
|||
key: "pcode", |
|||
}, |
|||
{ |
|||
title: "结构物", |
|||
dataIndex: "updateTime", |
|||
key: "structure", |
|||
}, |
|||
{ |
|||
title: "测点", |
|||
dataIndex: "updateTime", |
|||
key: "measuringPoint", |
|||
}, |
|||
{ |
|||
title: "监测因素", |
|||
dataIndex: "updateTime", |
|||
key: "factor", |
|||
}, |
|||
]; |
|||
for (let i = 0; i < arr.length; i++) { |
|||
let colum = column.filter((item) => { |
|||
return item.key === arr[i]; |
|||
}); |
|||
columns.splice(i + 2, 0, colum[0]); |
|||
} |
|||
setSetupp(columns); |
|||
} |
|||
|
|||
//条件赛选样式 |
|||
const screen = { |
|||
width: 193, |
|||
marginRight: 20, |
|||
marginBottom: 16, |
|||
color: "rgba(0, 0, 0, 0.65)", |
|||
}; |
|||
|
|||
return ( |
|||
<> |
|||
<div style={{ position: "" }}> |
|||
<video |
|||
id="cameraBanner" |
|||
autoPlay |
|||
loop |
|||
muted |
|||
style={{ width: "100%", objectFit: "cover", height: 171 }} |
|||
src="/assets/video/camera_banner.mp4" |
|||
type="video/mp4" |
|||
/> |
|||
<div style={{ position: "absolute", top: 12 }}> |
|||
<div |
|||
style={{ |
|||
fontSize: 22, |
|||
paddingTop: 15, |
|||
marginLeft: 21, |
|||
}} |
|||
> |
|||
摄像头管理 |
|||
</div> |
|||
<div |
|||
style={{ |
|||
fontSize: 14, |
|||
paddingTop: 18, |
|||
marginLeft: 20, |
|||
}} |
|||
> |
|||
对监控摄像设备设备添加、修改、删除的硬件管理页面。 |
|||
</div> |
|||
<div |
|||
style={{ |
|||
fontSize: 14, |
|||
marginTop: 28, |
|||
marginLeft: 21, |
|||
width: 89, |
|||
height: 32, |
|||
lineHeight: 32 + "px", |
|||
textAlign: "center", |
|||
backgroundColor: "#D9EAFF", |
|||
color: "#1859C1", |
|||
cursor: "pointer", |
|||
}} |
|||
onClick={() => { |
|||
setModalName("add"); |
|||
setCameraModal(true); |
|||
}} |
|||
> |
|||
添加摄像头 |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div |
|||
style={{ |
|||
width: "100%", |
|||
background: "#FFFFFF", |
|||
borderRadius: 3, |
|||
padding: "8px 20px", |
|||
marginTop: 20, |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
height: 22, |
|||
fontSize: 16, |
|||
fontFamily: "PingFangSC-Medium, PingFang SC", |
|||
fontWeight: "bold", |
|||
color: " rgba(0, 0, 0, 0.85)", |
|||
lineHeight: "22px", |
|||
marginBottom: 16, |
|||
}} |
|||
> |
|||
筛选条件 |
|||
</div> |
|||
<div style={{ display: "flex" }}> |
|||
<Form |
|||
onSubmit={(values) => console.log(values)} |
|||
// onValueChange={values=>console.log(values)} |
|||
getFormApi={(formApi) => (api.current = formApi)} |
|||
layout="horizontal" |
|||
style={{ position: "relative", width: "100%", flex: 1 }} |
|||
> |
|||
<Form.Input |
|||
label="设备搜索:" |
|||
field="name" |
|||
placeholder="请输入设备名称" |
|||
labelPosition="left" |
|||
style={screen} |
|||
/> |
|||
<Form.Select |
|||
label="接入类型:" |
|||
labelPosition="left" |
|||
field="type1" |
|||
style={screen} |
|||
placeholder="全部" |
|||
> |
|||
<Form.Select.Option value="12">111</Form.Select.Option> |
|||
<Form.Select.Option value="11">111111</Form.Select.Option> |
|||
</Form.Select> |
|||
<Form.Select |
|||
label="厂家筛选:" |
|||
labelPosition="left" |
|||
style={screen} |
|||
field="venderId" |
|||
placeholder="全部" |
|||
> |
|||
{venderList.map((item) => { |
|||
return ( |
|||
<Form.Select.Option key={item.id} value={item.id}> |
|||
{item.name} |
|||
</Form.Select.Option> |
|||
); |
|||
})} |
|||
</Form.Select> |
|||
<Form.Select |
|||
label="状态查询:" |
|||
labelPosition="left" |
|||
field="type2" |
|||
style={screen} |
|||
placeholder="全部" |
|||
> |
|||
<Form.Select.Option value="yes">在线</Form.Select.Option> |
|||
<Form.Select.Option value="no">离线</Form.Select.Option> |
|||
</Form.Select> |
|||
{/* <Form.Select |
|||
label="关联项目:" |
|||
labelPosition="left" |
|||
field="type3" |
|||
style={screen} |
|||
placeholder="全部" |
|||
> |
|||
<Form.Select.Option value="智慧环保"> |
|||
飞尚科技1 |
|||
</Form.Select.Option> |
|||
<Form.Select.Option value="智慧水务"> |
|||
飞尚科技2 |
|||
</Form.Select.Option> |
|||
</Form.Select> */} |
|||
</Form> |
|||
<div |
|||
style={{ |
|||
width: 150, |
|||
display: "flex", |
|||
justifyContent: "flex-end", |
|||
alignItems: "flex-end", |
|||
}} |
|||
> |
|||
<Button |
|||
theme="solid" |
|||
type="primary" |
|||
style={{ |
|||
width: 65, |
|||
height: 30, |
|||
borderRadius: 3, |
|||
marginBottom: 20, |
|||
marginRight: 20, |
|||
}} |
|||
onClick={() => { |
|||
api.current.validate().then((values) => { |
|||
console.log(values); |
|||
console.log( |
|||
equipmentWarehouseNvr.data.filter((item) => { |
|||
return ( |
|||
item.name.indexOf(values.name) > -1 && |
|||
item.venderId === values.venderId |
|||
); |
|||
// return item.venderId === values.venderId; |
|||
}) |
|||
); |
|||
}); |
|||
console.log(equipmentWarehouseNvr.data); |
|||
}} |
|||
> |
|||
搜素 |
|||
</Button> |
|||
<Button |
|||
theme="light" |
|||
type="primary" |
|||
style={{ |
|||
width: 65, |
|||
height: 30, |
|||
backGround: "#FFFFFF", |
|||
borderRadius: 3, |
|||
border: "1px solid #D9D9D9", |
|||
marginBottom: 20, |
|||
}} |
|||
> |
|||
重置 |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div style={{ background: "#FFFFFF", marginTop: 5 }}> |
|||
<div |
|||
style={{ |
|||
width: "100%", |
|||
display: "flex", |
|||
justifyContent: "space-between", |
|||
padding: "13px 20px", |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
width: 64, |
|||
height: 22, |
|||
fontSize: 16, |
|||
fontfAmily: "PingFangSC-Medium, PingFang SC", |
|||
fontWeight: "bold", |
|||
color: "rgba(0, 0, 0, 0.85)", |
|||
lineHeight: "22px", |
|||
}} |
|||
> |
|||
设备列表 |
|||
</div> |
|||
<div> |
|||
<Button |
|||
style={{ |
|||
width: 32, |
|||
height: 32, |
|||
background: "#D9D9D9", |
|||
borderadius: 3, |
|||
marginRight: 20, |
|||
}} |
|||
type="primary" |
|||
key="primary" |
|||
onClick={() => { |
|||
setSetup(true); |
|||
setcameraSetup(true); |
|||
}} |
|||
> |
|||
<img |
|||
src="/assets/images/background/setup.png" |
|||
alt="设置" |
|||
style={{ width: 18, height: 18 }} |
|||
/> |
|||
</Button> |
|||
<Button |
|||
style={{ |
|||
width: 65, |
|||
height: 32, |
|||
background: "#FFFFFF", |
|||
borderRadius: 3, |
|||
border: "1px solid #1859C1", |
|||
}} |
|||
> |
|||
导出 |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
<Table |
|||
columns={setupp} |
|||
dataSource={equipmentWarehouseNvr.data} |
|||
bordered={false} |
|||
empty="暂无数据" |
|||
style={{ |
|||
padding: "0px 20px", |
|||
}} |
|||
pagination={false} |
|||
/> |
|||
<div |
|||
style={{ |
|||
display: "flex", |
|||
justifyContent: "flex-end", |
|||
padding: "20px 20px", |
|||
}} |
|||
> |
|||
<span style={{ lineHeight: "30px" }}> |
|||
共{equipmentWarehouseNvr.total}个设备 |
|||
</span> |
|||
<Pagination |
|||
className="22" |
|||
total={equipmentWarehouseNvr.total} |
|||
showSizeChanger |
|||
currentPage={query.page + 1} |
|||
pageSizeOpts={[10, 20, 30, 40]} |
|||
onChange={(currentPage, pageSize) => { |
|||
setQuery({ limit: pageSize, page: currentPage - 1 }); |
|||
}} |
|||
/> |
|||
</div> |
|||
|
|||
{setup ? ( |
|||
<Setup |
|||
visible={true} |
|||
CAMERAS={CAMERAS} |
|||
cameraSetup={cameraSetup} |
|||
close={() => { |
|||
setSetup(false); |
|||
attribute(); |
|||
setcameraSetup(false); |
|||
}} |
|||
/> |
|||
) : ( |
|||
"" |
|||
)} |
|||
|
|||
{sideSheet ? ( |
|||
<SideSheets |
|||
visible={true} |
|||
cameraSetup={cameraSetup} |
|||
close={() => { |
|||
setSideSheet(false); |
|||
setcameraSetup(false); |
|||
}} |
|||
/> |
|||
) : ( |
|||
[] |
|||
)} |
|||
</div> |
|||
|
|||
{cameraModal ? ( |
|||
<CameraModal |
|||
visible={true} |
|||
close={() => { |
|||
setCameraModal(false); |
|||
// setEditData(null) |
|||
}} |
|||
modalName={modalName} |
|||
/> |
|||
) : ( |
|||
"" |
|||
)} |
|||
</> |
|||
); |
|||
}; |
|||
|
|||
function mapStateToProps(state) { |
|||
const { auth, global, members, equipmentWarehouseNvr } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
equipmentWarehouseNvr: equipmentWarehouseNvr.data || [], |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(CameraHeader); |
@ -0,0 +1,5 @@ |
|||
'use strict'; |
|||
|
|||
import Nvr from './nvr'; |
|||
import Camera from './camera'; |
|||
export { Nvr,Camera }; |
@ -0,0 +1,495 @@ |
|||
import React, { useState, useEffect, useRef } from "react"; |
|||
import { connect } from "react-redux"; |
|||
import moment from "moment"; |
|||
import { Button, Form, Input, Row, Table, Pagination } from "@douyinfe/semi-ui"; |
|||
import "../style.less"; |
|||
import NvrModal from "../components/nvrModal"; |
|||
import Setup from "../components/setup"; |
|||
import SideSheets from "../components/sideSheet"; |
|||
|
|||
const NvrHeader = (props) => { |
|||
const { dispatch, actions, user, loading, equipmentWarehouseNvr } = props; |
|||
const { equipmentWarehouse } = actions; |
|||
const [setup, setSetup] = useState(false); |
|||
const [sideSheet, setSideSheet] = useState(false); |
|||
const [setupp, setSetupp] = useState([]); |
|||
const [venderList, setvenderList] = useState([]); //厂商信息 |
|||
const [query, setQuery] = useState({ limit: 10, page: 0 }); |
|||
const api = useRef(); |
|||
const SETUPS = "setups"; |
|||
|
|||
useEffect(() => { |
|||
dispatch(actions.equipmentWarehouse.getVender()).then((res) => { |
|||
setvenderList(res.payload.data); |
|||
}); |
|||
//初始化表格显示设置 |
|||
localStorage.getItem(SETUPS) == null |
|||
? localStorage.setItem(SETUPS, JSON.stringify(["a", "c", "d", "e"])) |
|||
: ""; |
|||
// ; |
|||
attribute(); |
|||
}, []); |
|||
useEffect(() => { |
|||
equipmentGetNvr(); |
|||
}, [query]); |
|||
|
|||
function equipmentGetNvr() { |
|||
dispatch(equipmentWarehouse.getNvr(query)); |
|||
} |
|||
const columns = [ |
|||
{ |
|||
title: "序号", |
|||
render: (text, record, index) => { |
|||
return index + 1; |
|||
}, |
|||
}, |
|||
{ |
|||
title: "设备名称", |
|||
dataIndex: "name", |
|||
render: (text, record, index) => { |
|||
return ( |
|||
<div> |
|||
<span |
|||
style={{ |
|||
backgroundColor: record.avatarBg, |
|||
width: "10px", |
|||
height: "10px", |
|||
borderRadius: "50%", |
|||
display: "inline-block", |
|||
marginRight: "10px", |
|||
}} |
|||
/> |
|||
{record.name} |
|||
</div> |
|||
); |
|||
}, |
|||
}, |
|||
{ |
|||
title: "SIP地址", |
|||
dataIndex: "owner", |
|||
}, |
|||
{ |
|||
title: "操作", |
|||
width: "20%", |
|||
dataIndex: "", |
|||
render: (_, row) => { |
|||
// console.log(row); |
|||
return ( |
|||
<div style={{ display: "flex" }}> |
|||
<Button theme="borderless"> |
|||
<NvrModal |
|||
nvrData={row} |
|||
modalName="revise" |
|||
venderList={venderList} |
|||
close={() => { |
|||
equipmentGetNvr(); |
|||
}} |
|||
/> |
|||
</Button> |
|||
<Button |
|||
theme="borderless" |
|||
onClick={() => { |
|||
setSideSheet(true); |
|||
}} |
|||
> |
|||
查看 |
|||
</Button> |
|||
<Button |
|||
theme="borderless" |
|||
onClick={() => { |
|||
dispatch(equipmentWarehouse.delNvr(row.id)); |
|||
equipmentGetNvr(); |
|||
}} |
|||
> |
|||
删除 |
|||
</Button> |
|||
</div> |
|||
); |
|||
}, |
|||
}, |
|||
]; |
|||
|
|||
//获取表格属性设置 |
|||
function attribute() { |
|||
const arr = localStorage.getItem(SETUPS) |
|||
? JSON.parse(localStorage.getItem(SETUPS)) |
|||
: []; |
|||
|
|||
const column = [ |
|||
{ |
|||
title: "设备厂家", |
|||
dataIndex: "venderId", |
|||
key: "a", |
|||
}, |
|||
{ |
|||
title: "添加账号", |
|||
dataIndex: "createUserId", |
|||
key: "b", |
|||
}, |
|||
{ |
|||
title: "通道数", |
|||
dataIndex: "channelCount", |
|||
key: "c", |
|||
}, |
|||
{ |
|||
title: "端口", |
|||
dataIndex: "port", |
|||
key: "d", |
|||
}, |
|||
{ |
|||
title: "设备状态", |
|||
dataIndex: "size", |
|||
key: "e", |
|||
}, |
|||
{ |
|||
title: "创建时间", |
|||
dataIndex: "createTime", |
|||
key: "f", |
|||
render: (text, r, index) => { |
|||
return moment(r.createTime).format("YYYY-MM-DD HH:MM:SS"); |
|||
}, |
|||
}, |
|||
{ |
|||
title: "项目名称", |
|||
dataIndex: "size", |
|||
key: "g", |
|||
}, |
|||
{ |
|||
title: "things名称", |
|||
dataIndex: "updateTime", |
|||
key: "h", |
|||
}, |
|||
{ |
|||
title: "things数量", |
|||
dataIndex: "updateTime", |
|||
key: "i", |
|||
}, |
|||
]; |
|||
for (let i = 0; i < arr.length; i++) { |
|||
let colum = column.filter((item) => { |
|||
return item.key === arr[i]; |
|||
}); |
|||
columns.splice(i + 2, 0, colum[0]); |
|||
} |
|||
setSetupp(columns); |
|||
} |
|||
|
|||
//条件赛选样式 |
|||
const screen = { |
|||
width: 193, |
|||
marginRight: 20, |
|||
marginBottom: 16, |
|||
color: "rgba(0, 0, 0, 0.65)", |
|||
}; |
|||
|
|||
return ( |
|||
<> |
|||
<div style={{ position: "" }}> |
|||
<video |
|||
id="nvrBanner" |
|||
autoPlay |
|||
loop |
|||
muted |
|||
style={{ width: "100%", objectFit: "cover", height: 171 }} |
|||
src="/assets/video/nvr_banner.mp4" |
|||
type="video/mp4" |
|||
/> |
|||
<div style={{ position: "absolute", top: 12 }}> |
|||
<div |
|||
style={{ |
|||
fontSize: 22, |
|||
paddingTop: 15, |
|||
marginLeft: 21, |
|||
}} |
|||
> |
|||
NVR管理 |
|||
</div> |
|||
<div |
|||
style={{ |
|||
fontSize: 14, |
|||
paddingTop: 18, |
|||
marginLeft: 20, |
|||
}} |
|||
> |
|||
对NVR(网络硬盘录像机)设备节点的管理 |
|||
</div> |
|||
<div |
|||
style={{ |
|||
fontSize: 14, |
|||
marginTop: 28, |
|||
marginLeft: 21, |
|||
width: 89, |
|||
height: 32, |
|||
lineHeight: "32px", |
|||
textAlign: "center", |
|||
backgroundColor: "#D9EAFF", |
|||
color: "#1859C1", |
|||
cursor: "pointer", |
|||
}} |
|||
> |
|||
<NvrModal |
|||
modalName="add" |
|||
venderList={venderList} |
|||
close={() => { |
|||
equipmentGetNvr(); |
|||
}} |
|||
/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div |
|||
style={{ |
|||
width: "100%", |
|||
background: "#FFFFFF", |
|||
borderRadius: 3, |
|||
padding: "8px 20px", |
|||
marginTop: 20, |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
height: 22, |
|||
fontSize: 16, |
|||
fontFamily: "PingFangSC-Medium, PingFang SC", |
|||
fontWeight: "bold", |
|||
color: " rgba(0, 0, 0, 0.85)", |
|||
lineHeight: "22px", |
|||
marginBottom: 16, |
|||
}} |
|||
> |
|||
筛选条件 |
|||
</div> |
|||
<div style={{ display: "flex" }}> |
|||
<Form |
|||
onSubmit={(values) => console.log(values)} |
|||
// onValueChange={values=>console.log(values)} |
|||
getFormApi={(formApi) => (api.current = formApi)} |
|||
layout="horizontal" |
|||
style={{ position: "relative", width: "100%", flex: 1 }} |
|||
> |
|||
<Form.Input |
|||
label="设备搜索:" |
|||
field="name" |
|||
placeholder="请输入设备名称" |
|||
labelPosition="left" |
|||
style={screen} |
|||
/> |
|||
<Form.Select |
|||
label="厂家筛选:" |
|||
labelPosition="left" |
|||
style={screen} |
|||
field="venderId" |
|||
placeholder="全部" |
|||
> |
|||
{venderList.map((item) => { |
|||
return ( |
|||
<Form.Select.Option key={item.id} value={item.id}> |
|||
{item.name} |
|||
</Form.Select.Option> |
|||
); |
|||
})} |
|||
</Form.Select> |
|||
<Form.Select |
|||
label="状态查询:" |
|||
labelPosition="left" |
|||
field="type2" |
|||
style={screen} |
|||
placeholder="全部" |
|||
> |
|||
<Form.Select.Option value="yes">在线</Form.Select.Option> |
|||
<Form.Select.Option value="no">离线</Form.Select.Option> |
|||
</Form.Select> |
|||
{/* <Form.Select |
|||
label="关联项目:" |
|||
labelPosition="left" |
|||
field="type3" |
|||
style={screen} |
|||
placeholder="全部" |
|||
> |
|||
<Form.Select.Option value="智慧环保"> |
|||
飞尚科技1 |
|||
</Form.Select.Option> |
|||
<Form.Select.Option value="智慧水务"> |
|||
飞尚科技2 |
|||
</Form.Select.Option> |
|||
</Form.Select> */} |
|||
</Form> |
|||
<div |
|||
style={{ |
|||
width: 150, |
|||
display: "flex", |
|||
justifyContent: "flex-end", |
|||
alignItems: "flex-end", |
|||
}} |
|||
> |
|||
<Button |
|||
theme="solid" |
|||
type="primary" |
|||
style={{ |
|||
width: 65, |
|||
height: 30, |
|||
borderRadius: 3, |
|||
marginBottom: 20, |
|||
marginRight: 20, |
|||
}} |
|||
onClick={() => { |
|||
api.current.validate().then((values) => { |
|||
console.log(values); |
|||
console.log( |
|||
equipmentWarehouseNvr.data.filter((item) => { |
|||
return ( |
|||
item.name.indexOf(values.name) > -1 && |
|||
item.venderId === values.venderId |
|||
); |
|||
}) |
|||
); |
|||
}); |
|||
console.log(equipmentWarehouseNvr.data); |
|||
}} |
|||
> |
|||
搜素 |
|||
</Button> |
|||
<Button |
|||
theme="light" |
|||
type="primary" |
|||
style={{ |
|||
width: 65, |
|||
height: 30, |
|||
backGround: "#FFFFFF", |
|||
borderRadius: 3, |
|||
border: "1px solid #D9D9D9", |
|||
marginBottom: 20, |
|||
}} |
|||
> |
|||
重置 |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div style={{ background: "#FFFFFF", marginTop: 5 }}> |
|||
<div |
|||
style={{ |
|||
width: "100%", |
|||
display: "flex", |
|||
justifyContent: "space-between", |
|||
padding: "13px 20px", |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
width: 64, |
|||
height: 22, |
|||
fontSize: 16, |
|||
fontfAmily: "PingFangSC-Medium, PingFang SC", |
|||
fontWeight: "bold", |
|||
color: "rgba(0, 0, 0, 0.85)", |
|||
lineHeight: "22px", |
|||
}} |
|||
> |
|||
设备列表 |
|||
</div> |
|||
<div> |
|||
<Button |
|||
style={{ |
|||
width: 32, |
|||
height: 32, |
|||
background: "#D9D9D9", |
|||
borderadius: 3, |
|||
marginRight: 20, |
|||
}} |
|||
type="primary" |
|||
key="primary" |
|||
onClick={() => { |
|||
setSetup(true); |
|||
}} |
|||
> |
|||
<img |
|||
src="/assets/images/background/setup.png" |
|||
alt="设置" |
|||
style={{ width: 18, height: 18 }} |
|||
/> |
|||
</Button> |
|||
<Button |
|||
style={{ |
|||
width: 65, |
|||
height: 32, |
|||
background: "#FFFFFF", |
|||
borderRadius: 3, |
|||
border: "1px solid #1859C1", |
|||
}} |
|||
> |
|||
导出 |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
<Table |
|||
columns={setupp} |
|||
dataSource={equipmentWarehouseNvr.data} |
|||
bordered={false} |
|||
empty="暂无数据" |
|||
style={{ |
|||
padding: "0px 20px", |
|||
}} |
|||
pagination={false} |
|||
/> |
|||
<div |
|||
style={{ |
|||
display: "flex", |
|||
justifyContent: "flex-end", |
|||
padding: "20px 20px", |
|||
}} |
|||
> |
|||
<span style={{ lineHeight: "30px" }}> |
|||
共{equipmentWarehouseNvr.total}个设备 |
|||
</span> |
|||
<Pagination |
|||
total={equipmentWarehouseNvr.total} |
|||
showSizeChanger |
|||
currentPage={query.page + 1} |
|||
pageSizeOpts={[10, 20, 30, 40]} |
|||
onChange={(currentPage, pageSize) => { |
|||
setQuery({ limit: pageSize, page: currentPage - 1 }); |
|||
}} |
|||
/> |
|||
</div> |
|||
|
|||
{setup ? ( |
|||
<Setup |
|||
visible={true} |
|||
SETUPS={SETUPS} |
|||
close={() => { |
|||
setSetup(false); |
|||
attribute(); |
|||
}} |
|||
/> |
|||
) : ( |
|||
"" |
|||
)} |
|||
|
|||
{sideSheet ? ( |
|||
<SideSheets |
|||
visible={true} |
|||
close={() => { |
|||
setSideSheet(false); |
|||
}} |
|||
/> |
|||
) : ( |
|||
[] |
|||
)} |
|||
</div> |
|||
</> |
|||
); |
|||
}; |
|||
|
|||
function mapStateToProps(state) { |
|||
const { auth, global, members, equipmentWarehouseNvr } = state; |
|||
return { |
|||
loading: members.isRequesting, |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
members: members.data, |
|||
equipmentWarehouseNvr: equipmentWarehouseNvr.data || [], |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(NvrHeader); |
@ -0,0 +1,15 @@ |
|||
'use strict'; |
|||
|
|||
import reducers from './reducers'; |
|||
import routes from './routes'; |
|||
import actions from './actions'; |
|||
import { getNavItem } from './nav-item'; |
|||
|
|||
export default { |
|||
key: 'equipmentWarehouse', |
|||
name: '书写示例', |
|||
reducers: reducers, |
|||
routes: routes, |
|||
actions: actions, |
|||
getNavItem: getNavItem |
|||
}; |
@ -0,0 +1,16 @@ |
|||
import React from 'react'; |
|||
import { IconCode } from '@douyinfe/semi-icons'; |
|||
|
|||
export function getNavItem (user, dispatch) { |
|||
return ( |
|||
[ |
|||
{ |
|||
itemKey: 'equipmentWarehouse', text: '设备仓库', icon: <IconCode />, |
|||
items: [ |
|||
{ itemKey: 'nvr', to: '/equipmentWarehouse/nvr', text: 'NVR管理' }, |
|||
{ itemKey: 'camera', to: '/equipmentWarehouse/camera', text: '摄像头管理' }, |
|||
] |
|||
}, |
|||
] |
|||
); |
|||
} |
@ -0,0 +1,5 @@ |
|||
'use strict'; |
|||
|
|||
export default { |
|||
|
|||
} |
@ -0,0 +1,23 @@ |
|||
'use strict'; |
|||
import { Nvr,Camera } from './containers'; |
|||
|
|||
export default [{ |
|||
type: 'inner', |
|||
route: { |
|||
path: '/equipmentWarehouse', |
|||
key: 'equipmentWarehouse', |
|||
breadcrumb: '设备仓库', |
|||
// 不设置 component 则面包屑禁止跳转
|
|||
childRoutes: [{ |
|||
path: '/nvr', |
|||
key: 'nvr', |
|||
component: Nvr, |
|||
breadcrumb: 'NVR管理', |
|||
},{ |
|||
path: '/camera', |
|||
key: 'camera', |
|||
component: Camera, |
|||
breadcrumb: '摄像头管理', |
|||
}] |
|||
} |
|||
}]; |
@ -1,11 +1,14 @@ |
|||
'use strict'; |
|||
import Func from './func'; |
|||
import { isAuthorized } from './func'; |
|||
import { AuthorizationCode } from './authCode'; |
|||
import { ApiTable, RouteTable } from './webapi' |
|||
import { ApiTable, RouteTable, AuthRequest } from './webapi' |
|||
|
|||
export { |
|||
Func, |
|||
isAuthorized, |
|||
|
|||
AuthorizationCode, |
|||
|
|||
ApiTable, |
|||
RouteTable, |
|||
AuthorizationCode, |
|||
AuthRequest, |
|||
} |