Commit 53991eba authored by huai.li's avatar huai.li

Initial commit

parents
Pipeline #6 failed with stages
{
"presets": [
["env", { "modules": false }],
"stage-2"
],
"plugins": ["transform-runtime"],
"comments": false,
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": [ "istanbul" ]
}
}
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
build/*.js
config/*.js
// http://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
},
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: 'standard',
// required to lint *.vue files
plugins: [
'html'
],
// add your custom rules here
'rules': {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
}
}
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
test/unit/coverage
test/e2e/reports
selenium-debug.log
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<component name="ProjectDictionaryState">
<dictionary name="seven.zhong" />
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State>
<id />
</State>
<State>
<id>JavaScript</id>
</State>
</expanded-state>
<selected-state>
<State>
<id>JavaScript</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/FE.portal2.0-app-template.iml" filepath="$PROJECT_DIR$/.idea/FE.portal2.0-app-template.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
// to edit target browsers: use "browserlist" field in package.json
"autoprefixer": {}
}
}
# portal2.0-app-template
> vue2.0
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
# run unit tests
npm run unit
# run e2e tests
npm run e2e
# run all tests
npm test
```
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).
{"mock":"part"}
\ No newline at end of file
require('./check-versions')()
process.env.NODE_ENV = 'production'
var ora = require('ora')
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
var chalk = require('chalk')
var semver = require('semver')
var packageConfig = require('../package.json')
var shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
var versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
},
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
var warnings = []
for (var i = 0; i < versionRequirements.length; i++) {
var mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (var i = 0; i < warnings.length; i++) {
var warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})
require('./check-versions')()
let proxyMock = require('express-proxy-mock')
var config = require('../config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = process.env.NODE_ENV === 'testing'
? require('./webpack.prod.conf')
: require('./webpack.dev.conf')
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable
var app = express()
proxyMock(app)
var compiler = webpack(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
// app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// set a cookie
app.use(function(req, res, next) {
res.cookie('vup_token', '321421343124', {maxAge: 99999999999999999})
next()
})
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass').concat(
{
loader: 'sass-resources-loader',
options: {
resources: [
path.resolve(__dirname, '../node_modules/sass-bem/_bem.scss'),
path.resolve(__dirname, '../node_modules/compass-mixins/lib/_compass.scss'),
path.resolve(__dirname, '../src/theme/var.scss')
]
}
}
),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
var utils = require('./utils')
var config = require('../config')
var isProduction = process.env.NODE_ENV === 'production'
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
})
}
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
},
externals: {
'vis-portal': 'VupPortalSdk.vueAppDevSdk',
'jquery': 'VupPortalSdk.vueAppDevSdk.jQuery',
'vue': 'VupPortalSdk.vueAppDevSdk.Vue',
'vue-bus': 'VupPortalSdk.vueAppDevSdk.vueBus',
'bowser': 'VupPortalSdk.vueAppDevSdk.bowser',
'browser-cookie': 'VupPortalSdk.vueAppDevSdk.cookie',
'vue-router': 'VupPortalSdk.vueAppDevSdk.vueRouter',
'element-ui': 'VupPortalSdk.vueAppDevSdk.elementui',
'vue-cache-data': 'VupPortalSdk.vueAppDevSdk.VueCacheData',
'create-requestor': 'VupPortalSdk.vueAppDevSdk.createRequestor'
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})
module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
},
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.ejs',
inject: true
}),
new FriendlyErrorsPlugin()
]
})
var prodWebpackConfig = require('./webpack.prod.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var merge = require('webpack-merge')
var utils = require('./utils')
var webpackConfig = merge(prodWebpackConfig, {
output: {
filename: utils.assetsPath('js/[name].js'),
chunkFilename: utils.assetsPath('js/[id].js')
}
})
webpackConfig.plugins.splice(2, 1, new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].css')
})
)
module.exports = webpackConfig
var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
var env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: config.build.env
var webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// split vendor js into its own file
// new webpack.optimize.CommonsChunkPlugin({
// name: 'vendor',
// minChunks: function (module, count) {
// // any required modules inside node_modules are extracted to vendor
// return (
// module.resource &&
// /\.js$/.test(module.resource) &&
// module.resource.indexOf(
// path.join(__dirname, '../node_modules')
// ) === 0
// )
// }
// }),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
// new webpack.optimize.CommonsChunkPlugin({
// name: 'manifest',
// chunks: ['vendor']
// }),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
var CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
// This is the webpack config used for unit tests.
var utils = require('./utils')
var webpack = require('webpack')
var merge = require('webpack-merge')
var baseConfig = require('./webpack.base.conf')
var webpackConfig = merge(baseConfig, {
// use inline sourcemap for karma-sourcemap-loader
module: {
rules: utils.styleLoaders()
},
devtool: '#inline-source-map',
resolveLoader: {
alias: {
// necessary to to make lang="scss" work in test when using vue-loader's ?inject option
// see discussion at https://github.com/vuejs/vue-loader/issues/724
'scss-loader': 'sass-loader'
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/test.env')
})
]
})
// no need for app entry during tests
delete webpackConfig.entry
module.exports = webpackConfig
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
API_HOST: '"http://vue.jinchangxiao.com"',
API_PORT: '""',
JANUS_HOST: '""',
JANUS_PORT: '""'
})
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 8885,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}
module.exports = {
NODE_ENV: '"production"',
API_HOST: '"http://biw-mt.vip.vip.com"',
API_PORT: '""',
JANUS_HOST: '"http://vup-janus.vip.vip.com"',
JANUS_PORT: '""'
}
var merge = require('webpack-merge')
var devEnv = require('./dev.env')
module.exports = merge(devEnv, {
NODE_ENV: '"testing"'
})
const fs = require('fs')
if (!fs.existsSync('./mockData')) {
fs.mkdirSync('./mockData')
}
if (!fs.existsSync('./test/data')) {
console.log('没有可迁移数据')
return
}
console.log('数据迁移中..')
exchangeFiles('./test/data')
function parseUrlToName (url) {
return url.split('/').map(item => firstUpperCase(item)).join('')
}
function firstUpperCase (str) {
return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
}
function exchangeFiles (path) {
const files = fs.readdirSync(path)
files.forEach(item => {
let newPath = path + '/' + item
let stat = fs.lstatSync(newPath)
if (stat.isDirectory()) {
exchangeFiles(newPath)
} else {
if (item.includes('json')) {
const file = fs.readFileSync(newPath)
const data = JSON.parse(file)
data.forEach(itemData => {
if (itemData.response && itemData.response['json']) {
let name = parseUrlToName(itemData.request.uri).replace('-', '')
let newData = {
url: itemData.request.uri,
data: itemData.response.json,
name: name
}
fs.writeFileSync(`mockData/${name}.json`, JSON.stringify(newData, null, 2))
console.log(`mockData/${name}.json,迁移完成`)
}
})
}
}
})
}
console.log(`全部迁移完成`)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>portal2.0-template</title>
<!-- font icon css -->
<link rel="stylesheet" href="./static/css/font-awesome.min.css">
<!-- Sdk -->
<script src="./static/vupVueSdk.js"></script>
<link rel="stylesheet" href="./static/vupVueSdk.css">
<script>
(function (){
if (window.VupPortalSdk.vueAppDevSdk) {
console.log(window.VupPortalSdk.vueAppDevSdk)
var portal = VupPortalSdk.vueAppDevSdk
var $ = portal.jQuery
var portalName = 'element'
var menuConfig = {
menus: [{
"icon": "fa-home",
"isRouteShow": 1,
"title": "首页",
"appName": portalName,
"url": "/scheduleHome"
}],
homePage: {
appName: portalName,
url: '/scheduleHome'
}
}
$(document).ready(function () {
portal.setMenu(menuConfig.menus)
portal.initPortalForDev({
homePage: menuConfig.homePage
})
})
}
})()
</script>
</head>
<body>
<div id="portalApp"></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>portal2.0-app-template</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
[{"url":"http://vue.jinchangxiao.com","target":"http://localhost:8885","hasProxy":true,"ignorePath":false}]
\ No newline at end of file
{
"data": [
{
"name": "请求参数1",
"requestData": {},
"responseData": {
"code": 200,
"msg": "获取成功",
"result": [
{
"name": "name"
}
]
}
}
],
"name": "获取待办事项",
"url": "/vue/schedule/list",
"duration": 1000
}
\ No newline at end of file
This diff is collapsed.
{
"name": "portal2.0-app-template",
"version": "1.0.0",
"description": "vue2.0",
"author": "Huai.Li <Huai.Li@vipshop.com>",
"private": true,
"scripts": {
"dev": "node build/dev-server.js",
"start": "node build/dev-server.js",
"build": "node build/build.js",
"build-test": "rimraf dist && cross-env NODE_ENV=production webpack --progress --hide-modules --config build/webpack.prod-nohash.conf.js",
"unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
"e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e",
"lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs",
"moco": "cd test/data && java -jar moco.jar start -g settings.json -p 13009 && cd -"
},
"dependencies": {
"express-proxy-mock": "^1.2.12",
"sass-bem": "^2.6.5",
"sass-resources-loader": "^2.0.0",
"vis-requestor": "^1.0.11"
},
"devDependencies": {
"autoprefixer": "^6.7.2",
"babel-core": "^6.22.1",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.10",
"babel-plugin-istanbul": "^4.1.1",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^1.1.3",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.0.1",
"cross-env": "^4.0.0",
"cross-spawn": "^5.0.1",
"css-loader": "^0.28.0",
"eslint": "^3.19.0",
"eslint-config-standard": "^6.2.1",
"eslint-friendly-formatter": "^2.0.7",
"eslint-loader": "^1.7.1",
"eslint-plugin-html": "^2.0.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"eventsource-polyfill": "^0.9.6",
"express": "^4.14.1",
"extract-text-webpack-plugin": "^2.0.0",
"file-loader": "^0.11.1",
"friendly-errors-webpack-plugin": "^1.1.3",
"html-webpack-plugin": "^2.28.0",
"http-proxy-middleware": "^0.17.3",
"inject-loader": "^3.0.0",
"lolex": "^1.5.2",
"node-sass": "^4.5.3",
"opn": "^4.0.2",
"optimize-css-assets-webpack-plugin": "^1.3.0",
"ora": "^1.2.0",
"phantomjs-prebuilt": "^2.1.14",
"rimraf": "^2.6.0",
"sass-loader": "^4.0.2",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"url-loader": "^0.5.8",
"vue-loader": "^12.1.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.3.3",
"webpack": "^2.6.1",
"webpack-bundle-analyzer": "^2.2.1",
"webpack-dev-middleware": "^1.10.0",
"webpack-hot-middleware": "^2.18.0",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
[{"host":"http://vue.jinchangxiao.com/vue?duplextrans","port":"","name":"测试"}]
\ No newline at end of file
{"host":"","port":"","id":"","name":""}
\ No newline at end of file
import createRequestor from 'create-requestor'
import { default as API } from '@/api'
let config = {
ajaxOption: {
method: 'POST',
dataType: 'json',
contentType: 'application/json',
xhrFields: {
withCredentials: true
}
},
token: {
checkBeforeSend: true,
addToHeader: false,
cookieName: 'vup_token',
headerName: 'X-Token'
},
resultCode: {
SESSION_EXPIRED: 401,
SUCCEED: 200
},
urlOption: {
host: API.option.hostJanus,
port: API.option.portJanus,
base: ''
},
// alert: function (msg) {
// },
failedMsg: '请求失败,请稍后重试!'
}
let ajax = createRequestor(config)
export function requestAPI (option, data) {
let params = { data: JSON.stringify(data) }
return ajax.requestAPI(option, params)
}
export function requestWithJsonAPI (option, data) {
return ajax.requestAPI(option, data)
}
export function requestJanusAPI (option, data) {
return ajax.requestJanusAPI(option, data)
}
import createRequestor from 'create-requestor'
import {default as API} from 'src/api'
let config = {
ajaxOption: {
method: 'POST',
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
},
token: {
checkBeforeSend: true,
addToHeader: false,
cookieName: 'vup_token',
headerName: 'X-Token'
},
resultCode: {
SESSION_EXPIRED: 401,
SUCCEED: 200
},
urlOption: {
host: API.option.host,
port: API.option.port,
base: ''
},
// alert: function (msg) {
// bootbox.alert(msg)
// },
failedMsg: '请求失败,请稍后重试!'
}
let ajax = createRequestor(config)
export function requestAPIUpload (option, data) {
return ajax.requestAPI(option, data)
}
import createRequestor from 'create-requestor'
import { default as API } from '@/api'
let config = {
ajaxOption: {
method: 'GET',
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
},
token: {
checkBeforeSend: false,
addToHeader: false,
cookieName: 'vup_token',
headerName: 'X-Token'
},
resultCode: {
SESSION_EXPIRED: 401,
SUCCEED: 2000
},
urlOption: {
host: API.option.host,
port: API.option.port,
base: ''
},
// alert: function (msg) {
// },
failedMsg: '请求失败,请稍后重试!'
}
let ajax = createRequestor(config)
export function requestAPI (option, data) {
let params = { data: JSON.stringify(data) }
return ajax.requestAPI(option, params)
}
export function requestWithJsonAPI (option, data) {
return ajax.requestAPI(option, data)
}
export function requestJanusAPI (option, data) {
return ajax.requestJanusAPI(option, data)
}
import ElementApi from './apis/element'
const API_HOST = process.env.API_HOST
const API_PORT = process.env.API_PORT
const JANUS_HOST = process.env.JANUS_HOST
const JANUS_PORT = process.env.JANUS_PORT
const option = {
tokenKey: '__token__',
sessionExpiredCode: 401,
loginUrl: '/logout.php',
host: API_HOST,
port: API_PORT,
hostJanus: JANUS_HOST,
portJanus: JANUS_PORT,
baseUrl: '',
ajax: {
method: 'POST',
dataType: 'json'
}
}
let apis = {}
apis = Object.assign(apis, ElementApi)
export default {
option,
...apis
}
const urlEnd = '?duplextrans'
export default {
getScheduleList: {
url: '/vue/schedule/list' + urlEnd
}
}
/*# sourceMappingURL=app.css.map */
{
"version": 3,
"mappings": "",
"sources": [],
"names": [],
"file": "app.css"
}
\ No newline at end of file
.element-app {
.mb20 {
margin-bottom:20px;
}
}
import VueCacheData from 'vue-cache-data'
let AppCache = new VueCacheData()
import { requestAPI, api } from '@/lib/commonMixin'
AppCache.add('queryCount', {}, function (onSucc, onFail) {
requestAPI(api.queryContent, {}).then((result) => {
onSucc(result)
}, onFail)
})
AppCache.init()
export default AppCache
import {
requestAPI,
api
} from '@/lib/commonMixin'
import Breadcrumb from '../unit/Breadcrumb.vue'
import VTable from '../unit/VTable.vue'
function getDefault (vm, key, def) {
let value = def
if (vm.$route.query[key]) value = vm.$route.query[key]
if (vm.rule.pageSize) value = vm.rule.pageSize
return parseInt(value)
}
export default {
components: {
Breadcrumb,
VTable
},
data () {
return {
loading: false,
post: null,
error: null,
tableData: {},
formData: {}
}
},
created () {
// 组件创建完后获取数据,
// 此时 data 已经被 observed 了
this.formData = Object.assign(this.formData, this.$route.query)
this.fetchData()
},
mounted () {
},
watch: {
// 如果路由有变化,会再次执行该方法
'$route': function () {
this.fetchData()
}
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
let query = {
pageIndex: getDefault(this, 'pageIndex', 1),
pageSize: getDefault(this, 'pageSize', 20)
}
query = Object.assign({}, query, this.$route.query)
if (query.t) delete query.t
// replace getPost with your data fetching util / API wrapper
requestAPI(api[this.$options.options.api], query)
.then((res) => {
this.tableData = res
this.loading = false
})
.catch((res) => {
this.listLoading = false
})
},
query () {
let query = Object.assign({}, this.$route.query, this.formData, {t: +new Date()})
this.$router.push({query})
}
}
}
<template>
<el-breadcrumb style="padding-bottom: 0px; margin-bottom: 20px;" separator="/">
<el-breadcrumb-item v-for="t of titleAry">{{t}}</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script>
export default {
props: {
title: {
require: true,
type: String
}
},
computed: {
titleAry () {
return this.title.split('/')
}
}
}
</script>
<style>
</style>
<template>
<div>
<el-table :data="data.list" highlight-current-row v-loading="rule.loading" @selection-change="selectionChange"
style="width: 100%;">
<el-table-column v-if="this.rule.selectionChange" type="selection">
</el-table-column>
<template v-for="item in rule.list">
<el-table-column v-if="!item.slots" :label="item.label" :width="item.width" :formatter="formatter(item)"
:type="item.type">
</el-table-column>
<el-table-column v-if="item.slots" :label="item.label" :width="item.width">
<template scope="scope" :item="item" :handle="handle">
<template v-for="slot in item.slots">
<el-button v-if="slot.type=='btn' || !slot.type" :type="slot.btnType" size="small"
@click="handle(scope.row, scope.$index, slot)">{{slot.text}}
</el-button>
<a v-if="slot.type=='link'" :href="href(slot.href, scope.row)">{{slot.text}}</a>
</template>
</template>
</el-table-column>
</template>
</el-table>
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageIndex"
:page-sizes="rule.pageSizes?rule.pageSizes:pageSizes"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="data.total"></el-pagination>
</div>
</template>
<script>
export default{
props: {
rule: {
require: true,
type: Object
},
data: {
require: true,
type: [Object]
}
},
data: function () {
function getDefault (vm, key, def) {
let value = def
if (vm.$route.query[key]) value = vm.$route.query[key]
if (vm.rule.pageSize) value = vm.rule.pageSize
return parseInt(value)
}
return {
pageSizes: [20, 50, 100, 200],
pageSize: getDefault(this, 'pageSize', 20),
pageIndex: getDefault(this, 'pageIndex', 1)
}
},
methods: {
selectionChange (sels) {
if (this.rule.selectionChange) this.rule.selectionChange(sels)
},
formatter: function (item) {
if (item.formatter) return item.formatter
return function (row, column) {
if (item.exchange) {
return item.exchange[row.sex]
}
return row[item.prop]
}
},
handle (row, index, item) {
if (item.click) item.click(row, index)
},
href (href, row) {
if (typeof href === 'string') return href
if (typeof href === 'function') return href(row)
},
handleCurrentChange (pageIndex) {
this.updateRoute({pageIndex})
},
handleSizeChange (pageSize) {
this.updateRoute({pageSize})
},
updateRoute (obj) {
let query = this.$route.query
query = Object.assign({}, query, obj)
this.$router.push({query})
}
}
}
</script>
<style scope>
.pagination {
margin-top: 10px;
}
</style>
<template>
<section class="obear-schedule-item">
<el-row class="obear-schedule-row">
<el-col :span="3" class="obear-schedule-left">
<div>
<i class="fa fa-star-o" aria-hidden="true"></i><span>客户名称({{ isNullClient ? '未设置' : item.client.name }}</span>
</div>
<div>
<i class="fa fa-id-card" aria-hidden="true"></i></i><span>{{ item.createdBy.name }}</span>
</div>
<div>
<i class="fa fa-connectdevelop" aria-hidden="true"></i>
<span>{{ item.department.name }}</span>
<span class="obear-schedule-left__private" :class="[isPublic ? 'colRed' : 'colGreen']">{{ isPublic ? '私人' : '共享' }}</span>
</div>
</el-col>
<el-col :span="21" class="obear-schedule-right">
<div class="obear-schedule-right__item">
<div>
<span>待办时间:{{ item.schedule_week_display }}</span>
</div>
<div>
<span>状态:</span><span class="obear-schedule-right__status">{{ item.schedule_status_display }}</span>
</div>
<div>
<span class="obear-schedule-right__content">内容</span><span>:123</span>
</div>
</div>
<div class="obear-schedule-right__item">
<div>
<span>开始时间:{{ item.start_at }}</span>
</div>
<div>
<span>图片:</span><span></span>
</div>
<div>
<span class="obear-schedule-right__content">情况说明</span><span>{{ item.complete_description }}</span>
</div>
</div>
<div class="obear-schedule-right__item">
<div>
<span>结束时间:{{ item.end_at }}</span>
</div>
<div>
<span>创建时间:{{ item.created_at }}</span><span></span>
</div>
<div>
<span>&nbsp;</span>
</div>
</div>
<div class="obear-schedule-right__item">
<div>
<span>重复:</span>
</div>
<div>
<span>创建人:{{ item.scheduleCreator.name }}</span><span></span>
</div>
<div>
<el-button type="primary" size="mini"><i class="el-icon-share el-icon--left"></i>留言</el-button>
<el-button type="primary" size="mini"><i class="el-icon-share el-icon--left"></i>汇报</el-button>
<el-button type="primary" size="mini"><i class="el-icon-share el-icon--left"></i>编辑</el-button>
<el-button type="primary" size="mini"><i class="el-icon-share el-icon--left"></i>删除</el-button>
</div>
</div>
</el-col>
</el-row>
</section>
</template>
<script>
export default {
name: 'scheduleItem',
props: {
item: Object
},
data () {
return {
}
},
computed: {
isNullClient () {
return !this.item.client
},
isPublic () {
return !!this.item.is_public
}
},
mounted () {
}
}
</script>
<style scoped lang="scss">
.colRed {
color: red;
border: 1px solid red;
}
.colGreen {
color: green;
border: 1px solid green;
}
@include c('schedule-item') {
margin-bottom: 10px;
}
@include c('schedule-row') {
height:100px;
background-color:white;
}
@include c('schedule-left') {
background-color: #FF6A6A;
height:100%;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 5px 0 5px 0;
div {
margin-left:10px;
}
div:first-child {
color: white;
}
span {
display:inline-block;
padding-left:5px;
}
@include e('private') {
display: inline-block;
// border: 1px solid black;
padding-right: 5px;
border-radius:5px;
width:40px;
height:20px;
}
}
@include c('schedule-right') {
height:100%;
display: flex;
@include e('item') {
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 5px 0 5px 5px;
flex:1;
}
@include e('status') {
color: red;
}
@include e('content') {
display: inline-block;
border: 1px solid red;
border-radius:5px;
height:20px;
padding: 0 5px 0 5px;
color: red;
}
}
</style>
<template>
<section class="select-comp-wrap" @click="showList">
<div class="el-select">
<div class="el-input" :class="{'is-disabled': disabled}">
<i ref="icon" class="el-input__icon el-icon-caret-top" />
<input placeholder="请选择" readonly="readonly" :value="textFormat" :disabled="disabled" icon="caret-top" type="text" class="el-input__inner" >
</div>
<div class="list-wrap" ref="listWrap">
<div class="search-input">
<input type="text" :placeholder="placeholder" v-model="searchText" @input="search">
</div>
<div>
<ul v-if="noEmptyList">
<li v-for="item in list" :class="{ 'active': item.value == value }" @click.stop="select( item )">
{{ item.text }}
<template v-if="showValue && item.value !== '' && item.value !== '-1'">({{ item.value }})</template>
</li>
</ul>
<p v-else>没有数据</p>
</div>
</div>
</div>
</section>
</template>
<script>
import $ from 'jquery'
import {
api,
requestAPI
} from '@/lib/commonMixin'
export default {
props: {
text: String,
stillLoadWhenEmpty: {
type: Boolean,
default: true
},
startLoadInitial: {
type: Boolean,
default: true
},
showValue: Boolean,
localSearch: Boolean,
value: [String, Number],
apiName: String,
disabled: Boolean,
onSelect: Function,
dataFilter: Function,
paramsFilter: Function,
placeholder: {
type: String,
default: '请输入搜索关键字'
}
},
data () {
return {
list: [],
listBak: [],
searchText: '',
timeout: null
}
},
computed: {
textFormat () {
let text = this.text
let value = this.value
let newValue = (value !== '' && value !== '-1') ? ('(' + value + ')') : ''
let newText = text !== '' ? (text + newValue) : text
return this.showValue ? newText : this.text
},
noEmptyList () {
return this.list && this.list.length
},
listWrapEl () {
return $(this.$refs.listWrap)
},
iconEl () {
return $(this.$refs.icon)
}
},
watch: {
value (value) {
if (!this.disabled && value === '') {
this.$emit('onSelect', { text: '', value: '' })
}
}
},
mounted () {
if (this.disabled) return
this.setListWidth()
this.listWrapHideEventInit()
if (this.startLoadInitial) {
this.loadData()
}
},
destroyed () {
this.unbindHideEvent()
},
methods: {
loadData (resove, reject) {
if (!this.stillLoadWhenEmpty && this.searchText === '') {
reject && reject('!this.stillLoadWhenEmpty && this.searchText === \'\'')
return
}
return this.getList().then(result => {
resove && resove(this.list)
}, reject)
},
getList () {
if (!this.apiName) return
let params = {
q: this.searchText.trim(),
limit: 50
}
if (this.paramsFilter) {
params = this.paramsFilter(this.searchText)
}
return requestAPI(api[this.apiName], params)
.then((res = {}) => {
if (this.dataFilter) {
this.list = this.dataFilter(res)
this.listBak = this.dataFilter(res)
} else {
this.list = res || []
this.listBak = res || []
}
})
},
search () {
if (this.localSearch) {
this.searchInLocalData()
} else {
if (!this.stillLoadWhenEmpty && this.searchText === '') {
this.list = []
return
}
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
this.getList()
}, 400)
}
},
searchInLocalData () {
let listBak = this.listBak
let searchText = this.searchText.trim()
if (searchText === '') {
this.list = $.extend(true, [], listBak)
} else {
this.list = listBak.filter(item => {
return item.text.indexOf(searchText) > -1
})
}
},
select (item) {
this.$emit('onSelect', item)
this.listWrapEl.slideUp('fast')
this.iconEl.removeClass('is-reverse')
},
showList () {
if (this.disabled) return
this.listWrapEl.slideDown('fast')
this.iconEl.addClass('is-reverse')
},
setListWidth () {
const el = $(this.$el)
const width = el.width()
const paddingLeft = parseInt(el.css('padding-left'))
const paddingRight = parseInt(el.css('padding-right'))
this.listWrapEl.width(width + paddingLeft + paddingRight - 2)
},
listWrapHideEventInit () {
$(document.body).on('click', this.hideEvent)
},
hideEvent (event) {
const el = $(this.$el)
const nodesInCurrComp = $(event.target).closest(el)
if (!nodesInCurrComp.length && this.listWrapEl) {
this.listWrapEl.slideUp('fast')
this.iconEl.removeClass('is-reverse')
}
},
unbindHideEvent () {
$(document.body).unbind('click', this.hideEvent)
}
}
}
</script>
<style scoped>
.disabled {
background: #f4f4f4;
color: #999;
}
.el-select {
width: 100%;
}
.select-comp-wrap {
position: relative;
display: inline-block;
vertical-align: middle;
}
.select-comp-wrap .select-header {
width: 100%;
height: 100%;
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.select-comp-wrap i.fa-times {
position: absolute;
top: 0;
right: 0;
z-index: 999;
padding: 11px;
cursor: pointer;
color: #c4c4c4;
font-size: 12px;
}
.select-comp-wrap i.fa-times:hover {
color: #666;
}
.select-comp-wrap .list-wrap {
border: #ccc 1px solid;
display: none;
position: absolute;
top: 40px;
left: 0px;
z-index: 999;
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,.12), 0 0 6px rgba(0,0,0,.04);
}
.select-comp-wrap .list-wrap .search-input {
text-align: center;
margin: 5px 0;
}
.select-comp-wrap .list-wrap .search-input input {
width: 94%;
border-radius: 5px !important;
padding: 3px 6px;
margin: 3px 0;
border: #ddd 1px solid;
height: 30px;
}
.select-comp-wrap .list-wrap ul,
.select-comp-wrap .list-wrap ul li {
list-style: none;
margin: 0;
padding: 0;
}
.select-comp-wrap .list-wrap ul {
max-height: 200px;
padding: 0 0 5px 0;
overflow: auto;
}
.select-comp-wrap .list-wrap ul li {
padding: 7px 0 7px 10px;
cursor: pointer;
line-height: 20px;
}
.select-comp-wrap .list-wrap ul li:hover {
background: #e4e8f1;
}
.select-comp-wrap .list-wrap ul li.active {
cursor: inherit;
background: #1c8de0;
color: #fff;
}
.select-comp-wrap .list-wrap p {
margin-bottom: 0;
padding: 0 6px 5px 8px;
margin-top: -2px;
color: #999;
}
.select-comp-wrap .list-wrap .empty-tips {
color: #999;
padding: 4px 5px 4px 12px;
}
.select-comp-wrap .list-wrap .curr-list {
padding-bottom: 5px;
}
</style>
<template>
<section class="ec-page-wrapper" style="overflow: hidden; padding-bottom: 0px;">
<el-form label-width="120px" ref="form" :rules="rules" :model="model" class="ec-create-form">
<el-form-item label="客户名称" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="待办事项内容" prop="actMsg" class="ec-clear-left ec-form-item-lg">
<el-input
class="ec-input-normal"
size="mini"
type="textarea"
:rows="2"
v-model.trim="model.actMsg">
</el-input>
<span class="tips">待办事项内容不能为空</span>
</el-form-item>
<el-form-item label="待办时间" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="开始时间" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="结束时间" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="提醒时间" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="备注" prop="actMsg" class="ec-clear-left ec-form-item-lg">
<el-input
class="ec-input-normal"
size="mini"
type="textarea"
:rows="2"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="重复" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="负责人" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
<el-form-item label="是否共享" prop="actName" class="ec-clear-left">
<el-input
class="ec-input-normal"
size="mini"
v-model.trim="model.actMsg">
</el-input>
</el-form-item>
</el-form>
</section>
</template>
<script>
// import SingleSelect from '@/components/common/singleSelect'
export default {
name: 'fullCutForm',
components: {
// SingleSelect
},
data () {
return {
activateTimeStrRules: {
disabledDate (time) {
return time.getTime() < Date.now() - 8.64e7
}
},
model: {},
rules: {}
}
},
created () {
if (this.isCreate) {
this.queryOaDeptViaJanus()
}
},
mounted () {
if (this.isEdit) {
let id = this.$route.params.id
this.getActById(id)
}
},
computed: {
isCreate () {
return this.pageType === 'create'
},
isEdit () {
return this.pageType === 'edit'
}
},
methods: {
getActById (id) {
let param = { actHandleReq: { actId: id } }
this.$model.normalGetAct(param)
.then((res) => {
this.edit(res)
})
},
edit (res) {
let resModel = res.actFullCutDetailModel
this.visStatus = resModel.visStatus
this.oldBeginTimeFormat = resModel.beginTimeFormat
this.oldEndTimeFormat = resModel.endTimeFormat
this.oaDeptNameArray.push(
{
oaDepCode: resModel.bearOaCode,
oaDepName: resModel.bearOaName
}
)
// UTIL.flatten(this.Act.form.editModel.actFullcutParam, resModel)
},
saveEvent () {
this.$refs['form'].validate((valid) => {
if (valid) {
this.$model.createFullCutAct()
.then((res) => {
this.$message.success('添加成功')
this.go()
})
}
})
},
editEvent () {
this.$refs['form'].validate((valid) => {
if (valid) {
this.$model.editFullCutAct()
.then((res) => {
this.$message.success('编辑成功')
this.go()
})
}
})
},
returnEvent () {
this.go()
},
go () {
this.$router.push({
path: '/fullCutHome/actlist'
})
}
}
}
</script>
<style lang="scss" scoped>
strong {
color: red;
}
.ec-header-block {
margin-left: 83px;
i { color: #ff9900; }
span { color: red; }
}
.ec-input-normal {
width: 295px;
}
.ec-input-small {
width: 195px;
}
.ec-create-form .el-form-item.ec-form-item-lg .el-date-editor {
width: 100%;
}
footer {
margin-top: 500px;
text-align: center;
}
.addImg {
cursor: pointer;
width: 24px;
height: 24px;
}
.deleteImg {
cursor: pointer;
width: 24px;
height: 24px;
}
.el-icon-information {
color: #20a0ff;
}
.padding-left-isRepeatLimit {
padding-left: 10px;
}
.el-form-item {
margin-bottom:0px;
}
</style>
<template>
<section>
<el-dialog title="新建待办事项" :visible.sync="diaVis" :modal-append-to-body="false">
<ScheduleForm></ScheduleForm>
<div slot="footer" class="dialog-footer" style="text-align: center;">
<el-button @click="diaVis = false" size="mini">取 消</el-button>
<el-button type="primary" @click="diaVis = false" size="mini">确 定</el-button>
</div>
</el-dialog>
</section>
</template>
<script>
import ScheduleForm from './scheduleForm'
export default {
components: {
ScheduleForm
},
data () {
return {
diaVis: false
}
},
methods: {
show () {
this.diaVis = true
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<section>
<el-row :gutter="10" class="header-title">
<el-col :span="18">
<h2>待办事项</h2>
</el-col>
<el-col :span="6">
<el-input placeholder="关键词" size="small" style="width: 200px;"></el-input>
<el-button size="small">搜索</el-button>
<el-button type="primary" icon="el-icon-plus" size="small" @click="btnCreate">新建待办事项</el-button>
</el-col>
</el-row>
<el-row class="header-title" style="height:100px;">
<el-col :span="4">
<div>
待办时间
</div>
<el-input size="small"></el-input>
</el-col>
<el-col :span="4">
<div>
状态
</div>
<el-input size="small"></el-input>
</el-col>
<el-col :span="4">
<div>
部门
</div>
<el-input size="small"></el-input>
</el-col>
<el-col :span="4">
<div>
创建人
</div>
<el-input size="small"></el-input>
</el-col>
<el-col :span="4">
<div>
重复
</div>
<el-input size="small"></el-input>
</el-col>
</el-row>
<ScheduleModal ref="scheduleModal"></ScheduleModal>
</section>
</template>
<script>
import ScheduleModal from '../schedule/scheduleModal'
export default {
components: {
ScheduleModal
},
computed: {
},
data () {
return {
}
},
methods: {
btnCreate () {
this.$refs.scheduleModal.show()
}
}
}
</script>
<style scoped lang="scss">
.el-input {
width:67%;
}
</style>
<template>
<section>
<div class="content">
<ScheduleForm></ScheduleForm>
<div class="page-body-content">
<ScheduleItem
v-for="item in result.list"
:item="item">
</ScheduleItem>
</div>
<Pagenation
:pager.sync="result.pagenation"
:total="result.pagenation.totalcount">
</Pagenation>
</div>
</section>
</template>
<script>
import ScheduleForm from './scheduleForm'
import ScheduleItem from '../common/scheduleItem'
import Pagenation from './schedulePagenation'
import {
requestWithJsonAPI,
api
} from '@/lib/commonMixin'
export default {
name: '',
components: {
ScheduleForm,
ScheduleItem,
Pagenation
},
data () {
return {
result: {
list: [],
pagenation: {
totalcount: 1,
thispage: 1,
pagesize: 10
},
thisUser: {
id: '',
name: '',
sex: ''
}
}
}
},
mounted () {
this.getScheduleList()
},
methods: {
show () {
this.$refs.scheduleModal.show()
},
getScheduleList () {
requestWithJsonAPI(api.getScheduleList)
.then((res) => {
const {
list = [],
pagenation = {},
thisUser = {}
} = res
this.result.list = list
this.result.pagenation = pagenation
this.result.pagenation.totalcount = 120
this.result.thisUser = thisUser
})
}
}
}
</script>
<style scoped lang="scss">
</style>
<template>
<section>
<el-pagination v-if="total > 0" class="mb20 mt20"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pager.thispage"
:page-sizes="[10, 20, 40, 60, 80, 100]"
:page-size="pager.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</section>
</template>
<script>
export default {
props: {
total: {
type: Number,
default: 0
}
},
data () {
return {
pager: {
thispage: 1,
pagesize: 10,
totalcount: 0
}
}
},
created () {
this.$emit('update:pager', this.pager)
},
methods: {
handleSizeChange (val) {
this.pager.thispage = 1
this.pager.pagesize = val
this.pager.totalcount = this.total
this.$emit('update:pager', this.pager)
// this.$parent.loadList()
},
handleCurrentChange (val) {
this.pager.page = val
this.pager.totalcount = this.total
this.$emit('update:pager', this.pager)
// this.$parent.loadList()
}
}
}
</script>
<style scoped>
</style>
import Vue from 'vue'
import VueBus from 'vue-bus'
import VueRouter from 'vue-router'
Vue.use(VueBus)
Vue.use(VueRouter)
import ElementUI from 'element-ui'
if (process.env.NODE_ENV !== 'production') {
Vue.use(ElementUI)
}
import './assets/css/app.scss'
import RouterInit from './route'
RouterInit()
// request
export { requestAPI, requestWithJsonAPI } from '../ajax'
export { requestJanusAPI } from '../ajax-janus'
export { default as api } from '@/api'
import api from '../api'
import $ from 'jquery'
import Cookie from 'browser-cookie'
let globalOpt = api.option
const SESSION_EXPIRED_CODE = globalOpt.sessionExpiredCode
const SUCCESS_CODE = 200
const HTTP_PROTOCOL = /^http[s]?:\/\//
function normalizeUrl (url, query, option) {
if (HTTP_PROTOCOL.test(url)) return url
let fullUrl = option.host || ''
if (option.port) {
fullUrl += option.port ? ':' + option.port : ''
}
if (option.baseUrl) {
fullUrl += option.baseUrl
}
fullUrl += url
if (Object.keys(query).length > 0) {
fullUrl += '?' + $.param(query)
console.log(fullUrl)
}
return fullUrl
}
function mergeAjaxOption (...options) {
let option1 = options.shift()
let option2 = options.shift()
let query = {...option1.query, ...option2.query}
let data = {...option1.data, ...option2.data}
let headers = {...option1.headers, ...option2.headers}
let mergedResult = {
...option1,
...option2,
query,
data,
headers
}
if (options.length) {
options.unshift(mergedResult)
return mergeAjaxOption(...options)
} else {
return mergedResult
}
}
export function request (option) {
return new Promise(function (resolve, reject) {
$.ajax(option).then(function (res, status, xhr) {
let code = res.code
if (code === SESSION_EXPIRED_CODE) {
window.location.replace(globalOpt.loginUrl)
}
if (code === SUCCESS_CODE) {
resolve(res.result)
} else {
// 如果不执行 reject,可能加载中动画不被关闭
reject(res.result, xhr, null)
if (res.msg) {
// 先让界面变化
setTimeout(function () {
window.alert(res.msg)
}, 300)
}
}
}, function (xhr, status, error) {
console.error('请求' + option.url + '失败:', xhr, status, error)
// 如果不执行 reject,可能加载中动画不被关闭
reject(null, xhr, error)
// 先让界面变化
setTimeout(function () {
if ('onLine' in window.navigator) {
if (!window.navigator.onLine) {
window.alert('网络连接已断开,请连接网络后重试!')
} else {
window.alert('数据请求失败,请稍后重试。\n如还是未能解决,请向系统客服咨询,谢谢。\n数据请求地址:' + option.url)
}
} else {
window.alert('数据请求失败!\n请确认您的网络联接正常,并稍后重试或向系统客服咨询,谢谢。\n数据请求地址:' + option.url)
}
}, 300)
})
})
}
function getTokenFromCookie () {
let cookie = new Cookie()
return cookie.get('vup_token')
}
let isSessionExpired = false
export function requestAPI (api, option = {}) {
// 第一个请求会放过期提示用户登录后,避免之后的其他请求再次弹消息
if (isSessionExpired) {
window.location.href = globalOpt.loginUrl
return new Promise(function (resolve, reject) {
resolve({})
})
}
// merge option
let ajaxOption = mergeAjaxOption(
globalOpt.ajax, // global
api, // curr api option
option // curr request option
)
ajaxOption.url = normalizeUrl(ajaxOption.url, ajaxOption.query, globalOpt)
delete ajaxOption.query
// ajaxOption.contentType = 'application/json'
// ajaxOption.dataType = 'json'
// ajaxOption.data = JSON.stringify(ajaxOption.data)
ajaxOption.data = {data: JSON.stringify(ajaxOption.data)}
// stringify object member of data
let data = ajaxOption.data
for (let p in data) {
let dp = data[p]
if (typeof dp === 'object' && dp !== null) {
data[p] = JSON.stringify(dp)
}
}
// check is session expired
let token = getTokenFromCookie()
if (!token && process.env.NODE_ENV === 'production') {
console.info('token expired')
isSessionExpired = true
window.alert('登录超时,请重新登录!')
window.location.href = globalOpt.loginUrl
return new Promise(function (resolve, reject) {
resolve({})
})
}
// append token to header
let headers = ajaxOption.headers || (ajaxOption.headers = {})
headers['X-Token'] = token
return request(ajaxOption)
}
import Cookie from 'browser-cookie'
export let getAuthInfoFromCookie = () => {
let cookie = new Cookie()
return cookie.get('vup_token')
}
export function removeEmptyMember (obj) {
for (let p in obj) {
if (obj[p] === '') {
delete obj[p]
}
}
}
export function removeEmptyMemberArray (arr) {
let newArr = []
arr.forEach((v, i) => {
if (v.telNumber !== '') {
newArr.push(v)
}
})
return newArr
}
import './index'
import portal from 'vis-portal'
import ElementRoute from './routes/element'
let routes = []
const appName = 'element'
routes = [].concat(ElementRoute)
let RouterInit = () => {
portal.createApp(appName, {}, app => {
app.mapRoute(routes)
})
}
export default RouterInit
import ScheduleHome from '../components/schedule_list/scheduleHome'
const routes = [{
path: '/scheduleHome',
name: 'scheduleHome',
component: ScheduleHome
}]
export default routes
$bem-component-namespace: 'obear';
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
[
{
"request": {
"uri": "/dispatch-url/getExpensesDeptByName"
},
"response": {
"json": {
"code": 200,
"msg": "成功",
"result": {
"total": 2,
"list": [
{
"deptNo": 56547,
"deptName": "商务中心_运营组"
},
{
"deptNo": 56809,
"deptName": "商务中心_鞋包业务部"
}
]
}
}
}
}
]
This diff is collapsed.
[
{
"request": {
"uri": "/dispatch-url/getUsers",
"forms": {
"data": "{\"name\":\"\"}"
}
},
"response": {
"json": {
"code": 200,
"msg": "成功",
"result": {
"users": [
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部"
},
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部"
},
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部"
},
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部"
},
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部"
},
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部"
},
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305",
"remark": "商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部商务中心_服装业务部"
}
],
"total": "80"
}
}
}
},
{
"request": {
"uri": "/dispatch-url/getUsers",
"forms": {
"data": "{\"name\":\"test\"}"
}
},
"response": {
"json": {
"code": 200,
"msg": "成功",
"result": {
"users": [
{
"name": "test",
"sex": 0,
"age": "24",
"birth": "1986-10-18",
"addr": "十里煲5号院2单元305"
}
]
}
}
}
}
]
This diff is collapsed.
[
{
"request": {
"uri": "/dispatch-url/getStatus"
},
"response": {
"json": {
"code": 200,
"msg": "成功",
"result": {
"10": "待提交",
"20": "待出库",
"30": "待入库",
"40": "已出库",
"50": "已入库",
"99": "已取消"
}
}
}
}
]
This diff is collapsed.
// A custom Nightwatch assertion.
// the name of the method is the filename.
// can be used in tests like this:
//
// browser.assert.elementCount(selector, count)
//
// for how to write custom assertions see
// http://nightwatchjs.org/guide#writing-custom-assertions
exports.assertion = function (selector, count) {
this.message = 'Testing if element <' + selector + '> has count: ' + count
this.expected = count
this.pass = function (val) {
return val === this.expected
}
this.value = function (res) {
return res.value
}
this.command = function (cb) {
var self = this
return this.api.execute(function (selector) {
return document.querySelectorAll(selector).length
}, [selector], function (res) {
cb.call(self, res)
})
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"env": {
"mocha": true
},
"globals": {
"expect": true,
"sinon": true
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment