├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── README.md
├── build
├── build.js
├── check-versions.js
├── dev-client.js
├── dev-server.js
├── utils.js
├── vue-loader.conf.js
├── webpack.base.conf.js
├── webpack.dev.conf.js
├── webpack.prod.conf.js
└── webpack.test.conf.js
├── config
├── dev.env.js
├── index.js
├── prod.env.js
└── test.env.js
├── index.html
├── package.json
├── server
├── api
│ ├── assetApi.js
│ ├── callApi.js
│ ├── exportApi.js
│ ├── importApi.js
│ ├── resourceApi.js
│ ├── searchApi.js
│ ├── styles.xml
│ ├── uploadApi.js
│ └── userApi.js
├── conf
│ └── db.js
├── controller
│ └── user.js
├── index.js
├── middleware
│ ├── checkToken.js
│ └── createToken.js
├── models
│ ├── asset.js
│ ├── call.js
│ ├── export.js
│ ├── resource.js
│ ├── search.js
│ └── user.js
├── public
│ └── test.jpg
├── schema
│ ├── assets.js
│ ├── dictionarys.js
│ ├── resource.js
│ └── users.js
├── sql
│ └── sqlString.js
├── styles.xml
├── uploads
│ ├── avatar-1494579693303.jpeg
│ ├── avatar-1494635642596.jpeg
│ └── avatar-1494653671089.jpeg
└── util
│ ├── log.js
│ └── util.js
├── sql
└── ams.sql
├── src
├── App.vue
├── api
│ └── index.js
├── axios.js
├── components
│ ├── Hello.vue
│ ├── asset
│ │ ├── Addasset.vue
│ │ ├── Callasset.vue
│ │ ├── CallassetCheck.vue
│ │ ├── QueryAllAsset.vue
│ │ ├── Queryasset.vue
│ │ └── expand
│ │ │ └── Expand.vue
│ ├── common
│ │ ├── Footer.vue
│ │ ├── Header.vue
│ │ └── Sidebar.vue
│ ├── dashboard
│ │ └── Dashboard.vue
│ ├── index
│ │ └── Index.vue
│ ├── login
│ │ └── Login.vue
│ ├── personal
│ │ └── Personal.vue
│ ├── resource
│ │ └── Resource.vue
│ └── user
│ │ └── User.vue
├── lib
│ ├── auth.js
│ └── vue-cookie.js
├── main.js
├── router
│ └── index.js
└── store
│ ├── actions.js
│ ├── getters.js
│ ├── index.js
│ ├── modules
│ ├── login.js
│ └── user.js
│ ├── mutations.js
│ └── types.js
├── static
├── .gitkeep
├── css
│ ├── main.css
│ └── reset.css
└── images
│ ├── favicon.ico
│ ├── logo.png
│ └── mac.png
└── test
├── e2e
├── custom-assertions
│ └── elementCount.js
├── nightwatch.conf.js
├── runner.js
└── specs
│ └── test.js
└── unit
├── .eslintrc
├── index.js
├── karma.conf.js
└── specs
└── Hello.spec.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", { "modules": false }],
4 | "stage-2"
5 | ],
6 | "plugins": ["transform-runtime"],
7 | "comments": false,
8 | "env": {
9 | "test": {
10 | "presets": ["env", "stage-2"],
11 | "plugins": [ "istanbul" ]
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*.js
2 | config/*.js
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // http://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parser: 'babel-eslint',
6 | parserOptions: {
7 | sourceType: 'module'
8 | },
9 | env: {
10 | browser: true,
11 | },
12 | // required to lint *.vue files
13 | plugins: [
14 | 'html'
15 | ],
16 | // add your custom rules here
17 | 'rules': {
18 | // allow debugger during development
19 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log
5 | yarn-error.log
6 | test/unit/coverage
7 | test/e2e/reports
8 | selenium-debug.log
9 |
10 |
11 | # Created by https://www.gitignore.io/api/visualstudiocode,windows,macos,node
12 |
13 | ### macOS ###
14 | *.DS_Store
15 | .AppleDouble
16 | .LSOverride
17 |
18 | # Icon must end with two \r
19 | Icon
20 |
21 |
22 | # Thumbnails
23 | ._*
24 |
25 | # Files that might appear in the root of a volume
26 | .DocumentRevisions-V100
27 | .fseventsd
28 | .Spotlight-V100
29 | .TemporaryItems
30 | .Trashes
31 | .VolumeIcon.icns
32 | .com.apple.timemachine.donotpresent
33 |
34 | # Directories potentially created on remote AFP share
35 | .AppleDB
36 | .AppleDesktop
37 | Network Trash Folder
38 | Temporary Items
39 | .apdisk
40 |
41 | ### Node ###
42 | # Logs
43 | logs
44 | *.log
45 | npm-debug.log*
46 | yarn-debug.log*
47 | yarn-error.log*
48 |
49 | # Runtime data
50 | pids
51 | *.pid
52 | *.seed
53 | *.pid.lock
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul
59 | coverage
60 |
61 | # nyc test coverage
62 | .nyc_output
63 |
64 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
65 | .grunt
66 |
67 | # Bower dependency directory (https://bower.io/)
68 | bower_components
69 |
70 | # node-waf configuration
71 | .lock-wscript
72 |
73 | # Compiled binary addons (http://nodejs.org/api/addons.html)
74 | build/Release
75 |
76 | # Dependency directories
77 | node_modules/
78 | jspm_packages/
79 |
80 | # Typescript v1 declaration files
81 | typings/
82 |
83 | # Optional npm cache directory
84 | .npm
85 |
86 | # Optional eslint cache
87 | .eslintcache
88 |
89 | # Optional REPL history
90 | .node_repl_history
91 |
92 | # Output of 'npm pack'
93 | *.tgz
94 |
95 | # Yarn Integrity file
96 | .yarn-integrity
97 |
98 | # dotenv environment variables file
99 | .env
100 |
101 |
102 | ### VisualStudioCode ###
103 | .vscode/*
104 | !.vscode/settings.json
105 | !.vscode/tasks.json
106 | !.vscode/launch.json
107 | !.vscode/extensions.json
108 |
109 | ### Windows ###
110 | # Windows thumbnail cache files
111 | Thumbs.db
112 | ehthumbs.db
113 | ehthumbs_vista.db
114 |
115 | # Folder config file
116 | Desktop.ini
117 |
118 | # Recycle Bin used on file shares
119 | $RECYCLE.BIN/
120 |
121 | # Windows Installer files
122 | *.cab
123 | *.msi
124 | *.msm
125 | *.msp
126 |
127 | # Windows shortcuts
128 | *.lnk
129 |
130 | # idea
131 | .idea/
132 |
133 | # End of https://www.gitignore.io/api/visualstudiocode,windows,macos,node
134 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | // to edit target browsers: use "browserlist" field in package.json
6 | "autoprefixer": {}
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ams
2 |
3 | > A Vue.js project for asset management system
4 | > 一个基于Vue.js+Node.js+MySQL的资产管理系统
5 |
6 | 前端采用Element-UI框架、后端采用Express框架。此项目实现了以下功能
7 |
8 | 1.用户管理(用户登录、删除、基本信息修改)
9 |
10 | 2.资产管理(资产增加、上传图片、资产申报、资产调用、资产导出)
11 |
12 | 3.字典管理(增加字典)
13 |
14 | 4....
15 |
16 | ## Build Setup
17 |
18 | ``` bash
19 | # install dependencies
20 | npm install
21 |
22 | # serve with hot reload at localhost:8080
23 | npm run dev
24 |
25 | # build for production with minification
26 | npm run build
27 |
28 | # build for production and view the bundle analyzer report
29 | npm run build --report
30 |
31 | # run unit tests
32 | npm run unit
33 |
34 | # run e2e tests
35 | npm run e2e
36 |
37 | # run all tests
38 | npm test
39 | ```
40 |
41 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
42 |
--------------------------------------------------------------------------------
/build/build.js:
--------------------------------------------------------------------------------
1 | require('./check-versions')()
2 |
3 | process.env.NODE_ENV = 'production'
4 |
5 | var ora = require('ora')
6 | var rm = require('rimraf')
7 | var path = require('path')
8 | var chalk = require('chalk')
9 | var webpack = require('webpack')
10 | var config = require('../config')
11 | var webpackConfig = require('./webpack.prod.conf')
12 |
13 | var spinner = ora('building for production...')
14 | spinner.start()
15 |
16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
17 | if (err) throw err
18 | webpack(webpackConfig, function (err, stats) {
19 | spinner.stop()
20 | if (err) throw err
21 | process.stdout.write(stats.toString({
22 | colors: true,
23 | modules: false,
24 | children: false,
25 | chunks: false,
26 | chunkModules: false
27 | }) + '\n\n')
28 |
29 | console.log(chalk.cyan(' Build complete.\n'))
30 | console.log(chalk.yellow(
31 | ' Tip: built files are meant to be served over an HTTP server.\n' +
32 | ' Opening index.html over file:// won\'t work.\n'
33 | ))
34 | })
35 | })
36 |
--------------------------------------------------------------------------------
/build/check-versions.js:
--------------------------------------------------------------------------------
1 | var chalk = require('chalk')
2 | var semver = require('semver')
3 | var packageConfig = require('../package.json')
4 |
5 | function exec (cmd) {
6 | return require('child_process').execSync(cmd).toString().trim()
7 | }
8 |
9 | var versionRequirements = [
10 | {
11 | name: 'node',
12 | currentVersion: semver.clean(process.version),
13 | versionRequirement: packageConfig.engines.node
14 | },
15 | {
16 | name: 'npm',
17 | currentVersion: exec('npm --version'),
18 | versionRequirement: packageConfig.engines.npm
19 | }
20 | ]
21 |
22 | module.exports = function () {
23 | var warnings = []
24 | for (var i = 0; i < versionRequirements.length; i++) {
25 | var mod = versionRequirements[i]
26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
27 | warnings.push(mod.name + ': ' +
28 | chalk.red(mod.currentVersion) + ' should be ' +
29 | chalk.green(mod.versionRequirement)
30 | )
31 | }
32 | }
33 |
34 | if (warnings.length) {
35 | console.log('')
36 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
37 | console.log()
38 | for (var i = 0; i < warnings.length; i++) {
39 | var warning = warnings[i]
40 | console.log(' ' + warning)
41 | }
42 | console.log()
43 | process.exit(1)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/build/dev-client.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | require('eventsource-polyfill')
3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
4 |
5 | hotClient.subscribe(function (event) {
6 | if (event.action === 'reload') {
7 | window.location.reload()
8 | }
9 | })
10 |
--------------------------------------------------------------------------------
/build/dev-server.js:
--------------------------------------------------------------------------------
1 | require('./check-versions')()
2 |
3 | var config = require('../config')
4 | if (!process.env.NODE_ENV) {
5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
6 | }
7 |
8 | var opn = require('opn')
9 | var path = require('path')
10 | var express = require('express')
11 | var webpack = require('webpack')
12 | var proxyMiddleware = require('http-proxy-middleware')
13 | var webpackConfig = process.env.NODE_ENV === 'testing'
14 | ? require('./webpack.prod.conf')
15 | : require('./webpack.dev.conf')
16 |
17 | // default port where dev server listens for incoming traffic
18 | var port = process.env.PORT || config.dev.port
19 | // automatically open browser, if not set will be false
20 | var autoOpenBrowser = !!config.dev.autoOpenBrowser
21 | // Define HTTP proxies to your custom API backend
22 | // https://github.com/chimurai/http-proxy-middleware
23 | var proxyTable = config.dev.proxyTable
24 |
25 | var app = express()
26 | var compiler = webpack(webpackConfig)
27 |
28 | var devMiddleware = require('webpack-dev-middleware')(compiler, {
29 | publicPath: webpackConfig.output.publicPath,
30 | quiet: true
31 | })
32 |
33 | var hotMiddleware = require('webpack-hot-middleware')(compiler, {
34 | log: () => {}
35 | })
36 | // force page reload when html-webpack-plugin template changes
37 | compiler.plugin('compilation', function (compilation) {
38 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
39 | hotMiddleware.publish({ action: 'reload' })
40 | cb()
41 | })
42 | })
43 |
44 | // proxy api requests
45 | Object.keys(proxyTable).forEach(function (context) {
46 | var options = proxyTable[context]
47 | if (typeof options === 'string') {
48 | options = { target: options }
49 | }
50 | app.use(proxyMiddleware(options.filter || context, options))
51 | })
52 |
53 | // handle fallback for HTML5 history API
54 | app.use(require('connect-history-api-fallback')())
55 |
56 | // serve webpack bundle output
57 | app.use(devMiddleware)
58 |
59 | // enable hot-reload and state-preserving
60 | // compilation error display
61 | app.use(hotMiddleware)
62 |
63 | // serve pure static assets
64 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
65 | app.use(staticPath, express.static('./static'))
66 |
67 | var uri = 'http://localhost:' + port
68 |
69 | devMiddleware.waitUntilValid(function () {
70 | console.log('> Listening at ' + uri + '\n')
71 | })
72 |
73 | module.exports = app.listen(port, function (err) {
74 | if (err) {
75 | console.log(err)
76 | return
77 | }
78 |
79 | // when env is testing, don't need open it
80 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
81 | opn(uri)
82 | }
83 | })
84 |
--------------------------------------------------------------------------------
/build/utils.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
4 |
5 | exports.assetsPath = function (_path) {
6 | var assetsSubDirectory = process.env.NODE_ENV === 'production'
7 | ? config.build.assetsSubDirectory
8 | : config.dev.assetsSubDirectory
9 | return path.posix.join(assetsSubDirectory, _path)
10 | }
11 |
12 | exports.cssLoaders = function (options) {
13 | options = options || {}
14 |
15 | var cssLoader = {
16 | loader: 'css-loader',
17 | options: {
18 | minimize: process.env.NODE_ENV === 'production',
19 | sourceMap: options.sourceMap
20 | }
21 | }
22 |
23 | // generate loader string to be used with extract text plugin
24 | function generateLoaders (loader, loaderOptions) {
25 | var loaders = [cssLoader]
26 | if (loader) {
27 | loaders.push({
28 | loader: loader + '-loader',
29 | options: Object.assign({}, loaderOptions, {
30 | sourceMap: options.sourceMap
31 | })
32 | })
33 | }
34 |
35 | // Extract CSS when that option is specified
36 | // (which is the case during production build)
37 | if (options.extract) {
38 | return ExtractTextPlugin.extract({
39 | use: loaders,
40 | fallback: 'vue-style-loader'
41 | })
42 | } else {
43 | return ['vue-style-loader'].concat(loaders)
44 | }
45 | }
46 |
47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
48 | return {
49 | css: generateLoaders(),
50 | postcss: generateLoaders(),
51 | less: generateLoaders('less'),
52 | sass: generateLoaders('sass', { indentedSyntax: true }),
53 | scss: generateLoaders('sass'),
54 | stylus: generateLoaders('stylus'),
55 | styl: generateLoaders('stylus')
56 | }
57 | }
58 |
59 | // Generate loaders for standalone style files (outside of .vue)
60 | exports.styleLoaders = function (options) {
61 | var output = []
62 | var loaders = exports.cssLoaders(options)
63 | for (var extension in loaders) {
64 | var loader = loaders[extension]
65 | output.push({
66 | test: new RegExp('\\.' + extension + '$'),
67 | use: loader
68 | })
69 | }
70 | return output
71 | }
72 |
--------------------------------------------------------------------------------
/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | var utils = require('./utils')
2 | var config = require('../config')
3 | var isProduction = process.env.NODE_ENV === 'production'
4 |
5 | module.exports = {
6 | loaders: utils.cssLoaders({
7 | sourceMap: isProduction
8 | ? config.build.productionSourceMap
9 | : config.dev.cssSourceMap,
10 | extract: isProduction
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var utils = require('./utils')
3 | var config = require('../config')
4 | var vueLoaderConfig = require('./vue-loader.conf')
5 |
6 | function resolve (dir) {
7 | return path.join(__dirname, '..', dir)
8 | }
9 |
10 | module.exports = {
11 | entry: {
12 | app: './src/main.js'
13 | },
14 | output: {
15 | path: config.build.assetsRoot,
16 | filename: '[name].js',
17 | publicPath: process.env.NODE_ENV === 'production'
18 | ? config.build.assetsPublicPath
19 | : config.dev.assetsPublicPath
20 | },
21 | resolve: {
22 | extensions: ['.js', '.vue', '.json'],
23 | alias: {
24 | 'vue$': 'vue/dist/vue.esm.js',
25 | '@': resolve('src'),
26 | }
27 | },
28 | module: {
29 | rules: [
30 | {
31 | test: /\.(js|vue)$/,
32 | loader: 'eslint-loader',
33 | enforce: "pre",
34 | include: [resolve('src'), resolve('test')],
35 | options: {
36 | formatter: require('eslint-friendly-formatter')
37 | }
38 | },
39 | {
40 | test: /\.vue$/,
41 | loader: 'vue-loader',
42 | options: vueLoaderConfig
43 | },
44 | {
45 | test: /\.js$/,
46 | loader: 'babel-loader',
47 | include: [resolve('src'), resolve('test')]
48 | },
49 | {
50 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
51 | loader: 'url-loader',
52 | query: {
53 | limit: 10000,
54 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
55 | }
56 | },
57 | {
58 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
59 | loader: 'url-loader',
60 | query: {
61 | limit: 10000,
62 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
63 | }
64 | }
65 | ]
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | var utils = require('./utils')
2 | var webpack = require('webpack')
3 | var config = require('../config')
4 | var merge = require('webpack-merge')
5 | var baseWebpackConfig = require('./webpack.base.conf')
6 | var HtmlWebpackPlugin = require('html-webpack-plugin')
7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
8 |
9 | // add hot-reload related code to entry chunks
10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) {
11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
12 | })
13 |
14 | module.exports = merge(baseWebpackConfig, {
15 | module: {
16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
17 | },
18 | // cheap-module-eval-source-map is faster for development
19 | devtool: '#cheap-module-eval-source-map',
20 | plugins: [
21 | new webpack.DefinePlugin({
22 | 'process.env': config.dev.env
23 | }),
24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
25 | new webpack.HotModuleReplacementPlugin(),
26 | new webpack.NoEmitOnErrorsPlugin(),
27 | // https://github.com/ampedandwired/html-webpack-plugin
28 | new HtmlWebpackPlugin({
29 | filename: 'index.html',
30 | template: 'index.html',
31 | inject: true
32 | }),
33 | new FriendlyErrorsPlugin()
34 | ]
35 | })
36 |
--------------------------------------------------------------------------------
/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var utils = require('./utils')
3 | var webpack = require('webpack')
4 | var config = require('../config')
5 | var merge = require('webpack-merge')
6 | var baseWebpackConfig = require('./webpack.base.conf')
7 | var CopyWebpackPlugin = require('copy-webpack-plugin')
8 | var HtmlWebpackPlugin = require('html-webpack-plugin')
9 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
10 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
11 |
12 | var env = process.env.NODE_ENV === 'testing'
13 | ? require('../config/test.env')
14 | : config.build.env
15 |
16 | var webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true
21 | })
22 | },
23 | devtool: config.build.productionSourceMap ? '#source-map' : false,
24 | output: {
25 | path: config.build.assetsRoot,
26 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
27 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
28 | },
29 | plugins: [
30 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
31 | new webpack.DefinePlugin({
32 | 'process.env': env
33 | }),
34 | new webpack.optimize.UglifyJsPlugin({
35 | compress: {
36 | warnings: false
37 | },
38 | sourceMap: true
39 | }),
40 | // extract css into its own file
41 | new ExtractTextPlugin({
42 | filename: utils.assetsPath('css/[name].[contenthash].css')
43 | }),
44 | // Compress extracted CSS. We are using this plugin so that possible
45 | // duplicated CSS from different components can be deduped.
46 | new OptimizeCSSPlugin(),
47 | // generate dist index.html with correct asset hash for caching.
48 | // you can customize output by editing /index.html
49 | // see https://github.com/ampedandwired/html-webpack-plugin
50 | new HtmlWebpackPlugin({
51 | filename: process.env.NODE_ENV === 'testing'
52 | ? 'index.html'
53 | : config.build.index,
54 | template: 'index.html',
55 | inject: true,
56 | minify: {
57 | removeComments: true,
58 | collapseWhitespace: true,
59 | removeAttributeQuotes: true
60 | // more options:
61 | // https://github.com/kangax/html-minifier#options-quick-reference
62 | },
63 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
64 | chunksSortMode: 'dependency'
65 | }),
66 | // split vendor js into its own file
67 | new webpack.optimize.CommonsChunkPlugin({
68 | name: 'vendor',
69 | minChunks: function (module, count) {
70 | // any required modules inside node_modules are extracted to vendor
71 | return (
72 | module.resource &&
73 | /\.js$/.test(module.resource) &&
74 | module.resource.indexOf(
75 | path.join(__dirname, '../node_modules')
76 | ) === 0
77 | )
78 | }
79 | }),
80 | // extract webpack runtime and module manifest to its own file in order to
81 | // prevent vendor hash from being updated whenever app bundle is updated
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'manifest',
84 | chunks: ['vendor']
85 | }),
86 | // copy custom static assets
87 | new CopyWebpackPlugin([
88 | {
89 | from: path.resolve(__dirname, '../static'),
90 | to: config.build.assetsSubDirectory,
91 | ignore: ['.*']
92 | }
93 | ])
94 | ]
95 | })
96 |
97 | if (config.build.productionGzip) {
98 | var CompressionWebpackPlugin = require('compression-webpack-plugin')
99 |
100 | webpackConfig.plugins.push(
101 | new CompressionWebpackPlugin({
102 | asset: '[path].gz[query]',
103 | algorithm: 'gzip',
104 | test: new RegExp(
105 | '\\.(' +
106 | config.build.productionGzipExtensions.join('|') +
107 | ')$'
108 | ),
109 | threshold: 10240,
110 | minRatio: 0.8
111 | })
112 | )
113 | }
114 |
115 | if (config.build.bundleAnalyzerReport) {
116 | var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
117 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
118 | }
119 |
120 | module.exports = webpackConfig
121 |
--------------------------------------------------------------------------------
/build/webpack.test.conf.js:
--------------------------------------------------------------------------------
1 | // This is the webpack config used for unit tests.
2 |
3 | var utils = require('./utils')
4 | var webpack = require('webpack')
5 | var merge = require('webpack-merge')
6 | var baseConfig = require('./webpack.base.conf')
7 |
8 | var webpackConfig = merge(baseConfig, {
9 | // use inline sourcemap for karma-sourcemap-loader
10 | module: {
11 | rules: utils.styleLoaders()
12 | },
13 | devtool: '#inline-source-map',
14 | plugins: [
15 | new webpack.DefinePlugin({
16 | 'process.env': require('../config/test.env')
17 | })
18 | ]
19 | })
20 |
21 | // no need for app entry during tests
22 | delete webpackConfig.entry
23 |
24 | module.exports = webpackConfig
25 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"'
6 | })
7 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'static',
10 | assetsPublicPath: '/',
11 | productionSourceMap: true,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css'],
18 | // Run the build command with an extra argument to
19 | // View the bundle analyzer report after build finishes:
20 | // `npm run build --report`
21 | // Set to `true` or `false` to always turn it on or off
22 | bundleAnalyzerReport: process.env.npm_config_report
23 | },
24 | dev: {
25 | env: require('./dev.env'),
26 | port: 8090,
27 | autoOpenBrowser: true,
28 | assetsSubDirectory: 'static',
29 | assetsPublicPath: '/',
30 | proxyTable: {
31 | '/api': {
32 | target: 'http://127.0.0.1:4001/api/',
33 | changeOrigin: true,
34 | pathRewrite: {
35 | '^/api': ''
36 | }
37 | },
38 | '/server/uploads': {
39 | target: 'http://127.0.0.1:4001/server/uploads/',
40 | changeOrigin: true,
41 | pathRewrite: {
42 | '^/server/uploads': ''
43 | }
44 | },
45 | },
46 | // CSS Sourcemaps off by default because relative paths are "buggy"
47 | // with this option, according to the CSS-Loader README
48 | // (https://github.com/webpack/css-loader#sourcemaps)
49 | // In our experience, they generally work as expected,
50 | // just be aware of this issue when enabling this option.
51 | cssSourceMap: false
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/config/test.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var devEnv = require('./dev.env')
3 |
4 | module.exports = merge(devEnv, {
5 | NODE_ENV: '"testing"'
6 | })
7 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ams
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ams",
3 | "version": "1.0.0",
4 | "description": "A Vue.js project for asset management system",
5 | "author": "EryouHao ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "node build/dev-server.js",
9 | "build": "node build/build.js",
10 | "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
11 | "e2e": "node test/e2e/runner.js",
12 | "test": "npm run unit && npm run e2e",
13 | "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
14 | },
15 | "dependencies": {
16 | "async": "^2.4.0",
17 | "axios": "^0.15.3",
18 | "crypto": "0.0.3",
19 | "echarts": "^3.5.4",
20 | "element-ui": "^1.2.5",
21 | "excel-export": "^0.5.1",
22 | "express-jwt": "^5.1.0",
23 | "express-session": "^1.15.1",
24 | "jsonwebtoken": "^7.3.0",
25 | "moment": "^2.18.1",
26 | "multer": "^1.3.0",
27 | "mysql": "^2.13.0",
28 | "node-xlsx": "^0.7.4",
29 | "nodemon": "^1.11.0",
30 | "sequelize": "^3.30.2",
31 | "vue": "^2.2.2",
32 | "vue-axios": "^2.0.1",
33 | "vue-router": "^2.2.0",
34 | "vuex": "^2.2.1",
35 | "winston": "^2.3.1"
36 | },
37 | "devDependencies": {
38 | "autoprefixer": "^6.7.2",
39 | "babel-core": "^6.22.1",
40 | "babel-eslint": "^7.1.1",
41 | "babel-loader": "^6.2.10",
42 | "babel-plugin-transform-runtime": "^6.22.0",
43 | "babel-preset-env": "^1.2.1",
44 | "babel-preset-stage-2": "^6.22.0",
45 | "babel-register": "^6.22.0",
46 | "chalk": "^1.1.3",
47 | "connect-history-api-fallback": "^1.3.0",
48 | "copy-webpack-plugin": "^4.0.1",
49 | "css-loader": "^0.26.1",
50 | "eslint": "^3.14.1",
51 | "eslint-friendly-formatter": "^2.0.7",
52 | "eslint-loader": "^1.6.1",
53 | "eslint-plugin-html": "^2.0.0",
54 | "eventsource-polyfill": "^0.9.6",
55 | "express": "^4.14.1",
56 | "extract-text-webpack-plugin": "^2.0.0",
57 | "file-loader": "^0.10.0",
58 | "friendly-errors-webpack-plugin": "^1.1.3",
59 | "function-bind": "^1.1.0",
60 | "html-webpack-plugin": "^2.28.0",
61 | "http-proxy-middleware": "^0.17.3",
62 | "jsonwebtoken": "^7.3.0",
63 | "webpack-bundle-analyzer": "^2.2.1",
64 | "cross-env": "^3.1.4",
65 | "karma": "^1.4.1",
66 | "karma-coverage": "^1.1.1",
67 | "karma-mocha": "^1.3.0",
68 | "karma-phantomjs-launcher": "^1.0.2",
69 | "karma-sinon-chai": "^1.2.4",
70 | "karma-sourcemap-loader": "^0.3.7",
71 | "karma-spec-reporter": "0.0.26",
72 | "karma-webpack": "^2.0.2",
73 | "lolex": "^1.5.2",
74 | "mocha": "^3.2.0",
75 | "chai": "^3.5.0",
76 | "sinon": "^1.17.7",
77 | "sinon-chai": "^2.8.0",
78 | "inject-loader": "^2.0.1",
79 | "babel-plugin-istanbul": "^3.1.2",
80 | "phantomjs-prebuilt": "^2.1.14",
81 | "chromedriver": "^2.27.2",
82 | "cross-spawn": "^5.0.1",
83 | "nightwatch": "^0.9.12",
84 | "selenium-server": "^3.0.1",
85 | "semver": "^5.3.0",
86 | "opn": "^4.0.2",
87 | "optimize-css-assets-webpack-plugin": "^1.3.0",
88 | "ora": "^1.1.0",
89 | "rimraf": "^2.6.0",
90 | "url-loader": "^0.5.7",
91 | "vue-loader": "^11.1.4",
92 | "vue-style-loader": "^2.0.0",
93 | "vue-template-compiler": "^2.2.1",
94 | "webpack": "^2.2.1",
95 | "webpack-dev-middleware": "^1.10.0",
96 | "webpack-hot-middleware": "^2.16.1",
97 | "webpack-merge": "^2.6.1"
98 | },
99 | "engines": {
100 | "node": ">= 4.0.0",
101 | "npm": ">= 3.0.0"
102 | },
103 | "browserslist": [
104 | "> 1%",
105 | "last 2 versions",
106 | "not ie <= 8"
107 | ]
108 | }
109 |
--------------------------------------------------------------------------------
/server/api/assetApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var asset_m = require('../models/asset');
9 | var bodyParser = require('body-parser').json();
10 |
11 | // json 格式化函数
12 | var jsonWrite = function(res, ret) {
13 | if(typeof ret === 'undefined') {
14 | res.json({
15 | code: '1',
16 | msg: '操作失败'
17 | });
18 | } else {
19 | res.json(ret);
20 | }
21 | };
22 |
23 | // 增加资产
24 | router.post('/add', (req, res) => {
25 | const form = req.body
26 | if (req.session.user !== null) {
27 | asset_m.addAsset(form, (result) => {
28 | console.log('增加资产成功-api')
29 | jsonWrite(res, result)
30 | })
31 | } else {
32 | console.log('你需要登录才可以操作哦!')
33 | }
34 | })
35 |
36 | // 通过用户id查询可调用资产
37 | router.get('/query-uncall', (req, res) => {
38 | if (req.session.user !== null) {
39 | const id = req.session.user.uid
40 | asset_m.queryUncallAsset(id, (result) => {
41 | console.log('查询成功!')
42 | jsonWrite(res, result)
43 | })
44 | } else {
45 | console.log('你需要登录才可以操作哦!')
46 | }
47 | })
48 |
49 | // 查询未审核资产
50 | router.get('/query-asset-uncheck', (req, res) => {
51 | if (req.session.user !== null) {
52 | asset_m.queryAssetUncheck((result) => {
53 | jsonWrite(res, result)
54 | })
55 | }
56 | })
57 | // 审核资产
58 | router.post('/check-asset', (req, res) => {
59 | const params = req.body
60 | if (req.session.user !== null) {
61 | asset_m.check(params.id, params.state, (result) => {
62 | jsonWrite(res, result)
63 | })
64 | } else {
65 | console.log('你需要登录才可以操作哦!')
66 | }
67 | })
68 | // 通过审核资产
69 | router.post('/check-asset-pass', (req, res) => {
70 | const params = req.body
71 | if (req.session.user !== null) {
72 | asset_m.pass(params.id, params.assetNumber, params.state, (result) => {
73 | jsonWrite(res, result)
74 | })
75 | } else {
76 | console.log('你需要登录才可以操作哦!')
77 | }
78 | })
79 |
80 | // 查询系统资产总数
81 | router.get('/query-all-asset-count', (req, res) => {
82 | if (req.session.user !== null) {
83 | asset_m.queryAllAssetCount((result) => {
84 | console.log('查询成功!')
85 | jsonWrite(res, result)
86 | })
87 | } else {
88 | console.log('你需要登录才可以操作哦!')
89 | }
90 | })
91 |
92 | // 通过id查询资产数量
93 | router.get('/query-person-asset-count', (req, res) => {
94 | if (req.session.user !== null) {
95 | const id = req.session.user.uid
96 | asset_m.queryPersonAssetCount(id, (result) => {
97 | console.log('查询成功!')
98 | jsonWrite(res, result)
99 | })
100 | } else {
101 | console.log('你需要登录才可以操作哦!')
102 | }
103 | })
104 |
105 | // 查询当前页资产列表,返回指定数目数据和条件资产总数 ---- 管理员
106 | router.post('/query-current-page', (req, res) => {
107 | const params = req.body
108 | if (req.session.user !== null) {
109 | asset_m.queryCurrentPageAsset(params.page, params.size, (result) => {
110 | jsonWrite(res, result)
111 | })
112 | }
113 | })
114 |
115 | // 查询当前页资产列表,返回指定数目数据和条件资产总数 ---- 普通教师
116 | router.post('/query-person-current-page', (req, res) => {
117 | const params = req.body
118 | if (req.session.user !== null) {
119 | const id = req.session.user.uid
120 | asset_m.queryPersonCurrentPageAsset(id, params.page, params.size, (result) => {
121 | jsonWrite(res, result)
122 | })
123 | }
124 | })
125 |
126 | // 查询当前页资产列表,返回指定数目数据和条件资产总数 ---- (未审核申报)普通教师
127 | router.post('/query-uncheck-current-page', (req, res) => {
128 | const params = req.body
129 | if (req.session.user !== null) {
130 | asset_m.queryUncheckCurrentPageAsset(params.page, params.size, (result) => {
131 | jsonWrite(res, result)
132 | })
133 | }
134 | })
135 |
136 | // 通过用户id查询正在审核和正在调用资产列表 ---- 普通教师
137 | router.post('/query-doing', (req, res) => {
138 | const params = req.body
139 | if (req.session.user !== null) {
140 | const id = req.session.user.uid
141 | asset_m.queryDoing(id, params.page, params.size, (result) => {
142 | jsonWrite(res, result)
143 | })
144 | }
145 | })
146 |
147 | // 查询最近的待审核和待调用的资产列表 ---- 管理员
148 | router.post('/query-all-doing', (req, res) => {
149 | const params = req.body
150 | if (req.session.user !== null) {
151 | asset_m.queryAllDoing(params.page, params.size, (result) => {
152 | jsonWrite(res, result)
153 | })
154 | }
155 | })
156 | module.exports = router;
157 |
--------------------------------------------------------------------------------
/server/api/callApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var call_m = require('../models/call');
9 | var bodyParser = require('body-parser').json();
10 |
11 | // json 格式化函数
12 | var jsonWrite = function(res, ret) {
13 | if(typeof ret === 'undefined') {
14 | res.json({
15 | code: '1',
16 | msg: '操作失败'
17 | });
18 | } else {
19 | res.json(ret);
20 | }
21 | };
22 |
23 | // 资产调用
24 | router.post('/call-asset', (req, res) => {
25 | const form = req.body
26 | if (req.session.user !== null) {
27 | let result
28 | form.selectIdList.forEach((id) => {
29 | call_m.callAsset(id, form, (result) => {
30 | console.log('资产调用成功-api')
31 | result = result
32 | })
33 | })
34 | jsonWrite(res, result)
35 | } else {
36 | console.log('你需要登录才可以操作哦!')
37 | }
38 | })
39 |
40 | // 查询当前页资产调用列表
41 | router.post('/query-call-list', (req, res) => {
42 | const params = req.body
43 | if (req.session.user !== null) {
44 | call_m.queryCallList(params.page, params.size, (result) => {
45 | console.log('查询成功!')
46 | jsonWrite(res, result)
47 | // console.log(res)
48 | })
49 | } else {
50 | console.log('你需要登录才可以操作哦!')
51 | }
52 | })
53 |
54 | // 审核资产调用
55 | router.post('/check-call', (req, res) => {
56 | const params = req.body
57 | console.log('执行了submitapi')
58 | console.log(params)
59 | if (req.session.user !== null) {
60 | call_m.check(params.id, params.state, (result) => {
61 | jsonWrite(res, result)
62 | })
63 | } else {
64 | console.log('你需要登录才可以操作哦!')
65 | }
66 | })
67 |
68 | module.exports = router;
69 |
--------------------------------------------------------------------------------
/server/api/exportApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var export_m = require('../models/export');
9 | var bodyParser = require('body-parser').json();
10 |
11 | var nodeExcel = require('excel-export')
12 | var async = require('async')
13 |
14 | // json 格式化函数
15 | var jsonWrite = function(res, ret) {
16 | if(typeof ret === 'undefined') {
17 | res.json({
18 | code: '1',
19 | msg: '操作失败'
20 | });
21 | } else {
22 | res.json(ret);
23 | }
24 | };
25 |
26 | // 导出Excel
27 | router.get('/export-excel', (req, res) => {
28 | let rows
29 | async.series({
30 | flag1:function(done){ //flag1 是一个流程标识,用户自定义
31 |
32 | if (req.session.user !== null) {
33 | export_m.exportAsset((result) => {
34 | console.log('查询成功');
35 | // const obj = res.json(result)
36 | // jsonWrite(res, result)
37 | rows = result
38 | // console.log(rows)
39 | done(null,'one') // 第一个参数是异常错误,第二个参数的返回结果
40 | })
41 | } else {
42 | console.log('你需要登录才可以操作哦!')
43 | }
44 | }
45 | }, function(error,results){
46 | //最后结果
47 | //result是返回结果总集,包含了所有的流程控制 ,
48 | //result.flag1 可以获取标识1中处理的结果
49 | const conf = {}
50 | console.log('导出Excel')
51 | // console.log(rows[0])
52 | let tmpArr = []
53 | rows.forEach((item) => {
54 | console.log('----------------')
55 | console.log(item.id)
56 | let arr = [
57 | item.id,
58 | item.asset_name,
59 | item.user_name,
60 | item.asset_number,
61 | item.asset_bill,
62 | item.buy_date,
63 | item.asset_price,
64 | item.asset_type,
65 | item.asset_standard,
66 | item.asset_leavedate,
67 | item.asset_submitdate,
68 | item.asset_usedirection,
69 | item.asset_leavenum,
70 | item.asset_brand,
71 | item.storagePlace,
72 | item.assetBuyer,
73 | item.asset_purchaser,
74 | item.asset_attachnum,
75 | item.asset_attachamount,
76 | item.funds,
77 | item.asset_signature,
78 | item.organization,
79 | item.asset_mark
80 | ]
81 | tmpArr.push(arr)
82 | })
83 | conf.stylesXmlFile = './server/api/styles.xml'
84 |
85 | conf.name = 'mysheet'
86 | conf.cols = [
87 | {
88 | caption: '资产ID',
89 | type: 'number',
90 | },
91 | {
92 | caption: '资产名称',
93 | type: 'string',
94 | },
95 | {
96 | caption: '使用人',
97 | type: 'number',
98 | },
99 | {
100 | caption: '资产编号',
101 | type: 'string',
102 | },
103 | {
104 | caption: '发票号',
105 | type: 'string',
106 | },
107 | {
108 | caption: '购买日期',
109 | type: 'string',
110 | },
111 | {
112 | caption: '单价',
113 | type: 'string',
114 | },
115 | {
116 | caption: '型号',
117 | type: 'string',
118 | },
119 | {
120 | caption: '规格',
121 | type: 'string',
122 | },
123 | {
124 | caption: '出厂日期',
125 | type: 'string',
126 | },
127 | {
128 | caption: '订单提交日期',
129 | type: 'string',
130 | },
131 | {
132 | caption: '使用方向',
133 | type: 'string',
134 | },
135 | {
136 | caption: '出厂编号',
137 | type: 'string',
138 | },
139 | {
140 | caption: '厂家',
141 | type: 'string',
142 | },
143 | {
144 | caption: '存放地点',
145 | type: 'string',
146 | },
147 | {
148 | caption: '申购单位',
149 | type: 'string',
150 | },
151 | {
152 | caption: '购买人',
153 | type: 'string',
154 | },
155 | {
156 | caption: '附件数',
157 | type: 'number',
158 | },
159 | {
160 | caption: '附件金额',
161 | type: 'number',
162 | },
163 | {
164 | caption: '经费来源',
165 | type: 'string',
166 | },
167 | {
168 | caption: '经办人',
169 | type: 'string',
170 | },
171 | {
172 | caption: '采购组织形式',
173 | type: 'string',
174 | },
175 | {
176 | caption: '备注',
177 | type: 'string',
178 | },
179 | ]
180 |
181 |
182 | conf.rows = tmpArr
183 | // conf.rows = [
184 | // ['pi', new Date(Date.UTC(2013, 4, 1))],
185 | // ['e', new Date(2012, 4, 1)]
186 | // ]
187 | console.log(conf.rows)
188 | const result = nodeExcel.execute(conf);
189 | res.setHeader('Content-Type', 'application/octet-stream');
190 | res.setHeader("Content-Disposition", "attachment; filename=" + "Export.xlsx;");
191 | res.url = req.originalUrl;
192 | res.end(result, 'binary');
193 | });
194 |
195 |
196 | })
197 |
198 | module.exports = router;
199 |
--------------------------------------------------------------------------------
/server/api/importApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var asset_m = require('../models/asset');
9 | var bodyParser = require('body-parser').json();
10 |
11 | var xlsx = require('node-xlsx');
12 | var fs = require('fs');
13 |
14 | // 导入Excel TODO...
15 | router.get('/import-excel', (req, res, next) => {
16 | const file = './server/api/assets.xls';
17 | const obj = xlsx.parse(file);
18 |
19 | console.log(JSON.stringify(obj));
20 |
21 | res.send('import successfully');
22 | })
23 |
24 | module.exports = router;
25 |
--------------------------------------------------------------------------------
/server/api/resourceApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var resource_m = require('../models/resource');
9 | var bodyParser = require('body-parser').json();
10 |
11 | // json 格式化函数
12 | var jsonWrite = function(res, ret) {
13 | if(typeof ret === 'undefined') {
14 | res.json({
15 | code: '1',
16 | msg: '操作失败'
17 | });
18 | } else {
19 | res.json(ret);
20 | }
21 | };
22 |
23 | // 查询存放地点
24 | router.get('/queryStoragePlace', (req, res) => {
25 | resource_m.queryStoragePlace((result) => {
26 | jsonWrite(res, result)
27 | })
28 | })
29 |
30 | // 查询经费来源
31 | router.get('/query-funds', (req, res) => {
32 | resource_m.queryFunds((result) => {
33 | jsonWrite(res, result)
34 | })
35 | })
36 |
37 | // 查询经费来源
38 | router.get('/query-organization', (req, res) => {
39 | resource_m.queryOrganization((result) => {
40 | jsonWrite(res, result)
41 | })
42 | })
43 |
44 | // 查询申购单位
45 | router.get('/query-buyer', (req, res) => {
46 | resource_m.queryBuyer((result) => {
47 | jsonWrite(res, result)
48 | })
49 | })
50 |
51 | // 通过 id 查询字典名
52 | router.get('/query-resource-by-id', (req, res) => {
53 | let params = req.body
54 | if (req.session.user !== null) {
55 | resource_m.queryResourceById(params.id, (result) => {
56 | jsonWrite(res, result)
57 | })
58 | }
59 | })
60 |
61 | // 查询系统字典列表
62 | router.post('/query-resource-list', (req, res) => {
63 | const params = req.body
64 | if (req.session.user !== null) {
65 | resource_m.queryCurrentPageResourceList(params.page, params.size, (result) => {
66 | jsonWrite(res, result)
67 | })
68 | }
69 | })
70 |
71 | // 查询资产类型
72 | router.get('/type-list', (req, res) => {
73 | if (req.session.user !== null) {
74 | resource_m.queryResourceTypeList((result) => {
75 | jsonWrite(res, result)
76 | })
77 | }
78 | })
79 |
80 | // 增加字典
81 | router.post('/add', (req,res) => {
82 | const params = req.body
83 | if (req.session.user !== null) {
84 | resource_m.addResource(params, (result) => {
85 | jsonWrite(res, result)
86 | })
87 | }
88 | })
89 |
90 | module.exports = router;
91 |
--------------------------------------------------------------------------------
/server/api/searchApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var search_m = require('../models/search');
9 | var bodyParser = require('body-parser').json();
10 |
11 | // json 格式化函数
12 | var jsonWrite = function(res, ret) {
13 | if(typeof ret === 'undefined') {
14 | res.json({
15 | code: '1',
16 | msg: '操作失败'
17 | });
18 | } else {
19 | res.json(ret);
20 | }
21 | };
22 |
23 | // 通过资产编号查询资产
24 | router.post('/search', (req, res) => {
25 | const form = req.body
26 | if (req.session.user !== null) {
27 | search_m.searchAssetByNumber(form.assetNumber, (result) => {
28 | console.log('查询成功')
29 | jsonWrite(res, result)
30 | })
31 |
32 | } else {
33 | console.log('你需要登录才可以操作哦!')
34 | }
35 | })
36 |
37 | // 通过用户id和存放地点查询资产
38 | router.post('/search-storageplace', (req, res) => {
39 | const form = req.body
40 | if (req.session.user !== null) {
41 | const id = req.session.user.uid
42 | search_m.searchAssetByspId(id, form.storagePlaceId, (result) => {
43 | jsonWrite(res, result)
44 | })
45 | } else {
46 | console.log('你需要登录才可以操作哦!')
47 | }
48 | })
49 |
50 | module.exports = router;
51 |
--------------------------------------------------------------------------------
/server/api/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/server/api/uploadApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var asset_m = require('../models/asset');
9 | var bodyParser = require('body-parser').json();
10 |
11 | // json 格式化函数
12 | var jsonWrite = function(res, ret) {
13 | if(typeof ret === 'undefined') {
14 | res.json({
15 | code: '1',
16 | msg: '操作失败'
17 | });
18 | } else {
19 | res.json(ret);
20 | }
21 | };
22 |
23 |
24 | // 引入上传模块
25 | const multer = require('multer');
26 |
27 | var storage = multer.diskStorage({
28 | destination: function (req, file, cb) {
29 | cb(null, 'server/uploads/')
30 | },
31 | filename: function (req, file, cb) {
32 | var fileFormat = (file.originalname).split(".");
33 | cb(null, file.fieldname + '-' + Date.now() + "." + fileFormat[fileFormat.length - 1]);
34 | }
35 | })
36 |
37 | var upload = multer({ storage: storage })
38 |
39 | router.post('/upload-img', upload.single('avatar'), (req, res, next) => {
40 | console.log('上传的文件为')
41 | console.log(req.file)
42 | res.send({'path': req.file.path})
43 | });
44 |
45 | module.exports = router;
46 |
--------------------------------------------------------------------------------
/server/api/userApi.js:
--------------------------------------------------------------------------------
1 | var $conf = require('../conf/db');
2 | var express = require('express');
3 | var router = express.Router();
4 | var mysql = require('mysql');
5 | var $sql = require('../sql/sqlString');
6 | var $util = require('../util/util');
7 |
8 | var user_m = require('../models/user');
9 | var bodyParser = require('body-parser').json();
10 |
11 | var jsonWrite = function(res, ret) {
12 | if(typeof ret === 'undefined') {
13 | res.json({
14 | code: '1',
15 | msg: '操作失败'
16 | });
17 | } else {
18 | res.json(ret);
19 | }
20 | };
21 |
22 | // 登录
23 | router.post('/login', (req, res, next) => {
24 | var username = req.body.username || '',
25 | password = req.body.password || '';
26 | var password_hash = user_m.hash(password);
27 |
28 | user_m.login(username, password_hash, function (result) {
29 | if (result.length) {
30 | // 将数据保存到名为user的session中
31 | req.session.user = {
32 | uid: result[0].id,
33 | username: username,
34 | userright: result[0].right_id,
35 | }
36 | res.user = {
37 | uid: req.session.user.uid,
38 | username: req.session.user.username,
39 | userright: req.session.user.userright
40 | }
41 | jsonWrite(res, result)
42 | // res.redirect('/');
43 | } else {
44 | return res.json({status: 404, message: '登录失败'});
45 |
46 | }
47 | })
48 | })
49 |
50 | router.get('/', (req, res, next) => {
51 | if (!req.session.user) {
52 | console.log('还未登陆哦!');
53 | throw Error('error')
54 | }
55 | })
56 |
57 | // 注册
58 | router.post('/reg',bodyParser, (req, res, next) => {
59 | var username = req.body.username || 'fehey',
60 | password = req.body.password || '123456';
61 | var password_hash = user_m.hash(password),
62 | regtime = parseInt(Date.now() / 1000);
63 |
64 | // 数据库处理
65 | user_m.reg(username, password_hash, regtime, function(result) {
66 | if (result.affectedRows) {
67 | console.log('注册成功');
68 | res.send('注册成功');
69 | }
70 | })
71 | })
72 |
73 | //登出
74 | router.get('/logout', (req, res, next) => {
75 | console.log(req.session.user)
76 |
77 | req.session.destroy();
78 | console.log(req.session)
79 | res.json({ok: true})
80 | // res.redirect('/login');
81 | })
82 |
83 | // 增加用户接口
84 | router.post('/addUser', (req, res) => {
85 | var username = req.body.username || 'zhangfang',
86 | password = req.body.password || '123',
87 | mobile = req.body.mobile || 15733296573,
88 | accountName = req.body.accountName || 'zhangfang@qq.com',
89 | right = req.body.right || 1,
90 | state = 0;
91 | console.log('req')
92 | console.log(req)
93 | // 数据库处理
94 | user_m.addUser(username,mobile,accountName,password,right,state, (result) => {
95 | console.log('添加用户成功')
96 | // console.log(result)
97 | jsonWrite(res, result)
98 | })
99 | });
100 |
101 | // 删除用户接口
102 | router.post('/deleteUser', (req, res) => {
103 | user_m.deleteUser(req.body.id, (result) => {
104 |
105 | // 判断是否可删除
106 | if (result.affectedRows === 0) {
107 | console.log('不允许删除')
108 | result.status = 'ERROR' // 此用户已经使用过,不让删除
109 | } else {
110 | console.log('删除用户成功')
111 | result.status = 'SUCCESS' // 此用户还未使用,可以删除
112 | }
113 | jsonWrite(res, result)
114 | })
115 | });
116 |
117 | // 更新用户接口
118 | router.post('/updateUser', (req, res) => {
119 | let params = req.body
120 | user_m.updateUser(params.username, params.accountName, params.mobile, params.right, params.state, (result) => {
121 | // 待完成
122 | })
123 | });
124 | // 更新个人信息
125 | router.post('/update-user-info', (req, res) => {
126 | let params = req.body
127 | if (req.session.user !== null) {
128 | const id = req.session.user.uid
129 | user_m.updateUserInfo(params, id, (result) => {
130 | console.log('更新信息成功!')
131 | jsonWrite(res, result)
132 | })
133 | } else {
134 | console.log('你需要登录才可以操作哦!')
135 | }
136 | });
137 |
138 | // 查询用户接口
139 | router.get('/queryAllUser', (req, res) => {
140 | user_m.queryAllUser((result) => {
141 | console.log(jsonWrite(res, result))
142 | })
143 | });
144 | // 查询用户列表,填充使用人接口
145 | router.get('/queryUserList', (req, res) => {
146 | if (req.session.user !== null) {
147 | const id = req.session.user.uid
148 | user_m.queryUserList(id, (result) => {
149 | jsonWrite(res, result)
150 | })
151 | }
152 | })
153 | // 通过 id 查询用户
154 | router.post('/query-user-by-id', (req, res) => {
155 | let params = req.body
156 | if (req.session.user !== null) {
157 | user_m.queryUserById(params.id, (result) => {
158 | jsonWrite(res, result)
159 | })
160 | }
161 | })
162 |
163 | module.exports = router;
164 |
--------------------------------------------------------------------------------
/server/conf/db.js:
--------------------------------------------------------------------------------
1 | // 数据库连接配置
2 | // module.exports = {
3 | // mysql: {
4 | // host: 'localhost',
5 | // user: 'root',
6 | // password: '123456',
7 | // database: 'cms',
8 | // port: '3306'
9 | // }
10 | // }
11 | var mysql = require('mysql')
12 |
13 | var pool = mysql.createPool({
14 | host: 'localhost',
15 | user: 'root',
16 | password: '123456',
17 | database: 'ams',
18 | port: '3306',
19 | multipleStatements: true // 可以同时执行多条SQL
20 | });
21 |
22 | module.exports = pool;
23 |
--------------------------------------------------------------------------------
/server/controller/user.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const router = express.Router()
3 | const sha1 = require('sha1')
4 | const moment = require('moment')
5 |
6 | const createToken = require('../middleware/checkToken')
7 | const checkToken = require('../middleware/checkToken')
8 |
9 | const Login = (req, res) => {
10 | let userLogin = {
11 | username: req.body.username,
12 | password: sha1(req.body.password),
13 | token: createToken(this.username)
14 | }
15 | router.post('/login', userLogin, (req, res) => {
16 |
17 | })
18 | }
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | // node 后端服务器
2 |
3 | // 引入编写好的api
4 | const userApi = require('./api/userApi');
5 | const assetApi = require('./api/assetApi');
6 | const callApi = require('./api/callApi');
7 | const resourceApi = require('./api/resourceApi');
8 | const uploadApi = require('./api/uploadApi');
9 | const exportApi = require('./api/exportApi');
10 | const importApi = require('./api/importApi');
11 | const searchApi = require('./api/searchApi');
12 |
13 | // 引入文件模块
14 | const fs = require('fs');
15 | // 引入处理路径模块
16 | const path = require('path');
17 | // 引入处理post数据的模块
18 | const bodyParser = require('body-parser');
19 | // const cookieParser = require('cookie-parser');
20 | // 引入Express
21 | const express = require('express');
22 | const app = express();
23 |
24 | // 引入session模块
25 | const session = require('express-session');
26 |
27 | app.use(bodyParser.json());
28 | app.use(bodyParser.urlencoded({extended: false}));
29 |
30 | // 静态文件目录
31 | app.use('/server/uploads', express.static(path.join(__dirname, 'uploads')));
32 |
33 | app.use(session({
34 | secret: 'fehey',
35 | cookie: { maxAge: 60*60*1000 },
36 | resave: false,
37 | saveUninitialized: true,
38 | name: 'fehey' // 若不设置 默认为 connect.sid ,name可换成key
39 | }));
40 |
41 | app.use((req, res, next) => {
42 | // 如果cookie中存在,则说明已经登录
43 | if (req.session.user) {
44 | res.locals.user = {
45 | uid: req.session.user.uid,
46 | username: req.session.user.username,
47 | userright: req.session.user.userright
48 | }
49 | } else {
50 | res.locals.user = {};
51 | }
52 | next();
53 | })
54 |
55 | // 跨域支持
56 | app.all('*', (req, res, next) => {
57 | const origin = req.headers.origin;
58 | res.header('Access-Control-Allow-Origin', origin);
59 | res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, token,sign');
60 | res.header('Access-Control-Allow-Credentials', true);
61 | res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS, DELETE');
62 | next();
63 | });
64 |
65 | // 后端api路由
66 | app.use('/api/user', userApi);
67 | app.use('/api/asset', assetApi);
68 | app.use('/api/call', callApi);
69 | app.use('/api/resource', resourceApi);
70 | app.use('/api/upload', uploadApi);
71 | app.use('/api/export', exportApi);
72 | app.use('/api/import', importApi);
73 | app.use('/api/search', searchApi);
74 |
75 | // 日志
76 | const log = require('./util/log')
77 | log.info('hello')
78 |
79 | // 访问静态资源文件,这里是访问所有dist目录下的静态资源文件
80 | // ...
81 |
82 | // 监听3000端口
83 | app.listen(4001);
84 | console.log('success listen......');
85 |
--------------------------------------------------------------------------------
/server/middleware/checkToken.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 检测token是否过期
3 | */
4 | const jwt = require('jsonwebtoken')
5 |
6 | module.exports = function (req, res, next) {
7 | let token = req.headers['authorization'].split(' ')[1]
8 | // decode token, return object
9 | let decoded = jwt.decode(token, 'secret')
10 |
11 | // 检测 token 是否过期
12 | if (token && decoded.exp <= Date.now() / 1000) {
13 | return res.json({
14 | code: 401,
15 | message: 'token 失效,请重新登录'
16 | })
17 | }
18 |
19 | next()
20 | }
--------------------------------------------------------------------------------
/server/middleware/createToken.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建 token
3 | */
4 | const jwt = require('jsonwebtoken')
5 |
6 | module.exports = function(name) {
7 | const token = jwt.sign({
8 | name: name
9 | }, 'secret', {expiresIn: '10s'})
10 |
11 | return token
12 | }
13 |
--------------------------------------------------------------------------------
/server/models/asset.js:
--------------------------------------------------------------------------------
1 | const pool = require('../conf/db');
2 | module.exports = {
3 | // 增加资产: 资产名称、用户id、资产编号、发票号、购买日期、单价、规格、出厂日期、订单提交日期、使用方向、出厂编号、厂家、申购单位、购买人、附件数
4 | // 附件金额、经费来源id、经办人、资产图片、采购组织形式、状态、备注
5 | addAsset: function (form, cb) {
6 | console.log('form')
7 | console.log(form)
8 | pool.getConnection((err, connection) => {
9 | if (err) throw err;
10 | const sql = `
11 | INSERT INTO assets
12 | (
13 | asset_name,
14 | user_id,
15 | asset_number,
16 | asset_bill,
17 | buy_date,
18 | asset_price,
19 | asset_type,
20 | asset_standard,
21 | asset_leavedate,
22 | asset_submitdate,
23 | asset_usedirection,
24 | asset_leavenum,
25 | asset_brand,
26 | asset_storageplace,
27 | asset_buyer,
28 | asset_purchaser,
29 | asset_attachnum,
30 | asset_attachamount,
31 | funds_id,
32 | asset_signature,
33 | asset_imgurl,
34 | asset_orgid,
35 | asset_state,
36 | asset_mark,
37 | calling
38 | ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
39 | `
40 | const params = [
41 | form.assetName,
42 | form.userId,
43 | form.assetNumber,
44 | form.bill,
45 | form.buyDate,
46 | form.price,
47 | form.type,
48 | form.standard,
49 | form.leaveDate,
50 | form.submitDate,
51 | form.useDirection,
52 | form.leaveNum,
53 | form.brand,
54 | form.storagePlace,
55 | form.buyer,
56 | form.purchaser,
57 | form.attachNum,
58 | form.attachAmount,
59 | form.fundId,
60 | form.signature,
61 | form.imgUrl,
62 | form.orgId,
63 | form.state,
64 | form.mark,
65 | form.calling
66 | ]
67 | connection.query(sql, params, (err, results) => {
68 | if (err) throw err
69 |
70 | cb(results)
71 |
72 | connection.release()
73 | })
74 | })
75 | },
76 | // 通过用户id查询可调用的资产
77 | queryUncallAsset: function (id, cb) {
78 | pool.getConnection((err, connection) => {
79 | if (err) throw err
80 | const sql = `
81 | select a.*, u.user_name
82 | from assets a, users u
83 | where
84 | a.user_id = ? and a.user_id = u.id and a.asset_state = 1 and a.calling = 0
85 | `
86 | connection.query(sql, id, (err, result) => {
87 | if (err) throw err
88 | cb(result)
89 | connection.release()
90 | })
91 | })
92 | },
93 | // 查询未审核资产
94 | queryAssetUncheck: function (cb) {
95 | pool.getConnection((err, conn) => {
96 | if (err) throw err
97 | const sql = `
98 | select a.*, u.user_name,r1.name storagePlace, r2.name buyer, r3.name funds, r4.name organization
99 | from assets as a
100 | left join users as u on a.user_id = u.id
101 | left join resource as r1 on r1.id = a.asset_storageplace
102 | left join resource as r2 on r2.id = a.asset_buyer
103 | left join resource as r3 on r3.id = a.funds_id
104 | left join resource as r4 on r4.id = a.asset_orgid
105 | where assets.asset_state=0 and assets.user_id = users.id
106 | `
107 | conn.query(sql, (err, result) => {
108 | if (err) throw err
109 | cb(result)
110 | conn.release()
111 | })
112 | })
113 | },
114 | // 审核资产申报
115 | check: function (id, state, cb) {
116 | pool.getConnection((err, conn) => {
117 | if (err) throw err
118 | const sql = `
119 | update assets
120 | set asset_state = ?
121 | where id = ?
122 | `
123 | conn.query(sql, [state, id], (err, result) => {
124 | if (err) throw err
125 | cb(result)
126 | conn.release()
127 | })
128 | })
129 | },
130 | // 通过资产申报
131 | pass: function (id, assetNumber, state, cb) {
132 | pool.getConnection((err, conn) => {
133 | if (err) throw err
134 | const sql = `
135 | update assets
136 | set asset_number = ?, asset_state = ?
137 | where id = ?
138 | `
139 | conn.query(sql, [assetNumber, state, id], (err, result) => {
140 | if (err) throw err
141 | cb(result)
142 | conn.release()
143 | })
144 | })
145 | },
146 |
147 | // 查询系统资产总数
148 | queryAllAssetCount: function (cb) {
149 | pool.getConnection((err, conn) => {
150 | if (err) throw err
151 | const sql = `
152 | select count(*) as assetCount from assets where asset_state = 1;
153 | select count(*) as unCheckAssetCount from assets where asset_state = 0;
154 | select count(*) as callAssetCount from calls;
155 | `
156 | conn.query(sql, (err, result) => {
157 | if (err) throw err
158 | cb(result)
159 | conn.release()
160 | })
161 | })
162 | },
163 |
164 | // 通过用户id查询资产数目
165 | queryPersonAssetCount: function (id, cb) {
166 | pool.getConnection((err, conn) => {
167 | if (err) throw err
168 | const sql = `
169 | select count(*) as assetCount from assets where user_id = ? and asset_state = 1;
170 | select count(*) as unCheckAssetCount from assets where user_id = ? and asset_state = 0;
171 | select count(*) as callAssetCount from assets where user_id = ? and calling = 1;
172 | `
173 | conn.query(sql, [id, id, id], (err, result) => {
174 | if (err) throw err
175 | cb(result)
176 | conn.release()
177 | })
178 | })
179 | },
180 |
181 | // 查询当前页资产列表,返回指定数目数据和条件资产总数 ---- (已通过审核资产)管理员
182 | queryCurrentPageAsset: function (page, size, cb) {
183 | console.log(page, size)
184 | pool.getConnection((err, conn) => {
185 | if (err) throw err
186 | const sql = `
187 | select count(1) as totalCount from assets where asset_state = 1;
188 |
189 | select a.*, u.user_name,r1.name storagePlace, r2.name buyer, r3.name funds, r4.name organization
190 | from assets as a
191 | left join users as u on a.user_id = u.id
192 | left join resource as r1 on r1.id = a.asset_storageplace
193 | left join resource as r2 on r2.id = a.asset_buyer
194 | left join resource as r3 on r3.id = a.funds_id
195 | left join resource as r4 on r4.id = a.asset_orgid
196 | where a.asset_state=1
197 | order by id
198 | limit ?, ?;
199 | `
200 | conn.query(sql, [page, size], (err, result) => {
201 | if (err) throw err
202 | cb(result)
203 | conn.release()
204 | })
205 | })
206 | },
207 |
208 | // 查询当前页资产列表,返回指定数目数据和条件资产总数 ---- (已通过审核资产)普通教师
209 | queryPersonCurrentPageAsset: function (id, page, size, cb) {
210 | console.log(page, size)
211 | pool.getConnection((err, conn) => {
212 | if (err) throw err
213 | const sql = `
214 | select count(1) as totalCount from assets where user_id = ? and asset_state = 1;
215 |
216 | select a.*, u.user_name,r1.name storagePlace, r2.name buyer, r3.name funds, r4.name organization
217 | from assets as a
218 | left join users as u on a.user_id = u.id
219 | left join resource as r1 on r1.id = a.asset_storageplace
220 | left join resource as r2 on r2.id = a.asset_buyer
221 | left join resource as r3 on r3.id = a.funds_id
222 | left join resource as r4 on r4.id = a.asset_orgid
223 | where a.asset_state=1 and a.user_id = ?
224 | order by id
225 | limit ?, ?;
226 | `
227 | conn.query(sql, [id, id, page, size], (err, result) => {
228 | if (err) throw err
229 | cb(result)
230 | conn.release()
231 | })
232 | })
233 | },
234 | // 查询当前页资产列表,返回指定数目数据和条件资产总数 ---- (未审核申报资产)管理员
235 | queryUncheckCurrentPageAsset: function (page, size, cb) {
236 | console.log(page, size)
237 | pool.getConnection((err, conn) => {
238 | if (err) throw err
239 | const sql = `
240 | select count(1) as totalCount from assets where asset_state = 0;
241 |
242 | select a.*, u.user_name,r1.name storagePlace, r2.name buyer, r3.name funds, r4.name organization
243 | from assets as a
244 | left join users as u on a.user_id = u.id
245 | left join resource as r1 on r1.id = a.asset_storageplace
246 | left join resource as r2 on r2.id = a.asset_buyer
247 | left join resource as r3 on r3.id = a.funds_id
248 | left join resource as r4 on r4.id = a.asset_orgid
249 | where a.asset_state=0
250 | order by id
251 | limit ?, ?;
252 | `
253 | conn.query(sql, [page, size], (err, result) => {
254 | if (err) throw err
255 | cb(result)
256 | conn.release()
257 | })
258 | })
259 | },
260 | // 通过用户id查询正在审核和正在调用资产列表 ---- 普通教师
261 | queryDoing: function (id, page, size, cb) {
262 | pool.getConnection((err, conn) => {
263 | const sql = `
264 | select count(1) as totalCount from assets where user_id = ? and (asset_state = 0 or calling = 1);
265 |
266 | select * from assets
267 | where user_id = ? and (asset_state = 0 or calling = 1)
268 | order by id
269 | limit ?, ?;
270 | `
271 | conn.query(sql, [id, id, page, size], (err, result) => {
272 | if (err) throw err
273 | cb(result)
274 | conn.release()
275 | })
276 | })
277 | },
278 | // 查询最近的待审核和待调用的资产列表 ---- 管理员
279 | queryAllDoing: function (page, size, cb) {
280 | pool.getConnection((err, conn) => {
281 | const sql = `
282 | select count(1) as totalCount from assets where asset_state = 0 or calling = 1;
283 |
284 | select * from assets
285 | where (asset_state = 0 or calling = 1)
286 | order by id
287 | limit ?, ?;
288 | `
289 | conn.query(sql, [page, size], (err, result) => {
290 | if (err) throw err
291 | cb(result)
292 | conn.release()
293 | })
294 | })
295 | }
296 | }
297 |
--------------------------------------------------------------------------------
/server/models/call.js:
--------------------------------------------------------------------------------
1 | const pool = require('../conf/db');
2 |
3 | module.exports = {
4 |
5 | // 资产调用
6 | callAsset: function (id, form, cb) {
7 | pool.getConnection((err, conn) => {
8 | if (err) throw err
9 | const sql = `
10 | insert into calls
11 | (asset_id, new_user_id, new_storage_place_id, comment)
12 | values (?, ?, ?, ?);
13 | update assets
14 | set calling = 1
15 | where id = ?;
16 | `
17 | const params = [
18 | id,
19 | form.newUserId,
20 | form.newStoragePlace,
21 | form.comment,
22 | id
23 | ]
24 | conn.query(sql, params, (err, result) => {
25 | if (err) throw err
26 | cb(result)
27 | conn.release()
28 | })
29 | })
30 | },
31 | // 查询当前页调用申请列表
32 | queryCallList(page, size, cb) {
33 | pool.getConnection((err, conn) => {
34 | if (err) throw err
35 | const sql = `
36 | select count(1) from calls;
37 |
38 | select c.id, a.asset_name, u1.user_name old_user, u2.user_name new_user, r1.name old_place, r2.name new_place, c.comment from calls as c
39 | left join assets as a on a.id = c.asset_id
40 | left join users as u1 on u1.id = a.user_id
41 | left join users as u2 on u2.id = c.new_user_id
42 | left join resource as r1 on r1.id = a.asset_storageplace
43 | left join resource as r2 on r2.id = c.new_storage_place_id
44 | order by id
45 | limit ?, ?;
46 | `
47 | conn.query(sql,[page, size], (err, result) => {
48 | if (err) throw err
49 | cb(result)
50 | conn.release()
51 | })
52 | })
53 | },
54 | // 审核资产调用
55 | check: function (id, state, cb) {
56 | pool.getConnection((err, conn) => {
57 | if (err) throw err
58 | let sql = ''
59 | if (state === 'PASS') {
60 | sql = `
61 | UPDATE assets a
62 | INNER JOIN calls c ON a.id = c.asset_id and c.id = ?
63 | SET a.user_id = c.new_user_id,
64 | a.asset_storageplace = c.new_storage_place_id;
65 |
66 | update assets
67 | set calling = 0
68 | where id = (
69 | select asset_id
70 | from calls
71 | where id = ?
72 | );
73 |
74 | delete from calls where id = ?;
75 | `
76 | } else {
77 | sql = `
78 | select * from calls where id = ?;
79 |
80 | update assets
81 | set calling = 0
82 | where id = (
83 | select asset_id
84 | from calls
85 | where id = ?
86 | );
87 |
88 | delete from calls where id = ?;
89 | `
90 | }
91 | console.log(sql)
92 | conn.query(sql, [id, id, id], (err, result) => {
93 | if (err) throw err
94 | console.log(result)
95 | cb(result)
96 | conn.release()
97 | })
98 | })
99 | },
100 | }
101 |
--------------------------------------------------------------------------------
/server/models/export.js:
--------------------------------------------------------------------------------
1 | var pool = require('../conf/db');
2 | module.exports = {
3 | exportAsset(cb) {
4 | pool.getConnection((err, conn) => {
5 | if (err) throw err
6 | const sql = `
7 | select
8 | a.*,
9 | u.user_name,
10 | r1.name as storagePlace,
11 | r2.name as assetBuyer,
12 | r3.name as funds,
13 | r4.name as organization
14 | from assets as a
15 | left join users as u on u.id = a.user_id
16 | left join resource as r1 on r1.id = a.asset_storageplace
17 | left join resource as r2 on r2.id = a.asset_buyer
18 | left join resource as r3 on r3.id = a.funds_id
19 | left join resource as r4 on r4.id = a.asset_orgid
20 | where a.asset_state = 0
21 | `
22 | conn.query(sql, (err, result) => {
23 | if (err) throw err
24 | cb(result)
25 | conn.release()
26 | })
27 | })
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/server/models/resource.js:
--------------------------------------------------------------------------------
1 | const pool = require('../conf/db');
2 | module.exports = {
3 | // 查询存放地点
4 | queryStoragePlace(cb) {
5 | pool.getConnection((err, conn) => {
6 | if (err) throw err
7 | const sql = `
8 | select resource.id, resource.name
9 | from resource, resource_type
10 | where resource.type_id = resource_type.id and resource_type.name = '存放地点'
11 | `
12 | conn.query(sql, (err, result) => {
13 | if (err) throw err
14 | cb(result)
15 | conn.release()
16 | })
17 | })
18 | },
19 | // 查询经费来源
20 | queryFunds(cb) {
21 | pool.getConnection((err, conn) => {
22 | if (err) throw err
23 | const sql = `
24 | select resource.id, resource.name
25 | from resource, resource_type
26 | where resource.type_id = resource_type.id and resource_type.name = '经费来源'
27 | `
28 | conn.query(sql, (err, result) => {
29 | if (err) throw err
30 | cb(result)
31 | conn.release()
32 | })
33 | })
34 | },
35 | // 查询采购组织形式
36 | queryOrganization(cb) {
37 | pool.getConnection((err, conn) => {
38 | if (err) throw err
39 | const sql = `
40 | select resource.id, resource.name
41 | from resource, resource_type
42 | where resource.type_id = resource_type.id and resource_type.name = '采购组织形式'
43 | `
44 | conn.query(sql, (err, result) => {
45 | if (err) throw err
46 | cb(result)
47 | conn.release()
48 | })
49 | })
50 | },
51 | // 查询申购单位
52 | queryBuyer(cb) {
53 | pool.getConnection((err, conn) => {
54 | if (err) throw err
55 | const sql = `
56 | select resource.id, resource.name
57 | from resource, resource_type
58 | where resource.type_id = resource_type.id and resource_type.name = '申购单位'
59 | `
60 | conn.query(sql, (err, result) => {
61 | if (err) throw err
62 | cb(result)
63 | conn.release()
64 | })
65 | })
66 | },
67 | // 通过 id 查询字典名
68 | queryResourceById(id, cb) {
69 | pool.getConnection((err, conn) => {
70 | if (err) throw err
71 | const sql = `
72 | select name
73 | from resource
74 | where id = ?
75 | `
76 | conn.query(sql, id, (err, result) => {
77 | if (err) throw err
78 | cb(result)
79 | conn.release()
80 | })
81 | })
82 | },
83 | // 查询当前页系统字典列表
84 | queryCurrentPageResourceList(page, size, cb) {
85 | pool.getConnection((err, conn) => {
86 | if (err) throw err
87 | const sql = `
88 | select count(1) as totalCount from resource;
89 |
90 | select r.id, rt.name type, r.name name
91 | from resource as r
92 | left join resource_type as rt on rt.id = r.type_id
93 | order by r.id
94 | limit ?, ?;
95 | `
96 | conn.query(sql, [page, size], (err, result) => {
97 | if (err) throw err
98 | cb(result)
99 | conn.release()
100 | })
101 | })
102 | },
103 | // 查询资产类型
104 | queryResourceTypeList(cb) {
105 | pool.getConnection((err, conn) => {
106 | if (err) throw err
107 | const sql = `
108 | select * from resource_type;
109 | `
110 | conn.query(sql, (err, result) => {
111 | if (err) throw err
112 | cb(result)
113 | conn.release()
114 | })
115 |
116 | })
117 | },
118 | // 增加字典
119 | addResource(form,cb) {
120 | const params = [
121 | form.typeId,
122 | form.name
123 | ]
124 | pool.getConnection((err, conn) => {
125 | if (err) throw err
126 | const sql = `
127 | insert into resource
128 | (type_id, name)
129 | values (?, ?);
130 | `
131 | conn.query(sql, params, (err, result) => {
132 | if (err) throw err
133 | cb(result)
134 | conn.release()
135 | })
136 | })
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/server/models/search.js:
--------------------------------------------------------------------------------
1 | var pool = require('../conf/db');
2 |
3 | // 系统搜索功能模块
4 | module.exports = {
5 | searchAssetByNumber(number, cb) {
6 | pool.getConnection((err, conn) => {
7 | if (err) throw err
8 | const sql = `
9 | select a.*, u.user_name,r1.name storagePlace, r2.name buyer, r3.name funds, r4.name organization
10 | from assets as a
11 | left join users as u on a.user_id = u.id
12 | left join resource as r1 on r1.id = a.asset_storageplace
13 | left join resource as r2 on r2.id = a.asset_buyer
14 | left join resource as r3 on r3.id = a.funds_id
15 | left join resource as r4 on r4.id = a.asset_orgid
16 | where a.asset_state=1 and a.asset_number = ?
17 | `
18 | conn.query(sql, number, (err, result) => {
19 | if (err) throw err
20 | cb(result)
21 | conn.release()
22 | })
23 | })
24 | },
25 | searchAssetByspId(userId,spId,cb) {
26 | console.log('传进来的参数是')
27 | console.log(userId, spId);
28 | pool.getConnection((err, conn) => {
29 | if (err) throw err
30 | const sql = `
31 | select a.*, u.user_name
32 | from assets a, users u
33 | where
34 | a.user_id = ? and a.asset_storageplace = ? and a.user_id = u.id and a.asset_state = 1 and a.calling = 0
35 | `
36 | conn.query(sql, [userId, spId], (err, result) => {
37 | if (err) throw err
38 | cb(result)
39 | conn.release()
40 | })
41 | })
42 | },
43 | }
44 |
--------------------------------------------------------------------------------
/server/models/user.js:
--------------------------------------------------------------------------------
1 | var pool = require('../conf/db');
2 | var crypto = require('crypto');
3 | module.exports = {
4 | // 对字符串进行sha1加密 散列算法与密钥结合
5 | hash: function(str) {
6 | return crypto.createHmac('sha1', str).update('love').digest('hex');
7 | },
8 |
9 | // 注册
10 | reg: function (username, password, regtime, cb) {
11 | pool.getConnection(function (err, connection) {
12 | if (err) throw err;
13 |
14 | var params = {username: username, password: password};
15 | console.log(params);
16 | connection.query('INSERT INTO `users` (user_name,user_psd) VALUES (?, ?)', [params.username, params.password], function (err, insert_res) {
17 | if (err) throw err;
18 |
19 | cb(insert_res);
20 | connection.release();
21 | })
22 | })
23 | },
24 |
25 | // 登录
26 | login: function (username, password, cb) {
27 | console.log(username, password);
28 | pool.getConnection(function (err, connection) {
29 | if (err) throw err;
30 | connection.query('SELECT id,user_name,user_account,right_id,user_mobile FROM `users` WHERE `user_account`=? AND `user_psd`=?', [username, password], function (err, result) {
31 | if (err) throw err;
32 | console.log('登录里面的result是:')
33 | console.log('result' + result)
34 | cb(result);
35 | connection.release();
36 | })
37 | })
38 | },
39 |
40 | // 增加用户
41 | addUser: function (username, mobile, accountname, password, right, state, cb) {
42 |
43 | let params = {
44 | username: username,
45 | mobile: mobile,
46 | accountname: accountname,
47 | password: this.hash(password),
48 | right: right,
49 | state: state
50 | }
51 | pool.getConnection((err, connection) => {
52 | if (err) throw err;
53 | connection.query('INSERT INTO `users` (user_name,user_psd,user_account,user_state,right_id,user_mobile) values (?, ?, ?, ?, ?, ?)',
54 | [params.username, params.password, params.accountname, params.state, params.right, params.mobile], (err, results) => {
55 | if (err) throw err;
56 |
57 | cb(results);
58 |
59 | connection.release();
60 | })
61 |
62 | })
63 | },
64 |
65 | // 查询用户列表
66 | queryAllUser: function (cb) {
67 | pool.getConnection((err,connection) => {
68 | if (err) throw err;
69 | connection.query('SELECT id,user_name,user_account,right_id,user_mobile FROM `users`', (err, result) => {
70 | if (err) throw err;
71 | console.log('查询用户列表结果result是')
72 | console.log(result)
73 | cb(result);
74 | connection.release();
75 | })
76 | })
77 | },
78 |
79 | // 删除用户
80 | deleteUser: function (id, cb) {
81 | pool.getConnection((err, conn) => {
82 | if (err) throw err;
83 | const sql = `
84 | delete from users
85 | where id not in (
86 | select u.id from assets
87 | inner join (select * from users) as u on assets.user_id = u.id
88 | ) and id = ?
89 | ` // mysql 不能在判断条件中再from要更新的表 故 采用 select ... as u
90 | conn.query(sql, id, (err, result) => {
91 | console.log('------result------')
92 | console.log(result.affectedRows);
93 | // console.log(result.length);
94 | if (err) throw err;
95 | cb(result);
96 | conn.release();
97 | })
98 |
99 | })
100 | },
101 |
102 | //修改用户
103 | // UPDATE <表名> SET 列名=值表达式[,列名=值表达式…]
104 | // [WHERE 条件表达式]
105 | updateUser: function (username, accountname, mobile, right, state, cb) {
106 | pool.getConnection((err, connection) => {
107 | if (err) throw err;
108 | connection.query('UPDATE `users` SET user_name=?,user_account=?,right_id=?,user_mobile=?,user_state=? WHERE id=?', [username, accountname, right, mobile, state], (err, results) => {
109 | if (err) throw err;
110 | cb(results);
111 | connection.release();
112 | })
113 | })
114 | },
115 |
116 | /**
117 | * 使用人列表查询,用作填充下拉框
118 | *
119 | * @param {*} id 当前登录用户id
120 | */
121 | queryUserList(id, cb) {
122 | pool.getConnection((err, connection) => {
123 | if (err) throw err;
124 | const sql = `
125 | select id, user_name
126 | from users
127 | where right_id = 1
128 | `
129 | connection.query(sql, id, (err, result) => {
130 | if (err) throw err
131 |
132 | cb(result)
133 |
134 | connection.release()
135 | })
136 | })
137 | },
138 |
139 | // 通过id查询用户
140 | queryUserById(id, cb) {
141 | pool.getConnection((err, conn) => {
142 | if (err) throw err
143 | const sql = `
144 | select user_name
145 | from users
146 | where id = ?
147 | `
148 | console.log('执行了查询数据操作')
149 | console.log(sql, id)
150 | conn.query(sql, id, (err, result) => {
151 | if (err) throw err
152 | cb(result)
153 | conn.release()
154 | })
155 | })
156 | },
157 |
158 | // 更新用户信息
159 | updateUserInfo(params, id, cb) {
160 | pool.getConnection((err, conn) => {
161 | if (err) throw err
162 | const sql = `
163 | update users
164 | set user_name = ?,user_mobile = ?,user_psd = ?
165 | where
166 | id = ?
167 | `
168 | conn.query(sql, [params.name, params.mobile, this.hash(params.newPass), id], (err, result) => {
169 | if (err) throw err
170 | cb(result)
171 | conn.release()
172 | })
173 | })
174 | }
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/server/public/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/server/public/test.jpg
--------------------------------------------------------------------------------
/server/schema/assets.js:
--------------------------------------------------------------------------------
1 | /* jshint indent: 2 */
2 |
3 | module.exports = function(sequelize, DataTypes) {
4 | return sequelize.define('assets', {
5 | id: {
6 | type: DataTypes.INTEGER(11),
7 | allowNull: false,
8 | primaryKey: true,
9 | autoIncrement: true
10 | },
11 | asset_name: {
12 | type: DataTypes.STRING,
13 | allowNull: true
14 | },
15 | user_id: {
16 | type: DataTypes.INTEGER(11),
17 | allowNull: true
18 | },
19 | asset_bill: {
20 | type: DataTypes.STRING,
21 | allowNull: true
22 | },
23 | buy_date: {
24 | type: DataTypes.DATE,
25 | allowNull: true
26 | },
27 | asset_price: {
28 | type: DataTypes.INTEGER(11),
29 | allowNull: true
30 | },
31 | asset_standard: {
32 | type: DataTypes.STRING,
33 | allowNull: true
34 | },
35 | asset_leavedate: {
36 | type: DataTypes.DATE,
37 | allowNull: true
38 | },
39 | asset_submitdate: {
40 | type: DataTypes.DATE,
41 | allowNull: true
42 | },
43 | asset_usedirection: {
44 | type: DataTypes.STRING,
45 | allowNull: true
46 | },
47 | asset_leavenum: {
48 | type: DataTypes.STRING,
49 | allowNull: true
50 | },
51 | asset_brand: {
52 | type: DataTypes.STRING,
53 | allowNull: true
54 | },
55 | asset_organization: {
56 | type: DataTypes.STRING,
57 | allowNull: true
58 | },
59 | asset_purchaser: {
60 | type: DataTypes.STRING,
61 | allowNull: true
62 | },
63 | asset_attachnum: {
64 | type: DataTypes.INTEGER(11),
65 | allowNull: true
66 | },
67 | asset_attachamount: {
68 | type: "DOUBLE",
69 | allowNull: true
70 | },
71 | funds_id: {
72 | type: DataTypes.INTEGER(11),
73 | allowNull: true
74 | },
75 | asset_signature: {
76 | type: DataTypes.STRING,
77 | allowNull: true
78 | },
79 | asset_imgurl: {
80 | type: DataTypes.STRING,
81 | allowNull: true
82 | },
83 | asset_orgid: {
84 | type: DataTypes.INTEGER(11),
85 | allowNull: true
86 | },
87 | asset_state: {
88 | type: DataTypes.INTEGER(11),
89 | allowNull: true
90 | },
91 | asset_mark: {
92 | type: DataTypes.STRING,
93 | allowNull: true
94 | }
95 | }, {
96 | tableName: 'assets'
97 | });
98 | };
99 |
--------------------------------------------------------------------------------
/server/schema/dictionarys.js:
--------------------------------------------------------------------------------
1 | /* jshint indent: 2 */
2 |
3 | module.exports = function(sequelize, DataTypes) {
4 | return sequelize.define('dictionarys', {
5 | id: {
6 | type: DataTypes.INTEGER(11),
7 | allowNull: false,
8 | primaryKey: true,
9 | autoIncrement: true
10 | },
11 | org_nane: {
12 | type: DataTypes.STRING,
13 | allowNull: true
14 | },
15 | fundname: {
16 | type: DataTypes.STRING,
17 | allowNull: true
18 | },
19 | cgzzxs: {
20 | type: DataTypes.STRING,
21 | allowNull: true
22 | }
23 | }, {
24 | tableName: 'dictionarys'
25 | });
26 | };
27 |
--------------------------------------------------------------------------------
/server/schema/resource.js:
--------------------------------------------------------------------------------
1 | /* jshint indent: 2 */
2 |
3 | module.exports = function(sequelize, DataTypes) {
4 | return sequelize.define('resource', {
5 | id: {
6 | type: DataTypes.INTEGER(11),
7 | allowNull: false,
8 | primaryKey: true
9 | },
10 | user_id: {
11 | type: DataTypes.INTEGER(11),
12 | allowNull: true
13 | },
14 | type_num: {
15 | type: DataTypes.STRING,
16 | allowNull: true
17 | },
18 | storage_place: {
19 | type: DataTypes.STRING,
20 | allowNull: true
21 | },
22 | asset_id: {
23 | type: DataTypes.INTEGER(11),
24 | allowNull: true
25 | }
26 | }, {
27 | tableName: 'resource'
28 | });
29 | };
30 |
--------------------------------------------------------------------------------
/server/schema/users.js:
--------------------------------------------------------------------------------
1 | /* jshint indent: 2 */
2 |
3 | module.exports = function(sequelize, DataTypes) {
4 | return sequelize.define('users', {
5 | id: {
6 | type: DataTypes.INTEGER(11),
7 | allowNull: false,
8 | primaryKey: true,
9 | autoIncrement: true
10 | },
11 | user_name: {
12 | type: DataTypes.STRING,
13 | allowNull: true
14 | },
15 | user_psd: {
16 | type: DataTypes.STRING,
17 | allowNull: true
18 | },
19 | user_account: {
20 | type: DataTypes.STRING,
21 | allowNull: true
22 | },
23 | user_state: {
24 | type: DataTypes.INTEGER(11),
25 | allowNull: true
26 | },
27 | right_id: {
28 | type: DataTypes.INTEGER(11),
29 | allowNull: true
30 | }
31 | }, {
32 | tableName: 'users'
33 | });
34 | };
35 |
--------------------------------------------------------------------------------
/server/sql/sqlString.js:
--------------------------------------------------------------------------------
1 | // sql语句
2 | var sqlString = {
3 | // 增加用户
4 | user: {
5 | add: 'insert into user(id, name, age) values (0, ?, ?)',
6 | delete: 'delete from user where id=?',
7 | update: 'update user set name=?, age=? where id=?',
8 | queryAll: 'select * from users',
9 | login: 'select user_account from users where user_name=? and user_psd=?'
10 | }
11 | }
12 |
13 | module.exports = sqlString;
--------------------------------------------------------------------------------
/server/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/server/uploads/avatar-1494579693303.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/server/uploads/avatar-1494579693303.jpeg
--------------------------------------------------------------------------------
/server/uploads/avatar-1494635642596.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/server/uploads/avatar-1494635642596.jpeg
--------------------------------------------------------------------------------
/server/uploads/avatar-1494653671089.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/server/uploads/avatar-1494653671089.jpeg
--------------------------------------------------------------------------------
/server/util/log.js:
--------------------------------------------------------------------------------
1 | const winston = require('winston')
2 | const path = require('path')
3 | const moment = require('moment')
4 | const PROJECT_ROOT = path.join(__dirname, '../')
5 |
6 | function getStackInfo(stackIndex) {
7 | const stacklist = (new Error()).stack.split('\n').slice(3)
8 | const stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi
9 | const stackReg2 = /at\s+()(.*):(\d*):(\d*)/gi
10 | const s = stacklist[stackIndex] || stacklist[0]
11 | const sp = stackReg.exec(s) || stackReg2.exec(s)
12 | if (sp && sp.length === 5) {
13 | return {
14 | method: sp[1],
15 | relativePath: path.relative(PROJECT_ROOT, sp[2]),
16 | line: sp[3],
17 | pos: sp[4],
18 | file: path.basename(sp[2]),
19 | stack: stacklist.join('\n'),
20 | }
21 | }
22 | }
23 |
24 | function formatLogArguments(iargs) {
25 | const args = Array.prototype.slice.call(iargs)
26 | const stackInfo = getStackInfo(1)
27 | if (stackInfo) {
28 | const calleeStr = '(' + stackInfo.relativePath + ':' + stackInfo.line + ')'
29 | args.unshift(calleeStr)
30 | }
31 | args.unshift(moment().format('YYYY-MM-DD HH:mm:ss'))
32 | return args
33 | }
34 |
35 | const logger = new (winston.Logger)({
36 | transports: [
37 | new (winston.transports.Console)({
38 | level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
39 | colorize: true,
40 | }),
41 | new (winston.transports.File)({ filename: 'somefile.log' })
42 | ],
43 | })
44 |
45 | function debug() {
46 | logger.debug.apply(logger, formatLogArguments(arguments))
47 | }
48 | module.exports.debug = debug
49 |
50 | function info() {
51 | logger.info.apply(logger, formatLogArguments(arguments))
52 | }
53 | module.exports.info = info
54 |
55 | function warn() {
56 | logger.warn.apply(logger, formatLogArguments(arguments))
57 | }
58 | module.exports.warn = warn
59 |
60 | function error() {
61 | logger.error.apply(logger, formatLogArguments(arguments))
62 | }
63 | module.exports.error = error
64 |
--------------------------------------------------------------------------------
/server/util/util.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extend: function(target, source, flag) {
3 | for(var key in source) {
4 | if(source.hasOwnProperty(key))
5 | flag ?
6 | (target[key] = source[key]) :
7 | (target[key] === void 0 && (target[key] = source[key]));
8 | }
9 | return target;
10 | }
11 | }
--------------------------------------------------------------------------------
/sql/ams.sql:
--------------------------------------------------------------------------------
1 | # ************************************************************
2 | # Sequel Pro SQL dump
3 | # Version 4541
4 | #
5 | # http://www.sequelpro.com/
6 | # https://github.com/sequelpro/sequelpro
7 | #
8 | # Host: 127.0.0.1 (MySQL 5.7.17)
9 | # Database: ams
10 | # Generation Time: 2017-06-22 02:30:49 +0000
11 | # ************************************************************
12 |
13 |
14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
17 | /*!40101 SET NAMES utf8 */;
18 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
19 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
20 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
21 |
22 |
23 | # Dump of table assets
24 | # ------------------------------------------------------------
25 |
26 | DROP TABLE IF EXISTS `assets`;
27 |
28 | CREATE TABLE `assets` (
29 | `id` int(11) NOT NULL AUTO_INCREMENT,
30 | `asset_name` varchar(255) DEFAULT NULL COMMENT '资产名',
31 | `user_id` int(11) DEFAULT NULL,
32 | `asset_number` varchar(255) DEFAULT NULL COMMENT '资产编号',
33 | `asset_bill` varchar(255) DEFAULT NULL COMMENT '发票号',
34 | `buy_date` datetime DEFAULT NULL COMMENT '购买日期',
35 | `asset_price` int(11) DEFAULT NULL COMMENT '单价',
36 | `asset_type` varchar(255) DEFAULT NULL COMMENT '型号',
37 | `asset_standard` varchar(255) DEFAULT NULL COMMENT '规格',
38 | `asset_leavedate` datetime DEFAULT NULL COMMENT '出厂日期',
39 | `asset_submitdate` datetime DEFAULT NULL COMMENT '订单提交日期',
40 | `asset_usedirection` varchar(255) DEFAULT NULL COMMENT '使用方向',
41 | `asset_leavenum` varchar(255) DEFAULT NULL COMMENT '出厂编号',
42 | `asset_brand` varchar(255) DEFAULT NULL COMMENT '厂家',
43 | `asset_storageplace` int(11) DEFAULT NULL COMMENT '存放地点',
44 | `asset_buyer` varchar(255) DEFAULT NULL COMMENT '申购单位',
45 | `asset_purchaser` varchar(255) DEFAULT NULL COMMENT '购买人',
46 | `asset_attachnum` int(11) DEFAULT NULL COMMENT '附件数',
47 | `asset_attachamount` double DEFAULT NULL COMMENT '附件金额',
48 | `funds_id` int(11) DEFAULT NULL COMMENT '经费来源id',
49 | `asset_signature` varchar(255) DEFAULT NULL COMMENT '经办人',
50 | `asset_imgurl` varchar(255) DEFAULT NULL COMMENT '资产图片',
51 | `asset_orgid` int(11) DEFAULT NULL COMMENT '采购组织形式',
52 | `asset_state` int(11) DEFAULT NULL COMMENT ',状态,0,1,23',
53 | `asset_mark` varchar(255) DEFAULT NULL COMMENT '备注',
54 | `calling` tinyint(1) DEFAULT '0' COMMENT '是否正在调用',
55 | PRIMARY KEY (`id`)
56 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
57 |
58 |
59 |
60 | # Dump of table calls
61 | # ------------------------------------------------------------
62 |
63 | DROP TABLE IF EXISTS `calls`;
64 |
65 | CREATE TABLE `calls` (
66 | `id` int(11) NOT NULL AUTO_INCREMENT,
67 | `asset_id` int(11) DEFAULT NULL COMMENT '资产id',
68 | `new_user_id` int(11) DEFAULT NULL COMMENT '新使用人',
69 | `new_storage_place_id` varchar(255) DEFAULT NULL COMMENT '新存放地点',
70 | `comment` varchar(255) DEFAULT NULL COMMENT '备注',
71 | PRIMARY KEY (`id`)
72 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
73 |
74 |
75 |
76 | # Dump of table journal
77 | # ------------------------------------------------------------
78 |
79 | DROP TABLE IF EXISTS `journal`;
80 |
81 | CREATE TABLE `journal` (
82 | `id` int(11) NOT NULL COMMENT '日志编号',
83 | `time` datetime DEFAULT NULL COMMENT '操作时间',
84 | `content` varchar(255) NOT NULL COMMENT '日志内容',
85 | PRIMARY KEY (`id`)
86 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
87 |
88 |
89 |
90 | # Dump of table notice
91 | # ------------------------------------------------------------
92 |
93 | DROP TABLE IF EXISTS `notice`;
94 |
95 | CREATE TABLE `notice` (
96 | `id` int(11) NOT NULL COMMENT '通知id',
97 | `user_id` int(11) NOT NULL COMMENT '用户id',
98 | `content` varchar(255) DEFAULT NULL COMMENT '通知内容',
99 | PRIMARY KEY (`id`)
100 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
101 |
102 |
103 |
104 | # Dump of table resource
105 | # ------------------------------------------------------------
106 |
107 | DROP TABLE IF EXISTS `resource`;
108 |
109 | CREATE TABLE `resource` (
110 | `id` int(11) NOT NULL AUTO_INCREMENT,
111 | `type_id` int(11) NOT NULL COMMENT '字典类型id',
112 | `name` varchar(255) DEFAULT NULL COMMENT '存放地点',
113 | PRIMARY KEY (`id`)
114 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
115 |
116 |
117 |
118 | # Dump of table resource_type
119 | # ------------------------------------------------------------
120 |
121 | DROP TABLE IF EXISTS `resource_type`;
122 |
123 | CREATE TABLE `resource_type` (
124 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '字典类型id',
125 | `name` varchar(30) DEFAULT NULL COMMENT '字典名称',
126 | PRIMARY KEY (`id`)
127 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
128 |
129 |
130 |
131 | # Dump of table users
132 | # ------------------------------------------------------------
133 |
134 | DROP TABLE IF EXISTS `users`;
135 |
136 | CREATE TABLE `users` (
137 | `id` int(11) NOT NULL AUTO_INCREMENT,
138 | `user_name` varchar(255) DEFAULT NULL COMMENT '用户名',
139 | `user_psd` varchar(255) DEFAULT NULL COMMENT '用户密码',
140 | `user_account` varchar(255) DEFAULT NULL COMMENT '账号',
141 | `user_state` int(11) DEFAULT NULL COMMENT '0可用1不可用',
142 | `right_id` int(11) DEFAULT NULL COMMENT '权限id',
143 | `user_mobile` varchar(11) DEFAULT NULL COMMENT '联系方式',
144 | PRIMARY KEY (`id`)
145 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
146 |
147 |
148 |
149 |
150 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
151 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
152 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
153 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
154 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
155 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
156 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | // import Vue from 'vue'
2 | // import axios from 'axios'
3 | // import VueAxios from 'vue-axios'
4 |
5 | // Vue.use(VueAxios, axios)
6 |
7 | // const instance = axios.create();
8 |
9 | // if (localStorage.getItem('user')) {
10 | // instance.defaults.headers.common['Authorization'] = 'Bearer' + localStorage.getItem('user').replace(/(^\")|(\"$)/g, '')
11 | // }
12 |
13 | // export default {
14 | // localLogin: function (data) {
15 | // console.log('client api 执行了')
16 | // console.log(data)
17 | // return Vue.axios.post('/api/user/login', data)
18 | // },
19 | // localLogout: function (data) {
20 | // return instance.post('/api/logout', data)
21 | // },
22 | // localReg: function (data) {
23 | // return Vue.axios.post('/api/reg', data)
24 | // }
25 | // }
--------------------------------------------------------------------------------
/src/axios.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import router from './router/index'
3 | import store from './store/index'
4 | import * as types from './store/types'
5 |
6 | axios.defaults.timeout = 5000
7 | axios.defaults.headers.post['Content-Type'] = 'application/json'
8 |
9 | const instance = axios.create()
10 |
11 | instance.defaults.headers.post['Content-Type'] = 'application/json'
12 |
13 | axios.interceptors.request.use = instance.interceptors.request.use
14 |
15 | instance.interceptors.request.use(config => {
16 | if (localStorage.getItem('token')) {
17 | config.headers.Authorization = `token ${localStorage.getItem('token')}`
18 | .replace(/(^\")|(\"$)/g, '')
19 | }
20 | return config
21 | }, err => {
22 | return Promise.reject(err)
23 | })
24 |
25 | // axios 拦截响应
26 | instance.interceptors.response.use(response => {
27 | return response
28 | }, err => {
29 | return Promise.reject(err)
30 | })
31 |
32 | export default {
33 | // 用户注册
34 | userRegister(data) {
35 | return instance.post('/api/register', data)
36 | },
37 | // 用户登录
38 | UserLogin(data) {
39 | return instance.post('/api/login', data)
40 | },
41 | // 获取用户
42 | getUser() {
43 | return instance.get('/api/user')
44 | },
45 | // 删除用户
46 | delUser(data) {
47 | return instance.post('/api/delUser', data)
48 | }
49 | }
--------------------------------------------------------------------------------
/src/components/Hello.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
15 |
16 |
19 |
--------------------------------------------------------------------------------
/src/components/asset/Addasset.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
157 |
158 |
159 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 | 保存
178 |
179 |
180 |
181 |
182 |
183 |
349 |
350 |
359 |
--------------------------------------------------------------------------------
/src/components/asset/Callasset.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 查询
12 |
13 |
14 |
15 |
16 |
20 |
23 |
24 |
27 |
28 |
31 |
32 |
35 |
36 |
39 |
40 |
43 |
44 |
47 |
48 |
51 |
52 |
55 |
56 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | 提交
77 |
78 |
79 |
80 |
81 |
82 |
83 |
234 |
235 |
243 |
--------------------------------------------------------------------------------
/src/components/asset/CallassetCheck.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
待审列表
4 |
5 |
8 |
9 |
10 |
11 |
12 | {{ props.row.assetName }}
13 |
14 |
15 | {{ props.row.oldUserName }}
16 |
17 |
18 | {{ props.row.newUserName }}
19 |
20 |
21 | {{ props.row.oldStoragePlace }}
22 |
23 |
24 | {{ props.row.newStoragePlace }}
25 |
26 |
27 | {{ props.row.comment }}
28 |
29 |
30 |
31 |
32 |
35 |
36 |
39 |
40 |
43 |
44 |
47 |
48 |
51 |
52 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
176 |
177 |
190 |
204 |
--------------------------------------------------------------------------------
/src/components/asset/QueryAllAsset.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 查询
10 |
11 |
12 | 导出Excel
13 |
14 |
15 |
16 |
17 |
20 |
21 |
24 |
25 |
28 |
29 |
32 |
33 |
36 |
37 |
40 |
41 |
44 |
45 |
48 |
49 |
50 |
51 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
210 |
211 |
224 |
238 |
--------------------------------------------------------------------------------
/src/components/asset/Queryasset.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
待审列表
6 |
资产列表
7 |
8 |
11 |
12 |
15 |
16 |
19 |
20 |
23 |
24 |
27 |
28 |
31 |
32 |
35 |
36 |
39 |
40 |
44 |
45 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
61 |
62 |
66 |
67 |
68 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
286 |
287 |
300 |
301 |
315 |
--------------------------------------------------------------------------------
/src/components/asset/expand/Expand.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ props.row.assetName }}
7 |
8 |
9 | {{ props.row.userName }}
10 |
11 |
12 | {{ props.row.assetNumber }}
13 |
14 |
15 | {{ props.row.bill }}
16 |
17 |
18 | {{ props.row.buyDate }}
19 |
20 |
21 | {{ props.row.price }}
22 |
23 |
24 | {{ props.row.type }}
25 |
26 |
27 | {{ props.row.standard }}
28 |
29 |
30 | {{ props.row.leaveDate }}
31 |
32 |
33 | {{ props.row.useDirection }}
34 |
35 |
36 | {{ props.row.leaveNumber }}
37 |
38 |
39 | {{ props.row.brand }}
40 |
41 |
42 | {{ props.row.storagePlace }}
43 |
44 |
45 | {{ props.row.buyer }}
46 |
47 |
48 | {{ props.row.purchaser }}
49 |
50 |
51 | {{ props.row.attachNum }}
52 |
53 |
54 | {{ props.row.attachAmount }}
55 |
56 |
57 | {{ props.row.funds }}
58 |
59 |
60 | {{ props.row.signature }}
61 |
62 |
63 | {{ props.row.organization }}
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
82 |
83 |
96 |
97 |
111 |
--------------------------------------------------------------------------------
/src/components/common/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
18 |
19 |
30 |
--------------------------------------------------------------------------------
/src/components/common/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
30 |
31 |
32 |
68 |
69 |
100 |
--------------------------------------------------------------------------------
/src/components/common/Sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
39 |
40 |
43 |
--------------------------------------------------------------------------------
/src/components/dashboard/Dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
资产概览
4 |
5 |
6 |
7 |
8 | 系统资产总数
9 | {{ assetCount }}
10 |
11 |
12 |
13 |
14 | 待审申报资产
15 | {{ unCheckAssetCount }}
16 |
17 |
18 |
19 |
20 | 待审调用资产
21 | {{ callAssetCount }}
22 |
23 |
24 |
25 |
26 |
27 |
28 | 实验室存放资产
29 | {{ callAssetCount }}
30 |
31 |
32 |
33 |
34 |
申请动态
35 |
38 |
42 |
43 |
47 |
48 |
51 |
52 |
55 |
56 |
57 |
58 |
66 |
67 |
68 |
69 |
70 |
71 |
183 |
184 |
198 |
--------------------------------------------------------------------------------
/src/components/index/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
36 |
37 |
53 |
--------------------------------------------------------------------------------
/src/components/login/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
资产管理系统
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 登录
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
58 |
59 |
96 |
--------------------------------------------------------------------------------
/src/components/personal/Personal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
修改信息
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 保存
23 |
24 |
25 |
26 |
27 |
28 |
29 |
94 |
95 |
103 |
--------------------------------------------------------------------------------
/src/components/resource/Resource.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
字典管理
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 增加
15 |
16 |
17 |
20 |
24 |
25 |
28 |
29 |
30 |
31 |
39 |
40 |
41 |
42 |
43 |
44 |
115 |
116 |
122 |
--------------------------------------------------------------------------------
/src/components/user/User.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
用户列表
5 | 新增用户
6 |
7 |
10 |
14 |
15 |
19 |
20 |
23 |
24 |
27 |
28 |
29 |
30 |
34 |
39 |
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | 保存
73 | 取消
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
199 |
200 |
251 |
--------------------------------------------------------------------------------
/src/lib/auth.js:
--------------------------------------------------------------------------------
1 | export const types = {
2 | isAdmin: '0',
3 | addasset: '1',
4 | callasset: '1'
5 | }
6 |
7 | export const auth = {
8 | checkAuth: function (right) {
9 | const localRight = (JSON.parse(localStorage.getItem('user')).right_id).toString()
10 | return localRight === right
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/vue-cookie.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | Number.isInteger = Number.isInteger || function (value) {
3 | return typeof value === 'number' &&
4 | isFinite(value) &&
5 | Math.floor(value) === value;
6 | };
7 | var Cookie = require('tiny-cookie');
8 |
9 | var VueCookie = {
10 |
11 | install: function (Vue) {
12 | Vue.prototype.$cookie = this;
13 | Vue.cookie = this;
14 | },
15 | set: function (name, value, daysOrOptions) {
16 | var opts = daysOrOptions;
17 | if(Number.isInteger(daysOrOptions)) {
18 | opts = {expires: daysOrOptions};
19 | }
20 | return Cookie.set(name, value, opts);
21 | },
22 |
23 | get: function (name) {
24 | return Cookie.get(name);
25 | },
26 |
27 | delete: function (name, options) {
28 | var opts = {expires: -1};
29 | if(options !== undefined) {
30 | opts = Object.assign(options, opts);
31 | }
32 | this.set(name, '', opts);
33 | }
34 | };
35 |
36 | if (typeof exports == "object") {
37 | module.exports = VueCookie;
38 | } else if (typeof define == "function" && define.amd) {
39 | define([], function(){ return VueCookie; })
40 | } else if (window.Vue) {
41 | window.VueCookie = VueCookie;
42 | Vue.use(VueCookie);
43 | }
44 |
45 | })();
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App'
5 | import router from './router'
6 | import ElementUI from 'element-ui'
7 | import 'element-ui/lib/theme-default/index.css'
8 | import axios from 'axios'
9 | import store from './store/index'
10 |
11 | Vue.use(ElementUI)
12 | console.log(Vue.prototype.$http)
13 | Vue.prototype.$http = axios
14 | console.log(2)
15 |
16 | //设置cookie,增加到vue实例方便全局调用
17 | //vue全局调用的理由是,有些组件所用到的接口可能需要session验证,session从cookie获取
18 | //当然,如果session保存到vuex的话除外
19 | Vue.prototype.setCookie = (c_name, value, expiredays) => {
20 | var exdate = new Date();
21 | exdate.setDate(exdate.getDate() + expiredays);
22 | document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
23 | }
24 |
25 | //获取cookie、
26 | function getCookie(name) {
27 | var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
28 | if (arr = document.cookie.match(reg))
29 | return (arr[2]);
30 | else
31 | return null;
32 | }
33 | Vue.prototype.getCookie = getCookie;
34 |
35 | //删除cookie
36 | Vue.prototype.delCookie =(name) => {
37 | var exp = new Date();
38 | exp.setTime(exp.getTime() - 1);
39 | var cval = getCookie(name);
40 | if (cval != null)
41 | document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
42 | }
43 |
44 |
45 | // router.beforeEach(({meta, path}, from, next) => {
46 | // const {auth = true } = meta
47 | // const isLogin = Boolean(store.state.login.token)
48 |
49 | // if (auth && !isLogin && path !== '/login') {
50 | // return next({path: '/login'})
51 | // }
52 | // if (isLogin && (path == '/login' || path == '/reg')) {
53 | // return next({path: '/person'})
54 | // }
55 | // next()
56 | // })
57 |
58 | Vue.config.productionTip = false
59 |
60 | /* eslint-disable no-new */
61 | new Vue({
62 | el: '#app',
63 | router,
64 | store,
65 | template: '',
66 | components: { App }
67 | })
68 | // new Vue({
69 | // axios,
70 | // store,
71 | // router,
72 | // render: h => h(App)
73 | // }).$mount('#app')
74 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Index from '@/components/index/Index'
4 | import Dashboard from '@/components/dashboard/Dashboard'
5 | import Login from '@/components/login/Login'
6 | import Addasset from '@/components/asset/Addasset'
7 | import Queryasset from '@/components/asset/Queryasset'
8 | import QueryAllAsset from '@/components/asset/QueryAllAsset'
9 | import Callasset from '@/components/asset/Callasset'
10 | import CallassetCheck from '@/components/asset/CallassetCheck'
11 | import User from '@/components/user/User'
12 | import Resource from '@/components/resource/Resource'
13 | import Personal from '@/components/personal/Personal'
14 |
15 | Vue.use(Router)
16 |
17 | export default new Router({
18 | mode: 'history',
19 | scrollBehavior: (to) => {
20 | if (to.hash) {
21 | return {selector: to.hash}
22 | }
23 | return {x: 0, y: 0}
24 | },
25 | routes: [
26 | {
27 | path: '/',
28 | component: Index,
29 | children: [
30 | {
31 | path: '/dashboard',
32 | component: Dashboard
33 | },
34 | {
35 | path: '/addasset',
36 | component: Addasset
37 | },
38 | {
39 | path: '/queryasset',
40 | component: Queryasset
41 | },
42 | {
43 | path: '/query-all-asset',
44 | component: QueryAllAsset
45 | },
46 | {
47 | path: '/callasset',
48 | component: Callasset
49 | },
50 | {
51 | path: '/callasset-check',
52 | component: CallassetCheck
53 | },
54 | {
55 | path: '/user',
56 | component: User,
57 | // meta: {requiresAuth: true}
58 | },
59 | {
60 | path: '/resource',
61 | component: Resource,
62 | },
63 | {
64 | path: '/personal',
65 | component: Personal
66 | },]
67 | },
68 | {
69 | path: '/login',
70 | component: Login
71 | },
72 | {
73 | path: '/*',
74 | redirect: '/login'
75 | }
76 | ]
77 | })
78 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | // import api from '../api'
2 | import * as types from './types'
3 |
4 | console.log('actions')
5 | console.log(this.$http)
6 | export const UserLogin = ({ commit }, data) => {
7 | console.log('data', data)
8 | this.$http.post('/api/user/login', data, (res) => {
9 | var user = res.data[0]
10 | // ...
11 | if(true) {
12 | console.log('发送了commit')
13 | commit(types.USER_SIGNIN, user);
14 | // window.location = '/'
15 | }else{
16 | // window.location = '/login'
17 | }
18 | })
19 | };
20 |
21 | export const UserLogout = ({ commit }, data) => {
22 | this.$http.post('/api/logout', data, (res) => {
23 | commit(types.USER_SIGNOUT);
24 | window.location = '/login'
25 | })
26 | };
27 |
28 | export const UserReg = ({ commit }, data) => {
29 | this.$http.post('/api/reg', data, (res) => {
30 | if( res.data.type == true) {
31 | commit(types.USER_REG, res.data.token);
32 | window.location = '/person'
33 | }
34 | })
35 | };
36 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | export const UserInfo = state => state.login.token
2 | export const getName = state => { return state.name}
3 | export const getRight = state => {return state.right}
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import * as actions from './actions'
4 | import { state, mutations } from './mutations'
5 | import * as getters from './getters'
6 | import login from './modules/login'
7 |
8 | Vue.use(Vuex);
9 |
10 | const debug = process.env.NODE_ENV !== 'production';
11 |
12 | export default new Vuex.Store({
13 | state,
14 | actions,
15 | getters,
16 | mutations,
17 | modules: {
18 | login: login
19 | },
20 | strict: debug
21 | })
22 |
--------------------------------------------------------------------------------
/src/store/modules/login.js:
--------------------------------------------------------------------------------
1 | import { USER_SIGNIN, USER_SIGNOUT, USER_REG } from '../types'
2 |
3 | const isLoggedIn = function () {
4 | var token = localStorage.getItem('user')
5 | if (token) {
6 | // var payload = JSON.parse(window.atob(token.split('.')[1]));
7 | // if (payload.exp > Date.now() / 1000) {
8 | // return JSON.parse(localStorage.getItem('user'))
9 | // }
10 | } else {
11 | return false
12 | }
13 | }
14 |
15 | const state = {
16 | token: isLoggedIn() || null,
17 | name: null,
18 | right: null,
19 | }
20 |
21 | const mutations = {
22 | [USER_SIGNIN] (state, user) {
23 | localStorage.setItem('user', JSON.stringify(user));
24 | state.token = user
25 | },
26 | [USER_SIGNOUT] (state) {
27 | localStorage.removeItem('user')
28 | state.token = null
29 | },
30 | [USER_REG] (state, user) {
31 | localStorage.setItem('user', JSON.stringify(user))
32 | state.token = user
33 | }
34 | }
35 |
36 | export default {
37 | state,
38 | mutations
39 | }
--------------------------------------------------------------------------------
/src/store/modules/user.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/src/store/modules/user.js
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | import * as types from './types'
2 |
3 | export const state = {
4 | token: null,
5 | name: null,
6 | right: null
7 | }
8 | export const mutations = {
9 | [types.USER_SIGNIN] (state, data) {
10 | console.log('mutation data')
11 | console.log(data)
12 | // localStorage.setItem('token', data)
13 | localStorage.setItem('name', data.user_name)
14 | localStorage.setItem('right', data.right_id)
15 | console.log('localstorage 里面内容是')
16 | console.log(localStorage.getItem('name'), localStorage.getItem('right'))
17 | // state.token = data
18 | state.name = data.user_name
19 | state.right = data.right_id
20 | },
21 | [types.USER_SIGNOUT] (state) {
22 | localStorage.removeItem('token')
23 | state.token = null
24 | },
25 | [types.USER_REG] (state, data) {
26 | localStorage.setItem('username', data)
27 | state.username = data
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/store/types.js:
--------------------------------------------------------------------------------
1 | export const USER_SIGNIN = 'USER_SIGNIN' //登录成功
2 | export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登录
3 | export const USER_REG = 'USER_REG'
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/static/.gitkeep
--------------------------------------------------------------------------------
/static/css/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #f5f5f5;
3 | }
4 | h1, h2, h3, h4, h5, h6 {
5 | font-weight: normal;
6 | }
7 |
--------------------------------------------------------------------------------
/static/css/reset.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
2 |
3 | /**
4 | * 1. Change the default font family in all browsers (opinionated).
5 | * 2. Correct the line height in all browsers.
6 | * 3. Prevent adjustments of font size after orientation changes in
7 | * IE on Windows Phone and in iOS.
8 | */
9 |
10 | /* Document
11 | ========================================================================== */
12 |
13 | html {
14 | font-family: sans-serif; /* 1 */
15 | line-height: 1.15; /* 2 */
16 | -ms-text-size-adjust: 100%; /* 3 */
17 | -webkit-text-size-adjust: 100%; /* 3 */
18 | }
19 |
20 | /* Sections
21 | ========================================================================== */
22 |
23 | /**
24 | * Remove the margin in all browsers (opinionated).
25 | */
26 |
27 | body {
28 | margin: 0;
29 | }
30 |
31 | /**
32 | * Add the correct display in IE 9-.
33 | */
34 |
35 | article,
36 | aside,
37 | footer,
38 | header,
39 | nav,
40 | section {
41 | display: block;
42 | }
43 |
44 | /**
45 | * Correct the font size and margin on `h1` elements within `section` and
46 | * `article` contexts in Chrome, Firefox, and Safari.
47 | */
48 |
49 | h1 {
50 | font-size: 2em;
51 | margin: 0.67em 0;
52 | }
53 |
54 | /* Grouping content
55 | ========================================================================== */
56 |
57 | /**
58 | * Add the correct display in IE 9-.
59 | * 1. Add the correct display in IE.
60 | */
61 |
62 | figcaption,
63 | figure,
64 | main { /* 1 */
65 | display: block;
66 | }
67 |
68 | /**
69 | * Add the correct margin in IE 8.
70 | */
71 |
72 | figure {
73 | margin: 1em 40px;
74 | }
75 |
76 | /**
77 | * 1. Add the correct box sizing in Firefox.
78 | * 2. Show the overflow in Edge and IE.
79 | */
80 |
81 | hr {
82 | box-sizing: content-box; /* 1 */
83 | height: 0; /* 1 */
84 | overflow: visible; /* 2 */
85 | }
86 |
87 | /**
88 | * 1. Correct the inheritance and scaling of font size in all browsers.
89 | * 2. Correct the odd `em` font sizing in all browsers.
90 | */
91 |
92 | pre {
93 | font-family: monospace, monospace; /* 1 */
94 | font-size: 1em; /* 2 */
95 | }
96 |
97 | /* Text-level semantics
98 | ========================================================================== */
99 |
100 | /**
101 | * 1. Remove the gray background on active links in IE 10.
102 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
103 | */
104 |
105 | a {
106 | background-color: transparent; /* 1 */
107 | -webkit-text-decoration-skip: objects; /* 2 */
108 | }
109 |
110 | /**
111 | * Remove the outline on focused links when they are also active or hovered
112 | * in all browsers (opinionated).
113 | */
114 |
115 | a:active,
116 | a:hover {
117 | outline-width: 0;
118 | }
119 |
120 | /**
121 | * 1. Remove the bottom border in Firefox 39-.
122 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
123 | */
124 |
125 | abbr[title] {
126 | border-bottom: none; /* 1 */
127 | text-decoration: underline; /* 2 */
128 | text-decoration: underline dotted; /* 2 */
129 | }
130 |
131 | /**
132 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
133 | */
134 |
135 | b,
136 | strong {
137 | font-weight: inherit;
138 | }
139 |
140 | /**
141 | * Add the correct font weight in Chrome, Edge, and Safari.
142 | */
143 |
144 | b,
145 | strong {
146 | font-weight: bolder;
147 | }
148 |
149 | /**
150 | * 1. Correct the inheritance and scaling of font size in all browsers.
151 | * 2. Correct the odd `em` font sizing in all browsers.
152 | */
153 |
154 | code,
155 | kbd,
156 | samp {
157 | font-family: monospace, monospace; /* 1 */
158 | font-size: 1em; /* 2 */
159 | }
160 |
161 | /**
162 | * Add the correct font style in Android 4.3-.
163 | */
164 |
165 | dfn {
166 | font-style: italic;
167 | }
168 |
169 | /**
170 | * Add the correct background and color in IE 9-.
171 | */
172 |
173 | mark {
174 | background-color: #ff0;
175 | color: #000;
176 | }
177 |
178 | /**
179 | * Add the correct font size in all browsers.
180 | */
181 |
182 | small {
183 | font-size: 80%;
184 | }
185 |
186 | /**
187 | * Prevent `sub` and `sup` elements from affecting the line height in
188 | * all browsers.
189 | */
190 |
191 | sub,
192 | sup {
193 | font-size: 75%;
194 | line-height: 0;
195 | position: relative;
196 | vertical-align: baseline;
197 | }
198 |
199 | sub {
200 | bottom: -0.25em;
201 | }
202 |
203 | sup {
204 | top: -0.5em;
205 | }
206 |
207 | /* Embedded content
208 | ========================================================================== */
209 |
210 | /**
211 | * Add the correct display in IE 9-.
212 | */
213 |
214 | audio,
215 | video {
216 | display: inline-block;
217 | }
218 |
219 | /**
220 | * Add the correct display in iOS 4-7.
221 | */
222 |
223 | audio:not([controls]) {
224 | display: none;
225 | height: 0;
226 | }
227 |
228 | /**
229 | * Remove the border on images inside links in IE 10-.
230 | */
231 |
232 | img {
233 | border-style: none;
234 | }
235 |
236 | /**
237 | * Hide the overflow in IE.
238 | */
239 |
240 | svg:not(:root) {
241 | overflow: hidden;
242 | }
243 |
244 | /* Forms
245 | ========================================================================== */
246 |
247 | /**
248 | * 1. Change the font styles in all browsers (opinionated).
249 | * 2. Remove the margin in Firefox and Safari.
250 | */
251 |
252 | button,
253 | input,
254 | optgroup,
255 | select,
256 | textarea {
257 | font-family: sans-serif; /* 1 */
258 | font-size: 100%; /* 1 */
259 | line-height: 1.15; /* 1 */
260 | margin: 0; /* 2 */
261 | }
262 |
263 | /**
264 | * Show the overflow in IE.
265 | * 1. Show the overflow in Edge.
266 | */
267 |
268 | button,
269 | input { /* 1 */
270 | overflow: visible;
271 | }
272 |
273 | /**
274 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
275 | * 1. Remove the inheritance of text transform in Firefox.
276 | */
277 |
278 | button,
279 | select { /* 1 */
280 | text-transform: none;
281 | }
282 |
283 | /**
284 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
285 | * controls in Android 4.
286 | * 2. Correct the inability to style clickable types in iOS and Safari.
287 | */
288 |
289 | button,
290 | html [type="button"], /* 1 */
291 | [type="reset"],
292 | [type="submit"] {
293 | -webkit-appearance: button; /* 2 */
294 | }
295 |
296 | /**
297 | * Remove the inner border and padding in Firefox.
298 | */
299 |
300 | button::-moz-focus-inner,
301 | [type="button"]::-moz-focus-inner,
302 | [type="reset"]::-moz-focus-inner,
303 | [type="submit"]::-moz-focus-inner {
304 | border-style: none;
305 | padding: 0;
306 | }
307 |
308 | /**
309 | * Restore the focus styles unset by the previous rule.
310 | */
311 |
312 | button:-moz-focusring,
313 | [type="button"]:-moz-focusring,
314 | [type="reset"]:-moz-focusring,
315 | [type="submit"]:-moz-focusring {
316 | outline: 1px dotted ButtonText;
317 | }
318 |
319 | /**
320 | * Change the border, margin, and padding in all browsers (opinionated).
321 | */
322 |
323 | fieldset {
324 | border: 1px solid #c0c0c0;
325 | margin: 0 2px;
326 | padding: 0.35em 0.625em 0.75em;
327 | }
328 |
329 | /**
330 | * 1. Correct the text wrapping in Edge and IE.
331 | * 2. Correct the color inheritance from `fieldset` elements in IE.
332 | * 3. Remove the padding so developers are not caught out when they zero out
333 | * `fieldset` elements in all browsers.
334 | */
335 |
336 | legend {
337 | box-sizing: border-box; /* 1 */
338 | color: inherit; /* 2 */
339 | display: table; /* 1 */
340 | max-width: 100%; /* 1 */
341 | padding: 0; /* 3 */
342 | white-space: normal; /* 1 */
343 | }
344 |
345 | /**
346 | * 1. Add the correct display in IE 9-.
347 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
348 | */
349 |
350 | progress {
351 | display: inline-block; /* 1 */
352 | vertical-align: baseline; /* 2 */
353 | }
354 |
355 | /**
356 | * Remove the default vertical scrollbar in IE.
357 | */
358 |
359 | textarea {
360 | overflow: auto;
361 | }
362 |
363 | /**
364 | * 1. Add the correct box sizing in IE 10-.
365 | * 2. Remove the padding in IE 10-.
366 | */
367 |
368 | [type="checkbox"],
369 | [type="radio"] {
370 | box-sizing: border-box; /* 1 */
371 | padding: 0; /* 2 */
372 | }
373 |
374 | /**
375 | * Correct the cursor style of increment and decrement buttons in Chrome.
376 | */
377 |
378 | [type="number"]::-webkit-inner-spin-button,
379 | [type="number"]::-webkit-outer-spin-button {
380 | height: auto;
381 | }
382 |
383 | /**
384 | * 1. Correct the odd appearance in Chrome and Safari.
385 | * 2. Correct the outline style in Safari.
386 | */
387 |
388 | [type="search"] {
389 | -webkit-appearance: textfield; /* 1 */
390 | outline-offset: -2px; /* 2 */
391 | }
392 |
393 | /**
394 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
395 | */
396 |
397 | [type="search"]::-webkit-search-cancel-button,
398 | [type="search"]::-webkit-search-decoration {
399 | -webkit-appearance: none;
400 | }
401 |
402 | /**
403 | * 1. Correct the inability to style clickable types in iOS and Safari.
404 | * 2. Change font properties to `inherit` in Safari.
405 | */
406 |
407 | ::-webkit-file-upload-button {
408 | -webkit-appearance: button; /* 1 */
409 | font: inherit; /* 2 */
410 | }
411 |
412 | /* Interactive
413 | ========================================================================== */
414 |
415 | /*
416 | * Add the correct display in IE 9-.
417 | * 1. Add the correct display in Edge, IE, and Firefox.
418 | */
419 |
420 | details, /* 1 */
421 | menu {
422 | display: block;
423 | }
424 |
425 | /*
426 | * Add the correct display in all browsers.
427 | */
428 |
429 | summary {
430 | display: list-item;
431 | }
432 |
433 | /* Scripting
434 | ========================================================================== */
435 |
436 | /**
437 | * Add the correct display in IE 9-.
438 | */
439 |
440 | canvas {
441 | display: inline-block;
442 | }
443 |
444 | /**
445 | * Add the correct display in IE.
446 | */
447 |
448 | template {
449 | display: none;
450 | }
451 |
452 | /* Hidden
453 | ========================================================================== */
454 |
455 | /**
456 | * Add the correct display in IE 10-.
457 | */
458 |
459 | [hidden] {
460 | display: none;
461 | }
--------------------------------------------------------------------------------
/static/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/static/images/favicon.ico
--------------------------------------------------------------------------------
/static/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/static/images/logo.png
--------------------------------------------------------------------------------
/static/images/mac.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EryouHao/vue-ams/3b171713ae94ebd913d275fa6271f5d4022b9518/static/images/mac.png
--------------------------------------------------------------------------------
/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // the name of the method is the filename.
3 | // can be used in tests like this:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // for how to write custom assertions see
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 | exports.assertion = function (selector, count) {
10 | this.message = 'Testing if element <' + selector + '> has count: ' + count
11 | this.expected = count
12 | this.pass = function (val) {
13 | return val === this.expected
14 | }
15 | this.value = function (res) {
16 | return res.value
17 | }
18 | this.command = function (cb) {
19 | var self = this
20 | return this.api.execute(function (selector) {
21 | return document.querySelectorAll(selector).length
22 | }, [selector], function (res) {
23 | cb.call(self, res)
24 | })
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | var config = require('../../config')
3 |
4 | // http://nightwatchjs.org/getingstarted#settings-file
5 | module.exports = {
6 | src_folders: ['test/e2e/specs'],
7 | output_folder: 'test/e2e/reports',
8 | custom_assertions_path: ['test/e2e/custom-assertions'],
9 |
10 | selenium: {
11 | start_process: true,
12 | server_path: require('selenium-server').path,
13 | host: '127.0.0.1',
14 | port: 4444,
15 | cli_args: {
16 | 'webdriver.chrome.driver': require('chromedriver').path
17 | }
18 | },
19 |
20 | test_settings: {
21 | default: {
22 | selenium_port: 4444,
23 | selenium_host: 'localhost',
24 | silent: true,
25 | globals: {
26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
27 | }
28 | },
29 |
30 | chrome: {
31 | desiredCapabilities: {
32 | browserName: 'chrome',
33 | javascriptEnabled: true,
34 | acceptSslCerts: true
35 | }
36 | },
37 |
38 | firefox: {
39 | desiredCapabilities: {
40 | browserName: 'firefox',
41 | javascriptEnabled: true,
42 | acceptSslCerts: true
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server using production config
2 | process.env.NODE_ENV = 'testing'
3 | var server = require('../../build/dev-server.js')
4 |
5 | // 2. run the nightwatch test suite against it
6 | // to run in additional browsers:
7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
8 | // 2. add it to the --env flag below
9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
10 | // For more information on Nightwatch's config file, see
11 | // http://nightwatchjs.org/guide#settings-file
12 | var opts = process.argv.slice(2)
13 | if (opts.indexOf('--config') === -1) {
14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
15 | }
16 | if (opts.indexOf('--env') === -1) {
17 | opts = opts.concat(['--env', 'chrome'])
18 | }
19 |
20 | var spawn = require('cross-spawn')
21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
22 |
23 | runner.on('exit', function (code) {
24 | server.close()
25 | process.exit(code)
26 | })
27 |
28 | runner.on('error', function (err) {
29 | server.close()
30 | throw err
31 | })
32 |
--------------------------------------------------------------------------------
/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function (browser) {
6 | // automatically uses dev Server port from /config.index.js
7 | // default: http://localhost:8080
8 | // see nightwatch.conf.js
9 | const devServer = browser.globals.devServerURL
10 |
11 | browser
12 | .url(devServer)
13 | .waitForElementVisible('#app', 5000)
14 | .assert.elementPresent('.hello')
15 | .assert.containsText('h1', 'Welcome to Your Vue.js App')
16 | .assert.elementCount('img', 1)
17 | .end()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | },
5 | "globals": {
6 | "expect": true,
7 | "sinon": true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/test/unit/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | Vue.config.productionTip = false
3 |
4 | // Polyfill fn.bind() for PhantomJS
5 | /* eslint-disable no-extend-native */
6 | Function.prototype.bind = require('function-bind')
7 |
8 | // require all test files (files that ends with .spec.js)
9 | const testsContext = require.context('./specs', true, /\.spec$/)
10 | testsContext.keys().forEach(testsContext)
11 |
12 | // require all src files except main.js for coverage.
13 | // you can also change this to match only the subset of files that
14 | // you want coverage for.
15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/)
16 | srcContext.keys().forEach(srcContext)
17 |
--------------------------------------------------------------------------------
/test/unit/karma.conf.js:
--------------------------------------------------------------------------------
1 | // This is a karma config file. For more details see
2 | // http://karma-runner.github.io/0.13/config/configuration-file.html
3 | // we are also using it with karma-webpack
4 | // https://github.com/webpack/karma-webpack
5 |
6 | var webpackConfig = require('../../build/webpack.test.conf')
7 |
8 | module.exports = function (config) {
9 | config.set({
10 | // to run in additional browsers:
11 | // 1. install corresponding karma launcher
12 | // http://karma-runner.github.io/0.13/config/browsers.html
13 | // 2. add it to the `browsers` array below.
14 | browsers: ['PhantomJS'],
15 | frameworks: ['mocha', 'sinon-chai'],
16 | reporters: ['spec', 'coverage'],
17 | files: ['./index.js'],
18 | preprocessors: {
19 | './index.js': ['webpack', 'sourcemap']
20 | },
21 | webpack: webpackConfig,
22 | webpackMiddleware: {
23 | noInfo: true
24 | },
25 | coverageReporter: {
26 | dir: './coverage',
27 | reporters: [
28 | { type: 'lcov', subdir: '.' },
29 | { type: 'text-summary' }
30 | ]
31 | }
32 | })
33 | }
34 |
--------------------------------------------------------------------------------
/test/unit/specs/Hello.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Hello from '@/components/Hello'
3 |
4 | describe('Hello.vue', () => {
5 | it('should render correct contents', () => {
6 | const Constructor = Vue.extend(Hello)
7 | const vm = new Constructor().$mount()
8 | expect(vm.$el.querySelector('.hello h1').textContent)
9 | .to.equal('Welcome to Your Vue.js App')
10 | })
11 | })
12 |
--------------------------------------------------------------------------------