Compare commits
4 Commits
1b3ed3348b
...
8a4beed0c7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a4beed0c7 | ||
|
|
bae2b2524b | ||
|
|
8d97ee613e | ||
|
|
da98101aac |
@ -518,8 +518,8 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
|||||||
log.info("[目录订阅]成功: {}", device.getDeviceId());
|
log.info("[目录订阅]成功: {}", device.getDeviceId());
|
||||||
if (!subscribeTaskRunner.containsKey(SubscribeTaskForCatalog.getKey(device))) {
|
if (!subscribeTaskRunner.containsKey(SubscribeTaskForCatalog.getKey(device))) {
|
||||||
SIPResponse response = (SIPResponse) event.getResponse();
|
SIPResponse response = (SIPResponse) event.getResponse();
|
||||||
SipTransactionInfo transactionInfoForResonse = new SipTransactionInfo(response);
|
SipTransactionInfo transactionInfoForResponse = new SipTransactionInfo(response);
|
||||||
SubscribeTask subscribeTask = SubscribeTaskForCatalog.getInstance(device, this::catalogSubscribeExpire, transactionInfoForResonse);
|
SubscribeTask subscribeTask = SubscribeTaskForCatalog.getInstance(device, this::catalogSubscribeExpire, transactionInfoForResponse);
|
||||||
if (subscribeTask != null) {
|
if (subscribeTask != null) {
|
||||||
subscribeTaskRunner.addSubscribe(subscribeTask);
|
subscribeTaskRunner.addSubscribe(subscribeTask);
|
||||||
}
|
}
|
||||||
@ -582,13 +582,13 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
|||||||
log.info("[移动位置订阅]成功: {}", device.getDeviceId());
|
log.info("[移动位置订阅]成功: {}", device.getDeviceId());
|
||||||
if (!subscribeTaskRunner.containsKey(SubscribeTaskForMobilPosition.getKey(device))) {
|
if (!subscribeTaskRunner.containsKey(SubscribeTaskForMobilPosition.getKey(device))) {
|
||||||
SIPResponse response = (SIPResponse) event.getResponse();
|
SIPResponse response = (SIPResponse) event.getResponse();
|
||||||
SipTransactionInfo transactionInfoForResonse = new SipTransactionInfo(response);
|
SipTransactionInfo transactionInfoForResponse = new SipTransactionInfo(response);
|
||||||
SubscribeTask subscribeTask = SubscribeTaskForMobilPosition.getInstance(device, this::catalogSubscribeExpire, transactionInfoForResonse);
|
SubscribeTask subscribeTask = SubscribeTaskForMobilPosition.getInstance(device, this::mobilPositionSubscribeExpire, transactionInfoForResponse);
|
||||||
if (subscribeTask != null) {
|
if (subscribeTask != null) {
|
||||||
subscribeTaskRunner.addSubscribe(subscribeTask);
|
subscribeTaskRunner.addSubscribe(subscribeTask);
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
subscribeTaskRunner.updateDelay(SubscribeTaskForMobilPosition.getKey(device), (device.getSubscribeCycleForCatalog() * 1000L - 500L) + System.currentTimeMillis());
|
subscribeTaskRunner.updateDelay(SubscribeTaskForMobilPosition.getKey(device), (device.getSubscribeCycleForMobilePosition() * 1000L - 500L) + System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
},eventResult -> {
|
},eventResult -> {
|
||||||
@ -874,7 +874,16 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
|||||||
public void subscribeMobilePosition(int id, int cycle, int interval) {
|
public void subscribeMobilePosition(int id, int cycle, int interval) {
|
||||||
Device device = deviceMapper.query(id);
|
Device device = deviceMapper.query(id);
|
||||||
Assert.notNull(device, "未找到设备");
|
Assert.notNull(device, "未找到设备");
|
||||||
Assert.isTrue(device.isOnLine(), "设备已离线");
|
if (!device.isOnLine()) {
|
||||||
|
// 开启订阅
|
||||||
|
device.setSubscribeCycleForMobilePosition(cycle);
|
||||||
|
device.setMobilePositionSubmissionInterval(interval);
|
||||||
|
updateDevice(device);
|
||||||
|
if (subscribeTaskRunner.containsKey(SubscribeTaskForMobilPosition.getKey(device))) {
|
||||||
|
subscribeTaskRunner.removeSubscribe(SubscribeTaskForMobilPosition.getKey(device));
|
||||||
|
}
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备已离线");
|
||||||
|
}
|
||||||
|
|
||||||
if (device.getSubscribeCycleForMobilePosition() == cycle) {
|
if (device.getSubscribeCycleForMobilePosition() == cycle) {
|
||||||
return;
|
return;
|
||||||
@ -890,6 +899,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
|||||||
// 开启订阅
|
// 开启订阅
|
||||||
device.setSubscribeCycleForMobilePosition(cycle);
|
device.setSubscribeCycleForMobilePosition(cycle);
|
||||||
device.setMobilePositionSubmissionInterval(interval);
|
device.setMobilePositionSubmissionInterval(interval);
|
||||||
|
updateDevice(device);
|
||||||
if (cycle > 0) {
|
if (cycle > 0) {
|
||||||
addMobilePositionSubscribe(device, null);
|
addMobilePositionSubscribe(device, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public class SubscribeTaskForMobilPosition extends SubscribeTask {
|
|||||||
public static final String name = "mobilPosition";
|
public static final String name = "mobilPosition";
|
||||||
|
|
||||||
public static SubscribeTask getInstance(Device device, SubscribeCallback callback, SipTransactionInfo transactionInfo) {
|
public static SubscribeTask getInstance(Device device, SubscribeCallback callback, SipTransactionInfo transactionInfo) {
|
||||||
if (device.getSubscribeCycleForCatalog() <= 0) {
|
if (device.getSubscribeCycleForMobilePosition() <= 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SubscribeTaskForMobilPosition subscribeTaskForMobilPosition = new SubscribeTaskForMobilPosition();
|
SubscribeTaskForMobilPosition subscribeTaskForMobilPosition = new SubscribeTaskForMobilPosition();
|
||||||
|
|||||||
@ -861,7 +861,7 @@
|
|||||||
320623,如东县,3206
|
320623,如东县,3206
|
||||||
320681,启东市,3206
|
320681,启东市,3206
|
||||||
320682,如皋市,3206
|
320682,如皋市,3206
|
||||||
320684,海门市,3206
|
320684,海门区,3206
|
||||||
320685,海安市,3206
|
320685,海安市,3206
|
||||||
3207,连云港市,32
|
3207,连云港市,32
|
||||||
320703,连云区,3207
|
320703,连云区,3207
|
||||||
@ -918,8 +918,6 @@
|
|||||||
33,浙江省,
|
33,浙江省,
|
||||||
3301,杭州市,33
|
3301,杭州市,33
|
||||||
330102,上城区,3301
|
330102,上城区,3301
|
||||||
330103,下城区,3301
|
|
||||||
330104,江干区,3301
|
|
||||||
330105,拱墅区,3301
|
330105,拱墅区,3301
|
||||||
330106,西湖区,3301
|
330106,西湖区,3301
|
||||||
330108,滨江区,3301
|
330108,滨江区,3301
|
||||||
@ -927,6 +925,8 @@
|
|||||||
330110,余杭区,3301
|
330110,余杭区,3301
|
||||||
330111,富阳区,3301
|
330111,富阳区,3301
|
||||||
330112,临安区,3301
|
330112,临安区,3301
|
||||||
|
330113,临平区,3301
|
||||||
|
330114,钱塘区,3301
|
||||||
330122,桐庐县,3301
|
330122,桐庐县,3301
|
||||||
330127,淳安县,3301
|
330127,淳安县,3301
|
||||||
330182,建德市,3301
|
330182,建德市,3301
|
||||||
|
|||||||
|
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"presets": [
|
|
||||||
["env", {
|
|
||||||
"modules": false,
|
|
||||||
"targets": {
|
|
||||||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"stage-2"
|
|
||||||
],
|
|
||||||
"plugins": ["transform-vue-jsx", "transform-runtime"]
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
14
web_src/.gitignore
vendored
@ -1,14 +0,0 @@
|
|||||||
.DS_Store
|
|
||||||
node_modules/
|
|
||||||
/dist/
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
"plugins": {
|
|
||||||
"postcss-import": {},
|
|
||||||
"postcss-url": {},
|
|
||||||
// to edit target browsers: use "browserslist" field in package.json
|
|
||||||
"autoprefixer": {},
|
|
||||||
'postcss-pxtorem': {
|
|
||||||
rootValue: 16,
|
|
||||||
propList: ['font-size'] // 只转化font-size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
# gb_web
|
|
||||||
|
|
||||||
> A Vue.js project
|
|
||||||
|
|
||||||
## Build Setup
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
# install dependencies
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# serve with hot reload at localhost:8080
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# build for production with minification
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# build for production and view the bundle analyzer report
|
|
||||||
npm run build --report
|
|
||||||
```
|
|
||||||
|
|
||||||
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
require('./check-versions')()
|
|
||||||
|
|
||||||
process.env.NODE_ENV = 'production'
|
|
||||||
|
|
||||||
const ora = require('ora')
|
|
||||||
const rm = require('rimraf')
|
|
||||||
const path = require('path')
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
const config = require('../config')
|
|
||||||
const webpackConfig = require('./webpack.prod.conf')
|
|
||||||
|
|
||||||
const spinner = ora('building for production...')
|
|
||||||
spinner.start()
|
|
||||||
|
|
||||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
|
||||||
if (err) throw err
|
|
||||||
webpack(webpackConfig, (err, stats) => {
|
|
||||||
spinner.stop()
|
|
||||||
if (err) throw err
|
|
||||||
process.stdout.write(stats.toString({
|
|
||||||
colors: true,
|
|
||||||
modules: false,
|
|
||||||
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
|
|
||||||
chunks: false,
|
|
||||||
chunkModules: false
|
|
||||||
}) + '\n\n')
|
|
||||||
|
|
||||||
if (stats.hasErrors()) {
|
|
||||||
console.log(chalk.red(' Build failed with errors.\n'))
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(chalk.cyan(' Build complete.\n'))
|
|
||||||
console.log(chalk.yellow(
|
|
||||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
|
||||||
' Opening index.html over file:// won\'t work.\n'
|
|
||||||
))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const semver = require('semver')
|
|
||||||
const packageConfig = require('../package.json')
|
|
||||||
const shell = require('shelljs')
|
|
||||||
|
|
||||||
function exec (cmd) {
|
|
||||||
return require('child_process').execSync(cmd).toString().trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionRequirements = [
|
|
||||||
{
|
|
||||||
name: 'node',
|
|
||||||
currentVersion: semver.clean(process.version),
|
|
||||||
versionRequirement: packageConfig.engines.node
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
if (shell.which('npm')) {
|
|
||||||
versionRequirements.push({
|
|
||||||
name: 'npm',
|
|
||||||
currentVersion: exec('npm --version'),
|
|
||||||
versionRequirement: packageConfig.engines.npm
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
const warnings = []
|
|
||||||
|
|
||||||
for (let i = 0; i < versionRequirements.length; i++) {
|
|
||||||
const mod = versionRequirements[i]
|
|
||||||
|
|
||||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
|
||||||
warnings.push(mod.name + ': ' +
|
|
||||||
chalk.red(mod.currentVersion) + ' should be ' +
|
|
||||||
chalk.green(mod.versionRequirement)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (warnings.length) {
|
|
||||||
console.log('')
|
|
||||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
|
||||||
console.log()
|
|
||||||
|
|
||||||
for (let i = 0; i < warnings.length; i++) {
|
|
||||||
const warning = warnings[i]
|
|
||||||
console.log(' ' + warning)
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log()
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 6.7 KiB |
@ -1,101 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const path = require('path')
|
|
||||||
const config = require('../config')
|
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
|
||||||
const packageConfig = require('../package.json')
|
|
||||||
|
|
||||||
exports.assetsPath = function (_path) {
|
|
||||||
const assetsSubDirectory = process.env.NODE_ENV === 'production'
|
|
||||||
? config.build.assetsSubDirectory
|
|
||||||
: config.dev.assetsSubDirectory
|
|
||||||
|
|
||||||
return path.posix.join(assetsSubDirectory, _path)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.cssLoaders = function (options) {
|
|
||||||
options = options || {}
|
|
||||||
|
|
||||||
const cssLoader = {
|
|
||||||
loader: 'css-loader',
|
|
||||||
options: {
|
|
||||||
sourceMap: options.sourceMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const postcssLoader = {
|
|
||||||
loader: 'postcss-loader',
|
|
||||||
options: {
|
|
||||||
sourceMap: options.sourceMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate loader string to be used with extract text plugin
|
|
||||||
function generateLoaders (loader, loaderOptions) {
|
|
||||||
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
|
|
||||||
|
|
||||||
if (loader) {
|
|
||||||
loaders.push({
|
|
||||||
loader: loader + '-loader',
|
|
||||||
options: Object.assign({}, loaderOptions, {
|
|
||||||
sourceMap: options.sourceMap
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract CSS when that option is specified
|
|
||||||
// (which is the case during production build)
|
|
||||||
if (options.extract) {
|
|
||||||
return ExtractTextPlugin.extract({
|
|
||||||
use: loaders,
|
|
||||||
fallback: 'vue-style-loader'
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return ['vue-style-loader'].concat(loaders)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
|
||||||
return {
|
|
||||||
css: generateLoaders(),
|
|
||||||
postcss: generateLoaders(),
|
|
||||||
less: generateLoaders('less'),
|
|
||||||
sass: generateLoaders('sass', { indentedSyntax: true }),
|
|
||||||
scss: generateLoaders('sass'),
|
|
||||||
stylus: generateLoaders('stylus'),
|
|
||||||
styl: generateLoaders('stylus')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate loaders for standalone style files (outside of .vue)
|
|
||||||
exports.styleLoaders = function (options) {
|
|
||||||
const output = []
|
|
||||||
const loaders = exports.cssLoaders(options)
|
|
||||||
|
|
||||||
for (const extension in loaders) {
|
|
||||||
const loader = loaders[extension]
|
|
||||||
output.push({
|
|
||||||
test: new RegExp('\\.' + extension + '$'),
|
|
||||||
use: loader
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.createNotifierCallback = () => {
|
|
||||||
const notifier = require('node-notifier')
|
|
||||||
|
|
||||||
return (severity, errors) => {
|
|
||||||
if (severity !== 'error') return
|
|
||||||
|
|
||||||
const error = errors[0]
|
|
||||||
const filename = error.file && error.file.split('!').pop()
|
|
||||||
|
|
||||||
notifier.notify({
|
|
||||||
title: packageConfig.name,
|
|
||||||
message: severity + ': ' + error.name,
|
|
||||||
subtitle: filename || '',
|
|
||||||
icon: path.join(__dirname, 'logo.png')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const utils = require('./utils')
|
|
||||||
const config = require('../config')
|
|
||||||
const isProduction = process.env.NODE_ENV === 'production'
|
|
||||||
const sourceMapEnabled = isProduction
|
|
||||||
? config.build.productionSourceMap
|
|
||||||
: config.dev.cssSourceMap
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
loaders: utils.cssLoaders({
|
|
||||||
sourceMap: sourceMapEnabled,
|
|
||||||
extract: isProduction
|
|
||||||
}),
|
|
||||||
cssSourceMap: sourceMapEnabled,
|
|
||||||
cacheBusting: config.dev.cacheBusting,
|
|
||||||
transformToRequire: {
|
|
||||||
video: ['src', 'poster'],
|
|
||||||
source: 'src',
|
|
||||||
img: 'src',
|
|
||||||
image: 'xlink:href'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const path = require('path')
|
|
||||||
const utils = require('./utils')
|
|
||||||
const config = require('../config')
|
|
||||||
const vueLoaderConfig = require('./vue-loader.conf')
|
|
||||||
|
|
||||||
function resolve (dir) {
|
|
||||||
return path.join(__dirname, '..', dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
context: path.resolve(__dirname, '../'),
|
|
||||||
entry: {
|
|
||||||
app: './src/main.js'
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: config.build.assetsRoot,
|
|
||||||
filename: '[name].js',
|
|
||||||
publicPath: process.env.NODE_ENV === 'production'
|
|
||||||
? config.build.assetsPublicPath
|
|
||||||
: config.dev.assetsPublicPath
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js', '.vue', '.json'],
|
|
||||||
alias: {
|
|
||||||
'vue$': 'vue/dist/vue.esm.js',
|
|
||||||
'@': resolve('src'),
|
|
||||||
'@static': resolve('static'),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.vue$/,
|
|
||||||
loader: 'vue-loader',
|
|
||||||
options: vueLoaderConfig
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
loader: 'babel-loader',
|
|
||||||
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
limit: 10000,
|
|
||||||
name: utils.assetsPath('img/[name].[hash:7].[ext]')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
limit: 10000,
|
|
||||||
name: utils.assetsPath('media/[name].[hash:7].[ext]')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
limit: 10000,
|
|
||||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
// prevent webpack from injecting useless setImmediate polyfill because Vue
|
|
||||||
// source contains it (although only uses it if it's native).
|
|
||||||
setImmediate: false,
|
|
||||||
// prevent webpack from injecting mocks to Node native modules
|
|
||||||
// that does not make sense for the client
|
|
||||||
dgram: 'empty',
|
|
||||||
fs: 'empty',
|
|
||||||
net: 'empty',
|
|
||||||
tls: 'empty',
|
|
||||||
child_process: 'empty'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const utils = require('./utils')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
const config = require('../config')
|
|
||||||
const merge = require('webpack-merge')
|
|
||||||
const path = require('path')
|
|
||||||
const baseWebpackConfig = require('./webpack.base.conf')
|
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
||||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
|
|
||||||
const portfinder = require('portfinder')
|
|
||||||
|
|
||||||
const PORT = process.env.PORT && Number(process.env.PORT)
|
|
||||||
|
|
||||||
const devWebpackConfig = merge(baseWebpackConfig, {
|
|
||||||
module: {
|
|
||||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
|
|
||||||
},
|
|
||||||
// cheap-module-eval-source-map is faster for development
|
|
||||||
devtool: config.dev.devtool,
|
|
||||||
|
|
||||||
// these devServer options should be customized in /config/index.js
|
|
||||||
devServer: {
|
|
||||||
clientLogLevel: 'warning',
|
|
||||||
historyApiFallback: {
|
|
||||||
rewrites: [
|
|
||||||
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
hot: true,
|
|
||||||
contentBase: false, // since we use CopyWebpackPlugin.
|
|
||||||
compress: true,
|
|
||||||
host: config.dev.host,
|
|
||||||
port: config.dev.port,
|
|
||||||
open: config.dev.autoOpenBrowser,
|
|
||||||
overlay: config.dev.errorOverlay
|
|
||||||
? { warnings: false, errors: true }
|
|
||||||
: false,
|
|
||||||
publicPath: config.dev.assetsPublicPath,
|
|
||||||
proxy: config.dev.proxyTable,
|
|
||||||
quiet: true, // necessary for FriendlyErrorsPlugin
|
|
||||||
watchOptions: {
|
|
||||||
poll: config.dev.poll,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': require('../config/dev.env')
|
|
||||||
}),
|
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
|
||||||
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
|
|
||||||
new webpack.NoEmitOnErrorsPlugin(),
|
|
||||||
// https://github.com/ampedandwired/html-webpack-plugin
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
filename: 'index.html',
|
|
||||||
template: 'index.html',
|
|
||||||
inject: true
|
|
||||||
}),
|
|
||||||
// copy custom static assets
|
|
||||||
new CopyWebpackPlugin([
|
|
||||||
{
|
|
||||||
from: path.resolve(__dirname, '../static'),
|
|
||||||
to: config.dev.assetsSubDirectory,
|
|
||||||
ignore: ['.*']
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
new CopyWebpackPlugin([
|
|
||||||
{ from: 'node_modules/@liveqing/liveplayer/dist/component/crossdomain.xml'},
|
|
||||||
{ from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer.swf'},
|
|
||||||
{ from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer-lib.min.js', to: config.build.assetsSubDirectory + '/js/'},
|
|
||||||
])
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = new Promise((resolve, reject) => {
|
|
||||||
portfinder.basePort = process.env.PORT || config.dev.port
|
|
||||||
portfinder.getPort((err, port) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err)
|
|
||||||
} else {
|
|
||||||
// publish the new Port, necessary for e2e tests
|
|
||||||
process.env.PORT = port
|
|
||||||
// add port to devServer config
|
|
||||||
devWebpackConfig.devServer.port = port
|
|
||||||
|
|
||||||
// Add FriendlyErrorsPlugin
|
|
||||||
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
|
|
||||||
compilationSuccessInfo: {
|
|
||||||
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
|
|
||||||
},
|
|
||||||
onErrors: config.dev.notifyOnErrors
|
|
||||||
? utils.createNotifierCallback()
|
|
||||||
: undefined
|
|
||||||
}))
|
|
||||||
|
|
||||||
resolve(devWebpackConfig)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@ -1,150 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const path = require('path')
|
|
||||||
const utils = require('./utils')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
const config = require('../config')
|
|
||||||
const merge = require('webpack-merge')
|
|
||||||
const baseWebpackConfig = require('./webpack.base.conf')
|
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
|
||||||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
|
||||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
|
|
||||||
|
|
||||||
const env = require('../config/prod.env')
|
|
||||||
|
|
||||||
const webpackConfig = merge(baseWebpackConfig, {
|
|
||||||
module: {
|
|
||||||
rules: utils.styleLoaders({
|
|
||||||
sourceMap: config.build.productionSourceMap,
|
|
||||||
extract: true,
|
|
||||||
usePostCSS: true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
devtool: config.build.productionSourceMap ? config.build.devtool : false,
|
|
||||||
output: {
|
|
||||||
path: config.build.assetsRoot,
|
|
||||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
|
||||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': env
|
|
||||||
}),
|
|
||||||
new UglifyJsPlugin({
|
|
||||||
uglifyOptions: {
|
|
||||||
compress: {
|
|
||||||
warnings: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sourceMap: config.build.productionSourceMap,
|
|
||||||
parallel: true
|
|
||||||
}),
|
|
||||||
// extract css into its own file
|
|
||||||
new ExtractTextPlugin({
|
|
||||||
filename: utils.assetsPath('css/[name].[contenthash].css'),
|
|
||||||
// Setting the following option to `false` will not extract CSS from codesplit chunks.
|
|
||||||
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
|
|
||||||
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
|
|
||||||
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
|
|
||||||
allChunks: true,
|
|
||||||
}),
|
|
||||||
// Compress extracted CSS. We are using this plugin so that possible
|
|
||||||
// duplicated CSS from different components can be deduped.
|
|
||||||
new OptimizeCSSPlugin({
|
|
||||||
cssProcessorOptions: config.build.productionSourceMap
|
|
||||||
? { safe: true, map: { inline: false } }
|
|
||||||
: { safe: true }
|
|
||||||
}),
|
|
||||||
// generate dist index.html with correct asset hash for caching.
|
|
||||||
// you can customize output by editing /index.html
|
|
||||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
filename: config.build.index,
|
|
||||||
template: 'index.html',
|
|
||||||
inject: true,
|
|
||||||
minify: {
|
|
||||||
removeComments: true,
|
|
||||||
collapseWhitespace: true,
|
|
||||||
removeAttributeQuotes: true
|
|
||||||
// more options:
|
|
||||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
|
||||||
},
|
|
||||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
|
||||||
chunksSortMode: 'dependency'
|
|
||||||
}),
|
|
||||||
// keep module.id stable when vendor modules does not change
|
|
||||||
new webpack.HashedModuleIdsPlugin(),
|
|
||||||
// enable scope hoisting
|
|
||||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
|
||||||
// split vendor js into its own file
|
|
||||||
new webpack.optimize.CommonsChunkPlugin({
|
|
||||||
name: 'vendor',
|
|
||||||
minChunks (module) {
|
|
||||||
// any required modules inside node_modules are extracted to vendor
|
|
||||||
return (
|
|
||||||
module.resource &&
|
|
||||||
/\.js$/.test(module.resource) &&
|
|
||||||
module.resource.indexOf(
|
|
||||||
path.join(__dirname, '../node_modules')
|
|
||||||
) === 0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
// extract webpack runtime and module manifest to its own file in order to
|
|
||||||
// prevent vendor hash from being updated whenever app bundle is updated
|
|
||||||
new webpack.optimize.CommonsChunkPlugin({
|
|
||||||
name: 'manifest',
|
|
||||||
minChunks: Infinity
|
|
||||||
}),
|
|
||||||
// This instance extracts shared chunks from code splitted chunks and bundles them
|
|
||||||
// in a separate chunk, similar to the vendor chunk
|
|
||||||
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
|
|
||||||
new webpack.optimize.CommonsChunkPlugin({
|
|
||||||
name: 'app',
|
|
||||||
async: 'vendor-async',
|
|
||||||
children: true,
|
|
||||||
minChunks: 3
|
|
||||||
}),
|
|
||||||
|
|
||||||
// copy custom static assets
|
|
||||||
new CopyWebpackPlugin([
|
|
||||||
{
|
|
||||||
from: path.resolve(__dirname, '../static'),
|
|
||||||
to: config.build.assetsSubDirectory,
|
|
||||||
ignore: ['.*']
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
new CopyWebpackPlugin([
|
|
||||||
{ from: 'node_modules/@liveqing/liveplayer/dist/component/crossdomain.xml'},
|
|
||||||
{ from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer.swf'},
|
|
||||||
{ from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer-lib.min.js', to: config.build.assetsSubDirectory + '/js/'},
|
|
||||||
])
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (config.build.productionGzip) {
|
|
||||||
const CompressionWebpackPlugin = require('compression-webpack-plugin')
|
|
||||||
|
|
||||||
webpackConfig.plugins.push(
|
|
||||||
new CompressionWebpackPlugin({
|
|
||||||
asset: '[path].gz[query]',
|
|
||||||
algorithm: 'gzip',
|
|
||||||
test: new RegExp(
|
|
||||||
'\\.(' +
|
|
||||||
config.build.productionGzipExtensions.join('|') +
|
|
||||||
')$'
|
|
||||||
),
|
|
||||||
threshold: 10240,
|
|
||||||
minRatio: 0.8
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.build.bundleAnalyzerReport) {
|
|
||||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
|
||||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = webpackConfig
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
const merge = require('webpack-merge')
|
|
||||||
const prodEnv = require('./prod.env')
|
|
||||||
|
|
||||||
module.exports = merge(prodEnv, {
|
|
||||||
NODE_ENV: '"development"',
|
|
||||||
BASE_API: '"/debug"'
|
|
||||||
})
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
// Template version: 1.3.1
|
|
||||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
|
||||||
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
dev: {
|
|
||||||
|
|
||||||
// Paths
|
|
||||||
assetsSubDirectory: 'static',
|
|
||||||
assetsPublicPath: '/',
|
|
||||||
proxyTable: {
|
|
||||||
'/debug': {
|
|
||||||
target: 'http://127.0.0.1:18080',
|
|
||||||
changeOrigin: true,
|
|
||||||
pathRewrite: {
|
|
||||||
'^/debug': '/'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'/static/snap': {
|
|
||||||
target: 'http://127.0.0.1:18080',
|
|
||||||
changeOrigin: true,
|
|
||||||
// pathRewrite: {
|
|
||||||
// '^/static/snap': '/static/snap'
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
// Various Dev Server settings
|
|
||||||
host:"127.0.0.1",
|
|
||||||
useLocalIp: false, // can be overwritten by process.env.HOST
|
|
||||||
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
|
||||||
autoOpenBrowser: false,
|
|
||||||
errorOverlay: true,
|
|
||||||
notifyOnErrors: true,
|
|
||||||
hot: true,//自动保存
|
|
||||||
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source Maps
|
|
||||||
*/
|
|
||||||
|
|
||||||
// https://webpack.js.org/configuration/devtool/#development
|
|
||||||
devtool: 'cheap-module-eval-source-map',
|
|
||||||
|
|
||||||
// If you have problems debugging vue-files in devtools,
|
|
||||||
// set this to false - it *may* help
|
|
||||||
// https://vue-loader.vuejs.org/en/options.html#cachebusting
|
|
||||||
cacheBusting: true,
|
|
||||||
|
|
||||||
cssSourceMap: true
|
|
||||||
},
|
|
||||||
|
|
||||||
build: {
|
|
||||||
// Template for index.html
|
|
||||||
index: path.resolve(__dirname, '../../src/main/resources/static/index.html'),
|
|
||||||
|
|
||||||
// Paths
|
|
||||||
assetsRoot: path.resolve(__dirname, '../../src/main/resources/static/'),
|
|
||||||
assetsSubDirectory: './static',
|
|
||||||
assetsPublicPath: '/',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Source Maps
|
|
||||||
*/
|
|
||||||
|
|
||||||
productionSourceMap: true,
|
|
||||||
// https://webpack.js.org/configuration/devtool/#production
|
|
||||||
devtool: '#source-map',
|
|
||||||
|
|
||||||
// Gzip off by default as many popular static hosts such as
|
|
||||||
// Surge or Netlify already gzip all static assets for you.
|
|
||||||
// Before setting to `true`, make sure to:
|
|
||||||
// npm install --save-dev compression-webpack-plugin
|
|
||||||
productionGzip: false,
|
|
||||||
productionGzipExtensions: ['js', 'css'],
|
|
||||||
|
|
||||||
// Run the build command with an extra argument to
|
|
||||||
// View the bundle analyzer report after build finishes:
|
|
||||||
// `npm run build --report`
|
|
||||||
// Set to `true` or `false` to always turn it on or off
|
|
||||||
bundleAnalyzerReport: process.env.npm_config_report
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
module.exports = {
|
|
||||||
NODE_ENV: '"production"'
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
||||||
<title>国标28181</title>
|
|
||||||
<link rel="shortcut icon" href="static/favicon.ico" type="image/x-icon">
|
|
||||||
<link rel="stylesheet" type="text/css" href="./static/css/iconfont.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="./static/css/login.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script type="text/javascript" src="./static/js/jessibuca/jessibuca.js"></script>
|
|
||||||
<script type="text/javascript" src="./static/js/EasyWasmPlayer.js"></script>
|
|
||||||
<script type="text/javascript" src="./static/js/liveplayer-lib.min.js"></script>
|
|
||||||
<script type="text/javascript" src="./static/js/ZLMRTCClient.js"></script>
|
|
||||||
<script type="text/javascript" src="./static/js/config.js"></script>
|
|
||||||
<script type="text/javascript" src="./static/js/jquery-3.7.1.min.js"></script>
|
|
||||||
<script type="text/javascript" src="./static/js/h265web/h265webjs-v20221106.js"></script>
|
|
||||||
<script type="text/javascript" src="./static/js/h265web/missile.js"></script>
|
|
||||||
|
|
||||||
<div id="app"></div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "gb_web",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A Vue.js project",
|
|
||||||
"author": "648540858 <648540858@qq.com>",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
|
||||||
"start": "npm run dev",
|
|
||||||
"build": "node build/build.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.3.0",
|
|
||||||
"@femessage/log-viewer": "^1.5.0",
|
|
||||||
"@liveqing/liveplayer": "^2.7.10",
|
|
||||||
"@wchbrad/vue-easy-tree": "^1.0.12",
|
|
||||||
"axios": "^0.24.0",
|
|
||||||
"byte-weektime-picker": "^1.1.1",
|
|
||||||
"core-js": "^2.6.5",
|
|
||||||
"echarts": "^4.9.0",
|
|
||||||
"element-ui": "^2.15.14",
|
|
||||||
"fingerprintjs2": "^2.1.2",
|
|
||||||
"moment": "^2.29.1",
|
|
||||||
"ol": "^6.14.1",
|
|
||||||
"postcss-pxtorem": "^5.1.1",
|
|
||||||
"screenfull": "5.1.0",
|
|
||||||
"strip-ansi": "^7.1.0",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"v-charts": "^1.19.0",
|
|
||||||
"vue": "^2.6.11",
|
|
||||||
"vue-clipboard2": "^0.3.1",
|
|
||||||
"vue-clipboards": "^1.3.0",
|
|
||||||
"vue-contextmenujs": "^1.3.13",
|
|
||||||
"vue-cookies": "^1.8.3",
|
|
||||||
"vue-router": "^3.1.6",
|
|
||||||
"vue-ztree-2.0": "^1.0.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"autoprefixer": "^7.1.2",
|
|
||||||
"babel-core": "^6.22.1",
|
|
||||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
|
||||||
"babel-loader": "^7.1.1",
|
|
||||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
|
||||||
"babel-plugin-transform-runtime": "^6.22.0",
|
|
||||||
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
|
||||||
"babel-preset-env": "^1.3.2",
|
|
||||||
"babel-preset-stage-2": "^6.22.0",
|
|
||||||
"chalk": "^2.0.1",
|
|
||||||
"copy-webpack-plugin": "^4.6.0",
|
|
||||||
"css-loader": "^0.28.11",
|
|
||||||
"extract-text-webpack-plugin": "^3.0.0",
|
|
||||||
"file-loader": "^1.1.4",
|
|
||||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
|
||||||
"html-webpack-plugin": "^2.30.1",
|
|
||||||
"node-notifier": "^5.1.2",
|
|
||||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
|
||||||
"ora": "^1.2.0",
|
|
||||||
"portfinder": "^1.0.13",
|
|
||||||
"postcss-import": "^11.0.0",
|
|
||||||
"postcss-loader": "^2.0.8",
|
|
||||||
"postcss-url": "^7.2.1",
|
|
||||||
"rimraf": "^2.6.0",
|
|
||||||
"semver": "^5.3.0",
|
|
||||||
"shelljs": "^0.8.5",
|
|
||||||
"uglifyjs-webpack-plugin": "^1.1.1",
|
|
||||||
"url-loader": "^0.5.8",
|
|
||||||
"vue-loader": "^13.3.0",
|
|
||||||
"vue-style-loader": "^3.0.1",
|
|
||||||
"vue-template-compiler": "^2.5.2",
|
|
||||||
"webpack": "^3.6.0",
|
|
||||||
"webpack-bundle-analyzer": "^2.9.0",
|
|
||||||
"webpack-dev-server": "^2.9.1",
|
|
||||||
"webpack-merge": "^4.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6.0.0",
|
|
||||||
"npm": ">= 3.0.0"
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"> 1%",
|
|
||||||
"last 2 versions",
|
|
||||||
"not ie <= 8"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app">
|
|
||||||
<router-view></router-view>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import userService from './components/service/UserService'
|
|
||||||
export default {
|
|
||||||
name: 'app',
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
isLogin: false,
|
|
||||||
excludeLoginCheck: ["/play/wasm", "/play/rtc"],
|
|
||||||
userInfo: { //保存用户信息
|
|
||||||
nick: null,
|
|
||||||
ulevel: null,
|
|
||||||
uid: null,
|
|
||||||
portrait: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
if (userService.getToken() == null){
|
|
||||||
console.log(22222)
|
|
||||||
console.log(this.$route.path)
|
|
||||||
try {
|
|
||||||
if (this.excludeLoginCheck && this.excludeLoginCheck.length > 0) {
|
|
||||||
for (let i = 0; i < this.excludeLoginCheck.length; i++) {
|
|
||||||
if (this.$route.path.startsWith(this.excludeLoginCheck[i])){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
//如果没有登录状态则跳转到登录页
|
|
||||||
this.$router.push('/login');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted(){
|
|
||||||
//组件开始挂载时获取用户信息
|
|
||||||
// this.getUserInfo();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
},
|
|
||||||
components: {}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
html,
|
|
||||||
body,
|
|
||||||
#app {
|
|
||||||
margin: 0 0;
|
|
||||||
background-color: #e9eef3;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.el-header,
|
|
||||||
.el-footer {
|
|
||||||
/* background-color: #b3c0d1; */
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 60px;
|
|
||||||
}
|
|
||||||
.el-main {
|
|
||||||
background-color: #f0f2f5;
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*定义滚动条轨道 内阴影+圆角*/
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #F5F5F5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*定义滑块 内阴影+圆角*/
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #c8c8c8;
|
|
||||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
|
|
||||||
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
|
|
||||||
}
|
|
||||||
.table-header {
|
|
||||||
color: #727272;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 546 B |
|
Before Width: | Height: | Size: 48 KiB |
@ -1,35 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ChannelEdit" v-loading="locading" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="close" content="编辑通道"></el-page-header>
|
|
||||||
</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div style="display: inline;">
|
|
||||||
<el-button icon="el-icon-close" size="mini" style="font-size: 20px; color: #000;" type="text" @click="close" ></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<CommonChannelEdit ref="commonChannelEdit" :id="id" :saveSuccess="close" :cancel="close"></CommonChannelEdit>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CommonChannelEdit from './common/CommonChannelEdit'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "channelEdit",
|
|
||||||
props: [ 'id', 'closeEdit'],
|
|
||||||
components: {
|
|
||||||
CommonChannelEdit,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
close: function () {
|
|
||||||
this.closeEdit()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,307 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">
|
|
||||||
<div >云端录像</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="page-header-btn">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="initData" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="search" clearable></el-input>
|
|
||||||
开始时间:
|
|
||||||
<el-date-picker
|
|
||||||
v-model="startTime"
|
|
||||||
type="datetime"
|
|
||||||
size="mini"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
@change="initData"
|
|
||||||
placeholder="选择日期时间">
|
|
||||||
</el-date-picker>
|
|
||||||
结束时间:
|
|
||||||
<el-date-picker
|
|
||||||
v-model="endTime"
|
|
||||||
type="datetime"
|
|
||||||
size="mini"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
@change="initData"
|
|
||||||
placeholder="选择日期时间">
|
|
||||||
</el-date-picker>
|
|
||||||
节点选择:
|
|
||||||
<el-select size="mini" @change="initData" style="width: 16rem; margin-right: 1rem;"
|
|
||||||
v-model="mediaServerId" placeholder="请选择" >
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option
|
|
||||||
v-for="item in mediaServerList"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.id"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
<!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord()">批量删除</el-button>-->
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" :loading="loading"
|
|
||||||
@click="initData()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--设备列表-->
|
|
||||||
<el-table size="medium" :data="recordList" style="width: 100%" :height="$tableHeght">
|
|
||||||
<el-table-column
|
|
||||||
type="selection"
|
|
||||||
width="55">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="app" label="应用名">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="stream" label="流ID" width="380">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="开始时间">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
{{formatTimeStamp(scope.row.startTime)}}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="结束时间">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
{{formatTimeStamp(scope.row.endTime)}}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="时长">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-tag v-if="Vue.prototype.$myServerId !== scope.row.serverId" style="border-color: #ecf1af">{{formatTime(scope.row.timeLen)}}</el-tag>
|
|
||||||
<el-tag v-if="Vue.prototype.$myServerId === scope.row.serverId">{{formatTime(scope.row.timeLen)}}</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="fileName" label="文件名称">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="mediaServerId" label="流媒体">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" width="200" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button size="medium" icon="el-icon-video-play" type="text" @click="play(scope.row)">播放
|
|
||||||
</el-button>
|
|
||||||
<el-button size="medium" icon="el-icon-download" type="text" @click="downloadFile(scope.row)">下载
|
|
||||||
</el-button>
|
|
||||||
<!-- <el-button size="medium" icon="el-icon-delete" type="text" style="color: #f56c6c"-->
|
|
||||||
<!-- @click="deleteRecord(scope.row)">删除-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
<el-dialog
|
|
||||||
:title="playerTitle"
|
|
||||||
:visible.sync="showPlayer"
|
|
||||||
width="50%">
|
|
||||||
<easyPlayer ref="recordVideoPlayer" :videoUrl="videoUrl" :height="false" ></easyPlayer>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import MediaServer from './service/MediaServer'
|
|
||||||
import easyPlayer from './common/easyPlayer.vue'
|
|
||||||
import moment from 'moment'
|
|
||||||
import Vue from "vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'app',
|
|
||||||
components: {
|
|
||||||
uiHeader,easyPlayer
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
search: '',
|
|
||||||
startTime: '',
|
|
||||||
endTime: '',
|
|
||||||
showPlayer: false,
|
|
||||||
playerTitle: '',
|
|
||||||
videoUrl: '',
|
|
||||||
playerStyle: {
|
|
||||||
"margin": "auto",
|
|
||||||
"margin-bottom": "20px",
|
|
||||||
"width": window.innerWidth/2 + "px",
|
|
||||||
"height": this.winHeight/2 + "px",
|
|
||||||
},
|
|
||||||
mediaServerList: [], // 滅体节点列表
|
|
||||||
mediaServerId: "", // 媒体服务
|
|
||||||
mediaServerPath: null, // 媒体服务地址
|
|
||||||
recordList: [], // 设备列表
|
|
||||||
chooseRecord: null, // 媒体服务
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
winHeight: window.innerHeight - 250,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
loading: false,
|
|
||||||
mediaServerObj: new MediaServer(),
|
|
||||||
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
Vue() {
|
|
||||||
return Vue
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
this.getMediaServerList();
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$destroy('recordVideoPlayer');
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.getRecordList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getRecordList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getRecordList();
|
|
||||||
},
|
|
||||||
getMediaServerList: function () {
|
|
||||||
let that = this;
|
|
||||||
that.mediaServerObj.getOnlineMediaServerList((data) => {
|
|
||||||
that.mediaServerList = data.data;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
setMediaServerPath: function (serverId) {
|
|
||||||
let that = this;
|
|
||||||
let i;
|
|
||||||
for (i = 0; i < that.mediaServerList.length; i++) {
|
|
||||||
if (serverId === that.mediaServerList[i].id) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let port = that.mediaServerList[i].httpPort;
|
|
||||||
if (location.protocol === "https:" && that.mediaServerList[i].httpSSlPort) {
|
|
||||||
port = that.mediaServerList[i].httpSSlPort
|
|
||||||
}
|
|
||||||
that.mediaServerPath = location.protocol + "//" + that.mediaServerList[i].streamIp + ":" + port
|
|
||||||
console.log(that.mediaServerPath)
|
|
||||||
},
|
|
||||||
getRecordList: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/cloud/record/list`,
|
|
||||||
params: {
|
|
||||||
app: '',
|
|
||||||
stream: '',
|
|
||||||
query: this.search,
|
|
||||||
startTime: this.startTime,
|
|
||||||
endTime: this.endTime,
|
|
||||||
mediaServerId: this.mediaServerId,
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.recordList = res.data.data.list;
|
|
||||||
}
|
|
||||||
this.loading = false;
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
play(row) {
|
|
||||||
console.log(row)
|
|
||||||
this.chooseRecord = row;
|
|
||||||
this.showPlayer = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/cloud/record/play/path`,
|
|
||||||
params: {
|
|
||||||
recordId: row.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (location.protocol === "https:") {
|
|
||||||
this.videoUrl = res.data.data.httpsPath;
|
|
||||||
}else {
|
|
||||||
this.videoUrl = res.data.data.httpPath;
|
|
||||||
}
|
|
||||||
console.log(222 )
|
|
||||||
console.log(this.videoUrl )
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
downloadFile(file){
|
|
||||||
console.log(file)
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/cloud/record/play/path`,
|
|
||||||
params: {
|
|
||||||
recordId: file.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.target = "_blank";
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (location.protocol === "https:") {
|
|
||||||
link.href = res.data.data.httpsPath + "&save_name=" + file.fileName;
|
|
||||||
}else {
|
|
||||||
link.href = res.data.data.httpPath + "&save_name=" + file.fileName;
|
|
||||||
}
|
|
||||||
link.click();
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteRecord() {
|
|
||||||
// TODO
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'delete',
|
|
||||||
url: `/record_proxy/api/record/delete`,
|
|
||||||
params: {
|
|
||||||
page: that.currentPage,
|
|
||||||
count: that.count
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
console.log(res)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.total = res.data.data.total;
|
|
||||||
that.recordList = res.data.data.list;
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
formatTime(time) {
|
|
||||||
const h = parseInt(time / 3600 / 1000)
|
|
||||||
const minute = parseInt((time - h * 3600 * 1000) / 60 / 1000)
|
|
||||||
let second = Math.ceil((time - h * 3600 * 1000 - minute * 60 * 1000) / 1000)
|
|
||||||
if (second < 0) {
|
|
||||||
second = 0;
|
|
||||||
}
|
|
||||||
return (h > 0 ? h + `小时` : '') + (minute > 0 ? minute + '分' : '') + (second > 0 ? second + '秒' : '')
|
|
||||||
},
|
|
||||||
formatTimeStamp(time) {
|
|
||||||
return moment.unix(time/1000).format('yyyy-MM-DD HH:mm:ss')
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,710 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="recordDetail" style="width: 100%">
|
|
||||||
<div class="page-header" style="margin-bottom: 0">
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="backToList" content="云端录像"></el-page-header>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="page-header-btn" v-if="!this.$route.params.mediaServerId" style="padding-right: 1rem">
|
|
||||||
<!-- 节点选择:-->
|
|
||||||
<!-- <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" >-->
|
|
||||||
<!-- <el-option-->
|
|
||||||
<!-- key="undefined"-->
|
|
||||||
<!-- label="全部"-->
|
|
||||||
<!-- value="undefined">-->
|
|
||||||
<!-- </el-option>-->
|
|
||||||
<!-- <el-option-->
|
|
||||||
<!-- v-for="item in mediaServerList"-->
|
|
||||||
<!-- :key="item"-->
|
|
||||||
<!-- :label="item"-->
|
|
||||||
<!-- :value="item">-->
|
|
||||||
<!-- </el-option>-->
|
|
||||||
<!-- </el-select>-->
|
|
||||||
<b>节点:</b> {{ mediaServerId }}
|
|
||||||
</div>
|
|
||||||
<div v-if="this.$route.params.mediaServerId" style="margin-right: 1rem;">
|
|
||||||
<span>流媒体:{{ this.$route.params.mediaServerId }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-container>
|
|
||||||
<el-aside width="260px">
|
|
||||||
<div class="record-list-box-box">
|
|
||||||
<div style="margin-top: 20px">
|
|
||||||
<el-date-picker size="mini" v-model="chooseDate" :picker-options="pickerOptions" type="date"
|
|
||||||
value-format="yyyy-MM-dd" placeholder="日期" @change="dateChange()"></el-date-picker>
|
|
||||||
<!-- <el-button :disabled="!mediaServerId" size="mini" type="primary" icon="fa fa-cloud-download" style="margin: auto; margin-left: 12px " title="裁剪合并" @click="drawerOpen"></el-button>-->
|
|
||||||
</div>
|
|
||||||
<div class="record-list-box" :style="recordListStyle">
|
|
||||||
<ul v-if="detailFiles.length >0" class="infinite-list record-list" v-infinite-scroll="infiniteScroll" >
|
|
||||||
<li v-for="(item,index) in detailFiles" :key="index" class="infinite-list-item record-list-item" >
|
|
||||||
<el-tag v-if="choosedFile !== item.fileName" @click="chooseFile(item)">
|
|
||||||
<i class="el-icon-video-camera" ></i>
|
|
||||||
{{ getFileShowName(item) }}
|
|
||||||
</el-tag>
|
|
||||||
<el-tag type="danger" v-if="choosedFile === item.fileName">
|
|
||||||
<i class="el-icon-video-camera" ></i>
|
|
||||||
{{ getFileShowName(item) }}
|
|
||||||
</el-tag>
|
|
||||||
<a class="el-icon-download" @click="downloadFile(item)" style="color: #409EFF;font-weight: 600;margin-left: 10px;"
|
|
||||||
target="_blank"/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div v-if="detailFiles.length === 0" class="record-list-no-val">暂无数据</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</el-aside>
|
|
||||||
<el-main style="padding: 22px">
|
|
||||||
<div class="playBox" :style="playerStyle">
|
|
||||||
<player ref="recordVideoPlayer" :videoUrl="videoUrl" :height="true" style="width: 100%" ></player>
|
|
||||||
</div>
|
|
||||||
<div class="player-option-box" >
|
|
||||||
<el-slider
|
|
||||||
class="playtime-slider"
|
|
||||||
v-model="playTime"
|
|
||||||
id="playtimeSlider"
|
|
||||||
:disabled="detailFiles.length === 0"
|
|
||||||
:min="sliderMIn"
|
|
||||||
:max="sliderMax"
|
|
||||||
:format-tooltip="playTimeFormat"
|
|
||||||
@change="playTimeChange"
|
|
||||||
:marks="playTimeSliderMarks">
|
|
||||||
</el-slider>
|
|
||||||
<div class="slider-val-box">
|
|
||||||
<div class="slider-val" v-for="(item,index) of detailFiles" :key="index" :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
<el-drawer
|
|
||||||
title="录像下载"
|
|
||||||
:visible.sync="drawer"
|
|
||||||
:direction="direction"
|
|
||||||
:before-close="drawerClose">
|
|
||||||
<div class="drawer-box">
|
|
||||||
<el-button icon="el-icon-plus" size="mini" type="primary" @click="addTask"></el-button>
|
|
||||||
<el-tabs type="border-card" style="height: 100%" v-model="tabVal" @tab-click="tabClick">
|
|
||||||
<el-tab-pane name="running">
|
|
||||||
<span slot="label"><i class="el-icon-scissors"></i>进行中</span>
|
|
||||||
<ul class="task-list">
|
|
||||||
<li class="task-list-item" v-for="(item,index) in taskListForRuning" :key="index">
|
|
||||||
<div class="task-list-item-box">
|
|
||||||
<span>{{ item.startTime.substr(10) }}-{{item.endTime.substr(10)}}</span>
|
|
||||||
<el-progress :percentage="(parseFloat(item.percentage)*100).toFixed(1)"></el-progress>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="ended">
|
|
||||||
<span slot="label"><i class="el-icon-finished"></i>已完成</span>
|
|
||||||
<ul class="task-list">
|
|
||||||
<li class="task-list-item" v-for="(item, index) in taskListEnded" :key="index">
|
|
||||||
<div class="task-list-item-box" style="height: 2rem;line-height: 2rem;">
|
|
||||||
<span>{{ item.startTime.substr(10) }}-{{item.endTime.substr(10)}}</span>
|
|
||||||
<a class="el-icon-download download-btn" :href="getFileBasePath() + '/download.html?url=download/' "
|
|
||||||
target="_blank">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
</el-drawer>
|
|
||||||
<el-dialog title="选择时间段" :visible.sync="showTaskBox">
|
|
||||||
<el-date-picker
|
|
||||||
type="datetimerange"
|
|
||||||
v-model="taskTimeRange"
|
|
||||||
range-separator="至"
|
|
||||||
start-placeholder="开始时间"
|
|
||||||
end-placeholder="结束时间"
|
|
||||||
format="HH:mm:ss"
|
|
||||||
placeholder="选择时间范围">
|
|
||||||
</el-date-picker>
|
|
||||||
<el-button size="mini" type="primary" @click="addTaskToServer">确认</el-button>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// TODO 根据查询的时间列表设置滑轨的最大值与最小值,
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import player from './common/easyPlayer.vue'
|
|
||||||
import moment from 'moment'
|
|
||||||
import axios from "axios";
|
|
||||||
export default {
|
|
||||||
name: 'app',
|
|
||||||
components: {
|
|
||||||
uiHeader, player
|
|
||||||
},
|
|
||||||
// props: [ 'mediaServerId',],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
app: this.$route.params.app,
|
|
||||||
stream: this.$route.params.stream,
|
|
||||||
mediaServerId: this.$route.params.mediaServerId,
|
|
||||||
dateFilesObj: [],
|
|
||||||
mediaServerList: [],
|
|
||||||
detailFiles: [],
|
|
||||||
loading: false,
|
|
||||||
chooseDate: null,
|
|
||||||
videoUrl: null,
|
|
||||||
choosedFile: null,
|
|
||||||
queryDate: new Date(),
|
|
||||||
currentPage: 1,
|
|
||||||
count: 1000000, // TODO 分页导致滑轨视频有效值无法获取完全
|
|
||||||
total: 0,
|
|
||||||
direction: "ltr",
|
|
||||||
drawer: false,
|
|
||||||
showTaskBox: false,
|
|
||||||
taskTimeRange: [],
|
|
||||||
taskListEnded: [],
|
|
||||||
taskListForRuning: [],
|
|
||||||
sliderMIn: 0,
|
|
||||||
sliderMax: 86400,
|
|
||||||
autoPlay: true,
|
|
||||||
taskUpdate: null,
|
|
||||||
tabVal: "running",
|
|
||||||
recordListStyle: {
|
|
||||||
height: this.winHeight + "px",
|
|
||||||
overflow: "auto",
|
|
||||||
margin: "10px auto 10px auto"
|
|
||||||
},
|
|
||||||
playerStyle: {
|
|
||||||
"margin": "auto",
|
|
||||||
"margin-bottom": "20px",
|
|
||||||
"height": this.winHeight + "px",
|
|
||||||
},
|
|
||||||
timeFormat:'00:00:00',
|
|
||||||
winHeight: window.innerHeight - 240,
|
|
||||||
playTime: 0,
|
|
||||||
playTimeSliderMarks: {
|
|
||||||
0: "00:00",
|
|
||||||
3600: "01:00",
|
|
||||||
7200: "02:00",
|
|
||||||
10800: "03:00",
|
|
||||||
14400: "04:00",
|
|
||||||
18000: "05:00",
|
|
||||||
21600: "06:00",
|
|
||||||
25200: "07:00",
|
|
||||||
28800: "08:00",
|
|
||||||
32400: "09:00",
|
|
||||||
36000: "10:00",
|
|
||||||
39600: "11:00",
|
|
||||||
43200: "12:00",
|
|
||||||
46800: "13:00",
|
|
||||||
50400: "14:00",
|
|
||||||
54000: "15:00",
|
|
||||||
57600: "16:00",
|
|
||||||
61200: "17:00",
|
|
||||||
64800: "18:00",
|
|
||||||
68400: "19:00",
|
|
||||||
72000: "20:00",
|
|
||||||
75600: "21:00",
|
|
||||||
79200: "22:00",
|
|
||||||
82800: "23:00",
|
|
||||||
86400: "24:00",
|
|
||||||
},
|
|
||||||
pickerOptions:{
|
|
||||||
cellClassName:(date) =>{
|
|
||||||
// 通过显示一个点标识这一天有录像
|
|
||||||
let time = moment(date).format('YYYY-MM-DD')
|
|
||||||
if (this.dateFilesObj[time]){
|
|
||||||
return "data-picker-true"
|
|
||||||
}else {
|
|
||||||
return "data-picker-false"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.recordListStyle.height = this.winHeight + "px";
|
|
||||||
this.playerStyle["height"] = this.winHeight + "px";
|
|
||||||
// 查询当年有视频的日期
|
|
||||||
this.getDateInYear(()=>{
|
|
||||||
if (Object.values(this.dateFilesObj).length > 0){
|
|
||||||
this.chooseDate = Object.values(this.dateFilesObj)[Object.values(this.dateFilesObj).length -1];
|
|
||||||
this.dateChange();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$destroy('recordVideoPlayer');
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
dateChange(){
|
|
||||||
this.playTime = 0;
|
|
||||||
this.detailFiles = [];
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.sliderMIn= 0;
|
|
||||||
this.sliderMax= 86400;
|
|
||||||
let chooseFullDate = new Date(this.chooseDate +" " + this.timeFormat);
|
|
||||||
if (chooseFullDate.getFullYear() !== this.queryDate.getFullYear()
|
|
||||||
|| chooseFullDate.getMonth() !== this.queryDate.getMonth()){
|
|
||||||
this.queryDate = chooseFullDate;
|
|
||||||
this.getDateInYear()
|
|
||||||
}
|
|
||||||
this.queryRecordDetails(()=>{
|
|
||||||
if (this.detailFiles.length > 0){
|
|
||||||
console.log(this.detailFiles)
|
|
||||||
let timeForFile = this.getTimeForFile(this.detailFiles[0]);
|
|
||||||
let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]);
|
|
||||||
let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
|
|
||||||
console.log(timeNum)
|
|
||||||
let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
|
|
||||||
|
|
||||||
this.playTime = parseInt(timeNum/1000)
|
|
||||||
this.sliderMIn = parseInt(timeNum/1000 - timeNum/1000%(60*60))
|
|
||||||
console.log(this.sliderMIn )
|
|
||||||
this.sliderMax = parseInt(lastTimeNum/1000 - lastTimeNum/1000%(60*60)) + 60*60
|
|
||||||
console.log(this.sliderMax )
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
infiniteScroll(){
|
|
||||||
if (this.total > this.detailFiles.length) {
|
|
||||||
this.currentPage ++;
|
|
||||||
this.queryRecordDetails();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
queryRecordDetails: function (callback){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/cloud/record/list`,
|
|
||||||
params: {
|
|
||||||
app: this.app,
|
|
||||||
stream: this.stream,
|
|
||||||
startTime: this.chooseDate + " 00:00:00",
|
|
||||||
endTime: this.chooseDate + " 23:59:59",
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
mediaServerId: this.mediaServerId
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.detailFiles = this.detailFiles.concat(res.data.data.list);
|
|
||||||
let temp = new Set()
|
|
||||||
for (let i = 0; i < this.detailFiles.length; i++) {
|
|
||||||
temp.add(this.detailFiles[i].mediaServerId)
|
|
||||||
}
|
|
||||||
this.mediaServerList = Array.from(temp)
|
|
||||||
if (this.mediaServerList.length === 1) {
|
|
||||||
this.mediaServerId = this.mediaServerList[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.loading = false;
|
|
||||||
if (callback) callback();
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
chooseFile(file){
|
|
||||||
console.log(file)
|
|
||||||
if (file == null) {
|
|
||||||
this.videoUrl = "";
|
|
||||||
this.choosedFile = "";
|
|
||||||
}else {
|
|
||||||
this.choosedFile = file.fileName;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/cloud/record/play/path`,
|
|
||||||
params: {
|
|
||||||
recordId: file.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (location.protocol === "https:") {
|
|
||||||
this.videoUrl = res.data.data.httpsPath;
|
|
||||||
}else {
|
|
||||||
this.videoUrl = res.data.data.httpPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
downloadFile(file){
|
|
||||||
console.log(file)
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/cloud/record/play/path`,
|
|
||||||
params: {
|
|
||||||
recordId: file.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.target = "_blank";
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (location.protocol === "https:") {
|
|
||||||
link.href = res.data.data.httpsPath + "&save_name=" + file.fileName;
|
|
||||||
}else {
|
|
||||||
link.href = res.data.data.httpPath + "&save_name=" + file.fileName;
|
|
||||||
}
|
|
||||||
link.click();
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
backToList() {
|
|
||||||
this.$router.back()
|
|
||||||
},
|
|
||||||
getFileShowName(item) {
|
|
||||||
return moment(item.startTime).format('HH:mm:ss') + "-" + moment(item.endTime).format('HH:mm:ss')
|
|
||||||
},
|
|
||||||
chooseMediaChange() {
|
|
||||||
|
|
||||||
},
|
|
||||||
getRecordList() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
getFileBasePath(item) {
|
|
||||||
let basePath = ""
|
|
||||||
if (axios.defaults.baseURL.startsWith("http")) {
|
|
||||||
basePath = `${axios.defaults.baseURL}/record_proxy/${item.mediaServerId}`
|
|
||||||
}else {
|
|
||||||
basePath = `${window.location.origin}${axios.defaults.baseURL}/record_proxy/${item.mediaServerId}`
|
|
||||||
}
|
|
||||||
return basePath;
|
|
||||||
},
|
|
||||||
|
|
||||||
getDataWidth(item){
|
|
||||||
let timeForFile = this.getTimeForFile(item);
|
|
||||||
let result = (timeForFile[2])/((this.sliderMax - this.sliderMIn)*1000)
|
|
||||||
return result*100
|
|
||||||
},
|
|
||||||
getDataLeft(item){
|
|
||||||
let timeForFile = this.getTimeForFile(item);
|
|
||||||
let differenceTime = timeForFile[0].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
|
|
||||||
return parseFloat((differenceTime - this.sliderMIn * 1000)/((this.sliderMax - this.sliderMIn)*1000))*100 ;
|
|
||||||
},
|
|
||||||
playTimeChange(val){
|
|
||||||
let minTime = this.getTimeForFile(this.detailFiles[0])[0]
|
|
||||||
let maxTime = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1])[1];
|
|
||||||
this.chooseFile(null);
|
|
||||||
let timeMilli = new Date(this.chooseDate + " " + this.timeFormat).getTime() + val*1000
|
|
||||||
if (timeMilli >= minTime.getTime() && timeMilli <= maxTime.getTime()){
|
|
||||||
for (let i = 0; i < this.detailFiles.length; i++) {
|
|
||||||
let timeForFile = this.getTimeForFile(this.detailFiles[i]);
|
|
||||||
if (timeMilli >= timeForFile[0].getTime() && timeMilli <= timeForFile[1].getTime()){
|
|
||||||
// TODO 当前未按照实际时间偏移,仅仅是找到对应的文静播放
|
|
||||||
this.chooseFile(this.detailFiles[i])
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getTimeForFile(file){
|
|
||||||
console.log(file)
|
|
||||||
let starTime = new Date(file.startTime * 1000);
|
|
||||||
let endTime = new Date(file.endTime * 1000);
|
|
||||||
if(this.checkIsOver24h(starTime,endTime)){
|
|
||||||
endTime = new Date(this.chooseDate + " " + "23:59:59");
|
|
||||||
}
|
|
||||||
return [starTime, endTime, endTime.getTime() - starTime.getTime()];
|
|
||||||
},
|
|
||||||
checkIsOver24h(starTime,endTime){
|
|
||||||
return starTime > endTime;
|
|
||||||
},
|
|
||||||
playTimeFormat(val){
|
|
||||||
let h = parseInt(val/3600);
|
|
||||||
let m = parseInt((val - h*3600)/60);
|
|
||||||
let s = parseInt(val - h*3600 - m*60);
|
|
||||||
|
|
||||||
let hStr = h;
|
|
||||||
let mStr = m;
|
|
||||||
let sStr = s;
|
|
||||||
if (h < 10) {
|
|
||||||
hStr = "0" + hStr;
|
|
||||||
}
|
|
||||||
if (m < 10) {
|
|
||||||
mStr = "0" + mStr;s
|
|
||||||
}
|
|
||||||
if (s < 10) {
|
|
||||||
sStr = "0" + sStr;
|
|
||||||
}
|
|
||||||
return hStr + ":" + mStr + ":" + sStr
|
|
||||||
},
|
|
||||||
deleteRecord(){
|
|
||||||
// TODO
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'delete',
|
|
||||||
url:`/record_proxy/${that.mediaServerId}/api/record/delete`,
|
|
||||||
params: {
|
|
||||||
page: that.currentPage,
|
|
||||||
count: that.count
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.total = res.data.data.total;
|
|
||||||
that.recordList = res.data.data.list;
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getDateInYear(callback){
|
|
||||||
this.dateFilesObj = {};
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/cloud/record/date/list`,
|
|
||||||
params: {
|
|
||||||
app: this.app,
|
|
||||||
stream: this.stream,
|
|
||||||
year: this.queryDate.getFullYear(),
|
|
||||||
month: this.queryDate.getMonth() + 1,
|
|
||||||
mediaServerId: this.mediaServerId,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (res.data.data.length > 0) {
|
|
||||||
for (let i = 0; i < res.data.data.length; i++) {
|
|
||||||
this.dateFilesObj[res.data.data[i]] = res.data.data[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(this.dateFilesObj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(callback)callback();
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
tabClick(){
|
|
||||||
this.getTaskList(this.tabVal === "ended")
|
|
||||||
},
|
|
||||||
drawerClose(){
|
|
||||||
this.drawer = false;
|
|
||||||
if (this.taskUpdate != null) {
|
|
||||||
window.clearInterval(this.taskUpdate)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
drawerOpen(){
|
|
||||||
this.drawer = true;
|
|
||||||
if (this.taskUpdate != null) {
|
|
||||||
window.clearInterval(this.taskUpdate)
|
|
||||||
}
|
|
||||||
this.taskUpdate = setInterval(()=>{
|
|
||||||
this.getTaskList(this.tabVal === "ended")
|
|
||||||
}, 1000)
|
|
||||||
},
|
|
||||||
addTask(){
|
|
||||||
this.showTaskBox = true;
|
|
||||||
let startTimeStr = this.chooseDate + " " + this.detailFiles[0].fileName.substring(0, 8);
|
|
||||||
let endTimeStr = this.chooseDate + " " + this.detailFiles[this.detailFiles.length - 1].fileName.substring(9, 17);
|
|
||||||
this.taskTimeRange[0] = new Date(startTimeStr)
|
|
||||||
this.taskTimeRange[1] = new Date(endTimeStr)
|
|
||||||
},
|
|
||||||
addTaskToServer(){
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/cloud/record/task/add`,
|
|
||||||
params: {
|
|
||||||
app: this.app,
|
|
||||||
stream: this.stream,
|
|
||||||
mediaServerId: this.mediaServerId,
|
|
||||||
startTime: moment(this.taskTimeRange[0]).format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
endTime: moment(this.taskTimeRange[1]).format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0 ) {
|
|
||||||
that.showTaskBox = false
|
|
||||||
that.getTaskList(false);
|
|
||||||
}else {
|
|
||||||
that.$message.error(res.data.msg);
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleTabClick() {
|
|
||||||
this.getTaskList(this.tabVal === "ended")
|
|
||||||
},
|
|
||||||
getTaskList(isEnd){
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/cloud/record/task/list`,
|
|
||||||
params: {
|
|
||||||
mediaServerId: this.mediaServerId,
|
|
||||||
isEnd: isEnd,
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (isEnd){
|
|
||||||
that.taskListEnded = res.data.data;
|
|
||||||
}else {
|
|
||||||
that.taskListForRuning = res.data.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
goBack(){
|
|
||||||
this.$router.push('/cloudRecord');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.el-slider__runway {
|
|
||||||
background-color:rgba(206, 206, 206, 0.47) !important;
|
|
||||||
}
|
|
||||||
.el-slider__bar {
|
|
||||||
background-color: rgba(153, 153, 153, 0) !important;
|
|
||||||
}
|
|
||||||
.playtime-slider {
|
|
||||||
position: relative;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
.data-picker-true{
|
|
||||||
|
|
||||||
}
|
|
||||||
.data-picker-true:after{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
width: 4px;
|
|
||||||
height: 4px;
|
|
||||||
background-color: #606060;
|
|
||||||
border-radius: 4px;
|
|
||||||
left: 45%;
|
|
||||||
top: 74%;
|
|
||||||
|
|
||||||
}
|
|
||||||
.data-picker-false{
|
|
||||||
|
|
||||||
}
|
|
||||||
.slider-val-box{
|
|
||||||
height: 6px;
|
|
||||||
position: relative;
|
|
||||||
top: -22px;
|
|
||||||
}
|
|
||||||
.slider-val{
|
|
||||||
height: 6px;
|
|
||||||
background-color: #007CFF;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
.record-list-box-box{
|
|
||||||
width: 250px;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.record-list-box{
|
|
||||||
overflow: auto;
|
|
||||||
width: 220px;
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
margin-top: 0px;
|
|
||||||
padding: 1rem 0;
|
|
||||||
background-color: #FFF;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.record-list{
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
background-color: #FFF;
|
|
||||||
|
|
||||||
}
|
|
||||||
.record-list-no-val {
|
|
||||||
position: absolute;
|
|
||||||
color: #9f9f9f;
|
|
||||||
top: 50%;
|
|
||||||
left: 110px;
|
|
||||||
}
|
|
||||||
.record-list-item{
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.record-list-option {
|
|
||||||
width: 10px;
|
|
||||||
float: left;
|
|
||||||
margin-top: 39px;
|
|
||||||
|
|
||||||
}
|
|
||||||
.drawer-box{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-list{
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
background-color: #FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-list-item{
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
margin: 1.5rem 0;
|
|
||||||
}
|
|
||||||
.task-list-item-box{
|
|
||||||
text-align: left;
|
|
||||||
font-size: 13px;
|
|
||||||
color: #555;
|
|
||||||
}
|
|
||||||
.download-btn{
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
cursor: pointer;
|
|
||||||
background: #FFF;
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
border: 1px solid #DCDFE6;
|
|
||||||
border-top-color: rgb(220, 223, 230);
|
|
||||||
border-right-color: rgb(220, 223, 230);
|
|
||||||
border-bottom-color: rgb(220, 223, 230);
|
|
||||||
border-left-color: rgb(220, 223, 230);
|
|
||||||
border-top-color: rgb(220, 223, 230);
|
|
||||||
border-right-color: rgb(220, 223, 230);
|
|
||||||
border-bottom-color: rgb(220, 223, 230);
|
|
||||||
border-left-color: rgb(220, 223, 230);
|
|
||||||
-webkit-appearance: none;
|
|
||||||
text-align: center;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
outline: 0;
|
|
||||||
margin: 0;
|
|
||||||
-webkit-transition: .1s;
|
|
||||||
transition: .1s;
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 7px 14px;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #FFF;
|
|
||||||
background-color: #409EFF;
|
|
||||||
border-color: #409EFF;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
.download-btn:hover{
|
|
||||||
background: #66b1ff;
|
|
||||||
border-color: #66b1ff;
|
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
.time-box{
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,557 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">设备列表</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="initData" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
在线状态:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="initData" v-model="online" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="在线" value="true"></el-option>
|
|
||||||
<el-option label="离线" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加设备
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-info" size="mini" style="margin-right: 1rem;" type="primary" @click="showInfo()">平台信息
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading"
|
|
||||||
@click="getDeviceList()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--设备列表-->
|
|
||||||
<el-table size="medium" :data="deviceList" style="width: 100%;font-size: 12px;" :height="$tableHeght" header-row-class-name="table-header">
|
|
||||||
<el-table-column prop="name" label="名称" min-width="160">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="deviceId" label="设备编号" min-width="160" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="地址" min-width="160" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag v-if="scope.row.hostAddress" size="medium">{{ scope.row.hostAddress }}</el-tag>
|
|
||||||
<el-tag v-if="!scope.row.hostAddress" size="medium">未知</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="manufacturer" label="厂家" min-width="100" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="transport" label="信令传输模式" min-width="100" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="流传输模式" min-width="160" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择" style="width: 120px">
|
|
||||||
<el-option key="UDP" label="UDP" value="UDP"></el-option>
|
|
||||||
<el-option key="TCP-ACTIVE" label="TCP主动模式" value="TCP-ACTIVE"></el-option>
|
|
||||||
<el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="通道数" min-width="100" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<span style="font-size: 1rem">{{scope.row.channelCount}}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.onLine && Vue.prototype.$myServerId !== scope.row.serverId" style="border-color: #ecf1af">在线</el-tag>
|
|
||||||
<el-tag size="medium" v-if="scope.row.onLine && Vue.prototype.$myServerId === scope.row.serverId">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="!scope.row.onLine">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="订阅" min-width="260" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-checkbox label="目录" :checked="scope.row.subscribeCycleForCatalog > 0" @change="(e)=>subscribeForCatalog(scope.row.id, e)"></el-checkbox>
|
|
||||||
<el-checkbox label="位置" :checked="scope.row.subscribeCycleForMobilePosition > 0" @change="(e)=>subscribeForMobilePosition(scope.row.id, e)"></el-checkbox>
|
|
||||||
<el-checkbox label="报警" disabled :checked="scope.row.subscribeCycleForAlarm > 0"></el-checkbox>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="keepaliveTime" label="最近心跳" min-width="140" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="registerTime" label="最近注册" min-width="140">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" min-width="300" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button type="text" size="medium" v-bind:disabled="scope.row.online===0" icon="el-icon-refresh" @click="refDevice(scope.row)"
|
|
||||||
@mouseover="getTooltipContent(scope.row.deviceId)">刷新
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button type="text" size="medium" icon="el-icon-video-camera"
|
|
||||||
@click="showChannelList(scope.row)">通道
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">编辑</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-dropdown @command="(command)=>{moreClick(command, scope.row)}">
|
|
||||||
<el-button size="medium" type="text" >
|
|
||||||
操作<i class="el-icon-arrow-down el-icon--right"></i>
|
|
||||||
</el-button>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item command="delete" style="color: #f56c6c">
|
|
||||||
删除</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="setGuard" v-bind:disabled="!scope.row.onLine">
|
|
||||||
布防</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="resetGuard" v-bind:disabled="!scope.row.onLine">
|
|
||||||
撤防</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="syncBasicParam" v-bind:disabled="!scope.row.onLine">
|
|
||||||
基础配置同步</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
<deviceEdit ref="deviceEdit"></deviceEdit>
|
|
||||||
<syncChannelProgress ref="syncChannelProgress"></syncChannelProgress>
|
|
||||||
<configInfo ref="configInfo"></configInfo>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import deviceEdit from './dialog/deviceEdit.vue'
|
|
||||||
import syncChannelProgress from './dialog/SyncChannelProgress.vue'
|
|
||||||
import configInfo from "./dialog/configInfo.vue";
|
|
||||||
import Vue from "vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'app',
|
|
||||||
components: {
|
|
||||||
configInfo,
|
|
||||||
uiHeader,
|
|
||||||
deviceEdit,
|
|
||||||
syncChannelProgress,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
deviceList: [], //设备列表
|
|
||||||
currentDevice: {}, //当前操作设备对象
|
|
||||||
searchSrt: "",
|
|
||||||
online: null,
|
|
||||||
videoComponentList: [],
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
currentDeviceChannelsLength: 0,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
getDeviceListLoading: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
Vue() {
|
|
||||||
return Vue
|
|
||||||
},
|
|
||||||
getcurrentDeviceChannels: function () {
|
|
||||||
let data = this.currentDevice['channelMap'];
|
|
||||||
let channels = null;
|
|
||||||
if (data) {
|
|
||||||
channels = Object.keys(data).map(key => {
|
|
||||||
return data[key];
|
|
||||||
});
|
|
||||||
this.currentDeviceChannelsLength = channels.length;
|
|
||||||
}
|
|
||||||
return channels;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
this.updateLooper = setInterval(this.getDeviceList, 10000);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$destroy('videojs');
|
|
||||||
clearTimeout(this.updateLooper);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.total= 0;
|
|
||||||
this.getDeviceList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getDeviceList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getDeviceList();
|
|
||||||
},
|
|
||||||
getDeviceList: function () {
|
|
||||||
this.getDeviceListLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/query/devices`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
query: this.searchSrt,
|
|
||||||
status: this.online,
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.deviceList = res.data.data.list;
|
|
||||||
}
|
|
||||||
this.getDeviceListLoading = false;
|
|
||||||
}).catch( (error)=> {
|
|
||||||
console.error(error);
|
|
||||||
this.getDeviceListLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteDevice: function (row) {
|
|
||||||
let msg = "确定删除此设备?"
|
|
||||||
if (row.online !== 0) {
|
|
||||||
msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>"
|
|
||||||
}
|
|
||||||
this.$confirm(msg, '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
center: true,
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'delete',
|
|
||||||
url: `/api/device/query/devices/${row.deviceId}/delete`
|
|
||||||
}).then((res) => {
|
|
||||||
this.getDeviceList();
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
showChannelList: function (row) {
|
|
||||||
this.$router.push(`/channelList/${row.deviceId}/0`);
|
|
||||||
},
|
|
||||||
showDevicePosition: function (row) {
|
|
||||||
this.$router.push(`/map?deviceId=${row.deviceId}`);
|
|
||||||
},
|
|
||||||
|
|
||||||
//gb28181平台对接
|
|
||||||
//刷新设备信息
|
|
||||||
refDevice: function (itemData) {
|
|
||||||
console.log("刷新对应设备:" + itemData.deviceId);
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/device/query/devices/' + itemData.deviceId + '/sync'
|
|
||||||
}).then((res) => {
|
|
||||||
console.log("刷新设备结果:" + JSON.stringify(res));
|
|
||||||
if (res.data.code !== 0) {
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (res.data.data && res.data.data.errorMsg) {
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.data.errorMsg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$refs.syncChannelProgress.openDialog(itemData.deviceId, ()=>{
|
|
||||||
console.log(32322)
|
|
||||||
this.initData()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
that.initData()
|
|
||||||
}).catch((e) => {
|
|
||||||
console.error(e)
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: e,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
getTooltipContent: async function (deviceId) {
|
|
||||||
let result = "";
|
|
||||||
await this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
async: false,
|
|
||||||
url: `/api/device/query/${deviceId}/sync_status/`,
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code == 0) {
|
|
||||||
if (res.data.data.errorMsg !== null) {
|
|
||||||
result = res.data.data.errorMsg
|
|
||||||
} else if (res.data.msg !== null) {
|
|
||||||
result = res.data.msg
|
|
||||||
} else {
|
|
||||||
result = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
transportChange: function (row) {
|
|
||||||
console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode
|
|
||||||
}).then(function (res) {
|
|
||||||
|
|
||||||
}).catch(function (e) {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
edit: function (row) {
|
|
||||||
this.$refs.deviceEdit.openDialog(row, () => {
|
|
||||||
this.$refs.deviceEdit.close();
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "设备修改成功,通道字符集将在下次更新生效",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
setTimeout(this.getDeviceList, 200)
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
add: function () {
|
|
||||||
this.$refs.deviceEdit.openDialog(null, () => {
|
|
||||||
this.$refs.deviceEdit.close();
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "添加成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
setTimeout(this.getDeviceList, 200)
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showInfo: function (){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/server/system/configInfo`,
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.serverId = res.data.data.addOn.serverId;
|
|
||||||
this.$refs.configInfo.openDialog(res.data.data)
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
moreClick: function (command, itemData) {
|
|
||||||
if (command === "setGuard") {
|
|
||||||
this.setGuard(itemData)
|
|
||||||
}else if (command === "resetGuard") {
|
|
||||||
this.resetGuard(itemData)
|
|
||||||
}else if (command === "delete") {
|
|
||||||
this.deleteDevice(itemData)
|
|
||||||
}else if (command === "syncBasicParam") {
|
|
||||||
this.syncBasicParam(itemData)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setGuard: function (itemData) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/control/guard/${itemData.deviceId}/SetGuard`,
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "布防成功"
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error.message
|
|
||||||
})
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetGuard: function (itemData) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/control/guard/${itemData.deviceId}/ResetGuard`,
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "撤防成功"
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error.message
|
|
||||||
})
|
|
||||||
});
|
|
||||||
},
|
|
||||||
subscribeForCatalog: function (data, value) {
|
|
||||||
console.log(data)
|
|
||||||
console.log(value)
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/query/subscribe/catalog`,
|
|
||||||
params: {
|
|
||||||
id: data,
|
|
||||||
cycle: value?60:0
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: value?"订阅成功":"取消订阅成功"
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error.message
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
subscribeForMobilePosition: function (data, value) {
|
|
||||||
console.log(data)
|
|
||||||
console.log(value)
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/query/subscribe/mobile-position`,
|
|
||||||
params: {
|
|
||||||
id: data,
|
|
||||||
cycle: value?60:0,
|
|
||||||
interval: value?5:0
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: value?"订阅成功":"取消订阅成功"
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error.message
|
|
||||||
})
|
|
||||||
});
|
|
||||||
},
|
|
||||||
syncBasicParam: function (data) {
|
|
||||||
console.log(data)
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/config/query/${data.deviceId}/BasicParam`,
|
|
||||||
params: {
|
|
||||||
// channelId: data.deviceId
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: `配置已同步,当前心跳间隔: ${res.data.data.BasicParam.HeartBeatInterval} 心跳间隔:${res.data.data.BasicParam.HeartBeatCount}`
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error.message
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.videoList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item {
|
|
||||||
position: relative;
|
|
||||||
width: 15rem;
|
|
||||||
height: 10rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img:after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
background-image: url("../assets/loading.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-title {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #ffffff;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0.3rem;
|
|
||||||
width: 14.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,547 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div style="width: 100%">
|
|
||||||
<div class="page-header" >
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="goBack" content="国标录像"></el-page-header>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-container>
|
|
||||||
<el-aside width="300px">
|
|
||||||
<div class="record-list-box-box">
|
|
||||||
<el-date-picker size="mini" v-model="chooseDate" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="dateChange()"></el-date-picker>
|
|
||||||
<div class="record-list-box" v-loading="recordsLoading" :style="recordListStyle">
|
|
||||||
<ul v-if="detailFiles.length >0" class="infinite-list record-list" >
|
|
||||||
<li v-for="item in detailFiles" class="infinite-list-item record-list-item" >
|
|
||||||
|
|
||||||
<el-tag v-if="chooseFile != item" @click="checkedFile(item)">
|
|
||||||
<i class="el-icon-video-camera" ></i>
|
|
||||||
{{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}}
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="chooseFile == item" type="danger" >
|
|
||||||
<i class="el-icon-video-camera" ></i>
|
|
||||||
{{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}}
|
|
||||||
</el-tag>
|
|
||||||
<i style="color: #409EFF;margin-left: 5px;" class="el-icon-download" @click="downloadRecord(item)" ></i>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div size="mini" v-if="detailFiles.length ==0" class="record-list-no-val" >暂无数据</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-aside>
|
|
||||||
<el-main style="padding-bottom: 10px;">
|
|
||||||
<div class="playBox" :style="playerBoxStyle">
|
|
||||||
<player ref="recordVideoPlayer"
|
|
||||||
:videoUrl="videoUrl"
|
|
||||||
:error="videoError"
|
|
||||||
:message="videoError"
|
|
||||||
:hasAudio="hasAudio"
|
|
||||||
style="max-height: 100%"
|
|
||||||
:height="playerHeight"
|
|
||||||
fluent autoplay live ></player>
|
|
||||||
</div>
|
|
||||||
<div class="player-option-box">
|
|
||||||
<div>
|
|
||||||
<el-button-group >
|
|
||||||
<el-time-picker
|
|
||||||
size="mini"
|
|
||||||
is-range
|
|
||||||
align="left"
|
|
||||||
v-model="timeRange"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
range-separator="至"
|
|
||||||
start-placeholder="开始时间"
|
|
||||||
end-placeholder="结束时间"
|
|
||||||
@change="timePickerChange"
|
|
||||||
placeholder="选择时间范围">
|
|
||||||
</el-time-picker>
|
|
||||||
</el-button-group>
|
|
||||||
|
|
||||||
<el-button-group >
|
|
||||||
<el-button size="mini" class="iconfont icon-zanting" title="暂停" @click="gbPause()"></el-button>
|
|
||||||
<el-button size="mini" class="iconfont icon-kaishi" title="开始" @click="gbPlay()"></el-button>
|
|
||||||
<el-dropdown size="mini" title="播放倍速" @command="gbScale">
|
|
||||||
<el-button size="mini">
|
|
||||||
倍速 <i class="el-icon-arrow-down el-icon--right"></i>
|
|
||||||
</el-button>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item v-for="(item,index) in downloadSpeedArray" :key="index" :command="item">{{item}}倍速</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
<el-button size="mini" class="iconfont icon-xiazai1" title="下载选定录像" @click="downloadRecord()"></el-button>
|
|
||||||
<el-button v-if="sliderMIn === 0 && sliderMax === 86400" size="mini" class="iconfont icon-slider" title="放大滑块" @click="setSliderFit()"></el-button>
|
|
||||||
<el-button v-if="sliderMIn !== 0 || sliderMax !== 86400" size="mini" class="iconfont icon-slider-right" title="恢复滑块" @click="setSliderFit()"></el-button>
|
|
||||||
</el-button-group>
|
|
||||||
</div>
|
|
||||||
<el-slider
|
|
||||||
class="playtime-slider"
|
|
||||||
v-model="playTime"
|
|
||||||
id="playtimeSlider"
|
|
||||||
:disabled="detailFiles.length === 0"
|
|
||||||
:min="sliderMIn"
|
|
||||||
:max="sliderMax"
|
|
||||||
:range="true"
|
|
||||||
:format-tooltip="playTimeFormat"
|
|
||||||
@change="playTimeChange"
|
|
||||||
:marks="playTimeSliderMarks">
|
|
||||||
</el-slider>
|
|
||||||
<div class="slider-val-box">
|
|
||||||
<div class="slider-val" v-for="item of detailFiles" :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
<recordDownload ref="recordDownload"></recordDownload>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import player from './common/jessibuca.vue'
|
|
||||||
import moment from 'moment'
|
|
||||||
import recordDownload from './dialog/recordDownload.vue'
|
|
||||||
export default {
|
|
||||||
name: 'app',
|
|
||||||
components: {
|
|
||||||
uiHeader, player,recordDownload
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
deviceId: this.$route.params.deviceId,
|
|
||||||
channelId: this.$route.params.channelId,
|
|
||||||
downloadSpeedArray: [0.25, 0.5, 1, 2, 4],
|
|
||||||
recordsLoading: false,
|
|
||||||
streamId: "",
|
|
||||||
hasAudio: false,
|
|
||||||
detailFiles: [],
|
|
||||||
chooseDate: null,
|
|
||||||
videoUrl: null,
|
|
||||||
chooseFile: null,
|
|
||||||
streamInfo: null,
|
|
||||||
app: null,
|
|
||||||
mediaServerId: null,
|
|
||||||
ssrc: null,
|
|
||||||
|
|
||||||
sliderMIn: 0,
|
|
||||||
sliderMax: 86400,
|
|
||||||
autoPlay: true,
|
|
||||||
taskUpdate: null,
|
|
||||||
tabVal: "running",
|
|
||||||
recordListStyle: {
|
|
||||||
height: this.winHeight + "px",
|
|
||||||
overflow: "auto",
|
|
||||||
margin: "10px auto 10px auto"
|
|
||||||
},
|
|
||||||
playerBoxStyle: {
|
|
||||||
"margin": "0 auto 20px auto",
|
|
||||||
"height": this.winHeight + "px",
|
|
||||||
},
|
|
||||||
playerHeight: this.winHeight,
|
|
||||||
winHeight: window.innerHeight - 240,
|
|
||||||
playTime: null,
|
|
||||||
timeRange: null,
|
|
||||||
startTime: null,
|
|
||||||
endTime: null,
|
|
||||||
playTimeSliderMarks: {
|
|
||||||
0: "00:00",
|
|
||||||
3600: "01:00",
|
|
||||||
7200: "02:00",
|
|
||||||
10800: "03:00",
|
|
||||||
14400: "04:00",
|
|
||||||
18000: "05:00",
|
|
||||||
21600: "06:00",
|
|
||||||
25200: "07:00",
|
|
||||||
28800: "08:00",
|
|
||||||
32400: "09:00",
|
|
||||||
36000: "10:00",
|
|
||||||
39600: "11:00",
|
|
||||||
43200: "12:00",
|
|
||||||
46800: "13:00",
|
|
||||||
50400: "14:00",
|
|
||||||
54000: "15:00",
|
|
||||||
57600: "16:00",
|
|
||||||
61200: "17:00",
|
|
||||||
64800: "18:00",
|
|
||||||
68400: "19:00",
|
|
||||||
72000: "20:00",
|
|
||||||
75600: "21:00",
|
|
||||||
79200: "22:00",
|
|
||||||
82800: "23:00",
|
|
||||||
86400: "24:00",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.recordListStyle.height = this.winHeight + "px";
|
|
||||||
this.playerBoxStyle["height"] = this.winHeight + "px";
|
|
||||||
this.chooseDate = moment().format('YYYY-MM-DD')
|
|
||||||
this.dateChange();
|
|
||||||
this.getDownloadSpeedArray()
|
|
||||||
window.addEventListener('beforeunload', this.stopPlayRecord)
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$destroy('recordVideoPlayer');
|
|
||||||
window.removeEventListener('beforeunload', this.stopPlayRecord)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
dateChange(){
|
|
||||||
if (!this.chooseDate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setTime(this.chooseDate + " 00:00:00", this.chooseDate + " 23:59:59");
|
|
||||||
this.recordsLoading = true;
|
|
||||||
this.detailFiles = [];
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' + this.endTime
|
|
||||||
}).then((res)=>{
|
|
||||||
this.recordsLoading = false;
|
|
||||||
if(res.data.code === 0) {
|
|
||||||
// 处理时间信息
|
|
||||||
this.detailFiles = res.data.data.recordList;
|
|
||||||
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((e)=> {
|
|
||||||
this.recordsLoading = false;
|
|
||||||
// that.videoHistory.searchHistoryResult = falsificationData.recordData;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
moment: function (v) {
|
|
||||||
return moment(v)
|
|
||||||
},
|
|
||||||
setTime: function (startTime, endTime){
|
|
||||||
this.startTime = startTime;
|
|
||||||
this.endTime = endTime;
|
|
||||||
let start = (new Date(this.startTime).getTime() - new Date(this.chooseDate + " 00:00:00").getTime())/1000;
|
|
||||||
let end = (new Date(this.endTime).getTime() - new Date(this.chooseDate + " 00:00:00").getTime())/1000;
|
|
||||||
console.log(start)
|
|
||||||
console.log(end)
|
|
||||||
this.playTime = [start, end];
|
|
||||||
this.timeRange = [startTime, endTime];
|
|
||||||
},
|
|
||||||
videoError: function (e) {
|
|
||||||
console.log("播放器错误:" + JSON.stringify(e));
|
|
||||||
},
|
|
||||||
checkedFile(file){
|
|
||||||
this.chooseFile = file;
|
|
||||||
this.setTime(file.startTime, file.endTime);
|
|
||||||
// 开始回放
|
|
||||||
this.playRecord()
|
|
||||||
},
|
|
||||||
playRecord: function () {
|
|
||||||
|
|
||||||
if (this.streamId !== "") {
|
|
||||||
this.stopPlayRecord(()=> {
|
|
||||||
this.streamId = "";
|
|
||||||
this.playRecord();
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' +
|
|
||||||
this.endTime
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.streamInfo = res.data.data;
|
|
||||||
this.app = this.streamInfo.app;
|
|
||||||
this.streamId = this.streamInfo.stream;
|
|
||||||
this.mediaServerId = this.streamInfo.mediaServerId;
|
|
||||||
this.ssrc = this.streamInfo.ssrc;
|
|
||||||
this.videoUrl = this.getUrlByStreamInfo();
|
|
||||||
this.hasAudio = this.streamInfo.tracks && this.streamInfo.tracks.length > 1
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getDownloadSpeedArray(){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/device/query/channel/one',
|
|
||||||
params: {
|
|
||||||
deviceId: this.deviceId,
|
|
||||||
channelDeviceId: this.channelId,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0 && res.data.data.downloadSpeed) {
|
|
||||||
let speedArray = res.data.data.downloadSpeed.split('/');
|
|
||||||
|
|
||||||
speedArray.forEach(item => {
|
|
||||||
if (parseInt(item) > 4) {
|
|
||||||
this.downloadSpeedArray.push(parseInt(item));
|
|
||||||
console.log(this.downloadSpeedArray);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
gbPlay(){
|
|
||||||
console.log('前端控制:播放');
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/playback/resume/' + this.streamId
|
|
||||||
}).then((res)=> {
|
|
||||||
this.$refs["recordVideoPlayer"].play(this.videoUrl)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
gbPause(){
|
|
||||||
console.log('前端控制:暂停');
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/playback/pause/' + this.streamId
|
|
||||||
}).then(function (res) {});
|
|
||||||
},
|
|
||||||
gbScale(command){
|
|
||||||
console.log('前端控制:倍速 ' + command);
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/playback/speed/${this.streamId }/${command}`
|
|
||||||
}).then(function (res) {});
|
|
||||||
},
|
|
||||||
downloadRecord: function (row) {
|
|
||||||
if (!row) {
|
|
||||||
let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[0]*1000).format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[1]*1000).format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
console.log(startTimeStr);
|
|
||||||
console.log(endTimeStr);
|
|
||||||
row = {
|
|
||||||
startTime: startTimeStr,
|
|
||||||
endTime: endTimeStr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.streamId !== "") {
|
|
||||||
this.stopPlayRecord(()=> {
|
|
||||||
this.streamId = "";
|
|
||||||
this.downloadRecord(row);
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
|
|
||||||
row.endTime + '&downloadSpeed='+ this.downloadSpeedArray[this.downloadSpeedArray.length - 1]
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
let streamInfo = res.data.data;
|
|
||||||
this.$refs.recordDownload.openDialog(this.deviceId, this.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId);
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stopDownloadRecord: function (callback) {
|
|
||||||
this.$refs["recordVideoPlayer"].pause();
|
|
||||||
this.videoUrl = '';
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
|
|
||||||
}).then((res)=> {
|
|
||||||
if (callback) callback(res)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
stopPlayRecord: function (callback) {
|
|
||||||
console.log("停止录像回放")
|
|
||||||
if (this.streamId !== "") {
|
|
||||||
this.$refs["recordVideoPlayer"].pause();
|
|
||||||
this.videoUrl = '';
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
|
|
||||||
}).then(function (res) {
|
|
||||||
if (callback) callback()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
getDataWidth(item){
|
|
||||||
let timeForFile = this.getTimeForFile(item);
|
|
||||||
let result = (timeForFile[2])/((this.sliderMax - this.sliderMIn)*1000)
|
|
||||||
return result*100
|
|
||||||
},
|
|
||||||
getDataLeft(item){
|
|
||||||
let timeForFile = this.getTimeForFile(item);
|
|
||||||
let differenceTime = timeForFile[0].getTime() - new Date(this.chooseDate + " 00:00:00").getTime()
|
|
||||||
return parseFloat((differenceTime - this.sliderMIn * 1000)/((this.sliderMax - this.sliderMIn)*1000))*100 ;
|
|
||||||
},
|
|
||||||
getUrlByStreamInfo(){
|
|
||||||
if (location.protocol === "https:") {
|
|
||||||
this.videoUrl = this.streamInfo["wss_flv"]
|
|
||||||
}else {
|
|
||||||
this.videoUrl = this.streamInfo["ws_flv"]
|
|
||||||
}
|
|
||||||
return this.videoUrl;
|
|
||||||
|
|
||||||
},
|
|
||||||
timePickerChange: function (val){
|
|
||||||
this.setTime(val[0], val[1])
|
|
||||||
},
|
|
||||||
playTimeChange(val){
|
|
||||||
console.log(val)
|
|
||||||
|
|
||||||
let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[0]*1000).format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[1]*1000).format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
|
|
||||||
this.setTime(startTimeStr, endTimeStr)
|
|
||||||
|
|
||||||
this.playRecord();
|
|
||||||
},
|
|
||||||
setSliderFit() {
|
|
||||||
if (this.sliderMIn === 0 && this.sliderMax === 86400) {
|
|
||||||
if (this.detailFiles.length > 0){
|
|
||||||
let timeForFile = this.getTimeForFile(this.detailFiles[0]);
|
|
||||||
let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]);
|
|
||||||
let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
|
|
||||||
let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
|
|
||||||
|
|
||||||
this.playTime = parseInt(timeNum/1000)
|
|
||||||
this.sliderMIn = parseInt(timeNum/1000 - timeNum/1000%(60*60))
|
|
||||||
this.sliderMax = parseInt(lastTimeNum/1000 - lastTimeNum/1000%(60*60)) + 60*60
|
|
||||||
|
|
||||||
this.playTime = [this.sliderMIn, this.sliderMax];
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.sliderMIn = 0;
|
|
||||||
this.sliderMax = 86400;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getTimeForFile(file){
|
|
||||||
let startTime = new Date(file.startTime);
|
|
||||||
let endTime = new Date(file.endTime);
|
|
||||||
return [startTime, endTime, endTime.getTime() - startTime.getTime()];
|
|
||||||
},
|
|
||||||
playTimeFormat(val){
|
|
||||||
let h = parseInt(val/3600);
|
|
||||||
let m = parseInt((val - h*3600)/60);
|
|
||||||
let s = parseInt(val - h*3600 - m*60);
|
|
||||||
|
|
||||||
let hStr = h;
|
|
||||||
let mStr = m;
|
|
||||||
let sStr = s;
|
|
||||||
if (h < 10) {
|
|
||||||
hStr = "0" + hStr;
|
|
||||||
}
|
|
||||||
if (m < 10) {
|
|
||||||
mStr = "0" + mStr;s
|
|
||||||
}
|
|
||||||
if (s < 10) {
|
|
||||||
sStr = "0" + sStr;
|
|
||||||
}
|
|
||||||
return hStr + ":" + mStr + ":" + sStr
|
|
||||||
},
|
|
||||||
goBack(){
|
|
||||||
// 如果正在进行录像回放则,发送停止
|
|
||||||
if (this.streamId !== "") {
|
|
||||||
this.stopPlayRecord(()=> {
|
|
||||||
this.streamId = "";
|
|
||||||
})
|
|
||||||
}
|
|
||||||
window.history.go(-1);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.el-slider__runway {
|
|
||||||
background-color:rgba(206, 206, 206, 0.47) !important;
|
|
||||||
}
|
|
||||||
.el-slider__bar {
|
|
||||||
background-color: rgba(153, 153, 153, 0) !important;
|
|
||||||
}
|
|
||||||
.playtime-slider {
|
|
||||||
position: relative;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
.data-picker-true{
|
|
||||||
|
|
||||||
}
|
|
||||||
.data-picker-true:after{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
width: 4px;
|
|
||||||
height: 4px;
|
|
||||||
background-color: #606060;
|
|
||||||
border-radius: 4px;
|
|
||||||
left: 45%;
|
|
||||||
top: 74%;
|
|
||||||
|
|
||||||
}
|
|
||||||
.data-picker-false{
|
|
||||||
|
|
||||||
}
|
|
||||||
.slider-val-box{
|
|
||||||
height: 6px;
|
|
||||||
position: relative;
|
|
||||||
top: -22px;
|
|
||||||
}
|
|
||||||
.slider-val{
|
|
||||||
height: 6px;
|
|
||||||
background-color: #007CFF;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
.record-list-box-box{
|
|
||||||
width: 250px;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.record-list-box{
|
|
||||||
overflow: auto;
|
|
||||||
width: 220px;
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
margin-top: 0px;
|
|
||||||
padding: 1rem 0;
|
|
||||||
background-color: #FFF;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.record-list{
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
background-color: #FFF;
|
|
||||||
|
|
||||||
}
|
|
||||||
.record-list-no-val {
|
|
||||||
position: absolute;
|
|
||||||
color: #9f9f9f;
|
|
||||||
top: 50%;
|
|
||||||
left: 110px;
|
|
||||||
}
|
|
||||||
.record-list-item{
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.record-list-option {
|
|
||||||
width: 10px;
|
|
||||||
float: left;
|
|
||||||
margin-top: 39px;
|
|
||||||
|
|
||||||
}
|
|
||||||
.player-option-box{
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,250 +0,0 @@
|
|||||||
/**
|
|
||||||
* 经纬度转换
|
|
||||||
*/
|
|
||||||
export default {
|
|
||||||
PI: 3.1415926535897932384626,
|
|
||||||
//PI: 3.14159265358979324,
|
|
||||||
x_pi: (3.1415926535897932384626 * 3000.0) / 180.0,
|
|
||||||
delta: function (lat, lng) {
|
|
||||||
// Krasovsky 1940
|
|
||||||
//
|
|
||||||
// a = 6378245.0, 1/f = 298.3
|
|
||||||
// b = a * (1 - f)
|
|
||||||
// ee = (a^2 - b^2) / a^2;
|
|
||||||
var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
|
|
||||||
var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
|
|
||||||
var dLat = this.transformLat(lng - 105.0, lat - 35.0);
|
|
||||||
var dLng = this.transformLng(lng - 105.0, lat - 35.0);
|
|
||||||
var radLat = (lat / 180.0) * this.PI;
|
|
||||||
var magic = Math.sin(radLat);
|
|
||||||
magic = 1 - ee * magic * magic;
|
|
||||||
var sqrtMagic = Math.sqrt(magic);
|
|
||||||
dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * this.PI);
|
|
||||||
dLng = (dLng * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * this.PI);
|
|
||||||
return {
|
|
||||||
lat: dLat,
|
|
||||||
lng: dLng
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* WGS-84 to GCJ-02 GPS坐标转中国坐标
|
|
||||||
* @param {number} wgsLat GPS纬度
|
|
||||||
* @param {number} wgsLng GPS经度
|
|
||||||
* @return {object} 返回中国坐标经纬度对象
|
|
||||||
*/
|
|
||||||
GPSToChina: function (wgsLat, wgsLng) {
|
|
||||||
if (this.outOfChina(wgsLat, wgsLng)) return {
|
|
||||||
lat: wgsLat,
|
|
||||||
lng: wgsLng
|
|
||||||
};
|
|
||||||
var d = this.delta(wgsLat, wgsLng);
|
|
||||||
return {
|
|
||||||
lat: Number(wgsLat) + Number(d.lat),
|
|
||||||
lng: Number(wgsLng) + Number(d.lng)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* GCJ-02 to WGS-84 中国标准坐标转GPS坐标
|
|
||||||
* @param {number} gcjLat 中国标准坐标纬度
|
|
||||||
* @param {number} gcjLng 中国标准坐标经度
|
|
||||||
* @return {object} 返回GPS经纬度对象
|
|
||||||
*/
|
|
||||||
chinaToGPS: function (gcjLat, gcjLng) {
|
|
||||||
if (this.outOfChina(gcjLat, gcjLng)) return {
|
|
||||||
lat: gcjLat,
|
|
||||||
lng: gcjLng
|
|
||||||
};
|
|
||||||
var d = this.delta(gcjLat, gcjLng);
|
|
||||||
return {
|
|
||||||
lat: Number(gcjLat) - Number(d.lat),
|
|
||||||
lng: Number(gcjLng) - Number(d.lng)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* GCJ-02 to WGS-84 exactly 中国标准坐标转GPS坐标(精确)
|
|
||||||
* @param {number} gcjLat 中国标准坐标纬度
|
|
||||||
* @param {number} gcjLng 中国标准坐标经度
|
|
||||||
* @return {object} 返回GPS经纬度对象(精确)
|
|
||||||
*/
|
|
||||||
chinaToGPSExact: function (gcjLat, gcjLng) {
|
|
||||||
var initDelta = 0.01;
|
|
||||||
var threshold = 0.000000001;
|
|
||||||
var dLat = initDelta,
|
|
||||||
dLng = initDelta;
|
|
||||||
var mLat = gcjLat - dLat,
|
|
||||||
mLng = gcjLng - dLng;
|
|
||||||
var pLat = gcjLat + dLat,
|
|
||||||
pLng = gcjLng + dLng;
|
|
||||||
var wgsLat,
|
|
||||||
wgsLng,
|
|
||||||
i = 0;
|
|
||||||
while (1) {
|
|
||||||
wgsLat = (mLat + pLat) / 2;
|
|
||||||
wgsLng = (mLng + pLng) / 2;
|
|
||||||
var tmp = this.gcj_encrypt(wgsLat, wgsLng);
|
|
||||||
dLat = tmp.lat - gcjLat;
|
|
||||||
dLng = tmp.lng - gcjLng;
|
|
||||||
if (Math.abs(dLat) < threshold && Math.abs(dLng) < threshold) break;
|
|
||||||
|
|
||||||
if (dLat > 0) pLat = wgsLat;
|
|
||||||
else mLat = wgsLat;
|
|
||||||
if (dLng > 0) pLng = wgsLng;
|
|
||||||
else mLng = wgsLng;
|
|
||||||
|
|
||||||
if (++i > 10000) break;
|
|
||||||
}
|
|
||||||
//console.log(i);
|
|
||||||
return {
|
|
||||||
lat: wgsLat,
|
|
||||||
lng: wgsLng
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* GCJ-02 to BD-09 中国标准坐标转百度坐标(精确)
|
|
||||||
* @param {number} gcjLat 中国标准坐标纬度
|
|
||||||
* @param {number} gcjLng 中国标准坐标经度
|
|
||||||
* @return {object} 返回百度经纬度对象
|
|
||||||
*/
|
|
||||||
chinaToBaidu: function (gcjLat, gcjLng) {
|
|
||||||
var x = gcjLng,
|
|
||||||
y = gcjLat;
|
|
||||||
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);
|
|
||||||
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);
|
|
||||||
var bdLng = z * Math.cos(theta) + 0.0065;
|
|
||||||
var bdLat = z * Math.sin(theta) + 0.006;
|
|
||||||
return {
|
|
||||||
lat: bdLat,
|
|
||||||
lng: bdLng
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* BD-09 to GCJ-02 百度坐标转中国标准坐标
|
|
||||||
* @param {number} bdLat 百度坐标纬度
|
|
||||||
* @param {number} bdLng 百度坐标经度
|
|
||||||
* @return {object} 返回中国标准经纬度对象
|
|
||||||
*/
|
|
||||||
baiduToChina: function (bdLat, bdLng) {
|
|
||||||
var x = bdLng - 0.0065,
|
|
||||||
y = bdLat - 0.006;
|
|
||||||
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);
|
|
||||||
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);
|
|
||||||
var gcjLng = z * Math.cos(theta);
|
|
||||||
var gcjLat = z * Math.sin(theta);
|
|
||||||
return {
|
|
||||||
lat: gcjLat,
|
|
||||||
lng: gcjLng
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* BD-09 to GCJ-02 百度坐标转gps坐标
|
|
||||||
* @param {number} bdLat 百度坐标纬度
|
|
||||||
* @param {number} bdLng 百度坐标经度
|
|
||||||
* @return {object} 返回gps经纬度对象
|
|
||||||
*/
|
|
||||||
baiduToGPS: function (bdLat, bdLng) {
|
|
||||||
let china = this.baiduToChina(bdLat, bdLng);
|
|
||||||
return this.chinaToGPS(china.lat, china.lng);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* WGS-84 to to BD-09 GPS坐标转Baidu坐标
|
|
||||||
* @param {number} gpsLat GPS纬度
|
|
||||||
* @param {number} gpsLng GPS经度
|
|
||||||
* @return {object} 返回百度经纬度对象
|
|
||||||
*/
|
|
||||||
GPSToBaidu: function (gpsLat, gpsLng) {
|
|
||||||
var china = this.GPSToChina(gpsLat, gpsLng);
|
|
||||||
return this.chinaToBaidu(china.lat, china.lng);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* WGS-84 to Web mercator GPS坐标转墨卡托坐标
|
|
||||||
* @param {number} wgsLat GPS纬度
|
|
||||||
* @param {number} wgsLng GPS经度
|
|
||||||
* @return {object} 返回墨卡托经纬度对象
|
|
||||||
*/
|
|
||||||
GPSToMercator: function (wgsLat, wgsLng) {
|
|
||||||
var x = (wgsLng * 20037508.34) / 180;
|
|
||||||
var y = Math.log(Math.tan(((90 + wgsLat) * this.PI) / 360)) / (this.PI / 180);
|
|
||||||
y = (y * 20037508.34) / 180;
|
|
||||||
return {
|
|
||||||
lat: y,
|
|
||||||
lng: x
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
if ((Math.abs(wgsLng) > 180 || Math.abs(wgsLat) > 90))
|
|
||||||
return null;
|
|
||||||
var x = 6378137.0 * wgsLng * 0.017453292519943295;
|
|
||||||
var a = wgsLat * 0.017453292519943295;
|
|
||||||
var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
|
|
||||||
return {'lat' : y, 'lng' : x};
|
|
||||||
//*/
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Web mercator to WGS-84 墨卡托坐标转GPS坐标
|
|
||||||
* @param {number} mercatorLat 墨卡托纬度
|
|
||||||
* @param {number} mercatorLng 墨卡托经度
|
|
||||||
* @return {object} 返回GPS经纬度对象
|
|
||||||
*/
|
|
||||||
mercatorToGPS: function (mercatorLat, mercatorLng) {
|
|
||||||
var x = (mercatorLng / 20037508.34) * 180;
|
|
||||||
var y = (mercatorLat / 20037508.34) * 180;
|
|
||||||
y = (180 / this.PI) * (2 * Math.atan(Math.exp((y * this.PI) / 180)) - this.PI / 2);
|
|
||||||
return {
|
|
||||||
lat: y,
|
|
||||||
lng: x
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
if (Math.abs(mercatorLng) < 180 && Math.abs(mercatorLat) < 90)
|
|
||||||
return null;
|
|
||||||
if ((Math.abs(mercatorLng) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892))
|
|
||||||
return null;
|
|
||||||
var a = mercatorLng / 6378137.0 * 57.295779513082323;
|
|
||||||
var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0);
|
|
||||||
var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323;
|
|
||||||
return {'lat' : y, 'lng' : x};
|
|
||||||
//*/
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 两点之间的距离
|
|
||||||
* @param {number} latA 起点纬度
|
|
||||||
* @param {number} lngA 起点经度
|
|
||||||
* @param {number} latB 终点纬度
|
|
||||||
* @param {number} lngB 终点经度
|
|
||||||
* @return {number} 返回距离(米)
|
|
||||||
*/
|
|
||||||
distance: function (latA, lngA, latB, lngB) {
|
|
||||||
var earthR = 6371000;
|
|
||||||
var x = Math.cos((latA * this.PI) / 180) * Math.cos((latB * this.PI) / 180) * Math.cos(((lngA - lngB) * this.PI) / 180);
|
|
||||||
var y = Math.sin((latA * this.PI) / 180) * Math.sin((latB * this.PI) / 180);
|
|
||||||
var s = x + y;
|
|
||||||
if (s > 1) s = 1;
|
|
||||||
if (s < -1) s = -1;
|
|
||||||
var alpha = Math.acos(s);
|
|
||||||
var distance = alpha * earthR;
|
|
||||||
return distance;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 是否在中国之外
|
|
||||||
* @param {number} lat 纬度
|
|
||||||
* @param {number} lng 经度
|
|
||||||
* @return {boolean]} 返回结果真或假
|
|
||||||
*/
|
|
||||||
outOfChina: function (lat, lng) {
|
|
||||||
if (lat < 72.004 || lat > 137.8347) return true;
|
|
||||||
if (lng < 0.8293 || lng > 55.8271) return true;
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
transformLat: function (x, y) {
|
|
||||||
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
||||||
ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0;
|
|
||||||
ret += ((20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin((y / 3.0) * this.PI)) * 2.0) / 3.0;
|
|
||||||
ret += ((160.0 * Math.sin((y / 12.0) * this.PI) + 320 * Math.sin((y * this.PI) / 30.0)) * 2.0) / 3.0;
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
transformLng: function (x, y) {
|
|
||||||
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
||||||
ret += ((20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0) / 3.0;
|
|
||||||
ret += ((20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin((x / 3.0) * this.PI)) * 2.0) / 3.0;
|
|
||||||
ret += ((150.0 * Math.sin((x / 12.0) * this.PI) + 300.0 * Math.sin((x / 30.0) * this.PI)) * 2.0) / 3.0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="login" id="login">
|
|
||||||
<div class="limiter">
|
|
||||||
<div class="container-login100">
|
|
||||||
<div class="wrap-login100">
|
|
||||||
<span class="login100-form-title p-b-26">WVP视频平台</span>
|
|
||||||
<span class="login100-form-title p-b-48">
|
|
||||||
<i class="fa fa-video-camera"></i>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div class="wrap-input100 validate-input" data-validate = "Valid email is: a@b.c">
|
|
||||||
<input :class="'input100 ' + (username==''?'':'has-val')" type="text" v-model="username" name="username">
|
|
||||||
<span class="focus-input100" data-placeholder="用户名"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="wrap-input100 validate-input" data-validate="Enter password">
|
|
||||||
<span class="btn-show-pass">
|
|
||||||
<i :class="'fa ' + (!showPassword?'fa-eye':'fa-eye-slash')" @click="showPassword = !showPassword"></i>
|
|
||||||
</span>
|
|
||||||
<input :class="'input100 ' + (password==''?'':'has-val')" :type="(!showPassword?'password':'text')" v-model="password" name="password">
|
|
||||||
<span class="focus-input100" data-placeholder="密码"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container-login100-form-btn">
|
|
||||||
<div class="wrap-login100-form-btn" :class="{'login-loading': isLoging}" v-loading="isLoging" element-loading-background="rgb(0 0 0 / 0%);" element-loading-custom-class="login-loading-class">
|
|
||||||
<div class="login100-form-bgbtn"></div>
|
|
||||||
<button class="login100-form-btn" @click="login">登录</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import userService from "./service/UserService";
|
|
||||||
export default {
|
|
||||||
name: 'Login',
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
isLoging: false,
|
|
||||||
showPassword: false,
|
|
||||||
loginLoading: false,
|
|
||||||
username: '',
|
|
||||||
password: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created(){
|
|
||||||
var that = this;
|
|
||||||
document.onkeydown = function(e) {
|
|
||||||
var key = window.event.keyCode;
|
|
||||||
if (key == 13) {
|
|
||||||
that.login();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods:{
|
|
||||||
|
|
||||||
//登录逻辑
|
|
||||||
login(){
|
|
||||||
if(this.username!='' && this.password!=''){
|
|
||||||
this.toLogin();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//登录请求
|
|
||||||
toLogin(){
|
|
||||||
//需要想后端发送的登录参数
|
|
||||||
let loginParam = {
|
|
||||||
username: this.username,
|
|
||||||
password: crypto.createHash('md5').update(this.password, "utf8").digest('hex')
|
|
||||||
}
|
|
||||||
var that = this;
|
|
||||||
//设置在登录状态
|
|
||||||
this.isLoging = true;
|
|
||||||
let timeoutTask = setTimeout(()=>{
|
|
||||||
that.$message.error("登录超时");
|
|
||||||
that.isLoging = false;
|
|
||||||
}, 1000)
|
|
||||||
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:"/api/user/login",
|
|
||||||
params: loginParam
|
|
||||||
}).then(function (res) {
|
|
||||||
window.clearTimeout(timeoutTask)
|
|
||||||
console.log(res);
|
|
||||||
console.log("登录成功");
|
|
||||||
if (res.data.code === 0 ) {
|
|
||||||
userService.setUser(res.data.data)
|
|
||||||
//登录成功后
|
|
||||||
that.cancelEnterkeyDefaultAction();
|
|
||||||
that.$router.push('/');
|
|
||||||
}else{
|
|
||||||
that.isLoging = false;
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '登录失败,用户名或密码错误',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error)
|
|
||||||
window.clearTimeout(timeoutTask)
|
|
||||||
that.$message.error(error.response.data.msg);
|
|
||||||
that.isLoging = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
cancelEnterkeyDefaultAction: function() {
|
|
||||||
document.onkeydown = function(e) {
|
|
||||||
var key = window.event.keyCode;
|
|
||||||
if (key == 13) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
@ -1,189 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="mediaServerManger" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">节点列表</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-row :gutter="12">
|
|
||||||
<el-col :span="num" v-for="item in mediaServerList" :key="item.id">
|
|
||||||
<el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card">
|
|
||||||
<div v-if="item.type === 'zlm'" class="card-img-zlm"></div>
|
|
||||||
<div v-if="item.type === 'abl'" class="card-img-abl"></div>
|
|
||||||
<div style="padding: 14px;text-align: left">
|
|
||||||
<span style="font-size: 16px">{{item.id}}</span>
|
|
||||||
<el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button>
|
|
||||||
<el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">查看</el-button>
|
|
||||||
<el-button v-if="!item.defaultServer" icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">移除</el-button>
|
|
||||||
<div style="margin-top: 13px; line-height: 12px; ">
|
|
||||||
<span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span>
|
|
||||||
<span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i>
|
|
||||||
<i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i>
|
|
||||||
<i v-if="item.defaultServer" class="server-card-default" >默认</i>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import MediaServer from './service/MediaServer'
|
|
||||||
import mediaServerEdit from './dialog/MediaServerEdit'
|
|
||||||
export default {
|
|
||||||
name: 'mediaServerManger',
|
|
||||||
components: {
|
|
||||||
uiHeader,mediaServerEdit
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
mediaServerObj : new MediaServer(),
|
|
||||||
mediaServerList: [], //设备列表
|
|
||||||
winHeight: window.innerHeight - 200,
|
|
||||||
updateLooper: false,
|
|
||||||
currentPage:1,
|
|
||||||
count:15,
|
|
||||||
num: this.getNumberByWidth(),
|
|
||||||
total:0,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
this.updateLooper = setInterval(this.initData, 2000);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
clearTimeout(this.updateLooper);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function() {
|
|
||||||
this.getServerList()
|
|
||||||
},
|
|
||||||
currentChange: function(val){
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getServerList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function(val){
|
|
||||||
this.count = val;
|
|
||||||
this.getServerList();
|
|
||||||
},
|
|
||||||
getServerList: function(){
|
|
||||||
this.mediaServerObj.getMediaServerList((data)=>{
|
|
||||||
this.mediaServerList = data.data;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
add: function (){
|
|
||||||
this.$refs.mediaServerEdit.openDialog(null, this.initData)
|
|
||||||
},
|
|
||||||
edit: function (row){
|
|
||||||
this.$refs.mediaServerEdit.openDialog(row, this.initData)
|
|
||||||
},
|
|
||||||
del: function (row){
|
|
||||||
this.$confirm('确认删除此节点?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.mediaServerObj.delete(row.id, (data)=>{
|
|
||||||
if (data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
type: 'success',
|
|
||||||
message: '删除成功!'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
getNumberByWidth(){
|
|
||||||
let candidateNums = [1, 2, 3, 4, 6, 8, 12, 24]
|
|
||||||
let clientWidth = window.innerWidth - 30;
|
|
||||||
let interval = 20;
|
|
||||||
let itemWidth = 360;
|
|
||||||
let num = (clientWidth + interval)/(itemWidth + interval)
|
|
||||||
let result = Math.ceil(24/num);
|
|
||||||
let resultVal = 24;
|
|
||||||
for (let i = 0; i < candidateNums.length; i++) {
|
|
||||||
let value = candidateNums[i]
|
|
||||||
if (i + 1 >= candidateNums.length) {
|
|
||||||
return 24;
|
|
||||||
}
|
|
||||||
if (value <= result && candidateNums[i + 1] > result ) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultVal;
|
|
||||||
},
|
|
||||||
dateFormat: function(/** timestamp=0 **/) {
|
|
||||||
var ts = arguments[0] || 0;
|
|
||||||
var t,y,m,d,h,i,s;
|
|
||||||
t = ts ? new Date(ts*1000) : new Date();
|
|
||||||
y = t.getFullYear();
|
|
||||||
m = t.getMonth()+1;
|
|
||||||
d = t.getDate();
|
|
||||||
h = t.getHours();
|
|
||||||
i = t.getMinutes();
|
|
||||||
s = t.getSeconds();
|
|
||||||
// 可根据需要在这里定义时间格式
|
|
||||||
return y+'-'+(m<10?'0'+m:m)+'-'+(d<10?'0'+d:d)+' '+(h<10?'0'+h:h)+':'+(i<10?'0'+i:i)+':'+(s<10?'0'+s:s);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.server-card{
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.card-img-zlm{
|
|
||||||
width: 200px; height: 200px;
|
|
||||||
background: url('~@static/images/zlm-logo.png') no-repeat center;
|
|
||||||
background-position: center;
|
|
||||||
background-size: contain;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
.card-img-abl{
|
|
||||||
width: 200px; height: 200px;
|
|
||||||
background: url('~@static/images/abl-logo.jpg') no-repeat center;
|
|
||||||
background-position: center;
|
|
||||||
background-size: contain;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
.server-card-status-online{
|
|
||||||
position: absolute;
|
|
||||||
right: 20px;
|
|
||||||
top: 20px;
|
|
||||||
color: #3caf36;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
.server-card-status-offline{
|
|
||||||
position: absolute;
|
|
||||||
right: 20px;
|
|
||||||
top: 20px;
|
|
||||||
color: #808080;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
.server-card-default{
|
|
||||||
position: absolute;
|
|
||||||
left: 20px;
|
|
||||||
top: 20px;
|
|
||||||
color: #808080;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
.server-card:hover {
|
|
||||||
border: 1px solid #adadad;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,314 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="PlatformEdit" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="close" content="添加上级平台"></el-page-header>
|
|
||||||
</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div style="display: inline;">
|
|
||||||
<el-button icon="el-icon-close" size="mini" style="font-size: 20px; color: #000;" type="text" @click="close" ></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="shared" style="text-align: right; margin-top: 1rem; background-color: #FFFFFF; padding-top: 2rem;">
|
|
||||||
<el-row :gutter="24">
|
|
||||||
<el-col :span="11">
|
|
||||||
<el-form ref="platform1" :rules="rules" :model="value" size="medium" label-width="160px">
|
|
||||||
<el-form-item label="名称" prop="name">
|
|
||||||
<el-input v-model="value.name"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SIP服务国标编码" prop="serverGBId">
|
|
||||||
<el-input v-model="value.serverGBId" clearable @input="serverGBIdChange"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SIP服务国标域" prop="serverGBDomain">
|
|
||||||
<el-input v-model="value.serverGBDomain" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SIP服务IP" prop="serverIp">
|
|
||||||
<el-input v-model="value.serverIp" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SIP服务端口" prop="serverPort">
|
|
||||||
<el-input v-model="value.serverPort" clearable type="number"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备国标编号" prop="deviceGBId">
|
|
||||||
<el-input v-model="value.deviceGBId" clearable @input="deviceGBIdChange"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="本地IP" prop="deviceIp">
|
|
||||||
<el-select v-model="value.deviceIp" placeholder="请选择与上级相通的网卡" style="width: 100%">
|
|
||||||
<el-option
|
|
||||||
v-for="ip in deviceIps"
|
|
||||||
:key="ip"
|
|
||||||
:label="ip"
|
|
||||||
:value="ip">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="本地端口" prop="devicePort">
|
|
||||||
<el-input v-model="value.devicePort" :disabled="true" type="number"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="SIP认证用户名" prop="username">
|
|
||||||
<el-input v-model="value.username"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SIP认证密码" prop="password">
|
|
||||||
<el-input v-model="value.password"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="注册周期(秒)" prop="expires">
|
|
||||||
<el-input v-model="value.expires"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="心跳周期(秒)" prop="keepTimeout">
|
|
||||||
<el-input v-model="value.keepTimeout"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form ref="platform2" :rules="rules" :model="value" size="medium" label-width="160px">
|
|
||||||
<el-form-item label="SDP发流IP" prop="sendStreamIp">
|
|
||||||
<el-input v-model="value.sendStreamIp"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="信令传输" prop="transport">
|
|
||||||
<el-select
|
|
||||||
v-model="value.transport"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择信令传输方式"
|
|
||||||
>
|
|
||||||
<el-option label="UDP" value="UDP"></el-option>
|
|
||||||
<el-option label="TCP" value="TCP"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="保密属性" >
|
|
||||||
<el-select v-model="value.secrecy" style="width: 100%" placeholder="请选择保密属性">
|
|
||||||
<el-option label="不涉密" :value="0"></el-option>
|
|
||||||
<el-option label="涉密" :value="1"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="目录分组" prop="catalogGroup">
|
|
||||||
<el-select
|
|
||||||
v-model="value.catalogGroup"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择目录分组"
|
|
||||||
>
|
|
||||||
<el-option label="1" value="1"></el-option>
|
|
||||||
<el-option label="2" value="2"></el-option>
|
|
||||||
<el-option label="4" value="4"></el-option>
|
|
||||||
<el-option label="8" value="8"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="字符集" prop="characterSet">
|
|
||||||
<el-select
|
|
||||||
v-model="value.characterSet"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择字符集"
|
|
||||||
>
|
|
||||||
<el-option label="GB2312" value="GB2312"></el-option>
|
|
||||||
<el-option label="UTF-8" value="UTF-8"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="行政区划" prop="civilCode">
|
|
||||||
<el-input v-model="value.civilCode" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="平台厂商" prop="manufacturer">
|
|
||||||
<el-input v-model="value.manufacturer" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="平台型号" prop="model">
|
|
||||||
<el-input v-model="value.model" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="平台安装地址" prop="address">
|
|
||||||
<el-input v-model="value.address" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="其他选项" >
|
|
||||||
<div style="text-align: left">
|
|
||||||
<el-checkbox label="启用" v-model="value.enable" @change="checkExpires"></el-checkbox>
|
|
||||||
<!-- <el-checkbox label="云台控制" v-model="value.ptz"></el-checkbox>-->
|
|
||||||
<el-checkbox label="RTCP保活" v-model="value.rtcp" @change="rtcpCheckBoxChange"></el-checkbox>
|
|
||||||
<el-checkbox label="消息通道" v-model="value.asMessageChannel"></el-checkbox>
|
|
||||||
<el-checkbox label="主动推送通道" v-model="value.autoPushChannel"></el-checkbox>
|
|
||||||
<el-checkbox label="推送平台信息" :true-label="1" :false-label="0" v-model="value.catalogWithPlatform"></el-checkbox>
|
|
||||||
<el-checkbox label="推送分组信息" :true-label="1" :false-label="0" v-model="value.catalogWithGroup"></el-checkbox>
|
|
||||||
<el-checkbox label="推送行政区划" :true-label="1" :false-label="0" v-model="value.catalogWithRegion"></el-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="onSubmit">{{
|
|
||||||
onSubmit_text
|
|
||||||
}}
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "platformEdit",
|
|
||||||
props: [ 'value', 'closeEdit', 'deviceIps'],
|
|
||||||
components: {
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(newValue, oldValue){
|
|
||||||
this.streamProxy = newValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
var deviceGBIdRules = async (rule, value, callback) => {
|
|
||||||
console.log(value);
|
|
||||||
if (value === "") {
|
|
||||||
callback(new Error("请输入设备国标编号"));
|
|
||||||
} else {
|
|
||||||
var exit = await this.deviceGBIdExit(value);
|
|
||||||
if (exit) {
|
|
||||||
callback(new Error("设备国标编号格式错误或已存在"));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
onSubmit_text: "保存",
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
name: [{required: true, message: "请输入平台名称", trigger: "blur"}],
|
|
||||||
serverGBId: [
|
|
||||||
{required: true, message: "请输入SIP服务国标编码", trigger: "blur"},
|
|
||||||
],
|
|
||||||
serverGBDomain: [
|
|
||||||
{required: true, message: "请输入SIP服务国标域", trigger: "blur"},
|
|
||||||
],
|
|
||||||
serverIp: [{required: true, message: "请输入SIP服务IP", trigger: "blur"}],
|
|
||||||
serverPort: [{required: true, message: "请输入SIP服务端口", trigger: "blur"}],
|
|
||||||
deviceGBId: [{validator: deviceGBIdRules, trigger: "blur"}],
|
|
||||||
username: [{required: false, message: "请输入SIP认证用户名", trigger: "blur"}],
|
|
||||||
password: [{required: false, message: "请输入SIP认证密码", trigger: "blur"}],
|
|
||||||
expires: [{required: true, message: "请输入注册周期", trigger: "blur"}],
|
|
||||||
keepTimeout: [{required: true, message: "请输入心跳周期", trigger: "blur"}],
|
|
||||||
transport: [{required: true, message: "请选择信令传输", trigger: "blur"}],
|
|
||||||
characterSet: [{required: true, message: "请选择编码字符集", trigger: "blur"}],
|
|
||||||
deviceIp: [{required: true, message: "请选择本地IP", trigger: "blur"}],
|
|
||||||
},
|
|
||||||
|
|
||||||
saveLoading: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSubmit: function () {
|
|
||||||
this.saveLoading = true;
|
|
||||||
if (this.value.id) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/platform/update",
|
|
||||||
data: this.value
|
|
||||||
}).then((res) => {
|
|
||||||
this.saveLoading = false;
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
if (this.closeEdit) {
|
|
||||||
this.closeEdit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.saveLoading = false;
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/platform/add",
|
|
||||||
data: this.value
|
|
||||||
}).then((res) => {
|
|
||||||
this.saveLoading = false;
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
if (this.closeEdit) {
|
|
||||||
this.closeEdit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.saveLoading = false;
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
serverGBIdChange: function () {
|
|
||||||
if (this.value.serverGBId.length > 10) {
|
|
||||||
this.value.serverGBDomain = this.value.serverGBId.substr(0, 10);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deviceGBIdChange: function () {
|
|
||||||
this.value.username = this.value.deviceGBId;
|
|
||||||
},
|
|
||||||
checkExpires: function () {
|
|
||||||
if (this.value.enable && this.value.expires === "0") {
|
|
||||||
this.value.expires = "3600";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rtcpCheckBoxChange: function (result) {
|
|
||||||
if (result) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "开启RTCP保活需要上级平台支持,可以避免无效推流",
|
|
||||||
type: "warning",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deviceGBIdExit: async function (deviceGbId) {
|
|
||||||
let result = false;
|
|
||||||
await this.$axios({
|
|
||||||
method:"get",
|
|
||||||
url:`/api/platform/exit/${deviceGbId}`
|
|
||||||
}).then((res)=> {
|
|
||||||
result = res.data;
|
|
||||||
}).catch((error)=> {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.closeEdit()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,306 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app" style="width: 100%">
|
|
||||||
<div v-if="!platform">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">上级平台列表</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="getPlatformList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary"
|
|
||||||
@click="addParentPlatform">添加
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--设备列表-->
|
|
||||||
<el-table size="medium" :data="platformList" style="width: 100%" :height="$tableHeght" :loading="loading">
|
|
||||||
<el-table-column prop="name" label="名称"></el-table-column>
|
|
||||||
<el-table-column prop="serverGBId" label="平台编号" min-width="200"></el-table-column>
|
|
||||||
<el-table-column label="是否启用" min-width="80">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.enable && Vue.prototype.$myServerId !== scope.row.serverId" style="border-color: #ecf1af">已启用</el-tag>
|
|
||||||
<el-tag size="medium" v-if="scope.row.enable && Vue.prototype.$myServerId === scope.row.serverId">已启用</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="80">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.status">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="地址" min-width="160">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium">{{ scope.row.serverIp }}:{{ scope.row.serverPort }}</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="deviceGBId" label="设备国标编号" min-width="200"></el-table-column>
|
|
||||||
<el-table-column prop="transport" label="信令传输模式" min-width="120"></el-table-column>
|
|
||||||
<el-table-column prop="channelCount" label="通道数" min-width="120"></el-table-column>
|
|
||||||
<el-table-column label="订阅信息" min-width="120" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅"
|
|
||||||
class="iconfont icon-gbaojings subscribe-on "></i>
|
|
||||||
<i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅"
|
|
||||||
class="iconfont icon-gbaojings subscribe-off "></i>
|
|
||||||
<i v-if="scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-on"></i>
|
|
||||||
<i v-if="!scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-off"></i>
|
|
||||||
<i v-if="scope.row.mobilePositionSubscribe" title="位置订阅"
|
|
||||||
class="iconfont icon-gxunjians subscribe-on"></i>
|
|
||||||
<i v-if="!scope.row.mobilePositionSubscribe" title="位置订阅"
|
|
||||||
class="iconfont icon-gxunjians subscribe-off"></i>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column label="操作" min-width="240" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="editPlatform(scope.row)">编辑</el-button>
|
|
||||||
<el-button size="medium" icon="el-icon-share" type="text" @click="chooseChannel(scope.row)">通道共享
|
|
||||||
</el-button>
|
|
||||||
<el-button size="medium" icon="el-icon-top" type="text" :loading="pushChannelLoading"
|
|
||||||
@click="pushChannel(scope.row)">推送通道
|
|
||||||
</el-button>
|
|
||||||
<el-button size="medium" icon="el-icon-delete" type="text" style="color: #f56c6c"
|
|
||||||
@click="deletePlatform(scope.row)">删除
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<platformEdit ref="platformEdit" v-if="platform" v-model="platform" :closeEdit="closeEdit"
|
|
||||||
:device-ips="deviceIps"></platformEdit>
|
|
||||||
<shareChannel ref="shareChannel"></shareChannel>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import shareChannel from './dialog/shareChannel.vue'
|
|
||||||
import platformEdit from './PlatformEdit.vue'
|
|
||||||
import streamProxyEdit from "./dialog/StreamProxyEdit.vue";
|
|
||||||
import Vue from "vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'app',
|
|
||||||
components: {
|
|
||||||
streamProxyEdit,
|
|
||||||
uiHeader,
|
|
||||||
shareChannel,
|
|
||||||
platformEdit
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
platformList: [], //设备列表
|
|
||||||
deviceIps: [], //设备列表
|
|
||||||
defaultPlatform: null,
|
|
||||||
platform: null,
|
|
||||||
pushChannelLoading: false,
|
|
||||||
searchSrt: "",
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
Vue() {
|
|
||||||
return Vue
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
this.updateLooper = setInterval(this.initData, 10000);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
clearTimeout(this.updateLooper);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
addParentPlatform: function () {
|
|
||||||
this.platform = this.defaultPlatform;
|
|
||||||
},
|
|
||||||
editPlatform: function (platform) {
|
|
||||||
this.platform = platform;
|
|
||||||
},
|
|
||||||
closeEdit: function () {
|
|
||||||
this.platform = null;
|
|
||||||
this.getPlatformList()
|
|
||||||
},
|
|
||||||
deletePlatform: function (platform) {
|
|
||||||
this.$confirm('确认删除?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.deletePlatformCommit(platform)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deletePlatformCommit: function (platform) {
|
|
||||||
this.loading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'delete',
|
|
||||||
url: `/api/platform/delete/`,
|
|
||||||
params: {
|
|
||||||
id: platform.id
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
this.loading = false;
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: '删除成功',
|
|
||||||
});
|
|
||||||
this.initData()
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.loading = false;
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
chooseChannel: function (platform) {
|
|
||||||
this.$refs.shareChannel.openDialog(platform.id, this.initData)
|
|
||||||
},
|
|
||||||
pushChannel: function (row) {
|
|
||||||
this.pushChannelLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/platform/channel/push`,
|
|
||||||
params: {
|
|
||||||
id: row.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
this.pushChannelLoading = false;
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: '推送成功',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
this.pushChannelLoading = false;
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
initData: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/platform/server_config`
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.deviceIps = res.data.data.deviceIp.split(',');
|
|
||||||
this.defaultPlatform = {
|
|
||||||
id: null,
|
|
||||||
enable: true,
|
|
||||||
ptz: true,
|
|
||||||
rtcp: false,
|
|
||||||
asMessageChannel: false,
|
|
||||||
autoPushChannel: false,
|
|
||||||
name: null,
|
|
||||||
serverGBId: null,
|
|
||||||
serverGBDomain: null,
|
|
||||||
serverIp: null,
|
|
||||||
serverPort: null,
|
|
||||||
deviceGBId: res.data.data.username,
|
|
||||||
deviceIp: this.deviceIps[0],
|
|
||||||
devicePort: res.data.data.devicePort,
|
|
||||||
username: res.data.data.username,
|
|
||||||
password: res.data.data.password,
|
|
||||||
expires: 3600,
|
|
||||||
keepTimeout: 60,
|
|
||||||
transport: "UDP",
|
|
||||||
characterSet: "GB2312",
|
|
||||||
startOfflinePush: false,
|
|
||||||
customGroup: false,
|
|
||||||
catalogWithPlatform: 0,
|
|
||||||
catalogWithGroup: 0,
|
|
||||||
catalogWithRegion: 0,
|
|
||||||
manufacturer: null,
|
|
||||||
model: null,
|
|
||||||
address: null,
|
|
||||||
secrecy: 1,
|
|
||||||
catalogGroup: 1,
|
|
||||||
civilCode: null,
|
|
||||||
sendStreamIp: res.data.data.sendStreamIp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
this.getPlatformList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getPlatformList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getPlatformList();
|
|
||||||
},
|
|
||||||
getPlatformList: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/platform/query`,
|
|
||||||
params: {
|
|
||||||
count: this.count,
|
|
||||||
page: this.currentPage,
|
|
||||||
query: this.searchSrt
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.platformList = res.data.data.list;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
refresh: function () {
|
|
||||||
this.initData();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.subscribe-on {
|
|
||||||
color: #409EFF;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subscribe-off {
|
|
||||||
color: #afafb3;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,235 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="recordPLan" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">
|
|
||||||
<div >录像计划</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div style="display: inline;">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
<el-button size="mini" type="primary" @click="add()">
|
|
||||||
添加
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="getRecordPlanList()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-table size="medium" ref="recordPlanListTable" :data="recordPlanList" :height="$tableHeght" style="width: 100%"
|
|
||||||
header-row-class-name="table-header" >
|
|
||||||
<el-table-column type="selection" width="55" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="name" label="名称" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="channelCount" label="关联通道" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="updateTime" label="更新时间">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="创建时间">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" width="300" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button size="medium" icon="el-icon-link" type="text" @click="link(scope.row)">关联通道</el-button>
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">编辑</el-button>
|
|
||||||
<el-button size="medium" icon="el-icon-delete" style="color: #f56c6c" type="text" @click="deletePlan(scope.row)">删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
<editRecordPlan ref="editRecordPlan"></editRecordPlan>
|
|
||||||
<LinkChannelRecord ref="linkChannelRecord"></LinkChannelRecord>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import EditRecordPlan from "./dialog/editRecordPlan.vue";
|
|
||||||
import LinkChannelRecord from "./dialog/linkChannelRecord.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'recordPLan',
|
|
||||||
components: {
|
|
||||||
EditRecordPlan,
|
|
||||||
LinkChannelRecord,
|
|
||||||
uiHeader,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
recordPlanList: [],
|
|
||||||
searchSrt: "",
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
loading: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.getRecordPlanList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getRecordPlanList();
|
|
||||||
},
|
|
||||||
getRecordPlanList: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/record/plan/query`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
query: this.searchSrt,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.recordPlanList = res.data.data.list;
|
|
||||||
// 防止出现表格错位
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.recordPlanListTable.doLayout();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getSnap: function (row) {
|
|
||||||
let baseUrl = window.baseUrl ? window.baseUrl : "";
|
|
||||||
return ((process.env.NODE_ENV === 'development') ? process.env.BASE_API : baseUrl) + '/api/device/query/snap/' + this.deviceId + '/' + row.deviceId;
|
|
||||||
},
|
|
||||||
search: function () {
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.total = 0;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
refresh: function () {
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
add: function () {
|
|
||||||
this.$refs.editRecordPlan.openDialog(null, ()=>{
|
|
||||||
this.initData()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
edit: function (plan) {
|
|
||||||
this.$refs.editRecordPlan.openDialog(plan, ()=>{
|
|
||||||
this.initData()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
link: function (plan) {
|
|
||||||
this.$refs.linkChannelRecord.openDialog(plan.id, ()=>{
|
|
||||||
this.initData()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deletePlan: function (plan) {
|
|
||||||
this.$confirm('确定删除?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'delete',
|
|
||||||
url: "/api/record/plan/delete",
|
|
||||||
params: {
|
|
||||||
planId: plan.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '删除成功',
|
|
||||||
type: 'success',
|
|
||||||
});
|
|
||||||
this.initData();
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.videoList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item {
|
|
||||||
position: relative;
|
|
||||||
width: 15rem;
|
|
||||||
height: 10rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img:after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
background-image: url("../assets/loading.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-title {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #ffffff;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0.3rem;
|
|
||||||
width: 14.4rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,260 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="StreamProxyEdit" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="close" content="编辑拉流代理信息"></el-page-header>
|
|
||||||
</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div style="display: inline;">
|
|
||||||
<el-button icon="el-icon-close" size="mini" style="font-size: 20px; color: #000;" type="text" @click="close" ></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-tabs tab-position="left" style="background-color: #FFFFFF; padding-top: 1rem">
|
|
||||||
<el-tab-pane label="拉流代理信息">
|
|
||||||
<el-form ref="streamProxy" :rules="rules" :model="streamProxy" label-width="140px" style="width: 50%; margin: 0 auto">
|
|
||||||
<el-form-item label="类型" prop="type">
|
|
||||||
<el-select
|
|
||||||
v-model="streamProxy.type"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择代理类型"
|
|
||||||
>
|
|
||||||
<el-option key="默认" label="默认" value="default"></el-option>
|
|
||||||
<el-option key="FFmpeg" label="FFmpeg" value="ffmpeg"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="应用名" prop="app">
|
|
||||||
<el-input v-model="streamProxy.app" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流ID" prop="stream">
|
|
||||||
<el-input v-model="streamProxy.stream" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="拉流地址" prop="url">
|
|
||||||
<el-input v-model="streamProxy.srcUrl" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="超时时间(秒)" prop="timeoutMs">
|
|
||||||
<el-input v-model="streamProxy.timeout" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="节点选择" prop="rtpType">
|
|
||||||
<el-select
|
|
||||||
v-model="streamProxy.relatesMediaServerId"
|
|
||||||
@change="mediaServerIdChange"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择拉流节点"
|
|
||||||
>
|
|
||||||
<el-option key="auto" label="自动选择" value=""></el-option>
|
|
||||||
<el-option
|
|
||||||
v-for="item in mediaServerList"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.id"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="FFmpeg命令模板" prop="ffmpegCmdKey" v-if="streamProxy.type=='ffmpeg'">
|
|
||||||
<el-select
|
|
||||||
v-model="streamProxy.ffmpegCmdKey"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择FFmpeg命令模板"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in Object.keys(ffmpegCmdList)"
|
|
||||||
:key="item"
|
|
||||||
:label="ffmpegCmdList[item]"
|
|
||||||
:value="item">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="拉流方式(RTSP)" prop="rtspType">
|
|
||||||
<el-select
|
|
||||||
v-model="streamProxy.rtspType"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择拉流方式"
|
|
||||||
>
|
|
||||||
<el-option label="TCP" value="0"></el-option>
|
|
||||||
<el-option label="UDP" value="1"></el-option>
|
|
||||||
<el-option label="组播" value="2"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="无人观看" prop="noneReader" >
|
|
||||||
<el-radio-group v-model="streamProxy.noneReader">
|
|
||||||
<el-radio :label="0">不做处理</el-radio>
|
|
||||||
<el-radio :label="1">停用</el-radio>
|
|
||||||
<el-radio :label="2">移除</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="其他选项">
|
|
||||||
<div style="float: left;">
|
|
||||||
<el-checkbox label="启用" v-model="streamProxy.enable" ></el-checkbox>
|
|
||||||
<el-checkbox label="开启音频" v-model="streamProxy.enableAudio" ></el-checkbox>
|
|
||||||
<el-checkbox label="录制" v-model="streamProxy.enableMp4" ></el-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit" :loading="saveLoading" >保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="国标通道配置" v-if="streamProxy.id">
|
|
||||||
<CommonChannelEdit ref="commonChannelEdit" :dataForm="streamProxy" :cancel="close"></CommonChannelEdit>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CommonChannelEdit from './common/CommonChannelEdit'
|
|
||||||
import MediaServer from "./service/MediaServer";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "channelEdit",
|
|
||||||
props: [ 'value', 'closeEdit'],
|
|
||||||
components: {
|
|
||||||
CommonChannelEdit,
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
console.log(this.streamProxy)
|
|
||||||
this.mediaServer.getOnlineMediaServerList((data)=>{
|
|
||||||
this.mediaServerList = data.data;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(newValue, oldValue){
|
|
||||||
this.streamProxy = newValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
saveLoading: false,
|
|
||||||
streamProxy: this.value,
|
|
||||||
mediaServer: new MediaServer(),
|
|
||||||
mediaServerList:{},
|
|
||||||
ffmpegCmdList:{},
|
|
||||||
rules: {
|
|
||||||
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
|
||||||
app: [{ required: true, message: "请输入应用名", trigger: "blur" }],
|
|
||||||
stream: [{ required: true, message: "请输入流ID", trigger: "blur" }],
|
|
||||||
srcUrl: [{ required: true, message: "请输入要代理的流", trigger: "blur" }],
|
|
||||||
timeout: [{ required: true, message: "请输入FFmpeg推流成功超时时间", trigger: "blur" }],
|
|
||||||
ffmpegCmdKey: [{ required: false, message: "请输入FFmpeg命令参数模板(可选)", trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSubmit: function () {
|
|
||||||
console.log(typeof this.streamProxy.noneReader)
|
|
||||||
this.saveLoading = true;
|
|
||||||
this.noneReaderHandler();
|
|
||||||
if (this.streamProxy.id) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url:`/api/proxy/update`,
|
|
||||||
data: this.streamProxy
|
|
||||||
}).then((res)=> {
|
|
||||||
this.saveLoading = false;
|
|
||||||
if (typeof (res.data.code) != "undefined" && res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
});
|
|
||||||
this.streamProxy = res.data.data
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.saveLoading = false;
|
|
||||||
}).catch((error) =>{
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
this.saveLoading = false;
|
|
||||||
}).finally(()=>{
|
|
||||||
console.log("finally==finally")
|
|
||||||
this.saveLoading = false;
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url:`/api/proxy/add`,
|
|
||||||
data: this.streamProxy
|
|
||||||
}).then((res)=> {
|
|
||||||
this.saveLoading = false;
|
|
||||||
if (typeof (res.data.code) != "undefined" && res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
});
|
|
||||||
this.streamProxy = res.data.data
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) =>{
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
this.saveLoading = false;
|
|
||||||
}).finally(()=>{
|
|
||||||
this.saveLoading = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.closeEdit()
|
|
||||||
},
|
|
||||||
mediaServerIdChange:function (){
|
|
||||||
if (this.streamProxy.relatesMediaServerId !== "auto"){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/proxy/ffmpeg_cmd/list`,
|
|
||||||
params: {
|
|
||||||
mediaServerId: this.streamProxy.relatesMediaServerId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
this.ffmpegCmdList = res.data.data;
|
|
||||||
this.streamProxy.ffmpegCmdKey = Object.keys(res.data.data)[0];
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
noneReaderHandler: function() {
|
|
||||||
console.log(this.streamProxy)
|
|
||||||
if (!this.streamProxy.noneReader || this.streamProxy.noneReader === 0 ) {
|
|
||||||
this.streamProxy.enableDisableNoneReader = false;
|
|
||||||
this.streamProxy.enableRemoveNoneReader = false;
|
|
||||||
}else if (this.streamProxy.noneReader === 1){
|
|
||||||
this.streamProxy.enableDisableNoneReader = true;
|
|
||||||
this.streamProxy.enableRemoveNoneReader = false;
|
|
||||||
}else if (this.streamProxy.noneReader ===2){
|
|
||||||
this.streamProxy.enableDisableNoneReader = false;
|
|
||||||
this.streamProxy.enableRemoveNoneReader = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,405 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="streamProxyList" style="width: 100%">
|
|
||||||
|
|
||||||
<div v-if="!streamProxy">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">拉流代理列表</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="getStreamProxyList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
流媒体:
|
|
||||||
<el-select size="mini" @change="getStreamProxyList" style="margin-right: 1rem;" v-model="mediaServerId"
|
|
||||||
placeholder="请选择" default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option
|
|
||||||
v-for="item in mediaServerList"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.id"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
拉流状态:
|
|
||||||
<el-select size="mini" style="margin-right: 1rem;" @change="getStreamProxyList" v-model="pulling" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="正在拉流" value="true"></el-option>
|
|
||||||
<el-option label="尚未拉流" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
|
|
||||||
<el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button>
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
|
||||||
<el-table size="medium" :data="streamProxyList" style="width: 100%" :height="$tableHeght" >
|
|
||||||
<el-table-column prop="app" label="流应用名" min-width="120" show-overflow-tooltip/>
|
|
||||||
<el-table-column prop="stream" label="流ID" min-width="120" show-overflow-tooltip/>
|
|
||||||
<el-table-column label="流地址" min-width="250" show-overflow-tooltip >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium">
|
|
||||||
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.srcUrl" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
|
|
||||||
{{scope.row.srcUrl}}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="mediaServerId" label="流媒体" min-width="180" ></el-table-column>
|
|
||||||
<el-table-column label="代理方式" width="100" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
{{scope.row.type === "default"? "默认":"FFMPEG代理"}}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column prop="gbDeviceId" label="国标编码" min-width="180" show-overflow-tooltip/>
|
|
||||||
<el-table-column label="拉流状态" min-width="120" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.pulling && Vue.prototype.$myServerId !== scope.row.serverId" style="border-color: #ecf1af">正在拉流</el-tag>
|
|
||||||
<el-tag size="medium" v-if="scope.row.pulling && Vue.prototype.$myServerId === scope.row.serverId">正在拉流</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="!scope.row.pulling">尚未拉流</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="启用" min-width="120" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.enable && Vue.prototype.$myServerId !== scope.row.serverId" style="border-color: #ecf1af">已启用</el-tag>
|
|
||||||
<el-tag size="medium" v-if="scope.row.enable && Vue.prototype.$myServerId === scope.row.serverId">已启用</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="创建时间" min-width="150" show-overflow-tooltip/>
|
|
||||||
<el-table-column label="操作" width="400" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button size="medium" :loading="scope.row.playLoading" icon="el-icon-video-play" type="text" @click="play(scope.row)">播放</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-switch-button" style="color: #f56c6c" type="text" v-if="scope.row.pulling" @click="stopPlay(scope.row)">停止</el-button>
|
|
||||||
<el-divider direction="vertical" v-if="scope.row.pulling" ></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">
|
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-cloudy" type="text" @click="queryCloudRecords(scope.row)">云端录像</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-delete" type="text" style="color: #f56c6c" @click="deleteStreamProxy(scope.row)">删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
<streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
|
|
||||||
<onvifEdit ref="onvifEdit" ></onvifEdit>
|
|
||||||
<StreamProxyEdit v-if="streamProxy" v-model="streamProxy" :closeEdit="closeEdit" ></StreamProxyEdit>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import streamProxyEdit from './dialog/StreamProxyEdit.vue'
|
|
||||||
import onvifEdit from './dialog/onvifEdit.vue'
|
|
||||||
import devicePlayer from './dialog/devicePlayer.vue'
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import StreamProxyEdit from "./StreamProxyEdit";
|
|
||||||
import MediaServer from "./service/MediaServer";
|
|
||||||
import Vue from "vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'streamProxyList',
|
|
||||||
components: {
|
|
||||||
devicePlayer,
|
|
||||||
streamProxyEdit,
|
|
||||||
onvifEdit,
|
|
||||||
StreamProxyEdit,
|
|
||||||
uiHeader
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
streamProxyList: [],
|
|
||||||
currentPusher: {}, //当前操作设备对象
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
currentDeviceChannelsLenth:0,
|
|
||||||
currentPage:1,
|
|
||||||
count:15,
|
|
||||||
total:0,
|
|
||||||
streamProxy: null,
|
|
||||||
searchSrt: "",
|
|
||||||
mediaServerId: "",
|
|
||||||
pulling: "",
|
|
||||||
mediaServerObj: new MediaServer(),
|
|
||||||
mediaServerList: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
Vue() {
|
|
||||||
return Vue
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
this.startUpdateList()
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$destroy('videojs');
|
|
||||||
clearTimeout(this.updateLooper);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function() {
|
|
||||||
this.getStreamProxyList();
|
|
||||||
this.mediaServerObj.getOnlineMediaServerList((data) => {
|
|
||||||
this.mediaServerList = data.data;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
startUpdateList: function (){
|
|
||||||
this.updateLooper = setInterval(()=>{
|
|
||||||
if (!this.streamProxy) {
|
|
||||||
this.getStreamProxyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 1000);
|
|
||||||
},
|
|
||||||
currentChange: function(val){
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getStreamProxyList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function(val){
|
|
||||||
this.count = val;
|
|
||||||
this.getStreamProxyList();
|
|
||||||
},
|
|
||||||
getStreamProxyList: function() {
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/proxy/list`,
|
|
||||||
params: {
|
|
||||||
page: that.currentPage,
|
|
||||||
count: that.count,
|
|
||||||
query: this.searchSrt,
|
|
||||||
pulling: this.pulling,
|
|
||||||
mediaServerId: this.mediaServerId,
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.total = res.data.data.total;
|
|
||||||
for (let i = 0; i < res.data.data.list.length; i++) {
|
|
||||||
res.data.data.list[i]["playLoading"] = false;
|
|
||||||
}
|
|
||||||
that.streamProxyList = res.data.data.list;
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addStreamProxy: function(){
|
|
||||||
// this.$refs.streamProxyEdit.openDialog(null, this.initData)
|
|
||||||
this.streamProxy = {
|
|
||||||
type: "default",
|
|
||||||
dataType: 3,
|
|
||||||
noneReader: 1,
|
|
||||||
enable: true,
|
|
||||||
enableAudio: true,
|
|
||||||
mediaServerId: "",
|
|
||||||
timeout: 10,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addOnvif: function(){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/onvif/search?timeout=3000`,
|
|
||||||
}).then((res) =>{
|
|
||||||
if (res.data.code === 0 ){
|
|
||||||
if (res.data.data.length > 0) {
|
|
||||||
this.$refs.onvifEdit.openDialog(res.data.data, (url)=>{
|
|
||||||
if (url != null) {
|
|
||||||
this.$refs.onvifEdit.close();
|
|
||||||
this.$refs.streamProxyEdit.openDialog({type: "default", url: url, srcUrl: url}, this.initData())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "未找到可用设备"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
edit: function(row){
|
|
||||||
if (row.enableDisableNoneReader) {
|
|
||||||
this.$set(row, "noneReader", 1)
|
|
||||||
}else if (row.enableRemoveNoneReader) {
|
|
||||||
this.$set(row, "noneReader", 2)
|
|
||||||
}else {
|
|
||||||
this.$set(row, "noneReader", 0)
|
|
||||||
}
|
|
||||||
this.streamProxy = row
|
|
||||||
this.$set(this.streamProxy, "rtspType", row.rtspType)
|
|
||||||
},
|
|
||||||
closeEdit: function(row){
|
|
||||||
this.streamProxy = null
|
|
||||||
},
|
|
||||||
play: function(row){
|
|
||||||
row.playLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/proxy/start`,
|
|
||||||
params: {
|
|
||||||
id: row.id,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$refs.devicePlayer.openDialog("streamPlay", null, null, {
|
|
||||||
streamInfo: res.data.data,
|
|
||||||
hasAudio: true
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "获取地址失败:" + res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
}).finally(()=>{
|
|
||||||
row.playLoading = false;
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
stopPlay: function(row){
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/proxy/stop`,
|
|
||||||
params: {
|
|
||||||
id: row.id,
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
|
|
||||||
}else {
|
|
||||||
that.$message.error(res.data.msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
queryCloudRecords: function (row) {
|
|
||||||
|
|
||||||
this.$router.push(`/cloudRecordDetail/${row.app}/${row.stream}`)
|
|
||||||
},
|
|
||||||
deleteStreamProxy: function(row){
|
|
||||||
this.$confirm('确定删除此代理吗?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method:"delete",
|
|
||||||
url:"/api/proxy/delete",
|
|
||||||
params:{
|
|
||||||
id: row.id,
|
|
||||||
}
|
|
||||||
}).then((res)=>{
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "删除成功"
|
|
||||||
})
|
|
||||||
this.initData()
|
|
||||||
}).catch((error) =>{
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
refresh: function (){
|
|
||||||
this.initData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.videoList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item {
|
|
||||||
position: relative;
|
|
||||||
width: 15rem;
|
|
||||||
height: 10rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img:after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
background-image: url("../assets/loading.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-title {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #ffffff;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0.3rem;
|
|
||||||
width: 14.4rem;
|
|
||||||
}
|
|
||||||
.cpoy-btn {
|
|
||||||
cursor: pointer;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,136 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ChannelEdit" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="close" content="编辑推流信息"></el-page-header>
|
|
||||||
</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div style="display: inline;">
|
|
||||||
<el-button icon="el-icon-close" size="mini" style="font-size: 20px; color: #000;" type="text" @click="close" ></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-tabs tab-position="left">
|
|
||||||
<el-tab-pane label="推流信息编辑" style="background-color: #FFFFFF; padding: 1rem">
|
|
||||||
<el-divider content-position="center">基础信息</el-divider>
|
|
||||||
<el-form ref="streamPushForm" status-icon label-width="160px" class="channel-form" v-loading="locading">
|
|
||||||
<el-form-item label="应用名" >
|
|
||||||
<el-input v-model="streamPush.app" placeholder="请输入应用名"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流ID" >
|
|
||||||
<el-input v-model="streamPush.stream" placeholder="请输入流ID"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-divider content-position="center">策略</el-divider>
|
|
||||||
<el-form ref="streamPushForm" status-icon label-width="160px" v-loading="locading">
|
|
||||||
<el-form-item style="text-align: left">
|
|
||||||
<el-checkbox v-model="streamPush.startOfflinePush">拉起离线推流</el-checkbox>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
<el-form style="text-align: right">
|
|
||||||
<el-form-item >
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="国标通道配置" v-if="streamPush.id">
|
|
||||||
<CommonChannelEdit ref="commonChannelEdit" :dataForm="streamPush" :cancel="close"></CommonChannelEdit>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CommonChannelEdit from './common/CommonChannelEdit'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "channelEdit",
|
|
||||||
props: [ 'streamPush', 'closeEdit'],
|
|
||||||
components: {
|
|
||||||
CommonChannelEdit,
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
console.log(this.streamPush)
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
locading: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSubmit: function () {
|
|
||||||
console.log(this.streamPush)
|
|
||||||
this.locading = true
|
|
||||||
if (this.streamPush.id) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/push/update",
|
|
||||||
data: this.streamPush
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: '保存成功',
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
}).finally(()=>{
|
|
||||||
this.locading = false
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/push/add",
|
|
||||||
data: this.streamPush
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: '保存成功',
|
|
||||||
});
|
|
||||||
|
|
||||||
this.streamPush = res.data.data
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
}).finally(()=>{
|
|
||||||
this.locading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.closeEdit()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,384 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="streamPushList" style="width: 100%">
|
|
||||||
<div v-if="!streamPush">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">推流列表</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="getPushList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
流媒体:
|
|
||||||
<el-select size="mini" @change="getPushList" style="margin-right: 1rem;" v-model="mediaServerId"
|
|
||||||
placeholder="请选择" default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option
|
|
||||||
v-for="item in mediaServerList"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.id"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
推流状态:
|
|
||||||
<el-select size="mini" style="margin-right: 1rem;" @change="getPushList" v-model="pushing" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="推流中" value="true"></el-option>
|
|
||||||
<el-option label="已停止" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button icon="el-icon-upload2" size="mini" style="margin-right: 1rem;" type="primary" @click="importChannel">
|
|
||||||
通道导入
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary">
|
|
||||||
<a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip"
|
|
||||||
download='推流通道导入.zip'>下载模板</a>
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;"
|
|
||||||
:disabled="multipleSelection.length === 0" type="danger" @click="batchDel">移除
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStream">添加
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-table size="medium" ref="pushListTable" :data="pushList" style="width: 100%" :height="$tableHeght" :loading="loading"
|
|
||||||
@selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream">
|
|
||||||
<el-table-column type="selection" :reserve-selection="true" min-width="55">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbName" label="名称" min-width="200">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="app" label="应用名" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="stream" label="流ID" min-width="200">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="推流状态" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-tag size="medium" v-if="scope.row.pushing && Vue.prototype.$myServerId !== scope.row.serverId" style="border-color: #ecf1af">推流中</el-tag>
|
|
||||||
<el-tag size="medium" v-if="scope.row.pushing && Vue.prototype.$myServerId === scope.row.serverId">推流中</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="!scope.row.pushing">已停止</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbDeviceId" label="国标编码" min-width="200" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="位置信息" min-width="200">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<span size="medium" v-if="scope.row.gbLongitude && scope.row.gbLatitude">{{scope.row.gbLongitude}}<br/>{{scope.row.gbLatitude}}</span>
|
|
||||||
<span size="medium" v-if="!scope.row.gbLongitude || !scope.row.gbLatitude">无</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="mediaServerId" label="流媒体" min-width="200" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="开始时间" min-width="200">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button-group>
|
|
||||||
{{ scope.row.pushTime == null? "-":scope.row.pushTime }}
|
|
||||||
</el-button-group>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
|
|
||||||
<el-table-column label="操作" min-width="360" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button size="medium" :loading="scope.row.playLoading" icon="el-icon-video-play" @click="playPush(scope.row)" type="text">播放
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-delete" type="text" @click="deletePush(scope.row.id)" style="color: #f56c6c" >删除</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-position" type="text" @click="edit(scope.row)">
|
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
<el-button size="medium" icon="el-icon-cloudy" type="text" @click="queryCloudRecords(scope.row)">云端录像
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
|
||||||
<addStreamTOGB ref="addStreamTOGB"></addStreamTOGB>
|
|
||||||
<importChannel ref="importChannel"></importChannel>
|
|
||||||
<stream-push-edit v-if="streamPush" :streamPush="streamPush" :closeEdit="closeEdit"></stream-push-edit>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import devicePlayer from './dialog/devicePlayer.vue'
|
|
||||||
import addStreamTOGB from './dialog/pushStreamEdit.vue'
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import importChannel from './dialog/importChannel.vue'
|
|
||||||
import MediaServer from './service/MediaServer'
|
|
||||||
import StreamPushEdit from "./StreamPushEdit";
|
|
||||||
import ChannelEdit from "./ChannelEdit.vue";
|
|
||||||
import Vue from "vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'streamPushList',
|
|
||||||
components: {
|
|
||||||
ChannelEdit,
|
|
||||||
StreamPushEdit,
|
|
||||||
devicePlayer,
|
|
||||||
addStreamTOGB,
|
|
||||||
uiHeader,
|
|
||||||
importChannel,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pushList: [], //设备列表
|
|
||||||
currentPusher: {}, //当前操作设备对象
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
currentDeviceChannelsLenth: 0,
|
|
||||||
mediaServerObj: new MediaServer(),
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
searchSrt: "",
|
|
||||||
pushing: "",
|
|
||||||
mediaServerId: "",
|
|
||||||
mediaServerList: [],
|
|
||||||
multipleSelection: [],
|
|
||||||
loading: false,
|
|
||||||
streamPush: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
Vue() {
|
|
||||||
return Vue
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
this.updateLooper = setInterval(this.getPushList, 2000);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
clearTimeout(this.updateLooper);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.loading = true;
|
|
||||||
this.mediaServerObj.getOnlineMediaServerList((data) => {
|
|
||||||
this.mediaServerList = data.data;
|
|
||||||
})
|
|
||||||
this.getPushList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getPushList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getPushList();
|
|
||||||
},
|
|
||||||
getPushList: function () {
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/push/list`,
|
|
||||||
params: {
|
|
||||||
page: that.currentPage,
|
|
||||||
count: that.count,
|
|
||||||
query: that.searchSrt,
|
|
||||||
pushing: that.pushing,
|
|
||||||
mediaServerId: that.mediaServerId,
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.total = res.data.data.total;
|
|
||||||
that.pushList = res.data.data.list;
|
|
||||||
that.pushList.forEach(e => {
|
|
||||||
that.$set(e, "location", "");
|
|
||||||
that.$set(e, "playLoading", false);
|
|
||||||
if (e.gbLongitude && e.gbLatitude) {
|
|
||||||
that.$set(e, "location", e.gbLongitude + "," + e.gbLatitude);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.error(error);
|
|
||||||
}).finally(()=>{
|
|
||||||
this.loading = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
playPush: function (row) {
|
|
||||||
row.playLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/push/start',
|
|
||||||
params: {
|
|
||||||
id: row.id
|
|
||||||
}
|
|
||||||
}).then((res) =>{
|
|
||||||
if (res.data.code === 0 ) {
|
|
||||||
this.$refs.devicePlayer.openDialog("streamPlay", null, null, {
|
|
||||||
streamInfo: res.data.data,
|
|
||||||
hasAudio: true
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message.error(res.data.msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.error(error);
|
|
||||||
}).finally(()=>{
|
|
||||||
row.playLoading = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deletePush: function (id) {
|
|
||||||
this.$confirm(`确定删除通道?`, '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.loading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: "post",
|
|
||||||
url: "/api/push/remove",
|
|
||||||
params: {
|
|
||||||
id: id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.initData()
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
edit: function (row) {
|
|
||||||
this.streamPush = row
|
|
||||||
},
|
|
||||||
// 结束编辑
|
|
||||||
closeEdit: function (){
|
|
||||||
this.streamPush = null
|
|
||||||
this.getPushList()
|
|
||||||
},
|
|
||||||
removeFromGB: function (row) {
|
|
||||||
let that = this;
|
|
||||||
that.$axios({
|
|
||||||
method: "delete",
|
|
||||||
url: "/api/push/remove_form_gb",
|
|
||||||
data: row
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.initData()
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
queryCloudRecords: function (row) {
|
|
||||||
|
|
||||||
this.$router.push(`/cloudRecordDetail/${row.app}/${row.stream}`)
|
|
||||||
},
|
|
||||||
importChannel: function () {
|
|
||||||
this.$refs.importChannel.openDialog(() => {
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addStream: function (){
|
|
||||||
// this.$refs.addStreamTOGB.openDialog(null, this.initData);
|
|
||||||
this.streamPush = {}
|
|
||||||
},
|
|
||||||
batchDel: function () {
|
|
||||||
this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
let ids = []
|
|
||||||
for (let i = 0; i < this.multipleSelection.length; i++) {
|
|
||||||
ids.push(this.multipleSelection[i].id)
|
|
||||||
}
|
|
||||||
let that = this;
|
|
||||||
that.$axios({
|
|
||||||
method: "delete",
|
|
||||||
url: "/api/push/batchRemove",
|
|
||||||
data: {
|
|
||||||
ids: ids
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
this.initData();
|
|
||||||
this.$refs.pushListTable.clearSelection();
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleSelectionChange: function (val) {
|
|
||||||
this.multipleSelection = val;
|
|
||||||
},
|
|
||||||
refresh: function () {
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.videoList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item {
|
|
||||||
position: relative;
|
|
||||||
width: 15rem;
|
|
||||||
height: 10rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img:after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
background-image: url("../assets/loading.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-title {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #ffffff;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0.3rem;
|
|
||||||
width: 14.4rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,303 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app" style="width: 100%">
|
|
||||||
<div class="page-header" style="margin-bottom: 0">
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="goBack" content="ApiKey列表"></el-page-header>
|
|
||||||
</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addUserApiKey">
|
|
||||||
添加ApiKey
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--ApiKey列表-->
|
|
||||||
<el-table size="medium" :data="userList" style="width: 100%;font-size: 12px;" :height="winHeight"
|
|
||||||
header-row-class-name="table-header">
|
|
||||||
<el-table-column prop="user.username" label="用户名" min-width="120"/>
|
|
||||||
<el-table-column prop="app" label="应用名" min-width="160"/>
|
|
||||||
<el-table-column label="ApiKey" :show-overflow-tooltip="true" min-width="300">
|
|
||||||
<template #default="scope">
|
|
||||||
<!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.apiKey" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>-->
|
|
||||||
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.apiKey" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
|
|
||||||
<span>{{scope.row.apiKey}}</span>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="enable" label="启用" width="120">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-tag v-if="scope.row.enable">
|
|
||||||
启用
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-else type="info">
|
|
||||||
停用
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="expiredAt" label="过期时间" width="160"/>
|
|
||||||
<el-table-column prop="remark" label="备注信息" min-width="160"/>
|
|
||||||
<el-table-column label="操作" min-width="260" fixed="right">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-button v-if="scope.row.enable"
|
|
||||||
size="medium" icon="el-icon-circle-close" type="text" @click="disableUserApiKey(scope.row)">
|
|
||||||
停用
|
|
||||||
</el-button>
|
|
||||||
<el-button v-else
|
|
||||||
size="medium" icon="el-icon-circle-check" type="text" @click="enableUserApiKey(scope.row)">
|
|
||||||
启用
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-refresh" type="text" @click="resetUserApiKey(scope.row)">
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="remarkUserApiKey(scope.row)">
|
|
||||||
备注
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-delete" type="text" @click="deleteUserApiKey(scope.row)"
|
|
||||||
style="color: #f56c6c">
|
|
||||||
删除
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<addUserApiKey ref="addUserApiKey"></addUserApiKey>
|
|
||||||
<remarkUserApiKey ref="remarkUserApiKey"></remarkUserApiKey>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import addUserApiKey from "./dialog/addUserApiKey.vue";
|
|
||||||
import remarkUserApiKey from './dialog/remarkUserApiKey.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'userApiKeyManager',
|
|
||||||
components: {
|
|
||||||
uiHeader,
|
|
||||||
addUserApiKey,
|
|
||||||
remarkUserApiKey
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
userList: [], //设备列表
|
|
||||||
currentUser: {}, //当前操作设备对象
|
|
||||||
winHeight: window.innerHeight - 200,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
getUserApiKeyListLoading: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initParam();
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
goBack() {
|
|
||||||
this.$router.back()
|
|
||||||
},
|
|
||||||
initParam() {
|
|
||||||
this.userId = this.$route.params.userId;
|
|
||||||
},
|
|
||||||
initData() {
|
|
||||||
this.getUserApiKeyList();
|
|
||||||
},
|
|
||||||
currentChange(val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getUserApiKeyList();
|
|
||||||
},
|
|
||||||
handleSizeChange(val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getUserApiKeyList();
|
|
||||||
},
|
|
||||||
getUserApiKeyList() {
|
|
||||||
let that = this;
|
|
||||||
this.getUserApiKeyListLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/userApiKey/userApiKeys`,
|
|
||||||
params: {
|
|
||||||
page: that.currentPage,
|
|
||||||
count: that.count
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.total = res.data.data.total;
|
|
||||||
that.userList = res.data.data.list;
|
|
||||||
}
|
|
||||||
that.getUserApiKeyListLoading = false;
|
|
||||||
}).catch((error) => {
|
|
||||||
that.getUserApiKeyListLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addUserApiKey() {
|
|
||||||
this.$refs.addUserApiKey.openDialog(this.userId, () => {
|
|
||||||
this.$refs.addUserApiKey.close();
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "ApiKey添加成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
setTimeout(this.getUserApiKeyList, 200)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
remarkUserApiKey(row) {
|
|
||||||
this.$refs.remarkUserApiKey.openDialog(row.id, () => {
|
|
||||||
this.$refs.remarkUserApiKey.close();
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "备注修改成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
setTimeout(this.getUserApiKeyList, 200)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
enableUserApiKey(row) {
|
|
||||||
let msg = "确定启用此ApiKey?"
|
|
||||||
if (row.online !== 0) {
|
|
||||||
msg = "<strong>确定启用此ApiKey?</strong>"
|
|
||||||
}
|
|
||||||
this.$confirm(msg, '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
center: true,
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/userApiKey/enable?id=${row.id}`
|
|
||||||
}).then((res) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '启用成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.getUserApiKeyList();
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '启用失败',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
disableUserApiKey(row) {
|
|
||||||
let msg = "确定停用此ApiKey?"
|
|
||||||
if (row.online !== 0) {
|
|
||||||
msg = "<strong>确定停用此ApiKey?</strong>"
|
|
||||||
}
|
|
||||||
this.$confirm(msg, '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
center: true,
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/userApiKey/disable?id=${row.id}`
|
|
||||||
}).then((res) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '停用成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.getUserApiKeyList();
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '停用失败',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetUserApiKey(row) {
|
|
||||||
let msg = "确定重置此ApiKey?"
|
|
||||||
if (row.online !== 0) {
|
|
||||||
msg = "<strong>确定重置此ApiKey?</strong>"
|
|
||||||
}
|
|
||||||
this.$confirm(msg, '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
center: true,
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/userApiKey/reset?id=${row.id}`
|
|
||||||
}).then((res) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '重置成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.getUserApiKeyList();
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '重置失败',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteUserApiKey(row) {
|
|
||||||
let msg = "确定删除此ApiKey?"
|
|
||||||
if (row.online !== 0) {
|
|
||||||
msg = "<strong>确定删除此ApiKey?</strong>"
|
|
||||||
}
|
|
||||||
this.$confirm(msg, '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
center: true,
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'delete',
|
|
||||||
url: `/api/userApiKey/delete?id=${row.id}`
|
|
||||||
}).then((res) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '删除成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.getUserApiKeyList();
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '删除失败',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,241 +0,0 @@
|
|||||||
<template>
|
|
||||||
|
|
||||||
<div id="app" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
|
|
||||||
<div class="page-title">用户列表</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addUser">
|
|
||||||
添加用户
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--用户列表-->
|
|
||||||
<el-table size="medium" :data="userList" style="width: 100%;font-size: 12px;" :height="$tableHeght"
|
|
||||||
header-row-class-name="table-header">
|
|
||||||
<el-table-column prop="username" label="用户名" min-width="160"/>
|
|
||||||
<el-table-column prop="pushKey" label="pushkey" min-width="160"/>
|
|
||||||
<el-table-column prop="role.name" label="类型" min-width="160"/>
|
|
||||||
<el-table-column label="操作" min-width="450" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">修改密码</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="changePushKey(scope.row)">修改pushkey</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="showUserApiKeyManager(scope.row)">管理ApiKey</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-delete" type="text" @click="deleteUser(scope.row)"
|
|
||||||
style="color: #f56c6c">删除
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<changePasswordForAdmin ref="changePasswordForAdmin"></changePasswordForAdmin>
|
|
||||||
<changePushKey ref="changePushKey"></changePushKey>
|
|
||||||
<addUser ref="addUser"></addUser>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import changePasswordForAdmin from './dialog/changePasswordForAdmin.vue'
|
|
||||||
import changePushKey from './dialog/changePushKey.vue'
|
|
||||||
import addUser from '../components/dialog/addUser.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'userManager',
|
|
||||||
components: {
|
|
||||||
uiHeader,
|
|
||||||
changePasswordForAdmin,
|
|
||||||
changePushKey,
|
|
||||||
addUser
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
userList: [], //设备列表
|
|
||||||
currentUser: {}, //当前操作设备对象
|
|
||||||
|
|
||||||
videoComponentList: [],
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
currentUserLenth: 0,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
getUserListLoading: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
this.updateLooper = setInterval(this.initData, 10000);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$destroy('videojs');
|
|
||||||
clearTimeout(this.updateLooper);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.getUserList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getUserList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getUserList();
|
|
||||||
},
|
|
||||||
getUserList: function () {
|
|
||||||
let that = this;
|
|
||||||
this.getUserListLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/user/users`,
|
|
||||||
params: {
|
|
||||||
page: that.currentPage,
|
|
||||||
count: that.count
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.total = res.data.data.total;
|
|
||||||
that.userList = res.data.data.list;
|
|
||||||
}
|
|
||||||
that.getUserListLoading = false;
|
|
||||||
}).catch(function (error) {
|
|
||||||
that.getUserListLoading = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
edit: function (row) {
|
|
||||||
this.$refs.changePasswordForAdmin.openDialog(row, () => {
|
|
||||||
this.$refs.changePasswordForAdmin.close();
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "密码修改成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
setTimeout(this.getUserList, 200)
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteUser: function (row) {
|
|
||||||
let msg = "确定删除此用户?"
|
|
||||||
if (row.online !== 0) {
|
|
||||||
msg = "<strong>确定删除此用户?</strong>"
|
|
||||||
}
|
|
||||||
this.$confirm(msg, '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
center: true,
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'delete',
|
|
||||||
url: `/api/user/delete?id=${row.id}`
|
|
||||||
}).then((res) => {
|
|
||||||
this.getUserList();
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
changePushKey: function (row) {
|
|
||||||
this.$refs.changePushKey.openDialog(row, () => {
|
|
||||||
this.$refs.changePushKey.close();
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "pushKey修改成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
setTimeout(this.getUserList, 200)
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addUser: function () {
|
|
||||||
// this.$refs.addUser.openDialog()
|
|
||||||
this.$refs.addUser.openDialog( () => {
|
|
||||||
this.$refs.addUser.close();
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "用户添加成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
setTimeout(this.getUserList, 200)
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showUserApiKeyManager: function (row) {
|
|
||||||
this.$router.push(`/userApiKeyManager/${row.id}`)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.videoList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item {
|
|
||||||
position: relative;
|
|
||||||
width: 15rem;
|
|
||||||
height: 10rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img:after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
background-image: url("../assets/loading.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-title {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #ffffff;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0.3rem;
|
|
||||||
width: 14.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,669 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="channelList" style="width: 100%">
|
|
||||||
<div v-if="!editId">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">
|
|
||||||
<el-page-header @back="showDevice" content="通道列表"></el-page-header>
|
|
||||||
</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div v-if="!showTree" style="display: inline;">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
|
|
||||||
通道类型:
|
|
||||||
<el-select size="mini" @change="search" style="width: 8rem; margin-right: 1rem;" v-model="channelType" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="设备" value="false"></el-option>
|
|
||||||
<el-option label="子目录" value="true"></el-option>
|
|
||||||
</el-select>
|
|
||||||
在线状态:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="在线" value="true"></el-option>
|
|
||||||
<el-option label="离线" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
码流类型重置:
|
|
||||||
<el-select size="mini" style="width: 16rem; margin-right: 1rem;" @change="subStreamChange" v-model="subStream"
|
|
||||||
placeholder="请选择码流类型" default-first-option >
|
|
||||||
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
|
|
||||||
<el-option label="stream:1(子码流)" value="stream:1"></el-option>
|
|
||||||
<el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
|
|
||||||
<el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
|
|
||||||
<el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
|
|
||||||
<el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
|
|
||||||
<el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
|
|
||||||
<el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-table size="medium" ref="channelListTable" :data="deviceChannelList" :height="$tableHeght"
|
|
||||||
header-row-class-name="table-header">
|
|
||||||
<el-table-column prop="name" label="名称" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="deviceId" label="编号" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="快照" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-image
|
|
||||||
:src="getSnap(scope.row)"
|
|
||||||
:preview-src-list="getBigSnap(scope.row)"
|
|
||||||
@error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)"
|
|
||||||
:fit="'contain'"
|
|
||||||
style="width: 60px">
|
|
||||||
<div slot="error" class="image-slot">
|
|
||||||
<i class="el-icon-picture-outline"></i>
|
|
||||||
</div>
|
|
||||||
</el-image>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<!-- <el-table-column prop="subCount" label="子节点数" min-width="100">-->
|
|
||||||
<!-- </el-table-column>-->
|
|
||||||
<el-table-column prop="manufacturer" label="厂家" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="位置信息" min-width="150">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<span size="medium" v-if="scope.row.longitude && scope.row.latitude">{{scope.row.longitude}}<br/>{{scope.row.latitude}}</span>
|
|
||||||
<span size="medium" v-if="!scope.row.longitude || !scope.row.latitude">无</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="ptzType" label="云台类型" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div >{{ scope.row.ptzTypeText }}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="开启音频" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
|
|
||||||
</el-switch>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="码流类型" min-width="180">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-select size="mini" style="margin-right: 1rem;" @change="channelSubStreamChange(scope.row)" v-model="scope.row.streamIdentification"
|
|
||||||
placeholder="请选择码流类型" default-first-option >
|
|
||||||
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
|
|
||||||
<el-option label="stream:1(子码流)" value="stream:1"></el-option>
|
|
||||||
<el-option label="streamnumber:0(主码流-2022)" value="streamnumber:0"></el-option>
|
|
||||||
<el-option label="streamnumber:1(子码流-2022)" value="streamnumber:1"></el-option>
|
|
||||||
<el-option label="streamprofile:0(主码流-大华)" value="streamprofile:0"></el-option>
|
|
||||||
<el-option label="streamprofile:1(子码流-大华)" value="streamprofile:1"></el-option>
|
|
||||||
<el-option label="streamMode:main(主码流-水星+TP-LINK)" value="streamMode:main"></el-option>
|
|
||||||
<el-option label="streamMode:sub(子码流-水星+TP-LINK)" value="streamMode:sub"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.status === 'ON'">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="scope.row.status !== 'ON'">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" min-width="340" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
|
|
||||||
type="text" :loading="scope.row.playLoading" @click="sendDevicePush(scope.row)">播放
|
|
||||||
</el-button>
|
|
||||||
<el-button size="medium" v-bind:disabled="device == null || device.online === 0"
|
|
||||||
icon="el-icon-switch-button"
|
|
||||||
type="text" style="color: #f56c6c" v-if="!!scope.row.streamId"
|
|
||||||
@click="stopDevicePush(scope.row)">停止
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button
|
|
||||||
size="medium"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-edit"
|
|
||||||
@click="handleEdit(scope.row)"
|
|
||||||
>
|
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
|
||||||
<el-button size="medium" icon="el-icon-s-open" type="text"
|
|
||||||
v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8"
|
|
||||||
@click="changeSubchannel(scope.row)">查看
|
|
||||||
</el-button>
|
|
||||||
<el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1 || scope.row.deviceId.length <= 8" direction="vertical"></el-divider>
|
|
||||||
<el-dropdown @command="(command)=>{moreClick(command, scope.row)}">
|
|
||||||
<el-button size="medium" type="text" >
|
|
||||||
更多<i class="el-icon-arrow-down el-icon--right"></i>
|
|
||||||
</el-button>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item command="records" v-bind:disabled="device == null || device.online === 0">
|
|
||||||
设备录像</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="cloudRecords" v-bind:disabled="device == null || device.online === 0" >
|
|
||||||
云端录像</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="record" v-bind:disabled="device == null || device.online === 0" >
|
|
||||||
设备录像控制-开始</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="stopRecord" v-bind:disabled="device == null || device.online === 0" >
|
|
||||||
设备录像控制-停止</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
|
|
||||||
</el-dropdown>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
|
||||||
<channel-edit v-if="editId" :id="editId" :closeEdit="closeEdit"></channel-edit>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import devicePlayer from './dialog/devicePlayer.vue'
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import DeviceService from "./service/DeviceService";
|
|
||||||
import DeviceTree from "./common/DeviceTree";
|
|
||||||
import ChannelEdit from "./ChannelEdit";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'channelList',
|
|
||||||
components: {
|
|
||||||
devicePlayer,
|
|
||||||
uiHeader,
|
|
||||||
DeviceTree,
|
|
||||||
ChannelEdit,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
deviceService: new DeviceService(),
|
|
||||||
device: null,
|
|
||||||
deviceId: this.$route.params.deviceId,
|
|
||||||
parentChannelId: this.$route.params.parentChannelId,
|
|
||||||
deviceChannelList: [],
|
|
||||||
videoComponentList: [],
|
|
||||||
currentPlayerInfo: {}, //当前播放对象
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
searchSrt: "",
|
|
||||||
channelType: "",
|
|
||||||
online: "",
|
|
||||||
subStream: "",
|
|
||||||
winHeight: window.innerHeight - 200,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
beforeUrl: "/deviceList",
|
|
||||||
showTree: false,
|
|
||||||
editId: null,
|
|
||||||
loadSnap: {},
|
|
||||||
ptzTypes: {
|
|
||||||
0: "未知",
|
|
||||||
1: "球机",
|
|
||||||
2: "半球",
|
|
||||||
3: "固定枪机",
|
|
||||||
4: "遥控枪机"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
if (this.deviceId) {
|
|
||||||
this.deviceService.getDevice(this.deviceId, (result) => {
|
|
||||||
this.device = result;
|
|
||||||
|
|
||||||
}, (error) => {
|
|
||||||
console.log("获取设备信息失败")
|
|
||||||
console.error(error)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.initData();
|
|
||||||
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$destroy('videojs');
|
|
||||||
clearTimeout(this.updateLooper);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
if (typeof (this.parentChannelId) == "undefined" || this.parentChannelId == 0) {
|
|
||||||
this.getDeviceChannelList();
|
|
||||||
} else {
|
|
||||||
this.showSubchannels();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initParam: function () {
|
|
||||||
this.deviceId = this.$route.params.deviceId;
|
|
||||||
this.parentChannelId = this.$route.params.parentChannelId;
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.count = 15;
|
|
||||||
if (this.parentChannelId == "" || this.parentChannelId == 0) {
|
|
||||||
this.beforeUrl = "/deviceList"
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getDeviceChannelList();
|
|
||||||
},
|
|
||||||
getDeviceChannelList: function () {
|
|
||||||
let that = this;
|
|
||||||
if (typeof (this.$route.params.deviceId) == "undefined") return;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`,
|
|
||||||
params: {
|
|
||||||
page: that.currentPage,
|
|
||||||
count: that.count,
|
|
||||||
query: that.searchSrt,
|
|
||||||
online: that.online,
|
|
||||||
channelType: that.channelType
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.total = res.data.data.total;
|
|
||||||
that.deviceChannelList = res.data.data.list;
|
|
||||||
that.deviceChannelList.forEach(e => {
|
|
||||||
e.ptzType = e.ptzType + "";
|
|
||||||
that.$set(e, "playLoading", false);
|
|
||||||
});
|
|
||||||
// 防止出现表格错位
|
|
||||||
that.$nextTick(() => {
|
|
||||||
that.$refs.channelListTable.doLayout();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
//通知设备上传媒体流
|
|
||||||
sendDevicePush: function (itemData) {
|
|
||||||
let deviceId = this.deviceId;
|
|
||||||
let channelId = itemData.deviceId;
|
|
||||||
itemData.playLoading = true;
|
|
||||||
console.log("通知设备推流1:" + deviceId + " : " + channelId);
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/play/start/' + deviceId + '/' + channelId,
|
|
||||||
params: {
|
|
||||||
isSubStream: this.isSubStream
|
|
||||||
}
|
|
||||||
}).then((res) =>{
|
|
||||||
console.log(res)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
let snapId = deviceId + "_" + channelId;
|
|
||||||
this.loadSnap[deviceId + channelId] = 0;
|
|
||||||
this.getSnapErrorEvent(snapId)
|
|
||||||
}, 5000)
|
|
||||||
itemData.streamId = res.data.data.stream;
|
|
||||||
this.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
|
|
||||||
streamInfo: res.data.data,
|
|
||||||
hasAudio: itemData.hasAudio
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
this.initData();
|
|
||||||
}, 1000)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.data.msg);
|
|
||||||
}
|
|
||||||
}).catch(function (e) {
|
|
||||||
console.error(e)
|
|
||||||
// that.$message.error("请求超时");
|
|
||||||
}).finally(()=>{
|
|
||||||
itemData.playLoading = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
moreClick: function (command, itemData) {
|
|
||||||
if (command === "records") {
|
|
||||||
this.queryRecords(itemData)
|
|
||||||
}else if (command === "cloudRecords") {
|
|
||||||
this.queryCloudRecords(itemData)
|
|
||||||
}else if (command === "record") {
|
|
||||||
this.startRecord(itemData)
|
|
||||||
}else if (command === "stopRecord") {
|
|
||||||
this.stopRecord(itemData)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
queryRecords: function (itemData) {
|
|
||||||
let deviceId = this.deviceId;
|
|
||||||
let channelId = itemData.deviceId;
|
|
||||||
|
|
||||||
this.$router.push(`/gbRecordDetail/${deviceId}/${channelId}`)
|
|
||||||
},
|
|
||||||
queryCloudRecords: function (itemData) {
|
|
||||||
let deviceId = this.deviceId;
|
|
||||||
let channelId = itemData.deviceId;
|
|
||||||
|
|
||||||
this.$router.push(`/cloudRecordDetail/rtp/${deviceId}_${channelId}`)
|
|
||||||
},
|
|
||||||
startRecord: function (itemData) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/control/record`,
|
|
||||||
params: {
|
|
||||||
deviceId: this.deviceId,
|
|
||||||
channelId: itemData.deviceId,
|
|
||||||
recordCmdStr: "Record"
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "开始录像成功"
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error.message
|
|
||||||
})
|
|
||||||
});
|
|
||||||
},
|
|
||||||
stopRecord: function (itemData) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/control/record`,
|
|
||||||
params: {
|
|
||||||
deviceId: this.deviceId,
|
|
||||||
channelId: itemData.deviceId,
|
|
||||||
recordCmdStr: "StopRecord"
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "停止录像成功"
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error.message
|
|
||||||
})
|
|
||||||
});
|
|
||||||
},
|
|
||||||
stopDevicePush: function (itemData) {
|
|
||||||
var that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/play/stop/' + this.deviceId + "/" + itemData.deviceId,
|
|
||||||
params: {
|
|
||||||
isSubStream: this.isSubStream
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
that.initData();
|
|
||||||
}).catch(function (error) {
|
|
||||||
if (error.response.status === 402) { // 已经停止过
|
|
||||||
that.initData();
|
|
||||||
} else {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getSnap: function (row) {
|
|
||||||
let baseUrl = window.baseUrl ? window.baseUrl : "";
|
|
||||||
return ((process.env.NODE_ENV === 'development') ? process.env.BASE_API : baseUrl) + '/api/device/query/snap/' + this.deviceId + '/' + row.deviceId;
|
|
||||||
},
|
|
||||||
getBigSnap: function (row) {
|
|
||||||
return [this.getSnap(row)]
|
|
||||||
},
|
|
||||||
getSnapErrorEvent: function (deviceId, channelId) {
|
|
||||||
|
|
||||||
if (typeof (this.loadSnap[deviceId + channelId]) != "undefined") {
|
|
||||||
console.log("下载截图" + this.loadSnap[deviceId + channelId])
|
|
||||||
if (this.loadSnap[deviceId + channelId] > 5) {
|
|
||||||
delete this.loadSnap[deviceId + channelId];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
let url = (process.env.NODE_ENV === 'development' ? "debug" : "") + '/api/device/query/snap/' + deviceId + '/' + channelId
|
|
||||||
this.loadSnap[deviceId + channelId]++
|
|
||||||
document.getElementById(deviceId + channelId).setAttribute("src", url + '?' + new Date().getTime())
|
|
||||||
}, 1000)
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
showDevice: function () {
|
|
||||||
this.$router.push(this.beforeUrl).then(() => {
|
|
||||||
this.initParam();
|
|
||||||
this.initData();
|
|
||||||
})
|
|
||||||
},
|
|
||||||
changeSubchannel(itemData) {
|
|
||||||
this.beforeUrl = this.$router.currentRoute.path;
|
|
||||||
|
|
||||||
var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.deviceId}`
|
|
||||||
this.$router.push(url).then(() => {
|
|
||||||
this.searchSrt = "";
|
|
||||||
this.channelType = "";
|
|
||||||
this.online = "";
|
|
||||||
this.initParam();
|
|
||||||
this.initData();
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showSubchannels: function (channelId) {
|
|
||||||
if (!this.showTree) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
query: this.searchSrt,
|
|
||||||
online: this.online,
|
|
||||||
channelType: this.channelType
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.deviceChannelList = res.data.data.list;
|
|
||||||
this.deviceChannelList.forEach(e => {
|
|
||||||
e.ptzType = e.ptzType + "";
|
|
||||||
});
|
|
||||||
// 防止出现表格错位
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.channelListTable.doLayout();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/query/tree/channel/${this.deviceId}`,
|
|
||||||
params: {
|
|
||||||
parentId: this.parentChannelId,
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.total;
|
|
||||||
this.deviceChannelList = res.data.list;
|
|
||||||
// 防止出现表格错位
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.channelListTable.doLayout();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
search: function () {
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.total = 0;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
updateChannel: function (row) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/device/query/channel/audio`,
|
|
||||||
params: {
|
|
||||||
channelId: row.id,
|
|
||||||
audio: row.hasAudio
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
console.log(JSON.stringify(res));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
subStreamChange: function () {
|
|
||||||
this.$confirm('确定重置所有通道的码流类型?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/device/query/channel/stream/identification/update/`,
|
|
||||||
params: {
|
|
||||||
deviceDbId: this.device.id,
|
|
||||||
streamIdentification: this.subStream
|
|
||||||
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
console.log(JSON.stringify(res));
|
|
||||||
this.initData()
|
|
||||||
}).finally(()=>{
|
|
||||||
this.subStream = ""
|
|
||||||
})
|
|
||||||
}).catch(() => {
|
|
||||||
this.subStream = ""
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
channelSubStreamChange: function (row) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/device/query/channel/stream/identification/update/`,
|
|
||||||
params: {
|
|
||||||
deviceDbId: row.deviceDbId,
|
|
||||||
id: row.id,
|
|
||||||
streamIdentification: row.streamIdentification
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
console.log(JSON.stringify(res));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
refresh: function () {
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
switchTree: function () {
|
|
||||||
this.showTree = true;
|
|
||||||
this.deviceChannelList = [];
|
|
||||||
this.parentChannelId = 0;
|
|
||||||
this.currentPage = 1;
|
|
||||||
|
|
||||||
},
|
|
||||||
switchList: function () {
|
|
||||||
this.showTree = false;
|
|
||||||
this.deviceChannelList = [];
|
|
||||||
this.parentChannelId = 0;
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
treeNodeClickEvent: function (device, data, isCatalog) {
|
|
||||||
console.log(device)
|
|
||||||
if (!!!data.channelId) {
|
|
||||||
this.parentChannelId = device.deviceId;
|
|
||||||
} else {
|
|
||||||
this.parentChannelId = data.channelId;
|
|
||||||
}
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
// 编辑
|
|
||||||
handleEdit(row) {
|
|
||||||
this.editId = row.id
|
|
||||||
},
|
|
||||||
// 结束编辑
|
|
||||||
closeEdit: function (){
|
|
||||||
this.editId = null
|
|
||||||
this.getDeviceChannelList()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.videoList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item {
|
|
||||||
position: relative;
|
|
||||||
width: 15rem;
|
|
||||||
height: 10rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img:after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
background-image: url("../assets/loading.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-title {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #ffffff;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0.3rem;
|
|
||||||
width: 14.4rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,425 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="CommonChannelEdit" v-loading="locading" style="width: 100%">
|
|
||||||
<el-form ref="passwordForm" status-icon label-width="160px" class="channel-form">
|
|
||||||
<div class="form-box">
|
|
||||||
<el-form-item label="名称" >
|
|
||||||
<el-input v-model="form.gbName" placeholder="请输入通道名称"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="编码" >
|
|
||||||
<el-input v-model="form.gbDeviceId" placeholder="请输入通道编码">
|
|
||||||
<template v-slot:append>
|
|
||||||
<el-button @click="buildDeviceIdCode(form.gbDeviceId)">生成</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备厂商" >
|
|
||||||
<el-input v-model="form.gbManufacturer" placeholder="请输入设备厂商"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备型号" >
|
|
||||||
<el-input v-model="form.gbModel" placeholder="请输入设备型号"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="行政区域" >
|
|
||||||
<el-input v-model="form.gbCivilCode" placeholder="请输入行政区域">
|
|
||||||
<template v-slot:append>
|
|
||||||
<el-button @click="chooseCivilCode()">选择</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="安装地址" >
|
|
||||||
<el-input v-model="form.gbAddress" placeholder="请输入安装地址"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="子设备" >
|
|
||||||
<el-select v-model="form.gbParental" style="width: 100%" placeholder="请选择是否有子设备">
|
|
||||||
<el-option label="有" :value="1"></el-option>
|
|
||||||
<el-option label="无" :value="0"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="父节点编码" >
|
|
||||||
<el-input v-model="form.gbParentId" placeholder="请输入父节点编码或选择所属虚拟组织">
|
|
||||||
<template v-slot:append>
|
|
||||||
<el-button @click="chooseGroup()">选择</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备状态" >
|
|
||||||
<el-select v-model="form.gbStatus" style="width: 100%" placeholder="请选择设备状态">
|
|
||||||
<el-option label="在线" value="ON"></el-option>
|
|
||||||
<el-option label="离线" value="OFF"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="经度" >
|
|
||||||
<el-input v-model="form.gbLongitude" placeholder="请输入经度"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="纬度" >
|
|
||||||
<el-input v-model="form.gbLatitude" placeholder="请输入纬度"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="云台类型" >
|
|
||||||
<el-select v-model="form.gbPtzType" style="width: 100%" placeholder="请选择云台类型">
|
|
||||||
<el-option label="球机" :value="1"></el-option>
|
|
||||||
<el-option label="半球" :value="2"></el-option>
|
|
||||||
<el-option label="固定枪机" :value="3"></el-option>
|
|
||||||
<el-option label="遥控枪机" :value="4"></el-option>
|
|
||||||
<el-option label="遥控半球" :value="5"></el-option>
|
|
||||||
<el-option label="多目设备的全景/拼接通道" :value="6"></el-option>
|
|
||||||
<el-option label="多目设备的分割通道" :value="7"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-form-item label="警区" >
|
|
||||||
<el-input v-model="form.gbBlock" placeholder="请输入警区"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备归属" >
|
|
||||||
<el-input v-model="form.gbOwner" placeholder="请输入设备归属"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="信令安全模式" >
|
|
||||||
<el-select v-model="form.gbSafetyWay" style="width: 100%" placeholder="请选择信令安全模式">
|
|
||||||
<el-option label="不采用" :value="0"></el-option>
|
|
||||||
<el-option label="S/MIME签名" :value="2"></el-option>
|
|
||||||
<el-option label="S/MIME加密签名同时采用" :value="3"></el-option>
|
|
||||||
<el-option label="数字摘要" :value="4"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="注册方式" >
|
|
||||||
<el-select v-model="form.gbRegisterWay" style="width: 100%" placeholder="请选择注册方式">
|
|
||||||
<el-option label="IETFRFC3261标准" :value="1"></el-option>
|
|
||||||
<el-option label="基于口令的双向认证" :value="2"></el-option>
|
|
||||||
<el-option label="基于数字证书的双向认证注册" :value="3"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="证书序列号" >
|
|
||||||
<el-input type="number" v-model="form.gbCertNum" placeholder="请输入证书序列号"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="证书有效标识" >
|
|
||||||
<el-select v-model="form.gbCertifiable" style="width: 100%" placeholder="请选择证书有效标识">
|
|
||||||
<el-option label="有效" :value="1"></el-option>
|
|
||||||
<el-option label="无效" :value="0"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="无效原因码" >
|
|
||||||
<el-input type="errCode" v-model="form.gbCertNum" placeholder="请输入无效原因码"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="证书终止有效期" >
|
|
||||||
<el-date-picker
|
|
||||||
v-model="form.gbEndTime"
|
|
||||||
type="datetime"
|
|
||||||
placeholder="选择日期时间"
|
|
||||||
style="width: 100%">
|
|
||||||
</el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="保密属性" >
|
|
||||||
<el-select v-model="form.gbSecrecy" style="width: 100%" placeholder="请选择保密属性">
|
|
||||||
<el-option label="不涉密" :value="0"></el-option>
|
|
||||||
<el-option label="涉密" :value="1"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="IP地址" >
|
|
||||||
<el-input v-model="form.gbIpAddress" placeholder="请输入IP地址"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="端口" >
|
|
||||||
<el-input type="number" v-model="form.gbPort" placeholder="请输入端口"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备口令" >
|
|
||||||
<el-input v-model="form.gbPassword" placeholder="请输入设备口令"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-form-item label="业务分组编号" >
|
|
||||||
<el-input v-model="form.gbBusinessGroupId" placeholder="请输入业务分组编号"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="位置类型" >
|
|
||||||
<el-select v-model="form.gbPositionType" style="width: 100%" placeholder="请选择位置类型">
|
|
||||||
<el-option label="省际检查站" :value="1"></el-option>
|
|
||||||
<el-option label="党政机关" :value="2"></el-option>
|
|
||||||
<el-option label="车站码头" :value="3"></el-option>
|
|
||||||
<el-option label="中心广场" :value="4"></el-option>
|
|
||||||
<el-option label="体育场馆" :value="5"></el-option>
|
|
||||||
<el-option label="商业中心" :value="6"></el-option>
|
|
||||||
<el-option label="宗教场所" :value="7"></el-option>
|
|
||||||
<el-option label="校园周边" :value="8"></el-option>
|
|
||||||
<el-option label="治安复杂区域" :value="9"></el-option>
|
|
||||||
<el-option label="交通干线" :value="10"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="室外/室内" >
|
|
||||||
<el-select v-model="form.gbRoomType" style="width: 100%" placeholder="请选择位置类型">
|
|
||||||
<el-option label="室外" :value="1"></el-option>
|
|
||||||
<el-option label="室内" :value="2"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="用途" >
|
|
||||||
<el-select v-model="form.gbUseType" style="width: 100%" placeholder="请选择位置类型">
|
|
||||||
<el-option label="治安" :value="1"></el-option>
|
|
||||||
<el-option label="交通" :value="2"></el-option>
|
|
||||||
<el-option label="重点" :value="3"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="补光" >
|
|
||||||
<el-select v-model="form.gbSupplyLightType" style="width: 100%" placeholder="请选择位置类型">
|
|
||||||
<el-option label="无补光" :value="1"></el-option>
|
|
||||||
<el-option label="红外补光" :value="2"></el-option>
|
|
||||||
<el-option label="白光补光" :value="3"></el-option>
|
|
||||||
<el-option label="激光补光" :value="4"></el-option>
|
|
||||||
<el-option label="其他" :value="9"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="监视方位" >
|
|
||||||
<el-select v-model="form.gbDirectionType" style="width: 100%" placeholder="请选择位置类型">
|
|
||||||
<el-option label="东(西向东)" :value="1"></el-option>
|
|
||||||
<el-option label="西(东向西)" :value="2"></el-option>
|
|
||||||
<el-option label="南(北向南)" :value="3"></el-option>
|
|
||||||
<el-option label="北(南向北)" :value="4"></el-option>
|
|
||||||
<el-option label="东南(西北到东南)" :value="5"></el-option>
|
|
||||||
<el-option label="东北(西南到东北)" :value="6"></el-option>
|
|
||||||
<el-option label="西南(东北到西南)" :value="7"></el-option>
|
|
||||||
<el-option label="西北(东南到西北)" :value="8"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="分辨率" >
|
|
||||||
<el-input v-model="form.gbResolution" placeholder="请输入分辨率"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="下载倍速" >
|
|
||||||
<el-select v-model="form.gbDownloadSpeedArray" multiple style="width: 100%" placeholder="请选择位置类型">
|
|
||||||
<el-option label="1倍速" value="1"></el-option>
|
|
||||||
<el-option label="2倍速" value="2"></el-option>
|
|
||||||
<el-option label="4倍速" value="4"></el-option>
|
|
||||||
<el-option label="8倍速" value="8"></el-option>
|
|
||||||
<el-option label="16倍速" value="16"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="空域编码能力" >
|
|
||||||
<el-select v-model="form.gbSvcSpaceSupportMod" style="width: 100%" placeholder="请选择空域编码能力">
|
|
||||||
<el-option label="1级增强" value="1"></el-option>
|
|
||||||
<el-option label="2级增强" value="2"></el-option>
|
|
||||||
<el-option label="3级增强" value="3"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="时域编码能力" >
|
|
||||||
<el-select v-model="form.gbSvcTimeSupportMode" style="width: 100%" placeholder="请选择空域编码能力">
|
|
||||||
<el-option label="1级增强" value="1"></el-option>
|
|
||||||
<el-option label="2级增强" value="2"></el-option>
|
|
||||||
<el-option label="3级增强" value="3"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button v-if="cancel" @click="cancelSubmit">取消</el-button>
|
|
||||||
<el-button v-if="form.dataType === 1" @click="reset">重置</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
<channelCode ref="channelCode"></channelCode>
|
|
||||||
<chooseCivilCode ref="chooseCivilCode"></chooseCivilCode>
|
|
||||||
<chooseGroup ref="chooseGroup"></chooseGroup>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import channelCode from './../dialog/channelCode'
|
|
||||||
import ChooseCivilCode from "../dialog/chooseCivilCode.vue";
|
|
||||||
import ChooseGroup from "../dialog/chooseGroup.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "CommonChannelEdit",
|
|
||||||
props: [ 'id', 'dataForm', 'saveSuccess', 'cancel'],
|
|
||||||
components: {
|
|
||||||
ChooseCivilCode,
|
|
||||||
ChooseGroup,
|
|
||||||
channelCode,
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
// 获取完整信息
|
|
||||||
if (this.id) {
|
|
||||||
this.getCommonChannel()
|
|
||||||
}else {
|
|
||||||
if(!this.dataForm.gbDeviceId) {
|
|
||||||
this.dataForm.gbDeviceId = ""
|
|
||||||
}
|
|
||||||
console.log(this.dataForm)
|
|
||||||
this.form = this.dataForm
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
locading: false,
|
|
||||||
form: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSubmit: function () {
|
|
||||||
this.locading = true
|
|
||||||
if (this.form.gbDownloadSpeedArray) {
|
|
||||||
this.form.gbDownloadSpeed = this.form.gbDownloadSpeedArray.join("/")
|
|
||||||
}
|
|
||||||
if (this.form.gbId) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/common/channel/update",
|
|
||||||
data: this.form
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
});
|
|
||||||
if (this.saveSuccess) {
|
|
||||||
this.saveSuccess()
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
this.locading = false
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/common/channel/add",
|
|
||||||
data: this.form
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
});
|
|
||||||
this.form = res.data.data
|
|
||||||
if (this.saveSuccess) {
|
|
||||||
this.saveSuccess()
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
this.locading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
reset: function () {
|
|
||||||
this.$confirm("确定重置为默认内容?", '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.locading = true
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/common/channel/reset",
|
|
||||||
params: {
|
|
||||||
id: this.form.gbId
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "重置成功 已保存"
|
|
||||||
});
|
|
||||||
this.getCommonChannel()
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
}).finally(()=>{
|
|
||||||
this.locading = false
|
|
||||||
})
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
getCommonChannel:function () {
|
|
||||||
this.locading = true
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/common/channel/one",
|
|
||||||
params: {
|
|
||||||
id: this.id
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (res.data.data.gbDownloadSpeed) {
|
|
||||||
res.data.data.gbDownloadSpeedArray = res.data.data.gbDownloadSpeed.split("/")
|
|
||||||
}
|
|
||||||
this.form = res.data.data;
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
}).finally(()=>{
|
|
||||||
this.locading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
buildDeviceIdCode: function (deviceId){
|
|
||||||
|
|
||||||
this.$refs.channelCode.openDialog(code=>{
|
|
||||||
console.log(this.form)
|
|
||||||
console.log("code===> " + code)
|
|
||||||
this.form.gbDeviceId = code;
|
|
||||||
console.log("code22===> " + code)
|
|
||||||
}, deviceId);
|
|
||||||
},
|
|
||||||
chooseCivilCode: function (){
|
|
||||||
this.$refs.chooseCivilCode.openDialog(code=>{
|
|
||||||
this.form.gbCivilCode = code;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
chooseGroup: function (){
|
|
||||||
this.$refs.chooseGroup.openDialog((deviceId, businessGroupId)=>{
|
|
||||||
this.form.gbBusinessGroupId = businessGroupId;
|
|
||||||
this.form.gbParentId = deviceId;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
cancelSubmit: function (){
|
|
||||||
if(this.cancel) {
|
|
||||||
this.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// getDeviceChannel:function (callback) {
|
|
||||||
// this.$axios({
|
|
||||||
// method: 'get',
|
|
||||||
// url: "/api/device/query/channel/raw",
|
|
||||||
// params: {
|
|
||||||
// id: this.id
|
|
||||||
// }
|
|
||||||
// }).then((res) => {
|
|
||||||
// if (res.data.code === 0) {
|
|
||||||
// if(callback) {
|
|
||||||
// callback(res.data.data)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }).catch((error) => {
|
|
||||||
// console.error(error)
|
|
||||||
// }).finally(()=>[
|
|
||||||
// this.locading = false
|
|
||||||
// ])
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto">
|
|
||||||
<el-container>
|
|
||||||
<el-header>
|
|
||||||
<div style="display: grid; grid-template-columns: auto auto">
|
|
||||||
<div >通道列表</div>
|
|
||||||
<div >
|
|
||||||
<el-switch
|
|
||||||
v-model="showRegion"
|
|
||||||
active-color="#13ce66"
|
|
||||||
inactive-color="rgb(64, 158, 255)"
|
|
||||||
active-text="行政区划"
|
|
||||||
inactive-text="业务分组">
|
|
||||||
</el-switch>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-header>
|
|
||||||
<el-main style="background-color: #ffffff;">
|
|
||||||
<RegionTree v-if="showRegion" ref="regionTree" :edit="false" :showHeader="false" :hasChannel="true" :clickEvent="treeNodeClickEvent" ></RegionTree>
|
|
||||||
<GroupTree v-if="!showRegion" ref="groupTree" :edit="false" :showHeader="false" :hasChannel="true" :clickEvent="treeNodeClickEvent" ></GroupTree>
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import DeviceService from "../service/DeviceService.js";
|
|
||||||
import RegionTree from "./RegionTree.vue";
|
|
||||||
import GroupTree from "./GroupTree.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DeviceTree',
|
|
||||||
components: {GroupTree, RegionTree},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showRegion: true,
|
|
||||||
deviceService: new DeviceService(),
|
|
||||||
defaultProps: {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
isLeaf: 'isLeaf'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: ['device', 'onlyCatalog', 'clickEvent', 'contextMenuEvent'],
|
|
||||||
methods: {
|
|
||||||
handleClick: function (tab, event){
|
|
||||||
},
|
|
||||||
treeNodeClickEvent: function (data){
|
|
||||||
|
|
||||||
if (data.leaf) {
|
|
||||||
console.log(23111)
|
|
||||||
console.log(data)
|
|
||||||
if (this.clickEvent){
|
|
||||||
this.clickEvent(data.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
// if (this.jessibuca) {
|
|
||||||
// this.jessibuca.destroy();
|
|
||||||
// }
|
|
||||||
// this.playing = false;
|
|
||||||
// this.loaded = false;
|
|
||||||
// this.performance = "";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.device-tree-main-box{
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.device-online{
|
|
||||||
color: #252525;
|
|
||||||
}
|
|
||||||
.device-offline{
|
|
||||||
color: #727272;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,393 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="DeviceTree">
|
|
||||||
<div v-if="showHeader" class="page-header" style="margin-bottom: 1rem;">
|
|
||||||
<div class="page-title">业务分组</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div style="display: inline;">
|
|
||||||
<el-input @input="search" style="visibility:hidden; margin-right: 1rem; width: 12rem;" size="mini"
|
|
||||||
placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
|
|
||||||
<el-checkbox v-model="showCode">显示编号</el-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="showHeader" style="height: 2rem; background-color: #FFFFFF"></div>
|
|
||||||
<div>
|
|
||||||
<el-alert v-if="showAlert && edit" title="操作提示" description="你可以使用右键菜单管理节点" type="info" style="text-align: left"></el-alert>
|
|
||||||
<vue-easy-tree
|
|
||||||
class="flow-tree"
|
|
||||||
ref="veTree"
|
|
||||||
node-key="treeId"
|
|
||||||
:height="treeHeight?treeHeight:'78vh'"
|
|
||||||
lazy
|
|
||||||
style="padding: 0 0 2rem 0.5rem"
|
|
||||||
:load="loadNode"
|
|
||||||
:data="treeData"
|
|
||||||
:props="props"
|
|
||||||
:default-expanded-keys="['']"
|
|
||||||
@node-contextmenu="contextmenuEventHandler"
|
|
||||||
@node-click="nodeClickHandler"
|
|
||||||
>
|
|
||||||
<template v-slot:default="{ node, data }">
|
|
||||||
<span class="custom-tree-node">
|
|
||||||
<span v-if="node.data.type === 0 && chooseId !== node.data.deviceId" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
|
|
||||||
<span v-if="node.data.type === 0 && chooseId === node.data.deviceId" style="color: #c60135;" class="iconfont icon-bianzubeifen3"></span>
|
|
||||||
<span v-if="node.data.type === 1 && node.data.status === 'ON'" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
|
|
||||||
<span v-if="node.data.type === 1 && node.data.status !== 'ON'" style="color: #808181" class="iconfont icon-shexiangtou2"></span>
|
|
||||||
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}(编号:{{ node.data.deviceId }})</span>
|
|
||||||
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</vue-easy-tree>
|
|
||||||
</div>
|
|
||||||
<groupEdit ref="groupEdit"></groupEdit>
|
|
||||||
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
|
|
||||||
<gbChannelSelect ref="gbChannelSelect" dataType="group"></gbChannelSelect>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import VueEasyTree from "@wchbrad/vue-easy-tree";
|
|
||||||
import groupEdit from './../dialog/groupEdit'
|
|
||||||
import gbDeviceSelect from './../dialog/GbDeviceSelect'
|
|
||||||
import GbChannelSelect from "../dialog/GbChannelSelect.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DeviceTree',
|
|
||||||
components: {
|
|
||||||
GbChannelSelect,
|
|
||||||
VueEasyTree, groupEdit, gbDeviceSelect
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
label: "name",
|
|
||||||
id: "treeId"
|
|
||||||
},
|
|
||||||
showCode: false,
|
|
||||||
showAlert: true,
|
|
||||||
searchSrt: "",
|
|
||||||
chooseId: "",
|
|
||||||
treeData: [],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: ['edit','enableAddChannel', 'clickEvent', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToGroup', 'treeHeight'],
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
search() {
|
|
||||||
|
|
||||||
},
|
|
||||||
loadNode: function (node, resolve) {
|
|
||||||
if (node.level === 0) {
|
|
||||||
resolve([{
|
|
||||||
treeId: "",
|
|
||||||
deviceId: "",
|
|
||||||
name: "根资源组",
|
|
||||||
isLeaf: false,
|
|
||||||
type: 0
|
|
||||||
}]);
|
|
||||||
} else {
|
|
||||||
if (node.data.leaf) {
|
|
||||||
resolve([]);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/group/tree/list`,
|
|
||||||
params: {
|
|
||||||
query: this.searchSrt,
|
|
||||||
parent: node.data.id,
|
|
||||||
hasChannel: this.hasChannel
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (res.data.data.length > 0) {
|
|
||||||
this.showAlert = false
|
|
||||||
}
|
|
||||||
resolve(res.data.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
reset: function () {
|
|
||||||
this.$forceUpdate();
|
|
||||||
},
|
|
||||||
contextmenuEventHandler: function (event, data, node, element) {
|
|
||||||
if (!this.edit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (node.data.type === 0) {
|
|
||||||
let menuItem = [
|
|
||||||
{
|
|
||||||
label: "刷新节点",
|
|
||||||
icon: "el-icon-refresh",
|
|
||||||
disabled: false,
|
|
||||||
onClick: () => {
|
|
||||||
this.refreshNode(node);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "新建节点",
|
|
||||||
icon: "el-icon-plus",
|
|
||||||
disabled: false,
|
|
||||||
onClick: () => {
|
|
||||||
this.addGroup(data.id, node);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "编辑节点",
|
|
||||||
icon: "el-icon-edit",
|
|
||||||
disabled: node.level === 1,
|
|
||||||
onClick: () => {
|
|
||||||
this.editGroup(data, node);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "删除节点",
|
|
||||||
icon: "el-icon-delete",
|
|
||||||
disabled: node.level === 1,
|
|
||||||
divided: true,
|
|
||||||
onClick: () => {
|
|
||||||
this.$confirm('确定删除?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.removeGroup(data.id, node)
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
if (this.enableAddChannel) {
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: "添加设备",
|
|
||||||
icon: "el-icon-plus",
|
|
||||||
disabled: node.level <= 2,
|
|
||||||
onClick: () => {
|
|
||||||
this.addChannelFormDevice(data.id, node)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: "移除设备",
|
|
||||||
icon: "el-icon-delete",
|
|
||||||
disabled: node.level <= 2,
|
|
||||||
divided: true,
|
|
||||||
onClick: () => {
|
|
||||||
this.removeChannelFormDevice(data.id, node)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: "添加通道",
|
|
||||||
icon: "el-icon-plus",
|
|
||||||
disabled: node.level <= 2,
|
|
||||||
onClick: () => {
|
|
||||||
this.addChannel(data.id, node)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$contextmenu({
|
|
||||||
items: menuItem,
|
|
||||||
event, // 鼠标事件信息
|
|
||||||
customClass: "custom-class", // 自定义菜单 class
|
|
||||||
zIndex: 3000, // 菜单样式 z-index
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
removeGroup: function (id, node) {
|
|
||||||
this.$axios({
|
|
||||||
method: "delete",
|
|
||||||
url: `/api/group/delete`,
|
|
||||||
params: {
|
|
||||||
id: node.data.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
console.log("移除成功")
|
|
||||||
node.parent.loaded = false
|
|
||||||
node.parent.expand();
|
|
||||||
if (this.onChannelChange) {
|
|
||||||
this.onChannelChange(node.data.deviceId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addChannelFormDevice: function (id, node) {
|
|
||||||
this.$refs.gbDeviceSelect.openDialog((rows) => {
|
|
||||||
let deviceIds = []
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
|
||||||
deviceIds.push(rows[i].id)
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/common/channel/group/device/add`,
|
|
||||||
data: {
|
|
||||||
parentId: node.data.deviceId,
|
|
||||||
businessGroup: node.data.businessGroup,
|
|
||||||
deviceIds: deviceIds,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
})
|
|
||||||
if (this.onChannelChange) {
|
|
||||||
this.onChannelChange()
|
|
||||||
}
|
|
||||||
console.log(node)
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
this.loading = false
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
removeChannelFormDevice: function (id, node) {
|
|
||||||
this.$refs.gbDeviceSelect.openDialog((rows) => {
|
|
||||||
let deviceIds = []
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
|
||||||
deviceIds.push(rows[i].id)
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/common/channel/group/device/delete`,
|
|
||||||
data: {
|
|
||||||
deviceIds: deviceIds,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
})
|
|
||||||
if (this.onChannelChange) {
|
|
||||||
this.onChannelChange()
|
|
||||||
}
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
this.loading = false
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addChannel: function (id, node) {
|
|
||||||
this.$refs.gbChannelSelect.openDialog((data) => {
|
|
||||||
console.log("选择的数据")
|
|
||||||
console.log(data)
|
|
||||||
this.addChannelToGroup(node.data.deviceId, node.data.businessGroup, data)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
refreshNode: function (node) {
|
|
||||||
console.log(node)
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
},
|
|
||||||
refresh: function (id) {
|
|
||||||
console.log("刷新节点: " + id)
|
|
||||||
// 查询node
|
|
||||||
let node = this.$refs.veTree.getNode(id)
|
|
||||||
if (node) {
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addGroup: function (id, node) {
|
|
||||||
this.$refs.groupEdit.openDialog({
|
|
||||||
id: 0,
|
|
||||||
name: "",
|
|
||||||
deviceId: "",
|
|
||||||
civilCode: "",
|
|
||||||
parentDeviceId: node.level > 2 ? node.data.deviceId : "",
|
|
||||||
parentId: node.data.id,
|
|
||||||
businessGroup: node.level > 2 ? node.data.businessGroup : node.data.deviceId,
|
|
||||||
}, form => {
|
|
||||||
console.log(node)
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
}, id);
|
|
||||||
},
|
|
||||||
editGroup: function (id, node) {
|
|
||||||
console.log(node)
|
|
||||||
this.$refs.groupEdit.openDialog(node.data, form => {
|
|
||||||
console.log(node)
|
|
||||||
node.parent.loaded = false
|
|
||||||
node.parent.expand();
|
|
||||||
}, id);
|
|
||||||
},
|
|
||||||
nodeClickHandler: function (data, node, tree) {
|
|
||||||
this.chooseId = data.deviceId;
|
|
||||||
if (this.clickEvent) {
|
|
||||||
this.clickEvent(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
// if (this.jessibuca) {
|
|
||||||
// this.jessibuca.destroy();
|
|
||||||
// }
|
|
||||||
// this.playing = false;
|
|
||||||
// this.loaded = false;
|
|
||||||
// this.performance = "";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.device-tree-main-box {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-online {
|
|
||||||
color: #252525;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-offline {
|
|
||||||
color: #727272;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-tree-node .el-radio__label {
|
|
||||||
padding-left: 4px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,263 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="mapContainer" ref="mapContainer" style="width: 100%;height: 100%;"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import 'ol/ol.css';
|
|
||||||
import Map from 'ol/Map';
|
|
||||||
import OSM from 'ol/source/OSM';
|
|
||||||
import XYZ from 'ol/source/XYZ';
|
|
||||||
import VectorSource from 'ol/source/Vector';
|
|
||||||
import Tile from 'ol/layer/Tile';
|
|
||||||
import VectorLayer from 'ol/layer/Vector';
|
|
||||||
import Style from 'ol/style/Style';
|
|
||||||
import Stroke from 'ol/style/Stroke';
|
|
||||||
import Icon from 'ol/style/Icon';
|
|
||||||
import View from 'ol/View';
|
|
||||||
import Feature from 'ol/Feature';
|
|
||||||
import Overlay from 'ol/Overlay';
|
|
||||||
import {Point, LineString} from 'ol/geom';
|
|
||||||
import {get as getProj, fromLonLat} from 'ol/proj';
|
|
||||||
import {ZoomSlider, Zoom} from 'ol/control';
|
|
||||||
import {containsCoordinate} from 'ol/extent';
|
|
||||||
|
|
||||||
import {v4} from 'uuid'
|
|
||||||
|
|
||||||
let olMap = null;
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MapComponent',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created(){
|
|
||||||
this.$nextTick(() => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.init()
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
props: [],
|
|
||||||
mounted () {
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
init(){
|
|
||||||
|
|
||||||
let center = fromLonLat([116.41020, 39.915119]);
|
|
||||||
if (mapParam.center) {
|
|
||||||
center = fromLonLat(mapParam.center);
|
|
||||||
}
|
|
||||||
const view = new View({
|
|
||||||
center: center,
|
|
||||||
zoom: mapParam.zoom || 10,
|
|
||||||
projection: this.projection,
|
|
||||||
maxZoom: mapParam.maxZoom || 19,
|
|
||||||
minZoom: mapParam.minZoom || 1,
|
|
||||||
});
|
|
||||||
let tileLayer = null;
|
|
||||||
if (mapParam.tilesUrl) {
|
|
||||||
tileLayer = new Tile({
|
|
||||||
source: new XYZ({
|
|
||||||
projection: getProj("EPSG:3857"),
|
|
||||||
wrapX: false,
|
|
||||||
tileSize: 256 || mapParam.tileSize,
|
|
||||||
url: mapParam.tilesUrl
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
tileLayer = new Tile({
|
|
||||||
preload: 4,
|
|
||||||
source: new OSM(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
olMap = new Map({
|
|
||||||
target: this.$refs.mapContainer, // 容器ID
|
|
||||||
layers: [tileLayer], // 默认图层
|
|
||||||
view: view, // 视图
|
|
||||||
controls:[ // 控件
|
|
||||||
// new ZoomSlider(),
|
|
||||||
new Zoom(),
|
|
||||||
] ,
|
|
||||||
})
|
|
||||||
console.log(3222)
|
|
||||||
},
|
|
||||||
setCenter(point){
|
|
||||||
|
|
||||||
},
|
|
||||||
zoomIn(zoom){
|
|
||||||
|
|
||||||
},
|
|
||||||
zoomOut(zoom){
|
|
||||||
|
|
||||||
},
|
|
||||||
centerAndZoom(point,zoom,callback){
|
|
||||||
var zoom_ = olMap.getView().getZoom();
|
|
||||||
zoom = zoom|| zoom_;
|
|
||||||
var duration = 600;
|
|
||||||
olMap.getView().setCenter(fromLonLat(point))
|
|
||||||
olMap.getView().animate({
|
|
||||||
zoom: zoom ,
|
|
||||||
duration: duration
|
|
||||||
});
|
|
||||||
},
|
|
||||||
panTo(point, zoom){
|
|
||||||
let duration = 800;
|
|
||||||
|
|
||||||
olMap.getView().cancelAnimations()
|
|
||||||
olMap.getView().animate({
|
|
||||||
center: fromLonLat(point),
|
|
||||||
duration: duration
|
|
||||||
});
|
|
||||||
if (!containsCoordinate(olMap.getView().calculateExtent(), fromLonLat(point))) {
|
|
||||||
olMap.getView().animate({
|
|
||||||
zoom: olMap.getView().getZoom() - 1,
|
|
||||||
duration: duration / 2
|
|
||||||
}, {
|
|
||||||
zoom: zoom || olMap.getView().getZoom(),
|
|
||||||
duration: duration / 2
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
fit(layer){
|
|
||||||
let extent = layer.getSource().getExtent();
|
|
||||||
if (extent) {
|
|
||||||
olMap.getView().fit(extent,{
|
|
||||||
duration : 600,
|
|
||||||
padding: [100, 100, 100, 100]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
openInfoBox(position, content, offset){
|
|
||||||
let id = v4()
|
|
||||||
// let infoBox = document.createElement("div");
|
|
||||||
// infoBox.innerHTML = content ;
|
|
||||||
// infoBox.setAttribute("infoBoxId", id)
|
|
||||||
let overlay = new Overlay({
|
|
||||||
id:id,
|
|
||||||
autoPan:true,
|
|
||||||
autoPanAnimation:{
|
|
||||||
duration: 250
|
|
||||||
},
|
|
||||||
element: content,
|
|
||||||
positioning:"bottom-center",
|
|
||||||
offset:offset,
|
|
||||||
// className:overlayStyle.className
|
|
||||||
});
|
|
||||||
olMap.addOverlay(overlay);
|
|
||||||
overlay.setPosition(fromLonLat(position));
|
|
||||||
return id;
|
|
||||||
},
|
|
||||||
closeInfoBox(id){
|
|
||||||
olMap.getOverlayById(id).setPosition(undefined)
|
|
||||||
// olMap.removeOverlay(olMap.getOverlayById(id))
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 添加图层
|
|
||||||
* @param data
|
|
||||||
* [
|
|
||||||
* {
|
|
||||||
*
|
|
||||||
* position: [119.1212,45,122],
|
|
||||||
* image: {
|
|
||||||
* src:"/images/123.png",
|
|
||||||
* anchor: [0.5, 0.5]
|
|
||||||
*
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
addLayer(data, clickEvent){
|
|
||||||
let style = new Style();
|
|
||||||
if (data.length > 0) {
|
|
||||||
let features = [];
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
let feature = new Feature(new Point(fromLonLat(data[i].position)));
|
|
||||||
feature.customData = data[i].data;
|
|
||||||
let cloneStyle = style.clone()
|
|
||||||
cloneStyle.setImage(new Icon({
|
|
||||||
anchor: data[i].image.anchor,
|
|
||||||
crossOrigin: 'Anonymous',
|
|
||||||
src: data[i].image.src,
|
|
||||||
}))
|
|
||||||
feature.setStyle(cloneStyle)
|
|
||||||
features.push(feature);
|
|
||||||
}
|
|
||||||
let source = new VectorSource();
|
|
||||||
source.addFeatures(features);
|
|
||||||
let vectorLayer = new VectorLayer({
|
|
||||||
source:source,
|
|
||||||
style:style,
|
|
||||||
renderMode:"image",
|
|
||||||
declutter: false
|
|
||||||
})
|
|
||||||
olMap.addLayer(vectorLayer)
|
|
||||||
if (typeof clickEvent == "function") {
|
|
||||||
olMap.on("click", (event)=>{
|
|
||||||
vectorLayer.getFeatures(event.pixel).then((features)=>{
|
|
||||||
if (features.length > 0) {
|
|
||||||
let items = []
|
|
||||||
for (let i = 0; i < features.length; i++) {
|
|
||||||
items.push(features[i].customData)
|
|
||||||
}
|
|
||||||
clickEvent(items)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return vectorLayer;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeLayer(layer){
|
|
||||||
olMap.removeLayer(layer)
|
|
||||||
},
|
|
||||||
|
|
||||||
addLineLayer(positions) {
|
|
||||||
if (positions.length > 0) {
|
|
||||||
let points = [];
|
|
||||||
for (let i = 0; i < positions.length; i++) {
|
|
||||||
points.push(fromLonLat(positions[i]));
|
|
||||||
}
|
|
||||||
let line = new LineString(points)
|
|
||||||
let lineFeature = new Feature(line);
|
|
||||||
lineFeature.setStyle(new Style({
|
|
||||||
stroke: new Stroke({
|
|
||||||
width: 4 ,
|
|
||||||
color: "#0c6d6a",
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
let source = new VectorSource();
|
|
||||||
source.addFeature(lineFeature);
|
|
||||||
let vectorLayer = new VectorLayer({
|
|
||||||
source: source,
|
|
||||||
})
|
|
||||||
olMap.addLayer(vectorLayer)
|
|
||||||
return vectorLayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
// if (this.jessibuca) {
|
|
||||||
// this.jessibuca.destroy();
|
|
||||||
// }
|
|
||||||
// this.playing = false;
|
|
||||||
// this.loaded = false;
|
|
||||||
// this.performance = "";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,386 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="DeviceTree">
|
|
||||||
<div class="page-header" style="margin-bottom: 1rem;" v-if="showHeader">
|
|
||||||
<div class="page-title">行政区划</div>
|
|
||||||
<div class="page-header-btn">
|
|
||||||
<div style="display: inline;">
|
|
||||||
<el-input @input="search" style="visibility:hidden; margin-right: 1rem; width: 12rem;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
|
|
||||||
<el-checkbox v-model="showCode">显示编号</el-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="showHeader" style="height: 2rem; background-color: #FFFFFF" ></div>
|
|
||||||
<div>
|
|
||||||
<el-alert v-if="showAlert && edit" title="操作提示" description="你可以使用右键菜单管理节点" type="info" style="text-align: left"></el-alert>
|
|
||||||
<vue-easy-tree
|
|
||||||
class="flow-tree"
|
|
||||||
ref="veTree"
|
|
||||||
node-key="treeId"
|
|
||||||
:height="treeHeight?treeHeight:'78vh'"
|
|
||||||
lazy
|
|
||||||
style="padding: 0 0 2rem 0.5rem"
|
|
||||||
:load="loadNode"
|
|
||||||
:data="treeData"
|
|
||||||
:props="props"
|
|
||||||
:default-expanded-keys="['']"
|
|
||||||
@node-contextmenu="contextmenuEventHandler"
|
|
||||||
@node-click="nodeClickHandler"
|
|
||||||
>
|
|
||||||
<template class="custom-tree-node" v-slot:default="{ node, data }">
|
|
||||||
<span class="custom-tree-node" >
|
|
||||||
<span v-if="node.data.type === 0 && chooseId !== node.data.deviceId" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
|
|
||||||
<span v-if="node.data.type === 0 && chooseId === node.data.deviceId" style="color: #c60135;" class="iconfont icon-bianzubeifen3"></span>
|
|
||||||
<span v-if="node.data.type === 1 && node.data.status === 'ON'" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
|
|
||||||
<span v-if="node.data.type === 1 && node.data.status !== 'ON'" style="color: #808181" class="iconfont icon-shexiangtou2"></span>
|
|
||||||
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}(编号:{{ node.data.deviceId }})</span>
|
|
||||||
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</vue-easy-tree>
|
|
||||||
</div>
|
|
||||||
<regionEdit ref="regionEdit"></regionEdit>
|
|
||||||
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
|
|
||||||
<GbChannelSelect ref="gbChannelSelect" dataType="civilCode" ></GbChannelSelect>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import VueEasyTree from "@wchbrad/vue-easy-tree";
|
|
||||||
import regionEdit from './../dialog/regionEdit'
|
|
||||||
import gbDeviceSelect from './../dialog/GbDeviceSelect'
|
|
||||||
import GbChannelSelect from "../dialog/GbChannelSelect.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DeviceTree',
|
|
||||||
components: {
|
|
||||||
GbChannelSelect,
|
|
||||||
VueEasyTree, regionEdit, gbDeviceSelect
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
label: "name",
|
|
||||||
},
|
|
||||||
showCode: false,
|
|
||||||
showAlert: true,
|
|
||||||
searchSrt: "",
|
|
||||||
chooseId: "",
|
|
||||||
treeData: [],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: ['edit', 'enableAddChannel', 'clickEvent', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToCivilCode', 'treeHeight'],
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
search() {
|
|
||||||
|
|
||||||
},
|
|
||||||
loadNode: function (node, resolve) {
|
|
||||||
if (node.level === 0) {
|
|
||||||
resolve([{
|
|
||||||
treeId: "",
|
|
||||||
deviceId: "",
|
|
||||||
name: "根资源组",
|
|
||||||
isLeaf: false,
|
|
||||||
type: 0
|
|
||||||
}]);
|
|
||||||
} else if (node.data.deviceId.length <= 8) {
|
|
||||||
if (node.data.leaf) {
|
|
||||||
resolve([]);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/region/tree/list`,
|
|
||||||
params: {
|
|
||||||
query: this.searchSrt,
|
|
||||||
parent: node.data.id,
|
|
||||||
hasChannel: this.hasChannel
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (res.data.data.length > 0) {
|
|
||||||
this.showAlert = false
|
|
||||||
}
|
|
||||||
resolve(res.data.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
resolve([]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
reset: function () {
|
|
||||||
this.$forceUpdate();
|
|
||||||
},
|
|
||||||
contextmenuEventHandler: function (event, data, node, element) {
|
|
||||||
if (!this.edit) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
console.log(node.level)
|
|
||||||
if (node.data.type === 0) {
|
|
||||||
let menuItem = [
|
|
||||||
{
|
|
||||||
label: "刷新节点",
|
|
||||||
icon: "el-icon-refresh",
|
|
||||||
disabled: false,
|
|
||||||
onClick: () => {
|
|
||||||
this.refreshNode(node);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "新建节点",
|
|
||||||
icon: "el-icon-plus",
|
|
||||||
disabled: false,
|
|
||||||
onClick: () => {
|
|
||||||
this.addRegion(data.id, node);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "编辑节点",
|
|
||||||
icon: "el-icon-edit",
|
|
||||||
disabled: node.level === 1,
|
|
||||||
onClick: () => {
|
|
||||||
this.editCatalog(data, node);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "删除节点",
|
|
||||||
icon: "el-icon-delete",
|
|
||||||
disabled: node.level === 1,
|
|
||||||
divided: true,
|
|
||||||
onClick: () => {
|
|
||||||
this.$confirm('确定删除?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.removeRegion(data.id, node)
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
if (this.enableAddChannel) {
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: "添加设备",
|
|
||||||
icon: "el-icon-plus",
|
|
||||||
disabled: node.level === 1,
|
|
||||||
onClick: () => {
|
|
||||||
this.addChannelFormDevice(data.id, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: "移除设备",
|
|
||||||
icon: "el-icon-delete",
|
|
||||||
disabled: node.level === 1,
|
|
||||||
divided: true,
|
|
||||||
onClick: () => {
|
|
||||||
this.removeChannelFormDevice(data.id, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: "添加通道",
|
|
||||||
icon: "el-icon-plus",
|
|
||||||
disabled: node.level === 1,
|
|
||||||
onClick: () => {
|
|
||||||
this.addChannel(data.id, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.$contextmenu({
|
|
||||||
items: menuItem,
|
|
||||||
event, // 鼠标事件信息
|
|
||||||
customClass: "custom-class", // 自定义菜单 class
|
|
||||||
zIndex: 3000, // 菜单样式 z-index
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
removeRegion: function (id, node) {
|
|
||||||
this.$axios({
|
|
||||||
method: "delete",
|
|
||||||
url: `/api/region/delete`,
|
|
||||||
params: {
|
|
||||||
id: node.data.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
console.log("移除成功")
|
|
||||||
node.parent.loaded = false
|
|
||||||
node.parent.expand();
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addChannelFormDevice: function (id, node) {
|
|
||||||
this.$refs.gbDeviceSelect.openDialog((rows)=>{
|
|
||||||
let deviceIds = []
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
|
||||||
deviceIds.push(rows[i].id)
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/common/channel/region/device/add`,
|
|
||||||
data: {
|
|
||||||
civilCode: node.data.deviceId,
|
|
||||||
deviceIds: deviceIds,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
})
|
|
||||||
if (this.onChannelChange) {
|
|
||||||
this.onChannelChange()
|
|
||||||
}
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
this.loading = false
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
removeChannelFormDevice: function (id, node) {
|
|
||||||
this.$refs.gbDeviceSelect.openDialog((rows)=>{
|
|
||||||
let deviceIds = []
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
|
||||||
deviceIds.push(rows[i].id)
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/common/channel/region/device/delete`,
|
|
||||||
data: {
|
|
||||||
deviceIds: deviceIds,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
})
|
|
||||||
if (this.onChannelChange) {
|
|
||||||
this.onChannelChange(node.data.deviceId)
|
|
||||||
}
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
this.loading = false
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addChannel: function (id, node) {
|
|
||||||
this.$refs.gbChannelSelect.openDialog((data) => {
|
|
||||||
console.log("选择的数据")
|
|
||||||
console.log(data)
|
|
||||||
this.addChannelToCivilCode(node.data.deviceId, data)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
refreshNode: function (node) {
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
},
|
|
||||||
refresh: function (id) {
|
|
||||||
// 查询node
|
|
||||||
let node = this.$refs.veTree.getNode(id)
|
|
||||||
if (node) {
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
addRegion: function (id, node) {
|
|
||||||
|
|
||||||
console.log(node)
|
|
||||||
|
|
||||||
this.$refs.regionEdit.openDialog(form => {
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
}, {
|
|
||||||
deviceId: "",
|
|
||||||
name: "",
|
|
||||||
parentId: node.data.id,
|
|
||||||
parentDeviceId: node.data.deviceId,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
editCatalog: function (data, node){
|
|
||||||
// 打开添加弹窗
|
|
||||||
this.$refs.regionEdit.openDialog(form => {
|
|
||||||
node.loaded = false
|
|
||||||
node.expand();
|
|
||||||
}, node.data);
|
|
||||||
},
|
|
||||||
nodeClickHandler: function (data, node, tree) {
|
|
||||||
|
|
||||||
this.chooseId = data.deviceId;
|
|
||||||
if (this.clickEvent) {
|
|
||||||
this.clickEvent(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
// if (this.jessibuca) {
|
|
||||||
// this.jessibuca.destroy();
|
|
||||||
// }
|
|
||||||
// this.playing = false;
|
|
||||||
// this.loaded = false;
|
|
||||||
// this.performance = "";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.device-tree-main-box {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-online {
|
|
||||||
color: #252525;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-offline {
|
|
||||||
color: #727272;
|
|
||||||
}
|
|
||||||
.custom-tree-node .el-radio__label {
|
|
||||||
padding-left: 4px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="easyplayer" ></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'player',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
easyPlayer: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: ['videoUrl', 'error', 'hasaudio', 'height'],
|
|
||||||
mounted () {
|
|
||||||
let paramUrl = decodeURIComponent(this.$route.params.url)
|
|
||||||
this.$nextTick(() =>{
|
|
||||||
if (typeof (this.videoUrl) == "undefined") {
|
|
||||||
this.videoUrl = paramUrl;
|
|
||||||
}
|
|
||||||
console.log("初始化时的地址为: " + this.videoUrl)
|
|
||||||
this.play(this.videoUrl)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
watch:{
|
|
||||||
videoUrl(newData, oldData){
|
|
||||||
this.play(newData)
|
|
||||||
},
|
|
||||||
immediate:true
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
play: function (url) {
|
|
||||||
console.log(this.height)
|
|
||||||
if (this.easyPlayer != null) {
|
|
||||||
this.easyPlayer.destroy();
|
|
||||||
}
|
|
||||||
if (typeof (this.height) == "undefined") {
|
|
||||||
this.height = false
|
|
||||||
}
|
|
||||||
this.easyPlayer = new WasmPlayer(null, 'easyplayer', this.eventcallbacK, {Height: this.height})
|
|
||||||
this.easyPlayer.play(url, 1)
|
|
||||||
},
|
|
||||||
pause: function () {
|
|
||||||
this.easyPlayer.destroy();
|
|
||||||
this.easyPlayer = null
|
|
||||||
},
|
|
||||||
eventcallbacK: function(type, message) {
|
|
||||||
// console.log("player 事件回调")
|
|
||||||
// console.log(type)
|
|
||||||
// console.log(message)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.easyPlayer.destroy();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.LodingTitle {
|
|
||||||
min-width: 70px;
|
|
||||||
}
|
|
||||||
/* 隐藏logo */
|
|
||||||
.iconqingxiLOGO {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,246 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="container" @dblclick="fullscreenSwich" style="width:100%;height:100%;background-color: #000000;margin:0 auto;">
|
|
||||||
<div id="glplayer" style="width: 100%; height: 100%; display: flex"></div>
|
|
||||||
<div class="buttons-box" id="buttonsBox">
|
|
||||||
<div class="buttons-box-left">
|
|
||||||
<i v-if="!playing" class="iconfont icon-play h265web-btn" @click="unPause"></i>
|
|
||||||
<i v-if="playing" class="iconfont icon-pause h265web-btn" @click="pause"></i>
|
|
||||||
<i class="iconfont icon-stop h265web-btn" @click="destroy"></i>
|
|
||||||
<i v-if="isNotMute" class="iconfont icon-audio-high h265web-btn" @click="mute()"></i>
|
|
||||||
<i v-if="!isNotMute" class="iconfont icon-audio-mute h265web-btn" @click="cancelMute()"></i>
|
|
||||||
</div>
|
|
||||||
<div class="buttons-box-right">
|
|
||||||
<!-- <i class="iconfont icon-file-record1 h265web-btn"></i>-->
|
|
||||||
<!-- <i class="iconfont icon-xiangqing2 h265web-btn" ></i>-->
|
|
||||||
<i class="iconfont icon-camera1196054easyiconnet h265web-btn" @click="screenshot"
|
|
||||||
style="font-size: 1rem !important"></i>
|
|
||||||
<i class="iconfont icon-shuaxin11 h265web-btn" @click="playBtnClick"></i>
|
|
||||||
<i v-if="!fullscreen" class="iconfont icon-weibiaoti10 h265web-btn" @click="fullscreenSwich"></i>
|
|
||||||
<i v-if="fullscreen" class="iconfont icon-weibiaoti11 h265web-btn" @click="fullscreenSwich"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let h265webPlayer = {};
|
|
||||||
/**
|
|
||||||
* 从github上复制的
|
|
||||||
* @see https://github.com/numberwolf/h265web.js/blob/master/example_normal/index.js
|
|
||||||
*/
|
|
||||||
const token = "base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1";
|
|
||||||
export default {
|
|
||||||
name: 'h265web',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
playing: false,
|
|
||||||
isNotMute: false,
|
|
||||||
quieting: false,
|
|
||||||
fullscreen: false,
|
|
||||||
loaded: false, // mute
|
|
||||||
speed: 0,
|
|
||||||
kBps: 0,
|
|
||||||
btnDom: null,
|
|
||||||
videoInfo: null,
|
|
||||||
volume: 1,
|
|
||||||
rotate: 0,
|
|
||||||
vod: true, // 点播
|
|
||||||
forceNoOffscreen: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: ['videoUrl', 'error', 'hasAudio', 'height'],
|
|
||||||
mounted() {
|
|
||||||
window.onerror = (msg) => {
|
|
||||||
// console.error(msg)
|
|
||||||
};
|
|
||||||
console.log(this._uid)
|
|
||||||
let paramUrl = decodeURIComponent(this.$route.params.url)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.updatePlayerDomSize()
|
|
||||||
window.onresize = () => {
|
|
||||||
this.updatePlayerDomSize()
|
|
||||||
}
|
|
||||||
if (typeof (this.videoUrl) == "undefined") {
|
|
||||||
this.videoUrl = paramUrl;
|
|
||||||
}
|
|
||||||
this.btnDom = document.getElementById("buttonsBox");
|
|
||||||
console.log("初始化时的地址为: " + this.videoUrl)
|
|
||||||
this.play(this.videoUrl)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
videoUrl(newData, oldData) {
|
|
||||||
this.play(newData)
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updatePlayerDomSize() {
|
|
||||||
let dom = this.$refs.container;
|
|
||||||
let width = dom.parentNode.clientWidth
|
|
||||||
let height = (9 / 16) * width
|
|
||||||
|
|
||||||
const clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight)
|
|
||||||
if (height > clientHeight) {
|
|
||||||
height = clientHeight
|
|
||||||
width = (16 / 9) * height
|
|
||||||
}
|
|
||||||
|
|
||||||
dom.style.width = width + 'px';
|
|
||||||
dom.style.height = height + "px";
|
|
||||||
},
|
|
||||||
create() {
|
|
||||||
let options = {};
|
|
||||||
console.log("hasAudio " + this.hasAudio)
|
|
||||||
h265webPlayer[this._uid] = new window.new265webjs(this.videoUrl, Object.assign(
|
|
||||||
{
|
|
||||||
player: "glplayer", // 播放器容器id
|
|
||||||
width: 960,
|
|
||||||
height: 540,
|
|
||||||
token : token,
|
|
||||||
extInfo : {
|
|
||||||
coreProbePart : 0.4,
|
|
||||||
probeSize : 8192,
|
|
||||||
ignoreAudio : 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
options
|
|
||||||
));
|
|
||||||
let h265web = h265webPlayer[this._uid];
|
|
||||||
h265web.onOpenFullScreen = () => {
|
|
||||||
this.fullscreen = true
|
|
||||||
}
|
|
||||||
h265web.onCloseFullScreen = () => {
|
|
||||||
this.fullscreen = false
|
|
||||||
}
|
|
||||||
h265web.onReadyShowDone = () => {
|
|
||||||
// 准备好显示了,尝试自动播放
|
|
||||||
const result = h265web.play()
|
|
||||||
this.playing = result;
|
|
||||||
}
|
|
||||||
h265web.onLoadFinish = () => {
|
|
||||||
this.loaded = true;
|
|
||||||
// 可以获取mediaInfo
|
|
||||||
// @see https://github.com/numberwolf/h265web.js/blob/8b26a31ffa419bd0a0f99fbd5111590e144e36a8/example_normal/index.js#L252C9-L263C11
|
|
||||||
// mediaInfo = playerObj.mediaInfo();
|
|
||||||
}
|
|
||||||
h265web.onPlayTime = (...args) => {
|
|
||||||
console.log(args)
|
|
||||||
}
|
|
||||||
h265web.do()
|
|
||||||
},
|
|
||||||
screenshot: function () {
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
h265webPlayer[this._uid].screenshot();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
playBtnClick: function (event) {
|
|
||||||
this.play(this.videoUrl)
|
|
||||||
},
|
|
||||||
play: function (url) {
|
|
||||||
console.log(url)
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
this.destroy();
|
|
||||||
}
|
|
||||||
this.create();
|
|
||||||
},
|
|
||||||
unPause: function () {
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
h265webPlayer[this._uid].play();
|
|
||||||
}
|
|
||||||
this.playing = h265webPlayer[this._uid].isPlaying();
|
|
||||||
this.err = "";
|
|
||||||
},
|
|
||||||
pause: function () {
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
h265webPlayer[this._uid].pause();
|
|
||||||
}
|
|
||||||
this.playing = h265webPlayer[this._uid].isPlaying();
|
|
||||||
this.err = "";
|
|
||||||
},
|
|
||||||
mute: function () {
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
h265webPlayer[this._uid].setVoice(0.0);
|
|
||||||
this.isNotMute = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cancelMute: function () {
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
h265webPlayer[this._uid].setVoice(1.0);
|
|
||||||
this.isNotMute = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroy: function () {
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
h265webPlayer[this._uid].release();
|
|
||||||
}
|
|
||||||
if (document.getElementById("buttonsBox") == null) {
|
|
||||||
this.$refs.container.appendChild(this.btnDom)
|
|
||||||
}
|
|
||||||
h265webPlayer[this._uid] = null;
|
|
||||||
this.playing = false;
|
|
||||||
this.err = "";
|
|
||||||
|
|
||||||
},
|
|
||||||
eventcallbacK: function (type, message) {
|
|
||||||
// console.log("player 事件回调")
|
|
||||||
// console.log(type)
|
|
||||||
// console.log(message)
|
|
||||||
},
|
|
||||||
fullscreenSwich: function () {
|
|
||||||
let isFull = this.isFullscreen()
|
|
||||||
if (isFull) {
|
|
||||||
h265webPlayer[this._uid].closeFullScreen()
|
|
||||||
} else {
|
|
||||||
h265webPlayer[this._uid].fullScreen()
|
|
||||||
}
|
|
||||||
this.fullscreen = !isFull;
|
|
||||||
},
|
|
||||||
isFullscreen: function () {
|
|
||||||
return document.fullscreenElement ||
|
|
||||||
document.msFullscreenElement ||
|
|
||||||
document.mozFullScreenElement ||
|
|
||||||
document.webkitFullscreenElement || false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
if (h265webPlayer[this._uid]) {
|
|
||||||
h265webPlayer[this._uid].destroy();
|
|
||||||
}
|
|
||||||
this.playing = false;
|
|
||||||
this.loaded = false;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.buttons-box {
|
|
||||||
width: 100%;
|
|
||||||
height: 28px;
|
|
||||||
background-color: rgba(43, 51, 63, 0.7);
|
|
||||||
position: absolute;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
user-select: none;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h265web-btn {
|
|
||||||
width: 20px;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
line-height: 27px;
|
|
||||||
margin: 0px 10px;
|
|
||||||
padding: 0px 2px;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 0.8rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons-box-right {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,309 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="container" @dblclick="fullscreenSwich"
|
|
||||||
style="width:100%; height: 100%; background-color: #000000;margin:0 auto;position: relative;">
|
|
||||||
<div style="width:100%; padding-top: 56.25%; position: relative;"></div>
|
|
||||||
<div class="buttons-box" id="buttonsBox">
|
|
||||||
<div class="buttons-box-left">
|
|
||||||
<i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
|
|
||||||
<i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause"></i>
|
|
||||||
<i class="iconfont icon-stop jessibuca-btn" @click="destroy"></i>
|
|
||||||
<i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="mute()"></i>
|
|
||||||
<i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="cancelMute()"></i>
|
|
||||||
</div>
|
|
||||||
<div class="buttons-box-right">
|
|
||||||
<span class="jessibuca-btn">{{ kBps }} kb/s</span>
|
|
||||||
<!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>-->
|
|
||||||
<!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>-->
|
|
||||||
<i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot"
|
|
||||||
style="font-size: 1rem !important"></i>
|
|
||||||
<i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i>
|
|
||||||
<i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i>
|
|
||||||
<i v-if="fullscreen" class="iconfont icon-weibiaoti11 jessibuca-btn" @click="fullscreenSwich"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let jessibucaPlayer = {};
|
|
||||||
export default {
|
|
||||||
name: 'jessibuca',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
playing: false,
|
|
||||||
isNotMute: false,
|
|
||||||
quieting: false,
|
|
||||||
fullscreen: false,
|
|
||||||
loaded: false, // mute
|
|
||||||
speed: 0,
|
|
||||||
performance: "", // 工作情况
|
|
||||||
kBps: 0,
|
|
||||||
btnDom: null,
|
|
||||||
videoInfo: null,
|
|
||||||
volume: 1,
|
|
||||||
rotate: 0,
|
|
||||||
vod: true, // 点播
|
|
||||||
forceNoOffscreen: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: ['videoUrl', 'error', 'hasAudio', 'height'],
|
|
||||||
created() {
|
|
||||||
let paramUrl = decodeURIComponent(this.$route.params.url)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
console.log(2222)
|
|
||||||
this.updatePlayerDomSize()
|
|
||||||
window.onresize = this.updatePlayerDomSize
|
|
||||||
if (typeof (this.videoUrl) == "undefined") {
|
|
||||||
this.videoUrl = paramUrl;
|
|
||||||
}
|
|
||||||
this.btnDom = document.getElementById("buttonsBox");
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// mounted() {
|
|
||||||
// const ro = new ResizeObserver(entries => {
|
|
||||||
// entries.forEach(entry => {
|
|
||||||
// this.updatePlayerDomSize()
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// ro.observe(this.$refs.container);
|
|
||||||
// },
|
|
||||||
mounted(){
|
|
||||||
this.updatePlayerDomSize();
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
videoUrl: {
|
|
||||||
handler(val, _) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.play(val);
|
|
||||||
})
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updatePlayerDomSize() {
|
|
||||||
let dom = this.$refs.container;
|
|
||||||
let width = dom.parentNode.clientWidth
|
|
||||||
let height = (9 / 16) * width
|
|
||||||
console.log(height)
|
|
||||||
|
|
||||||
console.log(dom.clientHeight)
|
|
||||||
if (height > dom.clientHeight) {
|
|
||||||
height = dom.clientHeight
|
|
||||||
width = (16 / 9) * height
|
|
||||||
}
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
dom.style.width = width + 'px';
|
|
||||||
dom.style.height = height + "px";
|
|
||||||
dom.style.paddingTop = 0;
|
|
||||||
console.log(width)
|
|
||||||
console.log(height)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
create() {
|
|
||||||
let options = {
|
|
||||||
container: this.$refs.container,
|
|
||||||
autoWasm: true,
|
|
||||||
background: "",
|
|
||||||
controlAutoHide: false,
|
|
||||||
debug: false,
|
|
||||||
decoder: "static/js/jessibuca/decoder.js",
|
|
||||||
forceNoOffscreen: false,
|
|
||||||
hasAudio: typeof (this.hasAudio) == "undefined" ? true : this.hasAudio,
|
|
||||||
heartTimeout: 5,
|
|
||||||
heartTimeoutReplay: true,
|
|
||||||
heartTimeoutReplayTimes: 3,
|
|
||||||
hiddenAutoPause: false,
|
|
||||||
hotKey: true,
|
|
||||||
isFlv: false,
|
|
||||||
isFullResize: false,
|
|
||||||
isNotMute: this.isNotMute,
|
|
||||||
isResize: false,
|
|
||||||
keepScreenOn: true,
|
|
||||||
loadingText: "请稍等, 视频加载中......",
|
|
||||||
loadingTimeout: 10,
|
|
||||||
loadingTimeoutReplay: true,
|
|
||||||
loadingTimeoutReplayTimes: 3,
|
|
||||||
openWebglAlignment: false,
|
|
||||||
operateBtns: {
|
|
||||||
fullscreen: false,
|
|
||||||
screenshot: false,
|
|
||||||
play: false,
|
|
||||||
audio: false,
|
|
||||||
record: false
|
|
||||||
},
|
|
||||||
recordType: "mp4",
|
|
||||||
rotate: 0,
|
|
||||||
showBandwidth: false,
|
|
||||||
supportDblclickFullscreen: false,
|
|
||||||
timeout: 10,
|
|
||||||
useMSE: true,
|
|
||||||
useWCS: false,
|
|
||||||
useWebFullScreen: true,
|
|
||||||
videoBuffer: 0.1,
|
|
||||||
wasmDecodeErrorReplay: true,
|
|
||||||
wcsUseVideoRender: true
|
|
||||||
};
|
|
||||||
console.log("Jessibuca -> options: ", options);
|
|
||||||
jessibucaPlayer[this._uid] = new window.Jessibuca({...options});
|
|
||||||
|
|
||||||
let jessibuca = jessibucaPlayer[this._uid];
|
|
||||||
let _this = this;
|
|
||||||
jessibuca.on("pause", function () {
|
|
||||||
_this.playing = false;
|
|
||||||
});
|
|
||||||
jessibuca.on("play", function () {
|
|
||||||
_this.playing = true;
|
|
||||||
});
|
|
||||||
jessibuca.on("fullscreen", function (msg) {
|
|
||||||
_this.fullscreen = msg
|
|
||||||
});
|
|
||||||
jessibuca.on("mute", function (msg) {
|
|
||||||
_this.isNotMute = !msg;
|
|
||||||
});
|
|
||||||
jessibuca.on("performance", function (performance) {
|
|
||||||
let show = "卡顿";
|
|
||||||
if (performance === 2) {
|
|
||||||
show = "非常流畅";
|
|
||||||
} else if (performance === 1) {
|
|
||||||
show = "流畅";
|
|
||||||
}
|
|
||||||
_this.performance = show;
|
|
||||||
});
|
|
||||||
jessibuca.on('kBps', function (kBps) {
|
|
||||||
_this.kBps = Math.round(kBps);
|
|
||||||
});
|
|
||||||
jessibuca.on("videoInfo", function (msg) {
|
|
||||||
console.log("Jessibuca -> videoInfo: ", msg);
|
|
||||||
});
|
|
||||||
jessibuca.on("audioInfo", function (msg) {
|
|
||||||
console.log("Jessibuca -> audioInfo: ", msg);
|
|
||||||
});
|
|
||||||
jessibuca.on("error", function (msg) {
|
|
||||||
console.log("Jessibuca -> error: ", msg);
|
|
||||||
});
|
|
||||||
jessibuca.on("timeout", function (msg) {
|
|
||||||
console.log("Jessibuca -> timeout: ", msg);
|
|
||||||
});
|
|
||||||
jessibuca.on("loadingTimeout", function (msg) {
|
|
||||||
console.log("Jessibuca -> timeout: ", msg);
|
|
||||||
});
|
|
||||||
jessibuca.on("delayTimeout", function (msg) {
|
|
||||||
console.log("Jessibuca -> timeout: ", msg);
|
|
||||||
});
|
|
||||||
jessibuca.on("playToRenderTimes", function (msg) {
|
|
||||||
console.log("Jessibuca -> playToRenderTimes: ", msg);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
playBtnClick: function (event) {
|
|
||||||
this.play(this.videoUrl)
|
|
||||||
},
|
|
||||||
play: function (url) {
|
|
||||||
console.log("Jessibuca -> url: ", url);
|
|
||||||
if (jessibucaPlayer[this._uid]) {
|
|
||||||
this.destroy();
|
|
||||||
}
|
|
||||||
this.create();
|
|
||||||
jessibucaPlayer[this._uid].on("play", () => {
|
|
||||||
this.playing = true;
|
|
||||||
this.loaded = true;
|
|
||||||
this.quieting = jessibuca.quieting;
|
|
||||||
});
|
|
||||||
if (jessibucaPlayer[this._uid].hasLoaded()) {
|
|
||||||
jessibucaPlayer[this._uid].play(url);
|
|
||||||
} else {
|
|
||||||
jessibucaPlayer[this._uid].on("load", () => {
|
|
||||||
jessibucaPlayer[this._uid].play(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pause: function () {
|
|
||||||
if (jessibucaPlayer[this._uid]) {
|
|
||||||
jessibucaPlayer[this._uid].pause();
|
|
||||||
}
|
|
||||||
this.playing = false;
|
|
||||||
this.err = "";
|
|
||||||
this.performance = "";
|
|
||||||
},
|
|
||||||
screenshot: function () {
|
|
||||||
if (jessibucaPlayer[this._uid]) {
|
|
||||||
jessibucaPlayer[this._uid].screenshot();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mute: function () {
|
|
||||||
if (jessibucaPlayer[this._uid]) {
|
|
||||||
jessibucaPlayer[this._uid].mute();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cancelMute: function () {
|
|
||||||
if (jessibucaPlayer[this._uid]) {
|
|
||||||
jessibucaPlayer[this._uid].cancelMute();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroy: function () {
|
|
||||||
if (jessibucaPlayer[this._uid]) {
|
|
||||||
jessibucaPlayer[this._uid].destroy();
|
|
||||||
}
|
|
||||||
if (document.getElementById("buttonsBox") == null) {
|
|
||||||
this.$refs.container.appendChild(this.btnDom)
|
|
||||||
}
|
|
||||||
jessibucaPlayer[this._uid] = null;
|
|
||||||
this.playing = false;
|
|
||||||
this.err = "";
|
|
||||||
this.performance = "";
|
|
||||||
|
|
||||||
},
|
|
||||||
fullscreenSwich: function () {
|
|
||||||
let isFull = this.isFullscreen()
|
|
||||||
jessibucaPlayer[this._uid].setFullscreen(!isFull)
|
|
||||||
this.fullscreen = !isFull;
|
|
||||||
},
|
|
||||||
isFullscreen: function () {
|
|
||||||
return document.fullscreenElement ||
|
|
||||||
document.msFullscreenElement ||
|
|
||||||
document.mozFullScreenElement ||
|
|
||||||
document.webkitFullscreenElement || false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
if (jessibucaPlayer[this._uid]) {
|
|
||||||
jessibucaPlayer[this._uid].destroy();
|
|
||||||
}
|
|
||||||
this.playing = false;
|
|
||||||
this.loaded = false;
|
|
||||||
this.performance = "";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.buttons-box {
|
|
||||||
width: 100%;
|
|
||||||
height: 28px;
|
|
||||||
background-color: rgba(43, 51, 63, 0.7);
|
|
||||||
position: absolute;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
user-select: none;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jessibuca-btn {
|
|
||||||
width: 20px;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
line-height: 27px;
|
|
||||||
margin: 0px 10px;
|
|
||||||
padding: 0px 2px;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 0.8rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons-box-right {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="mediaInfo" >
|
|
||||||
<el-button style="position: absolute; right: 1rem;" icon="el-icon-refresh-right" circle size="mini" @click="getMediaInfo"></el-button>
|
|
||||||
<el-descriptions size="mini" :column="3" title="概况">
|
|
||||||
<el-descriptions-item label="观看人数">{{ info.readerCount }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="网络">{{ formatByteSpeed() }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="持续时间">{{info.aliveSecond}}秒</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr 1fr">
|
|
||||||
<el-descriptions size="mini" v-if="info.videoCodec" :column="2" title="视频信息">
|
|
||||||
<el-descriptions-item label="编码">{{ info.videoCodec }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="分辨率"
|
|
||||||
>{{ info.width }}x{{ info.height }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="FPS">{{ info.fps }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="丢包率">{{ info.loss }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
<el-descriptions size="mini" v-if="info.audioCodec" :column="2" title="音频信息">
|
|
||||||
<el-descriptions-item label="编码">
|
|
||||||
{{ info.audioCodec }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="采样率">{{ info.audioSampleRate }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "mediaInfo",
|
|
||||||
props: [ 'app', 'stream', 'mediaServerId'],
|
|
||||||
components: {},
|
|
||||||
created() {
|
|
||||||
this.getMediaInfo();
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
info: {},
|
|
||||||
task: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getMediaInfo: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/server/media_server/media_info`,
|
|
||||||
params: {
|
|
||||||
app: this.app,
|
|
||||||
stream: this.stream,
|
|
||||||
mediaServerId: this.mediaServerId,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
console.log(res.data.data);
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.info = res.data.data
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error)=> {
|
|
||||||
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
startTask: function () {
|
|
||||||
this.task = setInterval(this.getMediaInfo, 1000)
|
|
||||||
},
|
|
||||||
stopTask: function () {
|
|
||||||
if (this.task) {
|
|
||||||
window.clearInterval(this.task);
|
|
||||||
this.task = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
formatByteSpeed: function (){
|
|
||||||
let bytesSpeed = this.info.bytesSpeed
|
|
||||||
let num = 1024.0 //byte
|
|
||||||
if (bytesSpeed < num) return bytesSpeed + ' B/S'
|
|
||||||
if (bytesSpeed < Math.pow(num, 2)) return (bytesSpeed / num).toFixed(2) + ' KB/S' //kb
|
|
||||||
if (bytesSpeed < Math.pow(num, 3))
|
|
||||||
return (bytesSpeed / Math.pow(num, 2)).toFixed(2) + ' MB/S' //M
|
|
||||||
if (bytesSpeed < Math.pow(num, 4))
|
|
||||||
return (bytesSpeed / Math.pow(num, 3)).toFixed(2) + ' G/S' //G
|
|
||||||
return (bytesSpeed / Math.pow(num, 4)).toFixed(2) + ' T/S' //T
|
|
||||||
},
|
|
||||||
formatAliveSecond: function (){
|
|
||||||
let aliveSecond = this.info.aliveSecond
|
|
||||||
const h = parseInt(aliveSecond.value / 3600)
|
|
||||||
const minute = parseInt((aliveSecond.value / 60) % 60)
|
|
||||||
const second = Math.ceil(aliveSecond.value % 60)
|
|
||||||
|
|
||||||
const hours = h < 10 ? '0' + h : h
|
|
||||||
const formatSecond = second > 59 ? 59 : second
|
|
||||||
return `${hours > 0 ? `${hours}小时` : ''}${minute < 10 ? '0' + minute : minute}分${
|
|
||||||
formatSecond < 10 ? '0' + formatSecond : formatSecond
|
|
||||||
}秒`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,426 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ptzCruising">
|
|
||||||
<div style="display: grid; grid-template-columns: 80px auto; line-height: 28px">
|
|
||||||
<span>巡航组号: </span>
|
|
||||||
<el-input
|
|
||||||
min="1"
|
|
||||||
max="255"
|
|
||||||
placeholder="巡航组号"
|
|
||||||
addonBefore="巡航组号"
|
|
||||||
addonAfter="(1-255)"
|
|
||||||
v-model="cruiseId"
|
|
||||||
size="mini"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<el-tag v-for="(item, index) in presetList"
|
|
||||||
key="item.presetId"
|
|
||||||
closable
|
|
||||||
@close="delPreset(item, index)"
|
|
||||||
style="margin-right: 1rem; cursor: pointer"
|
|
||||||
>
|
|
||||||
{{item.presetName?item.presetName:item.presetId}}
|
|
||||||
</el-tag>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<el-form size="mini" :inline="true" v-if="selectPresetVisible">
|
|
||||||
<el-form-item >
|
|
||||||
<el-select v-model="selectPreset" placeholder="请选择预置点">
|
|
||||||
<el-option
|
|
||||||
v-for="item in allPresetList"
|
|
||||||
:key="item.presetId"
|
|
||||||
:label="item.presetName"
|
|
||||||
:value="item">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="addCruisePoint">保存</el-button>
|
|
||||||
<el-button type="primary" @click="cancelAddCruisePoint">取消</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-button size="mini" v-else @click="selectPresetVisible=true">添加巡航点</el-button>
|
|
||||||
|
|
||||||
<el-form size="mini" :inline="true" v-if="setSpeedVisible">
|
|
||||||
<el-form-item >
|
|
||||||
<el-input
|
|
||||||
min="1"
|
|
||||||
max="4095"
|
|
||||||
placeholder="巡航速度"
|
|
||||||
addonBefore="巡航速度"
|
|
||||||
addonAfter="(1-4095)"
|
|
||||||
v-if="setSpeedVisible"
|
|
||||||
v-model="cruiseSpeed"
|
|
||||||
size="mini"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="setCruiseSpeed">保存</el-button>
|
|
||||||
<el-button @click="cancelSetCruiseSpeed">取消</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-button v-else size="mini" @click="setSpeedVisible = true">设置巡航速度</el-button>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<el-form size="mini" :inline="true" v-if="setTimeVisible">
|
|
||||||
<el-form-item >
|
|
||||||
<el-input
|
|
||||||
min="1"
|
|
||||||
max="4095"
|
|
||||||
placeholder="巡航停留时间(秒)"
|
|
||||||
addonBefore="巡航停留时间(秒)"
|
|
||||||
addonAfter="(1-4095)"
|
|
||||||
style="width: 100%;"
|
|
||||||
v-model="cruiseTime"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="setCruiseTime">保存</el-button>
|
|
||||||
<el-button @click="cancelSetCruiseTime">取消</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-button v-else size="mini" @click="setTimeVisible = true">设置巡航时间</el-button>
|
|
||||||
<el-button size="mini" @click="startCruise">开始巡航</el-button>
|
|
||||||
<el-button size="mini" @click="stopCruise">停止巡航</el-button>
|
|
||||||
<el-button size="mini" type="danger" @click="deleteCruise">删除巡航</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ptzCruising",
|
|
||||||
props: [ 'channelDeviceId', 'deviceId'],
|
|
||||||
components: {},
|
|
||||||
created() {
|
|
||||||
this.getPresetList()
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
cruiseId: 1,
|
|
||||||
presetList: [],
|
|
||||||
allPresetList: [],
|
|
||||||
selectPreset: "",
|
|
||||||
inputVisible: false,
|
|
||||||
selectPresetVisible: false,
|
|
||||||
setSpeedVisible: false,
|
|
||||||
setTimeVisible: false,
|
|
||||||
cruiseSpeed: '',
|
|
||||||
cruiseTime: '',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getPresetList: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/preset/query/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.allPresetList = res.data.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error)=> {
|
|
||||||
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addCruisePoint: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/cruise/point/add/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
cruiseId: this.cruiseId,
|
|
||||||
presetId: this.selectPreset.presetId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.presetList.push(this.selectPreset)
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
this.selectPreset = ""
|
|
||||||
this.selectPresetVisible = false;
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
cancelAddCruisePoint: function () {
|
|
||||||
this.selectPreset = ""
|
|
||||||
this.selectPresetVisible = false;
|
|
||||||
},
|
|
||||||
delPreset: function (preset, index){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/cruise/point/delete/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
cruiseId: this.cruiseId,
|
|
||||||
presetId: preset.presetId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.presetList.splice(index, 1)
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteCruise: function (preset, index){
|
|
||||||
this.$confirm("确定删除此巡航组", '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/cruise/point/delete/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
cruiseId: this.cruiseId,
|
|
||||||
presetId: 0
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.presetList = []
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
setCruiseSpeed: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/cruise/speed/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
cruiseId: this.cruiseId,
|
|
||||||
speed: this.cruiseSpeed
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
this.cruiseSpeed = ""
|
|
||||||
this.setSpeedVisible = false
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
cancelSetCruiseSpeed: function (){
|
|
||||||
this.cruiseSpeed = ""
|
|
||||||
this.setSpeedVisible = false
|
|
||||||
},
|
|
||||||
setCruiseTime: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/cruise/time/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
cruiseId: this.cruiseId,
|
|
||||||
time: this.cruiseTime
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
this.setTimeVisible = false;
|
|
||||||
this.cruiseTime = "";
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
cancelSetCruiseTime: function (){
|
|
||||||
this.setTimeVisible = false;
|
|
||||||
this.cruiseTime = "";
|
|
||||||
},
|
|
||||||
startCruise: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/cruise/start/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
cruiseId: this.cruiseId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "发送成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
stopCruise: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/cruise/stop/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
cruiseId: this.cruiseId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "发送成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,212 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ptzPreset" style="width: 100%">
|
|
||||||
<el-tag v-for="item in presetList"
|
|
||||||
key="item.presetId"
|
|
||||||
closable
|
|
||||||
@close="delPreset(item)"
|
|
||||||
@click="gotoPreset(item)"
|
|
||||||
size="mini"
|
|
||||||
style="margin-right: 1rem; cursor: pointer; margin-bottom: 0.6rem"
|
|
||||||
>
|
|
||||||
{{item.presetName?item.presetName:item.presetId}}
|
|
||||||
</el-tag>
|
|
||||||
<el-input
|
|
||||||
min="1"
|
|
||||||
max="255"
|
|
||||||
placeholder="预置位编号"
|
|
||||||
addonBefore="预置位编号"
|
|
||||||
addonAfter="(1-255)"
|
|
||||||
style="width: 300px; vertical-align: bottom;"
|
|
||||||
v-if="inputVisible"
|
|
||||||
v-model="ptzPresetId"
|
|
||||||
ref="saveTagInput"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
<template v-slot:append>
|
|
||||||
<el-button @click="addPreset()">保存</el-button>
|
|
||||||
<el-button @click="cancel()">取消</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<el-button v-else size="small" @click="showInput">+ 添加</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ptzPreset",
|
|
||||||
props: [ 'channelDeviceId', 'deviceId'],
|
|
||||||
components: {},
|
|
||||||
created() {
|
|
||||||
this.getPresetList()
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
presetList: [],
|
|
||||||
inputVisible: false,
|
|
||||||
ptzPresetId: '',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getPresetList: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/preset/query/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.presetList = res.data.data;
|
|
||||||
// 防止出现表格错位
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.channelListTable.doLayout();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error)=> {
|
|
||||||
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showInput() {
|
|
||||||
this.inputVisible = true;
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
this.$refs.saveTagInput.$refs.input.focus();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addPreset: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/preset/add/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
presetId: this.ptzPresetId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
setTimeout(()=>{
|
|
||||||
loading.close()
|
|
||||||
this.inputVisible = false;
|
|
||||||
this.ptzPresetId = ""
|
|
||||||
this.getPresetList()
|
|
||||||
}, 1000)
|
|
||||||
}else {
|
|
||||||
loading.close()
|
|
||||||
this.inputVisible = false;
|
|
||||||
this.ptzPresetId = ""
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
loading.close()
|
|
||||||
this.inputVisible = false;
|
|
||||||
this.ptzPresetId = ""
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
cancel: function () {
|
|
||||||
this.inputVisible = false;
|
|
||||||
this.ptzPresetId = ""
|
|
||||||
},
|
|
||||||
gotoPreset: function (preset){
|
|
||||||
console.log(preset)
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/preset/call/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
presetId: preset.presetId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '调用成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
delPreset: function (preset){
|
|
||||||
this.$confirm("确定删除此预置位", '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/preset/delete/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
presetId: preset.presetId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
setTimeout(()=>{
|
|
||||||
loading.close()
|
|
||||||
this.getPresetList()
|
|
||||||
}, 1000)
|
|
||||||
}else {
|
|
||||||
loading.close()
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error)=> {
|
|
||||||
loading.close()
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,273 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ptzScan">
|
|
||||||
<div style="display: grid; grid-template-columns: 80px auto; line-height: 28px">
|
|
||||||
<span>扫描组号: </span>
|
|
||||||
<el-input
|
|
||||||
min="1"
|
|
||||||
max="255"
|
|
||||||
placeholder="扫描组号"
|
|
||||||
addonBefore="扫描组号"
|
|
||||||
addonAfter="(1-255)"
|
|
||||||
v-model="scanId"
|
|
||||||
size="mini"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-button size="mini" @click="setScanLeft">设置左边界</el-button>
|
|
||||||
<el-button size="mini" @click="setScanRight">设置右边界</el-button>
|
|
||||||
|
|
||||||
<el-form size="mini" :inline="true" v-if="setSpeedVisible">
|
|
||||||
<el-form-item >
|
|
||||||
<el-input
|
|
||||||
min="1"
|
|
||||||
max="4095"
|
|
||||||
placeholder="巡航速度"
|
|
||||||
addonBefore="巡航速度"
|
|
||||||
addonAfter="(1-4095)"
|
|
||||||
v-if="setSpeedVisible"
|
|
||||||
v-model="speed"
|
|
||||||
size="mini"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="setSpeed">保存</el-button>
|
|
||||||
<el-button @click="cancelSetSpeed">取消</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-button v-else size="mini" @click="setSpeedVisible = true">设置扫描速度</el-button>
|
|
||||||
|
|
||||||
<el-button size="mini" @click="startScan">开始自动扫描</el-button>
|
|
||||||
<el-button size="mini" @click="stopScan">停止自动扫描</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ptzScan",
|
|
||||||
props: [ 'channelDeviceId', 'deviceId'],
|
|
||||||
components: {},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
scanId: 1,
|
|
||||||
setSpeedVisible: false,
|
|
||||||
speed: '',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setSpeed: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/scan/set/speed/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
scanId: this.scanId,
|
|
||||||
speed: this.speed
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
this.speed = ""
|
|
||||||
this.setSpeedVisible = false
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
cancelSetSpeed: function (){
|
|
||||||
this.speed = ""
|
|
||||||
this.setSpeedVisible = false
|
|
||||||
},
|
|
||||||
setScanLeft: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/scan/set/left/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
scanId: this.scanId,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
setScanRight: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/scan/set/right/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
scanId: this.scanId,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
this.setSpeedVisible = false;
|
|
||||||
this.speed = "";
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
startScan: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/scan/start/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
scanId: this.scanId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "发送成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
stopScan: function (){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/scan/stop/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
scanId: this.scanId
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "发送成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ptzScan">
|
|
||||||
<el-form size="mini" :inline="true" >
|
|
||||||
<el-form-item >
|
|
||||||
<el-input
|
|
||||||
min="1"
|
|
||||||
max="4095"
|
|
||||||
placeholder="开关编号"
|
|
||||||
addonBefore="开关编号"
|
|
||||||
addonAfter="(2-255)"
|
|
||||||
v-model="switchId"
|
|
||||||
size="mini"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button size="mini" @click="open('on')">开启</el-button>
|
|
||||||
<el-button size="mini" @click="open('off')">关闭</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ptzScan",
|
|
||||||
props: [ 'channelDeviceId', 'deviceId'],
|
|
||||||
components: {},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
switchId: 1,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
open: function (command){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/auxiliary/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
command: command,
|
|
||||||
switchId: this.switchId,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ptzWiper">
|
|
||||||
<el-button size="mini" @click="open('on')">开启</el-button>
|
|
||||||
<el-button size="mini" @click="open('off')">关闭</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ptzWiper",
|
|
||||||
props: [ 'channelDeviceId', 'deviceId'],
|
|
||||||
components: {},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
open: function (command){
|
|
||||||
const loading = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
fullscreen: true,
|
|
||||||
text: '正在发送指令',
|
|
||||||
spinner: 'el-icon-loading',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/front-end/wiper/${this.deviceId}/${this.channelDeviceId}`,
|
|
||||||
params: {
|
|
||||||
command: command,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}).finally(()=>{
|
|
||||||
loading.close()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.channel-form {
|
|
||||||
display: grid;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
padding: 1rem 2rem 0 2rem;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,158 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app" style="width: 100%">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-title">控制台</div>
|
|
||||||
</div>
|
|
||||||
<el-row style="width: 100%">
|
|
||||||
<el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
|
|
||||||
<div class="control-cell" id="ThreadsLoad" >
|
|
||||||
<div style="width:100%; height:100%; ">
|
|
||||||
<consoleCPU ref="consoleCPU"></consoleCPU>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
|
|
||||||
<div class="control-cell" id="WorkThreadsLoad" >
|
|
||||||
<div style="width:100%; height:100%; ">
|
|
||||||
<consoleResource ref="consoleResource"></consoleResource>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
|
|
||||||
<div class="control-cell" id="WorkThreadsLoad" >
|
|
||||||
<div style="width:100%; height:100%; ">
|
|
||||||
<consoleNet ref="consoleNet"></consoleNet>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
|
|
||||||
<div class="control-cell" id="WorkThreadsLoad" >
|
|
||||||
<div style="width:100%; height:100%; ">
|
|
||||||
|
|
||||||
<consoleMem ref="consoleMem"></consoleMem>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
|
|
||||||
<div class="control-cell" id="WorkThreadsLoad" >
|
|
||||||
<div style="width:100%; height:100%; ">
|
|
||||||
<consoleNodeLoad ref="consoleNodeLoad"></consoleNodeLoad>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
|
|
||||||
<div class="control-cell" id="WorkThreadsLoad" >
|
|
||||||
<div style="width:100%; height:100%; ">
|
|
||||||
<consoleDisk ref="consoleDisk"></consoleDisk>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import uiHeader from '../layout/UiHeader.vue'
|
|
||||||
import consoleCPU from './console/ConsoleCPU.vue'
|
|
||||||
import consoleMem from './console/ConsoleMEM.vue'
|
|
||||||
import consoleNet from './console/ConsoleNet.vue'
|
|
||||||
import consoleNodeLoad from './console/ConsoleNodeLoad.vue'
|
|
||||||
import consoleDisk from './console/ConsoleDisk.vue'
|
|
||||||
import consoleResource from './console/ConsoleResource.vue'
|
|
||||||
|
|
||||||
import echarts from 'echarts';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'app',
|
|
||||||
components: {
|
|
||||||
echarts,
|
|
||||||
uiHeader,
|
|
||||||
consoleCPU,
|
|
||||||
consoleMem,
|
|
||||||
consoleNet,
|
|
||||||
consoleNodeLoad,
|
|
||||||
consoleDisk,
|
|
||||||
consoleResource,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
timer: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getSystemInfo();
|
|
||||||
this.getLoad();
|
|
||||||
this.getResourceInfo();
|
|
||||||
this.loopForSystemInfo();
|
|
||||||
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
loopForSystemInfo: function (){
|
|
||||||
if (this.timer != null) {
|
|
||||||
window.clearTimeout(this.timer);
|
|
||||||
}
|
|
||||||
this.timer = setTimeout(()=>{
|
|
||||||
if (this.$route.path === "/console") {
|
|
||||||
this.getSystemInfo();
|
|
||||||
this.getLoad();
|
|
||||||
this.timer = null;
|
|
||||||
this.loopForSystemInfo()
|
|
||||||
this.getResourceInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 2000)
|
|
||||||
},
|
|
||||||
getSystemInfo: function (){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/server/system/info`,
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$refs.consoleCPU.setData(res.data.data.cpu)
|
|
||||||
this.$refs.consoleMem.setData(res.data.data.mem)
|
|
||||||
this.$refs.consoleNet.setData(res.data.data.net, res.data.data.netTotal)
|
|
||||||
this.$refs.consoleDisk.setData(res.data.data.disk)
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getLoad: function (){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/server/media_server/load`,
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$refs.consoleNodeLoad.setData(res.data.data)
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getResourceInfo: function (){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/server/resource/info`,
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$refs.consoleResource.setData(res.data.data)
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
#app {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.control-cell {
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 10px;
|
|
||||||
height: 360px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="consoleCPU" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
|
|
||||||
<ve-line ref="consoleCPU" :data="chartData" :extend="extend" width="100%" height="100%" :legend-visible="false"></ve-line>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
import moment from "moment/moment";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'consoleCPU',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chartData: {
|
|
||||||
columns: ['time', 'data'],
|
|
||||||
rows: []
|
|
||||||
},
|
|
||||||
|
|
||||||
extend: {
|
|
||||||
title: {
|
|
||||||
show: true,
|
|
||||||
text: "CPU",
|
|
||||||
left: "center",
|
|
||||||
top: 20,
|
|
||||||
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
show: true,
|
|
||||||
right: "30px",
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
time: "time",
|
|
||||||
max: 'dataMax',
|
|
||||||
boundaryGap: ['20%', '20%'],
|
|
||||||
axisLabel: {
|
|
||||||
formatter:(v)=>{
|
|
||||||
return moment(v).format("HH:mm:ss");
|
|
||||||
},
|
|
||||||
showMaxLabel: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
min: 0,
|
|
||||||
max: 1,
|
|
||||||
splitNumber: 6,
|
|
||||||
position: "left",
|
|
||||||
silent: true,
|
|
||||||
axisLabel: {
|
|
||||||
formatter: (v)=>{
|
|
||||||
return v*100 + "%";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: (data)=>{
|
|
||||||
console.log(data)
|
|
||||||
return moment(data[0].data[0]).format("HH:mm:ss") + "</br> "
|
|
||||||
+ data[0].marker + "使用:" + (data[0].data[1]*100).toFixed(2) + "%";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: {
|
|
||||||
itemStyle: {
|
|
||||||
color: "#409EFF"
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
color: {
|
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 0,
|
|
||||||
y2: 1,
|
|
||||||
colorStops: [{
|
|
||||||
offset: 0, color: '#50a3f8' // 0% 处的颜色
|
|
||||||
}, {
|
|
||||||
offset: 1, color: '#69b0fa' // 100% 处的颜色
|
|
||||||
}],
|
|
||||||
global: false // 缺省为 false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.$refs.consoleCPU.echarts.resize()
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData: function(data) {
|
|
||||||
this.chartData .rows = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ConsoleNet" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
|
|
||||||
<ve-bar ref="ConsoleNet" :data="chartData" :extend="extend" :settings="chartSettings" width="100%" height="100%" ></ve-bar>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
import moment from "moment/moment";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ConsoleNet',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chartData: {
|
|
||||||
columns: ['path','free','use'],
|
|
||||||
rows: []
|
|
||||||
},
|
|
||||||
chartSettings: {
|
|
||||||
stack: {
|
|
||||||
'xxx': ['free', 'use']
|
|
||||||
},
|
|
||||||
labelMap: {
|
|
||||||
'free': '剩余',
|
|
||||||
'use': '已使用'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
title: {
|
|
||||||
show: true,
|
|
||||||
text: "磁盘",
|
|
||||||
left: "center",
|
|
||||||
top: 20,
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
show: true,
|
|
||||||
right: "30px",
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
series: {
|
|
||||||
barWidth: 30
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
left: "center",
|
|
||||||
bottom: "15px",
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: (data)=>{
|
|
||||||
console.log(data)
|
|
||||||
let relVal = "";
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
relVal += data[i].marker + data[i].seriesName + ":" + data[i].value.toFixed(2) + "GB"
|
|
||||||
if (i < data.length - 1) {
|
|
||||||
relVal += "</br>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return relVal;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.$refs.ConsoleNet.echarts.resize()
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData: function(data) {
|
|
||||||
this.chartData.rows = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ConsoleMEM" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
|
|
||||||
<ve-line ref="ConsoleMEM" :data="chartData" :extend="extend" width="100%" height="100%" :legend-visible="false"></ve-line>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
import moment from "moment/moment";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ConsoleMEM',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chartData: {
|
|
||||||
columns: ['time', 'data'],
|
|
||||||
rows: []
|
|
||||||
},
|
|
||||||
|
|
||||||
extend: {
|
|
||||||
title: {
|
|
||||||
show: true,
|
|
||||||
text: "内存",
|
|
||||||
left: "center",
|
|
||||||
top: 20,
|
|
||||||
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
show: true,
|
|
||||||
right: "30px",
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
time: "time",
|
|
||||||
max: 'dataMax',
|
|
||||||
boundaryGap: ['20%', '20%'],
|
|
||||||
axisLabel: {
|
|
||||||
formatter:(v)=>{
|
|
||||||
return moment(v).format("HH:mm:ss");
|
|
||||||
},
|
|
||||||
showMaxLabel: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
min: 0,
|
|
||||||
max: 1,
|
|
||||||
splitNumber: 6,
|
|
||||||
position: "left",
|
|
||||||
silent: true,
|
|
||||||
axisLabel: {
|
|
||||||
formatter: (v)=>{
|
|
||||||
return v*100 + "%";
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: (data)=>{
|
|
||||||
console.log(data)
|
|
||||||
return moment(data[0].data[0]).format("HH:mm:ss") + "</br>"+ data[0].marker +" 使用:" + (data[0].data[1]*100).toFixed(2) + "%";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: {
|
|
||||||
itemStyle: {
|
|
||||||
color: "#409EFF"
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
color: {
|
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 0,
|
|
||||||
y2: 1,
|
|
||||||
colorStops: [{
|
|
||||||
offset: 0, color: '#50a3f8' // 0% 处的颜色
|
|
||||||
}, {
|
|
||||||
offset: 1, color: '#69b0fa' // 100% 处的颜色
|
|
||||||
}],
|
|
||||||
global: false // 缺省为 false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.$refs.ConsoleMEM.echarts.resize()
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData: function(data) {
|
|
||||||
this.chartData .rows = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ConsoleMediaServer" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
|
|
||||||
<ve-histogram ref="ConsoleMEM" :data="chartData" :extend="extend" :settings="chartSettings" width="100%" height="100%" ></ve-histogram>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
import moment from "moment/moment";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ConsoleMediaServer',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chartData: {
|
|
||||||
columns: ['time', 'in', 'out'],
|
|
||||||
rows: [
|
|
||||||
]
|
|
||||||
},
|
|
||||||
chartSettings: {
|
|
||||||
area: true,
|
|
||||||
labelMap: {
|
|
||||||
'in': '下载',
|
|
||||||
'out': '上传'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
title: {
|
|
||||||
show: true,
|
|
||||||
text: "网络",
|
|
||||||
left: "center",
|
|
||||||
top: 20,
|
|
||||||
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
show: true,
|
|
||||||
right: "30px",
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
time: "time",
|
|
||||||
max: 'dataMax',
|
|
||||||
boundaryGap: ['20%', '20%'],
|
|
||||||
axisLabel: {
|
|
||||||
formatter:(v)=>{
|
|
||||||
return moment(v).format("HH:mm:ss");
|
|
||||||
},
|
|
||||||
showMaxLabel: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: (data)=>{
|
|
||||||
console.log(parseFloat(data[0].data[1]).toFixed(2))
|
|
||||||
console.log(parseFloat(data[1].data[1]).toFixed(2))
|
|
||||||
console.log("############")
|
|
||||||
return "下载:" + parseFloat(data[0].data[1]).toFixed(2) + "Mbps" + "</br> 上传:" + parseFloat(data[1].data[1]).toFixed(2) + "Mbps";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
left: "center",
|
|
||||||
bottom: "15px",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.$refs.ConsoleMEM.echarts.resize()
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData: function(data) {
|
|
||||||
console.log(data)
|
|
||||||
this.chartData .rows = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ConsoleNet" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
|
|
||||||
<ve-line ref="ConsoleNet" :data="chartData" :extend="extend" :settings="chartSettings" :events="chartEvents" width="100%" height="100%" ></ve-line>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
import moment from "moment/moment";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ConsoleNet',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chartData: {
|
|
||||||
columns: ['time','out','in'],
|
|
||||||
rows: []
|
|
||||||
},
|
|
||||||
chartSettings: {
|
|
||||||
area: true,
|
|
||||||
labelMap: {
|
|
||||||
'in': '下载',
|
|
||||||
'out': '上传'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
title: {
|
|
||||||
show: true,
|
|
||||||
text: "网络",
|
|
||||||
left: "center",
|
|
||||||
top: 20,
|
|
||||||
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
show: true,
|
|
||||||
right: "30px",
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
time: "time",
|
|
||||||
max: 'dataMax',
|
|
||||||
boundaryGap: ['20%', '20%'],
|
|
||||||
axisLabel: {
|
|
||||||
formatter:(v)=>{
|
|
||||||
return moment(v).format("HH:mm:ss");
|
|
||||||
},
|
|
||||||
showMaxLabel: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
min: 0,
|
|
||||||
max: 1000,
|
|
||||||
splitNumber: 6,
|
|
||||||
position: "left",
|
|
||||||
silent: true,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: (data)=>{
|
|
||||||
let in_sel = true;
|
|
||||||
let out_sel = true;
|
|
||||||
for (let key in this.extend.legend.selected) {
|
|
||||||
if (key == "上传") {
|
|
||||||
out_sel = this.extend.legend.selected[key];
|
|
||||||
}
|
|
||||||
if (key == "下载") {
|
|
||||||
in_sel = this.extend.legend.selected[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (out_sel && in_sel) {
|
|
||||||
return (
|
|
||||||
data[1].marker +
|
|
||||||
"下载:" +
|
|
||||||
parseFloat(data[1].data[1]).toFixed(2) +
|
|
||||||
"Mbps" +
|
|
||||||
"</br> " +
|
|
||||||
data[0].marker +
|
|
||||||
"上传:" +
|
|
||||||
parseFloat(data[0].data[1]).toFixed(2) +
|
|
||||||
"Mbps"
|
|
||||||
);
|
|
||||||
} else if (out_sel)
|
|
||||||
return (
|
|
||||||
data[0].marker +
|
|
||||||
"上传:" +
|
|
||||||
parseFloat(data[0].data[1]).toFixed(2) +
|
|
||||||
"Mbps"
|
|
||||||
);
|
|
||||||
else if (in_sel)
|
|
||||||
return (
|
|
||||||
data[0].marker +
|
|
||||||
"下载:" +
|
|
||||||
parseFloat(data[0].data[1]).toFixed(2) +
|
|
||||||
"Mbps"
|
|
||||||
);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
left: "center",
|
|
||||||
bottom: "15px",
|
|
||||||
selected: {},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
chartEvents: {
|
|
||||||
legendselectchanged: (item) => {
|
|
||||||
this.extend.legend.selected = item.selected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.$refs.ConsoleNet.echarts.resize()
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData: function(data, total) {
|
|
||||||
this.chartData .rows = data;
|
|
||||||
this.extend.yAxis.max= total;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ConsoleNodeLoad" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
|
|
||||||
<ve-histogram ref="consoleNodeLoad" :data="chartData" :extend="extend" :settings="chartSettings" width="100%" height="100%" :legend-visible="true"></ve-histogram>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
import moment from "moment/moment";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ConsoleNodeLoad',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chartData: {
|
|
||||||
columns: ['id', 'push', 'proxy', 'gbReceive', 'gbSend'],
|
|
||||||
rows: []
|
|
||||||
},
|
|
||||||
chartSettings: {
|
|
||||||
labelMap: {
|
|
||||||
'push': '直播推流',
|
|
||||||
'proxy': '拉流代理',
|
|
||||||
'gbReceive': '国标收流',
|
|
||||||
'gbSend': '国标推流',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
title: {
|
|
||||||
show: true,
|
|
||||||
text: "节点负载",
|
|
||||||
left: "center",
|
|
||||||
top: 20,
|
|
||||||
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
left: "center",
|
|
||||||
bottom: "15px",
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: "top"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.$refs.consoleNodeLoad.echarts.resize()
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData: function(data) {
|
|
||||||
this.chartData .rows = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
<template >
|
|
||||||
<div id="consoleResource" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
|
|
||||||
<div style="width: 50%;height: 50%; float:left; ">
|
|
||||||
<el-progress v-if="deviceInfo.total > 0" :width="100" :stroke-width="8" type="circle" :percentage="Math.floor(deviceInfo.online/deviceInfo.total*100)" style="margin-top: 20px; font-size: 18px"></el-progress>
|
|
||||||
<el-progress v-if="deviceInfo.total === 0" :width="100" :stroke-width="8" type="circle" :percentage="0" style="margin-top: 20px; font-size: 18px"></el-progress>
|
|
||||||
<div class="resourceInfo">
|
|
||||||
设备总数:{{deviceInfo.total}}<br/>
|
|
||||||
在线数:{{deviceInfo.online}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 50%;height: 50%; float:left; ">
|
|
||||||
<el-progress v-if="channelInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(channelInfo.online/channelInfo.total*100)" style="margin-top: 20px"></el-progress>
|
|
||||||
<el-progress v-if="channelInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
|
|
||||||
<div class="resourceInfo">
|
|
||||||
通道总数:{{channelInfo.total}}<br/>
|
|
||||||
在线数:{{channelInfo.online}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 50%;height: 50%; float:left; ">
|
|
||||||
<el-progress v-if="pushInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(pushInfo.online/pushInfo.total*100)" style="margin-top: 20px"></el-progress>
|
|
||||||
<el-progress v-if="pushInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
|
|
||||||
<div class="resourceInfo">
|
|
||||||
推流总数:{{pushInfo.total}}<br/>
|
|
||||||
在线数:{{pushInfo.online}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="width: 50%;height: 50%; float:left; ">
|
|
||||||
<el-progress v-if="proxyInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(proxyInfo.online/proxyInfo.total*100)" style="margin-top: 20px"></el-progress>
|
|
||||||
<el-progress v-if="proxyInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
|
|
||||||
<div class="resourceInfo">
|
|
||||||
拉流代理总数:{{proxyInfo.total}}<br/>
|
|
||||||
在线数:{{proxyInfo.online}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'consoleResource',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
deviceInfo: {
|
|
||||||
total: 0,
|
|
||||||
online: 0
|
|
||||||
},
|
|
||||||
channelInfo: {
|
|
||||||
total: 0,
|
|
||||||
online: 0
|
|
||||||
},
|
|
||||||
pushInfo: {
|
|
||||||
total: 0,
|
|
||||||
online: 0
|
|
||||||
},
|
|
||||||
proxyInfo: {
|
|
||||||
total: 0,
|
|
||||||
online: 0
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData: function(data) {
|
|
||||||
this.deviceInfo = data.device;
|
|
||||||
this.channelInfo = data.channel;
|
|
||||||
this.pushInfo = data.push;
|
|
||||||
this.proxyInfo = data.proxy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.resourceInfo{
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px
|
|
||||||
}
|
|
||||||
.el-progress__text {
|
|
||||||
font-size: 18px !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,188 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="gbChannelSelect" v-loading="getChannelListLoading">
|
|
||||||
<el-dialog
|
|
||||||
title="添加国标通道"
|
|
||||||
width="60%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
append-to-body
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div class="page-header" style="width: 100%">
|
|
||||||
<div class="page-header-btn" style="width: 100%; text-align: left">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="getChannelList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
在线状态:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="online" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="在线" value="true"></el-option>
|
|
||||||
<el-option label="离线" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
类型:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="channelType" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option v-for="item in Object.values($channelTypeList)" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button size="mini" :loading="getChannelListLoading"
|
|
||||||
@click="getChannelList()">刷新</el-button>
|
|
||||||
<el-button type="primary" size="mini" style="float: right" @click="onSubmit">确 定</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--通道列表-->
|
|
||||||
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
|
|
||||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
|
|
||||||
<el-table-column type="selection" width="55" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="类型" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" effect="plain" type="success" :style="$channelTypeList[scope.row.dataType].style" >{{$channelTypeList[scope.row.dataType].name}}</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr 1fr">
|
|
||||||
<div style="text-align: left; line-height: 32px">
|
|
||||||
<i class="el-icon-info"></i> 未找到通道,可在国标设备/通道中选择编辑按钮, 选择{{dataType === 'civilCode'?'行政区划':'父节点编码'}}
|
|
||||||
</div>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[10, 25, 35, 50, 200, 1000, 50000]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "gbChannelSelect",
|
|
||||||
props: ['dataType', "selected"],
|
|
||||||
computed: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
channelList: [], //设备列表
|
|
||||||
currentDevice: {}, //当前操作设备对象
|
|
||||||
searchSrt: "",
|
|
||||||
online: null,
|
|
||||||
channelType: "",
|
|
||||||
videoComponentList: [],
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
currentDeviceChannelsLenth: 0,
|
|
||||||
winHeight: 580,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 10,
|
|
||||||
total: 0,
|
|
||||||
getChannelListLoading: false,
|
|
||||||
multipleSelection: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
handleSelectionChange: function (val){
|
|
||||||
this.multipleSelection = val;
|
|
||||||
},
|
|
||||||
getChannelList: function () {
|
|
||||||
this.getChannelListLoading = true;
|
|
||||||
if (this.dataType === "civilCode") {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/common/channel/civilcode/list`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
channelType: this.channelType,
|
|
||||||
query: this.searchSrt,
|
|
||||||
online: this.online,
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.channelList = res.data.data.list;
|
|
||||||
}
|
|
||||||
this.getChannelListLoading = false;
|
|
||||||
}).catch( (error)=> {
|
|
||||||
console.error(error);
|
|
||||||
this.getChannelListLoading = false;
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/common/channel/parent/list`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
query: this.searchSrt,
|
|
||||||
channelType: this.channelType,
|
|
||||||
online: this.online,
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.channelList = res.data.data.list;
|
|
||||||
}
|
|
||||||
this.getChannelListLoading = false;
|
|
||||||
}).catch( (error)=> {
|
|
||||||
console.error(error);
|
|
||||||
this.getChannelListLoading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
openDialog: function (callback) {
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
this.showDialog = true;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
if (this.listChangeCallback ) {
|
|
||||||
this.listChangeCallback(this.multipleSelection)
|
|
||||||
}
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,153 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="addUser" v-loading="getDeviceListLoading">
|
|
||||||
<el-dialog
|
|
||||||
title="添加国标设备通道"
|
|
||||||
width="60%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
append-to-body
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div class="page-header" style="width: 100%">
|
|
||||||
<div class="page-header-btn" style="width: 100%; text-align: left">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="getDeviceList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
在线状态:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getDeviceList" v-model="online" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="在线" value="true"></el-option>
|
|
||||||
<el-option label="离线" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button size="mini" :loading="getDeviceListLoading"
|
|
||||||
@click="getDeviceList()">刷新</el-button>
|
|
||||||
<el-button type="primary" size="mini" style="float: right" @click="onSubmit">确 定</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--设备列表-->
|
|
||||||
<el-table size="medium" :data="deviceList" style="width: 100%;font-size: 12px;" :height="winHeight" header-row-class-name="table-header" @selection-change="handleSelectionChange">
|
|
||||||
<el-table-column type="selection" width="55" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="name" label="名称" min-width="160">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="deviceId" label="设备编号" min-width="200" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="channelCount" label="通道数" min-width="120" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="manufacturer" label="厂家" min-width="120" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="地址" min-width="160" >
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag v-if="scope.row.hostAddress" size="medium">{{ scope.row.hostAddress }}</el-tag>
|
|
||||||
<el-tag v-if="!scope.row.hostAddress" size="medium">未知</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="120">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.onLine">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="!scope.row.onLine">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[10, 25, 35, 50, 200, 1000, 50000]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "gbDeviceSelect",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
deviceList: [], //设备列表
|
|
||||||
currentDevice: {}, //当前操作设备对象
|
|
||||||
searchSrt: "",
|
|
||||||
online: null,
|
|
||||||
videoComponentList: [],
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
|
||||||
currentDeviceChannelsLenth: 0,
|
|
||||||
winHeight: 580,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 10,
|
|
||||||
total: 0,
|
|
||||||
getDeviceListLoading: false,
|
|
||||||
multipleSelection: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.getDeviceList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getDeviceList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getDeviceList();
|
|
||||||
},
|
|
||||||
handleSelectionChange: function (val){
|
|
||||||
this.multipleSelection = val;
|
|
||||||
},
|
|
||||||
getDeviceList: function () {
|
|
||||||
this.getDeviceListLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/device/query/devices`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
query: this.searchSrt,
|
|
||||||
status: this.online,
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.deviceList = res.data.data.list;
|
|
||||||
}
|
|
||||||
this.getDeviceListLoading = false;
|
|
||||||
}).catch( (error)=> {
|
|
||||||
console.error(error);
|
|
||||||
this.getDeviceListLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
openDialog: function (callback) {
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
this.showDialog = true;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
if (this.listChangeCallback ) {
|
|
||||||
this.listChangeCallback(this.multipleSelection)
|
|
||||||
}
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,386 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="mediaServerEdit" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="媒体节点"
|
|
||||||
:width="dialogWidth"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="formStep" style="margin-top: 1rem; margin-right: 20px;">
|
|
||||||
<el-form v-if="currentStep == 1" ref="mediaServerForm" :rules="rules" :model="mediaServerForm" label-width="140px" >
|
|
||||||
<el-form-item label="IP" prop="ip">
|
|
||||||
<el-input v-model="mediaServerForm.ip" placeholder="媒体服务IP" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="HTTP端口" prop="httpPort">
|
|
||||||
<el-input v-model="mediaServerForm.httpPort" placeholder="媒体服务HTTP端口" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SECRET" prop="secret">
|
|
||||||
<el-input v-model="mediaServerForm.secret" placeholder="媒体服务SECRET" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="类型" prop="type">
|
|
||||||
<el-select v-model="mediaServerForm.type" style="float: left; width: 100%" >
|
|
||||||
<el-option key="zlm" label="ZLMediaKit" value="zlm"></el-option>
|
|
||||||
<el-option key="abl" label="ABLMediaServer" value="abl"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" v-if="currentStep === 1 && serverCheck === 1" @click="next" >下一步</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
<el-button type="primary" @click="checkServer" >测试</el-button>
|
|
||||||
<i v-if="serverCheck === 1" class="el-icon-success" style="color: #3caf36"></i>
|
|
||||||
<i v-if="serverCheck === -1" class="el-icon-error" style="color: #c80000"></i>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-row :gutter="24">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form v-if="currentStep === 2 || currentStep === 3" ref="mediaServerForm1" :rules="rules" :model="mediaServerForm" label-width="140px" >
|
|
||||||
<el-form-item label="IP" prop="ip">
|
|
||||||
<el-input v-if="currentStep === 2" v-model="mediaServerForm.ip" disabled :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
<el-input v-if="currentStep === 3" v-model="mediaServerForm.ip" :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="HTTP端口" prop="httpPort">
|
|
||||||
<el-input v-if="currentStep === 2" v-model="mediaServerForm.httpPort" disabled :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
<el-input v-if="currentStep === 3" v-model="mediaServerForm.httpPort" :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="HOOK IP" prop="ip">
|
|
||||||
<el-input v-model="mediaServerForm.hookIp" placeholder="媒体服务HOOK_IP" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SDP IP" prop="ip">
|
|
||||||
<el-input v-model="mediaServerForm.sdpIp" placeholder="媒体服务SDP_IP" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流IP" prop="ip">
|
|
||||||
<el-input v-model="mediaServerForm.streamIp" placeholder="媒体服务流IP" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="HTTPS PORT" prop="httpSSlPort">
|
|
||||||
<el-input v-model="mediaServerForm.httpSSlPort" placeholder="媒体服务HTTPS_PORT" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="RTSP PORT" prop="rtspPort">
|
|
||||||
<el-input v-model="mediaServerForm.rtspPort" placeholder="媒体服务RTSP_PORT" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="RTSPS PORT" prop="rtspSSLPort">
|
|
||||||
<el-input v-model="mediaServerForm.rtspSSLPort" placeholder="媒体服务RTSPS_PORT" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form v-if="currentStep === 2 || currentStep === 3" ref="mediaServerForm2" :rules="rules" :model="mediaServerForm" label-width="180px" >
|
|
||||||
<el-form-item label="RTMP PORT" prop="rtmpPort">
|
|
||||||
<el-input v-model="mediaServerForm.rtmpPort" placeholder="媒体服务RTMP_PORT" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="RTMPS PORT" prop="rtmpSSlPort">
|
|
||||||
<el-input v-model="mediaServerForm.rtmpSSlPort" placeholder="媒体服务RTMPS_PORT" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SECRET" prop="secret">
|
|
||||||
<el-input v-if="currentStep === 2" v-model="mediaServerForm.secret" disabled :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
<el-input v-if="currentStep === 3" v-model="mediaServerForm.secret" :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="自动配置媒体服务" >
|
|
||||||
<el-switch v-model="mediaServerForm.autoConfig" :disabled="mediaServerForm.defaultServer"></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收流端口模式" >
|
|
||||||
<el-switch active-text="多端口" inactive-text="单端口" @change="portRangeChange" v-model="mediaServerForm.rtpEnable" :disabled="mediaServerForm.defaultServer"></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
|
|
||||||
<el-form-item v-if="!mediaServerForm.rtpEnable" label="收流端口" prop="rtpProxyPort">
|
|
||||||
<el-input v-model.number="mediaServerForm.rtpProxyPort" clearable :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="mediaServerForm.rtpEnable" label="收流端口" >
|
|
||||||
<el-input v-model="rtpPortRange1" placeholder="起始" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange1" :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
-
|
|
||||||
<el-input v-model="rtpPortRange2" placeholder="终止" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="mediaServerForm.sendRtpEnable" label="发流端口" >
|
|
||||||
<el-input v-model="sendRtpPortRange1" placeholder="起始" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange1" :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
-
|
|
||||||
<el-input v-model="sendRtpPortRange2" placeholder="终止" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="录像管理服务端口" prop="recordAssistPort">
|
|
||||||
<el-input v-model.number="mediaServerForm.recordAssistPort" :disabled="mediaServerForm.defaultServer">
|
|
||||||
<!-- <el-button v-if="mediaServerForm.recordAssistPort > 0" slot="append" type="primary" @click="checkRecordServer">测试</el-button>-->
|
|
||||||
<el-button v-if="mediaServerForm.recordAssistPort > 0" class="el-icon-check" slot="append" type="primary" @click="checkRecordServer"></el-button>
|
|
||||||
</el-input>
|
|
||||||
<i v-if="recordServerCheck == 1" class="el-icon-success" style="color: #3caf36; position: absolute;top: 14px;"></i>
|
|
||||||
<i v-if="recordServerCheck == 2" class="el-icon-loading" style="color: #3caf36; position: absolute;top: 14px;"></i>
|
|
||||||
<i v-if="recordServerCheck === -1" class="el-icon-error" style="color: #c80000; position: absolute;top: 14px;"></i>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button v-if="!mediaServerForm.defaultServer" type="primary" @click="onSubmit" >提交</el-button>
|
|
||||||
<el-button v-if="!mediaServerForm.defaultServer" @click="close">取消</el-button>
|
|
||||||
<el-button v-if="mediaServerForm.defaultServer" @click="close">关闭</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MediaServer from './../service/MediaServer'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "streamProxyEdit",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {
|
|
||||||
this.setDialogWidth()
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
const isValidIp = (rule, value, callback) => { // 校验IP是否符合规则
|
|
||||||
var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
|
||||||
console.log(this.mediaServerForm.ip)
|
|
||||||
if (!reg.test(this.mediaServerForm.ip)) {
|
|
||||||
return callback(new Error('请输入有效的IP地址'))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
const isValidPort = (rule, value, callback) => { // 校验IP是否符合规则
|
|
||||||
var reg = /^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5]))$/
|
|
||||||
if (!reg.test(this.mediaServerForm.httpPort)) {
|
|
||||||
return callback(new Error('请输入有效的端口号'))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
dialogWidth: 0,
|
|
||||||
defaultWidth: 1000,
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
dialogLoading: false,
|
|
||||||
|
|
||||||
currentStep: 1,
|
|
||||||
platformList: [],
|
|
||||||
mediaServer: new MediaServer(),
|
|
||||||
serverCheck: 0,
|
|
||||||
recordServerCheck: 0,
|
|
||||||
mediaServerForm: {
|
|
||||||
id: "",
|
|
||||||
ip: "",
|
|
||||||
autoConfig: true,
|
|
||||||
hookIp: "",
|
|
||||||
sdpIp: "",
|
|
||||||
streamIp: "",
|
|
||||||
secret: "",
|
|
||||||
httpPort: "",
|
|
||||||
httpSSlPort: "",
|
|
||||||
recordAssistPort: "",
|
|
||||||
rtmpPort: "",
|
|
||||||
rtmpSSlPort: "",
|
|
||||||
rtpEnable: false,
|
|
||||||
rtpPortRange: "",
|
|
||||||
sendRtpPortRange: "",
|
|
||||||
rtpProxyPort: "",
|
|
||||||
rtspPort: "",
|
|
||||||
rtspSSLPort: "",
|
|
||||||
type: "zlm",
|
|
||||||
},
|
|
||||||
rtpPortRange1:30000,
|
|
||||||
rtpPortRange2:30500,
|
|
||||||
|
|
||||||
sendRtpPortRange1:50000,
|
|
||||||
sendRtpPortRange2:60000,
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
ip: [{ required: true, validator: isValidIp, message: '请输入有效的IP地址', trigger: 'blur' }],
|
|
||||||
httpPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
httpSSlPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
recordAssistPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
rtmpPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
rtmpSSlPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
rtpPortRange1: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
rtpPortRange2: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
rtpProxyPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
rtspPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
rtspSSLPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
|
|
||||||
secret: [{ required: true, message: "请输入secret", trigger: "blur" }],
|
|
||||||
timeout_ms: [{ required: true, message: "请输入FFmpeg推流成功超时时间", trigger: "blur" }],
|
|
||||||
ffmpeg_cmd_key: [{ required: false, message: "请输入FFmpeg命令参数模板(可选)", trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setDialogWidth() {
|
|
||||||
let val = document.body.clientWidth
|
|
||||||
if (val < this.defaultWidth) {
|
|
||||||
this.dialogWidth = '100%'
|
|
||||||
} else {
|
|
||||||
this.dialogWidth = this.defaultWidth + 'px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openDialog: function (param, callback) {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
if (param != null) {
|
|
||||||
this.mediaServerForm = param;
|
|
||||||
this.currentStep = 3;
|
|
||||||
if (param.rtpPortRange) {
|
|
||||||
let rtpPortRange = this.mediaServerForm.rtpPortRange.split(",");
|
|
||||||
let sendRtpPortRange = this.mediaServerForm.sendRtpPortRange.split(",");
|
|
||||||
if (rtpPortRange.length > 0) {
|
|
||||||
this.rtpPortRange1 = rtpPortRange[0]
|
|
||||||
this.rtpPortRange2 = rtpPortRange[1]
|
|
||||||
}
|
|
||||||
if (sendRtpPortRange.length > 0) {
|
|
||||||
this.sendRtpPortRange1 = sendRtpPortRange[0]
|
|
||||||
this.sendRtpPortRange2 = sendRtpPortRange[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
checkServer: function() {
|
|
||||||
let that = this;
|
|
||||||
that.serverCheck = 0;
|
|
||||||
that.mediaServer.checkServer(that.mediaServerForm, data =>{
|
|
||||||
if (data.code === 0) {
|
|
||||||
if (parseInt(that.mediaServerForm.httpPort) !== parseInt(data.data.httpPort)) {
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '如果你正在使用docker部署你的媒体服务,请注意的端口映射。',
|
|
||||||
type: 'warning',
|
|
||||||
duration: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let httpPort = that.mediaServerForm.httpPort;
|
|
||||||
that.mediaServerForm = data.data;
|
|
||||||
that.mediaServerForm.httpPort = httpPort;
|
|
||||||
that.mediaServerForm.autoConfig = true;
|
|
||||||
that.rtpPortRange1 = 30000
|
|
||||||
that.rtpPortRange2 = 30500
|
|
||||||
that.sendRtpPortRange1 = 50000
|
|
||||||
that.sendRtpPortRange2 = 60000
|
|
||||||
that.serverCheck = 1;
|
|
||||||
}else {
|
|
||||||
that.serverCheck = -1;
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
next: function (){
|
|
||||||
this.currentStep = 2;
|
|
||||||
this.defaultWidth = 900;
|
|
||||||
this.setDialogWidth();
|
|
||||||
},
|
|
||||||
checkRecordServer: function (){
|
|
||||||
let that = this;
|
|
||||||
that.recordServerCheck = 2;
|
|
||||||
if (that.mediaServerForm.recordAssistPort <= 0 || that.mediaServerForm.recordAssistPort > 65535 ) {
|
|
||||||
that.recordServerCheck = -1;
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "端口号应该在-65535之间",
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
that.mediaServer.checkRecordServer(that.mediaServerForm, data =>{
|
|
||||||
if (data.code === 0) {
|
|
||||||
that.recordServerCheck = 1;
|
|
||||||
}else {
|
|
||||||
that.recordServerCheck = -1;
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
this.dialogLoading = true;
|
|
||||||
let that = this;
|
|
||||||
that.mediaServer.addServer(this.mediaServerForm, data => {
|
|
||||||
if (data.code === 0) {
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
if (this.listChangeCallback) this.listChangeCallback();
|
|
||||||
that.close()
|
|
||||||
}else {
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.dialogLoading = false;
|
|
||||||
this.mediaServerForm = {
|
|
||||||
id: "",
|
|
||||||
ip: "",
|
|
||||||
autoConfig: true,
|
|
||||||
hookIp: "",
|
|
||||||
sdpIp: "",
|
|
||||||
streamIp: "",
|
|
||||||
secret: "",
|
|
||||||
httpPort: "",
|
|
||||||
httpSSlPort: "",
|
|
||||||
recordAssistPort: "",
|
|
||||||
rtmpPort: "",
|
|
||||||
rtmpSSlPort: "",
|
|
||||||
rtpEnable: false,
|
|
||||||
rtpPortRange: "",
|
|
||||||
sendRtpPortRange: "",
|
|
||||||
rtpProxyPort: "",
|
|
||||||
rtspPort: "",
|
|
||||||
rtspSSLPort: "",
|
|
||||||
};
|
|
||||||
this.rtpPortRange1 = 30500;
|
|
||||||
this.rtpPortRange2 = 30500;
|
|
||||||
this.sendRtpPortRange1 = 50000;
|
|
||||||
this.sendRtpPortRange2 = 60000;
|
|
||||||
this.listChangeCallback = null
|
|
||||||
this.currentStep = 1;
|
|
||||||
},
|
|
||||||
deviceGBIdExit: async function (deviceGbId) {
|
|
||||||
var result = false;
|
|
||||||
var that = this;
|
|
||||||
await that.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/platform/exit/${deviceGbId}`
|
|
||||||
}).then(function (res) {
|
|
||||||
result = res.data;
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
checkExpires: function() {
|
|
||||||
if (this.platform.enable && this.platform.expires == "0") {
|
|
||||||
this.platform.expires = "300";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
portRangeChange: function() {
|
|
||||||
if (this.mediaServerForm.rtpEnable) {
|
|
||||||
this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2
|
|
||||||
this.mediaServerForm.sendRtpPortRange = this.sendRtpPortRange1 + "," + this.sendRtpPortRange2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,294 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="addStreamProxy" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="添加代理"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
|
||||||
<el-form ref="streamProxy" :rules="rules" :model="proxyParam" label-width="140px" >
|
|
||||||
<el-form-item label="类型" prop="type">
|
|
||||||
<el-select
|
|
||||||
v-model="proxyParam.type"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择代理类型"
|
|
||||||
>
|
|
||||||
<el-option label="默认" value="default"></el-option>
|
|
||||||
<el-option label="FFmpeg" value="ffmpeg"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="名称" prop="name">
|
|
||||||
<el-input v-model="proxyParam.name" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流应用名" prop="app">
|
|
||||||
<el-input v-model="proxyParam.app" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流ID" prop="stream">
|
|
||||||
<el-input v-model="proxyParam.stream" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="拉流地址" prop="url" v-if="proxyParam.type=='default'">
|
|
||||||
<el-input v-model="proxyParam.url" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="拉流地址" prop="srcUrl" v-if="proxyParam.type=='ffmpeg'">
|
|
||||||
<el-input v-model="proxyParam.srcUrl" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="超时时间:毫秒" prop="timeoutMs" v-if="proxyParam.type=='ffmpeg'">
|
|
||||||
<el-input v-model="proxyParam.timeoutMs" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="节点选择" prop="rtpType">
|
|
||||||
<el-select
|
|
||||||
v-model="proxyParam.mediaServerId"
|
|
||||||
@change="mediaServerIdChange"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择拉流节点"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in mediaServerList"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.id"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="FFmpeg命令模板" prop="ffmpegCmdKey" v-if="proxyParam.type=='ffmpeg'">
|
|
||||||
<el-select
|
|
||||||
v-model="proxyParam.ffmpegCmdKey"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择FFmpeg命令模板"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in Object.keys(ffmpegCmdList)"
|
|
||||||
:key="item"
|
|
||||||
:label="ffmpegCmdList[item]"
|
|
||||||
:value="item">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="国标编码" prop="gbId">
|
|
||||||
<el-input v-model="proxyParam.gbId" placeholder="设置国标编码可推送到国标" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="拉流方式" prop="rtpType" v-if="proxyParam.type=='default'">
|
|
||||||
<el-select
|
|
||||||
v-model="proxyParam.rtpType"
|
|
||||||
style="width: 100%"
|
|
||||||
placeholder="请选择拉流方式"
|
|
||||||
>
|
|
||||||
<el-option label="TCP" value="0"></el-option>
|
|
||||||
<el-option label="UDP" value="1"></el-option>
|
|
||||||
<el-option label="组播" value="2"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="无人观看" prop="rtpType" >
|
|
||||||
<el-radio v-model="proxyParam.noneReader" label="0">不做处理</el-radio>
|
|
||||||
<el-radio v-model="proxyParam.noneReader" label="1">停用</el-radio>
|
|
||||||
<el-radio v-model="proxyParam.noneReader" label="2">移除</el-radio>
|
|
||||||
<!-- <el-select-->
|
|
||||||
<!-- @change="noneReaderHandler"-->
|
|
||||||
<!-- v-model="proxyParam.noneReader"-->
|
|
||||||
<!-- style="width: 100%"-->
|
|
||||||
<!-- placeholder="请选择无人观看的处理方式"-->
|
|
||||||
<!-- >-->
|
|
||||||
<!-- <el-option label="不做处理" value="0"></el-option>-->
|
|
||||||
<!-- <el-option label="停用" value="1"></el-option>-->
|
|
||||||
<!-- <el-option label="移除" value="2"></el-option>-->
|
|
||||||
<!-- </el-select>-->
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="其他选项">
|
|
||||||
<div style="float: left;">
|
|
||||||
<el-checkbox label="启用" v-model="proxyParam.enable" ></el-checkbox>
|
|
||||||
<el-checkbox label="开启音频" v-model="proxyParam.enableAudio" ></el-checkbox>
|
|
||||||
<el-checkbox label="录制" v-model="proxyParam.enableMp4" ></el-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit" :loading="dialogLoading" >{{onSubmit_text}}</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MediaServer from './../service/MediaServer'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "streamProxyEdit",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
// var deviceGBIdRules = async (rule, value, callback) => {
|
|
||||||
// console.log(value);
|
|
||||||
// if (value === "") {
|
|
||||||
// callback(new Error("请输入设备国标编号"));
|
|
||||||
// } else {
|
|
||||||
// var exit = await this.deviceGBIdExit(value);
|
|
||||||
// console.log(exit);
|
|
||||||
// console.log(exit == "true");
|
|
||||||
// console.log(exit === "true");
|
|
||||||
// if (exit) {
|
|
||||||
// callback(new Error("设备国标编号已存在"));
|
|
||||||
// } else {
|
|
||||||
// callback();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
return {
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
dialogLoading: false,
|
|
||||||
onSubmit_text: "保存",
|
|
||||||
platformList: [],
|
|
||||||
mediaServer: new MediaServer(),
|
|
||||||
proxyParam: {
|
|
||||||
name: null,
|
|
||||||
type: "default",
|
|
||||||
app: null,
|
|
||||||
stream: null,
|
|
||||||
url: "",
|
|
||||||
srcUrl: null,
|
|
||||||
timeoutMs: null,
|
|
||||||
ffmpegCmdKey: null,
|
|
||||||
gbId: null,
|
|
||||||
rtpType: null,
|
|
||||||
enable: true,
|
|
||||||
enableAudio: true,
|
|
||||||
enableMp4: false,
|
|
||||||
noneReader: null,
|
|
||||||
enableRemoveNoneReader: false,
|
|
||||||
enableDisableNoneReader: false,
|
|
||||||
platformGbId: null,
|
|
||||||
mediaServerId: null,
|
|
||||||
},
|
|
||||||
mediaServerList:{},
|
|
||||||
ffmpegCmdList:{},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
|
||||||
app: [{ required: true, message: "请输入应用名", trigger: "blur" }],
|
|
||||||
stream: [{ required: true, message: "请输入流ID", trigger: "blur" }],
|
|
||||||
url: [{ required: true, message: "请输入要代理的流", trigger: "blur" }],
|
|
||||||
srcUrl: [{ required: true, message: "请输入要代理的流", trigger: "blur" }],
|
|
||||||
timeoutMs: [{ required: true, message: "请输入FFmpeg推流成功超时时间", trigger: "blur" }],
|
|
||||||
ffmpegCmdKey: [{ required: false, message: "请输入FFmpeg命令参数模板(可选)", trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (proxyParam, callback) {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
if (proxyParam != null) {
|
|
||||||
this.proxyParam = proxyParam;
|
|
||||||
this.proxyParam.noneReader = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/platform/query/10000/1`
|
|
||||||
}).then(function (res) {
|
|
||||||
that.platformList = res.data.data.list;
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
this.mediaServer.getOnlineMediaServerList((data)=>{
|
|
||||||
this.mediaServerList = data.data;
|
|
||||||
this.proxyParam.mediaServerId = this.mediaServerList[0].id
|
|
||||||
this.mediaServerIdChange()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
mediaServerIdChange:function (){
|
|
||||||
let that = this;
|
|
||||||
if (that.proxyParam.mediaServerId !== "auto"){
|
|
||||||
that.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/proxy/ffmpeg_cmd/list`,
|
|
||||||
params: {
|
|
||||||
mediaServerId: that.proxyParam.mediaServerId
|
|
||||||
}
|
|
||||||
}).then(function (res) {
|
|
||||||
that.ffmpegCmdList = res.data.data;
|
|
||||||
that.proxyParam.ffmpegCmdKey = Object.keys(res.data.data)[0];
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
this.dialogLoading = true;
|
|
||||||
this.noneReaderHandler();
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url:`/api/proxy/save`,
|
|
||||||
data: this.proxyParam
|
|
||||||
}).then((res)=> {
|
|
||||||
this.dialogLoading = false;
|
|
||||||
if (typeof (res.data.code) != "undefined" && res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
if (this.listChangeCallback != null) {
|
|
||||||
this.listChangeCallback();
|
|
||||||
this.dialogLoading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch((error) =>{
|
|
||||||
console.log(error);
|
|
||||||
this.dialogLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.dialogLoading = false;
|
|
||||||
this.$refs.streamProxy.resetFields();
|
|
||||||
},
|
|
||||||
deviceGBIdExit: async function (deviceGbId) {
|
|
||||||
var result = false;
|
|
||||||
var that = this;
|
|
||||||
await that.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/platform/exit/${deviceGbId}`
|
|
||||||
}).then(function (res) {
|
|
||||||
result = res.data;
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
checkExpires: function() {
|
|
||||||
if (this.platform.enable && this.platform.expires == "0") {
|
|
||||||
this.platform.expires = "300";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
noneReaderHandler: function() {
|
|
||||||
if (this.proxyParam.noneReader === null || this.proxyParam.noneReader === "0") {
|
|
||||||
this.proxyParam.enableDisableNoneReader = false;
|
|
||||||
this.proxyParam.enableRemoveNoneReader = false;
|
|
||||||
}else if (this.proxyParam.noneReader === "1"){
|
|
||||||
this.proxyParam.enableDisableNoneReader = true;
|
|
||||||
this.proxyParam.enableRemoveNoneReader = false;
|
|
||||||
}else if (this.proxyParam.noneReader ==="2"){
|
|
||||||
this.proxyParam.enableDisableNoneReader = false;
|
|
||||||
this.proxyParam.enableRemoveNoneReader = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="SyncChannelProgress" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
width="240px"
|
|
||||||
top="13%"
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
:show-close="true"
|
|
||||||
@close="close()"
|
|
||||||
style="text-align: center">
|
|
||||||
<el-progress type="circle" :percentage="percentage" :status="syncStatus"></el-progress>
|
|
||||||
<div style="text-align: center">
|
|
||||||
{{msg}}
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "SyncChannelProgress",
|
|
||||||
computed: {},
|
|
||||||
props: ['platformId'],
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
endCallBack: null,
|
|
||||||
syncStatus: null,
|
|
||||||
percentage: 0,
|
|
||||||
total: 0,
|
|
||||||
current: 0,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
syncFlag: false,
|
|
||||||
deviceId: null,
|
|
||||||
timmer: null,
|
|
||||||
msg: "正在同步",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (deviceId, endCallBack) {
|
|
||||||
console.log("deviceId: " + deviceId)
|
|
||||||
this.deviceId = deviceId;
|
|
||||||
this.showDialog = true;
|
|
||||||
this.msg = "";
|
|
||||||
this.percentage= 0;
|
|
||||||
this.total= 0;
|
|
||||||
this.current= 0;
|
|
||||||
this.syncFlag= false;
|
|
||||||
this.syncStatus = null;
|
|
||||||
this.endCallBack = endCallBack;
|
|
||||||
this.getProgress()
|
|
||||||
},
|
|
||||||
getProgress(){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/device/query/${this.deviceId}/sync_status/`,
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
|
|
||||||
if (res.data.data != null) {
|
|
||||||
if (res.data.data.syncIng) {
|
|
||||||
if (res.data.data.total === 0) {
|
|
||||||
this.msg = `等待同步中`;
|
|
||||||
this.timmer = setTimeout(this.getProgress, 300)
|
|
||||||
}else {
|
|
||||||
this.syncFlag = true;
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.current = res.data.data.current;
|
|
||||||
this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
|
|
||||||
this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
|
|
||||||
this.timmer = setTimeout(this.getProgress, 300)
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
if (res.data.data.errorMsg){
|
|
||||||
this.msg = res.data.data.errorMsg;
|
|
||||||
this.syncStatus = "exception"
|
|
||||||
}else {
|
|
||||||
this.syncStatus = "success"
|
|
||||||
this.percentage = 100;
|
|
||||||
this.msg = '同步成功';
|
|
||||||
setTimeout(()=>{
|
|
||||||
this.showDialog = false;
|
|
||||||
}, 3000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.msg = res.data.msg;
|
|
||||||
this.timmer = setTimeout(this.getProgress, 300)
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
if (this.syncFlag) {
|
|
||||||
this.syncStatus = "success"
|
|
||||||
this.percentage = 100;
|
|
||||||
this.msg = '同步成功';
|
|
||||||
}else {
|
|
||||||
this.syncStatus = "error"
|
|
||||||
this.msg = res.data.msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch((error) =>{
|
|
||||||
console.log(error);
|
|
||||||
this.syncStatus = "error"
|
|
||||||
this.msg = error.response.data.msg;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function (){
|
|
||||||
if (this.endCallBack) {
|
|
||||||
this.endCallBack()
|
|
||||||
}
|
|
||||||
window.clearTimeout(this.timmer)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,257 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="gbChannelSelect" v-loading="getChannelListLoading">
|
|
||||||
<el-dialog
|
|
||||||
title="异常挂载通道"
|
|
||||||
width="60%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
append-to-body
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div class="page-header" style="width: 100%">
|
|
||||||
<div class="page-header-btn" style="width: 100%; text-align: left">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="getChannelList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
在线状态:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="online" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="在线" value="true"></el-option>
|
|
||||||
<el-option label="离线" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
类型:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="channelType" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option v-for="item in Object.values($channelTypeList)" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button size="mini" type="primary" :loading="getChannelListLoading" :disabled="multipleSelection.length ===0"
|
|
||||||
@click="clearUnusualRegion()">清除</el-button>
|
|
||||||
<el-button size="mini" :loading="getChannelListLoading"
|
|
||||||
@click="clearUnusualRegion(true)">全部清除</el-button>
|
|
||||||
<el-button size="mini" :loading="getChannelListLoading"
|
|
||||||
@click="getChannelList()">刷新</el-button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--通道列表-->
|
|
||||||
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
|
|
||||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
|
|
||||||
<el-table-column type="selection" width="55" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbCivilCode" label="行政区划" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="类型" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" effect="plain" type="success" :style="$channelTypeList[scope.row.dataType].style">{{$channelTypeList[scope.row.dataType].name}}</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr 1fr">
|
|
||||||
<div style="text-align: left; line-height: 32px">
|
|
||||||
<i class="el-icon-info"></i> 清除后通道可正常添加到分组节点。
|
|
||||||
</div>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[10, 25, 35, 50, 200, 1000, 50000]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "UnusualGroupChannelSelect",
|
|
||||||
props: [],
|
|
||||||
computed: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
channelList: [], //设备列表
|
|
||||||
searchSrt: "",
|
|
||||||
online: null,
|
|
||||||
channelType: "",
|
|
||||||
winHeight: 580,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 10,
|
|
||||||
total: 0,
|
|
||||||
getChannelListLoading: false,
|
|
||||||
multipleSelection: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
handleSelectionChange: function (val){
|
|
||||||
this.multipleSelection = val;
|
|
||||||
},
|
|
||||||
getChannelList: function () {
|
|
||||||
this.getChannelListLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/common/channel/parent/unusual/list`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
channelType: this.channelType,
|
|
||||||
query: this.searchSrt,
|
|
||||||
online: this.online,
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
for (let i = 0; i < res.data.data.list.length; i++) {
|
|
||||||
res.data.data.list[i]["addRegionLoading"] = false
|
|
||||||
}
|
|
||||||
this.channelList = res.data.data.list;
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
console.error(error);
|
|
||||||
}).finally(()=>{
|
|
||||||
this.getChannelListLoading = false;
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
openDialog: function () {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
clearUnusualRegion: function (all) {
|
|
||||||
let channels = null
|
|
||||||
if (all || this.multipleSelection.length > 0 ) {
|
|
||||||
channels = []
|
|
||||||
for (let i = 0; i < this.multipleSelection.length; i++) {
|
|
||||||
channels.push(this.multipleSelection[i].gbId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/common/channel/parent/unusual/clear`,
|
|
||||||
data: {
|
|
||||||
all: all,
|
|
||||||
channelIds: channels
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "清除成功"
|
|
||||||
})
|
|
||||||
this.getChannelList()
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
}).finally(()=>{
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
addRegion: function (row) {
|
|
||||||
row.addRegionLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/region/description`,
|
|
||||||
params: {
|
|
||||||
civilCode: row.gbCivilCode,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$confirm(`确定添加: ${res.data.data}`, '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'info'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/region/addByCivilCode`,
|
|
||||||
params: {
|
|
||||||
civilCode: row.gbCivilCode,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "添加成功"
|
|
||||||
})
|
|
||||||
this.initData()
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
}).finally(()=>{
|
|
||||||
row.addRegionLoading = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,270 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="gbChannelSelect" v-loading="getChannelListLoading">
|
|
||||||
<el-dialog
|
|
||||||
title="异常挂载通道"
|
|
||||||
width="60%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
append-to-body
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div class="page-header" style="width: 100%">
|
|
||||||
<div class="page-header-btn" style="width: 100%; text-align: left">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="getChannelList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
在线状态:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="online" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="在线" value="true"></el-option>
|
|
||||||
<el-option label="离线" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
类型:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="channelType" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option v-for="item in Object.values($channelTypeList)" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button size="mini" type="primary" :loading="getChannelListLoading" :disabled="multipleSelection.length ===0"
|
|
||||||
@click="clearUnusualRegion()">清除</el-button>
|
|
||||||
<el-button size="mini" :loading="getChannelListLoading"
|
|
||||||
@click="clearUnusualRegion(true)">全部清除</el-button>
|
|
||||||
<el-button size="mini" :loading="getChannelListLoading"
|
|
||||||
@click="getChannelList()">刷新</el-button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--通道列表-->
|
|
||||||
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
|
|
||||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
|
|
||||||
<el-table-column type="selection" width="55" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbCivilCode" label="行政区划" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="类型" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" effect="plain" type="success" :style="$channelTypeList[scope.row.dataType].style">{{$channelTypeList[scope.row.dataType].name}}</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" min-width="140" fixed="right">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button
|
|
||||||
size="medium"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-plus"
|
|
||||||
:loading="scope.row.addRegionLoading"
|
|
||||||
@click="addRegion(scope.row)"
|
|
||||||
>
|
|
||||||
添加
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div style="display: grid; grid-template-columns: 1fr 1fr">
|
|
||||||
<div style="text-align: left; line-height: 32px">
|
|
||||||
<i class="el-icon-info"></i> 清除后通道可正常添加到行政区划,添加可以自动添加对应的行政区划节点。
|
|
||||||
</div>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[10, 25, 35, 50, 200, 1000, 50000]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "UnusualRegionChannelSelect",
|
|
||||||
props: [],
|
|
||||||
computed: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
channelList: [], //设备列表
|
|
||||||
searchSrt: "",
|
|
||||||
online: null,
|
|
||||||
channelType: "",
|
|
||||||
winHeight: 580,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 10,
|
|
||||||
total: 0,
|
|
||||||
getChannelListLoading: false,
|
|
||||||
multipleSelection: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
handleSelectionChange: function (val){
|
|
||||||
this.multipleSelection = val;
|
|
||||||
},
|
|
||||||
getChannelList: function () {
|
|
||||||
this.getChannelListLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/common/channel/civilCode/unusual/list`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
channelType: this.channelType,
|
|
||||||
query: this.searchSrt,
|
|
||||||
online: this.online,
|
|
||||||
}
|
|
||||||
}).then( (res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
for (let i = 0; i < res.data.data.list.length; i++) {
|
|
||||||
res.data.data.list[i]["addRegionLoading"] = false
|
|
||||||
}
|
|
||||||
this.channelList = res.data.data.list;
|
|
||||||
}
|
|
||||||
}).catch( (error)=> {
|
|
||||||
console.error(error);
|
|
||||||
}).finally(()=>{
|
|
||||||
this.getChannelListLoading = false;
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
openDialog: function () {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
clearUnusualRegion: function (all) {
|
|
||||||
let channels = null
|
|
||||||
if (all || this.multipleSelection.length > 0 ) {
|
|
||||||
channels = []
|
|
||||||
for (let i = 0; i < this.multipleSelection.length; i++) {
|
|
||||||
channels.push(this.multipleSelection[i].gbId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/common/channel/civilCode/unusual/clear`,
|
|
||||||
data: {
|
|
||||||
all: all,
|
|
||||||
channelIds: channels
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "清除成功"
|
|
||||||
})
|
|
||||||
this.getChannelList()
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
}).finally(()=>{
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
addRegion: function (row) {
|
|
||||||
row.addRegionLoading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/region/description`,
|
|
||||||
params: {
|
|
||||||
civilCode: row.gbCivilCode,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$confirm(`确定添加: ${res.data.data}`, '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'info'
|
|
||||||
}).then(() => {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/region/addByCivilCode`,
|
|
||||||
params: {
|
|
||||||
civilCode: row.gbCivilCode,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "添加成功"
|
|
||||||
})
|
|
||||||
this.initData()
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
}).finally(()=>{
|
|
||||||
row.addRegionLoading = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,154 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="addUser" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="添加用户"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-right: 20px;">
|
|
||||||
<el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
|
|
||||||
<el-form-item label="用户名" prop="username">
|
|
||||||
<el-input v-model="username" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="用户类型" prop="roleId" >
|
|
||||||
<el-select v-model="roleId" placeholder="请选择" style="width: 100%">
|
|
||||||
<el-option
|
|
||||||
v-for="item in options"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="密码" prop="password">
|
|
||||||
<el-input v-model="password" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="确认密码" prop="confirmPassword">
|
|
||||||
<el-input v-model="confirmPassword" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "addUser",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {
|
|
||||||
this.getAllRole();
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
let validatePass1 = (rule, value, callback) => {
|
|
||||||
if (value === '') {
|
|
||||||
callback(new Error('请输入新密码'));
|
|
||||||
} else {
|
|
||||||
if (this.confirmPassword !== '') {
|
|
||||||
this.$refs.passwordForm.validateField('confirmPassword');
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let validatePass2 = (rule, value, callback) => {
|
|
||||||
if (this.confirmPassword === '') {
|
|
||||||
callback(new Error('请再次输入密码'));
|
|
||||||
} else if (this.confirmPassword !== this.password) {
|
|
||||||
callback(new Error('两次输入密码不一致!'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
value:"",
|
|
||||||
options: [],
|
|
||||||
loading: false,
|
|
||||||
username: null,
|
|
||||||
password: null,
|
|
||||||
roleId: null,
|
|
||||||
confirmPassword: null,
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
rules: {
|
|
||||||
newPassword: [{required: true, validator: validatePass1, trigger: "blur"}, {
|
|
||||||
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
|
|
||||||
message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
|
|
||||||
},],
|
|
||||||
confirmPassword: [{required: true, validator: validatePass2, trigger: "blur"}],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (callback) {
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
this.showDialog = true;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/user/add",
|
|
||||||
params: {
|
|
||||||
username: this.username,
|
|
||||||
password: this.password,
|
|
||||||
roleId: this.roleId
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '添加成功',
|
|
||||||
type: 'success',
|
|
||||||
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
this.listChangeCallback()
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.password = null;
|
|
||||||
this.confirmPassword = null;
|
|
||||||
this.username = null;
|
|
||||||
this.roleId = null;
|
|
||||||
},
|
|
||||||
getAllRole:function () {
|
|
||||||
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/role/all"
|
|
||||||
}).then((res) => {
|
|
||||||
this.loading = true;
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.options=res.data.data
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,139 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="addUserApiKey" v-loading="isLoading">
|
|
||||||
<el-dialog
|
|
||||||
title="添加ApiKey"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-right: 20px;">
|
|
||||||
<el-form ref="formRef" :model="form" :rules="rules" status-icon label-width="80px">
|
|
||||||
<el-form-item label="应用名" prop="app">
|
|
||||||
<el-input
|
|
||||||
v-model="form.app"
|
|
||||||
property="app"
|
|
||||||
autocomplete="off"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="启用状态" prop="enable" style="text-align: left">
|
|
||||||
<el-switch
|
|
||||||
v-model="form.enable"
|
|
||||||
property="enable"
|
|
||||||
active-text="启用"
|
|
||||||
inactive-text="停用"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="过期时间" prop="expiresAt" style="text-align: left">
|
|
||||||
<el-date-picker v-model="form.expiresAt"
|
|
||||||
style="width: 100%"
|
|
||||||
property="expiresAt"
|
|
||||||
type="datetime"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
placeholder="选择过期时间"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="备注信息" prop="remark">
|
|
||||||
<el-input v-model="form.remark"
|
|
||||||
type="textarea"
|
|
||||||
property="remark"
|
|
||||||
autocomplete="off"
|
|
||||||
:autosize="{ minRows: 5}"
|
|
||||||
maxlength="255"
|
|
||||||
show-word-limit/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'addUserApiKey',
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
userId: null,
|
|
||||||
form: {
|
|
||||||
app: null,
|
|
||||||
enable: true,
|
|
||||||
expiresAt: null,
|
|
||||||
remark: null
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
app: [{required: true, trigger: 'blur', message: '应用名不能为空'}]
|
|
||||||
},
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoading: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
resetForm() {
|
|
||||||
this.form = {
|
|
||||||
app: null,
|
|
||||||
enable: true,
|
|
||||||
expiresAt: null,
|
|
||||||
remark: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openDialog(userId, callback) {
|
|
||||||
this.resetForm()
|
|
||||||
this.userId = userId
|
|
||||||
this.listChangeCallback = callback
|
|
||||||
this.showDialog = true
|
|
||||||
},
|
|
||||||
onSubmit() {
|
|
||||||
this.$refs.formRef.validate((valid) => {
|
|
||||||
if (valid) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: '/api/userApiKey/add',
|
|
||||||
params: {
|
|
||||||
userId: this.userId,
|
|
||||||
app: this.form.app,
|
|
||||||
enable: this.form.enable,
|
|
||||||
expiresAt: this.form.expiresAt,
|
|
||||||
remark: this.form.remark,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '添加成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.showDialog = false
|
|
||||||
if (this.listChangeCallback) {
|
|
||||||
this.listChangeCallback()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.showDialog = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,158 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="catalogEdit" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="通道共享"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
|
||||||
<el-form ref="form" :rules="rules" :model="form" label-width="140px" >
|
|
||||||
<el-form-item label="节点编号" prop="id" >
|
|
||||||
<el-input v-model="form.id" :disabled="isEdit" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="节点名称" prop="name">
|
|
||||||
<el-input v-model="form.name" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit" >确认</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "catalogEdit",
|
|
||||||
computed: {},
|
|
||||||
props: ['platformId', 'platformDeviceId'],
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
let checkId = (rule, value, callback) => {
|
|
||||||
console.log("checkId")
|
|
||||||
console.log(rule)
|
|
||||||
console.log(value)
|
|
||||||
console.log(value.length)
|
|
||||||
console.log(this.level)
|
|
||||||
if (!value) {
|
|
||||||
return callback(new Error('编号不能为空'));
|
|
||||||
}
|
|
||||||
if (value.trim().length <= 8) {
|
|
||||||
if (value.trim().length%2 !== 0) {
|
|
||||||
return callback(new Error('行政区划编号必须为2/4/6/8位'));
|
|
||||||
}
|
|
||||||
if (this.form.parentId !== this.platformDeviceId && this.form.parentId.length >= value.trim().length) {
|
|
||||||
if (this.form.parentId.length === 20) {
|
|
||||||
return callback(new Error('业务分组/虚拟组织下不可创建行政区划'));
|
|
||||||
}else {
|
|
||||||
return callback(new Error('行政区划编号长度应该每次两位递增'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
if (value.trim().length !== 20) {
|
|
||||||
return callback(new Error('编号必须为2/4/6/8位的行政区划或20位的虚拟组织/业务分组'));
|
|
||||||
}
|
|
||||||
let catalogType = value.substring(10, 13);
|
|
||||||
console.log(catalogType)
|
|
||||||
if (catalogType !== "215" && catalogType !== "216") {
|
|
||||||
return callback(new Error('编号错误,业务分组11-13位为215,虚拟组织11-13位为216'));
|
|
||||||
}
|
|
||||||
if (catalogType === "216") {
|
|
||||||
|
|
||||||
if (this.form.parentId !== this.platformDeviceId){
|
|
||||||
if (this.form.parentId.length <= 8) {
|
|
||||||
return callback(new Error('编号错误,建立虚拟组织前必须先建立业务分组(11-13位为215)'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (catalogType === "215") {
|
|
||||||
if (this.form.parentId.length === "215") {
|
|
||||||
return callback(new Error('编号错误,业务分组下只能建立虚拟组织(11-13位为216)'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
submitCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
isEdit: false,
|
|
||||||
level: 0,
|
|
||||||
form: {
|
|
||||||
id: null,
|
|
||||||
name: null,
|
|
||||||
platformId: null,
|
|
||||||
parentId: null,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
|
||||||
id: [{ required: true, trigger: "blur",validator: checkId }]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (isEdit, id, name, parentId, level, callback) {
|
|
||||||
console.log("parentId: " + parentId)
|
|
||||||
console.log(this.form)
|
|
||||||
this.isEdit = isEdit;
|
|
||||||
this.form.id = id;
|
|
||||||
this.form.name = name;
|
|
||||||
this.form.platformId = this.platformId;
|
|
||||||
this.form.parentId = parentId;
|
|
||||||
this.showDialog = true;
|
|
||||||
this.submitCallback = callback;
|
|
||||||
this.level = level;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
this.$refs["form"].validate((valid) => {
|
|
||||||
if (valid) {
|
|
||||||
this.$axios({
|
|
||||||
method:"post",
|
|
||||||
url:`/api/platform/catalog/${!this.isEdit? "add":"edit"}`,
|
|
||||||
data: this.form
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (this.submitCallback)this.submitCallback(this.form)
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
})
|
|
||||||
.catch((error)=> {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.isEdit = false;
|
|
||||||
this.form.id = null;
|
|
||||||
this.form.name = null;
|
|
||||||
this.form.platformId = null;
|
|
||||||
this.form.parentId = null;
|
|
||||||
this.callback = null;
|
|
||||||
this.showDialog = false;
|
|
||||||
console.log(this.form)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,132 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="changePassword" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="修改密码"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-right: 20px;">
|
|
||||||
<el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
|
|
||||||
<el-form-item label="旧密码" prop="oldPassword" >
|
|
||||||
<el-input v-model="oldPassword" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="新密码" prop="newPassword" >
|
|
||||||
<el-input v-model="newPassword" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="确认密码" prop="confirmPassword">
|
|
||||||
<el-input v-model="confirmPassword" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import userService from "../service/UserService";
|
|
||||||
export default {
|
|
||||||
name: "changePassword",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
let validatePass0 = (rule, value, callback) => {
|
|
||||||
if (value === '') {
|
|
||||||
callback(new Error('请输入旧密码'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let validatePass1 = (rule, value, callback) => {
|
|
||||||
if (value === '') {
|
|
||||||
callback(new Error('请输入新密码'));
|
|
||||||
} else {
|
|
||||||
if (this.confirmPassword !== '') {
|
|
||||||
this.$refs.passwordForm.validateField('confirmPassword');
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let validatePass2 = (rule, value, callback) => {
|
|
||||||
if (this.confirmPassword === '') {
|
|
||||||
callback(new Error('请再次输入密码'));
|
|
||||||
} else if (this.confirmPassword !== this.newPassword) {
|
|
||||||
callback(new Error('两次输入密码不一致!'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
oldPassword: null,
|
|
||||||
newPassword: null,
|
|
||||||
confirmPassword: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
rules: {
|
|
||||||
oldPassword: [{ required: true, validator: validatePass0, trigger: "blur" }],
|
|
||||||
newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, {
|
|
||||||
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
|
|
||||||
message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
|
|
||||||
},],
|
|
||||||
confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function () {
|
|
||||||
this.showDialog = true;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url:"/api/user/changePassword",
|
|
||||||
params: {
|
|
||||||
oldPassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'),
|
|
||||||
password: this.newPassword
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '修改成功,请重新登录',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
setTimeout(()=>{
|
|
||||||
// 删除cookie,回到登录页面
|
|
||||||
userService.clearUserInfo();
|
|
||||||
this.$router.push('/login');
|
|
||||||
this.sseSource.close();
|
|
||||||
},800)
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '修改密码失败,是否已登录(接口鉴权关闭无法修改密码)',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.oldPassword = null;
|
|
||||||
this.newPassword = null;
|
|
||||||
this.confirmPassword = null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="changePassword" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="修改密码"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-right: 20px;">
|
|
||||||
<el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
|
|
||||||
<el-form-item label="新密码" prop="newPassword" >
|
|
||||||
<el-input v-model="newPassword" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="确认密码" prop="confirmPassword">
|
|
||||||
<el-input v-model="confirmPassword" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "changePasswordForAdmin",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
let validatePass1 = (rule, value, callback) => {
|
|
||||||
if (value === '') {
|
|
||||||
callback(new Error('请输入新密码'));
|
|
||||||
} else {
|
|
||||||
if (this.confirmPassword !== '') {
|
|
||||||
this.$refs.passwordForm.validateField('confirmPassword');
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let validatePass2 = (rule, value, callback) => {
|
|
||||||
if (this.confirmPassword === '') {
|
|
||||||
callback(new Error('请再次输入密码'));
|
|
||||||
} else if (this.confirmPassword !== this.newPassword) {
|
|
||||||
callback(new Error('两次输入密码不一致!'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
newPassword: null,
|
|
||||||
confirmPassword: null,
|
|
||||||
userId: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
listChangeCallback: null,
|
|
||||||
form: {},
|
|
||||||
rules: {
|
|
||||||
newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, {
|
|
||||||
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
|
|
||||||
message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
|
|
||||||
},],
|
|
||||||
confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (row, callback) {
|
|
||||||
console.log(row)
|
|
||||||
this.showDialog = true;
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
if (row != null) {
|
|
||||||
this.form = row;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url:"/api/user/changePasswordForAdmin",
|
|
||||||
params: {
|
|
||||||
password: this.newPassword,
|
|
||||||
userId: this.form.id,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '修改成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '修改密码失败,是否已登录(接口鉴权关闭无法修改密码)',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.newPassword = null;
|
|
||||||
this.confirmPassword = null;
|
|
||||||
this.userId=null;
|
|
||||||
this.adminId=null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="changepushKey" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="修改pushKey"
|
|
||||||
width="42%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-right: 18px;">
|
|
||||||
<el-form ref="pushKeyForm" :rules="rules" status-icon label-width="86px">
|
|
||||||
<el-form-item label="新pushKey" prop="newPushKey" >
|
|
||||||
<el-input v-model="newPushKey" autocomplete="off"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "changePushKey",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
let validatePass1 = (rule, value, callback) => {
|
|
||||||
if (value === '') {
|
|
||||||
callback(new Error('请输入新pushKey'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
newPushKey: null,
|
|
||||||
confirmpushKey: null,
|
|
||||||
userId: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
listChangeCallback: null,
|
|
||||||
form: {},
|
|
||||||
rules: {
|
|
||||||
newpushKey: [{ required: true, validator: validatePass1, trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (row, callback) {
|
|
||||||
console.log(row)
|
|
||||||
this.showDialog = true;
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
if (row != null) {
|
|
||||||
this.form = row;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url:"/api/user/changePushKey",
|
|
||||||
params: {
|
|
||||||
pushKey: this.newPushKey,
|
|
||||||
userId: this.form.id,
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '修改成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
this.listChangeCallback();
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '修改pushKey失败,是否已登录(接口鉴权关闭无法修改pushKey)',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.newpushKey = null;
|
|
||||||
this.userId=null;
|
|
||||||
this.adminId=null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,364 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
title="生成国标编码"
|
|
||||||
width="65rem"
|
|
||||||
top="2rem"
|
|
||||||
center
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showVideoDialog"
|
|
||||||
:destroy-on-close="false"
|
|
||||||
>
|
|
||||||
<el-tabs v-model="activeKey" style="padding: 0 1rem; margin: auto 0" @tab-click="getRegionList">
|
|
||||||
<el-tab-pane name="0" >
|
|
||||||
<div slot="label" >
|
|
||||||
<div class="show-code-item">{{ allVal[0].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[0].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio-group v-model="allVal[0].val" >
|
|
||||||
<el-radio v-for="item in regionList" :key="item.deviceId" :label="item.deviceId" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.deviceId }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="1">
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[1].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[1].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio-group v-model="allVal[1].val" :disabled="allVal[1].lock">
|
|
||||||
<el-radio v-for="item in regionList" :key="item.deviceId" :label="item.deviceId.substring(2)" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.deviceId.substring(2) }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="2">
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[2].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[2].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio-group v-model="allVal[2].val" :disabled="allVal[2].lock">
|
|
||||||
<el-radio v-for="item in regionList" :key="item.deviceId" :label="item.deviceId.substring(4)" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.deviceId.substring(4) }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="3">
|
|
||||||
请手动输入基层接入单位编码,两位数字
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[3].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[3].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-input
|
|
||||||
type="text"
|
|
||||||
placeholder="请输入内容"
|
|
||||||
v-model="allVal[3].val"
|
|
||||||
maxlength="2"
|
|
||||||
:disabled="allVal[3].lock"
|
|
||||||
show-word-limit
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="4">
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[4].val }}</div>
|
|
||||||
<div style="text-align: center; ">{{ allVal[4].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio-group v-model="allVal[4].val" :disabled="allVal[4].lock">
|
|
||||||
<el-radio v-for="item in industryCodeTypeList" :key="item.code" :label="item.code" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.code }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="5">
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[5].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[5].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio-group v-model="allVal[5].val" :disabled="allVal[5].lock" >
|
|
||||||
<el-radio v-for="item in deviceTypeList" :label="item.code" :key="item.code" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.code }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="6">
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[6].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[6].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio-group v-model="allVal[6].val" :disabled="allVal[6].lock">
|
|
||||||
<el-radio v-for="item in networkIdentificationTypeList" :label="item.code" :key="item.code" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.code }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="7">
|
|
||||||
请手动输入设备/用户序号, 六位数字
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[7].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[7].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-input
|
|
||||||
type="text"
|
|
||||||
placeholder="请输入内容"
|
|
||||||
v-model="allVal[7].val"
|
|
||||||
maxlength="6"
|
|
||||||
:disabled="allVal[7].lock"
|
|
||||||
show-word-limit
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
<el-form style="">
|
|
||||||
|
|
||||||
<el-form-item style="margin-top: 22px; margin-bottom: 0;">
|
|
||||||
<div style="float:right;">
|
|
||||||
<el-button type="primary" @click="handleOk">保存</el-button>
|
|
||||||
<el-button @click="closeModel">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showVideoDialog: false,
|
|
||||||
activeKey: '0',
|
|
||||||
allVal: [
|
|
||||||
{
|
|
||||||
id: [1, 2],
|
|
||||||
meaning: '省级编码',
|
|
||||||
val: '11',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [3, 4],
|
|
||||||
meaning: '市级编码',
|
|
||||||
val: '01',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [5, 6],
|
|
||||||
meaning: '区级编码',
|
|
||||||
val: '01',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [7, 8],
|
|
||||||
meaning: '基层接入单位编码',
|
|
||||||
val: '01',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [9, 10],
|
|
||||||
meaning: '行业编码',
|
|
||||||
val: '00',
|
|
||||||
type: '行业编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [11, 13],
|
|
||||||
meaning: '类型编码',
|
|
||||||
val: '132',
|
|
||||||
type: '类型编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [14],
|
|
||||||
meaning: '网络标识编码',
|
|
||||||
val: '7',
|
|
||||||
type: '网络标识',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [15, 20],
|
|
||||||
meaning: '设备/用户序号',
|
|
||||||
val: '000001',
|
|
||||||
type: '序号',
|
|
||||||
lock: false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
regionList: [],
|
|
||||||
deviceTypeList: [],
|
|
||||||
industryCodeTypeList: [],
|
|
||||||
networkIdentificationTypeList: [],
|
|
||||||
endCallBck: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (endCallBck, code, lockIndex, lockContent) {
|
|
||||||
console.log(code)
|
|
||||||
this.showVideoDialog = true
|
|
||||||
this.activeKey= '0';
|
|
||||||
this.regionList = []
|
|
||||||
|
|
||||||
this.getRegionList()
|
|
||||||
if (typeof code != 'undefined' && code.length === 20) {
|
|
||||||
this.allVal[0].val = code.substring(0, 2)
|
|
||||||
this.allVal[1].val = code.substring(2, 4)
|
|
||||||
this.allVal[2].val = code.substring(4, 6)
|
|
||||||
this.allVal[3].val = code.substring(6, 8)
|
|
||||||
this.allVal[4].val = code.substring(8, 10)
|
|
||||||
this.allVal[5].val = code.substring(10, 13)
|
|
||||||
this.allVal[6].val = code.substring(13, 14)
|
|
||||||
this.allVal[7].val = code.substring(14)
|
|
||||||
}
|
|
||||||
console.log(this.allVal)
|
|
||||||
if (typeof lockIndex != 'undefined') {
|
|
||||||
this.allVal[lockIndex].lock = true
|
|
||||||
this.allVal[lockIndex].val = lockContent
|
|
||||||
}
|
|
||||||
this.endCallBck = endCallBck;
|
|
||||||
},
|
|
||||||
getRegionList: function() {
|
|
||||||
if (this.activeKey === '0' || this.activeKey === '1' || this.activeKey === '2') {
|
|
||||||
let parent = ''
|
|
||||||
if (this.activeKey === '1') {
|
|
||||||
parent = this.allVal[0].val
|
|
||||||
}
|
|
||||||
if (this.activeKey === '2') {
|
|
||||||
parent = this.allVal[0].val + this.allVal[1].val
|
|
||||||
}
|
|
||||||
if (this.activeKey !== '0' && parent === '') {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: '请先选择上级行政区划'
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
this.queryChildList(parent);
|
|
||||||
} else if (this.activeKey === '4') {
|
|
||||||
console.log(222)
|
|
||||||
this.queryIndustryCodeList();
|
|
||||||
} else if (this.activeKey === '5') {
|
|
||||||
this.queryDeviceTypeList();
|
|
||||||
} else if (this.activeKey === '6') {
|
|
||||||
this.queryNetworkIdentificationTypeList();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
queryChildList: function(parent){
|
|
||||||
this.regionList = []
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/region/base/child/list",
|
|
||||||
params: {
|
|
||||||
parent: parent,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.regionList = res.data.data
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
queryIndustryCodeList: function(){
|
|
||||||
this.industryCodeTypeList = []
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/common/channel/industry/list",
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.industryCodeTypeList = res.data.data
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
queryDeviceTypeList: function(){
|
|
||||||
this.deviceTypeList = []
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/common/channel/type/list",
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.deviceTypeList = res.data.data
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
queryNetworkIdentificationTypeList: function(){
|
|
||||||
this.networkIdentificationTypeList = []
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/common/channel/network/identification/list",
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.networkIdentificationTypeList = res.data.data
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
closeModel: function (){
|
|
||||||
this.showVideoDialog = false
|
|
||||||
},
|
|
||||||
handleOk: function() {
|
|
||||||
const code =
|
|
||||||
this.allVal[0].val +
|
|
||||||
this.allVal[1].val +
|
|
||||||
this.allVal[2].val +
|
|
||||||
this.allVal[3].val +
|
|
||||||
this.allVal[4].val +
|
|
||||||
this.allVal[5].val +
|
|
||||||
this.allVal[6].val +
|
|
||||||
this.allVal[7].val
|
|
||||||
console.log(code)
|
|
||||||
if (this.endCallBck) {
|
|
||||||
this.endCallBck(code)
|
|
||||||
}
|
|
||||||
this.showVideoDialog = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.show-code-item {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 3rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="channelMapInfobox" style="display: none">
|
|
||||||
<div >
|
|
||||||
<el-descriptions class="margin-top" title="channel.name" :column="4" direction="vertical">
|
|
||||||
<el-descriptions-item label="生产厂商">{{channel.manufacture}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="型号">{{channel.model}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="设备归属" >{{channel.owner}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="行政区域" >{{channel.civilCode}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="安装地址" >{{channel.address}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="云台类型" >{{channel.ptzTypeText}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="经纬度" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="状态">
|
|
||||||
<el-tag size="small" v-if="channel.status === 1">在线</el-tag>
|
|
||||||
<el-tag size="small" v-if="channel.status === 0">离线</el-tag>
|
|
||||||
</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import devicePlayer from '../dialog/devicePlayer.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "channelMapInfobox",
|
|
||||||
props: ['channel'],
|
|
||||||
computed: {devicePlayer},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
play: function (){
|
|
||||||
let deviceId = this.channel.deviceId;
|
|
||||||
this.isLoging = true;
|
|
||||||
let channelId = this.channel.channelId;
|
|
||||||
console.log("通知设备推流1:" + deviceId + " : " + channelId);
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/play/start/' + deviceId + '/' + channelId
|
|
||||||
}).then(function (res) {
|
|
||||||
that.isLoging = false;
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
|
|
||||||
streamInfo: res.data.data,
|
|
||||||
hasAudio: this.channel.hasAudio
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
that.$message.error(res.data.msg);
|
|
||||||
}
|
|
||||||
}).catch(function (e) {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="chooseCivilCode" >
|
|
||||||
<el-dialog
|
|
||||||
title="选择行政区划"
|
|
||||||
width="30%"
|
|
||||||
top="5rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<RegionTree ref="regionTree" :showHeader=true :edit="true" :enableAddChannel="false" :clickEvent="treeNodeClickEvent"
|
|
||||||
:onChannelChange="onChannelChange" :treeHeight="'45vh'"></RegionTree>
|
|
||||||
<el-form>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="text-align: right">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import RegionTree from "../common/RegionTree.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "chooseCivilCode",
|
|
||||||
components: {RegionTree},
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
endCallback: false,
|
|
||||||
regionDeviceId: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (callback) {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.endCallback = callback;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
if (this.endCallback) {
|
|
||||||
this.endCallback(this.regionDeviceId)
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
treeNodeClickEvent: function (region) {
|
|
||||||
this.regionDeviceId = region.deviceId;
|
|
||||||
},
|
|
||||||
onChannelChange: function (deviceId) {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="chooseGroup" >
|
|
||||||
<el-dialog
|
|
||||||
title="选择虚拟组织"
|
|
||||||
width="30%"
|
|
||||||
top="5rem"
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<GroupTree ref="regionTree" :showHeader=true :edit="true" :enableAddChannel="false" :clickEvent="treeNodeClickEvent"
|
|
||||||
:onChannelChange="onChannelChange" :treeHeight="'45vh'"></GroupTree>
|
|
||||||
<el-form>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="text-align: right">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import GroupTree from "../common/GroupTree.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "chooseCivilCode",
|
|
||||||
components: {GroupTree},
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
endCallback: false,
|
|
||||||
groupDeviceId: "",
|
|
||||||
businessGroup: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (callback) {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.endCallback = callback;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
if (this.endCallback) {
|
|
||||||
this.endCallback(this.groupDeviceId, this.businessGroup)
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
treeNodeClickEvent: function (group) {
|
|
||||||
if (group.deviceId === "" || group.deviceId === group.businessGroup) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.groupDeviceId = group.deviceId;
|
|
||||||
this.businessGroup = group.businessGroup;
|
|
||||||
},
|
|
||||||
onChannelChange: function (deviceId) {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="configInfo">
|
|
||||||
<el-dialog
|
|
||||||
title="系统信息"
|
|
||||||
width="=80%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
|
||||||
<el-descriptions title="国标服务信息" v-if="configInfoData.sip" :span="2">
|
|
||||||
<el-descriptions-item label="编号" >{{configInfoData.sip.id}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="域">{{configInfoData.sip.domain}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="IP">{{configInfoData.sip.showIp}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="端口">{{configInfoData.sip.port}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="密码">
|
|
||||||
<el-tag size="small">{{configInfoData.sip.password}}</el-tag>
|
|
||||||
</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
<el-descriptions title="版本信息"v-if="configInfoData.version">
|
|
||||||
<el-descriptions-item label="版本">{{configInfoData.version.version}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="编译时间">{{configInfoData.version.build_DATE}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="GIT版本">{{configInfoData.version.git_Revision_SHORT}}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="GIT最后提交时间">{{configInfoData.version.git_DATE}}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "configInfo",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showDialog: false,
|
|
||||||
configInfoData: {
|
|
||||||
sip:{},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (data) {
|
|
||||||
console.log(data)
|
|
||||||
this.showDialog = true;
|
|
||||||
this.configInfoData = data;
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,135 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="deviceEdit" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="设备编辑"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
|
||||||
<el-form ref="form" :rules="rules" :model="form" label-width="200px" >
|
|
||||||
<el-form-item label="设备编号" prop="deviceId">
|
|
||||||
<el-input v-if="isEdit" v-model="form.deviceId" disabled></el-input>
|
|
||||||
<el-input v-if="!isEdit" v-model="form.deviceId" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="设备名称" prop="name">
|
|
||||||
<el-input v-model="form.name" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="密码" prop="password">
|
|
||||||
<el-input v-model="form.password" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="收流IP" prop="sdpIp">
|
|
||||||
<el-input type="sdpIp" v-model="form.sdpIp" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流媒体ID" prop="mediaServerId">
|
|
||||||
<el-select v-model="form.mediaServerId" style="float: left; width: 100%" >
|
|
||||||
<el-option key="auto" label="自动负载最小" value="auto"></el-option>
|
|
||||||
<el-option
|
|
||||||
v-for="item in mediaServerList"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.id"
|
|
||||||
:value="item.id">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="字符集" prop="charset" >
|
|
||||||
<el-select v-model="form.charset" style="float: left; width: 100%" >
|
|
||||||
<el-option key="GB2312" label="GB2312" value="gb2312"></el-option>
|
|
||||||
<el-option key="UTF-8" label="UTF-8" value="utf-8"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="其他选项">
|
|
||||||
<el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
|
|
||||||
<el-checkbox label="作为消息通道" v-model="form.asMessageChannel" style="float: left"></el-checkbox>
|
|
||||||
<el-checkbox label="收到ACK后发流" v-model="form.broadcastPushAfterAck" style="float: left"></el-checkbox>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit" >确认</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MediaServer from '../service/MediaServer'
|
|
||||||
export default {
|
|
||||||
name: "deviceEdit",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
hostNames:[],
|
|
||||||
mediaServerList: [], // 滅体节点列表
|
|
||||||
mediaServerObj : new MediaServer(),
|
|
||||||
form: {},
|
|
||||||
isEdit: false,
|
|
||||||
rules: {
|
|
||||||
deviceId: [{ required: true, message: "请输入设备编号", trigger: "blur" }]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (row, callback) {
|
|
||||||
console.log(row)
|
|
||||||
this.showDialog = true;
|
|
||||||
this.isEdit = false;
|
|
||||||
if (row) {
|
|
||||||
this.isEdit = true;
|
|
||||||
}
|
|
||||||
this.form = {};
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
if (row != null) {
|
|
||||||
this.form = row;
|
|
||||||
}
|
|
||||||
this.getMediaServerList();
|
|
||||||
},
|
|
||||||
getMediaServerList: function (){
|
|
||||||
let that = this;
|
|
||||||
that.mediaServerObj.getOnlineMediaServerList((data)=>{
|
|
||||||
that.mediaServerList = data.data;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
console.log("onSubmit");
|
|
||||||
console.log(this.form);
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url:`/api/device/query/device/${this.isEdit?'update':'add'}`,
|
|
||||||
data: this.form
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res.data)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.listChangeCallback()
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.$refs.form.resetFields();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,866 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="devicePlayer" v-loading="isLoging">
|
|
||||||
|
|
||||||
<el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="close()" v-if="showVideoDialog">
|
|
||||||
<div style="width: 100%; height: 100%">
|
|
||||||
<el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer"
|
|
||||||
v-if="Object.keys(this.player).length > 1">
|
|
||||||
<el-tab-pane label="Jessibuca" name="jessibuca">
|
|
||||||
<jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog"
|
|
||||||
:videoUrl="videoUrl" :error="videoError" :message="videoError"
|
|
||||||
:hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="WebRTC" name="webRTC">
|
|
||||||
<rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog"
|
|
||||||
:videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px"
|
|
||||||
:hasAudio="hasAudio" fluent autoplay live></rtc-player>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="h265web" name="h265web">
|
|
||||||
<h265web v-if="activePlayer === 'h265web'" ref="h265web"
|
|
||||||
:videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px"
|
|
||||||
:hasAudio="hasAudio" fluent autoplay live></h265web>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
<jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca"
|
|
||||||
:visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
|
|
||||||
:hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
|
|
||||||
<rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca"
|
|
||||||
:visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
|
|
||||||
height="100px" :hasAudio="hasAudio" fluent autoplay live></rtc-player>
|
|
||||||
<h265web v-if="Object.keys(this.player).length == 1 && this.player.h265web" ref="jessibuca"
|
|
||||||
:visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
|
|
||||||
height="100px" :hasAudio="hasAudio" fluent autoplay live></h265web>
|
|
||||||
</div>
|
|
||||||
<div id="shared" style="text-align: right; margin-top: 1rem;">
|
|
||||||
|
|
||||||
<el-tabs v-model="tabActiveName" @tab-click="tabHandleClick">
|
|
||||||
<el-tab-pane label="实时视频" name="media">
|
|
||||||
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
|
|
||||||
<span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span>
|
|
||||||
<el-input v-model="getPlayerShared.sharedUrl" :disabled="true">
|
|
||||||
<template slot="append">
|
|
||||||
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedUrl"
|
|
||||||
@success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
|
|
||||||
<span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe:</span>
|
|
||||||
<el-input v-model="getPlayerShared.sharedIframe" :disabled="true">
|
|
||||||
<template slot="append">
|
|
||||||
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedIframe"
|
|
||||||
@success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
|
|
||||||
<span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span>
|
|
||||||
<el-input v-model="getPlayerShared.sharedRtmp" :disabled="true">
|
|
||||||
<el-button slot="append" icon="el-icon-document-copy" title="点击拷贝"
|
|
||||||
v-clipboard="getPlayerShared.sharedRtmp"
|
|
||||||
@success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
|
|
||||||
<el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl">
|
|
||||||
<el-button>
|
|
||||||
更多地址<i class="el-icon-arrow-down el-icon--right"></i>
|
|
||||||
</el-button>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv">
|
|
||||||
<el-tag>FLV:</el-tag>
|
|
||||||
<span>{{ streamInfo.flv }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv">
|
|
||||||
<el-tag>FLV(https):</el-tag>
|
|
||||||
<span>{{ streamInfo.https_flv }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv">
|
|
||||||
<el-tag>FLV(ws):</el-tag>
|
|
||||||
<span>{{ streamInfo.ws_flv }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv">
|
|
||||||
<el-tag>FLV(wss):</el-tag>
|
|
||||||
<span>{{ streamInfo.wss_flv }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4">
|
|
||||||
<el-tag>FMP4:</el-tag>
|
|
||||||
<span>{{ streamInfo.fmp4 }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4">
|
|
||||||
<el-tag>FMP4(https):</el-tag>
|
|
||||||
<span>{{ streamInfo.https_fmp4 }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4">
|
|
||||||
<el-tag>FMP4(ws):</el-tag>
|
|
||||||
<span>{{ streamInfo.ws_fmp4 }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4">
|
|
||||||
<el-tag>FMP4(wss):</el-tag>
|
|
||||||
<span>{{ streamInfo.wss_fmp4 }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls">
|
|
||||||
<el-tag>HLS:</el-tag>
|
|
||||||
<span>{{ streamInfo.hls }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls">
|
|
||||||
<el-tag>HLS(https):</el-tag>
|
|
||||||
<span>{{ streamInfo.https_hls }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls">
|
|
||||||
<el-tag>HLS(ws):</el-tag>
|
|
||||||
<span>{{ streamInfo.ws_hls }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls">
|
|
||||||
<el-tag>HLS(wss):</el-tag>
|
|
||||||
<span>{{ streamInfo.wss_hls }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts">
|
|
||||||
<el-tag>TS:</el-tag>
|
|
||||||
<span>{{ streamInfo.ts }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts">
|
|
||||||
<el-tag>TS(https):</el-tag>
|
|
||||||
<span>{{ streamInfo.https_ts }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts">
|
|
||||||
<el-tag>TS(ws):</el-tag>
|
|
||||||
<span>{{ streamInfo.ws_ts }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts">
|
|
||||||
<el-tag>TS(wss):</el-tag>
|
|
||||||
<span>{{ streamInfo.wss_ts }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc">
|
|
||||||
<el-tag>RTC:</el-tag>
|
|
||||||
<span>{{ streamInfo.rtc }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs">
|
|
||||||
<el-tag>RTCS:</el-tag>
|
|
||||||
<span>{{ streamInfo.rtcs }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp">
|
|
||||||
<el-tag>RTMP:</el-tag>
|
|
||||||
<span>{{ streamInfo.rtmp }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps">
|
|
||||||
<el-tag>RTMPS:</el-tag>
|
|
||||||
<span>{{ streamInfo.rtmps }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp">
|
|
||||||
<el-tag>RTSP:</el-tag>
|
|
||||||
<span>{{ streamInfo.rtsp }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps">
|
|
||||||
<el-tag>RTSPS:</el-tag>
|
|
||||||
<span>{{ streamInfo.rtsps }}</span>
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
</el-input>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
|
||||||
<!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
|
|
||||||
<!--遥控界面-->
|
|
||||||
<el-tab-pane label="云台控制" name="control" v-if="showPtz">
|
|
||||||
<div style="display: grid; grid-template-columns: 240px auto; height: 180px; overflow: auto">
|
|
||||||
<div style="display: grid; grid-template-columns: 6.25rem auto;">
|
|
||||||
|
|
||||||
<div class="control-wrapper">
|
|
||||||
<div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">
|
|
||||||
<i class="el-icon-caret-top"></i>
|
|
||||||
<div class="control-inner-btn control-inner"></div>
|
|
||||||
</div>
|
|
||||||
<div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')">
|
|
||||||
<i class="el-icon-caret-left"></i>
|
|
||||||
<div class="control-inner-btn control-inner"></div>
|
|
||||||
</div>
|
|
||||||
<div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')">
|
|
||||||
<i class="el-icon-caret-bottom"></i>
|
|
||||||
<div class="control-inner-btn control-inner"></div>
|
|
||||||
</div>
|
|
||||||
<div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')">
|
|
||||||
<i class="el-icon-caret-right"></i>
|
|
||||||
<div class="control-inner-btn control-inner"></div>
|
|
||||||
</div>
|
|
||||||
<div class="control-round">
|
|
||||||
<div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
|
|
||||||
</div>
|
|
||||||
<div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 6.25rem;">
|
|
||||||
<el-slider v-model="controSpeed" :max="100"></el-slider>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="ptz-btn-box">
|
|
||||||
<div style="" @mousedown="ptzCamera('zoomin')" @mouseup="ptzCamera('stop')" title="变倍+">
|
|
||||||
<i class="el-icon-zoom-in control-zoom-btn" style="font-size: 1.5rem;"></i>
|
|
||||||
</div>
|
|
||||||
<div style="" @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')" title="变倍-">
|
|
||||||
<i class="el-icon-zoom-out control-zoom-btn" style="font-size: 1.5rem;"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ptz-btn-box">
|
|
||||||
<div @mousedown="focusCamera('near')" @mouseup="focusCamera('stop')" title="聚焦+">
|
|
||||||
<i class="iconfont icon-bianjiao-fangda control-zoom-btn" style="font-size: 1.5rem;"></i>
|
|
||||||
</div>
|
|
||||||
<div @mousedown="focusCamera('far')" @mouseup="focusCamera('stop')" title="聚焦-">
|
|
||||||
<i class="iconfont icon-bianjiao-suoxiao control-zoom-btn" style="font-size: 1.5rem;"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ptz-btn-box">
|
|
||||||
<div @mousedown="irisCamera('in')" @mouseup="irisCamera('stop')" title="光圈+">
|
|
||||||
<i class="iconfont icon-guangquan control-zoom-btn" style="font-size: 1.5rem;"></i>
|
|
||||||
</div>
|
|
||||||
<div @mousedown="pirisCamera('out')" @mouseup="irisCamera('stop')" title="光圈-">
|
|
||||||
<i class="iconfont icon-guangquan- control-zoom-btn" style="font-size: 1.5rem;"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: left" >
|
|
||||||
<el-select
|
|
||||||
v-model="ptzMethod"
|
|
||||||
style="width: 100%"
|
|
||||||
size="mini"
|
|
||||||
placeholder="请选择云台功能"
|
|
||||||
>
|
|
||||||
<el-option label="预置点" value="preset"></el-option>
|
|
||||||
<el-option label="巡航组" value="cruise"></el-option>
|
|
||||||
<el-option label="自动扫描" value="scan"></el-option>
|
|
||||||
<el-option label="雨刷" value="wiper"></el-option>
|
|
||||||
<el-option label="辅助开关" value="switch"></el-option>
|
|
||||||
</el-select>
|
|
||||||
|
|
||||||
<ptzPreset :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'preset'" style="margin-top: 1rem"></ptzPreset>
|
|
||||||
<ptzCruising :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'cruise'" style="margin-top: 1rem"></ptzCruising>
|
|
||||||
<ptzScan :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'scan'" style="margin-top: 1rem"></ptzScan>
|
|
||||||
<ptzWiper :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'wiper'" style="margin-top: 1rem"></ptzWiper>
|
|
||||||
<ptzSwitch :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'switch'" style="margin-top: 1rem"></ptzSwitch>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="编码信息" name="codec" >
|
|
||||||
<mediaInfo ref="mediaInfo" :app="app" :stream="streamId" :mediaServerId="mediaServerId"></mediaInfo>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="语音对讲" name="broadcast">
|
|
||||||
<div style="padding: 0 10px">
|
|
||||||
<!-- <el-switch v-model="broadcastMode" :disabled="broadcastStatus !== -1" active-color="#409EFF"-->
|
|
||||||
<!-- active-text="喊话(Broadcast)"-->
|
|
||||||
<!-- inactive-text="对讲(Talk)"></el-switch>-->
|
|
||||||
|
|
||||||
<el-radio-group v-model="broadcastMode" :disabled="broadcastStatus !== -1">
|
|
||||||
<el-radio :label="true" >喊话(Broadcast)</el-radio>
|
|
||||||
<el-radio :label="false" >对讲(Talk)</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
<div class="trank" style="text-align: center;">
|
|
||||||
<el-button @click="broadcastStatusClick()" :type="getBroadcastStatus()" :disabled="broadcastStatus === -2"
|
|
||||||
circle icon="el-icon-microphone" style="font-size: 32px; padding: 24px;margin-top: 24px;"/>
|
|
||||||
<p>
|
|
||||||
<span v-if="broadcastStatus === -2">正在释放资源</span>
|
|
||||||
<span v-if="broadcastStatus === -1">点击开始对讲</span>
|
|
||||||
<span v-if="broadcastStatus === 0">等待接通中...</span>
|
|
||||||
<span v-if="broadcastStatus === 1">请说话</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
|
||||||
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import rtcPlayer from '../dialog/rtcPlayer.vue'
|
|
||||||
import LivePlayer from '@liveqing/liveplayer'
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import jessibucaPlayer from '../common/jessibuca.vue'
|
|
||||||
import PtzPreset from "../common/ptzPreset.vue";
|
|
||||||
import PtzCruising from "../common/ptzCruising.vue";
|
|
||||||
import ptzScan from "../common/ptzScan.vue";
|
|
||||||
import ptzWiper from "../common/ptzWiper.vue";
|
|
||||||
import ptzSwitch from "../common/ptzSwitch.vue";
|
|
||||||
import mediaInfo from "../common/mediaInfo.vue";
|
|
||||||
import H265web from "../common/h265web.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'devicePlayer',
|
|
||||||
props: {},
|
|
||||||
components: {
|
|
||||||
H265web,
|
|
||||||
PtzPreset,PtzCruising,ptzScan,ptzWiper,ptzSwitch,mediaInfo,
|
|
||||||
LivePlayer, jessibucaPlayer, rtcPlayer,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
getPlayerShared: function () {
|
|
||||||
return {
|
|
||||||
sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl),
|
|
||||||
sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>',
|
|
||||||
sharedRtmp: this.videoUrl
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
console.log("created")
|
|
||||||
console.log(this.player)
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
if (Object.keys(this.player).length === 1) {
|
|
||||||
this.activePlayer = Object.keys(this.player)[0]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4',
|
|
||||||
videoUrl: '',
|
|
||||||
activePlayer: "jessibuca",
|
|
||||||
// 如何你只是用一种播放器,直接注释掉不用的部分即可
|
|
||||||
player: {
|
|
||||||
jessibuca: ["ws_flv", "wss_flv"],
|
|
||||||
webRTC: ["rtc", "rtcs"],
|
|
||||||
h265web: ["ws_flv", "wss_flv"],
|
|
||||||
},
|
|
||||||
showVideoDialog: false,
|
|
||||||
streamId: '',
|
|
||||||
ptzMethod: 'preset',
|
|
||||||
ptzPresetId: '',
|
|
||||||
app: '',
|
|
||||||
mediaServerId: '',
|
|
||||||
deviceId: '',
|
|
||||||
channelId: '',
|
|
||||||
tabActiveName: 'media',
|
|
||||||
hasAudio: false,
|
|
||||||
loadingRecords: false,
|
|
||||||
recordsLoading: false,
|
|
||||||
isLoging: false,
|
|
||||||
controSpeed: 30,
|
|
||||||
timeVal: 0,
|
|
||||||
timeMin: 0,
|
|
||||||
timeMax: 1440,
|
|
||||||
presetPos: 1,
|
|
||||||
cruisingSpeed: 100,
|
|
||||||
cruisingTime: 5,
|
|
||||||
cruisingGroup: 0,
|
|
||||||
scanSpeed: 100,
|
|
||||||
scanGroup: 0,
|
|
||||||
tracks: [],
|
|
||||||
showPtz: true,
|
|
||||||
showRrecord: true,
|
|
||||||
sliderTime: 0,
|
|
||||||
seekTime: 0,
|
|
||||||
recordStartTime: 0,
|
|
||||||
showTimeText: "00:00:00",
|
|
||||||
streamInfo: null,
|
|
||||||
broadcastMode: true,
|
|
||||||
broadcastRtc: null,
|
|
||||||
broadcastStatus: -1, // -2 正在释放资源 -1 默认状态 0 等待接通 1 接通成功
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
tabHandleClick: function (tab, event) {
|
|
||||||
console.log(tab)
|
|
||||||
this.tracks = [];
|
|
||||||
if (tab.name === "codec") {
|
|
||||||
this.$refs.mediaInfo.startTask()
|
|
||||||
}else {
|
|
||||||
this.$refs.mediaInfo.stopTask()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changePlayer: function (tab) {
|
|
||||||
console.log(this.player[tab.name][0])
|
|
||||||
this.activePlayer = tab.name;
|
|
||||||
this.videoUrl = this.getUrlByStreamInfo()
|
|
||||||
console.log(this.videoUrl)
|
|
||||||
},
|
|
||||||
openDialog: function (tab, deviceId, channelId, param) {
|
|
||||||
if (this.showVideoDialog) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.tabActiveName = tab;
|
|
||||||
this.channelId = channelId;
|
|
||||||
this.deviceId = deviceId;
|
|
||||||
this.streamId = "";
|
|
||||||
this.mediaServerId = "";
|
|
||||||
this.app = "";
|
|
||||||
this.videoUrl = ""
|
|
||||||
if (!!this.$refs[this.activePlayer]) {
|
|
||||||
this.$refs[this.activePlayer].pause();
|
|
||||||
}
|
|
||||||
switch (tab) {
|
|
||||||
case "media":
|
|
||||||
this.play(param.streamInfo, param.hasAudio)
|
|
||||||
break;
|
|
||||||
case "streamPlay":
|
|
||||||
this.tabActiveName = "media";
|
|
||||||
this.showRrecord = false;
|
|
||||||
this.showPtz = false;
|
|
||||||
this.play(param.streamInfo, param.hasAudio)
|
|
||||||
break;
|
|
||||||
case "control":
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
play: function (streamInfo, hasAudio) {
|
|
||||||
this.streamInfo = streamInfo;
|
|
||||||
this.hasAudio = hasAudio;
|
|
||||||
this.isLoging = false;
|
|
||||||
// this.videoUrl = streamInfo.rtc;
|
|
||||||
this.videoUrl = this.getUrlByStreamInfo();
|
|
||||||
this.streamId = streamInfo.stream;
|
|
||||||
this.app = streamInfo.app;
|
|
||||||
this.mediaServerId = streamInfo.mediaServerId;
|
|
||||||
this.playFromStreamInfo(false, streamInfo)
|
|
||||||
},
|
|
||||||
getUrlByStreamInfo() {
|
|
||||||
console.log(this.streamInfo)
|
|
||||||
let streamInfo = this.streamInfo
|
|
||||||
if (this.streamInfo.transcodeStream) {
|
|
||||||
streamInfo = this.streamInfo.transcodeStream;
|
|
||||||
}
|
|
||||||
if (location.protocol === "https:") {
|
|
||||||
this.videoUrl = streamInfo[this.player[this.activePlayer][1]]
|
|
||||||
} else {
|
|
||||||
this.videoUrl = streamInfo[this.player[this.activePlayer][0]]
|
|
||||||
}
|
|
||||||
return this.videoUrl;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
playFromStreamInfo: function (realHasAudio, streamInfo) {
|
|
||||||
this.showVideoDialog = true;
|
|
||||||
this.hasaudio = realHasAudio && this.hasaudio;
|
|
||||||
if (this.$refs[this.activePlayer]) {
|
|
||||||
this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo))
|
|
||||||
}else {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
console.log('关闭视频');
|
|
||||||
if (!!this.$refs[this.activePlayer]){
|
|
||||||
this.$refs[this.activePlayer].pause();
|
|
||||||
}
|
|
||||||
this.videoUrl = '';
|
|
||||||
this.coverPlaying = false;
|
|
||||||
this.showVideoDialog = false;
|
|
||||||
this.stopBroadcast()
|
|
||||||
},
|
|
||||||
|
|
||||||
copySharedInfo: function (data) {
|
|
||||||
console.log('复制内容:' + data);
|
|
||||||
this.coverPlaying = false;
|
|
||||||
this.tracks = []
|
|
||||||
let _this = this;
|
|
||||||
this.$copyText(data).then(
|
|
||||||
function (e) {
|
|
||||||
_this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '复制成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function (e) {
|
|
||||||
_this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '复制失败,请手动复制',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
ptzCamera: function (command) {
|
|
||||||
console.log('云台控制:' + command);
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/front-end/ptz/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + parseInt(this.controSpeed * 255/100) + '&verticalSpeed=' + parseInt(this.controSpeed * 255/100) + '&zoomSpeed=' + parseInt(this.controSpeed * 16/100)
|
|
||||||
}).then(function (res) {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
irisCamera: function (command) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/front-end/fi/iris/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&speed=' + parseInt(this.controSpeed * 255/100)
|
|
||||||
}).then(function (res) {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
focusCamera: function (command) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/front-end/fi/focus/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&speed=' + parseInt(this.controSpeed * 255/100)
|
|
||||||
}).then(function (res) {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
//////////////////////播放器事件处理//////////////////////////
|
|
||||||
videoError: function (e) {
|
|
||||||
console.log("播放器错误:" + JSON.stringify(e));
|
|
||||||
},
|
|
||||||
copyUrl: function (dropdownItem) {
|
|
||||||
console.log(dropdownItem)
|
|
||||||
this.$copyText(dropdownItem).then((e) => {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "成功拷贝到粘贴板"
|
|
||||||
})
|
|
||||||
}, (e) => {
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getBroadcastStatus() {
|
|
||||||
if (this.broadcastStatus == -2) {
|
|
||||||
return "primary"
|
|
||||||
}
|
|
||||||
if (this.broadcastStatus == -1) {
|
|
||||||
return "primary"
|
|
||||||
}
|
|
||||||
if (this.broadcastStatus == 0) {
|
|
||||||
return "warning"
|
|
||||||
}
|
|
||||||
if (this.broadcastStatus == 1) {
|
|
||||||
return "danger"
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
broadcastStatusClick() {
|
|
||||||
if (this.broadcastStatus == -1) {
|
|
||||||
// 默认状态, 开始
|
|
||||||
this.broadcastStatus = 0
|
|
||||||
// 发起语音对讲
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/play/broadcast/' + this.deviceId + '/' + this.channelId + "?timeout=30&broadcastMode=" + this.broadcastMode
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
let streamInfo = res.data.data.streamInfo;
|
|
||||||
if (document.location.protocol.includes("https")) {
|
|
||||||
this.startBroadcast(streamInfo.rtcs)
|
|
||||||
} else {
|
|
||||||
this.startBroadcast(streamInfo.rtc)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (this.broadcastStatus === 1) {
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
this.broadcastRtc.close()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
startBroadcast(url) {
|
|
||||||
// 获取推流鉴权Key
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: '/api/user/userInfo',
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code !== 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "获取推流鉴权Key失败",
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
} else {
|
|
||||||
let pushKey = res.data.data.pushKey;
|
|
||||||
// 获取推流鉴权KEY
|
|
||||||
url += "&sign=" + crypto.createHash('md5').update(pushKey, "utf8").digest('hex')
|
|
||||||
console.log("开始语音喊话: " + url)
|
|
||||||
this.broadcastRtc = new ZLMRTCClient.Endpoint({
|
|
||||||
debug: true, // 是否打印日志
|
|
||||||
zlmsdpUrl: url, //流地址
|
|
||||||
simulecast: false,
|
|
||||||
useCamera: false,
|
|
||||||
audioEnable: true,
|
|
||||||
videoEnable: false,
|
|
||||||
recvOnly: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_NOT_SUPPORT, (e) => {// 获取到了本地流
|
|
||||||
console.error('不支持webrtc', e)
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '不支持webrtc, 无法进行语音喊话',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR, (e) => {// ICE 协商出错
|
|
||||||
console.error('ICE 协商出错')
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: 'ICE 协商出错',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, (e) => {// offer anwser 交换失败
|
|
||||||
console.error('offer anwser 交换失败', e)
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: 'offer anwser 交换失败' + e,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
});
|
|
||||||
this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, (e) => {// offer anwser 交换失败
|
|
||||||
console.log('状态改变', e)
|
|
||||||
if (e === "connecting") {
|
|
||||||
this.broadcastStatus = 0;
|
|
||||||
} else if (e === "connected") {
|
|
||||||
this.broadcastStatus = 1;
|
|
||||||
} else if (e === "disconnected") {
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.broadcastRtc.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED, (e) => {// offer anwser 交换失败
|
|
||||||
console.log('捕获流失败', e)
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '捕获流失败' + e,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((e) => {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: e,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
stopBroadcast() {
|
|
||||||
this.broadcastRtc.close();
|
|
||||||
this.broadcastStatus = -1;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/play/broadcast/stop/' + this.deviceId + '/' + this.channelId
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code == 0) {
|
|
||||||
// this.broadcastStatus = -1;
|
|
||||||
// this.broadcastRtc.close()
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.control-wrapper {
|
|
||||||
position: relative;
|
|
||||||
width: 6.25rem;
|
|
||||||
height: 6.25rem;
|
|
||||||
max-width: 6.25rem;
|
|
||||||
max-height: 6.25rem;
|
|
||||||
border-radius: 100%;
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-panel {
|
|
||||||
position: relative;
|
|
||||||
top: 0;
|
|
||||||
left: 5rem;
|
|
||||||
height: 11rem;
|
|
||||||
max-height: 11rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-btn {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
position: absolute;
|
|
||||||
width: 44%;
|
|
||||||
height: 44%;
|
|
||||||
border-radius: 5px;
|
|
||||||
border: 1px solid #78aee4;
|
|
||||||
box-sizing: border-box;
|
|
||||||
transition: all 0.3s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-btn:hover {
|
|
||||||
cursor: pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-btn i {
|
|
||||||
font-size: 20px;
|
|
||||||
color: #78aee4;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-btn i:hover {
|
|
||||||
cursor: pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-zoom-btn:hover {
|
|
||||||
cursor: pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-round {
|
|
||||||
position: absolute;
|
|
||||||
top: 21%;
|
|
||||||
left: 21%;
|
|
||||||
width: 58%;
|
|
||||||
height: 58%;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-round-inner {
|
|
||||||
position: absolute;
|
|
||||||
left: 13%;
|
|
||||||
top: 13%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
width: 70%;
|
|
||||||
height: 70%;
|
|
||||||
font-size: 40px;
|
|
||||||
color: #78aee4;
|
|
||||||
border: 1px solid #78aee4;
|
|
||||||
border-radius: 100%;
|
|
||||||
transition: all 0.3s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-inner-btn {
|
|
||||||
position: absolute;
|
|
||||||
width: 60%;
|
|
||||||
height: 60%;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-top {
|
|
||||||
top: -8%;
|
|
||||||
left: 27%;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
border-radius: 5px 100% 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-top i {
|
|
||||||
transform: rotate(45deg);
|
|
||||||
border-radius: 5px 100% 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-top .control-inner {
|
|
||||||
left: -1px;
|
|
||||||
bottom: 0;
|
|
||||||
border-top: 1px solid #78aee4;
|
|
||||||
border-right: 1px solid #78aee4;
|
|
||||||
border-radius: 0 100% 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-top .fa {
|
|
||||||
transform: rotate(45deg) translateY(-7px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-left {
|
|
||||||
top: 27%;
|
|
||||||
left: -8%;
|
|
||||||
transform: rotate(45deg);
|
|
||||||
border-radius: 5px 0 5px 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-left i {
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-left .control-inner {
|
|
||||||
right: -1px;
|
|
||||||
top: -1px;
|
|
||||||
border-bottom: 1px solid #78aee4;
|
|
||||||
border-left: 1px solid #78aee4;
|
|
||||||
border-radius: 0 0 0 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-left .fa {
|
|
||||||
transform: rotate(-45deg) translateX(-7px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-right {
|
|
||||||
top: 27%;
|
|
||||||
right: -8%;
|
|
||||||
transform: rotate(45deg);
|
|
||||||
border-radius: 5px 100% 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-right i {
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-right .control-inner {
|
|
||||||
left: -1px;
|
|
||||||
bottom: -1px;
|
|
||||||
border-top: 1px solid #78aee4;
|
|
||||||
border-right: 1px solid #78aee4;
|
|
||||||
border-radius: 0 100% 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-right .fa {
|
|
||||||
transform: rotate(-45deg) translateX(7px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-bottom {
|
|
||||||
left: 27%;
|
|
||||||
bottom: -8%;
|
|
||||||
transform: rotate(45deg);
|
|
||||||
border-radius: 0 5px 100% 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-bottom i {
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-bottom .control-inner {
|
|
||||||
top: -1px;
|
|
||||||
left: -1px;
|
|
||||||
border-bottom: 1px solid #78aee4;
|
|
||||||
border-right: 1px solid #78aee4;
|
|
||||||
border-radius: 0 0 100% 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-bottom .fa {
|
|
||||||
transform: rotate(-45deg) translateY(7px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.trank {
|
|
||||||
width: 80%;
|
|
||||||
height: 180px;
|
|
||||||
text-align: left;
|
|
||||||
padding: 0 10%;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.trankInfo {
|
|
||||||
width: 80%;
|
|
||||||
padding: 0 10%;
|
|
||||||
}
|
|
||||||
.el-dialog__body{
|
|
||||||
padding: 10px 20px;
|
|
||||||
}
|
|
||||||
.ptz-btn-box {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
padding: 0 2rem;
|
|
||||||
height: 3rem;
|
|
||||||
line-height: 4rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,228 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="editRecordPlan" v-loading="loading" style="text-align: left;">
|
|
||||||
<el-dialog
|
|
||||||
title="录制计划"
|
|
||||||
width="700px"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-right: 20px;">
|
|
||||||
<el-form >
|
|
||||||
<el-form-item label="名称">
|
|
||||||
<el-input type="text" v-model="planName"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<ByteWeektimePicker v-model="byteTime" name="name"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right; margin-top: 20px">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ByteWeektimePicker } from 'byte-weektime-picker'
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "editRecordPlan",
|
|
||||||
props: {},
|
|
||||||
components: {ByteWeektimePicker},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
options: [],
|
|
||||||
loading: false,
|
|
||||||
edit: false,
|
|
||||||
planName: null,
|
|
||||||
id: null,
|
|
||||||
showDialog: false,
|
|
||||||
endCallback: "",
|
|
||||||
byteTime: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (recordPlan, endCallback) {
|
|
||||||
this.endCallback = endCallback;
|
|
||||||
this.showDialog = true;
|
|
||||||
this.byteTime= "";
|
|
||||||
if (recordPlan) {
|
|
||||||
this.edit = true
|
|
||||||
this.planName = recordPlan.name
|
|
||||||
this.id = recordPlan.id
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/record/plan/get",
|
|
||||||
params: {
|
|
||||||
planId: recordPlan.id,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0 && res.data.data.planItemList) {
|
|
||||||
this.byteTime = this.plan2Byte(res.data.data.planItemList)
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
let planList = this.byteTime2PlanList();
|
|
||||||
if (!this.edit) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/record/plan/add",
|
|
||||||
data: {
|
|
||||||
name: this.planName,
|
|
||||||
planItemList: planList
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '添加成功',
|
|
||||||
type: 'success',
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
this.endCallback()
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: "/api/record/plan/update",
|
|
||||||
data: {
|
|
||||||
id: this.id,
|
|
||||||
name: this.planName,
|
|
||||||
planItemList: planList
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '更新成功',
|
|
||||||
type: 'success',
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
this.endCallback()
|
|
||||||
} else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.id = null
|
|
||||||
this.planName = null
|
|
||||||
this.byteTime = ""
|
|
||||||
this.endCallback = ""
|
|
||||||
if(this.endCallback) {
|
|
||||||
this.endCallback();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
byteTime2PlanList() {
|
|
||||||
if (this.byteTime.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const DayTimes = 24 * 2;
|
|
||||||
let planList = []
|
|
||||||
let week = 1;
|
|
||||||
// 把 336长度的 list 分成 7 组,每组 48 个
|
|
||||||
for (let i = 0; i < this.byteTime.length; i += DayTimes) {
|
|
||||||
let planArray = this.byteTime2Plan(this.byteTime.slice(i, i + DayTimes));
|
|
||||||
if(!planArray || planArray.length === 0) {
|
|
||||||
week ++;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for (let j = 0; j < planArray.length; j++) {
|
|
||||||
planList.push({
|
|
||||||
planId: this.id,
|
|
||||||
start: planArray[j].start,
|
|
||||||
stop: planArray[j].stop,
|
|
||||||
weekDay: week
|
|
||||||
})
|
|
||||||
}
|
|
||||||
week ++;
|
|
||||||
}
|
|
||||||
return planList
|
|
||||||
},
|
|
||||||
byteTime2Plan(weekItem){
|
|
||||||
let start = null;
|
|
||||||
let stop = null;
|
|
||||||
let result = []
|
|
||||||
for (let i = 0; i < weekItem.length; i++) {
|
|
||||||
let item = weekItem[i]
|
|
||||||
if (item === '1') { // 表示选中
|
|
||||||
stop = i
|
|
||||||
if (start === null ) {
|
|
||||||
start = i
|
|
||||||
}
|
|
||||||
if (i === weekItem.length - 1 && start != null && stop != null) {
|
|
||||||
result.push({
|
|
||||||
start: start,
|
|
||||||
stop: stop,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (stop !== null){
|
|
||||||
result.push({
|
|
||||||
start: start,
|
|
||||||
stop: stop,
|
|
||||||
})
|
|
||||||
start = null
|
|
||||||
stop = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
plan2Byte(planList) {
|
|
||||||
let byte = ""
|
|
||||||
let indexArray = {}
|
|
||||||
for (let i = 0; i < planList.length; i++) {
|
|
||||||
|
|
||||||
let weekDay = planList[i].weekDay
|
|
||||||
let index = planList[i].start
|
|
||||||
let endIndex = planList[i].stop
|
|
||||||
for (let j = index; j <= endIndex; j++) {
|
|
||||||
indexArray["key_" + (j + (weekDay - 1 )*48)] = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = 0; i < 336; i++) {
|
|
||||||
if (indexArray["key_" + i]){
|
|
||||||
byte += "1"
|
|
||||||
}else {
|
|
||||||
byte += "0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return byte
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="groupEdit" v-loading="loading">
|
|
||||||
<el-dialog
|
|
||||||
title="分组编辑"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
|
||||||
<el-form ref="form" :model="group" label-width="140px" >
|
|
||||||
<el-form-item label="节点编号" prop="id" >
|
|
||||||
<el-input v-model="group.deviceId" placeholder="请输入编码">
|
|
||||||
<el-button slot="append" @click="buildDeviceIdCode(group.deviceId)">生成</el-button>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="节点名称" prop="name">
|
|
||||||
<el-input v-model="group.name" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="行政区划" prop="name">
|
|
||||||
<el-input v-model="group.civilCode" >
|
|
||||||
<el-button slot="append" @click="buildCivilCode(group.civilCode)">选择</el-button>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit" >确认</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
<channelCode ref="channelCode"></channelCode>
|
|
||||||
<chooseCivilCode ref="chooseCivilCode"></chooseCivilCode>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import channelCode from "./channelCode.vue";
|
|
||||||
import ChooseCivilCode from "./chooseCivilCode.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "groupEdit",
|
|
||||||
components: {ChooseCivilCode, channelCode},
|
|
||||||
computed: {},
|
|
||||||
props: [],
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
submitCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
loading: false,
|
|
||||||
level: 0,
|
|
||||||
group: {
|
|
||||||
id: 0,
|
|
||||||
deviceId: "",
|
|
||||||
name: "",
|
|
||||||
parentDeviceId: "",
|
|
||||||
businessGroup: "",
|
|
||||||
civilCode: "",
|
|
||||||
platformId: "",
|
|
||||||
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (group, callback) {
|
|
||||||
console.log(group)
|
|
||||||
if (group) {
|
|
||||||
this.group = group;
|
|
||||||
}
|
|
||||||
this.showDialog = true;
|
|
||||||
this.submitCallback = callback;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
|
|
||||||
this.$axios({
|
|
||||||
method:"post",
|
|
||||||
url: this.group.id ? '/api/group/update':'/api/group/add',
|
|
||||||
data: this.group
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
})
|
|
||||||
if (this.submitCallback)this.submitCallback(this.group)
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
})
|
|
||||||
.catch((error)=> {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: error,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
buildDeviceIdCode: function (deviceId){
|
|
||||||
console.log(this.group)
|
|
||||||
let lockContent = this.group.businessGroup ? "216":"215"
|
|
||||||
this.$refs.channelCode.openDialog(code=>{
|
|
||||||
this.group.deviceId = code;
|
|
||||||
}, deviceId, 5 , lockContent);
|
|
||||||
},
|
|
||||||
buildCivilCode: function (deviceId){
|
|
||||||
this.$refs.chooseCivilCode.openDialog(code=>{
|
|
||||||
this.group.civilCode = code;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
console.log(this.group)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="importChannel" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="导入通道数据"
|
|
||||||
width="30rem"
|
|
||||||
top="2rem"
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<el-upload
|
|
||||||
class="upload-box"
|
|
||||||
drag
|
|
||||||
:action="uploadUrl"
|
|
||||||
name="file"
|
|
||||||
:headers="headers"
|
|
||||||
:on-success="successHook"
|
|
||||||
:on-error="errorHook"
|
|
||||||
>
|
|
||||||
<i class="el-icon-upload"></i>
|
|
||||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
|
||||||
<div class="el-upload__tip" slot="tip">只能上传 csv / xls / xlsx 文件</div>
|
|
||||||
</el-upload>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
<ShowErrorData ref="showErrorData" :gbIds="errorGBIds" :streams="errorStreams" ></ShowErrorData>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import ShowErrorData from './importChannelShowErrorData.vue'
|
|
||||||
|
|
||||||
import userService from "../service/UserService";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "importChannel",
|
|
||||||
components: {
|
|
||||||
ShowErrorData,
|
|
||||||
},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
submitCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
isEdit: false,
|
|
||||||
errorStreams: [],
|
|
||||||
errorGBIds: [],
|
|
||||||
headers: {
|
|
||||||
"access-token": userService.getToken()
|
|
||||||
},
|
|
||||||
uploadUrl: process.env.NODE_ENV === 'development'? `http://127.0.0.1:8080/debug/api/push/upload`: (window.baseUrl ? window.baseUrl : "") + `/api/push/upload`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (callback) {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.submitCallback = callback;
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
console.log("onSubmit");
|
|
||||||
console.log(this.form);
|
|
||||||
this.$axios({
|
|
||||||
method:"post",
|
|
||||||
url:`/api/platform/catalog/${!this.isEdit? "add":"edit"}`,
|
|
||||||
data: this.form
|
|
||||||
})
|
|
||||||
.then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
console.log("添加/修改成功")
|
|
||||||
if (this.submitCallback)this.submitCallback()
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
})
|
|
||||||
.catch((error)=> {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
successHook: function(response, file, fileList){
|
|
||||||
if (response.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: response.msg,
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
}else if (response.code === 1) {
|
|
||||||
this.errorGBIds = response.data.gbId
|
|
||||||
this.errorStreams = response.data.stream
|
|
||||||
console.log(this.$refs)
|
|
||||||
console.log(this.$refs.showErrorData)
|
|
||||||
this.$refs.showErrorData.openDialog()
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: response.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
errorHook: function (err, file, fileList) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: err,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.upload-box{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.errDataBox{
|
|
||||||
max-height: 15rem;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="importChannelShowErrorData" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="导入通道数据成功,但数据存在重复"
|
|
||||||
width="30rem"
|
|
||||||
top="2rem"
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div >
|
|
||||||
重复国标ID:
|
|
||||||
<el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="gbIds.join(',')" @success="$message({type:'success', message:'成功拷贝到粘贴板'})">复制</el-button>
|
|
||||||
<ul class="errDataBox">
|
|
||||||
<li v-for="id in gbIds" >
|
|
||||||
{{ id }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div >
|
|
||||||
重复App/stream:
|
|
||||||
<el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="streams.join(',')" @success="$message({type:'success', message:'成功拷贝到粘贴板'})">复制</el-button>
|
|
||||||
<ul class="errDataBox">
|
|
||||||
<li v-for="id in streams" >
|
|
||||||
{{ id }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "importChannelShowErrorData",
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
props: ['gbIds', 'streams'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isLoging: false,
|
|
||||||
showDialog: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function () {
|
|
||||||
this.showDialog = true;
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.errDataBox{
|
|
||||||
max-height: 15rem;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,351 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="linkChannelRecord" style="width: 100%; background-color: #FFFFFF; display: grid; grid-template-columns: 200px auto;">
|
|
||||||
<el-dialog title="通道关联" v-loading="dialogLoading" v-if="showDialog" top="2rem" width="80%" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()">
|
|
||||||
<div style="display: grid; grid-template-columns: 100px auto;">
|
|
||||||
<el-tabs tab-position="left" style="" v-model="hasLink" @tab-click="search">
|
|
||||||
<el-tab-pane label="未关联" name="false"></el-tab-pane>
|
|
||||||
<el-tab-pane label="已关联" name="true"></el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
<div>
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-header-btn" >
|
|
||||||
<div style="display: inline;">
|
|
||||||
搜索:
|
|
||||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
|
||||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
|
||||||
|
|
||||||
在线状态:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option label="在线" value="true"></el-option>
|
|
||||||
<el-option label="离线" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
类型:
|
|
||||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="channelType" placeholder="请选择"
|
|
||||||
default-first-option>
|
|
||||||
<el-option label="全部" value=""></el-option>
|
|
||||||
<el-option v-for="item in Object.values($channelTypeList)" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-button v-if="hasLink !=='true'" size="mini" type="primary" @click="add()">
|
|
||||||
添加
|
|
||||||
</el-button>
|
|
||||||
<el-button v-if="hasLink ==='true'" size="mini" type="danger" @click="remove()">
|
|
||||||
移除
|
|
||||||
</el-button>
|
|
||||||
<el-button size="mini" v-if="hasLink !=='true'" @click="addByDevice()">按设备添加</el-button>
|
|
||||||
<el-button size="mini" v-if="hasLink ==='true'" @click="removeByDevice()">按设备移除</el-button>
|
|
||||||
<el-button size="mini" v-if="hasLink !=='true'" @click="addAll()">添加所有通道</el-button>
|
|
||||||
<el-button size="mini" v-if="hasLink ==='true'" @click="removeAll()">移除所有通道</el-button>
|
|
||||||
<el-button size="mini" @click="getChannelList()">刷新</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight"
|
|
||||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
|
|
||||||
<el-table-column type="selection" width="55" >
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="类型" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" effect="plain" type="success" :style="$channelTypeList[scope.row.dataType].style">{{$channelTypeList[scope.row.dataType].name}}</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="100">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<div slot="reference" class="name-wrapper">
|
|
||||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
|
||||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination
|
|
||||||
style="text-align: right"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="currentChange"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:page-size="count"
|
|
||||||
:page-sizes="[15, 25, 35, 50]"
|
|
||||||
layout="total, sizes, prev, pager, next"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import gbDeviceSelect from "./GbDeviceSelect.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'linkChannelRecord',
|
|
||||||
components: {gbDeviceSelect},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogLoading: false,
|
|
||||||
showDialog: false,
|
|
||||||
chooseData: {},
|
|
||||||
channelList: [],
|
|
||||||
searchSrt: "",
|
|
||||||
channelType: "",
|
|
||||||
online: "",
|
|
||||||
hasLink: "false",
|
|
||||||
winHeight: window.innerHeight - 250,
|
|
||||||
currentPage: 1,
|
|
||||||
count: 15,
|
|
||||||
total: 0,
|
|
||||||
loading: false,
|
|
||||||
planId: null,
|
|
||||||
loadSnap: {},
|
|
||||||
multipleSelection: []
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {},
|
|
||||||
destroyed() {},
|
|
||||||
methods: {
|
|
||||||
openDialog(planId, closeCallback) {
|
|
||||||
this.planId = planId
|
|
||||||
this.showDialog = true
|
|
||||||
this.closeCallback = closeCallback
|
|
||||||
this.initData()
|
|
||||||
},
|
|
||||||
initData: function () {
|
|
||||||
this.currentPage= 1;
|
|
||||||
this.count= 15;
|
|
||||||
this.total= 0;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
currentChange: function (val) {
|
|
||||||
this.currentPage = val;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
handleSizeChange: function (val) {
|
|
||||||
this.count = val;
|
|
||||||
this.getChannelList();
|
|
||||||
},
|
|
||||||
getChannelList: function () {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/record/plan/channel/list`,
|
|
||||||
params: {
|
|
||||||
page: this.currentPage,
|
|
||||||
count: this.count,
|
|
||||||
query: this.searchSrt,
|
|
||||||
online: this.online,
|
|
||||||
channelType: this.channelType,
|
|
||||||
planId: this.planId,
|
|
||||||
hasLink: this.hasLink
|
|
||||||
}
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.total = res.data.data.total;
|
|
||||||
this.channelList = res.data.data.list;
|
|
||||||
// 防止出现表格错位
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.channelListTable.doLayout();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error)=> {
|
|
||||||
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleSelectionChange: function (val){
|
|
||||||
this.multipleSelection = val;
|
|
||||||
},
|
|
||||||
|
|
||||||
linkPlan: function (data){
|
|
||||||
this.loading = true
|
|
||||||
return this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: `/api/record/plan/link`,
|
|
||||||
data: data
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message.success({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功"
|
|
||||||
})
|
|
||||||
this.getChannelList()
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch((error)=> {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
})
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
add: function (row) {
|
|
||||||
let channels = []
|
|
||||||
for (let i = 0; i < this.multipleSelection.length; i++) {
|
|
||||||
channels.push(this.multipleSelection[i].gbId)
|
|
||||||
}
|
|
||||||
if (channels.length === 0) {
|
|
||||||
this.$message.info({
|
|
||||||
showClose: true,
|
|
||||||
message: "请选择通道"
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.linkPlan({
|
|
||||||
planId: this.planId,
|
|
||||||
channelIds: channels
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addAll: function (row) {
|
|
||||||
this.$confirm("添加所有通道将包括已经添加到其他计划的通道,确定添加所有通道?", '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.linkPlan({
|
|
||||||
planId: this.planId,
|
|
||||||
allLink: true
|
|
||||||
})
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
addByDevice: function (row) {
|
|
||||||
this.$refs.gbDeviceSelect.openDialog((rows)=>{
|
|
||||||
let deviceIds = []
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
|
||||||
deviceIds.push(rows[i].id)
|
|
||||||
}
|
|
||||||
this.linkPlan({
|
|
||||||
planId: this.planId,
|
|
||||||
deviceDbIds: deviceIds
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
removeByDevice: function (row) {
|
|
||||||
this.$refs.gbDeviceSelect.openDialog((rows)=>{
|
|
||||||
let deviceIds = []
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
|
||||||
deviceIds.push(rows[i].id)
|
|
||||||
}
|
|
||||||
this.linkPlan({
|
|
||||||
deviceDbIds: deviceIds
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
remove: function (row) {
|
|
||||||
let channels = []
|
|
||||||
for (let i = 0; i < this.multipleSelection.length; i++) {
|
|
||||||
channels.push(this.multipleSelection[i].gbId)
|
|
||||||
}
|
|
||||||
if (channels.length === 0) {
|
|
||||||
this.$message.info({
|
|
||||||
showClose: true,
|
|
||||||
message: "请选择通道"
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.linkPlan({
|
|
||||||
channelIds: channels
|
|
||||||
})
|
|
||||||
},
|
|
||||||
removeAll: function (row) {
|
|
||||||
|
|
||||||
this.$confirm("确定移除所有通道?", '提示', {
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
this.linkPlan({
|
|
||||||
planId: this.planId,
|
|
||||||
allLink: false
|
|
||||||
})
|
|
||||||
}).catch(() => {
|
|
||||||
});
|
|
||||||
},
|
|
||||||
search: function () {
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.total = 0;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
refresh: function () {
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.videoList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item {
|
|
||||||
position: relative;
|
|
||||||
width: 15rem;
|
|
||||||
height: 10rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-img:after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
background-image: url("../../assets/loading.png");
|
|
||||||
background-size: cover;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-item-title {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: #000000;
|
|
||||||
background-color: #ffffff;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
padding: 0.3rem;
|
|
||||||
width: 14.4rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="onvif搜索" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title="onvif搜索"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
|
||||||
<el-form ref="form" :rules="rules" :model="form" label-width="140px" >
|
|
||||||
<el-form-item label="地址" prop="hostName" >
|
|
||||||
<el-select v-model="form.hostName" style="float: left; width: 100%" >
|
|
||||||
<el-option
|
|
||||||
v-for="item in hostNames"
|
|
||||||
:key="item"
|
|
||||||
:label="item.replace('http://', '')"
|
|
||||||
:value="item">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="用户名" prop="username">
|
|
||||||
<el-input v-model="form.username" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="密码" prop="password">
|
|
||||||
<el-input v-model="form.password" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit" >确认</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "onvifEdit",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
hostNames:[],
|
|
||||||
form: {
|
|
||||||
hostName: null,
|
|
||||||
username: "admin",
|
|
||||||
password: "admin123",
|
|
||||||
},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
hostName: [{ required: true, message: "请选择", trigger: "blur" }],
|
|
||||||
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
|
||||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (hostNamesParam, callback) {
|
|
||||||
console.log(hostNamesParam)
|
|
||||||
this.showDialog = true;
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
if (hostNamesParam != null) {
|
|
||||||
this.hostNames = hostNamesParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
console.log("onSubmit");
|
|
||||||
console.log(this.form);
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url:`/api/onvif/rtsp`,
|
|
||||||
params: {
|
|
||||||
hostname: this.form.hostName,
|
|
||||||
timeout: 3000,
|
|
||||||
username: this.form.username,
|
|
||||||
password: this.form.password,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
console.log(res.data)
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
if (res.data.data != null) {
|
|
||||||
this.listChangeCallback(res.data.data)
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.$refs.form.resetFields();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,181 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="log" style="width: 100%;height: 100%;">
|
|
||||||
<div style="width: 100%; height: 40px; display: grid; grid-template-columns: 1fr 1fr">
|
|
||||||
<div style="text-align: left; line-height: 40px;">
|
|
||||||
<span style="width: 5vw">过滤: </span>
|
|
||||||
<el-input size="mini" v-model="filter" placeholder="请输入过滤关键字" style="width: 20vw"></el-input>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right; line-height: 40px;">
|
|
||||||
<el-button size="mini" icon="el-icon-download" @click="downloadFile()">下载
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<log-viewer :log="logData" :auto-scroll="true" :height="winHeight"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import userService from "./../service/UserService";
|
|
||||||
import moment from "moment/moment";
|
|
||||||
import stripAnsi from "strip-ansi";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'log',
|
|
||||||
props: [ 'fileUrl', 'remoteUrl', 'loadEnd'],
|
|
||||||
components: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
winHeight: window.innerHeight - 300,
|
|
||||||
data: [],
|
|
||||||
filter: "",
|
|
||||||
logData: "",
|
|
||||||
websocket: null,
|
|
||||||
destroyedCallback: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
remoteUrl(newValue) {
|
|
||||||
console.log(newValue);
|
|
||||||
this.remoteUrl = newValue;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
fileUrl(newValue) {
|
|
||||||
this.fileUrl = newValue;
|
|
||||||
this.initData();
|
|
||||||
},
|
|
||||||
filter(newValue) {
|
|
||||||
this.filter = newValue;
|
|
||||||
this.logData = this.getLogData();
|
|
||||||
},
|
|
||||||
data(newValue) {
|
|
||||||
this.data = newValue;
|
|
||||||
this.logData = this.getLogData();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.data = []
|
|
||||||
if (this.fileUrl || this.remoteUrl) {
|
|
||||||
this.initData();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
console.log('destroyed');
|
|
||||||
if (this.destroyedCallback) {
|
|
||||||
this.destroyedCallback()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initData: function () {
|
|
||||||
this.loading = true
|
|
||||||
this.data = []
|
|
||||||
console.log(this.loading)
|
|
||||||
if (this.fileUrl) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: this.fileUrl,
|
|
||||||
}).then((res) => {
|
|
||||||
let dataArray = res.data.split("\n");
|
|
||||||
dataArray.forEach(item => {
|
|
||||||
this.data.push(item);
|
|
||||||
})
|
|
||||||
this.loading = false
|
|
||||||
if (this.loadEnd && typeof this.loadEnd === "function") {
|
|
||||||
this.loadEnd()
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}else if (this.remoteUrl) {
|
|
||||||
console.log('remoteUrl' + this.remoteUrl);
|
|
||||||
console.log(window.location.host)
|
|
||||||
window.websocket = new WebSocket(this.remoteUrl, userService.getToken());
|
|
||||||
window.websocket.onclose = e => {
|
|
||||||
console.log(`conn closed: code=${e.code}, reason=${e.reason}, wasClean=${e.wasClean}`)
|
|
||||||
}
|
|
||||||
window.websocket.onmessage = e => {
|
|
||||||
this.loading = false
|
|
||||||
this.data.push(e.data);
|
|
||||||
}
|
|
||||||
window.websocket.onerror = e => {
|
|
||||||
console.log(`conn err`)
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
window.websocket.onopen = e => {
|
|
||||||
console.log(`conn open: ${e}`);
|
|
||||||
this.destroyedCallback = ()=>{
|
|
||||||
window.websocket.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getLogData: function () {
|
|
||||||
this.loading = true;
|
|
||||||
if (this.data.length === 0) {
|
|
||||||
this.loading = false;
|
|
||||||
return "";
|
|
||||||
}else {
|
|
||||||
let result = '';
|
|
||||||
for (let i = 0; i < this.data.length; i++) {
|
|
||||||
if (this.filter.length === 0) {
|
|
||||||
result += this.data[i] + "\r\n"
|
|
||||||
}else {
|
|
||||||
if (this.data[i].indexOf(this.filter) > -1) {
|
|
||||||
result += this.data[i] + "\r\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.loading = false;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getLogDataWithOutAnsi: function () {
|
|
||||||
if (this.data.length === 0) {
|
|
||||||
return "";
|
|
||||||
}else {
|
|
||||||
let result = '';
|
|
||||||
for (let i = 0; i < this.data.length; i++) {
|
|
||||||
if (this.filter.length === 0) {
|
|
||||||
result += stripAnsi(this.data[i]) + "\r\n"
|
|
||||||
}else {
|
|
||||||
if (this.data[i].indexOf(this.filter) > -1) {
|
|
||||||
result += stripAnsi(this.data[i]) + "\r\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
downloadFile() {
|
|
||||||
let blob = new Blob([this.getLogDataWithOutAnsi()], {
|
|
||||||
type: "text/plain;charset=utf-8"
|
|
||||||
});
|
|
||||||
let reader = new FileReader();
|
|
||||||
reader.readAsDataURL(blob);
|
|
||||||
reader.onload = (e)=> {
|
|
||||||
let a = document.createElement('a');
|
|
||||||
a.download = `wvp-${this.filter}-${moment().format('yyyy-MM-DD')}.log`;
|
|
||||||
a.href = e.target.result;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
document.body.removeChild(a);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.log-loading{
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
background-color: transparent;
|
|
||||||
font-size: 20px;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,180 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="addStreamProxy" v-loading="isLoging">
|
|
||||||
<el-dialog
|
|
||||||
title=" 加入"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
|
||||||
<el-form ref="streamProxy" :rules="rules" :model="proxyParam" label-width="140px">
|
|
||||||
<el-form-item label="名称" prop="name">
|
|
||||||
<el-input v-model="proxyParam.name" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流应用名" prop="app">
|
|
||||||
<el-input v-model="proxyParam.app" clearable :disabled="edit"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="流ID" prop="stream">
|
|
||||||
<el-input v-model="proxyParam.stream" clearable :disabled="edit"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="国标编码" prop="gbId">
|
|
||||||
<el-input v-model="proxyParam.gbId" placeholder="设置国标编码可推送到国标" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="经度" prop="longitude" v-if="proxyParam.gbId">
|
|
||||||
<el-input v-model="proxyParam.longitude" placeholder="经度" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="纬度" prop="latitude" v-if="proxyParam.gbId">
|
|
||||||
<el-input v-model="proxyParam.latitude" placeholder="经度" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<div style="float: right;">
|
|
||||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "pushStreamEdit",
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
// var deviceGBIdRules = async (rule, value, callback) => {
|
|
||||||
// console.log(value);
|
|
||||||
// if (value === "") {
|
|
||||||
// callback(new Error("请输入设备国标编号"));
|
|
||||||
// } else {
|
|
||||||
// var exit = await this.deviceGBIdExit(value);
|
|
||||||
// console.log(exit);
|
|
||||||
// console.log(exit == "true");
|
|
||||||
// console.log(exit === "true");
|
|
||||||
// if (exit) {
|
|
||||||
// callback(new Error("设备国标编号已存在"));
|
|
||||||
// } else {
|
|
||||||
// callback();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
return {
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
edit: false,
|
|
||||||
proxyParam: {
|
|
||||||
name: null,
|
|
||||||
app: null,
|
|
||||||
stream: null,
|
|
||||||
gbId: null,
|
|
||||||
longitude: null,
|
|
||||||
latitude: null,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
|
||||||
app: [{ required: true, message: "请输入应用名", trigger: "blur" }],
|
|
||||||
stream: [{ required: true, message: "请输入流ID", trigger: "blur" }],
|
|
||||||
gbId: [{ required: true, message: "请输入国标编码", trigger: "blur" }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (proxyParam, callback) {
|
|
||||||
this.showDialog = true;
|
|
||||||
this.listChangeCallback = callback;
|
|
||||||
if (proxyParam != null) {
|
|
||||||
this.proxyParam = proxyParam;
|
|
||||||
this.edit = true
|
|
||||||
}else{
|
|
||||||
this.proxyParam= {
|
|
||||||
name: null,
|
|
||||||
app: null,
|
|
||||||
stream: null,
|
|
||||||
gbId: null,
|
|
||||||
longitude: null,
|
|
||||||
latitude: null,
|
|
||||||
}
|
|
||||||
this.edit = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSubmit: function () {
|
|
||||||
console.log("onSubmit");
|
|
||||||
if (this.edit) {
|
|
||||||
this.$axios({
|
|
||||||
method:"post",
|
|
||||||
url:`/api/push/save_to_gb`,
|
|
||||||
data: this.proxyParam
|
|
||||||
}).then( (res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
if (this.listChangeCallback != null) {
|
|
||||||
this.listChangeCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}else {
|
|
||||||
this.$axios({
|
|
||||||
method:"post",
|
|
||||||
url:`/api/push/add`,
|
|
||||||
data: this.proxyParam
|
|
||||||
}).then( (res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: "保存成功",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
this.showDialog = false;
|
|
||||||
if (this.listChangeCallback != null) {
|
|
||||||
this.listChangeCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch((error)=> {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
console.log("关闭加入GB");
|
|
||||||
this.showDialog = false;
|
|
||||||
this.$refs.streamProxy.resetFields();
|
|
||||||
},
|
|
||||||
deviceGBIdExit: async function (deviceGbId) {
|
|
||||||
var result = false;
|
|
||||||
var that = this;
|
|
||||||
await that.$axios({
|
|
||||||
method:"get",
|
|
||||||
url:`/api/platform/exit/${deviceGbId}`
|
|
||||||
}).then(function (res) {
|
|
||||||
result = res.data;
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
checkExpires: function() {
|
|
||||||
if (this.platform.enable && this.platform.expires == "0") {
|
|
||||||
this.platform.expires = "300";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleNodeClick: function (node){
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="queryTrace" >
|
|
||||||
<el-dialog
|
|
||||||
title="查询轨迹"
|
|
||||||
width="40%"
|
|
||||||
top="2rem"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showDialog"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
@close="close()"
|
|
||||||
>
|
|
||||||
<div v-loading="isLoging">
|
|
||||||
<el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" value-format="yyyy-MM-dd HH:mm:ss" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
|
|
||||||
<el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" value-format="yyyy-MM-dd HH:mm:ss" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
|
|
||||||
<el-button icon="el-icon-search" size="mini" type="primary" @click="onSubmit">查询</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import DeviceService from '../service/DeviceService'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "deviceEdit",
|
|
||||||
props: [],
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
deviceService: new DeviceService(),
|
|
||||||
pickerOptions: {
|
|
||||||
shortcuts: [{
|
|
||||||
text: '今天',
|
|
||||||
onClick(picker) {
|
|
||||||
picker.$emit('pick', new Date());
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
text: '昨天',
|
|
||||||
onClick(picker) {
|
|
||||||
const date = new Date();
|
|
||||||
date.setTime(date.getTime() - 3600 * 1000 * 24);
|
|
||||||
picker.$emit('pick', date);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
text: '一周前',
|
|
||||||
onClick(picker) {
|
|
||||||
const date = new Date();
|
|
||||||
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
|
|
||||||
picker.$emit('pick', date);
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
searchFrom: null,
|
|
||||||
searchTo: null,
|
|
||||||
listChangeCallback: null,
|
|
||||||
showDialog: false,
|
|
||||||
isLoging: false,
|
|
||||||
channel: null,
|
|
||||||
callback: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (channel, callback) {
|
|
||||||
console.log(channel)
|
|
||||||
this.showDialog = true;
|
|
||||||
this.callback = callback;
|
|
||||||
this.channel = channel;
|
|
||||||
},
|
|
||||||
|
|
||||||
onSubmit: function () {
|
|
||||||
console.log("onSubmit");
|
|
||||||
this.isLoging = true;
|
|
||||||
let url = `/api/position/history/${this.channel.deviceId}?start=${this.searchFrom}&end=${this.searchTo}`;
|
|
||||||
if (this.channel.channelId) {
|
|
||||||
url+="&channelId=${this.channel.channelId}"
|
|
||||||
}
|
|
||||||
this.$axios.get(url, {
|
|
||||||
}).then((res)=> {
|
|
||||||
this.isLoging = false;
|
|
||||||
if (typeof this.callback == "function") {
|
|
||||||
if (res.data.code == 0) {
|
|
||||||
this.callback(res.data.data)
|
|
||||||
this.close()
|
|
||||||
}else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}).catch(function (error) {
|
|
||||||
this.isLoging = false;
|
|
||||||
console.error(error);
|
|
||||||
})
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
this.showDialog = false;
|
|
||||||
this.isLoging = false;
|
|
||||||
this.callback = null;
|
|
||||||
this.channel = null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,156 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="recordDownload" >
|
|
||||||
<el-dialog :title="title" v-if="showDialog" width="45rem" :append-to-body="true" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()" center>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="18" style="padding-top: 7px;">
|
|
||||||
<el-progress :percentage="percentage"></el-progress>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6" >
|
|
||||||
<el-button icon="el-icon-download" v-if="downloadFile" size="mini" title="点击下载" @click="downloadFileClientEvent()">下载</el-button>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import moment from "moment";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'recordDownload',
|
|
||||||
created() {
|
|
||||||
window.addEventListener('beforeunload', this.stopDownloadRecord)
|
|
||||||
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
title: "下载中...",
|
|
||||||
deviceId: "",
|
|
||||||
channelId: "",
|
|
||||||
app: "",
|
|
||||||
stream: "",
|
|
||||||
mediaServerId: "",
|
|
||||||
showDialog: false,
|
|
||||||
scale: 1,
|
|
||||||
percentage: 0.00,
|
|
||||||
streamInfo: null,
|
|
||||||
taskId: null,
|
|
||||||
getProgressRun: false,
|
|
||||||
timer: null,
|
|
||||||
downloadFile: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (deviceId, channelId, app, stream, mediaServerId) {
|
|
||||||
this.deviceId = deviceId;
|
|
||||||
this.channelId = channelId;
|
|
||||||
this.app = app;
|
|
||||||
this.stream = stream;
|
|
||||||
this.mediaServerId = mediaServerId;
|
|
||||||
this.showDialog = true;
|
|
||||||
this.getProgressRun = true;
|
|
||||||
this.percentage = 0.0;
|
|
||||||
this.downloadFile = null;
|
|
||||||
this.getProgressTimer()
|
|
||||||
},
|
|
||||||
getProgressTimer: function (){
|
|
||||||
if (!this.getProgressRun) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.downloadFile) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setTimeout( ()=>{
|
|
||||||
if (!this.showDialog) return;
|
|
||||||
this.getProgress(this.getProgressTimer)
|
|
||||||
}, 5000)
|
|
||||||
},
|
|
||||||
getProgress: function (callback){
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
|
|
||||||
}).then((res)=> {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.streamInfo = res.data.data;
|
|
||||||
if (parseFloat(res.data.progress) === 1) {
|
|
||||||
this.percentage = 100;
|
|
||||||
}else {
|
|
||||||
this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1);
|
|
||||||
}
|
|
||||||
if (this.streamInfo.downLoadFilePath) {
|
|
||||||
if (location.protocol === "https:") {
|
|
||||||
this.downloadFile = this.streamInfo.downLoadFilePath.httpsPath;
|
|
||||||
}else {
|
|
||||||
this.downloadFile = this.streamInfo.downLoadFilePath.httpPath;
|
|
||||||
}
|
|
||||||
this.percentage = 100
|
|
||||||
this.getProgressRun = false;
|
|
||||||
this.downloadFileClientEvent()
|
|
||||||
}
|
|
||||||
if (callback)callback();
|
|
||||||
}else {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((e) =>{
|
|
||||||
console.log(e)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: function (){
|
|
||||||
if (this.streamInfo.progress < 1) {
|
|
||||||
this.stopDownloadRecord();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.timer !== null) {
|
|
||||||
window.clearTimeout(this.timer);
|
|
||||||
this.timer = null;
|
|
||||||
}
|
|
||||||
this.showDialog=false;
|
|
||||||
this.getProgressRun = false;
|
|
||||||
},
|
|
||||||
gbScale: function (scale){
|
|
||||||
this.scale = scale;
|
|
||||||
},
|
|
||||||
|
|
||||||
stopDownloadRecord: function (callback) {
|
|
||||||
if (this.deviceId && this.channelId && this.stream) {
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.stream
|
|
||||||
}).then((res)=> {
|
|
||||||
if (callback) callback(res)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
downloadFileClientEvent: function (){
|
|
||||||
// window.open(this.downloadFile )
|
|
||||||
|
|
||||||
let x = new XMLHttpRequest();
|
|
||||||
x.open("GET", this.downloadFile, true);
|
|
||||||
x.responseType = 'blob';
|
|
||||||
x.onload=(e)=> {
|
|
||||||
let url = window.URL.createObjectURL(x.response)
|
|
||||||
let a = document.createElement('a');
|
|
||||||
a.href = url
|
|
||||||
a.download = this.deviceId + "-" + this.channelId + ".mp4";
|
|
||||||
a.click()
|
|
||||||
}
|
|
||||||
x.send();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
window.removeEventListener('beforeunload', this.stopDownloadRecord)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,275 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
title="生成行政区划编码"
|
|
||||||
width="65rem"
|
|
||||||
top="2rem"
|
|
||||||
center
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:visible.sync="showVideoDialog"
|
|
||||||
:destroy-on-close="false"
|
|
||||||
>
|
|
||||||
<el-tabs v-model="activeKey" style="padding: 0 1rem; margin: auto 0" @tab-click="getRegionList">
|
|
||||||
<el-tab-pane name="0" >
|
|
||||||
<div slot="label" >
|
|
||||||
<div class="show-code-item">{{ allVal[0].val }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[0].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio v-for="item in regionList" v-model="allVal[0].val" :key="item.deviceId" :name="item.name" :label="item.deviceId" @input="deviceChange(item)" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.deviceId }}
|
|
||||||
</el-radio>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="1">
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[1].val?allVal[1].val:"--" }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[1].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio :key="-1" v-model="allVal[1].val" @input="deviceChange" label="" style="line-height: 2rem">
|
|
||||||
不添加
|
|
||||||
</el-radio>
|
|
||||||
<el-radio v-for="item in regionList" v-model="allVal[1].val" @input="deviceChange(item)" :key="item.deviceId" :label="item.deviceId.substring(2)" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.deviceId.substring(2) }}
|
|
||||||
</el-radio>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="2">
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[2].val?allVal[2].val:"--" }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[2].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-radio :key="-1" label="" v-model="allVal[2].val" style="line-height: 2rem" @input="deviceChange">
|
|
||||||
不添加
|
|
||||||
</el-radio>
|
|
||||||
<el-radio v-for="item in regionList" v-model="allVal[2].val" @input="deviceChange(item)" :key="item.deviceId" :label="item.deviceId.substring(4)" style="line-height: 2rem">
|
|
||||||
{{ item.name }} - {{ item.deviceId.substring(4) }}
|
|
||||||
</el-radio>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane name="3">
|
|
||||||
请手动输入基层接入单位编码,两位数字
|
|
||||||
<div slot="label">
|
|
||||||
<div class="show-code-item">{{ allVal[3].val?allVal[3].val:"--" }}</div>
|
|
||||||
<div style="text-align: center">{{ allVal[3].meaning }}</div>
|
|
||||||
</div>
|
|
||||||
<el-input
|
|
||||||
type="text"
|
|
||||||
placeholder="请输入内容"
|
|
||||||
v-model="allVal[3].val"
|
|
||||||
maxlength="2"
|
|
||||||
:disabled="allVal[3].lock"
|
|
||||||
show-word-limit
|
|
||||||
@input="deviceChange"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
<el-form style="">
|
|
||||||
|
|
||||||
<el-form-item style="margin-top: 22px; margin-bottom: 0;">
|
|
||||||
<div style="float:right;">
|
|
||||||
<el-button type="primary" @click="handleOk">保存</el-button>
|
|
||||||
<el-button @click="closeModel">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {},
|
|
||||||
computed: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showVideoDialog: false,
|
|
||||||
activeKey: '0',
|
|
||||||
allVal: [
|
|
||||||
{
|
|
||||||
id: [1, 2],
|
|
||||||
meaning: '省级编码',
|
|
||||||
val: '11',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [3, 4],
|
|
||||||
meaning: '市级编码',
|
|
||||||
val: '',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [5, 6],
|
|
||||||
meaning: '区级编码',
|
|
||||||
val: '',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [7, 8],
|
|
||||||
meaning: '基层接入单位编码',
|
|
||||||
val: '',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
regionList: [],
|
|
||||||
deviceTypeList: [],
|
|
||||||
industryCodeTypeList: [],
|
|
||||||
networkIdentificationTypeList: [],
|
|
||||||
endCallBck: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openDialog: function (endCallBck, code, lockContent) {
|
|
||||||
this.showVideoDialog = true
|
|
||||||
this.activeKey= '0';
|
|
||||||
this.regionList = []
|
|
||||||
this.allVal = [
|
|
||||||
{
|
|
||||||
id: [1, 2],
|
|
||||||
meaning: '省级编码',
|
|
||||||
val: '11',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [3, 4],
|
|
||||||
meaning: '市级编码',
|
|
||||||
val: '',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [5, 6],
|
|
||||||
meaning: '区级编码',
|
|
||||||
val: '',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: [7, 8],
|
|
||||||
meaning: '基层接入单位编码',
|
|
||||||
val: '',
|
|
||||||
type: '中心编码',
|
|
||||||
lock: false,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
if (code) {
|
|
||||||
if (code.length >= 2) {
|
|
||||||
this.allVal[0].val = code.substring(0, 2)
|
|
||||||
this.activeKey = "0"
|
|
||||||
}
|
|
||||||
if (code.length >= 4) {
|
|
||||||
this.allVal[1].val = code.substring(2, 4)
|
|
||||||
this.activeKey = "1"
|
|
||||||
}
|
|
||||||
if (code.length >= 6) {
|
|
||||||
this.allVal[2].val = code.substring(4, 6)
|
|
||||||
this.activeKey = "2"
|
|
||||||
}
|
|
||||||
if (code.length === 8) {
|
|
||||||
this.allVal[3].val = code.substring(6, 8)
|
|
||||||
this.activeKey = "3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getRegionList()
|
|
||||||
this.endCallBck = endCallBck;
|
|
||||||
},
|
|
||||||
getRegionList: function() {
|
|
||||||
console.log("getRegionList")
|
|
||||||
if (this.activeKey === '0' ) {
|
|
||||||
this.queryChildList();
|
|
||||||
}else if (this.activeKey === '1' || this.activeKey === '2') {
|
|
||||||
let parent = ''
|
|
||||||
if (this.activeKey === '1') {
|
|
||||||
parent = this.allVal[0].val
|
|
||||||
}
|
|
||||||
if (this.activeKey === '2') {
|
|
||||||
if (this.allVal[1].val === ""){
|
|
||||||
parent = ""
|
|
||||||
} else {
|
|
||||||
parent = this.allVal[0].val + this.allVal[1].val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.activeKey !== '0' && parent === '') {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: "请先选择上级行政区划"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (parent !== "") {
|
|
||||||
this.queryChildList(parent);
|
|
||||||
}else {
|
|
||||||
this.regionList = []
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
queryChildList: function(parent){
|
|
||||||
console.log("queryChildList")
|
|
||||||
this.regionList = []
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: "/api/region/base/child/list",
|
|
||||||
params: {
|
|
||||||
parent: parent,
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.data.code === 0) {
|
|
||||||
this.regionList = res.data.data
|
|
||||||
} else {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data.msg
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error({
|
|
||||||
showClose: true,
|
|
||||||
message: error
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleOk: function (){
|
|
||||||
const code =
|
|
||||||
this.allVal[0].val +
|
|
||||||
this.allVal[1].val +
|
|
||||||
this.allVal[2].val +
|
|
||||||
this.allVal[3].val
|
|
||||||
console.log(code)
|
|
||||||
if (this.endCallBck) {
|
|
||||||
this.endCallBck(code)
|
|
||||||
}
|
|
||||||
this.showVideoDialog = false
|
|
||||||
},
|
|
||||||
closeModel: function (){
|
|
||||||
this.showVideoDialog = false
|
|
||||||
},
|
|
||||||
deviceChange: function (item){
|
|
||||||
console.log(item)
|
|
||||||
let code = this.allVal[0].val
|
|
||||||
if (this.allVal[1].val) {
|
|
||||||
code += this.allVal[1].val
|
|
||||||
if (this.allVal[2].val) {
|
|
||||||
code += this.allVal[2].val
|
|
||||||
if (this.allVal[3].val) {
|
|
||||||
code += this.allVal[3].val
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.allVal[3].val = ""
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.allVal[2].val = ""
|
|
||||||
this.allVal[3].val = ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.show-code-item {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 3rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||