├── .babelrc ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── Dockerfile ├── LICENSE ├── README.md ├── build ├── build.js ├── check-versions.js ├── utils.js ├── vue-loader.conf.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js └── prod.env.js ├── default.conf ├── index.html ├── package-lock.json ├── package.json ├── pageview ├── API模板.jpg ├── API模板1.jpg ├── excel报告.jpg ├── 历史报告.jpg ├── 参数配置.jpg ├── 参数配置1.jpg ├── 后台管理系统.jpg ├── 域名管理.jpg ├── 定时任务.jpg ├── 定时任务1.jpg ├── 定时任务2.jpg ├── 定时任务3.jpg ├── 异步回执.jpg ├── 测试报告页面.jpg ├── 测试数据.jpg ├── 测试用例.jpg ├── 测试用例1.jpg ├── 测试用例2.jpg ├── 测试用例3.jpg ├── 环境变量.jpg ├── 登录.jpg ├── 项目概况.jpg ├── 首页页面.jpg ├── 驱动代码.jpg └── 驱动代码1.jpg ├── src ├── App.vue ├── assets │ ├── images │ │ └── background.jpg │ ├── styles │ │ ├── home.css │ │ ├── icon-font │ │ │ ├── iconfont.eot │ │ │ ├── iconfont.svg │ │ │ ├── iconfont.ttf │ │ │ └── iconfont.woff │ │ ├── iconfont.css │ │ ├── reports.css │ │ ├── swagger.css │ │ └── tree.css │ └── theme │ │ ├── fonts │ │ ├── element-icons.ttf │ │ └── element-icons.woff │ │ └── index.css ├── main.js ├── pages │ ├── auth │ │ ├── Login.vue │ │ └── Register.vue │ ├── fastrunner │ │ ├── api │ │ │ ├── RecordApi.vue │ │ │ └── components │ │ │ │ ├── ApiBody.vue │ │ │ │ └── ApiList.vue │ │ ├── case │ │ │ ├── AutoTest.vue │ │ │ └── components │ │ │ │ ├── EditTest.vue │ │ │ │ ├── TestBody.vue │ │ │ │ └── TestList.vue │ │ └── config │ │ │ ├── RecordConfig.vue │ │ │ └── components │ │ │ ├── ConfigBody.vue │ │ │ └── ConfigList.vue │ ├── home │ │ ├── Home.vue │ │ └── components │ │ │ ├── Header.vue │ │ │ └── Side.vue │ ├── httprunner │ │ └── components │ │ │ ├── Extract.vue │ │ │ ├── Headers.vue │ │ │ ├── Hooks.vue │ │ │ ├── OutParams.vue │ │ │ ├── Parameters.vue │ │ │ ├── Request.vue │ │ │ ├── Validate.vue │ │ │ └── Variables.vue │ ├── project │ │ ├── DataBase.vue │ │ ├── ProjectDetail.vue │ │ └── ProjectList.vue │ ├── pycode │ │ ├── RecordPycode.vue │ │ └── components │ │ │ └── PycodeDebug.vue │ ├── reports │ │ ├── DebugReport.vue │ │ ├── ReportList.vue │ │ └── TaskMeta.vue │ ├── task │ │ ├── AddTasks.vue │ │ ├── EditTestCase.vue │ │ └── Tasks.vue │ ├── testdata │ │ └── TestData.vue │ └── variables │ │ ├── GlobalEnv.vue │ │ ├── HostAddress.vue │ │ └── components │ │ ├── HostBody.vue │ │ └── HostList.vue ├── restful │ └── api.js ├── router │ └── index.js └── store │ ├── index.js │ ├── mutations.js │ └── state.js └── static ├── .gitkeep └── FasterRunner ├── css └── extent.css ├── favicon.ico ├── fonts ├── Mater_Icons.woff2 ├── Source_Sans_Pro.woff2 └── Source_Sans_Pro_Regular.woff2 └── js └── extent.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | .vscode 11 | *.suo 12 | *.ntvs* 13 | *.njsproj 14 | *.sln 15 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM hub.c.163.com/library/nginx 2 | 3 | RUN rm /etc/nginx/conf.d/default.conf 4 | 5 | RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 yinquanwang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FasterWeb 2 | 3 | ![LICENSE](https://img.shields.io/github/license/yinquanwang/FasterRunner.svg) 4 | > FasterWeb depend on FasterRunner 5 | 6 | ## 页面展示 7 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/登录.jpg) 8 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/首页页面.jpg) 9 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/项目概况.jpg) 10 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/测试数据.jpg) 11 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/驱动代码.jpg) 12 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/驱动代码1.jpg) 13 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/API模板.jpg) 14 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/API模板1.jpg) 15 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/测试用例.jpg) 16 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/测试用例1.jpg) 17 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/测试用例2.jpg) 18 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/测试用例3.jpg) 19 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/定时任务.jpg) 20 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/定时任务1.jpg) 21 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/定时任务2.jpg) 22 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/定时任务3.jpg) 23 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/环境变量.jpg) 24 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/参数配置.jpg) 25 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/参数配置1.jpg) 26 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/域名管理.jpg) 27 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/域名管理1.jpg) 28 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/历史报告.jpg) 29 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/excel报告.jpg) 30 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/异步回执.jpg) 31 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/弹出报告.jpg) 32 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/测试报告页面.jpg) 33 | ![Image text](https://github.com/weirdohaibo/FasterWeb/blob/master/pageview/后台管理系统.jpg) 34 | 35 | ## Docker 部署nginx模式 36 | ``` 37 | 1. 修改default.conf配置文件 server_name的ip(宿主机IP), 端口默认8080 38 | 2. 修改/src/restful/api.js baseUrl地址, 即为fastrunner容器运行的宿主机地址 39 | 3. 执行npm install, npm run build # 生成生产环境包 40 | 3. docker build -t fastweb:latest . # 构建docker镜像 41 | 4. docker run -d --name fastweb -p8888:8888 --restart always fastweb:latest # 后台运行docker容器 42 | 5. open url: http://宿主机ip:8888/fastrunner/login 43 | ``` 44 | 45 | ## 本地开发环境部署 46 | 47 | ``` bash 48 | 1. 修改FasterWeb/src/restful/api.js的baseUrl配置为FasterRunner启动的ip:port 49 | 2. npm install 安装依赖包 50 | 3. npm run dev 开发环境启动服务 51 | 4. open url: http://localhost:8080/fastrunner/login 52 | ``` 53 | 54 | ### 其他注意点: 55 | - npm 安装太慢时参考:http://npm.taobao.org/ 56 | - 安装指定版本node: 57 | 1. wget https://nodejs.org/dist/v8.11.4/node-v8.11.4-linux-x64.tar.xz 58 | 2. tar xf node-v8.11.4-linux-x64.tar.xz 59 | 3. sudo ln -s /home/ebao/node-v8.11.4-linux-x64/bin/npm /usr/bin/npm 60 | 4. sudo ln -s /home/ebao/node-v8.11.4-linux-x64/bin/node /usr/bin/node 61 | - 安装指定版本npm: sudo npm install -g npm@5.6.0 62 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve(dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | module.exports = { 13 | context: path.resolve(__dirname, '../'), 14 | entry: { 15 | app: './src/main.js' 16 | }, 17 | output: { 18 | path: config.build.assetsRoot, 19 | filename: '[name].js', 20 | publicPath: process.env.NODE_ENV === 'production' 21 | ? config.build.assetsPublicPath 22 | : config.dev.assetsPublicPath 23 | }, 24 | resolve: { 25 | extensions: ['.js', '.vue', '.json'], 26 | alias: { 27 | 'vue$': 'vue/dist/vue.esm.js', 28 | '@': resolve('src'), 29 | 'styles': resolve('src/assets/styles'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.vue$/, 36 | loader: 'vue-loader', 37 | options: vueLoaderConfig 38 | }, 39 | { 40 | test: /\.js$/, 41 | loader: 'babel-loader', 42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 43 | }, 44 | { 45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 46 | loader: 'url-loader', 47 | options: { 48 | limit: 10000, 49 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 50 | } 51 | }, 52 | { 53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 54 | loader: 'url-loader', 55 | options: { 56 | limit: 10000, 57 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 58 | } 59 | }, 60 | { 61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 62 | loader: 'url-loader', 63 | options: { 64 | limit: 10000, 65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 66 | } 67 | } 68 | ] 69 | }, 70 | node: { 71 | // prevent webpack from injecting useless setImmediate polyfill because Vue 72 | // source contains it (although only uses it if it's native). 73 | setImmediate: false, 74 | // prevent webpack from injecting mocks to Node native modules 75 | // that does not make sense for the client 76 | dgram: 'empty', 77 | fs: 'empty', 78 | net: 'empty', 79 | tls: 'empty', 80 | child_process: 'empty' 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const webpack = require('webpack') 5 | const config = require('../config') 6 | const merge = require('webpack-merge') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 13 | 14 | const env = require('../config/prod.env') 15 | 16 | const webpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ 19 | sourceMap: config.build.productionSourceMap, 20 | extract: true, 21 | usePostCSS: true 22 | }) 23 | }, 24 | devtool: config.build.productionSourceMap ? config.build.devtool : false, 25 | output: { 26 | path: config.build.assetsRoot, 27 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 29 | }, 30 | plugins: [ 31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 32 | new webpack.DefinePlugin({ 33 | 'process.env': env 34 | }), 35 | new UglifyJsPlugin({ 36 | uglifyOptions: { 37 | compress: { 38 | warnings: false 39 | } 40 | }, 41 | sourceMap: config.build.productionSourceMap, 42 | parallel: true 43 | }), 44 | // extract css into its own file 45 | new ExtractTextPlugin({ 46 | filename: utils.assetsPath('css/[name].[contenthash].css'), 47 | // Setting the following option to `false` will not extract CSS from codesplit chunks. 48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. 49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 51 | allChunks: true, 52 | }), 53 | // Compress extracted CSS. We are using this plugin so that possible 54 | // duplicated CSS from different components can be deduped. 55 | new OptimizeCSSPlugin({ 56 | cssProcessorOptions: config.build.productionSourceMap 57 | ? { safe: true, map: { inline: false } } 58 | : { safe: true } 59 | }), 60 | // generate dist index.html with correct asset hash for caching. 61 | // you can customize output by editing /index.html 62 | // see https://github.com/ampedandwired/html-webpack-plugin 63 | new HtmlWebpackPlugin({ 64 | filename: config.build.index, 65 | template: 'index.html', 66 | inject: true, 67 | minify: { 68 | removeComments: true, 69 | collapseWhitespace: true, 70 | removeAttributeQuotes: true 71 | // more options: 72 | // https://github.com/kangax/html-minifier#options-quick-reference 73 | }, 74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 75 | chunksSortMode: 'dependency' 76 | }), 77 | // keep module.id stable when vendor modules does not change 78 | new webpack.HashedModuleIdsPlugin(), 79 | // enable scope hoisting 80 | new webpack.optimize.ModuleConcatenationPlugin(), 81 | // split vendor js into its own file 82 | new webpack.optimize.CommonsChunkPlugin({ 83 | name: 'vendor', 84 | minChunks (module) { 85 | // any required modules inside node_modules are extracted to vendor 86 | return ( 87 | module.resource && 88 | /\.js$/.test(module.resource) && 89 | module.resource.indexOf( 90 | path.join(__dirname, '../node_modules') 91 | ) === 0 92 | ) 93 | } 94 | }), 95 | // extract webpack runtime and module manifest to its own file in order to 96 | // prevent vendor hash from being updated whenever app bundle is updated 97 | new webpack.optimize.CommonsChunkPlugin({ 98 | name: 'manifest', 99 | minChunks: Infinity 100 | }), 101 | // This instance extracts shared chunks from code splitted chunks and bundles them 102 | // in a separate chunk, similar to the vendor chunk 103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 104 | new webpack.optimize.CommonsChunkPlugin({ 105 | name: 'app', 106 | async: 'vendor-async', 107 | children: true, 108 | minChunks: 3 109 | }), 110 | 111 | // copy custom static assets 112 | new CopyWebpackPlugin([ 113 | { 114 | from: path.resolve(__dirname, '../static'), 115 | to: config.build.assetsSubDirectory, 116 | ignore: ['.*'] 117 | } 118 | ]) 119 | ] 120 | }) 121 | 122 | if (config.build.productionGzip) { 123 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 124 | 125 | webpackConfig.plugins.push( 126 | new CompressionWebpackPlugin({ 127 | asset: '[path].gz[query]', 128 | algorithm: 'gzip', 129 | test: new RegExp( 130 | '\\.(' + 131 | config.build.productionGzipExtensions.join('|') + 132 | ')$' 133 | ), 134 | threshold: 10240, 135 | minRatio: 0.8 136 | }) 137 | ) 138 | } 139 | 140 | if (config.build.bundleAnalyzerReport) { 141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 143 | } 144 | 145 | module.exports = webpackConfig 146 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"', 7 | }) 8 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: { 14 | /* '/httprunner': { 15 | target: 'http://localhost:8000',//设置你调用的接口域名和端口号 别忘了加http 16 | changeOrigin: true, 17 | pathRewrite: { 18 | '^/httprunner': '' 19 | } 20 | }*/ 21 | }, 22 | 23 | // Various Dev Server settings 24 | host: 'localhost', // can be overwritten by process.variables.HOST 25 | port: 8080, // can be overwritten by process.variables.PORT, if port is in use, a free one will be determined 26 | autoOpenBrowser: false, 27 | errorOverlay: true, 28 | notifyOnErrors: true, 29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 30 | 31 | 32 | /** 33 | * Source Maps 34 | */ 35 | 36 | // https://webpack.js.org/configuration/devtool/#development 37 | devtool: 'cheap-module-eval-source-map', 38 | 39 | // If you have problems debugging vue-files in devtools, 40 | // set this to false - it *may* help 41 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 42 | cacheBusting: true, 43 | 44 | cssSourceMap: true 45 | }, 46 | 47 | build: { 48 | // Template for index.html 49 | index: path.resolve(__dirname, '../dist/index.html'), 50 | 51 | // Paths 52 | assetsRoot: path.resolve(__dirname, '../dist'), 53 | assetsSubDirectory: 'static', 54 | assetsPublicPath: '/', 55 | 56 | /** 57 | * Source Maps 58 | */ 59 | 60 | productionSourceMap: true, 61 | // https://webpack.js.org/configuration/devtool/#production 62 | devtool: '#source-map', 63 | 64 | // Gzip off by default as many popular static hosts such as 65 | // Surge or Netlify already gzip all static assets for you. 66 | // Before setting to `true`, make sure to: 67 | // npm install --save-dev compression-webpack-plugin 68 | productionGzip: false, 69 | productionGzipExtensions: ['js', 'css'], 70 | 71 | // Run the build command with an extra argument to 72 | // View the bundle analyzer report after build finishes: 73 | // `npm run build --report` 74 | // Set to `true` or `false` to always turn it on or off 75 | bundleAnalyzerReport: process.env.npm_config_report 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"', 4 | } 5 | -------------------------------------------------------------------------------- /default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8888; 3 | server_name localhost; # 修改为docker服务宿主机的ip 4 | 5 | keepalive_timeout 1800; 6 | client_header_timeout 3m; 7 | client_body_timeout 3m; 8 | proxy_connect_timeout 1800s; 9 | proxy_read_timeout 30m; 10 | proxy_send_timeout 3m; 11 | send_timeout 1800; 12 | 13 | location / { 14 | root /usr/share/nginx/html; 15 | index index.html index.htm; 16 | try_files $uri $uri/ /index.html =404; 17 | } 18 | 19 | error_page 500 502 503 504 /50x.html; 20 | location = /50x.html { 21 | root html; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | FastRunner 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api-web", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "尹全旺 <1263374981@qq.com>", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "build": "node build/build.js" 11 | }, 12 | "dependencies": { 13 | "ajv": "^6.0.0", 14 | "axios": "^0.18.0", 15 | "element-ui": "2.12.0", 16 | "vue": "^2.5.4", 17 | "vue-monaco-editor": "0.0.19", 18 | "vue-router": "^3.0.1", 19 | "vuedraggable": "^2.21.0", 20 | "vuex": "^3.0.1" 21 | }, 22 | "devDependencies": { 23 | "autoprefixer": "^7.1.2", 24 | "babel-core": "^6.22.1", 25 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 26 | "babel-loader": "^7.1.1", 27 | "babel-plugin-syntax-jsx": "^6.18.0", 28 | "babel-plugin-transform-runtime": "^6.22.0", 29 | "babel-plugin-transform-vue-jsx": "^3.5.0", 30 | "babel-preset-env": "^1.3.2", 31 | "babel-preset-stage-2": "^6.22.0", 32 | "chalk": "^2.0.1", 33 | "copy-webpack-plugin": "^4.0.1", 34 | "css-loader": "^0.28.0", 35 | "extract-text-webpack-plugin": "^3.0.0", 36 | "file-loader": "^1.1.4", 37 | "friendly-errors-webpack-plugin": "^1.6.1", 38 | "html-webpack-plugin": "^2.30.1", 39 | "node-notifier": "^5.1.2", 40 | "optimize-css-assets-webpack-plugin": "^3.2.0", 41 | "ora": "^1.2.0", 42 | "portfinder": "^1.0.13", 43 | "postcss-import": "^11.0.0", 44 | "postcss-loader": "^2.0.8", 45 | "postcss-url": "^7.2.1", 46 | "rimraf": "^2.6.0", 47 | "semver": "^5.3.0", 48 | "shelljs": "^0.7.6", 49 | "uglifyjs-webpack-plugin": "^1.1.1", 50 | "url-loader": "^0.5.8", 51 | "vue-easytable": "^1.7.1", 52 | "vue-loader": "^13.3.0", 53 | "vue-style-loader": "^3.0.1", 54 | "vue-template-compiler": "^2.5.2", 55 | "vue2-ace-editor": "0.0.11", 56 | "webpack": "^3.6.0", 57 | "webpack-bundle-analyzer": "^2.9.0", 58 | "webpack-dev-server": "^2.9.1", 59 | "webpack-merge": "^4.1.0" 60 | }, 61 | "engines": { 62 | "node": ">= 6.0.0", 63 | "npm": ">= 3.0.0" 64 | }, 65 | "browserslist": [ 66 | "> 1%", 67 | "last 2 versions", 68 | "not ie <= 8" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /pageview/API模板.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/API模板.jpg -------------------------------------------------------------------------------- /pageview/API模板1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/API模板1.jpg -------------------------------------------------------------------------------- /pageview/excel报告.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/excel报告.jpg -------------------------------------------------------------------------------- /pageview/历史报告.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/历史报告.jpg -------------------------------------------------------------------------------- /pageview/参数配置.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/参数配置.jpg -------------------------------------------------------------------------------- /pageview/参数配置1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/参数配置1.jpg -------------------------------------------------------------------------------- /pageview/后台管理系统.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/后台管理系统.jpg -------------------------------------------------------------------------------- /pageview/域名管理.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/域名管理.jpg -------------------------------------------------------------------------------- /pageview/定时任务.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/定时任务.jpg -------------------------------------------------------------------------------- /pageview/定时任务1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/定时任务1.jpg -------------------------------------------------------------------------------- /pageview/定时任务2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/定时任务2.jpg -------------------------------------------------------------------------------- /pageview/定时任务3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/定时任务3.jpg -------------------------------------------------------------------------------- /pageview/异步回执.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/异步回执.jpg -------------------------------------------------------------------------------- /pageview/测试报告页面.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/测试报告页面.jpg -------------------------------------------------------------------------------- /pageview/测试数据.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/测试数据.jpg -------------------------------------------------------------------------------- /pageview/测试用例.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/测试用例.jpg -------------------------------------------------------------------------------- /pageview/测试用例1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/测试用例1.jpg -------------------------------------------------------------------------------- /pageview/测试用例2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/测试用例2.jpg -------------------------------------------------------------------------------- /pageview/测试用例3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/测试用例3.jpg -------------------------------------------------------------------------------- /pageview/环境变量.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/环境变量.jpg -------------------------------------------------------------------------------- /pageview/登录.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/登录.jpg -------------------------------------------------------------------------------- /pageview/项目概况.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/项目概况.jpg -------------------------------------------------------------------------------- /pageview/首页页面.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/首页页面.jpg -------------------------------------------------------------------------------- /pageview/驱动代码.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/驱动代码.jpg -------------------------------------------------------------------------------- /pageview/驱动代码1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/pageview/驱动代码1.jpg -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 32 | -------------------------------------------------------------------------------- /src/assets/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/src/assets/images/background.jpg -------------------------------------------------------------------------------- /src/assets/styles/home.css: -------------------------------------------------------------------------------- 1 | #form-content { 2 | width: 380px; 3 | height: 380px; 4 | margin: 40px auto; 5 | background-color: #FFFFFF; 6 | padding: 5px; 7 | text-align: center; 8 | border-radius: 2px; 9 | -webkit-box-shadow: 0px 16px 44px 0 RGBA(0, 0, 1, 0.2); 10 | -moz-box-shadow: 0px 16px 44px 0 RGBA(0, 0, 1, 0.2); 11 | box-shadow: 0px 16px 44px 0 RGBA(0, 0, 1, 0.2); 12 | } 13 | 14 | .bottom-right { 15 | position: fixed; 16 | right: 0px; 17 | bottom: 0px; 18 | } 19 | 20 | .bottom-left { 21 | position: fixed; 22 | left: 0px; 23 | bottom: 0px; 24 | } 25 | 26 | .bottom-right img { 27 | width: 364px; 28 | height: 208px; 29 | } 30 | 31 | .bottom-left img { 32 | width: 332px; 33 | height: 271px; 34 | } 35 | 36 | img { 37 | vertical-align: middle; 38 | } 39 | 40 | img { 41 | border: 0; 42 | } 43 | 44 | .form-input-div .icon { 45 | position: relative; 46 | left: 16px; 47 | top: 8px; 48 | color: #172B4D; 49 | font-size: 18px; 50 | } 51 | 52 | .form-input-div input.has-error { 53 | border-color: #fc4949; 54 | } 55 | 56 | #form-msg { 57 | margin-top: 50px; 58 | color: #172B4D; 59 | font-size: 30px; 60 | text-align: left; 61 | font-weight: 300; 62 | } 63 | 64 | .form-submit .btn-primary { 65 | width: 50%; 66 | height: 30px; 67 | font-size: 14px; 68 | color: #fff; 69 | background: #1F5DEA; 70 | border: 1px solid #1F5DEA; 71 | border-radius: 2px; 72 | } 73 | 74 | .form-foot { 75 | position: relative; 76 | margin-top: 20px; 77 | color: #A8ACB9; 78 | font-size: 12px; 79 | text-align: center; 80 | } 81 | 82 | .form-foot a, .form-foot a:hover, .form-foot a:active { 83 | color: #1F5DEA; 84 | text-decoration: none; 85 | } 86 | 87 | body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td { 88 | margin: 0; 89 | padding: 0; 90 | -webkit-box-sizing: border-box; 91 | -moz-box-sizing: border-box; 92 | box-sizing: border-box; 93 | } 94 | 95 | a:hover, a:active, a:visited, a:focus { 96 | text-decoration: none !important; 97 | cursor: pointer; 98 | } 99 | 100 | .btn:active { 101 | background: #19A8FF; 102 | } 103 | 104 | .btn { 105 | display: inline-block; 106 | padding: 6px 10px; 107 | margin-bottom: 0; 108 | font-size: 13px; 109 | font-weight: normal; 110 | line-height: 1.42857143; 111 | text-align: center; 112 | white-space: nowrap; 113 | vertical-align: middle; 114 | -ms-touch-action: manipulation; 115 | touch-action: manipulation; 116 | cursor: pointer; 117 | -webkit-user-select: none; 118 | -moz-user-select: none; 119 | -ms-user-select: none; 120 | user-select: none; 121 | background-image: none; 122 | border: 1px solid transparent; 123 | border-radius: 2px; 124 | } 125 | 126 | input, button, select, textarea { 127 | font-family: inherit; 128 | font-size: inherit; 129 | line-height: inherit; 130 | } 131 | 132 | .form-input-div input { 133 | width: 250px; 134 | height: 42px; 135 | padding-left: 100px; 136 | border: 1px solid #E1E2E6; 137 | margin:0 auto; 138 | } 139 | 140 | .err_msg { 141 | position: relative; 142 | color: #fc4949; 143 | height: 20px; 144 | line-height: 20px; 145 | } 146 | 147 | #form-inputs { 148 | width: 250px; 149 | margin:0 auto; 150 | margin-top: 40px; 151 | } 152 | 153 | .login { 154 | background-color: #f7f8fa; 155 | font-family: "PingFang SC", "Helvetica Neue", Helvetica, "Hiragino Sans GB", STHeitiSC-Light, "Microsoft YaHei", "微软雅黑", Arial, sans-serif; 156 | font-size: 13px; 157 | line-height: 1.42857143; 158 | color: #333; 159 | } 160 | -------------------------------------------------------------------------------- /src/assets/styles/icon-font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/src/assets/styles/icon-font/iconfont.eot -------------------------------------------------------------------------------- /src/assets/styles/icon-font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/src/assets/styles/icon-font/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/styles/icon-font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/src/assets/styles/icon-font/iconfont.woff -------------------------------------------------------------------------------- /src/assets/styles/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face {font-family: "iconfont"; 2 | src: url('./icon-font/iconfont.eot?t=1551323395845'); /* IE9 */ 3 | src: url('./icon-font/iconfont.eot?t=1551323395845#iefix') format('embedded-opentype'), /* IE6-IE8 */ 4 | url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), 5 | url('./icon-font/iconfont.woff?t=1551323395845') format('woff'), 6 | url('./icon-font/iconfont.ttf?t=1551323395845') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 7 | url('./icon-font/iconfont.svg?t=1551323395845#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont { 11 | font-family: "iconfont" !important; 12 | font-size: 16px; 13 | font-style: normal; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | } 17 | 18 | .icon-youxiang:before { 19 | content: "\e668"; 20 | } 21 | 22 | .icon-baogao:before { 23 | content: "\e66e"; 24 | } 25 | 26 | .icon-ybbindex:before { 27 | content: "\e631"; 28 | } 29 | 30 | .icon-02:before { 31 | content: "\e64a"; 32 | } 33 | 34 | .icon-iconset0196:before { 35 | content: "\e65f"; 36 | } 37 | 38 | .icon-17:before { 39 | content: "\e610"; 40 | } 41 | 42 | .icon-xiazai:before { 43 | content: "\e600"; 44 | } 45 | 46 | .icon-index:before { 47 | content: "\e66d"; 48 | } 49 | 50 | .icon-fuzhifuzhi:before { 51 | content: "\e636"; 52 | } 53 | 54 | .icon-debug:before { 55 | content: "\e606"; 56 | } 57 | 58 | .icon-shijian:before { 59 | content: "\e63b"; 60 | } 61 | 62 | .icon-language-python-text:before { 63 | content: "\e7ca"; 64 | } 65 | 66 | .icon-xiangmu:before { 67 | content: "\e63c"; 68 | } 69 | 70 | .icon-jiankong:before { 71 | content: "\e61f"; 72 | } 73 | 74 | .icon-houtui:before { 75 | content: "\e617"; 76 | } 77 | 78 | .icon-dingshirenwu:before { 79 | content: "\e61e"; 80 | } 81 | 82 | .icon-xiangmu1:before { 83 | content: "\e707"; 84 | } 85 | 86 | .icon-ceshi:before { 87 | content: "\e6da"; 88 | } 89 | 90 | .icon-mima:before { 91 | content: "\e652"; 92 | } 93 | 94 | .icon-quanju_yuming:before { 95 | content: "\e609"; 96 | } 97 | 98 | .icon-jiekou:before { 99 | content: "\e74a"; 100 | } 101 | 102 | .icon-shujuku:before { 103 | content: "\e615"; 104 | } 105 | 106 | .icon-yali:before { 107 | content: "\e632"; 108 | } 109 | 110 | .icon-xingmingyonghumingnicheng:before { 111 | content: "\e61c"; 112 | } 113 | 114 | .icon-xiugai:before { 115 | content: "\e67d"; 116 | } 117 | 118 | .icon-houtui1:before { 119 | content: "\e66f"; 120 | } 121 | 122 | .icon-yumingguanli:before { 123 | content: "\e6cc"; 124 | } 125 | 126 | .icon-yonghuming:before { 127 | content: "\e60d"; 128 | } 129 | 130 | .icon-houtui2:before { 131 | content: "\e613"; 132 | } 133 | 134 | .icon-171:before { 135 | content: "\e601"; 136 | } 137 | 138 | .icon-bendibianliang:before { 139 | content: "\e692"; 140 | } 141 | 142 | .icon-youxiang1:before { 143 | content: "\e650"; 144 | } 145 | 146 | .icon-config:before { 147 | content: "\ee32"; 148 | } 149 | 150 | .icon-fuzhi:before { 151 | content: "\e63d"; 152 | } 153 | 154 | .icon-shujuku1:before { 155 | content: "\e782"; 156 | } 157 | 158 | .icon-xiangmuliebiao:before { 159 | content: "\e7a7"; 160 | } 161 | 162 | .icon-python:before { 163 | content: "\f216"; 164 | } 165 | 166 | .icon-yunhang:before { 167 | content: "\e616"; 168 | } 169 | 170 | .icon-shanchu:before { 171 | content: "\e608"; 172 | } 173 | 174 | .icon-xiazai1:before { 175 | content: "\e602"; 176 | } 177 | 178 | -------------------------------------------------------------------------------- /src/assets/styles/reports.css: -------------------------------------------------------------------------------- 1 | .success { 2 | font-weight: bold; 3 | font-size: medium; 4 | color: #67c23a; 5 | } 6 | 7 | .error { 8 | font-weight: bold; 9 | font-size: medium; 10 | color: red; 11 | } 12 | 13 | .failure { 14 | font-weight: bold; 15 | font-size: medium; 16 | color: salmon; 17 | } 18 | 19 | .skipped { 20 | font-weight: bold; 21 | font-size: medium; 22 | color: #909399; 23 | } 24 | 25 | .POST { 26 | color: #49cc90; 27 | } 28 | 29 | 30 | .PUT { 31 | color: #fca130; 32 | } 33 | 34 | .GET { 35 | color: #61affe; 36 | } 37 | 38 | 39 | .DELETE { 40 | color: #f93e3e; 41 | } 42 | 43 | 44 | .PATCH { 45 | color: #50e3c2; 46 | } 47 | 48 | .HEAD { 49 | color: #e6a23c; 50 | } 51 | 52 | .OPTIONS { 53 | color: #409eff; 54 | } 55 | 56 | 57 | .code-block { 58 | min-height: 0; 59 | max-height: 500px; 60 | border: 1px solid #ebedef; 61 | border-radius: 4px; 62 | color: #222 !important; 63 | font-family: Consolas,monospace; 64 | font-size: 13px; 65 | margin: 0; 66 | padding: 7px 10px; 67 | overflow: auto; 68 | } 69 | -------------------------------------------------------------------------------- /src/assets/styles/swagger.css: -------------------------------------------------------------------------------- 1 | .block_post { 2 | border: 1px solid #49cc90; 3 | background-color: rgba(73, 204, 144, .1); 4 | } 5 | 6 | .block_method_post { 7 | background-color: #49cc90; 8 | } 9 | 10 | .block_put { 11 | border: 1px solid #fca130; 12 | background-color: rgba(252, 161, 48, .1) 13 | } 14 | 15 | .block_method_put { 16 | background-color: #fca130; 17 | } 18 | 19 | .block_get { 20 | border: 1px solid #61affe; 21 | background-color: rgba(97, 175, 254, .1) 22 | } 23 | 24 | .block_method_get { 25 | background-color: #61affe; 26 | } 27 | 28 | .block_delete { 29 | border: 1px solid #f93e3e; 30 | background-color: rgba(249, 62, 62, .1) 31 | } 32 | 33 | .block_method_delete { 34 | background-color: #f93e3e; 35 | } 36 | 37 | .block_patch { 38 | border: 1px solid #50e3c2; 39 | background-color: rgba(80, 227, 194, .1) 40 | } 41 | 42 | .block_method_patch { 43 | background-color: #50e3c2; 44 | } 45 | 46 | .block_head { 47 | border: 1px solid #e6a23c; 48 | background-color: rgba(230, 162, 60, .1) 49 | } 50 | 51 | .block_method_head { 52 | background-color: #e6a23c; 53 | } 54 | 55 | .block_options { 56 | border: 1px solid #409eff; 57 | background-color: rgba(64, 158, 255, .1) 58 | } 59 | 60 | .block_method_options { 61 | background-color: #409eff; 62 | } 63 | 64 | .block { 65 | position: relative; 66 | border-radius: 4px; 67 | height: 43.6px; 68 | padding: 5px; 69 | display: flex; 70 | align-items: center; 71 | } 72 | 73 | .block_url { 74 | word-break: normal; 75 | width: auto; 76 | display: block; 77 | white-space: pre-wrap; 78 | word-wrap: break-word; 79 | overflow: hidden; 80 | -webkit-box-flex: 1; 81 | -ms-flex: 1; 82 | font-family: Open Sans, sans-serif; 83 | color: #3b4151; 84 | } 85 | 86 | .block_name { 87 | font-size: 13px; 88 | padding-left: 5px; 89 | word-break: normal; 90 | width: auto; 91 | display: block; 92 | white-space: pre-wrap; 93 | word-wrap: break-word; 94 | overflow: hidden; 95 | -webkit-box-flex: 1; 96 | -ms-flex: 1; 97 | font-family: Open Sans, sans-serif; 98 | color: #3b4151; 99 | } 100 | 101 | .block_method_color { 102 | cursor: pointer; 103 | color: #fff; 104 | } 105 | 106 | .block-method { 107 | font-size: 12px; 108 | font-weight: 600; 109 | min-width: 80px; 110 | padding: 4px; 111 | text-align: center; 112 | border-radius: 3px; 113 | text-shadow: 0 1px 0 rgba(0, 0, 0, .1); 114 | font-family: Titillium Web, sans-serif; 115 | } 116 | 117 | .block-summary-description { 118 | word-break: normal; 119 | width: auto; 120 | display: block; 121 | white-space: pre-wrap; 122 | word-wrap: break-word; 123 | overflow: hidden; 124 | -webkit-box-flex: 1; 125 | -ms-flex: 1; 126 | font-size: 13px; 127 | font-family: Open Sans, sans-serif; 128 | color: #3b4151; 129 | } 130 | 131 | h4 { 132 | display: block; 133 | -webkit-margin-before: 1.33em; 134 | -webkit-margin-after: 1.33em; 135 | -webkit-margin-start: 0px; 136 | -webkit-margin-end: 0px; 137 | font-weight: bold; 138 | } 139 | -------------------------------------------------------------------------------- /src/assets/styles/tree.css: -------------------------------------------------------------------------------- 1 | ul li { 2 | list-style: none; 3 | } 4 | 5 | .operation-li { 6 | line-height: 60px; 7 | color: #555; 8 | font-size: 12px; 9 | width: 240px; 10 | margin-top: 1px; 11 | } 12 | 13 | .api-tree { 14 | padding: 0; 15 | margin: 0; 16 | } 17 | 18 | .nav-api-header { 19 | height: 48px; 20 | border-bottom: 1px solid #ddd; 21 | background-color: #F7F7F7; 22 | 23 | } 24 | 25 | .nav-api-side { 26 | overflow: auto; 27 | border: 1px solid #ddd; 28 | width: 280px; 29 | margin-left: 10px; 30 | border-radius: 4px; 31 | position: fixed; 32 | top: 110px; 33 | bottom: 0; 34 | 35 | } 36 | 37 | .custom-tree-node { 38 | flex: 1; 39 | display: flex; 40 | align-items: center; 41 | justify-content: space-between; 42 | font-size: 14px; 43 | padding-right: 8px; 44 | } 45 | 46 | 47 | .tree { 48 | overflow-y: auto; 49 | overflow-x: auto; 50 | width: 280px; 51 | height: 500px; 52 | } 53 | 54 | .el-tree { 55 | min-width: 100%; 56 | display: inline-block !important; 57 | } 58 | 59 | .el-tree-node__expand-icon { 60 | padding: 4px !important; 61 | } 62 | 63 | .el-tree-node__content { 64 | height: 50px; 65 | } 66 | 67 | .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content { 68 | background-color: rgba(64, 158, 255, .1); 69 | color: #409EFF; 70 | } 71 | -------------------------------------------------------------------------------- /src/assets/theme/fonts/element-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/src/assets/theme/fonts/element-icons.ttf -------------------------------------------------------------------------------- /src/assets/theme/fonts/element-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/src/assets/theme/fonts/element-icons.woff -------------------------------------------------------------------------------- /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 ElementUI from 'element-ui' 5 | import './assets/theme/index.css' 6 | import App from './App' 7 | import router from './router' 8 | import 'styles/iconfont.css' 9 | import 'styles/swagger.css' 10 | import 'styles/tree.css' 11 | import 'styles/home.css' 12 | import 'styles/reports.css' 13 | import * as api from './restful/api' 14 | import store from './store' 15 | 16 | Vue.config.productionTip = false; 17 | Vue.use(ElementUI); 18 | Vue.prototype.$api = api; 19 | 20 | Vue.filter('datetimeFormat', function (time, format = 'YY-MM-DD hh:mm:ss') { 21 | let date = new Date(time); 22 | let year = date.getFullYear(), 23 | month = date.getMonth() + 1, 24 | day = date.getDate(), 25 | hour = date.getHours(), 26 | min = date.getMinutes(), 27 | sec = date.getSeconds(); 28 | let preArr = Array.apply(null, Array(10)).map(function (elem, index) { 29 | return '0' + index; 30 | }); 31 | 32 | let newTime = format.replace(/YY/g, year) 33 | .replace(/MM/g, preArr[month] || month) 34 | .replace(/DD/g, preArr[day] || day) 35 | .replace(/hh/g, preArr[hour] || hour) 36 | .replace(/mm/g, preArr[min] || min) 37 | .replace(/ss/g, preArr[sec] || sec); 38 | 39 | return newTime; 40 | }); 41 | 42 | Vue.filter("timestampToTime", function (timestamp) { 43 | let date = new Date(timestamp * 1000); 44 | const Y = date.getFullYear() + '-'; 45 | const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; 46 | const D = date.getDate() + ' '; 47 | const h = date.getHours() + ':'; 48 | const m = date.getMinutes() + ':'; 49 | const s = date.getSeconds(); 50 | 51 | return Y + M + D + h + m + s; 52 | 53 | }); 54 | Vue.prototype.setLocalValue = function (name, value) { 55 | if (window.localStorage) { 56 | localStorage.setItem(name, value); 57 | } else { 58 | alert('This browser does NOT support localStorage'); 59 | } 60 | }; 61 | Vue.prototype.getLocalValue = function (name) { 62 | const value = localStorage.getItem(name); 63 | if (value) { 64 | return value; 65 | } else { 66 | return ''; 67 | } 68 | }; 69 | Vue.prototype.getViewportSize = function(){ 70 | return { 71 | width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, 72 | height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 73 | }; 74 | }; 75 | router.beforeEach((to, from, next) => { 76 | /* 路由发生变化修改页面title */ 77 | setTimeout((res) => { 78 | if (to.meta.title) { 79 | document.title = to.meta.title 80 | } 81 | 82 | if (to.meta.requireAuth) { 83 | if (store.state.token !== '') { 84 | next(); 85 | } else { 86 | next({ 87 | name: 'Login', 88 | }) 89 | } 90 | } else { 91 | next() 92 | } 93 | }) 94 | 95 | }) 96 | 97 | /* eslint-disable no-new */ 98 | new Vue({ 99 | el: '#app', 100 | router, 101 | store, 102 | components: {App}, 103 | template: '', 104 | created() { 105 | if (this.getLocalValue("token") === null) { 106 | this.setLocalValue("token", ""); 107 | } 108 | if (this.getLocalValue("user") === null) { 109 | this.setLocalValue("user", ""); 110 | } 111 | if (this.getLocalValue("routerName") === null) { 112 | this.setLocalValue("routerName", "ProjectList"); 113 | } 114 | this.$store.commit("isLogin", this.getLocalValue("token")); 115 | this.$store.commit("setUser", this.getLocalValue("user")); 116 | this.$store.commit("setRouterName", this.getLocalValue("routerName")); 117 | 118 | } 119 | }) 120 | -------------------------------------------------------------------------------- /src/pages/auth/Login.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 95 | 96 | 99 | -------------------------------------------------------------------------------- /src/pages/auth/Register.vue: -------------------------------------------------------------------------------- 1 | 86 | 87 | 88 | 164 | 165 | 168 | -------------------------------------------------------------------------------- /src/pages/fastrunner/case/components/TestBody.vue: -------------------------------------------------------------------------------- 1 | 143 | 144 | 280 | 281 | 297 | -------------------------------------------------------------------------------- /src/pages/fastrunner/config/RecordConfig.vue: -------------------------------------------------------------------------------- 1 | 60 | 61 | 148 | 149 | 153 | -------------------------------------------------------------------------------- /src/pages/fastrunner/config/components/ConfigBody.vue: -------------------------------------------------------------------------------- 1 | 104 | 105 | 247 | 248 | 264 | -------------------------------------------------------------------------------- /src/pages/fastrunner/config/components/ConfigList.vue: -------------------------------------------------------------------------------- 1 | 99 | 100 | 230 | 231 | 234 | 235 | -------------------------------------------------------------------------------- /src/pages/home/Home.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 33 | 34 | 40 | -------------------------------------------------------------------------------- /src/pages/home/components/Header.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 32 | 33 | 71 | -------------------------------------------------------------------------------- /src/pages/home/components/Side.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 90 | 91 | 106 | 107 | -------------------------------------------------------------------------------- /src/pages/httprunner/components/Extract.vue: -------------------------------------------------------------------------------- 1 | 62 | 63 | 140 | 141 | 143 | -------------------------------------------------------------------------------- /src/pages/httprunner/components/Headers.vue: -------------------------------------------------------------------------------- 1 | 80 | 81 | 187 | 188 | 190 | -------------------------------------------------------------------------------- /src/pages/httprunner/components/Hooks.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 145 | 146 | 148 | -------------------------------------------------------------------------------- /src/pages/httprunner/components/OutParams.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 96 | 97 | 100 | -------------------------------------------------------------------------------- /src/pages/httprunner/components/Parameters.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 154 | 155 | 157 | -------------------------------------------------------------------------------- /src/pages/httprunner/components/Validate.vue: -------------------------------------------------------------------------------- 1 | 90 | 91 | 323 | 324 | 326 | -------------------------------------------------------------------------------- /src/pages/httprunner/components/Variables.vue: -------------------------------------------------------------------------------- 1 | 87 | 88 | 259 | 260 | 263 | -------------------------------------------------------------------------------- /src/pages/project/ProjectDetail.vue: -------------------------------------------------------------------------------- 1 | F 57 | 58 | 83 | 84 | 145 | -------------------------------------------------------------------------------- /src/pages/pycode/components/PycodeDebug.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 97 | 98 | 110 | -------------------------------------------------------------------------------- /src/pages/reports/DebugReport.vue: -------------------------------------------------------------------------------- 1 | 153 | 154 | 198 | 199 | 205 | -------------------------------------------------------------------------------- /src/pages/reports/TaskMeta.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 119 | 120 | 132 | -------------------------------------------------------------------------------- /src/pages/task/EditTestCase.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 123 | 124 | 127 | -------------------------------------------------------------------------------- /src/pages/variables/HostAddress.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 106 | 107 | 111 | -------------------------------------------------------------------------------- /src/pages/variables/components/HostBody.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 129 | 130 | 140 | -------------------------------------------------------------------------------- /src/pages/variables/components/HostList.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 208 | 209 | 212 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Home from '@/pages/home/Home' 4 | import Login from '@/pages/auth/Login' 5 | import ProjectList from '@/pages/project/ProjectList' 6 | import ProjectDetail from '@/pages/project/ProjectDetail' 7 | import DebugTalk from '@/pages/pycode/RecordPycode' 8 | import RecordApi from '@/pages/fastrunner/api/RecordApi' 9 | import AutoTest from '@/pages/fastrunner/case/AutoTest' 10 | import GlobalEnv from '@/pages/variables/GlobalEnv' 11 | import ReportList from '@/pages/reports/ReportList' 12 | import RecordConfig from '@/pages/fastrunner/config/RecordConfig' 13 | import Tasks from '@/pages/task/Tasks' 14 | import HostAddress from '@/pages/variables/HostAddress' 15 | import TestData from "@/pages/testdata/TestData"; 16 | import TaskMeta from "@/pages/reports/TaskMeta"; 17 | //import Register from '@/pages/auth/Register' 18 | Vue.use(Router); 19 | 20 | export default new Router({ 21 | mode:'history', 22 | routes: [ 23 | // { 24 | // path: '/fastrunner/register', 25 | // name: 'Register', 26 | // component: Register, 27 | // meta: { 28 | // title: '用户注册' 29 | // } 30 | // }, 31 | { 32 | path: '/fastrunner/login', 33 | name: 'Login', 34 | component: Login, 35 | meta: { 36 | title: '用户登录' 37 | } 38 | }, { 39 | 40 | path: '/fastrunner', 41 | name: 'Index', 42 | component: Home, 43 | meta: { 44 | title: '首页', 45 | requireAuth: true 46 | }, 47 | children: [ 48 | { 49 | name: 'ProjectList', 50 | path: 'project_list', 51 | component: ProjectList, 52 | meta: { 53 | title: '项目列表', 54 | requireAuth: true, 55 | } 56 | }, 57 | { 58 | name: 'ProjectDetail', 59 | path: 'dashbord/:id', 60 | component: ProjectDetail, 61 | meta: { 62 | title: '项目预览', 63 | requireAuth: true, 64 | } 65 | }, 66 | { 67 | name: 'DebugTalk', 68 | path: 'debugtalk/:id', 69 | component: DebugTalk, 70 | meta: { 71 | title: '编辑驱动', 72 | requireAuth: true, 73 | } 74 | }, 75 | { 76 | name: 'RecordApi', 77 | path: 'api_record/:id', 78 | component: RecordApi, 79 | meta: { 80 | title: '接口模板', 81 | requireAuth: true 82 | } 83 | }, 84 | { 85 | name: 'AutoTest', 86 | path: 'auto_test/:id', 87 | component: AutoTest, 88 | meta: { 89 | title: '自动化测试', 90 | requireAuth: true 91 | } 92 | }, 93 | { 94 | name: 'RecordConfig', 95 | path: 'record_config/:id', 96 | component: RecordConfig, 97 | meta: { 98 | title: '配置管理', 99 | requireAuth: true 100 | } 101 | }, 102 | { 103 | name: 'GlobalEnv', 104 | path: 'global_env/:id', 105 | component: GlobalEnv, 106 | meta: { 107 | title: '全局变量', 108 | requireAuth: true 109 | } 110 | }, 111 | { 112 | name: 'Reports', 113 | path: 'reports/:id', 114 | component: ReportList, 115 | meta: { 116 | title: '历史报告', 117 | requireAuth: true 118 | } 119 | }, 120 | { 121 | name: 'Task', 122 | path: 'tasks/:id', 123 | component: Tasks, 124 | meta: { 125 | title: '定时任务', 126 | requireAuth: true 127 | } 128 | }, 129 | { 130 | name: 'HostIP', 131 | path: 'host_ip/:id', 132 | component: HostAddress, 133 | meta: { 134 | title: 'HOST配置', 135 | requireAuth: true 136 | } 137 | }, 138 | { 139 | name: "TestData", 140 | path: 'testdata/:id', 141 | component: TestData, 142 | meta: { 143 | title: '测试数据', 144 | requireAuth: true 145 | } 146 | }, 147 | { 148 | name: "TaskMeta", 149 | path: 'taskmeta/:id', 150 | component: TaskMeta, 151 | meta: { 152 | title: '异步回执', 153 | requireAuth: true 154 | } 155 | }, 156 | ] 157 | }, 158 | 159 | ] 160 | }) 161 | 162 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import state from './state' 4 | import mutations from './mutations' 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | state, 10 | mutations 11 | }) 12 | -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 3 | isLogin(state, value) { 4 | state.token = value; 5 | }, 6 | 7 | setUser(state, value) { 8 | state.user = value; 9 | }, 10 | setRouterName(state, value) { 11 | state.routerName = value 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/store/state.js: -------------------------------------------------------------------------------- 1 | export default { 2 | routerName: null, 3 | token:null, 4 | user: null, 5 | headTitle:'FasterRunner 接口自动化测试平台' 6 | } 7 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/static/.gitkeep -------------------------------------------------------------------------------- /static/FasterRunner/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/static/FasterRunner/favicon.ico -------------------------------------------------------------------------------- /static/FasterRunner/fonts/Mater_Icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/static/FasterRunner/fonts/Mater_Icons.woff2 -------------------------------------------------------------------------------- /static/FasterRunner/fonts/Source_Sans_Pro.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/static/FasterRunner/fonts/Source_Sans_Pro.woff2 -------------------------------------------------------------------------------- /static/FasterRunner/fonts/Source_Sans_Pro_Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weirdohaibo/FasterWeb/5b2d3f9ff7b3355a25e63ab5dbf684274fbc987e/static/FasterRunner/fonts/Source_Sans_Pro_Regular.woff2 --------------------------------------------------------------------------------