Browse Source

八月一日提交

master
xiaohei 1 year ago
parent
commit
b69413a021
872 changed files with 741314 additions and 0 deletions
  1. +18
    -0
      .babelrc
  2. +9
    -0
      .editorconfig
  3. +10
    -0
      .postcssrc.js
  4. +41
    -0
      build/build.js
  5. +54
    -0
      build/check-versions.js
  6. BIN
      build/logo.png
  7. +102
    -0
      build/utils.js
  8. +22
    -0
      build/vue-loader.conf.js
  9. +106
    -0
      build/webpack.base.conf.js
  10. +96
    -0
      build/webpack.dev.conf.js
  11. +140
    -0
      build/webpack.prod.conf.js
  12. +7
    -0
      config/dev.env.js
  13. +60
    -0
      config/index.js
  14. +4
    -0
      config/prod.env.js
  15. +7
    -0
      config/test.env.js
  16. +1
    -0
      dist/index.html
  17. +12644
    -0
      dist/static/config.js
  18. +474
    -0
      dist/static/css/app.4235ce62fb9c140db2020a89f8ca28fc.css
  19. BIN
      dist/static/equipment/cardReader/IcCardReader.ocx
  20. +500
    -0
      dist/static/equipment/cardReader/ic01java.html
  21. +213
    -0
      dist/static/equipment/cardReader/index.vue
  22. BIN
      dist/static/equipment/cardReader/出现“Windows已经阻止此软件因为无法验证发行者”的解决办法.doc
  23. +3
    -0
      dist/static/equipment/cardReader/反注册控件.bat
  24. +3
    -0
      dist/static/equipment/cardReader/复制及注册IcCardReader控件win10_64.bat
  25. +3
    -0
      dist/static/equipment/cardReader/复制及注册IcCardReader控件win_32.bat
  26. +3
    -0
      dist/static/equipment/cardReader/请先根据自己的系统运行“复制及注册IcCardReader控件.bat”.txt
  27. BIN
      dist/static/equipment/mafp_serial.zip
  28. +6
    -0
      dist/static/equipment/mafp_serial/README.txt
  29. +6
    -0
      dist/static/equipment/mafp_serial/Readme.md
  30. +37
    -0
      dist/static/equipment/mafp_serial/fprintBackground.svg
  31. +290
    -0
      dist/static/equipment/mafp_serial/index.html
  32. +104
    -0
      dist/static/equipment/mafp_serial/index.js
  33. +4
    -0
      dist/static/equipment/mafp_serial/jquery.min.js
  34. +28
    -0
      dist/static/equipment/mafp_serial/jquery.toast.css
  35. +1
    -0
      dist/static/equipment/mafp_serial/jquery.toast.min.js
  36. +107
    -0
      dist/static/equipment/mafp_serial/mafp_sdk.js
  37. +29
    -0
      dist/static/equipment/mafp_serial/plugin/background.js
  38. +17
    -0
      dist/static/equipment/mafp_serial/plugin/event.js
  39. +894
    -0
      dist/static/equipment/mafp_serial/plugin/http.js
  40. BIN
      dist/static/equipment/mafp_serial/plugin/logo.png
  41. +27
    -0
      dist/static/equipment/mafp_serial/plugin/main.html
  42. +883
    -0
      dist/static/equipment/mafp_serial/plugin/main.js
  43. +30
    -0
      dist/static/equipment/mafp_serial/plugin/manifest.json
  44. +232
    -0
      dist/static/equipment/mafp_serial/plugin/sha1.js
  45. +32
    -0
      dist/static/equipment/mafp_serial/plugin/style.css
  46. BIN
      dist/static/equipment/mafp_serial/press.mp3
  47. BIN
      dist/static/equipment/mafp_serial/up.mp3
  48. BIN
      dist/static/equipment/mafp_serial/指纹采集器软件通信流程.doc
  49. +2
    -0
      dist/static/favicon.ico
  50. BIN
      dist/static/fonts/element-icons.535877f.woff
  51. BIN
      dist/static/fonts/element-icons.732389d.ttf
  52. BIN
      dist/static/fonts/iconfont.5dd52cc.woff
  53. BIN
      dist/static/fonts/iconfont.7e75b66.woff2
  54. BIN
      dist/static/fonts/iconfont.acc85de.ttf
  55. +3
    -0
      dist/static/global.json
  56. BIN
      dist/static/img/alert.f2fea34.png
  57. BIN
      dist/static/img/beijingtu01.f8608d7.png
  58. BIN
      dist/static/img/beijingtu24.b50f73c.jpg
  59. BIN
      dist/static/img/bgBox.719f731.png
  60. BIN
      dist/static/img/bgfixed.15a99f0.jpg
  61. BIN
      dist/static/img/dd.c03303f.gif
  62. BIN
      dist/static/img/logo1.38f1073.png
  63. BIN
      dist/static/img/logo2.0754d14.png
  64. BIN
      dist/static/img/mapbg.2f52c08.png
  65. BIN
      dist/static/img/no-rooms.dfc2fbf1.dfc2fbf.png
  66. BIN
      dist/static/img/pageBg.f9f9dcd.png
  67. BIN
      dist/static/img/product1.94f4481.png
  68. BIN
      dist/static/img/product10.be88006.png
  69. BIN
      dist/static/img/product2.6175ede.png
  70. BIN
      dist/static/img/product3.0ba44dd.png
  71. BIN
      dist/static/img/product4.ed5b542.png
  72. BIN
      dist/static/img/product5.88c5ef6.png
  73. BIN
      dist/static/img/product6.23e10b2.png
  74. BIN
      dist/static/img/product7.de38d89.png
  75. BIN
      dist/static/img/product8.4d433d8.png
  76. BIN
      dist/static/img/product9.100a788.png
  77. BIN
      dist/static/img/red.6dbe9e9.gif
  78. BIN
      dist/static/img/topbg.820ebf9.png
  79. BIN
      dist/static/img/yellow.762c207.gif
  80. +10274
    -0
      dist/static/js/0.2aa86481213c7a5ffc5e.js
  81. +3170
    -0
      dist/static/js/1.6509e5523c4acd63d661.js
  82. +622
    -0
      dist/static/js/10.b76c738e1897991df5e1.js
  83. +32
    -0
      dist/static/js/100.b06af9d3849781624c1b.js
  84. +58
    -0
      dist/static/js/101.752ae74e0b5776b02cef.js
  85. +32
    -0
      dist/static/js/102.bd2b09fcdb0fc921ce0f.js
  86. +32
    -0
      dist/static/js/103.4620884103b690a2d101.js
  87. +58
    -0
      dist/static/js/104.0098f9c85ecc7e2a06bb.js
  88. +58
    -0
      dist/static/js/105.35dcf6f8b99bd44a9ce4.js
  89. +58
    -0
      dist/static/js/106.3da7311810b8afa9dda6.js
  90. +32
    -0
      dist/static/js/107.065b65fa197e1140e1a6.js
  91. +58
    -0
      dist/static/js/108.132f68c23ee6697fb922.js
  92. +58
    -0
      dist/static/js/109.cc20db0661a2380e2ce9.js
  93. +583
    -0
      dist/static/js/11.f8a88a805a4cc2ebdadc.js
  94. +58
    -0
      dist/static/js/110.cc9abf3baf77be63bd8d.js
  95. +58
    -0
      dist/static/js/111.26a887a7ac9349204d4e.js
  96. +58
    -0
      dist/static/js/112.074ea4fa9a376f967638.js
  97. +58
    -0
      dist/static/js/113.98971d8a44acdf4e1776.js
  98. +58
    -0
      dist/static/js/114.16708a12a3468bd674f6.js
  99. +58
    -0
      dist/static/js/115.f68058217804647ef908.js
  100. +58
    -0
      dist/static/js/116.84bc60701df5f739bd33.js

+ 18
- 0
.babelrc View File

@ -0,0 +1,18 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}

+ 9
- 0
.editorconfig View File

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

+ 10
- 0
.postcssrc.js View File

@ -0,0 +1,10 @@
// 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": {}
}
}

+ 41
- 0
build/build.js View File

@ -0,0 +1,41 @@
'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'
))
})
})

+ 54
- 0
build/check-versions.js View File

@ -0,0 +1,54 @@
'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)
}
}

BIN
build/logo.png View File

Before After
Width: 32  |  Height: 32  |  Size: 1.6 KiB

+ 102
- 0
build/utils.js View File

@ -0,0 +1,102 @@
'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',
publicPath:'../../'
})
} 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')
})
}
}

+ 22
- 0
build/vue-loader.conf.js View File

@ -0,0 +1,22 @@
'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'
}
}

+ 106
- 0
build/webpack.base.conf.js View File

@ -0,0 +1,106 @@
'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'
app: ['babel-polyfill','./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'),
'jquery': path.resolve(__dirname, '../node_modules/jquery/src/jquery')
}
},
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: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/@jiaminghi/data-view/lib')]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'),resolve('test'),resolve('node_modules/element-ui/src'),resolve('/node_modules/element-ui/packages')
]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'),resolve('test'),resolve('node_modules/element-ui/src'),resolve('/node_modules/vue-baidu-map/components/base')
]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'),resolve('test'),resolve('node_modules/js-base64')
]
},
{
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'
}
}

+ 96
- 0
build/webpack.dev.conf.js View File

@ -0,0 +1,96 @@
'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 HOST = process.env.HOST
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') },
],
},
https:false,
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: 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: ['.*']
}
])
]
})
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)
}
})
})

+ 140
- 0
build/webpack.prod.conf.js View File

@ -0,0 +1,140 @@
'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 env = process.env.NODE_ENV === 'testing'
? require('../config/test.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: {
publicPath: '/',
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
}),
// 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: process.env.NODE_ENV === 'testing'
? 'index.html'
: 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: ['.*']
}
])
]
})
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

+ 7
- 0
config/dev.env.js View File

@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

+ 60
- 0
config/index.js View File

@ -0,0 +1,60 @@
'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: {
'/api': {
target: 'http://apartmentcloud.xiaozhisz.cn/',
// target: 'http://test.zhiweisz.cn/',
// target: 'http://192.168.1.26:8600/',
changeOrigin: true, //是否跨域
pathRewrite: {
//重写路径
'^/api': '' //代理路径
}
}
},
configureWebpack: {
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
vue$: 'vue/dist/vue.esm.js',
'@': path.join(__dirname, '/', 'src')
}
}
},
host: '192.168.1.20',
port: 8082,
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false,
devtool: 'cheap-module-eval-source-map',
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: false,
devtool: '#source-map',
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report
}
}

+ 4
- 0
config/prod.env.js View File

@ -0,0 +1,4 @@
'use strict'
module.exports = {
NODE_ENV: '"production"'
}

+ 7
- 0
config/test.env.js View File

@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const devEnv = require('./dev.env')
module.exports = merge(devEnv, {
NODE_ENV: '"testing"'
})

+ 1
- 0
dist/index.html View File

@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta http-equiv=Content-Language><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta http-equiv=Content-Type content="text/html;charset=utf-8"><title>智慧公寓管理系统</title><link href=/static/css/app.4235ce62fb9c140db2020a89f8ca28fc.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.18ec6b5593d846b34fd0.js></script><script type=text/javascript src=/static/js/vendor.9c8489941f3a5aa906bb.js></script><script type=text/javascript src=/static/js/app.509b36048f5247e714bd.js></script></body></html>

+ 12644
- 0
dist/static/config.js
File diff suppressed because it is too large
View File


+ 474
- 0
dist/static/css/app.4235ce62fb9c140db2020a89f8ca28fc.css
File diff suppressed because it is too large
View File


BIN
dist/static/equipment/cardReader/IcCardReader.ocx View File


+ 500
- 0
dist/static/equipment/cardReader/ic01java.html View File

@ -0,0 +1,500 @@
<html>
<head>
<!-- <meta http-equiv="Content-Language" content="zh-cn">
<meta name="GENERATOR" content="Microsoft FrontPage 6.0">
<meta name="ProgId" content="FrontPage.Editor.Document"> -->
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>USB IC 卡读卡器控件调用例程 V1.0</title>
<script language="javascript">
var strls = "";
var errorno = "";
//控制字定义,控制字指定,控制字的含义请查看本公司网站提供的动态库说明
//javascript无法自定义常量, 你可以使用变量代替
var BLOCK0_EN = 0x01;//读第一块的(16个字节)
var BLOCK1_EN = 0x02;//读第二块的(16个字节)
var BLOCK2_EN = 0x04;//读第三块的(16个字节)
var NEEDSERIAL = 0x08;//仅读指定序列号的卡
var EXTERNKEY = 0x10;//用明码认证密码,产品开发完成后,建议把密码放到设备的只写区,然后用该区的密码后台认证,这样谁都不知道密码是多少,需要这方面支持请联系
var NEEDHALT = 0x20;//读/写完卡后立即休眠该卡,相当于这张卡不在感应区。要相重新操作该卡必要拿开卡再放上去
var myctrlword = 0;
var myareano = 0;
var authmode = 0;
var mypiccserial = "";
var mypicckey = "";
var piccdata0_2 = "";
var mypicckey_old = "";//旧密码
var mypicckey_new = "";//新密码
function readcard()
{
//指定控制字
myctrlword=BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;
//指定区号
myareano = 8; //指定为第8区
//批定密码模式
authmode = 1; //大于0表示用A密码认证,推荐用A密码认证
//指定序列号,未知卡序列号时可指定为8个0
mypiccserial="00000000";
//指定密码,以下密码为厂家出厂密码
mypicckey = "ffffffffffff";
strls=IcCardReader.piccreadex(myctrlword, mypiccserial,myareano,authmode,mypicckey);
errorno = strls.substr(0,4);
if(errorno == "ER00"){
beep()
}
switch(errorno)
{
case "ER08":
alert("寻不到卡");
break;
case "ER09":
alert("寻不到卡");
break;
case "ER10":
alert("寻不到卡");
break;
case "ER11":
CardIDShower.value = "密码认证错误\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("密码认证错误");
break;
case "ER12":
CardIDShower.value = "密码认证错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("密码认证错误");
break;
case "ER13":
CardIDShower.value = "读卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("读卡错误");
break;
case "ER14":
CardIDShower.value = "写卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("写卡错误");
break;
case "ER21":
alert("没找到动态库");
break;
case "ER22":
alert("动态库或驱动程序异常");
break;
case "ER23":
alert("读卡器未插上或动态库或驱动程序异常");
break;
case "ER24":
alert("操作超时,一般是动态库没有反应");
break;
case "ER25":
alert("发送字数不够");
break;
case "ER26":
alert("发送的CRC错");
break;
case "ER27":
alert("接收的字数不够");
break;
case "ER28":
alert("接收的CRC错");
break;
case "ER29":
alert("函数输入参数格式错误,请仔细查看" );
break;
default :
//读卡成功,其中ER00表示完全成功,ER01表示完全没读到卡数据,ER02表示仅读该卡的第一块成功,,ER02表示仅读该卡的第一二块成功,这是刷卡太快原因
CardIDShower.value = "读卡成功" + "\r\n";
// CardIDShower.value = CardIDShower.value + strls + "\r\n";
// CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
// CardIDShower.value = CardIDShower.value + "该区第一块十六进制数据为:" + strls.substr(14,32) + "\r\n";
// CardIDShower.value = CardIDShower.value + "该区第二块十六进制数据为:" + strls.substr(46,32) + "\r\n";
// CardIDShower.value = CardIDShower.value + "该区第三块十六进制数据为:" + strls.substr(78,32) + "\r\n";
break;
}
}
function writecard()
{
//指定控制字
myctrlword=BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;
//指定区号
myareano = 8; //指定为第8区
//批定密码模式
authmode = 1; //大于0表示用A密码认证,推荐用A密码认证
//指定序列号,未知卡序列号时可指定为8个0
mypiccserial="00000000";
//指定密码,以下密码为厂家出厂密码
mypicckey = "ffffffffffff";
//指定写卡内容,长度为48个字节,其中每个字节以两个字符表示为十六进制数
piccdata0_2 = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F";
strls=IcCardReader.piccwriteex(myctrlword, mypiccserial,myareano,authmode,mypicckey,piccdata0_2);
errorno = strls.substr(0,4);
switch(errorno)
{
case "ER08":
alert("寻不到卡");
break;
case "ER09":
alert("寻不到卡");
break;
case "ER10":
alert("寻不到卡");
break;
case "ER11":
CardIDShower.value = "密码认证错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("密码认证错误");
break;
case "ER12":
CardIDShower.value = "密码认证错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("密码认证错误");
break;
case "ER13":
CardIDShower.value = "读卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("读卡错误");
break;
case "ER14":
CardIDShower.value = "写卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
alert("写卡错误");
break;
case "ER21":
alert("没找到动态库");
break;
case "ER22":
alert("动态库或驱动程序异常");
break;
case "ER23":
alert("读卡器未插上或动态库或驱动程序异常");
break;
case "ER24":
alert("操作超时,一般是动态库没有反应");
break;
case "ER25":
alert("发送字数不够");
break;
case "ER26":
alert("发送的CRC错");
break;
case "ER27":
alert("接收的字数不够");
break;
case "ER28":
alert("接收的CRC错");
break;
case "ER29":
alert("函数输入参数格式错误,请仔细查看");
break;
default ://写卡成功,其中ER00表示完全成功,ER01表示完全没写到卡数据,ER02表示仅写该卡的第一块成功,,ER02表示仅写该卡的第一二块成功,这是刷卡太快原因
CardIDShower.value = "写卡成功" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5,8) + "\r\n";
break;
}
}
function writecarduid() {
//指定控制字
myctrlword = BLOCK0_EN;
//批定密码模式
authmode = 1; //大于0表示用A密码认证,推荐用A密码认证
//指定序列号,未知卡序列号时可指定为8个0
mypiccserial = "12345678";
//指定密码,以下密码为厂家出厂密码
mypicckey = "ffffffffffff";
//指定写卡内容,长度为48个字节,其中每个字节以两个字符表示为十六进制数
piccdata0 = "12345678000102030405060708090A0B0";
strls = IcCardReader.piccwriteserial(myctrlword, mypiccserial,authmode, mypicckey, piccdata0);
errorno = strls.substr(0, 4);
switch (errorno) {
case "ER08":
alert("寻不到卡");
break;
case "ER09":
alert("寻不到卡");
break;
case "ER10":
alert("寻不到卡");
break;
case "ER11":
CardIDShower.value = "密码认证错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5, 8) + "\r\n";
alert("密码认证错误");
break;
case "ER12":
CardIDShower.value = "密码认证错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5, 8) + "\r\n";
alert("密码认证错误");
break;
case "ER13":
CardIDShower.value = "读卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5, 8) + "\r\n";
alert("读卡错误");
break;
case "ER14":
CardIDShower.value = "写卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5, 8) + "\r\n";
alert("写卡错误");
break;
case "ER21":
alert("没找到动态库");
break;
case "ER22":
alert("动态库或驱动程序异常");
break;
case "ER23":
alert("读卡器未插上或动态库或驱动程序异常");
break;
case "ER24":
alert("操作超时,一般是动态库没有反应");
break;
case "ER25":
alert("发送字数不够");
break;
case "ER26":
alert("发送的CRC错");
break;
case "ER27":
alert("接收的字数不够");
break;
case "ER28":
alert("接收的CRC错");
break;
case "ER29":
alert("函数输入参数格式错误,请仔细查看");
break;
default://写卡成功,其中ER00表示完全成功,ER01表示完全没写到卡数据,ER02表示仅写该卡的第一块成功,,ER02表示仅写该卡的第一二块成功,这是刷卡太快原因
CardIDShower.value = "写UID号成功" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value = CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value = CardIDShower.value + "卡十六进制序列号为:" + strls.substr(5, 8) + "\r\n";
break;
}
}
function changecardkeyex()
{
//指定控制字
myctrlword= EXTERNKEY;
//指定区号
myareano = 8; //指定为第8区
//批定密码模式
authmode = 1; //大于0表示用A密码认证,推荐用A密码认证
//指定序列号,未知卡序列号时可指定为8个0
mypiccserial="00000000";
//旧密码
mypicckey_old = "ffffffffffff";
//新密码
mypicckey_new = "ffffffffffffFF078069ffffffffffff";//其中最前面的ffffffffffff为A密码,中间的FF078069为访问控制位,最后面的ffffffffffff为B密码
strls=IcCardReader.piccchangesinglekeyex(myctrlword, mypiccserial,myareano,authmode,mypicckey_old,mypicckey_new)
errorno = strls.substr(0,4);
if(errorno == "ER00")
{
CardIDShower.value = CardIDShower.value + "修改密码成功,卡序列为:" + strls.substr(strls.length - 8,8) + "\r\n";
}
else if(errorno == "ER08")
{
alert("寻不到卡");
}
else
{
CardIDShower.value = CardIDShower.value + "修改密码:错误:" + errorno + "\r\n";
}
}
function getdevicenumber()
{
strls=IcCardReader.pcdgetdevicenumber();
errorno = strls.substr(0,4);
if(errorno == "ER00")
{
CardIDShower.value = CardIDShower.value + "设备硬件号为:" + strls.substr(strls.length - 8,8) + "\r\n";
}
}
function beep()
{
IcCardReader.pcdbeep(100);//100表示响100毫秒
}
function clears1()
{
//alert("abc");
CardIDShower.value = "";
}
window.onerror=function()
{
alert("不好意思,出错了!");
return true;//屏蔽系统事件
}
</script>
<object classid="clsid:05782014-9FF7-468C-BE96-8EDC73084202" id="IcCardReader" viewastext
width="0" height="0">
</object>
</head>
<body>
<table border="0" style="border-collapse: collapse" width="200" height="100">
<tr>
<td width="160">
<textarea rows="2" cols="40" id="CardIDShower" name="S1"></textarea>
</td>
</tr>
<tr>
<td width="160">
<!-- <input type="button" value="读卡" onclick="javascript:readcard()" /> -->
<button onclick="javascript:readcard()">读卡</button>
</td>
</tr>
<!-- <tr>
<td width="160">
<input type="button" value=" 写 卡 " onclick="javascript:writecard()" />
</td>
</tr>
<tr>
<td width="160">
<input type="button" value="蜂鸣器响" onclick="javascript:beep()" />
</td>
</tr>
<tr>
<td width="160">
<input type="button" value="更改卡密码" onclick="javascript:changecardkeyex()" />
</td>
</tr>
<tr>
<td width="160">
<input type="button" value="读取读写器硬件号" onclick="javascript:getdevicenumber()" />
</td>
</tr>
<tr>
<td width="160">
<input type="button" value="写卡UID号为12345678" onclick="javascript:writecarduid()" />
</td>
</tr>
<tr>
<td width="160">
<input type="button" value="清空提示" onclick="javascript:clears1()" />
</td>
</tr> -->
</table>
<!-- <p>
<font style="font-size: 9pt">提示:</font></p>
<p>
<font style="font-size: 9pt">&nbsp;&nbsp;&nbsp; 1、运行本例程前,需先注册 IcCardReader 控件,注册方法为:“开始”-&gt;“运行”-&gt;输入“regsvr32 ***\IcCardReader.ocx”-&gt;“确定”。其中“***”为控件所在路径。</font></p>
<p>
<font style="font-size: 9pt">&nbsp;&nbsp;&nbsp; 2、在IE的Internet 属性设定,让浏览器允许运行 ActiveX 控件。</font></p>
<p>
<font style="font-size: 9pt">&nbsp;&nbsp;&nbsp; 3、如果是在服务器端运行本网页,还需在IE的Internet 属性中设定,将服务器网址设为可信站点,否则网页无权运行本地控件。</font></p> -->
</body>
</html>

+ 213
- 0
dist/static/equipment/cardReader/index.vue View File

@ -0,0 +1,213 @@
<template>
<div>
<!-- <object
classid="clsid:05782014-9FF7-468C-BE96-8EDC73084202"
id="IcCardReader"
viewastext
width="0"
height="0"
></object> -->
<table
border="0"
style="border-collapse: collapse"
width="200"
height="100"
>
<tr>
<td width="160">
<textarea rows="2" cols="40" id="CardIDShower" name="S1"></textarea>
</td>
</tr>
<tr>
<td width="160">
<input
type="button"
value=" 读 卡 "
@click="readcard()"
/>
</td>
</tr>
</table>
</div>
</template>
<script>
var strls = "";
var errorno = "";
//,,
//javascript, 使
var BLOCK0_EN = 0x01;//(16)
var BLOCK1_EN = 0x02;//(16)
var BLOCK2_EN = 0x04;//(16)
var NEEDSERIAL = 0x08;//
var EXTERNKEY = 0x10;//,
var NEEDHALT = 0x20;///
var myctrlword = 0;
var myareano = 0;
var authmode = 0;
var mypiccserial = "";
var mypicckey = "";
var piccdata0_2 = "";
var mypicckey_old = "";//
var mypicckey_new = "";//
export default {
name: "index",
data() {
return {};
},
methods: {
readcard() {
//
myctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;
//
myareano = 8; //8
//
authmode = 1; //0AA
//80
mypiccserial = "00000000";
//
mypicckey = "ffffffffffff";
var CardIDShower = document.getElementById('CardIDShower')
strls = window.IcCardReader.piccreadex(
myctrlword,
mypiccserial,
myareano,
authmode,
mypicckey
);
errorno = strls.substr(0, 4);
if (errorno == "ER00") {
this.beep();
}
switch (errorno) {
case "ER08":
alert("寻不到卡");
break;
case "ER09":
alert("寻不到卡");
break;
case "ER10":
alert("寻不到卡");
break;
case "ER11":
CardIDShower.value = "密码认证错误\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value =
CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value =
CardIDShower.value +
"卡十六进制序列号为:" +
strls.substr(5, 8) +
"\r\n";
alert("密码认证错误");
break;
case "ER12":
CardIDShower.value = "密码认证错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value =
CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value =
CardIDShower.value +
"卡十六进制序列号为:" +
strls.substr(5, 8) +
"\r\n";
alert("密码认证错误");
break;
case "ER13":
CardIDShower.value = "读卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value =
CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value =
CardIDShower.value +
"卡十六进制序列号为:" +
strls.substr(5, 8) +
"\r\n";
alert("读卡错误");
break;
case "ER14":
CardIDShower.value = "写卡错误" + "\r\n";
CardIDShower.value = CardIDShower.value + strls + "\r\n";
CardIDShower.value =
CardIDShower.value + "其中错误号为:" + errorno + "\r\n";
CardIDShower.value =
CardIDShower.value +
"卡十六进制序列号为:" +
strls.substr(5, 8) +
"\r\n";
alert("写卡错误");
break;
case "ER21":
alert("没找到动态库");
break;
case "ER22":
alert("动态库或驱动程序异常");
break;
case "ER23":
alert("读卡器未插上或动态库或驱动程序异常");
break;
case "ER24":
alert("操作超时,一般是动态库没有反应");
break;
case "ER25":
alert("发送字数不够");
break;
case "ER26":
alert("发送的CRC错");
break;
case "ER27":
alert("接收的字数不够");
break;
case "ER28":
alert("接收的CRC错");
break;
case "ER29":
alert("函数输入参数格式错误,请仔细查看");
break;
default:
//,ER00,ER01ER02,ER02
CardIDShower.value = "读卡成功" + "\r\n";
// CardIDShower.value = CardIDShower.value + strls + "\r\n";
// CardIDShower.value = CardIDShower.value + "" + errorno + "\r\n";
CardIDShower.value =
CardIDShower.value +
"卡十六进制序列号为:" +
strls.substr(5, 8) +
"\r\n";
// CardIDShower.value = CardIDShower.value + "" + strls.substr(14,32) + "\r\n";
// CardIDShower.value = CardIDShower.value + "" + strls.substr(46,32) + "\r\n";
// CardIDShower.value = CardIDShower.value + "" + strls.substr(78,32) + "\r\n";
break;
}
},
beep() {
IcCardReader.pcdbeep(100); //100100
},
clears1() {
//alert("abc");
CardIDShower.value = "";
},
},
};
</script>
<style>
</style>

BIN
dist/static/equipment/cardReader/出现“Windows已经阻止此软件因为无法验证发行者”的解决办法.doc View File


+ 3
- 0
dist/static/equipment/cardReader/反注册控件.bat View File

@ -0,0 +1,3 @@
%Windir%\SysWOW64\regsvr32 %Windir%\System32\IcCardReader.ocx -u
%Windir%\SysWOW64\regsvr32 %Windir%\SysWOW64\IcCardReader.ocx -u
pause

+ 3
- 0
dist/static/equipment/cardReader/复制及注册IcCardReader控件win10_64.bat View File

@ -0,0 +1,3 @@
Copy %~dp0\IcCardReader.ocx %Windir%\SysWOW64\
%Windir%\SysWOW64\regsvr32 %Windir%\SysWOW64\IcCardReader.ocx
pause

+ 3
- 0
dist/static/equipment/cardReader/复制及注册IcCardReader控件win_32.bat View File

@ -0,0 +1,3 @@
Copy %~dp0\IcCardReader.ocx %Windir%\System32\
%Windir%\SysWOW64\regsvr32 %Windir%\System32\IcCardReader.ocx
pause

+ 3
- 0
dist/static/equipment/cardReader/请先根据自己的系统运行“复制及注册IcCardReader控件.bat”.txt View File

@ -0,0 +1,3 @@
如果你的系统是32位的x86系统,请运行 复制及注册IcCardReader控件win_32.bat
或者
如果你的系统是64位的x64系统,请运行 复制及注册IcCardReader控件win10_64.bat

BIN
dist/static/equipment/mafp_serial.zip View File


+ 6
- 0
dist/static/equipment/mafp_serial/README.txt View File

@ -0,0 +1,6 @@
1. 安装chrome最新版本
2. chrome 访问 chrome://extensions/
3. 打开开发者模式
4. 加载已解压的扩展程序 选中mafp_serial\plugin文件夹
5. chrome 访问 chrome://apps/ 打开MAFP Serial, 等待出现日志 found valid device XXX
6. chrome 打开index.html 进行注册操作

+ 6
- 0
dist/static/equipment/mafp_serial/Readme.md View File

@ -0,0 +1,6 @@
1. 安装chrome最新版本
2. chrome 访问 chrome://extensions/
3. 打开开发者模式
4. 加载已解压的扩展程序 选中mafp_serial\plugin文件夹
5. chrome 访问 chrome://apps/ 打开MAFP Serial, 等待出现日志 found valid device XXX
6. chrome 打开index.html 进行注册操作

+ 37
- 0
dist/static/equipment/mafp_serial/fprintBackground.svg View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 180 320" style="enable-background:new 0 0 180 320;" xml:space="preserve">
<style type="text/css">
.demo__background-path {
fill: none;
stroke: #aaa;
stroke-linecap: round;
stroke-width: 2px;
}
</style>
<path class="demo__background-path" d="M46.1,214.3c0,0-4.7-15.6,4.1-33.3"/>
<path class="demo__background-path" d="M53.5,176.8c0,0,18.2-30.3,57.5-13.7"/>
<path class="demo__background-path" d="M115.8,166.5c0,0,19.1,8.7,19.6,38.4"/>
<path class="demo__background-path" d="M47.3,221c0,0,3.1-2.1,4.1-4.6s-5.7-20.2,7-36.7c8.5-11,22.2-19,37.9-15.3"/>
<path class="demo__background-path" d="M102.2,165.4c10.2,2.7,19.5,10.4,23.5,20.2c6.2,15.2,4.9,27.1,4.1,39.4"/>
<path class="demo__background-path" d="M51.1,226.5c3.3-2.7,5.1-6.3,5.7-10.5c0.5-4-0.3-7.7-0.3-11.7"/>
<path class="demo__background-path" d="M129.3,200.1"/>
<path class="demo__background-path" d="M56.3,197.9c3.1-16.8,17.6-29.9,35.1-28.8c17.7,1.1,30.9,14.9,32.8,32.2"/>
<path class="demo__background-path" d="M124.2,207.9c0.5,9.3,0.5,18.7-2.1,27.7"/>
<path class="demo__background-path" d="M54.2,231.1c2.1-2.6,4.6-5.1,6.3-8c4.2-6.8,0.9-14.8,1.5-22.3c0.5-7.1,3.4-16.3,10.4-19.7"/>
<path class="demo__background-path" d="M77.9,178.2c9.3-5.1,22.9-4.7,30.5,3.3"/>
<path class="demo__background-path" d="M113,186.5c0,0,13.6,18.9,1,54.8"/>
<path class="demo__background-path" d="M57.3,235.2c0,0,5.7-3.8,9-12.3"/>
<path class="demo__background-path" d="M111.7,231.5c0,0-4.1,11.5-5.7,13.6"/>
<path class="demo__background-path" d="M61.8,239.4c9.3-8.4,12.7-19.7,11.8-31.9c-0.9-12.7,3.8-20.6,18.5-21.2"/>
<path class="demo__background-path" d="M97.3,188.1c8.4,2.7,11,13,11.3,20.8c0.4,11.8-2.5,23.7-7.9,34.1c-0.1,0.1-0.1,0.2-0.2,0.3
c-0.4,0.8-0.8,1.5-1.2,2.3c-0.5,0.8-1,1.7-1.5,2.5"/>
<path class="demo__background-path" d="M66.2,242.5c0,0,15.3-11.1,13.6-34.9"/>
<path class="demo__background-path" d="M78.7,202.5c1.5-4.6,3.8-9.4,8.9-10.6c13.5-3.2,15.7,13.3,14.6,22.1"/>
<path class="demo__background-path" d="M102.2,219.7c0,0-1.7,15.6-10.5,28.4"/>
<path class="demo__background-path" d="M72,244.9c0,0,8.8-9.9,9.9-15.7"/>
<path class="demo__background-path" d="M84.5,223c0.3-2.6,0.5-5.2,0.7-7.8c0.1-2.1,0.2-4.6-0.1-6.8c-0.3-2.2-1.1-4.3-0.9-6.5c0.5-4.4,7.2-6.9,10.1-3.1c1.7,2.2,1.7,5.3,1.9,7.9c0.4,3.8,0.3,7.6,0,11.4c-1,10.8-5.4,21-11.5,29.9"/>
<path class="demo__background-path" d="M90,201.2c0,0,4.6,28.1-11.4,45.2"/>
<path class="demo__background-path" d="M67.3,219C65,188.1,78,180.1,92.7,180.3c18.3,2,23.7,18.3,20,46.7"/>
</svg>

+ 290
- 0
dist/static/equipment/mafp_serial/index.html View File

@ -0,0 +1,290 @@
<!DOCTYPE html>
<head>
<link type="text/css" rel="stylesheet" href="jquery.toast.css">
<style type="text/css">
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.log-text {
font-size: 14px;
padding: 10px 0 0 10px;
color: #666;
text-align: center;
margin-bottom: 30px;
}
.fprint-container {
width: 300px;
height: 252px;
margin: 0 auto;
position: relative;
}
.demo__fprint {
width: 300px;
height: 260px;
overflow: visible;
display: block;
}
.demo__fprint_bg {
position: absolute;
top: 0;
left: 0;
width: 297px;
height: 260px;
z-index: -1;
background: url(./fprintBackground.svg) no-repeat;
background-position: 78px -260px;
background-size: auto;
/* background-position: -100px 0; */
/* background-size: cover; */
}
.demo__fprint_bg img{position: absolute;width: 147px;top: 50%;
left: 75px;
opacity: .9;
transform: translateY(-50%);}
.demo__fprint_bg.leave {
opacity: 0.5;
}
.demo__fprint_bg.down {
opacity: 1;
}
.demo__fprint-path {
stroke-width: 2.5px;
stroke-linecap: round;
fill: none;
stroke: white;
visibility: hidden;
transition: opacity 0.5s ease;
will-change: stroke-dashoffset, stroke-dasharray;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.demo__fprint-path--pinkish {
stroke: #a94a8c;
}
.demo__fprint-path--purplish {
stroke: #8742cc;
}
.demo__fprint-path#demo__elastic-path {
will-change: opacity;
opacity: 1;
}
.demo__hidden-path {
display: none;
}
.demo__ending-path {
fill: none;
stroke-width: 2.5px;
stroke-dasharray: 60 1000;
stroke-dashoffset: 61;
stroke-linecap: round;
will-change: stroke-dashoffset, stroke-dasharray, opacity;
-webkit-transform: translateZ(0);
transform: translateZ(0);
transition: stroke-dashoffset 1s ease, stroke-dasharray 0.5s linear, opacity 0.75s ease;
}
.demo__ending-path--pinkish {
stroke: #a94a8c;
}
.demo__ending-path--purplish {
stroke: #8742cc;
}
.buttons {
width: 500px;
display: flex;
margin: auto;
align-items: center;
justify-content: center;
}
#enroll-btn {
width: 140px;
}
</style>
</head>
<body>
<div class="fprint-container">
<div class="demo__fprint_bg leave"><img src="./fprintBackground.svg" alt=""></div>
<svg class="demo__fprint" viewBox="0 0 180 320">
<defs>
<linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#8742cc"></stop>
<stop offset="100%" stop-color="#a94a8c"></stop>
</linearGradient>
</defs>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--pinkish" d="M46.1,214.3c0,0-4.7-15.6,4.1-33.3" style="stroke-dasharray: 34.235, 36.235; stroke-dashoffset: 35.235px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--purplish" d="M53.5,176.8c0,0,18.2-30.3,57.5-13.7" style="stroke-dasharray: 64.5064, 66.5064; stroke-dashoffset: 65.5064px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--pinkish" d="M115.8,166.5c0,0,19.1,8.7,19.6,38.4" style="stroke-dasharray: 45.1842, 47.1842; stroke-dashoffset: 46.1842px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--pinkish" d="M47.3,221c0,0,3.1-2.1,4.1-4.6s-5.7-20.2,7-36.7c8.5-11,22.2-19,37.9-15.3" style="stroke-dasharray: 88.0272, 90.0272; stroke-dashoffset: 89.0272px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--pinkish" d="M102.2,165.4c10.2,2.7,19.5,10.4,23.5,20.2c6.2,15.2,4.9,27.1,4.1,39.4" style="stroke-dasharray: 72.1106, 74.1106; stroke-dashoffset: 73.1106px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--purplish" d="M51.1,226.5c3.3-2.7,5.1-6.3,5.7-10.5c0.5-4-0.3-7.7-0.3-11.7" style="stroke-dasharray: 23.9625, 25.9625; stroke-dashoffset: 24.9625px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--purplish" d="M56.3,197.9c3.1-16.8,17.6-29.9,35.1-28.8c17.7,1.1,30.9,14.9,32.8,32.2" style="stroke-dasharray: 99.6723, 101.672; stroke-dashoffset: 100.672px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--purplish" d="M124.2,207.9c0.5,9.3,0.5,18.7-2.1,27.7" style="stroke-dasharray: 27.9142, 29.9142; stroke-dashoffset: 28.9142px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--pinkish" d="M54.2,231.1c2.1-2.6,4.6-5.1,6.3-8c4.2-6.8,0.9-14.8,1.5-22.3c0.5-7.1,3.4-16.3,10.4-19.7" style="stroke-dasharray: 56.1771, 58.1771; stroke-dashoffset: 57.1771px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--purplish" d="M77.9,178.2c9.3-5.1,22.9-4.7,30.5,3.3" style="stroke-dasharray: 32.824, 34.824; stroke-dashoffset: 33.824px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--purplish" d="M113,186.5c0,0,13.6,18.9,1,54.8" style="stroke-dasharray: 56.5353, 58.5353; stroke-dashoffset: 57.5353px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--pinkish" d="M57.3,235.2c0,0,5.7-3.8,9-12.3" style="stroke-dasharray: 15.4365, 17.4365; stroke-dashoffset: 16.4365px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--pinkish" d="M111.7,231.5c0,0-4.1,11.5-5.7,13.6" style="stroke-dasharray: 14.7687, 16.7687; stroke-dashoffset: 15.7687px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--purplish" d="M61.8,239.4c9.3-8.4,12.7-19.7,11.8-31.9c-0.9-12.7,3.8-20.6,18.5-21.2" style="stroke-dasharray: 67.9598, 69.9598; stroke-dashoffset: 68.9598px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--pinkish" d="M97.3,188.1c8.4,2.7,11,13,11.3,20.8c0.4,11.8-2.5,23.7-7.9,34.1c-0.1,0.1-0.1,0.2-0.2,0.3
c-0.4,0.8-0.8,1.5-1.2,2.3c-0.5,0.8-1,1.7-1.5,2.5" style="stroke-dasharray: 66.4444, 68.4444; stroke-dashoffset: 67.4444px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--purplish" d="M66.2,242.5c0,0,15.3-11.1,13.6-34.9" style="stroke-dasharray: 38.917, 40.917; stroke-dashoffset: 39.917px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--pinkish" d="M78.7,202.5c1.5-4.6,3.8-9.4,8.9-10.6c13.5-3.2,15.7,13.3,14.6,22.1" style="stroke-dasharray: 46.1932, 48.1932; stroke-dashoffset: 47.1932px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--pinkish" d="M102.2,219.7c0,0-1.7,15.6-10.5,28.4" style="stroke-dasharray: 30.5375, 32.5375; stroke-dashoffset: 31.5375px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-backwards demo__fprint-path--pinkish" d="M72,244.9c0,0,8.8-9.9,9.9-15.7" style="stroke-dasharray: 18.7134, 20.7134; stroke-dashoffset: 19.7134px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--pinkish" d="M84.5,223c0.3-2.6,0.5-5.2,0.7-7.8c0.1-2.1,0.2-4.6-0.1-6.8c-0.3-2.2-1.1-4.3-0.9-6.5c0.5-4.4,7.2-6.9,10.1-3.1
c1.7,2.2,1.7,5.3,1.9,7.9c0.4,3.8,0.3,7.6,0,11.4c-1,10.8-5.4,21-11.5,29.9" style="stroke-dasharray: 86.4028, 88.4028; stroke-dashoffset: 87.4028px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--removes-forwards demo__fprint-path--purplish" d="M90,201.2c0,0,4.6,28.1-11.4,45.2" style="stroke-dasharray: 48.0853, 50.0853; stroke-dashoffset: 49.0853px; visibility: visible;"></path>
<path class="demo__fprint-path demo__fprint-path--pinkish" id="demo__elastic-path" d="M67.3,219C65,188.1,78,180.1,92.7,180.3c18.3,2,23.7,18.3,20,46.7" style="stroke-dasharray: 111.304, 113.304; stroke-dashoffset: 112.304px; visibility: visible;"></path>
<!-- <line id="demo__straight-path" x1="0" y1="151.3" x2="180" y2="151.3"></line>
<path class="demo__hidden-path" id="demo__arc-to-top" d="M0,148.4c62.3-13.5,122.3-13.5,180,0"></path>
<path class="demo__hidden-path" id="demo__curve" d="M0,140.2c13.1-10.5,34.7-17,48.5-4.1c5.5,5.2,7.6,12.1,9.2,19.2c2.4,10.5,4.3,21,7.2,31.4c2.4,8.6,4.3,19.6,10.4,26.7c4.3,5,17.7,13.4,23.1,4.8c5.9-9.4,6.8-22.5,9.7-33c4.9-17.8,13-14.6,15.7-14.6c1.8,0,9,2.3,15.4,5.4c6.2,3,11.9,7.7,17.9,11.2c7,4.1,16.5,9.2,22.8,6.6"></path>
<path class="demo__ending-path demo__ending-path--pinkish" d="M48.4,220c-5.8,4.2-6.9,11.5-7.6,18.1c-0.8,6.7-0.9,14.9-9.9,12.4c-9.1-2.5-14.7-5.4-19.9-13.4c-3.4-5.2-0.4-12.3,2.3-17.2c3.2-5.9,6.8-13,14.5-11.6c3.5,0.6,7.7,3.4,4.5,7.1"></path>
<path class="demo__ending-path demo__ending-path--pinkish" d="M57.3,235.2c-14.4,9.4-10.3,19.4-17.8,21.1c-5.5,1.3-8.4-7.8-13.8-4.2c-2.6,1.7-5.7,7.7-4.6,10.9c0.7,2,4.1,2,5.8,2.4c3,0.7,8.4,3,7.6,7.2c-0.6,3-5,5.3-2.4,8.7c1.8,2.2,4.7,1.1,6.9,0.3c11.7-4.3,14.5,0.8,16.5,0.9"></path>
<path class="demo__ending-path demo__ending-path--purplish" d="M79,246c-1.8,2.4-4.9,2.9-7.6,3.2c-2.7,0.3-5.8-0.8-7.7,1.6c-2.9,3.3,0.7,8.2-1.2,12c-1.5,2.8-4.5,2.4-6.9,1.3c-10.1-4.7-33.2-17.5-38.1-2.5c-1.1,3.4-1.9,7.5-1.3,11c0.6,4,5.6,7.9,7.7,2.3c0.8-2.1,3.1-8.6-1-8.9"></path>
<path class="demo__ending-path demo__ending-path--pinkish" d="M91.8,248c0,0-3.9,6.4-6.2,9.2c-3.8,4.5-7.9,8.9-11.2,13.8c-1.9,2.8-4.4,6.4-3.7,10c0.9,5.2,4.7,12.5,9.7,14.7c5.2,2.2,15.9-4.7,13.1-10.8c-1.4-3-6.3-7.9-10-7.2c-1,0.2-1.8,1-2,2"></path>
<path class="demo__ending-path demo__ending-path--purplish" d="M114.8,239.4c-2.7,6.1-8.3,12.8-7.8,19.8c0.3,4.6,3.8,7.4,7.8,9.1c8.9,3.8,19.7,0.4,28.6-1.3c8.8-1.7,19.7-3.2,23.7,6.7c2.8,6.8,6.1,14.7,4.4,22.2"></path>
<path class="demo__ending-path demo__ending-path--pinkish" d="M129.9,224.2c-0.4,7.5-3.1,18,0.7,25c2.8,5.1,14.3,6.3,19.5,7.4c3.7,0.7,8.7,2.2,12-0.5c6.7-5.4,11.1-13.7,14.1-21.6c3.1-8-4.4-12.8-11.1-14.5c-5-1.3-19.1-0.7-21-6.7c-0.9-2.8,1.8-5.9,3.4-7.9"></path>
<path class="demo__under-curve" d="M0,140.2c13.1-10.5,34.7-17,48.5-4.1c5.5,5.2,7.6,12.1,9.2,19.2c2.4,10.5,4.3,21,7.2,31.4c2.4,8.6,4.3,19.6,10.4,26.7c4.3,5,17.7,13.4,23.1,4.8c5.9-9.4,6.8-22.5,9.7-33c4.9-17.8,13-14.6,15.7-14.6c1.8,0,9,2.3,15.4,5.4c6.2,3,11.9,7.7,17.9,11.2c7,4.1,16.5,9.2,23.8,6.6l0,125.5l-181,0l0,-179.8"></path> -->
</svg>
</div>
<div class="log-text">loading...</div>
<div class="buttons">
<button id="enroll-btn">GX1000采集指纹</button>
</div>
<audio src="./press.mp3" id="press"></audio>
<audio src="./up.mp3" id="up"></audio>
<script src='jquery.min.js'></script>
<script src='jquery.toast.min.js'></script>
<script src='index.js'></script>
<script src='mafp_sdk.js'></script>
<script type="text/javascript">
function log(msg) {
document.querySelector(".log-text").innerHTML = msg;
}
onload = function() {
const EnrollCount = 6;
const EnrollTimeout = 30 * 1000;
setFprintProgress(0);
log("初始化...");
mafp.init({
enrollCount: EnrollCount,
enrollTimeout: EnrollTimeout
}).then(() => {
log("初始化成功.");
}).catch(e => {
log("初始化失败.");
});
var up = document.getElementById("up");
var press = document.getElementById("press");
$("#enroll-btn").click(() => {
if (mafp.isWorking) {
mafp.cancelEnroll();
$("#enroll-btn").text("注册");
log("注册取消");
}else {
log("注册准备中...");
mafp.startEnroll((status) => {
// console.log(status)
if (status.err) {
let logText = "注册出错";
switch(status.err) {
case ErrorReceiveDataErr:
logText = "数据包传输错误";
break;
case ErrorEnrollTimeout:
logText = "注册超时";
break;
case ErrorDeviceNotFound:
logText = "设备未找到";
break;
case ErrorEmptyFail:
logText = "清空数据失败";
break;
default:
logText = "注册出错:" + status.err;
}
log(logText);
$.toast({text: logText, position: 'top-center', icon: "error", hideAfter: 5000})
$("#enroll-btn").text("注册");
return;
}else {
if(status.state == STATE_WAIT_FINGER_DOWN) {
up.pause()
press.play()
log("请按手指");
}
else if(status.state == STATE_WAIT_FINGER_LEAVE) {
up.play()
log("请抬起手指");
}
else if(status.state == STATE_EXTRACT_TEMPLATE) {
log("提取特征点...");
}
else if(status.state == STATE_DOWNLOAD_TEMPLATE) {
log("模板传输中...");
}
else if (status.state == STATE_FINGER_DOWN) {
$(".demo__fprint_bg").addClass("down");
}else if (status.state == STATE_FINGER_LEAVE) {
$(".demo__fprint_bg").removeClass("down");
}else if (status.state >= STATE_EXTRACT_TEMPLATE_FAIL) {
let errText = "提取特征点失败";
if (status.state == STATE_EXTRACT_TEMPLATE_DIRTY) {
errText = "提取特征点失败, 指纹图像太乱";
}else if (status.state == STATE_EXTRACT_TEMPLATE_POINTS_FEW) {
errText = "提取特征点失败, 特征点太少";
}else if (status.state == STATE_EXTRACT_TEMPLATE_DIRTY) {
errText = "提取特征点失败, 合并失败";
}
$.toast({text: errText, position: 'top-center', hideAfter: 5000})
}
}
if (status.data) {
//注册完成 模板数据 二进制数据
//可封装成 multipart/form-data 上传服务端
console.log(status.data,'指纹数据')
var templateData = new Uint8Array(status.data);
localStorage.setItem('fingerprint',status.data)
// console.log(status.data);
log("注册完成");
$("#enroll-btn").text("注册");
}
if (status.data || status.step == EnrollCount && (status.state == 5 || status.state == 6)) {
setFprintProgress(1);
}else {
setFprintProgress((status.step - 1) / EnrollCount);
}
});
$("#enroll-btn").text("取消");
}
})
}
</script>
</body>

+ 104
- 0
dist/static/equipment/mafp_serial/index.js View File

@ -0,0 +1,104 @@
const TIME_TO_FILL_FPRINT = 2000; //ms
const $fprintPaths = document.querySelectorAll('.demo__fprint-path');
const $endingPaths = document.querySelectorAll('.demo__ending-path');
const fprintPathSelector = '.demo__fprint-path';
let fprintPaths = [];
let lastRafCallTimestamp = 0;
let curFprintPathsOffset = -1;
let fprintProgressionDirection = 1;
let isFprintAnimationInProgress = false;
let isFprintAnimationOver = false;
let fprintTick = 0;
let currentFprintProgresss = 0;
function offsetAllFprintPaths(ratio) {
fprintPaths.forEach(path => path.offset(ratio));
}
function fprintFrame(timestamp) {
if (!lastRafCallTimestamp) {
lastRafCallTimestamp = timestamp;
window.requestAnimationFrame(fprintFrame);
return;
}
let diff = timestamp - lastRafCallTimestamp;
fprintTick = (diff / TIME_TO_FILL_FPRINT) * 2;
lastRafCallTimestamp = timestamp;
curFprintPathsOffset += fprintTick * fprintProgressionDirection;
offsetAllFprintPaths(curFprintPathsOffset);
if (curFprintPathsOffset >= -1 && curFprintPathsOffset <= 1) {
window.requestAnimationFrame(fprintFrame);
}
else if (curFprintPathsOffset > 1) {
curFprintPathsOffset = curFprintPathsOffset - 2;
offsetAllFprintPaths(curFprintPathsOffset);
window.requestAnimationFrame(fprintFrame);
}
else if (curFprintPathsOffset < -1) {
curFprintPathsOffset = curFprintPathsOffset + 2;
offsetAllFprintPaths(curFprintPathsOffset);
window.requestAnimationFrame(fprintFrame);
}
}
function fprintFrameToProcess(timestamp) {
if (!lastRafCallTimestamp) {
lastRafCallTimestamp = timestamp;
window.requestAnimationFrame(fprintFrameToProcess);
return;
}
let diff = timestamp - lastRafCallTimestamp;
fprintTick = (diff / TIME_TO_FILL_FPRINT) * 2;
lastRafCallTimestamp = timestamp;
curFprintPathsOffset += fprintTick * fprintProgressionDirection;
offsetAllFprintPaths(curFprintPathsOffset);
if (curFprintPathsOffset >= -1 && curFprintPathsOffset <= currentFprintProgresss - 1) {
window.requestAnimationFrame(fprintFrameToProcess);
}
else if (curFprintPathsOffset > currentFprintProgresss - 1) {
curFprintPathsOffset = currentFprintProgresss - 1;
offsetAllFprintPaths(curFprintPathsOffset);
lastRafCallTimestamp = 0;
}
}
function setFprintProgress(progress) {
if (progress == 0) {
curFprintPathsOffset = -1;
offsetAllFprintPaths(curFprintPathsOffset);
}else {
currentFprintProgresss = progress;
window.requestAnimationFrame(fprintFrameToProcess);
}
}
class Path {
constructor(selector, index) {
this.index = index;
this.querySelection = document.querySelectorAll(selector)[index];
this.length = this.querySelection.getTotalLength();
this.$ = $(selector).eq(index);
this.setDasharray();
this.removesForwards = this.$.hasClass('demo__fprint-path--removes-forwards');
}
setDasharray() {
this.$.css('stroke-dasharray', `${this.length} ${this.length + 2}`);
return this;
}
offset(ratio) {
this.$.css('stroke-dashoffset', -this.length * ratio );
return this;
}
makeVisible() {
this.$.css('visibility', 'visible');
return this;
}
}
$(document).ready(() => {
for (let i = 0; i < document.querySelectorAll(fprintPathSelector).length; i++) {
fprintPaths.push(new Path(fprintPathSelector, i));
fprintPaths[i].offset(-1).makeVisible();
}
//window.requestAnimationFrame(fprintFrame);
})

+ 4
- 0
dist/static/equipment/mafp_serial/jquery.min.js
File diff suppressed because it is too large
View File


+ 28
- 0
dist/static/equipment/mafp_serial/jquery.toast.css View File

@ -0,0 +1,28 @@
/**
* jQuery toast plugin created by Kamran Ahmed copyright MIT license 2014
*/
.jq-toast-wrap { display: block; position: fixed; width: 250px; pointer-events: none !important; margin: 0; padding: 0; letter-spacing: normal; z-index: 9000 !important; }
.jq-toast-wrap * { margin: 0; padding: 0; }
.jq-toast-wrap.bottom-left { bottom: 20px; left: 20px; }
.jq-toast-wrap.bottom-right { bottom: 20px; right: 40px; }
.jq-toast-wrap.top-left { top: 20px; left: 20px; }
.jq-toast-wrap.top-right { top: 20px; right: 40px; }
.jq-toast-single { display: block; width: 100%; padding: 10px; margin: 0px 0px 5px; border-radius: 4px; font-size: 12px; font-family: arial, sans-serif; line-height: 17px; position: relative; pointer-events: all !important; background-color: #444444; color: white; }
.jq-toast-single h2 { font-family: arial, sans-serif; font-size: 14px; margin: 0px 0px 7px; background: none; color: inherit; line-height: inherit; letter-spacing: normal; }
.jq-toast-single a { color: #eee; text-decoration: none; font-weight: bold; border-bottom: 1px solid white; padding-bottom: 3px; font-size: 12px; }
.jq-toast-single ul { margin: 0px 0px 0px 15px; background: none; padding:0px; }
.jq-toast-single ul li { list-style-type: disc !important; line-height: 17px; background: none; margin: 0; padding: 0; letter-spacing: normal; }
.close-jq-toast-single { position: absolute; top: 3px; right: 7px; font-size: 14px; cursor: pointer; }
.jq-toast-loader { display: block; position: absolute; top: -2px; height: 5px; width: 0%; left: 0; border-radius: 5px; background: red; }
.jq-toast-loaded { width: 100%; }
.jq-has-icon { padding: 10px 10px 10px 50px; background-repeat: no-repeat; background-position: 10px; }
.jq-icon-info { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII='); background-color: #31708f; color: #d9edf7; border-color: #bce8f1; }
.jq-icon-warning { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII='); background-color: #8a6d3b; color: #fcf8e3; border-color: #faebcc; }
.jq-icon-error { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII='); background-color: #a94442; color: #f2dede; border-color: #ebccd1; }
.jq-icon-success { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg=='); color: #dff0d8; background-color: #3c763d; border-color: #d6e9c6; }

+ 1
- 0
dist/static/equipment/mafp_serial/jquery.toast.min.js
File diff suppressed because it is too large
View File


+ 107
- 0
dist/static/equipment/mafp_serial/mafp_sdk.js View File

@ -0,0 +1,107 @@
const STATE_WAIT_FINGER_DOWN = 1;
const STATE_WAIT_FINGER_LEAVE = 2;
const STATE_FINGER_DOWN = 3;
const STATE_FINGER_LEAVE = 4;
const STATE_EXTRACT_TEMPLATE = 5;
const STATE_DOWNLOAD_TEMPLATE = 6;
const STATE_EXTRACT_TEMPLATE_FAIL = 100;
const STATE_EXTRACT_TEMPLATE_DIRTY = 101;
const STATE_EXTRACT_TEMPLATE_POINTS_FEW = 102;
const STATE_EXTRACT_TEMPLATE_MERGE_FAIL = 103;
const ErrorReceiveDataErr = 1;
const ErrorEnrollTimeout = 2;
const ErrorDeviceNotFound = 3;
const ErrorEmptyFail = 4;
var mafp = {
isConnected: false,
ws: null,
enrollCount: 6,
enrollTimeout: 30 * 1000,
callback: null,
isWorking: false,
init(conf) {
if (conf && conf.enrollCount) {
this.enrollCount = conf.enrollCount;
}
if (conf && conf.enrollTimeout) {
this.enrollTimeout = conf.enrollTimeout;
}
return new Promise((resolve,reject) => {
var that = this;
if (this.isConnected) {
resolve();
return;
}
var timeout = setTimeout(() => {
if (!that.isConnected) {
reject("Connection timeout");
}
}, 2000)
var port = 9897;
var address = 'ws://localhost:' + port + '/';
that.ws = new WebSocket(address);
that.ws.addEventListener('open', function() {
that.isConnected = true;
if (timeout) {
clearTimeout(timeout);
timeout = 0;
}
resolve()
});
that.ws.addEventListener('close', function() {
console.log('Connection lost');
that.isConnected = false;
reject("Connection lost");
});
that.ws.addEventListener('message', function(e) {
let resp = JSON.parse(e.data);
if (that.callback) {
that.callback(resp);
if(resp.err || resp.data) {
that.isWorking = false;
that.callback = null;
}
}
});
});
},
_sendMessage(msg) {
this.ws.send(JSON.stringify(msg));
},
startEnroll(callback=((status, data)=>{})) {
this.callback = callback;
this.isWorking = true;
this.init().then(() => {
this._sendMessage({
cmd: "enrollStart",
config: {
enrollCount: this.enrollCount,
enrollTimeout: this.enrollTimeout
}
});
}).catch(err => {
this.callback = null;
this.isWorking = false;
callback({
err: err,
state: 0,
step:0
})
})
},
cancelEnroll() {
this.callback = null;
this.isWorking = false;
this._sendMessage({
cmd: "enrollCancel"
});
}
};

+ 29
- 0
dist/static/equipment/mafp_serial/plugin/background.js View File

@ -0,0 +1,29 @@
var socketId = 0;
chrome.app.runtime.onLaunched.addListener(function() {
if (socketId) {
console.log("close socket " +socketId);
chrome.sockets.tcpServer.close(socketId);
socketId = 0;
}
chrome.app.window.create('main.html', {
id: "mainwin",
innerBounds: {
width: 670,
height: 350,
minWidth: 670,
minHeight: 350
}
});
})
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
socketId = request.socketId;
});
chrome.runtime.onSuspend.addListener(function() {
if(socketId) {
chrome.sockets.tcpServer.close(socketId);
socketId = 0;
}
});

+ 17
- 0
dist/static/equipment/mafp_serial/plugin/event.js View File

@ -0,0 +1,17 @@
var MyEvent = function(type="") {
this.type = type;
this.listeners = [];
};
MyEvent.prototype.addListener = function(listener) {
this.listeners.push(listener);
}
MyEvent.prototype.dispatch = function() {
for (var listener of this.listeners) {
var ret = listener.apply(null, arguments);
if (!ret) {
return;
}
}
}

+ 894
- 0
dist/static/equipment/mafp_serial/plugin/http.js View File

@ -0,0 +1,894 @@
/**
* Copyright (c) 2013 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
**/
var http = function() {
if (!chrome.sockets || !chrome.sockets.tcpServer)
return {};
// Wrap chrome.sockets.tcp socketId with a Promise API.
var PSocket = (function() {
// chrome.sockets.tcp uses a global listener for incoming data so
// use a map to dispatch to the proper instance.
var socketMap = {};
chrome.sockets.tcp.onReceive.addListener(function(info) {
var pSocket = socketMap[info.socketId];
if (pSocket) {
if (pSocket.handlers) {
// Fulfil the pending read.
pSocket.handlers.resolve(info.data);
delete pSocket.handlers;
}
else {
// No pending read so put data on the queue.
pSocket.readQueue.push(info);
}
}
});
// Read errors also use a global listener.
chrome.sockets.tcp.onReceiveError.addListener(function(info) {
var pSocket = socketMap[info.socketId];
if (pSocket) {
if (pSocket.handlers) {
// Reject the pending read.
pSocket.handlers.reject(new Error('chrome.sockets.tcp error ' + info.resultCode));
delete pSocket.handlers;
}
else {
// No pending read so put data on the queue.
pSocket.readQueue.push(info);
}
}
});
// PSocket constructor.
return function(socketId) {
this.socketId = socketId;
this.readQueue = [];
// Register this instance for incoming data processing.
socketMap[socketId] = this;
chrome.sockets.tcp.setPaused(socketId, false);
};
})();
// Returns a Promise<ArrayBuffer> with read data.
PSocket.prototype.read = function() {
var that = this;
if (this.readQueue.length) {
// Return data from the queue.
var info = this.readQueue.shift();
if (!info.resultCode)
return Promise.resolve(info.data);
else
return Promise.reject(new Error('chrome.sockets.tcp error ' + info.resultCode));
}
else {
// The queue is empty so install handlers.
return new Promise(function(resolve, reject) {
that.handlers = { resolve: resolve, reject: reject };
});
}
};
// Returns a Promise<integer> with the number of bytes written.
PSocket.prototype.write = function(data) {
var that = this;
return new Promise(function(resolve, reject) {
chrome.sockets.tcp.send(that.socketId, data, function(info) {
if (info && info.resultCode >= 0)
resolve(info.bytesSent);
else
reject(new Error('chrome sockets.tcp error ' + (info && info.resultCode)));
});
});
};
// Returns a Promise.
PSocket.prototype.close = function() {
var that = this;
return new Promise(function(resolve, reject) {
chrome.sockets.tcp.disconnect(that.socketId, function() {
chrome.sockets.tcp.close(that.socketId, resolve);
});
});
};
// Http response code strings.
var responseMap = {
200: 'OK',
301: 'Moved Permanently',
304: 'Not Modified',
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
413: 'Request Entity Too Large',
414: 'Request-URI Too Long',
500: 'Internal Server Error'};
/**
* Convert from an ArrayBuffer to a string.
* @param {ArrayBuffer} buffer The array buffer to convert.
* @return {string} The textual representation of the array.
*/
var arrayBufferToString = function(buffer) {
var array = new Uint8Array(buffer);
var str = '';
for (var i = 0; i < array.length; ++i) {
str += String.fromCharCode(array[i]);
}
return str;
};
/**
* Convert from an UTF-8 array to UTF-8 string.
* @param {array} UTF-8 array
* @return {string} UTF-8 string
*/
var ary2utf8 = (function() {
var patterns = [
{pattern: '0xxxxxxx', bytes: 1},
{pattern: '110xxxxx', bytes: 2},
{pattern: '1110xxxx', bytes: 3},
{pattern: '11110xxx', bytes: 4},
{pattern: '111110xx', bytes: 5},
{pattern: '1111110x', bytes: 6}
];
patterns.forEach(function(item) {
item.header = item.pattern.replace(/[^10]/g, '');
item.pattern01 = item.pattern.replace(/[^10]/g, '0');
item.pattern01 = parseInt(item.pattern01, 2);
item.mask_length = item.header.length;
item.data_length = 8 - item.header.length;
var mask = '';
for (var i = 0, len = item.mask_length; i < len; i++) {
mask += '1';
}
for (var i = 0, len = item.data_length; i < len; i++) {
mask += '0';
}
item.mask = mask;
item.mask = parseInt(item.mask, 2);
});
return function(ary) {
var codes = [];
var cur = 0;
while(cur < ary.length) {
var first = ary[cur];
var pattern = null;
for (var i = 0, len = patterns.length; i < len; i++) {
if ((first & patterns[i].mask) == patterns[i].pattern01) {
pattern = patterns[i];
break;
}
}
if (pattern == null) {
throw 'utf-8 decode error';
}
var rest = ary.slice(cur + 1, cur + pattern.bytes);
cur += pattern.bytes;
var code = '';
code += ('00000000' + (first & (255 ^ pattern.mask)).toString(2)).slice(-pattern.data_length);
for (var i = 0, len = rest.length; i < len; i++) {
code += ('00000000' + (rest[i] & parseInt('111111', 2)).toString(2)).slice(-6);
}
codes.push(parseInt(code, 2));
}
return String.fromCharCode.apply(null, codes);
};
})();
/**
* Convert from an UTF-8 string to UTF-8 array.
* @param {string} UTF-8 string
* @return {array} UTF-8 array
*/
var utf82ary = (function() {
var patterns = [
{pattern: '0xxxxxxx', bytes: 1},
{pattern: '110xxxxx', bytes: 2},
{pattern: '1110xxxx', bytes: 3},
{pattern: '11110xxx', bytes: 4},
{pattern: '111110xx', bytes: 5},
{pattern: '1111110x', bytes: 6}
];
patterns.forEach(function(item) {
item.header = item.pattern.replace(/[^10]/g, '');
item.mask_length = item.header.length;
item.data_length = 8 - item.header.length;
item.max_bit_length = (item.bytes - 1) * 6 + item.data_length;
});
var code2utf8array = function(code) {
var pattern = null;
var code01 = code.toString(2);
for (var i = 0, len = patterns.length; i < len; i++) {
if (code01.length <= patterns[i].max_bit_length) {
pattern = patterns[i];
break;
}
}
if (pattern == null) {
throw 'utf-8 encode error';
}
var ary = [];
for (var i = 0, len = pattern.bytes - 1; i < len; i++) {
ary.unshift(parseInt('10' + ('000000' + code01.slice(-6)).slice(-6), 2));
code01 = code01.slice(0, -6);
}
ary.unshift(parseInt(pattern.header + ('00000000' + code01).slice(-pattern.data_length), 2));
return ary;
};
return function(str) {
var codes = [];
for (var i = 0, len = str.length; i < len; i++) {
var code = str.charCodeAt(i);
Array.prototype.push.apply(codes, code2utf8array(code));
}
return codes;
};
})();
/**
* Convert a string to an ArrayBuffer.
* @param {string} string The string to convert.
* @return {ArrayBuffer} An array buffer whose bytes correspond to the string.
*/
var stringToArrayBuffer = function(string) {
var buffer = new ArrayBuffer(string.length);
var bufferView = new Uint8Array(buffer);
for (var i = 0; i < string.length; i++) {
bufferView[i] = string.charCodeAt(i);
}
return buffer;
};
/**
* An event source can dispatch events. These are dispatched to all of the
* functions listening for that event type with arguments.
* @constructor
*/
function EventSource() {
this.listeners_ = {};
};
EventSource.prototype = {
/**
* Add |callback| as a listener for |type| events.
* @param {string} type The type of the event.
* @param {function(Object|undefined): boolean} callback The function to call
* when this event type is dispatched. Arguments depend on the event
* source and type. The function returns whether the event was "handled"
* which will prevent delivery to the rest of the listeners.
*/
addEventListener: function(type, callback) {
if (!this.listeners_[type])
this.listeners_[type] = [];
this.listeners_[type].push(callback);
},
/**
* Remove |callback| as a listener for |type| events.
* @param {string} type The type of the event.
* @param {function(Object|undefined): boolean} callback The callback
* function to remove from the event listeners for events having type
* |type|.
*/
removeEventListener: function(type, callback) {
if (!this.listeners_[type])
return;
for (var i = this.listeners_[type].length - 1; i >= 0; i--) {
if (this.listeners_[type][i] == callback) {
this.listeners_[type].splice(i, 1);
}
}
},
/**
* Dispatch an event to all listeners for events of type |type|.
* @param {type} type The type of the event being dispatched.
* @param {...Object} var_args The arguments to pass when calling the
* callback function.
* @return {boolean} Returns true if the event was handled.
*/
dispatchEvent: function(type, var_args) {
if (!this.listeners_[type])
return false;
for (var i = 0; i < this.listeners_[type].length; i++) {
if (this.listeners_[type][i].apply(
/* this */ null,
/* var_args */ Array.prototype.slice.call(arguments, 1))) {
return true;
}
}
}
};
/**
* HttpServer provides a lightweight Http web server. Currently it only
* supports GET requests and upgrading to other protocols (i.e. WebSockets).
* @constructor
*/
function HttpServer() {
EventSource.apply(this);
this.readyState_ = 0;
}
HttpServer.prototype = {
__proto__: EventSource.prototype,
/**
* Listen for connections on |port| using the interface |host|.
* @param {number} port The port to listen for incoming connections on.
* @param {string=} opt_host The host interface to listen for connections on.
* This will default to 0.0.0.0 if not specified which will listen on
* all interfaces.
*/
listen: function(port, opt_host) {
var t = this;
chrome.sockets.tcpServer.create(function(socketInfo) {
chrome.sockets.tcpServer.onAccept.addListener(function(acceptInfo) {
if (acceptInfo.socketId === socketInfo.socketId)
t.readRequestFromSocket_(new PSocket(acceptInfo.clientSocketId));
});
this.socketId = socketInfo.socketId;
chrome.runtime.sendMessage({socketId: this.socketId});
chrome.sockets.tcpServer.listen(
socketInfo.socketId,
opt_host || '0.0.0.0',
port,
50,
function(result) {
if (!result) {
t.readyState_ = 1;
}
else {
console.log(
'listen error ' +
chrome.runtime.lastError.message +
' (normal if another instance is already serving requests)');
}
});
});
},
close: function() {
if (this.socketId) {
chrome.sockets.tcpServer.close(this.socketId);
this.socketId = 0;
}
},
readRequestFromSocket_: function(pSocket) {
var t = this;
var requestData = '';
var endIndex = 0;
var onDataRead = function(data) {
requestData += arrayBufferToString(data).replace(/\r\n/g, '\n');
// Check for end of request.
endIndex = requestData.indexOf('\n\n', endIndex);
if (endIndex == -1) {
endIndex = requestData.length - 1;
return pSocket.read().then(onDataRead);
}
var headers = requestData.substring(0, endIndex).split('\n');
var headerMap = {};
// headers[0] should be the Request-Line
var requestLine = headers[0].split(' ');
headerMap['method'] = requestLine[0];
headerMap['url'] = requestLine[1];
headerMap['Http-Version'] = requestLine[2];
for (var i = 1; i < headers.length; i++) {
requestLine = headers[i].split(':', 2);
if (requestLine.length == 2)
headerMap[requestLine[0]] = requestLine[1].trim();
}
var request = new HttpRequest(headerMap, pSocket);
t.onRequest_(request);
};
pSocket.read().then(onDataRead).catch(function(e) {
pSocket.close();
});
},
onRequest_: function(request) {
var type = request.headers['Upgrade'] ? 'upgrade' : 'request';
var keepAlive = request.headers['Connection'] == 'keep-alive';
if (!this.dispatchEvent(type, request))
request.close();
else if (keepAlive)
this.readRequestFromSocket_(request.pSocket_);
},
};
// MIME types for common extensions.
var extensionTypes = {
'css': 'text/css',
'html': 'text/html',
'htm': 'text/html',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'js': 'text/javascript',
'png': 'image/png',
'svg': 'image/svg+xml',
'txt': 'text/plain'};
/**
* Constructs an HttpRequest object which tracks all of the request headers and
* socket for an active Http request.
* @param {Object} headers The HTTP request headers.
* @param {Object} pSocket The socket to use for the response.
* @constructor
*/
function HttpRequest(headers, pSocket) {
this.version = 'HTTP/1.1';
this.headers = headers;
this.responseHeaders_ = {};
this.headersSent = false;
this.pSocket_ = pSocket;
this.writes_ = 0;
this.bytesRemaining = 0;
this.finished_ = false;
this.readyState = 1;
}
HttpRequest.prototype = {
__proto__: EventSource.prototype,
/**
* Closes the Http request.
*/
close: function() {
// The socket for keep alive connections will be re-used by the server.
// Just stop referencing or using the socket in this HttpRequest.
if (this.headers['Connection'] != 'keep-alive')
pSocket.close();
this.pSocket_ = null;
this.readyState = 3;
},
/**
* Write the provided headers as a response to the request.
* @param {int} responseCode The HTTP status code to respond with.
* @param {Object} responseHeaders The response headers describing the
* response.
*/
writeHead: function(responseCode, responseHeaders) {
var headerString = this.version + ' ' + responseCode + ' ' +
(responseMap[responseCode] || 'Unknown');
this.responseHeaders_ = responseHeaders;
if (this.headers['Connection'] == 'keep-alive')
responseHeaders['Connection'] = 'keep-alive';
if (!responseHeaders['Content-Length'] && responseHeaders['Connection'] == 'keep-alive')
responseHeaders['Transfer-Encoding'] = 'chunked';
for (var i in responseHeaders) {
headerString += '\r\n' + i + ': ' + responseHeaders[i];
}
headerString += '\r\n\r\n';
this.write_(stringToArrayBuffer(headerString));
},
/**
* Writes data to the response stream.
* @param {string|ArrayBuffer} data The data to write to the stream.
*/
write: function(data) {
if (this.responseHeaders_['Transfer-Encoding'] == 'chunked') {
var newline = '\r\n';
var byteLength = (data instanceof ArrayBuffer) ? data.byteLength : data.length;
var chunkLength = byteLength.toString(16).toUpperCase() + newline;
var buffer = new ArrayBuffer(chunkLength.length + byteLength + newline.length);
var bufferView = new Uint8Array(buffer);
for (var i = 0; i < chunkLength.length; i++)
bufferView[i] = chunkLength.charCodeAt(i);
if (data instanceof ArrayBuffer) {
bufferView.set(new Uint8Array(data), chunkLength.length);
} else {
for (var i = 0; i < data.length; i++)
bufferView[chunkLength.length + i] = data.charCodeAt(i);
}
for (var i = 0; i < newline.length; i++)
bufferView[chunkLength.length + byteLength + i] = newline.charCodeAt(i);
data = buffer;
} else if (!(data instanceof ArrayBuffer)) {
data = stringToArrayBuffer(data);
}
this.write_(data);
},
/**
* Finishes the HTTP response writing |data| before closing.
* @param {string|ArrayBuffer=} opt_data Optional data to write to the stream
* before closing it.
*/
end: function(opt_data) {
if (opt_data)
this.write(opt_data);
if (this.responseHeaders_['Transfer-Encoding'] == 'chunked')
this.write('');
this.finished_ = true;
this.checkFinished_();
},
/**
* Automatically serve the given |url| request.
* @param {string} url The URL to fetch the file to be served from. This is
* retrieved via an XmlHttpRequest and served as the response to the
* request.
*/
serveUrl: function(url) {
var t = this;
var xhr = new XMLHttpRequest();
xhr.onloadend = function() {
var type = 'text/plain';
if (this.getResponseHeader('Content-Type')) {
type = this.getResponseHeader('Content-Type');
} else if (url.indexOf('.') != -1) {
var extension = url.substr(url.indexOf('.') + 1);
type = extensionTypes[extension] || type;
}
console.log('Served ' + url);
var contentLength = this.getResponseHeader('Content-Length');
if (xhr.status == 200)
contentLength = (this.response && this.response.byteLength) || 0;
t.writeHead(this.status, {
'Content-Type': type,
'Content-Length': contentLength});
t.end(this.response);
};
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.send();
},
write_: function(array) {
var t = this;
this.bytesRemaining += array.byteLength;
this.pSocket_.write(array).then(function(bytesWritten) {
t.bytesRemaining -= bytesWritten;
t.checkFinished_();
}).catch(function(e) {
console.error(e.message);
return;
});
},
checkFinished_: function() {
if (!this.finished_ || this.bytesRemaining > 0)
return;
this.close();
}
};
/**
* Constructs a server which is capable of accepting WebSocket connections.
* @param {HttpServer} httpServer The Http Server to listen and handle
* WebSocket upgrade requests on.
* @constructor
*/
function WebSocketServer(httpServer) {
EventSource.apply(this);
httpServer.addEventListener('upgrade', this.upgradeToWebSocket_.bind(this));
}
WebSocketServer.prototype = {
__proto__: EventSource.prototype,
upgradeToWebSocket_: function(request) {
if (request.headers['Upgrade'] != 'websocket' ||
!request.headers['Sec-WebSocket-Key']) {
return false;
}
if (this.dispatchEvent('request', new WebSocketRequest(request))) {
if (request.pSocket_)
request.reject();
return true;
}
return false;
}
};
/**
* Constructs a WebSocket request object from an Http request. This invalidates
* the Http request's socket and offers accept and reject methods for accepting
* and rejecting the WebSocket upgrade request.
* @param {HttpRequest} httpRequest The HTTP request to upgrade.
*/
function WebSocketRequest(httpRequest) {
// We'll assume control of the socket for this request.
HttpRequest.apply(this, [httpRequest.headers, httpRequest.pSocket_]);
httpRequest.pSocket_ = null;
}
WebSocketRequest.prototype = {
__proto__: HttpRequest.prototype,
/**
* Accepts the WebSocket request.
* @return {WebSocketServerSocket} The websocket for the accepted request.
*/
accept: function() {
// Construct WebSocket response key.
var clientKey = this.headers['Sec-WebSocket-Key'];
var toArray = function(str) {
var a = [];
for (var i = 0; i < str.length; i++) {
a.push(str.charCodeAt(i));
}
return a;
}
var toString = function(a) {
var str = '';
for (var i = 0; i < a.length; i++) {
str += String.fromCharCode(a[i]);
}
return str;
}
// Magic string used for websocket connection key hashing:
// http://en.wikipedia.org/wiki/WebSocket
var magicStr = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
// clientKey is base64 encoded key.
clientKey += magicStr;
var sha1 = new Sha1();
sha1.reset();
sha1.update(toArray(clientKey));
var responseKey = btoa(toString(sha1.digest()));
var responseHeader = {
'Upgrade': 'websocket',
'Connection': 'Upgrade',
'Sec-WebSocket-Accept': responseKey};
if (this.headers['Sec-WebSocket-Protocol'])
responseHeader['Sec-WebSocket-Protocol'] = this.headers['Sec-WebSocket-Protocol'];
this.writeHead(101, responseHeader);
var socket = new WebSocketServerSocket(this.pSocket_);
// Detach the socket so that we don't use it anymore.
this.pSocket_ = 0;
return socket;
},
/**
* Rejects the WebSocket request, closing the connection.
*/
reject: function() {
this.close();
}
}
/**
* Constructs a WebSocketServerSocket using the given socketId. This should be
* a socket which has already been upgraded from an Http request.
* @param {number} socketId The socket id with an active websocket connection.
*/
function WebSocketServerSocket(pSocket) {
this.pSocket_ = pSocket;
this.readyState = 1;
EventSource.apply(this);
this.readFromSocket_();
}
WebSocketServerSocket.prototype = {
__proto__: EventSource.prototype,
/**
* Send |data| on the WebSocket.
* @param {string|Array.<number>|ArrayBuffer} data The data to send over the WebSocket.
*/
send: function(data) {
// WebSocket must specify opcode when send frame.
// The opcode for data frame is 1(text) or 2(binary).
if (typeof data == 'string' || data instanceof String) {
this.sendFrame_(1, data);
} else {
this.sendFrame_(2, data);
}
},
/**
* Begin closing the WebSocket. Note that the WebSocket protocol uses a
* handshake to close the connection, so this call will begin the closing
* process.
*/
close: function() {
if (this.readyState === 1) {
this.sendFrame_(8);
this.readyState = 2;
}
},
readFromSocket_: function() {
var t = this;
var data = [];
var message = '';
var fragmentedOp = 0;
var fragmentedMessages = [];
var onDataRead = function(dataBuffer) {
var a = new Uint8Array(dataBuffer);
for (var i = 0; i < a.length; i++)
data.push(a[i]);
while (data.length) {
var length_code = -1;
var data_start = 6;
var mask;
var fin = (data[0] & 128) >> 7;
var op = data[0] & 15;
if (data.length > 1)
length_code = data[1] & 127;
if (length_code > 125) {
if ((length_code == 126 && data.length > 7) ||
(length_code == 127 && data.length > 14)) {
if (length_code == 126) {
length_code = data[2] * 256 + data[3];
mask = data.slice(4, 8);
data_start = 8;
} else if (length_code == 127) {
length_code = 0;
for (var i = 0; i < 8; i++) {
length_code = length_code * 256 + data[2 + i];
}
mask = data.slice(10, 14);
data_start = 14;
}
} else {
length_code = -1; // Insufficient data to compute length
}
} else {
if (data.length > 5)
mask = data.slice(2, 6);
}
if (length_code > -1 && data.length >= data_start + length_code) {
var decoded = data.slice(data_start, data_start + length_code).map(function(byte, index) {
return byte ^ mask[index % 4];
});
if (op == 1) {
decoded = ary2utf8(decoded);
}
data = data.slice(data_start + length_code);
if (fin && op > 0) {
// Unfragmented message.
if (!t.onFrame_(op, decoded))
return;
} else {
// Fragmented message.
fragmentedOp = fragmentedOp || op;
fragmentedMessages.push(decoded);
if (fin) {
var joinMessage = null;
if (op == 1) {
joinMessage = fragmentedMessagess.join('');
} else {
joinMessage = fragmentedMessages.reduce(function(pre, cur) {
return Array.prototype.push.apply(pre, cur);
}, []);
}
if (!t.onFrame_(fragmentedOp, joinMessage))
return;
fragmentedOp = 0;
fragmentedMessages = [];
}
}
} else {
break; // Insufficient data, wait for more.
}
}
return t.pSocket_.read().then(onDataRead);
};
this.pSocket_.read().then(function(data) {
return onDataRead(data);
}).catch(function(e) {
t.close_();
});
},
onFrame_: function(op, data) {
if (op == 1 || op == 2) {
if (typeof data == 'string' || data instanceof String) {
// Don't do anything.
} else if (Array.isArray(data)) {
data = new Uint8Array(data).buffer;
} else if (data instanceof ArrayBuffer) {
// Don't do anything.
} else {
data = data.buffer;
}
this.dispatchEvent('message', {'data': data});
} else if (op == 8) {
// A close message must be confirmed before the websocket is closed.
if (this.readyState === 1) {
this.sendFrame_(8);
this.readyState = 2;
} else {
this.close_();
return false;
}
}
return true;
},
sendFrame_: function(op, data) {
var t = this;
var WebsocketFrameData = function(op, data) {
var ary = data;
if (typeof data == 'string' || data instanceof String) {
ary = utf82ary(data);
}
if (Array.isArray(ary)) {
ary = new Uint8Array(ary);
}
if (ary instanceof ArrayBuffer) {
ary = new Uint8Array(ary);
}
ary = new Uint8Array(ary.buffer);
var length = ary.length;
if (ary.length > 65535)
length += 10;
else if (ary.length > 125)
length += 4;
else
length += 2;
var lengthBytes = 0;
var buffer = new ArrayBuffer(length);
var bv = new Uint8Array(buffer);
bv[0] = 128 | (op & 15); // Fin and type text.
bv[1] = ary.length > 65535 ? 127 :
(ary.length > 125 ? 126 : ary.length);
if (ary.length > 65535)
lengthBytes = 8;
else if (ary.length > 125)
lengthBytes = 2;
var len = ary.length;
for (var i = lengthBytes - 1; i >= 0; i--) {
bv[2 + i] = len & 255;
len = len >> 8;
}
var dataStart = lengthBytes + 2;
for (var i = 0; i < ary.length; i++) {
bv[dataStart + i] = ary[i];
}
return buffer;
}
var array = WebsocketFrameData(op, data || '');
this.pSocket_.write(array).then(function(bytesWritten) {
if (bytesWritten !== array.byteLength)
throw new Error('insufficient write');
}).catch(function(e) {
t.close_();
});
},
close_: function() {
if (this.readyState !== 3) {
this.pSocket_.close();
this.readyState = 3;
this.dispatchEvent('close');
}
}
};
return {
'Server': HttpServer,
'WebSocketServer': WebSocketServer,
};
}();

BIN
dist/static/equipment/mafp_serial/plugin/logo.png View File

Before After
Width: 95  |  Height: 94  |  Size: 3.6 KiB

+ 27
- 0
dist/static/equipment/mafp_serial/plugin/main.html View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<script src="event.js"></script>
<script src="sha1.js"></script>
<script src="http.js"></script>
<script src="main.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="msg">
<div id="buffer"> </div>
<div id="msg_end"></div>
</div>
<div class="buttons">
<input type="checkbox" id="show-log"> Debug
<button id="enroll">Enroll</button>
<button id="down">Down</button>
<button id="match">Match</button>
<button id="refresh">Refesh Device</button>
<button id="export">Export</button>
<button id="import">Import&Down</button>
<input type="file" id="import-file" style="display:none"/>
</div>
</body>
</html>

+ 883
- 0
dist/static/equipment/mafp_serial/plugin/main.js View File

@ -0,0 +1,883 @@
const serial = chrome.serial;
var showDebugLog = false;
var SerialConnection = function() {
this.connectionId = -1;
this.boundOnReceive = this.onReceive.bind(this);
this.boundOnReceiveError = this.onReceiveError.bind(this);
this.onConnect = new MyEvent();
this.onReceive = new MyEvent();
this.onError = new MyEvent();
this.recvBuffer = new Uint8Array(8*1024);
this.recvView = new DataView(this.recvBuffer.buffer);
this.recvCursor = 0;
this.bitrate = 57600;
};
SerialConnection.prototype.onConnectComplete = function(connectionInfo) {
if (!connectionInfo) {
if (chrome.runtime.lastError != undefined) {
logln('chrome.serial.connect error: ' + chrome.runtime.lastError.message);
}
return;
}
this.connectionId = connectionInfo.connectionId;
chrome.serial.onReceive.addListener(this.boundOnReceive);
chrome.serial.onReceiveError.addListener(this.boundOnReceiveError);
this.onConnect.dispatch();
};
SerialConnection.prototype.onReceive = function(receiveInfo) {
if (receiveInfo.connectionId !== this.connectionId) {
return;
}
this.recvBuffer.set(new Uint8Array(receiveInfo.data), this.recvCursor);
this.recvCursor += receiveInfo.data.byteLength;
//console.log(buf2hex(receiveInfo.data));
if (this.recvCursor < 6) {
return;
}
this._dispathReceiveData();
};
SerialConnection.prototype.clearRecvData = function() {
this.recvCursor = 0;
this.recvBuffer.fill(0);
}
SerialConnection.prototype._dispathReceiveData = function() {
var dLen = this.recvView.getUint16(7);
if (this.recvCursor < dLen + 9) {
return;
}
var dataBuffer = new Uint8Array(dLen + 9);
dataBuffer.set(this.recvBuffer.subarray(0, dLen + 9));
if (showDebugLog) {
logln("recv: " + buf2hex(dataBuffer.buffer));
}
var realCrc = calcCRC(dataBuffer, 6, dLen + 7);
var crc = dataBuffer[dLen+7] * 256 + dataBuffer[dLen+8];
if (crc != realCrc) {
logln("invalid crc " + crc + " ,real= " + realCrc);
}else {
var packet = new Packet().fromDataBuffer(dataBuffer);
this.onReceive.dispatch(packet);
}
if (this.recvCursor > dLen + 9) {
dataBuffer = new Uint8Array(this.recvCursor - dLen - 6);
dataBuffer.set(this.recvBuffer.subarray(dLen + 9, this.recvCursor));
this.recvBuffer.fill(0);
this.recvBuffer.set(dataBuffer);
this.recvCursor -= dLen + 9;
this._dispathReceiveData();
}else {
this.recvCursor = 0;
this.recvBuffer.fill(0);
}
}
SerialConnection.prototype.onReceiveError = function(errorInfo) {
if (errorInfo.connectionId === this.connectionId) {
this.onError.dispatch(errorInfo.error);
}
};
SerialConnection.prototype.update = function(conf, cb) {
if (!this.connectionId) {return;}
serial.update(this.connectionId, conf, cb);
}
SerialConnection.prototype.connect = function(path, bitrate=57600) {
this.clearRecvData();
this.bitrate = bitrate;
serial.connect(path, { bitrate: this.bitrate },this.onConnectComplete.bind(this))
};
SerialConnection.prototype.send = function(packet) {
if (this.connectionId < 0) {
throw 'Invalid connection';
}
var data = packet.getDataBuffer();
if (showDebugLog) {
logln("send: " + buf2hex(data));
}
serial.send(this.connectionId, data, function() {});
};
SerialConnection.prototype.disconnect = function() {
if (this.connectionId < 0) {
throw 'Invalid connection';
}
serial.disconnect(this.connectionId, function() {});
};
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
function logln(msg) {
var buffer = document.querySelector('#buffer');
buffer.innerHTML += msg + '<br/>';
var msgEnd = document.querySelector('#msg_end');
msgEnd.scrollIntoView();
}
function log(msg) {
var buffer = document.querySelector('#buffer');
buffer.innerHTML += msg;
var msgEnd = document.querySelector('#msg_end');
msgEnd.scrollIntoView();
}
function buf2hex(buffer) {
return '0x' + Array.prototype.map.call(new Uint8Array(buffer), x => ('0x00' + x.toString(16)).slice(-2)).join(' 0x');
}
function calcCRC(buffer, start, end) {
var crc = 0;
for (var i = start; i < end; i++) {
crc += buffer[i] & 0xff;
}
return crc & 0xffff;
}
const PacketTypeCmd = 0x01;
const PacketTypeData = 0x02;
const PacketTypeDataEnd = 0x08;
const PacketTypeCmdResp = 0x07;
const PacketTypeDataResp = 0x09;
var Packet = function(data=new Uint8Array([0x35]), dataLen=1, type=PacketTypeCmd) {
this.dataBuffer = new Uint8Array(512);
this.dataBuffer.set([0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]);
this.type = type;
this.dataLen = dataLen;
this.data = data;
this.result = 0;
}
Packet.prototype.setCmd = function(cmd) {
this.type = PacketTypeCmd;
this.data = Uint8Array.of(cmd);
this.dataLen = 1;
}
Packet.prototype.getDataBuffer = function () {
var dataView = new DataView(this.dataBuffer.buffer);
dataView.setUint8(6, this.type);
var len = this.dataLen + 2;
dataView.setUint16(7, len);
this.dataBuffer.set(this.data, 9);
var crc = calcCRC(this.dataBuffer, 6, this.dataLen + 9);
dataView.setUint16(9 + this.dataLen, crc);
return new Uint8Array(this.dataBuffer.buffer, 0, this.dataLen + 11);
}
Packet.prototype.fromDataBuffer = function(buffer) {
this.dataBuffer.set(buffer);
var dataView = new DataView(this.dataBuffer.buffer);
this.type = dataView.getUint8(6);
var len = dataView.getUint16(7);
this.dataLen = len - 2;
this.data = new Uint8Array(buffer.buffer, 9, this.dataLen);
if (this.type == PacketTypeCmdResp) {
this.result = this.data[0];
}
return this;
}
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
var curDevice = null;
function tryHandshake(device) {
return new Promise((resolve, reject) =>{
logln("try handshake with " + device.path);
var connection = new SerialConnection();
var isValidDevice = 0;
device.bitrate = 57600;
connection.onConnect.addListener(function() {
logln("device " + device.path + " connected");
connection.send(new Packet());
});
connection.onReceive.addListener(function(packet) {
if (packet.type == PacketTypeCmdResp && packet.result == 0) {
isValidDevice = 1;
connection.disconnect();
resolve(1)
}
});
connection.connect(device.path, device.bitrate);
setTimeout(() => {
if (isValidDevice) {
}else {
device.bitrate = 115200;
connection.update({
bitrate: device.bitrate
}, (result) => {
if (result) {
connection.send(new Packet());
setTimeout(() => {
connection.disconnect();
if (!isValidDevice) {
resolve(0);
}
}, 500);
}else {
connection.disconnect();
resolve(0);
}
})
}
}, 500);
})
}
async function checkDevices(devices) {
for (var device of devices) {
logln("found device, path = " + device.path);
var res = await tryHandshake(device);
if (res) {
curDevice = device;
logln("found valid device " + device.path);
break;
}
}
}
////////////////////////////////////////////////////////
var EnrollSchedule = function(device, enrollCount=6, callback=((err=null, step=0, state=0, data=null)=>{}), timeout = 60 * 1000) {
this.step = 0;
this.enrollCount = enrollCount;
this.callback = callback;
this.device = device;
this.connection = null;
this.timeout = timeout;
this.timeoutFlag = 0;
this.responseTime = 1000;
this.responseTimeout = 0;
this.responseCallback = null;
this.canceled = false;
}
const STATE_WAIT_FINGER_DOWN = 1;
const STATE_WAIT_FINGER_LEAVE = 2;
const STATE_FINGER_DOWN = 3;
const STATE_FINGER_LEAVE = 4;
const STATE_EXTRACT_TEMPLATE = 5;
const STATE_DOWNLOAD_TEMPLATE = 6;
const STATE_EXTRACT_TEMPLATE_FAIL = 100;
const STATE_EXTRACT_TEMPLATE_DIRTY = 101;
const STATE_EXTRACT_TEMPLATE_POINTS_FEW = 102;
const STATE_EXTRACT_TEMPLATE_MERGE_FAIL = 103;
const ErrorReceiveDataErr = 1;
const ErrorEnrollTimeout = 2;
const ErrorDeviceNotFound = 3;
const ErrorEmptyFail = 4;
function printError(err) {
logln( "enroll err with code: " + err);
}
EnrollSchedule.prototype.start = async function() {
this.step = 0;
this.canceled = false;
try {
await this._connect();
if(this.canceled) { return this._disConnect(); }
var ret = await this._sendAndWaitRecvCmd(0x0d);
if (ret == 0x11) {
throw ErrorEmptyFail;
}
while(this.step < this.enrollCount) {
this.step += 1;
ret = await this._enrollOne(this.step);
if (ret) {
let stateErr = STATE_EXTRACT_TEMPLATE_FAIL;
if(ret == 0x06) {
stateErr = STATE_EXTRACT_TEMPLATE_DIRTY;
}else if (ret == 0x07) {
stateErr = STATE_EXTRACT_TEMPLATE_POINTS_FEW;
}else if (ret == 0x0a) {
stateErr = STATE_EXTRACT_TEMPLATE_MERGE_FAIL;
}
this.callback(null, this.step, stateErr, null);
this.step -= 1;
}
if(this.canceled) { return this._disConnect(); }
}
logln("receive tempalte");
this.callback(null, this.step, STATE_DOWNLOAD_TEMPLATE, null);
var ret = await this._mergeTemplate();
if(this.canceled) { return this._disConnect(); }
var recvBuffer = await this._receiveTemplate();
if(this.canceled) { return this._disConnect(); }
this.callback(null, this.step, 0, recvBuffer);
}catch(e) {
this.callback(e, this.step, 0, null);
}
this._disConnect();
}
EnrollSchedule.prototype._mergeTemplate = function() {
return this._sendAndWaitRecvCmd(0x05);
}
EnrollSchedule.prototype._receiveTemplate = function() {
return new Promise((resolve, reject) => {
var that = this;
var data = Uint8Array.of(0x08, 0x01);
var packet = new Packet(data, 2);
var recvDataLen = 4 * 1024 * 1024;
var recvData = new Uint8Array(recvDataLen);
var recvDataCursor = 0;
var resetTimeoutCheck = function() {
if (that.responseTimeout) {
clearTimeout(that.responseTimeout);
}
that.responseTimeout = setTimeout(() => {
var dummy = new Packet();
that.connection.send(dummy);
that.responseTimeout = setTimeout(() => {
reject(ErrorReceiveDataErr);
}, that.responseTime);
}, that.responseTime);
}
this.responseCallback = (packet) => {
resetTimeoutCheck();
if (packet.type == PacketTypeCmdResp) {
}else if (packet.type == PacketTypeData || packet.type == PacketTypeDataEnd) {
if (recvDataCursor + packet.dataLen < recvDataLen) {
recvData.set(packet.data, recvDataCursor);
recvDataCursor += packet.dataLen;
}else {
if (that.responseTimeout) {
clearTimeout(that.responseTimeout);
}
reject("recv buffer full");
}
}
if (packet.type == PacketTypeDataEnd) {
if (that.responseTimeout) {
clearTimeout(that.responseTimeout);
}
resolve(recvData.slice(0, recvDataCursor));
}
}
this.connection.send(packet);
resetTimeoutCheck();
});
}
EnrollSchedule.prototype._sendAndWaitRecvCmd = function(cmd) {
return new Promise((resolve, reject) =>{
var packet = new Packet();
packet.setCmd(cmd);
this._sendAndWaitRecv(packet).then(packet => {
if (packet.type == PacketTypeCmdResp) {
resolve(packet.result);
}
}).catch(err => {
reject(err);
});
});
}
EnrollSchedule.prototype._enrollOne = async function(step) {
var down = false;
var leave = false;
var isTimeout = false;
this.timeoutFlag = setTimeout(() => {
if (!down) {
isTimeout = true;
}
}, this.timeout);
//wait finger leave
logln("wait leave")
this.callback(null, this.step, STATE_WAIT_FINGER_LEAVE, null);
while (leave == false && !isTimeout) {
if(this.canceled) { return; }
leave = !(await this.captureOne());
}
this.callback(null, this.step, STATE_FINGER_LEAVE, null);
if (isTimeout) {
throw ErrorEnrollTimeout;
}
this.callback(null, this.step, STATE_WAIT_FINGER_DOWN, null);
//wait finger down
logln("wait down")
while (!down && !isTimeout) {
if(this.canceled) { return; }
down = await this.captureOne();
}
if (isTimeout) {
throw ErrorEnrollTimeout;
}
this.callback(null, this.step, STATE_FINGER_DOWN, null);
logln("finger down step = " + step);
if(this.canceled) { return; }
this.callback(null, this.step, STATE_EXTRACT_TEMPLATE, null);
var ret = await this.extractOne(step);
if (ret != 0) {
logln("extract tempate err " + ret);
return ret;
}
return 0;
}
EnrollSchedule.prototype.extractOne = function(step) {
return new Promise((resolve, reject) =>{
var data = Uint8Array.of(0x02, step);
var packet = new Packet(data, 2);
this._sendAndWaitRecv(packet).then(packet => {
if (packet.type == PacketTypeCmdResp) {
resolve(packet.result);
}
}).catch(err => {
reject(err);
});
});
}
EnrollSchedule.prototype.captureOne = function() {
return new Promise((resolve, reject) => {
var packet = new Packet();
packet.setCmd(0x01);
this._sendAndWaitRecv(packet).then(packet => {
if (packet.type == PacketTypeCmdResp) {
resolve(packet.result == 0);
}
}).catch(err => {
reject(err);
});
});
}
EnrollSchedule.prototype._sendAndWaitRecv = function(packet) {
return new Promise((resolve, reject) => {
var that = this;
this.responseCallback = (packet) => {
if (packet.type == PacketTypeCmdResp) {
if (that.responseTimeout) {
clearTimeout(that.responseTimeout);
that.responseTimeout = 0;
}
if (packet.result == 0x01) {
reject(ErrorReceiveDataErr);
}else {
resolve(packet);
}
}
}
this.connection.send(packet);
this.responseTimeout = setTimeout(() => {
that.connection.send(packet);
this.responseTimeout = setTimeout(() => {
reject(ErrorReceiveDataErr);
}, this.responseTime);
}, this.responseTime);
});
}
EnrollSchedule.prototype._resolvePacket = function(packet) {
if (this.responseCallback) {
this.responseCallback(packet);
}
}
EnrollSchedule.prototype._connect = function() {
return new Promise((resolve, reject) => {
var that = this;
this.connection = new SerialConnection();
this.connection.onConnect.addListener(function() {
logln("device " + that.device.path + " connected");
resolve();
});
this.connection.onReceive.addListener(function(packet) {
that._resolvePacket(packet);
});
this.connection.connect(this.device.path, this.device.bitrate);
setTimeout(() => {
reject("connect timeout");
}, 500);
});
}
EnrollSchedule.prototype._disConnect = function() {
if (this.connection) {
this.connection.disconnect();
this.connection = null;
}
if (this.responseTimeout) {
clearTimeout(this.responseTimeout);
this.responseTimeout = 0;
}
if (this.timeoutFlag) {
clearTimeout(this.timeoutFlag);
this.timeoutFlag = 0;
}
}
EnrollSchedule.prototype.stop = function() {
this.canceled = true;
}
var enrollSchedule = null;
var tempData = null;
function startEnroll(enrollCount=6, timeout=10*1000, cb) {
if (!curDevice) {
logln("device not found");
cb.call(null, {
err: ErrorDeviceNotFound
}, 0, null);
return;
}
enrollSchedule = new EnrollSchedule(curDevice, enrollCount, (err, step, state, data) => {
if (err) {
printError(status.err);
}
if(cb) {
cb.call(null, {
err: err,
state: state,
step: step,
data: data
});
}
if (data) {
tempData = data;
}
}, timeout);
logln("start enroll");
enrollSchedule.start();
}
function stopEnroll() {
if (enrollSchedule) {
enrollSchedule.stop();
enrollSchedule = null;
}
}
////////////////////////////////////////////////////////
//test
EnrollSchedule.prototype.sleep = function(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
}
EnrollSchedule.prototype.downloadTemplate = async function(data) {
var cmdData = Uint8Array.of(0x09, 0x02);
var packet = new Packet(cmdData, 2);
this.connection.send(packet);
await this.sleep(1000);
var dataLength = data.length;
var packetLen = 256;
var sendCursor = 0;
var sendLen = 0;
var sendType = PacketTypeData;
logln("downloading");
while (sendCursor < dataLength) {
sendLen = (dataLength-sendCursor > packetLen) ? packetLen : (dataLength-sendCursor);
sendType = (dataLength-sendCursor > packetLen) ? PacketTypeData : PacketTypeDataEnd;
var sendData = new Uint8Array(data.buffer, sendCursor, sendLen);
var dataPack = new Packet(sendData, sendLen, sendType);
this.connection.send(dataPack);
console.log("send "+ sendLen)
log('.');
sendCursor += sendLen;
await this.sleep(100);
}
cmdData = Uint8Array.of(0x06, 0x02, 0x00, 0x03);
packet = new Packet(cmdData, 4);
this.connection.send(packet);
logln('.');
await this.sleep(500);
}
async function downloadTemplate() {
if (!curDevice) {
var err = "device not found";
logln(err);
return;
}
if (!tempData) {
var err = "please enroll";
logln(err);
return;
}
var enroll = new EnrollSchedule(curDevice);
try {
await enroll._connect();
await enroll.downloadTemplate(tempData);
logln("download complete");
}catch(err) {
logln("download err: " + err);
}
await enroll._disConnect();
}
async function matchTemplate() {
if (!curDevice) {
var err = "device not found";
logln(err);
return;
}
var enroll = new EnrollSchedule(curDevice);
try {
await enroll._connect();
await enroll._enrollOne(1);
var packData = Uint8Array.of(0x04, 0x01, 0x00, 0x03, 0x00, 0x03);
var packet = new Packet(packData, 6);
await new Promise((resolve, reject) =>{
enroll._sendAndWaitRecv(packet).then(packet => {
if (packet.type == PacketTypeCmdResp) {
if(packet.result) {
logln("match fail");
}else {
logln("match success score " + (packet.data[3] * 256 + packet.data[4]));
}
resolve();
}
}).catch(err => {
reject("match err: " + err);
});
})
}catch(err) {
logln("download err: " + err);
}
await enroll._disConnect();
}
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
function disableAll() {
document.querySelector("#enroll").disabled = true;
document.querySelector("#down").disabled = true;
document.querySelector("#match").disabled = true;
document.querySelector("#refresh").disabled = true;
document.querySelector("#export").disabled = true;
document.querySelector("#import").disabled = true;
}
function enableAll() {
document.querySelector("#enroll").disabled = false;
document.querySelector("#down").disabled = false;
document.querySelector("#match").disabled = false;
document.querySelector("#refresh").disabled = false;
document.querySelector("#export").disabled = false;
document.querySelector("#import").disabled = false;
}
var server = null;
onload = function() {
document.querySelector('#show-log').checked = showDebugLog;
document.querySelector('#show-log').onchange = function(e) {
showDebugLog = e.target.checked;
}
document.querySelector('#enroll').onclick = function(e) {
if (e.currentTarget.innerText == "Enroll") {
e.currentTarget.innerText = "Stop";
startEnroll(6, 10* 1000, (status) => {
console.log(status.step);
if (status.err) {
console.log(status.err);
}
if (status.err || status.data) {
document.querySelector('#enroll').innerText = "Enroll";
}
if (status.data) {
// console.log(data);
// console.log(buf2hex(data.buffer));
}
});
}else {
e.currentTarget.innerText = "Enroll";
stopEnroll();
}
}
document.querySelector('.msg').style="height:" + (window.innerHeight - 70) + "px";
chrome.serial.getDevices((devices) => {
checkDevices(devices);
});
document.querySelector("#down").onclick = async function(e) {
disableAll();
try {
await downloadTemplate();
}catch(err) {
logln("download err: " + err);
}
enableAll();
}
document.querySelector("#match").onclick = async function(e) {
disableAll();
try {
await matchTemplate();
}catch(err) {
logln("match err: " + err);
}
enableAll();
}
document.querySelector("#refresh").onclick = function(e) {
disableAll();
chrome.serial.getDevices(async function(devices) {
try {
await checkDevices(devices);
}catch (e) {
console.log(e)
}
enableAll();
});
}
document.querySelector("#export").onclick = function(e) {
if (!tempData) {
logln("please enroll");
return;
}
let reader = new FileReader();
reader.onload = function(eve) {
if (eve.target.readyState == FileReader.DONE)
{
let a = document.createElement('a');
a.download = "mafp_template.bin";
a.href = this.result;
a.click();
}
}
reader.readAsDataURL(new Blob([tempData]));
}
document.querySelector("#import").onclick = function(e) {
let fileInput = document.querySelector("#import-file");
fileInput.value = "";
fileInput.click();
}
document.querySelector("#import-file").onchange = function(e) {
let files = e.target.files;
if (files && files.length) {
let reader = new FileReader();
reader.onload = async function(ev) {
if (ev.total == 4096) {
tempData = new Uint8Array(this.result);
disableAll();
try {
await downloadTemplate();
}catch(err) {
logln("download err: " + err);
}
enableAll();
}else {
logln("invalid file length " + ev.total);
}
}
reader.readAsArrayBuffer(files[0]);
}
}
const port = 9897;
if (http.Server && http.WebSocketServer) {
server = new http.Server();
var wsServer = new http.WebSocketServer(server);
server.listen(port);
logln("ws socket server listen at " + port);
var connectedSocket = null;
wsServer.addEventListener('request', function(req) {
if (connectedSocket) {
req.reject();
return;
}
console.log('Client connected');
var socket = req.accept();
connectedSocket = socket;
socket.addEventListener('message', function(e) {
var reqData = JSON.parse(e.data);
if (reqData.cmd == "enrollStart") {
startEnroll(reqData.config.enrollCount,
reqData.config.enrollTimeout,
(status) =>{
var resp = {
err: status.err ? status.err : "",
state: status.state ? status.state : 0,
step: status.step
}
if (status.data) {
resp.data = Array.from(status.data);
}
connectedSocket.send(JSON.stringify(resp));
});
}else if (reqData.cmd == "enrollCancel") {
stopEnroll();
}
});
socket.addEventListener('close', function() {
connectedSocket = null;
stopEnroll();
console.log('Client disconnected');
if (chrome.runtime.lastError != undefined) {
console.log(chrome.runtime.lastError.message);
}
});
return true;
});
}
};
onresize = function(e) {
document.querySelector('.msg').style="height:" + (e.currentTarget.innerHeight - 70) + "px";
document.querySelector('#msg_end').scrollIntoView();
}

+ 30
- 0
dist/static/equipment/mafp_serial/plugin/manifest.json View File

@ -0,0 +1,30 @@
{
"name": "MAFP Serial",
"version": "1.0",
"manifest_version": 2,
"minimum_chrome_version": "23",
"description": "microarray fingerprint serial control.",
"icons":
{
"48": "logo.png",
"128": "logo.png"
},
"app": {
"background": {
"scripts": [ "background.js" ]
}
},
"sockets": {
"tcp": {
"connect": "*"
},
"tcpServer": {
"listen": "*"
}
},
"permissions": [
"serial"
]
}

+ 232
- 0
dist/static/equipment/mafp_serial/plugin/sha1.js View File

@ -0,0 +1,232 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2005 Google Inc. All Rights Reserved.
/**
* @fileoverview SHA-1 cryptographic hash.
* Variable names follow the notation in FIPS PUB 180-3:
* http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
*
* Usage:
* var sha1 = new goog.crypt.sha1();
* sha1.update(bytes);
* var hash = sha1.digest();
*
*/
/**
* SHA-1 cryptographic hash constructor.
*
* The properties declared here are discussed in the above algorithm document.
* @constructor
*/
var Sha1 = function() {
/**
* Holds the previous values of accumulated variables a-e in the compress_
* function.
* @type {Array.<number>}
* @private
*/
this.chain_ = [];
/**
* A buffer holding the partially computed hash result.
* @type {Array.<number>}
* @private
*/
this.buf_ = [];
/**
* An array of 80 bytes, each a part of the message to be hashed. Referred to
* as the message schedule in the docs.
* @type {Array.<number>}
* @private
*/
this.W_ = [];
/**
* Contains data needed to pad messages less than 64 bytes.
* @type {Array.<number>}
* @private
*/
this.pad_ = [];
this.pad_[0] = 128;
for (var i = 1; i < 64; ++i) {
this.pad_[i] = 0;
}
this.reset();
};
/**
* Resets the internal accumulator.
*/
Sha1.prototype.reset = function() {
this.chain_[0] = 0x67452301;
this.chain_[1] = 0xefcdab89;
this.chain_[2] = 0x98badcfe;
this.chain_[3] = 0x10325476;
this.chain_[4] = 0xc3d2e1f0;
this.inbuf_ = 0;
this.total_ = 0;
};
/**
* Internal helper performing 32 bit left rotate.
* @return {number} w rotated left by r bits.
* @private
*/
Sha1.prototype.rotl_ = function(w, r) {
return ((w << r) | (w >>> (32 - r))) & 0xffffffff;
};
/**
* Internal compress helper function.
* @param {Array} buf containing block to compress.
* @private
*/
Sha1.prototype.compress_ = function(buf) {
var W = this.W_;
// get 16 big endian words
for (var i = 0; i < 64; i += 4) {
var w = (buf[i] << 24) |
(buf[i + 1] << 16) |
(buf[i + 2] << 8) |
(buf[i + 3]);
W[i / 4] = w;
}
// expand to 80 words
for (var i = 16; i < 80; i++) {
W[i] = this.rotl_(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
}
var a = this.chain_[0];
var b = this.chain_[1];
var c = this.chain_[2];
var d = this.chain_[3];
var e = this.chain_[4];
var f, k;
for (var i = 0; i < 80; i++) {
if (i < 40) {
if (i < 20) {
f = d ^ (b & (c ^ d));
k = 0x5a827999;
} else {
f = b ^ c ^ d;
k = 0x6ed9eba1;
}
} else {
if (i < 60) {
f = (b & c) | (d & (b | c));
k = 0x8f1bbcdc;
} else {
f = b ^ c ^ d;
k = 0xca62c1d6;
}
}
var t = (this.rotl_(a, 5) + f + e + k + W[i]) & 0xffffffff;
e = d;
d = c;
c = this.rotl_(b, 30);
b = a;
a = t;
}
this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;
this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;
this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;
this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;
this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;
};
/**
* Adds a byte array to internal accumulator.
* @param {Array.<number>} bytes to add to digest.
* @param {number} opt_length is # of bytes to compress.
*/
Sha1.prototype.update = function(bytes, opt_length) {
if (!opt_length) {
opt_length = bytes.length;
}
var n = 0;
// Optimize for 64 byte chunks at 64 byte boundaries.
if (this.inbuf_ == 0) {
while (n + 64 < opt_length) {
this.compress_(bytes.slice(n, n + 64));
n += 64;
this.total_ += 64;
}
}
while (n < opt_length) {
this.buf_[this.inbuf_++] = bytes[n++];
this.total_++;
if (this.inbuf_ == 64) {
this.inbuf_ = 0;
this.compress_(this.buf_);
// Pick up 64 byte chunks.
while (n + 64 < opt_length) {
this.compress_(bytes.slice(n, n + 64));
n += 64;
this.total_ += 64;
}
}
}
};
/**
* @return {Array} byte[20] containing finalized hash.
*/
Sha1.prototype.digest = function() {
var digest = [];
var totalBits = this.total_ * 8;
// Add pad 0x80 0x00*.
if (this.inbuf_ < 56) {
this.update(this.pad_, 56 - this.inbuf_);
} else {
this.update(this.pad_, 64 - (this.inbuf_ - 56));
}
// Add # bits.
for (var i = 63; i >= 56; i--) {
this.buf_[i] = totalBits & 255;
totalBits >>>= 8;
}
this.compress_(this.buf_);
var n = 0;
for (var i = 0; i < 5; i++) {
for (var j = 24; j >= 0; j -= 8) {
digest[n++] = (this.chain_[i] >> j) & 255;
}
}
return digest;
};

+ 32
- 0
dist/static/equipment/mafp_serial/plugin/style.css View File

@ -0,0 +1,32 @@
body {
font-family: "Helvetica Neue", Helvetica, sans-serif;
font-size: 13px;
width: 100%;
height: 100%;;
margin: 0;
}
html {
width: 100%;
height: 100%;;
}
#buffer {
line-height: 20px;
}
.msg {
overflow: auto;
padding: 20px;
}
.buttons {
position: absolute;
bottom: 0;
display: flex;
align-items: center;
justify-content: flex-start;
height: 50px;
}
button {
margin-left: 20px;
}

BIN
dist/static/equipment/mafp_serial/press.mp3 View File


BIN
dist/static/equipment/mafp_serial/up.mp3 View File


BIN
dist/static/equipment/mafp_serial/指纹采集器软件通信流程.doc View File


+ 2
- 0
dist/static/favicon.ico View File

@ -0,0 +1,2 @@
<br />
<b>Warning</b>: readfile(): Filename cannot be empty in <b>/www/wwwroot/51tool.com/ico/download.php</b> on line <b>17</b><br />

BIN
dist/static/fonts/element-icons.535877f.woff View File


BIN
dist/static/fonts/element-icons.732389d.ttf View File


BIN
dist/static/fonts/iconfont.5dd52cc.woff View File


BIN
dist/static/fonts/iconfont.7e75b66.woff2 View File


BIN
dist/static/fonts/iconfont.acc85de.ttf View File


+ 3
- 0
dist/static/global.json View File

@ -0,0 +1,3 @@
{
"tenantId": "200,300,400"
}

BIN
dist/static/img/alert.f2fea34.png View File

Before After
Width: 300  |  Height: 200  |  Size: 10 KiB

BIN
dist/static/img/beijingtu01.f8608d7.png View File

Before After
Width: 1890  |  Height: 1417  |  Size: 641 KiB

BIN
dist/static/img/beijingtu24.b50f73c.jpg View File

Before After
Width: 1700  |  Height: 1275  |  Size: 225 KiB

BIN
dist/static/img/bgBox.719f731.png View File

Before After
Width: 502  |  Height: 261  |  Size: 17 KiB

BIN
dist/static/img/bgfixed.15a99f0.jpg View File

Before After
Width: 1920  |  Height: 1080  |  Size: 103 KiB

BIN
dist/static/img/dd.c03303f.gif View File

Before After
Width: 2000  |  Height: 2000  |  Size: 133 KiB

BIN
dist/static/img/logo1.38f1073.png View File

Before After
Width: 770  |  Height: 430  |  Size: 15 KiB

BIN
dist/static/img/logo2.0754d14.png View File

Before After
Width: 770  |  Height: 430  |  Size: 10 KiB

BIN
dist/static/img/mapbg.2f52c08.png View File

Before After
Width: 780  |  Height: 467  |  Size: 21 KiB

BIN
dist/static/img/no-rooms.dfc2fbf1.dfc2fbf.png View File

Before After
Width: 584  |  Height: 352  |  Size: 74 KiB

BIN
dist/static/img/pageBg.f9f9dcd.png View File

Before After
Width: 1920  |  Height: 1080  |  Size: 289 KiB

BIN
dist/static/img/product1.94f4481.png View File

Before After
Width: 794  |  Height: 730  |  Size: 190 KiB

BIN
dist/static/img/product10.be88006.png View File

Before After
Width: 300  |  Height: 295  |  Size: 28 KiB

BIN
dist/static/img/product2.6175ede.png View File

Before After
Width: 338  |  Height: 349  |  Size: 90 KiB

BIN
dist/static/img/product3.0ba44dd.png View File

Before After
Width: 299  |  Height: 384  |  Size: 33 KiB

BIN
dist/static/img/product4.ed5b542.png View File

Before After
Width: 419  |  Height: 474  |  Size: 182 KiB

BIN
dist/static/img/product5.88c5ef6.png View File

Before After
Width: 1036  |  Height: 584  |  Size: 505 KiB

BIN
dist/static/img/product6.23e10b2.png View File

Before After
Width: 400  |  Height: 400  |  Size: 26 KiB

BIN
dist/static/img/product7.de38d89.png View File

Before After
Width: 550  |  Height: 509  |  Size: 61 KiB

BIN
dist/static/img/product8.4d433d8.png View File

Before After
Width: 300  |  Height: 295  |  Size: 42 KiB

BIN
dist/static/img/product9.100a788.png View File

Before After
Width: 416  |  Height: 418  |  Size: 43 KiB

BIN
dist/static/img/red.6dbe9e9.gif View File

Before After
Width: 112  |  Height: 112  |  Size: 656 KiB

BIN
dist/static/img/topbg.820ebf9.png View File

Before After
Width: 1920  |  Height: 1080  |  Size: 22 KiB

BIN
dist/static/img/yellow.762c207.gif View File

Before After
Width: 112  |  Height: 112  |  Size: 720 KiB

+ 10274
- 0
dist/static/js/0.2aa86481213c7a5ffc5e.js
File diff suppressed because it is too large
View File


+ 3170
- 0
dist/static/js/1.6509e5523c4acd63d661.js
File diff suppressed because it is too large
View File


+ 622
- 0
dist/static/js/10.b76c738e1897991df5e1.js
File diff suppressed because it is too large
View File


+ 32
- 0
dist/static/js/100.b06af9d3849781624c1b.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/101.752ae74e0b5776b02cef.js
File diff suppressed because it is too large
View File


+ 32
- 0
dist/static/js/102.bd2b09fcdb0fc921ce0f.js
File diff suppressed because it is too large
View File


+ 32
- 0
dist/static/js/103.4620884103b690a2d101.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/104.0098f9c85ecc7e2a06bb.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/105.35dcf6f8b99bd44a9ce4.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/106.3da7311810b8afa9dda6.js
File diff suppressed because it is too large
View File


+ 32
- 0
dist/static/js/107.065b65fa197e1140e1a6.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/108.132f68c23ee6697fb922.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/109.cc20db0661a2380e2ce9.js
File diff suppressed because it is too large
View File


+ 583
- 0
dist/static/js/11.f8a88a805a4cc2ebdadc.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/110.cc9abf3baf77be63bd8d.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/111.26a887a7ac9349204d4e.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/112.074ea4fa9a376f967638.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/113.98971d8a44acdf4e1776.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/114.16708a12a3468bd674f6.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/115.f68058217804647ef908.js
File diff suppressed because it is too large
View File


+ 58
- 0
dist/static/js/116.84bc60701df5f739bd33.js
File diff suppressed because it is too large
View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save