Authored by 郭成尧

merge_develop

root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
... ...
bundle/**/*.js
dist/**/*.js
\ No newline at end of file
... ...
# Created by https://www.gitignore.io/api/node,webstorm,netbeans,sublimetext,vim
### Node ###
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### WebStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
.nb-gradle/
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
### YOHO ###
dist
# Created by https://www.gitignore.io/api/node,webstorm,netbeans,sublimetext,vim
### Node ###
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### WebStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
.nb-gradle/
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
### YOHO ###
dist
public/css/*
public/bundle/*
.eslintcache
public/bundle/*
.eslintcache
*.log.*
... ...
css/**/*.css
dist/**/*.css
\ No newline at end of file
... ...
... ... @@ -3,21 +3,26 @@
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/4/25
*/
'use strict';
var express = require('express'),
let express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
favicon = require('serve-favicon'),
cookieParser = require('cookie-parser');
cookieParser = require('cookie-parser'),
favicon = require('serve-favicon');
var app = express();
require('express-handlebars');
let app = express();
app.set('view engine', '.hbs');
app.use(favicon(path.join(__dirname, '/public/favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// dispatcher
require('./dispatch')(app);
... ...
/**
* sub app guang
* @author: hbomb<qiqi.zhou@yoho.cn>
* @date: 2016/05/06
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
var app = express();
// set view engin
var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: ['./views/partial', `${doraemon}/partial`],
helpers: 'helpers'
}));
// router
require('./router')(app);
module.exports = app;
... ...
/**
* router of sub app guang
* @author: hbomb<qiqi.zhou@yoho.cn>
* @date: 2016/05/06
*/
'use strict';
let API = require('../../library/api');
// Your controller here
let router = function(app) {
app.get('/', function(req, res) {
let api = new API();
let name = '/productColor/queryProductColors';
api.get(name, {}).then(function(body) {
res.send(body);
}).catch(function() {
res.send('something wrong');
});
});
};
module.exports = router;
... ...
/**
* 系统配置
*
* @author hbomb qiqi.zhou@yoho.cn
* @date 2016/05/06
*/
module.exports = {
domains: {
api: 'http://192.168.102.202:8088/platform'
},
loggers: {
infoFile: {
name: 'info',
level: 'info',
filename: 'info.log'
},
errorFile: {
name: 'error',
level: 'error',
filename: 'error.log',
handleExceptions: true
},
udp: { // send by udp
level: 'debug', // logger level
host: '192.168.102.162', // influxdb host
port: '4444'// influxdb port
},
console: {
level: 'debug',
colorize: 'all',
prettyPrint: true
}
}
};
... ...
... ... @@ -8,21 +8,64 @@
const rp = require('request-promise');
const _ = require('lodash');
const log = require('./logger');
const api = require('../config/common').domains.api;
const Timer = require('./timer');
const ApiUrl = 'http://testapi.yoho.cn:28078/';
/**
* 日志打印
* @param {Object} requestPromise 请求的promise对象
*/
function logPrint(options, requestPromise) {
// 接口统计
let timer = new Timer();
timer.put('getApi');// 统计时间开始
let method = options.method ? options.method : 'get';
log.info('API Begin %s call: %s, parms: %j',
method, options.url, options.qs, {});
requestPromise.then((body) => {
let duration = timer.put('getApi');// 接口返回
log.info('API %s res: %s, parms: %j , durationMs: %d ms , body: %s',
method, options.url, options.qs, duration, body);
}).catch((error) => {
let duration = timer.put('getApi');// 接口返回
log.error('API %s res: %s, parms: %j , durationMs: %d ms error: %s , statusCode: %d',
method, options.url, options.qs, duration, error.message, error.statusCode);
});
}
let ApiUrl;
class API {
constructor(url) {
ApiUrl = url || api;
}
/**
* get
* @param url String
* @param data Obejct
*/
get(url, data) {
return rp({
let options = {
url: `${ApiUrl}${url}`,
qs: data
});
};
let requestPromise = rp(options);
logPrint(options, requestPromise);// 日志打印
return requestPromise;
}
/**
... ... @@ -30,13 +73,19 @@ class API {
* @params: urls => Array[Object[url[string], data[object]]]
*/
multiGet(urls) {
var rps = [];
let rps = [];
_.forEach(urls, function(el) {
rps.push(rp({
let options = {
url: `${ApiUrl}${el.url}`,
qs: el.data
}));
};
let requestPromise = rp(options);
logPrint(options, requestPromise);// 打印日志
rps.push(requestPromise);
});
return Promise.all(rps).then((d) => {
... ... @@ -50,11 +99,17 @@ class API {
* @param data Obejct
*/
post(url, data) {
return rp({
let options = {
url: `${ApiUrl}${url}`,
method: 'post',
form: data
});
};
let requestPromise = rp(options);
logPrint(options, requestPromise);// 打印日志
return requestPromise;
}
}
... ...
/**
* 日志工具类
* @author: hbomb<qiqi.zhou@yoho.cn>
* @date: 2016/05/06
*/
'use strict';
let winston = require('winston'),
config = require('../config/common'),
FileTransport = require('winston-daily-rotate-file');
require('influxdb-winston');
let logger = new (winston.Logger)({
transports: [
new (FileTransport)(config.loggers.infoFile),
new (FileTransport)(config.loggers.errorFile),
new (winston.transports.UdpTransport)(config.loggers.udp),
new (winston.transports.Console)(config.loggers.console)
]
});
module.exports = logger;
... ...
... ... @@ -31,7 +31,7 @@ const packageSort = argument => {
}
return newObj;
}
};
/**
* 生成签名
... ... @@ -46,7 +46,7 @@ const makeSign = argument => {
});
return md5(qs.join('&')).toLowerCase();
}
};
// 生成API签名,调用后端接口的时候有私钥校验
exports.apiSign = (params) => {
... ... @@ -91,4 +91,4 @@ exports.webSign = (params) => {
var webPrivateKey = 'yohobuyapp';
return params.key === md5(md5(webPrivateKey) + params.uid);
};
\ No newline at end of file
};
... ...
'use strict';
/**
* 计时类
* @example
* let timer = new Timer();
* timer.put('profile');
* timer.put('proflie'); // console output: 12.14
*
* @author: hbomb<qiqi.zhou@yoho.cn>
* @date: 2016/05/07
*/
class Timer {
constructor() {
this.timers = {};
}
/**
* 打点计时
*/
put(label) {
let labelTime = this.timers[label];
if (labelTime) {
let duration = process.hrtime(labelTime);
return this._round(duration[1]);
} else {
this.timers[label] = process.hrtime();
}
}
/**
* 格式化成毫秒
* @param {Number} value 纳秒
*/
_round(value) {
return Math.round(value / 10000) / 100;
}
}
module.exports = Timer;
... ...
const shelljs = require('shelljs');
const path = require('path');
const changeFiles = {
js: shelljs.exec('git diff --cached --name-only --diff-filter=ACM | grep .js$', {silent: true}).stdout,
css: shelljs.exec('git diff --cached --name-only --diff-filter=ACM | grep .css$', {silent: true}).stdout
};
const lintPath = {
js: path.resolve('./node_modules/.bin/eslint'),
css: path.resolve('./node_modules/.bin/stylelint')
};
const lintResult = {
js: {},
css: {}
};
const ext = process.platform === 'win32' ? '.cmd' : ''; // Windows 平台需要加后缀
// 在执行检查脚本的时候,不显示 NPM 错误日志
if (!shelljs.grep('npm run -s', path.resolve('./.git/hooks/pre-commit')).stdout.trim()) {
shelljs.sed('-i', 'npm run', 'npm run -s', path.resolve('./.git/hooks/pre-commit'));
}
if (changeFiles.js) {
changeFiles.js = changeFiles.js.replace(/\n/g, ' ');
lintResult.js = shelljs.exec(`${lintPath.js}${ext} -c .eslintrc --cache --fix ${changeFiles.js}`);
}
if (changeFiles.css) {
changeFiles.css = changeFiles.css.replace(/\n/g, ' ');
lintResult.css = shelljs.exec(`${lintPath.css}${ext} --config .stylelintrc ${changeFiles.css}`);
}
if (lintResult.js.code || lintResult.css.code) {
process.exit(lintResult.js.code || lintResult.css.code); // eslint-disable-line
}
... ...
... ... @@ -12,9 +12,9 @@
"dev": "node_modules/.bin/nodemon -e js,hbs -i public/ app.js",
"online": "NODE_ENV=\"production\" node app.js",
"debug": "DEBUG=\"express:*\" node app.js",
"lint-js": "node_modules/.bin/eslint -c .eslintrc --cache --fix `git diff --cached --name-only --diff-filter=ACM | grep .js$` app.js",
"lint-css": "node_modules/.bin/stylelint --config .stylelintrc `git diff --cached --name-only --diff-filter=ACM | grep .css$`",
"precommit": "npm run lint-js && npm run lint-css"
"lint-js": "./node_modules/.bin/eslint -c .eslintrc --cache --fix .",
"lint-css": "./node_modules/.bin/stylelint --config .stylelintrc public/**/*.css",
"precommit": "node lint.js"
},
"license": "MIT",
"dependencies": {
... ... @@ -22,11 +22,14 @@
"cookie-parser": "^1.4.1",
"express": "^4.13.1",
"express-handlebars": "^3.0.0",
"lodash": "^4.8.2",
"influxdb-winston": "^1.0.1",
"lodash": "^4.12.0",
"md5": "^2.1.0",
"morgan": "^1.7.0",
"request-promise": "^2.0.1",
"serve-favicon": "^2.3.0"
"request-promise": "^3.0.0",
"serve-favicon": "^2.3.0",
"winston": "^2.2.0",
"winston-daily-rotate-file": "^1.0.1"
},
"devDependencies": {
"autoprefixer": "^6.3.6",
... ... @@ -39,6 +42,8 @@
"gulp-sourcemaps": "^2.0.0-alpha",
"gulp-util": "^3.0.7",
"husky": "^0.11.4",
"mocha": "^2.4.5",
"nodemon": "1.9.2",
"postcss-assets": "^4.0.1",
"postcss-cachebuster": "^0.1.2",
"postcss-calc": "^5.2.1",
... ... @@ -51,11 +56,12 @@
"postcss-sprites": "^3.1.2",
"postcss-use": "^2.0.2",
"precss": "^1.4.0",
"stylelint": "^6.2.2",
"stylelint-config-yoho": "^1.2.0",
"rewire": "^2.5.1",
"shelljs": "^0.7.0",
"stylelint": "^6.3.3",
"stylelint-config-yoho": "^1.2.2",
"webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1",
"webpack-stream": "^3.1.0",
"shelljs": "^0.7.0"
"webpack-stream": "^3.1.0"
}
}
... ...
let expect = require('expect.js');
let Timer = require('../../library/timer');
describe('/library/timer', function() {
it('延迟100ms,期望大于或等于100ms', function(done) {
let t = new Timer();
t.put('aa');
setTimeout(function() {
let time = t.put('aa');
expect(Math.round(time) >= 100).to.be.ok();
done();
}, 100);
});
});
... ...
require('./library/timer.test');
... ...