Commit 262012ff authored by yaobeibei's avatar yaobeibei

init

parent 449b5738
draft
node_modules
draft/
config/dev.js
.vscode
*.logs
*.log
.DS_Store
package-lock.json
**/*.swp
### Health check 'curl /ping'
FROM reg.yunpro.cn/library/node:9.11.1
WORKDIR /app
ADD . /app/
ENV PORT=8017
ENV PROJECT_LEVEL=production
ENV MONGO_STOCK_DB='mongodb://root:h4R1FWWVcNiR@mongo-bjwjh-v4-1.localhost:1304,mongo-bjwjh-v4-2.localhost:1304,mongo-bjwjh-v4-3.localhost:1304/rmk-invoicing?replicaSet=bjwjh-v4&authSource=admin'
ENV MONGO_DB='mongodb://open:h4R1FWWVcNiR@mongo-bjwjh-v4-1.localhost:1304,mongo-bjwjh-v4-2.localhost:1304,mongo-bjwjh-v4-3.localhost:1304/rmk-open-api?replicaSet=bjwjh-v4&authSource=admin'
ENV MONGO_URI='mongodb://bjwjh-admin:c9yJ2gBFkp7U6@mongo-bjwjh-rs-1.localhost:1302,mongo-bjwjh-rs-2.localhost:1302,mongo-bjwjh-rs-3.localhost:1302/tag_urls?replicaSet=bjwjh-rs&authSource=admin'
RUN \
rm /etc/localtime && \
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV NODE_ENV='production'
EXPOSE 8017
CMD node index.js
### Health check 'curl /ping'
FROM reg.yunpro.cn/library/node:9.11.1
WORKDIR /app
ADD . /app/
ENV PORT=8010
ENV PROJECT_LEVEL=production
ENV MONGO_STOCK_DB='mongodb://root:h4R1FWWVcNiR@mongo-bjwjh-v4-1.localhost:1304,mongo-bjwjh-v4-2.localhost:1304,mongo-bjwjh-v4-3.localhost:1304/rmk-invoicing?replicaSet=bjwjh-v4&authSource=admin'
ENV MONGO_DB='mongodb://open:h4R1FWWVcNiR@mongo-bjwjh-v4-1.localhost:1304,mongo-bjwjh-v4-2.localhost:1304,mongo-bjwjh-v4-3.localhost:1304/rmk-open-api?replicaSet=bjwjh-v4&authSource=admin'
ENV MONGO_URI='mongodb://bjwjh-admin:c9yJ2gBFkp7U6@mongo-bjwjh-rs-1.localhost:1302,mongo-bjwjh-rs-2.localhost:1302,mongo-bjwjh-rs-3.localhost:1302/tag_urls?replicaSet=bjwjh-rs&authSource=admin'
RUN \
rm /etc/localtime && \
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV NODE_ENV='production'
EXPOSE 8010
CMD node index.js
# open-api /*
管理后台
*/
功能:
文章管理
运营管理
客户管理
订单管理
项目启动
build npm run build
prod / npm run start
dev /node app
docker镜像
reg.yunpro.cn/wifi/prod-awbr-admin
访问地址
http://awbr.apps.xiaoyun.com/
admin账户
admin 123
\ No newline at end of file
const config = process.env.NODE_ENV === 'production'
? require('./prod')
: require('./dev');
console.log('RUN as ', process.env.NODE_ENV === 'production' ? 'Production' : 'Development');
module.exports = config;
\ No newline at end of file
const {
MONGO_DB = 'mongodb://root:h4R1FWWVcNiR@10.11.3.136:1304/rmk-open',
MONGO_STOCK_DB = 'mongodb://root:h4R1FWWVcNiR@10.11.3.136:1304/rmk-invoicing',
MONGO_URI = 'mongodb://bjwjh-admin:c9yJ2gBFkp7U6@10.11.3.136:1302/tag_urls?authSource=admin',
JWT_SECRET = '9104b291d48a4844d2a346a695d2602fa4d8ffe7328f7c98c27270b32a6b636f',
HOST = 'http://callcenter.xiaoyun.com',
APPID = 'wx868fb5b459229a1e',
APPSECRET = '17d470ec5bbe1560ade35e8014c5d993',
accessKey = 'D1CSX8QB0BTCDRTSK32E',
secretKey = 'GV/4BEPn7GQcbxHYD4X2mIIVpXhFPywxsHJRxdgT'
} = process.env;
module.exports = {
MONGO_DB: MONGO_DB.replace(/&/g, ','),
MONGO_STOCK_DB,
MONGO_URI,
JWT_SECRET,
APPID,
APPSECRET,
HOST,
accessKey,
secretKey,
MONGO_URI
}
const jwt = require('jsonwebtoken');
const config = require('config');
const hash = require('utils/hash');
const tools = require('utils/tools');
const _ = require('lodash');
const mongoose = require('mongoose');
const Account = require('db/mongo/open/account');
const {
ObjectId
} = require('mongoose').Types;
function getToken(user, opt = {}) {
if (!opt.expiresIn) {
opt.expiresIn = '7d';
}
return jwt.sign(
user,
config.JWT_SECRET,
opt
);
}
exports.session = async (ctx, next) => {
let {
zyxKey,
zyxSecret
} = ctx.request.body;
let tokenObj = await Account.findOne({
zyxKey,
removed: { $ne: true }
});
ctx.assert(tokenObj, 404, 'zyxKey 不存在,请联系客服', {
code: 1
});
ctx.assert(
hash(zyxSecret) === tokenObj.zyxSecret,
500,
'zyxSecret错误', {
code: 1
}
);
let session = getToken(_.pick(tokenObj, '_id','zyxKey', 'zyxSecret'));
ctx.body = {
status: 'ok',
result: {
session
}
}
}
// 开通开放账户
exports.account = async (ctx, next) => {
let {
zyxKey,
zyxSecret,
company='',
phone='',
nickname='',
calltaskNotityUrl='',
orderNotifyUrl=''
} = ctx.request.body;
let account = await new Account({
zyxKey,
zyxSecret,
company,
phone,
nickname,
calltaskNotityUrl,
orderNotifyUrl
}).save();
ctx.body = {
status: 'ok',
result: {
account
}
}
}
exports.auth = async(ctx, next) => {
let user = ctx.state.user;
ctx.assert(
user,
401,
'认证错误', {
code: 1
}
);
await next();
}
const jwt = require('jsonwebtoken');
const config = require('config');
const hash = require('utils/hash');
const tools = require('utils/tools');
const _ = require('lodash');
const api = require('utils/api');
const mongoose = require('mongoose');
const clueContrl = require('./clue');
const groupContrl = require('./group');
const Clue = require('db/mongo/open/clue');
const CallTask = require('db/mongo/open/calltask');
//const callTaskContrl = require('./callTask');
const HOST = config.HOST;
const STAMP = 1000 * 60;
const {
ObjectId
} = require('mongoose').Types;
const areaCode = require('utils/area');
const INFINITE = 1000000000;
async function unbindWhenCall( phone ) {
let calltasks = await CallTask.find({ caller: phone + '', result: { $exists: false } }, null, {
skip: 0,
limit: INFINITE
});
console.log('拨打前解绑:*******' + calltasks.length)
if(!calltasks.length) return;
for( let calltask of calltasks ) {
let { bindID, _id } = calltask;
let rep = await api({
method: 'GET',
url: HOST + '/unbinding',
qs: {
bindID
},
json: true
});
console.dir(rep);
console.log('****************************')
console.log(rep)
await CallTask.updateOne({ _id }, { $set: {
updateTime: Date.now(),
duration: 0,
url: null,
result: 'OTHER',
minutes: 0,
whencall: true
}})
}
console.log('拨打前解绑结束:*******' )
return;
}
async function unbind() {
console.dir('自动解绑任务')
let calltasks = await CallTask.find({ startTime: { $lt: Date.now() - 1000 * 60 * 30 }, result: { $exists: false } }, null, {
skip: 0,
limit: INFINITE
});
console.dir(calltasks ? calltasks.length : 0 + '个解绑任务');
for( let calltask of calltasks ) {
let { bindID, _id } = calltask;
let rep = await api({
method: 'GET',
url: HOST + '/unbinding',
qs: {
bindID
},
json: true
});
console.log('auto unbinding job result')
console.log(rep)
if((rep && rep.status === 'ok') || rep.msg === 'already unbinded')
await CallTask.updateOne({ _id }, { $set: {
updateTime: Date.now(),
duration: 0,
url: null,
result: 'OTHER',
minutes: 0,
cron: true
}})
}
}
console.dir(process.env.NODE_ENV);
if(process.env.NODE_ENV == 'production')
setInterval(async () => {
await unbind();
}, STAMP);
// 获取订单列表
exports.bind = async (ctx, next) => {
let {
clue,
caller,
callback_data
} = ctx.request.body;
console.dir(ctx.request.body)
let clueObj = await clueContrl.findByCode(clue);
ctx.assert(clueObj && clueObj.account + '' === ctx.state.user._id + '', 500, '参数错误,clue', {
code: 1
});
ctx.assert(/^1(3|4|5|7|8|9)\d{9}$/.test(caller), 500, '参数错误,caller', {
code: 1
});
let { unikey, from: operator, province, city, account, type: clueType, _id, user } = clueObj;
await unbindWhenCall(caller + '');
let provinceCode = areaCode(province, city);
try {
let rep = await api({
method: 'POST',
url: HOST + '/binding',
body: {
caller: caller + '',
unikey: unikey,
province: provinceCode,
operator
},
json: true
});
console.dir(rep);
let { bindID, volan } = rep;
console.dir('请求绑定成功' + caller );
let callTask = await new CallTask({ clueType, user, callback_data, from: operator, bindID, unikey, caller, called: volan, account, clue: _id, account, startTime: Date.now() }).save();
await Clue.updateOne({
_id
}, {
$push: {
calledHistory: callTask._id
}
});
console.dir('初始化话单成功' + caller );
ctx.body = {
status: 'ok',
data: callTask
}
} catch( error ) {
console.dir(error);
ctx.assert(!error, 500, '运营商拒绝服务', {
code: 1
});
}
}
exports.list = async (ctx, next) => {
let {
skip=0,
limit=10,
caller,
start,
bindID,
end
} = ctx.request.body;
let account = ctx.state.user;
skip = parseInt(skip);
limit = parseInt(limit);
ctx.assert(!isNaN(skip), 500, '参数错误,skip', {
code: 1
});
ctx.assert(!isNaN(limit), 500, '参数错误,limit', {
code: 1
});
ctx.assert(limit <= 500, 500, '参数错误,limit <= 500', {
code: 1
});
if(start || end) {
ctx.assert(/^\d{8}$/.test(start) && /^\d{8}$/.test(end), 500, '参数错误,start end', {
code: 1
});
}
let conditions = tools.generateDateQuery(start, end);
conditions.account = account._id;
if(bindID) {
conditions.bindID = bindID;
}
if(caller) conditions.caller = caller;
let calltasks = await CallTask.find(conditions, null, {
skip,
limit
});
let total = await CallTask.count(conditions);
ctx.body = {
status: 'ok',
result: {
calltasks,
total,
skip
}
}
}
\ No newline at end of file
This diff is collapsed.
const jwt = require('jsonwebtoken');
const config = require('config');
const hash = require('utils/hash');
const tools = require('utils/tools');
const _ = require('lodash');
const mongoose = require('mongoose');
const Group = require('db/mongo/open/group');
const User = require('db/mongo/open/user');
const {
ObjectId
} = require('mongoose').Types;
exports.findById = async(group) => {
return await Group.findById(group);
}
// 获取画像列表
exports.list = async (ctx, next) => {
let {
skip=0,
limit=10,
start,
end,
user
} = ctx.request.body;
let account = ctx.state.user;
skip = parseInt(skip);
limit = parseInt(limit);
ctx.assert(!isNaN(skip), 500, '参数错误,skip', {
code: 1
});
ctx.assert(!isNaN(limit), 500, '参数错误,limit', {
code: 1
});
if(start || end) {
ctx.assert(/^\d{8}$/.test(start) && /^\d{8}$/.test(end), 500, '参数错误,start end', {
code: 1
});
}
let conditions = tools.generateDateQuery(start, end);
if(user) {
ctx.assert(tools.valid(user), 500, '参数错误,user', {
code: 1
});
let userObj = await User.findById(user);
ctx.assert(userObj && userObj.account + '' === ctx.state.user._id + '', 500, '参数错误,user', {
code: 1
});
conditions.user = user;
}
conditions.account = account._id;
let groups = await Group.find(conditions, null, {
skip,
limit
});
let total = await Group.count(conditions);
ctx.body = {
status: 'ok',
result: {
groups,
total,
skip
}
}
}
//创建画像
exports.create = async (ctx, next) => {
let {
name,
hosts,
sex,
age,
province,
city,
user
} = ctx.request.body;
ctx.assert(hosts && Array.isArray(hosts) && hosts.length, 500, '参数错误,hosts', {
code: 1
});
ctx.assert(name && name.length, 500, '参数错误,name', {
code: 1
});
ctx.assert(ctx.state.user._id , 401, '权限错误', {
code: 1
});
let data = {
name,
hosts,
user,
account: ctx.state.user._id
};
if(user) {
ctx.assert(tools.valid(user), 500, '参数错误,user', {
code: 1
});
let userObj = await User.findById(user);
ctx.assert(userObj && userObj.account + '' === ctx.state.user._id + '', 500, '参数错误,user', {
code: 1
});
data.user = user;
}
if(province) {
ctx.assert(province && Array.isArray(province) && province.length, 500, '参数错误,province', {
code: 1
});
data.province = province;
}
if(city) {
ctx.assert(city && Array.isArray(city) && city.length, 500, '参数错误,city', {
code: 1
});
data.city = city;
}
if(sex){
ctx.assert(sex && Array.isArray(sex) && sex.length, 500, '参数错误,sex', {
code: 1
});
data.sex = sex;
}
if(age){
ctx.assert(age && Array.isArray(age) && age.length, 500, '参数错误,age', {
code: 1
});
data.age = age;
}
let group = await new Group(data).save();
ctx.body = {
status: 'ok',
result: {
group
}
}
}
const jwt = require('jsonwebtoken');
const config = require('config');
const hash = require('utils/hash');
const tools = require('utils/tools');
const _ = require('lodash');
const mongoose = require('mongoose');
const groupContrl = require('./group');
const Order = require('db/mongo/open/order');
const User = require('db/mongo/open/user');
const {
ObjectId
} = require('mongoose').Types;
const Types = ['data', 'media', 'msg', 'record', 'imei']
// 获取订单列表
exports.list = async (ctx, next) => {
let {
id=0,
skip=0,
limit=10,
start,
award,
end,
user
} = ctx.request.body;
let account = ctx.state.user;
skip = parseInt(skip);
limit = parseInt(limit);
ctx.assert(!isNaN(skip), 500, '参数错误,skip', {
code: 1
});
ctx.assert(!isNaN(limit), 500, '参数错误,limit', {
code: 1
});
if(start || end) {
ctx.assert(/^\d{8}$/.test(start) && /^\d{8}$/.test(end), 500, '参数错误,start end', {
code: 1
});
}
let conditions = tools.generateDateQuery(start, end);
if(user) {
ctx.assert(tools.valid(user), 500, '参数错误,user', {
code: 1
});
let userObj = await User.findById(user);
ctx.assert(userObj && userObj.account + '' === ctx.state.user._id + '', 500, '参数错误,user', {
code: 1
});
conditions.user = user;
}
if(id) {
ctx.assert(tools.valid(id), 500, '参数错误,id', {
code: 1
});
conditions._id = id;
}
if(award == true || award == false) {
conditions.award = award;
}
let orders = await Order.find(conditions, null, {
skip,
limit
}).populate('origin', 'account user code meta awardCount type award count clue group subOrder status meta').populate('subOrder', 'count createdAt');
let total = await Order.count(conditions);
ctx.body = {
status: 'ok',
result: {
orders,
total,
skip
}
}
}
exports.all = async (ctx, next) => {
let {
id=0,
skip=0,
limit=10,
start,
award,
end
} = ctx.request.body;
skip = parseInt(skip);
limit = parseInt(limit);
ctx.assert(!isNaN(skip), 500, '参数错误,skip', {
code: 1
});
ctx.assert(!isNaN(limit), 500, '参数错误,limit', {
code: 1
});
if(start || end) {
ctx.assert(/^\d{8}$/.test(start) && /^\d{8}$/.test(end), 500, '参数错误,start end', {
code: 1
});
}
let conditions = tools.generateDateQuery(start, end);
if(id) {
ctx.assert(tools.valid(id), 500, '参数错误,id', {
code: 1
});
conditions._id = id;
}
if(award == true || award == false) {
conditions.award = award;
}
let orders = await Order.find(conditions, null, {
skip,
limit
}).populate('origin', 'account user code meta awardCount type award count clue group subOrder status meta').populate(
'account', 'company nickname phone zyxKey'
).populate('user', 'company name').populate('group', 'hosts province sex city age name');
let total = await Order.count(conditions);
ctx.body = {
status: 'ok',
result: {
orders,
total,
skip
}
}
}
//创建订单
exports.create = async (ctx, next) => {
let {
group,
user,
count=500,
type='data',
origin,
} = ctx.request.body;
let account = ctx.state.user._id;
ctx.assert(tools.valid(group), 500, '参数错误,group', {
code: 1
});
ctx.assert(Types.indexOf(type) >= 0, 500, '参数错误,type', {
code: 1
});
ctx.assert(tools.valid(user), 500, '参数错误,user', {
code: 1
});
let userObj = await User.findById(user);
ctx.assert(userObj && userObj.account + '' === ctx.state.user._id + '', 500, '参数错误,user', {
code: 1
});
let groupObj = await groupContrl.findById(group)
ctx.assert(groupObj && groupObj.account + '' === account + '', 500, '参数错误,group', {
code: 1
});
if(groupObj.user) {
ctx.assert(groupObj && groupObj.user + '' === user + '', 500, '参数错误,group 和 user 不匹配', {
code: 1
});
}
count = parseInt(count);
ctx.assert(count && !isNaN(count) && count > 0 , 500, '参数错误,count', {
code: 1
});
let data = {
group,
account,
user,
type,
count,
status:'审核中',
code: 'unknown',
history:[{
status: '审核中',
date: new Date()
}]
};
if(origin) {
ctx.assert(tools.valid(origin), 500, '参数错误,origin', {
code: 1
});
let orderObj = await Order.findById(origin);
ctx.assert(orderObj && orderObj.user + '' === user , 500, '参数错误,origin', {
code: 1
});
data.origin = origin;
data.award = true;
}
let order = await new Order(data).save();
ctx.body = {
status: 'ok',
result: {
order
}
}
}
const jwt = require('jsonwebtoken');
const config = require('config');
const hash = require('utils/hash');
const tools = require('utils/tools');
const _ = require('lodash');
const mongoose = require('mongoose');
const Url = require('db/mongo/tag_url/domain');
const {
ObjectId
} = require('mongoose').Types;
// 获取预测
exports.list = async (ctx, next) => {
let {
url,
province
} = ctx.request.body;
let account = ctx.state.user;
ctx.assert(account, 401, '权限错误', {
code: 1
});
ctx.assert(url && url.length, 500, '参数错误,url', {
code: 1
});
let names = Array.isArray(url) ? url : [ url ];
ctx.assert(names.length > 0 && names.length < 10, 500, '参数错误,url 数组不能超过10个', {
code: 1
});
let conditions = { name: { $in: names } }
if(province && province.length) conditions.province = province;
let list = await Url.find(conditions, { name: 1, code: 1, count: 1, province: 1 }, { limit: 500, skip: 0 });
ctx.body = {
status: 'ok',
result: {
urls: list
}
}
}
const jwt = require('jsonwebtoken');
const config = require('config');
const hash = require('utils/hash');
const tools = require('utils/tools');
const _ = require('lodash');
const mongoose = require('mongoose');
const User = require('db/mongo/open/user');
const Order = require('db/mongo/open/order');
const {
ObjectId
} = require('mongoose').Types;
// 获取用户
exports.list = async (ctx, next) => {
let {
skip=0,
limit=10,
} = ctx.request.body;
skip = parseInt(skip);
limit = parseInt(limit);
ctx.assert(!isNaN(skip), 500, '参数错误,skip', {
code: 1
});
ctx.assert(!isNaN(limit), 500, '参数错误,limit', {
code: 1
});
ctx.assert(limit <= 500, 500, '参数错误,limit <= 500', {
code: 1
});
let conditions = { removed : {$ne: true }, account: ctx.state.user._id };
let users = await User.find(conditions, null, {
skip,
limit
});
let total = await User.count(conditions);
ctx.body = {
status: 'ok',
result: {
users,
total,
skip
}
}
}
exports.remove = async (ctx, next) => {
let {
user
} = ctx.request.body;
ctx.assert(tools.valid(user), 500, '参数错误,user', {
code: 1
});
let userObj = await User.findById(user);
ctx.assert(userObj && userObj.account + '' === ctx.state.user._id + '', 401, '权限错误', {
code: 1
});
let order= await Order.findOne({ user });
ctx.assert(!order, 400, '该用户存在订单不能删除,user', {
code: 1
});
let _user = await User.updateOne({ _id: user }, { $set: { removed: true } });
ctx.body = {
status: 'ok'
}
}
//备案用户
exports.create = async (ctx, next) => {
let {
licenses,
company,
name,
phone,
report
} = ctx.request.body;
ctx.assert(licenses && Array.isArray(licenses) && licenses.length , 500, '参数错误,licenses', {
code: 1
});
ctx.assert(company , 500, '参数错误,company', {
code: 1
});
ctx.assert(report , 500, '参数错误,report', {
code: 1
});
let user = await new User({
licenses,
company,
name,
phone,
report,
account: ctx.state.user._id
}).save();
ctx.body = {
status: 'ok',
result: {
user
}
}
}
const mongoose = require('mongoose');
const config = require('config');
global.Promise = mongoose.Promise = require('bluebird');
const options = {
useMongoClient: true
};
exports.db = mongoose.createConnection(process.env.MONGO_DB || config.MONGO_DB, {});
exports.stockDb = mongoose.createConnection(process.env.MONGO_STOCK_DB || config.MONGO_STOCK_DB, {});
exports.urlDb = mongoose.createConnection(process.env.MONGO_URI || config.MONGO_URI, {});
console.log('MONGO CONNECT INFO: ', process.env.MONGO_DB || config.MONGO_DB);
console.log('MONGO_STOCK_DB CONNECT INFO: ', process.env.MONGO_STOCK_DB || config.MONGO_STOCK_DB);
console.log('MONGO_URI CONNECT INFO: ', process.env.MONGO_URI || config.MONGO_URI);
\ No newline at end of file
const hash = require('utils/hash');
const mongoose = require('mongoose');
const connect = require('../connect');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
zyxKey: {
type: String,
unique: true,
required: true
},
zyxSecret: {
type: String,
required: true,
set: v => hash(v)
},
callTaskUrl: String,
clueTaskUrl: String,
nickname: String,
meta: String,
company: String,
phone: Number,
calltaskNotityUrl: String,
orderNotifyUrl: String
}, {
timestamps: true
});
module.exports = connect.db.model('account', schema);
\ No newline at end of file
/* 话单 处理 */
const mongoose = require('mongoose');
const connect = require('../connect');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
unikey: {
type: String,
required: true
},
bindID: { // 绑定ID
type: String,
required: true
},
caller: { // 主叫号
type: Number,
required: true,
},
callback_data: String,
called: { // 被叫号
type: Number,
required: true,
},
account: { // 账户
type: ObjectId,
required: true,
ref: 'account'
},
user: {
type: ObjectId,
required: true,
ref: 'user'
},
startTime: { // 开始时间
type: Number,
required: false,
},
updateTime: { // 结束时间
type: Number,
required: false,
},
duration: { // 持续时间
type: Number,
required: false,
},
clue: { // 线索
type: ObjectId,
required: true,
ref: 'clue'
},
from: {
type: String,
required: false,
},
clueType: {
type: String,
required: true,
enum: ['group', 'slot']
},
expiration: {
type: Number,
required: false,
},
result: { // 通话结果
type: String,
required: false,
},
url: { // 通话录音
type: String,
required: false,
},
minutes: { // 持续时长 分钟
type: Number,
required: false,
},
archive: { // 归档标识
type: Boolean
},
archiveDate: { // 归档日期
type: Date
}
}, {
timestamps: true
});
schema.index({ caller: -1 });
schema.index({ bindID: -1 });
module.exports = connect.db.model('calltask', schema);
\ No newline at end of file
const mongoose = require('mongoose');
const connect = require('../connect');
const generateCode = require('utils/generate-code');
const {
ObjectId
} = mongoose.SchemaTypes;
const counter = require('db/mongo/open/counter');
const schema = mongoose.Schema({
account: {
type: ObjectId,
required: true,
ref: 'account'
},
user: {
type: ObjectId,
required: true,
ref: 'user'
},
unikey: {
type: String,
required: true,
},
award: Boolean, // 是否补量
code: {
type: String,
required: true,
unique: true
},
type: {
type: String,
required: true,
enum: ['slot','group'] // 自媒体 精选画像
},
retrive: {
type: Boolean
},
retriveDate: {
type: Date
},
from: { // 来源
type: String,
required: true,
enum: ['cmcc', 'ctcc', 'cucc', 'unknow'] // 移动 电信 联通 未知
},
group: { // 画像
type: ObjectId,
required: false,
ref: 'group'
},
sex: {
type: String,
required: false,
},
age: {
type: String,
required: false,
},
city: {
type: String,
required: false,
},
province: {
type: String,
required: false,
},
host: {
type: String,
required: false,
},
virtualHost: String,
lastCall: {
type: Date,
required: false
},
order: { // 订单
type: ObjectId,
required: true,
ref: 'order'
},
subOrder: { // 子订单
type: ObjectId,
required: false,
ref: 'order_production'
},
calledHistory: [{
type: ObjectId,
ref: 'calltask'
}]
/*tagHistory: [{
type: ObjectId,
ref: 'tag_history'
}],*/
}, {
timestamps: true
});
schema.index({ createdAt: -1 });
schema.index({ calledHistory: -1 });
schema.index({ selfTag: -1 });
schema.index({ systemTag: -1 });
schema.index({ selfTag: -1, systemTag: -1 });
schema.pre('save', function (next) {
const doc = this;
console.dir(doc._id);
if(!doc.isNew) next();
else {
doc.code = doc._id + '';
next();
}
});
module.exports = connect.db.model('clue', schema);
\ No newline at end of file
const mongoose = require('mongoose');
const connect = require('../connect');
const counterSchema = mongoose.Schema({
type: { type: String, required: true, unique: true },
seq: { type: Number, default: 0 }
});
module.exports = connect.db.model('counter', counterSchema);
const mongoose = require('mongoose');
const connect = require('../connect');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
account: {
type: ObjectId,
required: true,
ref: 'account'
},
name: String,
user: {
type: ObjectId,
ref: 'user'
},
hosts:[{
type:String
}],
province: [String],
city: [String],
age:[String],
sex:[String]
}, {
timestamps: true
});
module.exports = connect.db.model('group', schema);
\ No newline at end of file
const mongoose = require('mongoose');
const connect = require('../connect');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
type: { // 锁类型
type: String,
required: true
},
status: Boolean // true 为锁定不能操作
}, {
timestamps: true
});
module.exports = connect.db.model('lock', schema);
\ No newline at end of file
const mongoose = require('mongoose');
const connect = require('../connect');
const moment = require('moment');
const generateCode = require('utils/generate-code');
const {
ObjectId
} = mongoose.SchemaTypes;
const counter = require('db/mongo/open/counter');
const schema = mongoose.Schema({
account: {
type: ObjectId,
required: true,
ref: 'account'
},
user: {
type: ObjectId,
required: true,
ref: 'user'
},
code: { // 订单编号
type: String,
required: true
},
meta: String, // 备注
origin: { // 补量订单父级来源
type: ObjectId,
ref: 'order',
required: false
},
awardCount: Number, // 需要补数线索数
type: {
type: String,
required: true,
enum: ['data', 'media', 'msg', 'record', 'imei'] // 数据 自媒体 短信 话单 imei
},
award: { // 补量订单
type: Boolean,
default: false
},
count: { // 预购数量
type: Number,
required: true
},
clue: { // 返回 发送 线索数量
type: Number,
required: false,
default: 0
},
group: { // 数据画像
type: ObjectId,
required: false,
ref: 'group'
},
subOrder: [{ // 拆分订单
type: ObjectId,
ref: 'order_production'
}],
status: { // 数据 当前状态 进展
type: String,
required: true,
enum: ['审核中', '执行中', '已关闭', '已拒绝']
},
meta: String,
check: Boolean,
checkDate: Date,
history:[{ // 生产历史
date: Date,
operator: String,
status: String
}]
}, {
timestamps: true
});
schema.index({ createdAt: -1 });
schema.index({ order: -1 });
schema.index({ type: -1 });
schema.pre('save', function (next) {
const doc = this;
let date = moment().format('YYYYMMDD');
let map = {
'data': 'D',
'msg': 'M',
'record': 'R',
'imei': 'I'
}
let suffix = ((map[doc.type] || 'U') + date);
if(!doc.isNew) next();
else
counter.findOneAndUpdate({ type: 'order' + date }, { $inc: { seq: 1 } }, { upsert: 1 }, function(error, counter) {
if(error)
return next(error);
doc.code = suffix + (counter && counter.seq ? generateCode(3, counter.seq) : '000');
next();
})
});
module.exports = connect.db.model('order', schema);
\ No newline at end of file
const mongoose = require('mongoose');
const connect = require('../connect');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
account: {
type: ObjectId,
required: true,
ref: 'account'
},
user: {
type: ObjectId,
required: true,
ref: 'user'
},
order: { // 基础订单
type: ObjectId,
required: true,
ref: 'order'
},
count: { // 数量
type: Number,
required: false
},
group: { // 基础画像
type: ObjectId,
required: true,
ref: 'group'
},
tags:[String],
retrive: {
type: Boolean
},
retriveDate: {
type: Date
},
meta: String
}, {
timestamps: true
});
module.exports = connect.db.model('order_production', schema);
\ No newline at end of file
const hash = require('utils/hash');
const mongoose = require('mongoose');
const connect = require('../connect');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
account: { // 账户
type: ObjectId,
required: true,
ref: 'account'
},
licenses: [String],
report: String,
phone: String,
company: String,
name: String
}, {
timestamps: true
});
module.exports = connect.db.model('user', schema);
\ No newline at end of file
const connect = require('../connect');
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
unikey: String,
province: {
name: String,
code: String,
},
city: {
name: String,
code: String,
},
url: String,
repoId: { type: ObjectId, ref: 'repo' },
repoCode: String,
source: {
name: String,
code: String,
},
sellRecord: Array,
undoRecord: Array,
logs: Array,
filename: String,
operatorId: { type: ObjectId, ref: 'user' },
}, {
timestamps: true
})
schema.index({ unikey: 1 });
module.exports = connect.stockDb.model('repo', schema);
\ No newline at end of file
const connect = require('../connect');
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
name: { type: String, required: true },
seq: { type: Number, default: 0 }
}, {
timestamps: true
})
module.exports = connect.stockDb.model('sequence', schema);
\ No newline at end of file
const connect = require('../connect');
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
unikey: String,
province: {
name: String,
code: String,
},
city: {
name: String,
code: String,
},
url: String,
repoId: { type: ObjectId, ref: 'repo' },
repoCode: String,
source: {
name: String,
code: String,
},
sellRecord: Array,
undoRecord: Array,
logs: Array,
filename: String,
operatorId: { type: ObjectId, ref: 'user' },
}, {
timestamps: true
})
module.exports = connect.stockDb.model('unikey', schema);
\ No newline at end of file
const connect = require('../connect');
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
orderId: String,
orderCode: String,
subOrderID: String,
account: Object,
unikeyId: { type: ObjectId, ref: 'Unikey' },
operator: String,
isCanceled: Boolean,
openapi: Boolean
}, {
timestamps: true
})
module.exports = connect.stockDb.model('unikeyout', schema);
\ No newline at end of file
const connect = require('../connect');
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
username: {
type: String,
unique: true,
required: true,
},
email: {
type: String,
unique: true,
},
password: {
type: String,
required: true,
},
role: Number,
creator: { type: ObjectId, ref: 'user' },
}, {
timestamps: true
})
module.exports = connect.stockDb.model('user', schema);
\ No newline at end of file
const connect = require('../connect');
const mongoose = require('mongoose');
const {
ObjectId
} = mongoose.SchemaTypes;
const schema = mongoose.Schema({
province: String,
city: String,
name: String,
code: String,
count : String,
description : String,
hitKeywords : Array,
industry : String,
industryCode : String,
keywords : String,
province : String,
title : String
,
}, {
timestamps: true
})
schema.index({ name: 1 });
module.exports = connect.urlDb.model('domain', schema, 'subdomain');
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>测试</title>
<meta content="sig,cmcc,toolbar" name="keywords">
<link href="http://cdn.bootcss.com/highlight.js/8.0/styles/monokai_sublime.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/highlight.js/8.0/highlight.min.js"></script>
<script >hljs.initHighlightingOnLoad();</script>
</head>
<style type="text/css">
</style>
<body style="height: 100%">
<pre style="height: 100%"><code class="plaintext">
<p>本接口为测试接口,后端没有保存话单信息,绑定成功后需要自行解绑,以免占用小号资源;限制测试500次
host为本页面域名
再营销开放接口文档</p>
</code></pre>
</body>
</html>
\ No newline at end of file
require('colors');
require('app-module-path/register');
const api = require('./utils/api');
const config = require('config');
const Koa = require('koa');
const compress = require('koa-compress');
const koaBody = require('koa-body');
const cors = require('kcors');
const bodyParser = require('koa-bodyparser');
const logger = require('koa-logger');
const path = require('path');
const mongoose = require('mongoose');
const error = require('middleware/error');
const jwt = require('middleware/jwt');
const mountRoutes = require('utils/mount-routes');
// const { uploadFile } = require('utils/upload');
const fs = require('fs');
var crypto = require('crypto');
global.Promise = mongoose.Promise = require('bluebird');
const Router = require('koa-router');
const multer = require('koa-multer');
const AGENT_BUCKET = 'remarketing-agent';
const Minio = require('minio');
const websockify = require('koa-websocket');
const { createAuto } = require('controllers/clue');
const app = websockify(new Koa());
app.ws.use(createAuto);
const file = `
<h1>upload demo</h1>
<form method="POST" action="/upload" enctype="multipart/form-data">
<p>file upload</p>
<span>picName:</span><input name="picName" type="text" /><br/>
<input name="license-pics" type="file" /><br/><br/>
<button type="submit">submit</button>
</form>`;
const bucket = 'open-api';
const minioClient = new Minio.Client({
endPoint: 'minio.xiaoyun.com',
port: 80,
useSSL: false,
accessKey: 'D1CSX8QB0BTCDRTSK32E',
secretKey: 'GV/4BEPn7GQcbxHYD4X2mIIVpXhFPywxsHJRxdgT'
});
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, './public/uploads'))
},
filename: function (req, file, cb) {
cb(null, `${file.fieldname}-${Date.now()}.png`)
}
})
const licensePic = multer({ storage: storage }).single('license-pics')
function createBucketAndUpload(bucketName, objectName, filePath) {
console.dir(arguments);
minioClient.bucketExists(bucketName, function(err, exists) {
if (err) {
return console.log(err)
}
if (exists) {
console.log(bucketName, objectName, filePath);
return uploadToMinio(bucketName, objectName, filePath);
}
// Make a bucket called remarketing-agent.
minioClient.makeBucket(bucketName, 'us-east-1', function(err) {
if (err) return console.log(err)
console.log('Bucket created successfully in "us-east-1".')
uploadToMinio(bucketName, objectName, filePath);
});
});
}
function uploadToMinio(bucketName, objectName, filePath) {
// Using fPutObject API upload your file to the bucket remarketing-agent.
minioClient.fPutObject(bucketName, objectName, filePath, { 'Content-Type': 'application/octet-stream' }, function(err, etag) {
if (err) return console.log(err)
console.log(`${objectName} uploaded successfully.`)
});
}
function downloadFromMinio(bucketName, objectName, filePath) {
if (fs.existsSync(filePath)) return console.log(`${objectName} exists`)
minioClient.fGetObject(bucketName, objectName, filePath, function(err) {
if (err) {
return console.log(err)
}
console.log(`${objectName} download success`)
})
}
const router = new Router();
/*// /home
router.get('/', async (ctx, next) => {
const _content = fs.readFileSync(
path.resolve(__dirname, 'dist/' + 'index.html'),
'binary'
);
ctx.res.writeHead(200)
ctx.res.write(_content, 'binary')
ctx.res.end();
})
*/
router.get('/upload/demo', ctx => {
ctx.body = file;
});
router.post('/upload', licensePic, async (ctx, next) => {
createBucketAndUpload(bucket, ctx.req.file.filename, ctx.req.file.path);
//return res.send({ status: 'ok', file: `static/uploads/${req.file.filename}` });
ctx.body = {
filename: ctx.req.file.filename //返回文件名
}
})
router.get('/file/:name', async(ctx, next) => {
//const filePath = path.join(__dirname, `./public/uploads/${ctx.params.name}`);
let stream = await minioClient.getObject(bucket, ctx.params.name);
ctx.type = 'jpg';
ctx.body = stream;
});
app.use(cors());
app.use(router.routes());
app.use(logger());
app.use(error());
app.use(require('koa-static')(__dirname + '/dist'))
app.use(jwt());
app.use(bodyParser({}));
app.use(mountRoutes().routes());
const { PORT = 8080 } = process.env;
app.listen(PORT, () => {
console.log(`server start at ${PORT}`);
});
process.on('unhandledRejection', (err, promise) => {
console.error('Unhandled rejection (promise: ', promise, ', reason: ', err, ').');
});
\ No newline at end of file
// const {merge} = require('lodash');
// const ERROR = {
// '10401': {
// status: {
// code: 10401,
// message: '密码错误'
// }
// },
// '10404': {
// status: {
// code: 10404,
// message: '没有该用户'
// }
// },
// '10422': {
// status: {
// code: 10422,
// message: '用户已存在'
// }
// },
// '11400': {
// status: {
// code: 11400,
// message: '参数不全'
// }
// },
// '11401': {
// status: {
// code: 11401,
// message: '操作权限不够'
// }
// },
// '11422': {
// status: {
// code: 11422,
// message: '用户名已存在'
// }
// },
// '20404': {
// status: {
// code: 20404,
// message: '没有该文章'
// }
// },
// '20403': {
// status: {
// code: 20403,
// message: '没有修改此文章的权限'
// }
// },
// '30404': {
// status: {
// code: 30404,
// message: '上游帐号不存在'
// }
// },
// '30422': {
// status: {
// code: 30422,
// message: '重复的平台帐号'
// }
// },
// '40404': {
// status: {
// code: 40404,
// message: '找不到该上游副本'
// }
// }
// };
module.exports = () => async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.status = err.status || 400;
ctx.body = {
status: {
code: err.code || 'unknow',
message: err.message || 'unknow'
}
};
}
// try {
// await next();
// } catch (err) {
// if (err.status === 401) {
// ctx.status = 401;
// ctx.body = {
// status: {
// code: 99401,
// message: '认证信息失效, 请重新登录'
// }
// };
// } else {
// if (process.env.NODE_ENV !== 'production' && !ERROR[err.message]) {
// console.error(err.message, '\n', err.stack);
// }
// ctx.status = ctx.status || 500;
// ctx.body = ERROR[err.message] || merge({
// status: {
// code: 99500,
// message: err.message || 'unknow error'
// }
// }, ctx.body);
// }
// }
};
const jwt = require('koa-jwt');
const config = require('config');
module.exports = (opt = {}) => {
return jwt({
secret: config.JWT_SECRET,
audience: opt.audience,
issuer: opt.issuer
}).unless({
path: [
'/',
'/api/token/account',
'/api/token',
'/api/clue/input',
'/api/order/all'
]
});
};
\ No newline at end of file
{
"private": true,
"scripts": {
"start": "umi dev",
"build": "umi build",
"test": "umi test",
"lint": "eslint --ext .js src mock tests"
},
"devDependencies": {
"app-module-path": "^2.2.0",
"axios": "^0.16.2",
"babel-eslint": "^9.0.0",
"bluebird": "^3.5.0",
"busboy": "^0.2.14",
"camelize": "^1.0.0",
"colors": "^1.3.2",
"cron": "^1.2.1",
"elasticsearch": "^12.1.3",
"eslint": "^5.4.0",
"eslint-config-umi": "^0.1.5",
"eslint-plugin-flowtype": "^2.50.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-react": "^7.11.1",
"html-to-text": "^3.3.0",
"husky": "^0.14.3",
"kcors": "2",
"koa": "^2.0.1",
"koa-body": "^4.0.4",
"koa-bodyparser": "^4.2.1",
"koa-compress": "^2.0.0",
"koa-jwt": "koa2",
"koa-logger": "^3.2.0",
"koa-multer": "^1.0.2",
"koa-router": "7.1.1",
"koa-send": "^5.0.0",
"koa-static": "^5.0.0",
"lint-staged": "^7.2.2",
"lodash": "^4.17.4",
"moment": "^2.17.1",
"mongoose": "^5.3.14",
"node-cache": "^4.2.0",
"node-fetch": "^1.6.3",
"node-xlsx": "^0.12.1",
"nodemailer": "^4.7.0",
"promise-retry": "^1.1.1",
"qiniu": "^7.2.1",
"request": "^2.81.0",
"request-promise": "^4.2.0",
"umi": "^2.1.2",
"umi-plugin-react": "^1.1.1",
"uuid": "^3.0.1"
},
"lint-staged": {
"*.{js,jsx}": [
"eslint --fix",
"git add"
]
},
"engines": {
"node": ">=8.0.0"
},
"dependencies": {
"braft-editor": "^2.2.0",
"koa-websocket": "^5.0.1",
"koa-xml-body": "^2.1.0",
"minio": "^7.0.5",
"node-qiniu": "^6.2.0",
"querystring": "^0.2.0",
"xml2js": "^0.4.19"
}
}
const Router = require('koa-router');
const router = new Router();
const $ = require('controllers/calltask');
const Auth = require('controllers/auth');
router.post('/bind', Auth.auth, $.bind);
router.post('/list', Auth.auth, $.list);
module.exports = router;
\ No newline at end of file
const Router = require('koa-router');
const router = new Router();
const $ = require('controllers/clue');
const Auth = require('controllers/auth');
router.post('/list', Auth.auth, $.list);
router.post('/input', $.createAuto);
module.exports = router;
\ No newline at end of file
const Router = require('koa-router');
const router = new Router();
const $ = require('controllers/group');
const Auth = require('controllers/auth');
router.post('/list', Auth.auth, $.list);
router.post('/create', Auth.auth, $.create);
module.exports = router;
\ No newline at end of file
const Router = require('koa-router');
const router = new Router();
const $ = require('controllers/order');
const Auth = require('controllers/auth');
router.post('/list', Auth.auth, $.list);
router.post('/create', Auth.auth, $.create);
router.post('/all', $.all);
module.exports = router;
\ No newline at end of file
const Router = require('koa-router');
const router = new Router();
const $ = require('controllers/auth');
router.post('/', $.session);
router.post('/account', $.account);
module.exports = router;
\ No newline at end of file
const Router = require('koa-router');
const router = new Router();
const $ = require('controllers/url');
router.post('/list', $.list);
module.exports = router;
\ No newline at end of file
const Router = require('koa-router');
const router = new Router();
const $ = require('controllers/user');
const Auth = require('controllers/auth');
router.post('/create', Auth.auth, $.create);
router.post('/list', Auth.auth, $.list);
router.post('/remove', Auth.auth, $.remove)
module.exports = router;
\ No newline at end of file
const request = require('request');
module.exports = async (options) => {
return new Promise((resolve, reject) => {
request(options, function(err, result, body) {
if(err) reject(err)
else resolve(body);
})
})
}
\ No newline at end of file
This diff is collapsed.
module.exports = (leng,num) => {
let s = '';
if(leng <= (num + '').length) return num + '';
for (var i = 0; i < leng - (num + '').length; i++) {
s += '0';
}
return s + (num + '');
}
\ No newline at end of file
const crypto = require('crypto');
module.exports = (str) => {
if (!str) return '';
return crypto.createHash('md5').update(str).digest('hex')
};
const fs = require('fs');
const path = require('path');
const Router = require('koa-router');
const router = new Router();
module.exports = (readPath) => {
const absoluteReadPath = getRoutesPath(readPath);
const routerMap = getRouerMap(absoluteReadPath);
routerMap.forEach(({route, filePath}, idx) => {
const m = require(filePath);
if (m.constructor.name !== 'Router') return;
router.use(route, m.routes());
if (idx === 0) {
log(`\n┏${Array(42).join('━')}${Array(83).join('━')}┓`.black);
} else {
log(`┣${Array(42).join('━')}${Array(83).join('━')}┫`.black);
}
log(
'┃'.black,
`${fixWidth(route)}`.green,
'┃'.black,
` ${fixWidth(filePath, 80)}`.blue,
'┃'.black
);
if (idx !== 0 && idx === routerMap.length - 1) {
log(`┗${Array(42).join('━')}${Array(83).join('━')}┛\n`.black);
}
});
return router;
};
function log (...arg) {
if (process.env.NODE_ENV !== 'production') {
console.log(...arg);
}
}
function getRoutesPath (readPath) {
if (!readPath) {
return path.resolve(
path.dirname(module.parent.filename),
'routes'
);
}
if (path.isAbsolute(readPath)) {
return readPath;
}
return path.resolve(
path.dirname(module.parent.filename),
readPath
);
}
function getRouerMap (r) {
const result = [];
function routerMap (readPath, prefix = '/') {
fs.readdirSync(readPath).forEach(cName => {
const absolutePath = path.resolve(readPath, cName);
const stat = fs.statSync(absolutePath);
if (stat.isDirectory()) {
routerMap(absolutePath, prefix + cName + '/');
}
if (!stat.isFile() || !cName.endsWith('.js')) return;
if (cName !== 'index.js') {
result.push({
route: prefix + cName.replace(/\.js$/, ''),
filePath: absolutePath
});
} else if (readPath !== __dirname) {
result.push({
route: prefix === '/' ? '/' : prefix.replace(/\/$/, ''),
filePath: absolutePath
});
}
});
}
routerMap(r);
return result;
}
function fixWidth (str, width = 40) {
const restNum = width - str.length;
if (restNum < 0) {
return str.substr(0, width - 1);
}
return str + Array(restNum).join(' ');
}
const moment = require('moment');
const fs = require('fs');
module.exports = {
generateDateQuery: (start, end, option) => {
if(/^[0-9]{8}$/.test(start) && /^[0-9]{8}$/.test(end)) {
let data = {};
if(option && option.type === 'string') {
data[option && option.key ? option.key : 'createdAt'] = { '$gte': start, '$lte': end };
} else {
data[option && option.key ? option.key : 'createdAt'] = { '$gte': moment(start,'YYYYMMDD').startOf('day').toDate(), '$lt': moment(end,'YYYYMMDD').endOf('day').toDate() };
}
return data;
}
else return {};
},
generateTokenCode: () => {
return Math.random().toString(36).substr(8);
},
getFixedNumber: (number) => {
return parseFloat(Number(number || 0).toFixed(2));
},
valid: (id) => {
return /^[0-9a-z]{24}$/.test(id);
},
allUndefined: (array) => {
let b = true
for(var k in array) {
b = b && (array[k] === undefined)
}
return b;
},
log: (content,file) => {
let to = file || 'public/log';
let time = moment().format('YYYYMMDD HH:mm:ss') + '~~';
fs.appendFile(to, 'At '+ time + content + '\n',function(){
console.log(content);
});
}
}
\ No newline at end of file
const inspect = require('util').inspect
const path = require('path')
const os = require('os')
const fs = require('fs')
const Busboy = require('busboy')
/**
* 同步创建文件目录
* @param {string} dirname 目录绝对地址
* @return {boolean} 创建目录结果
*/
function mkdirsSync( dirname ) {
if (fs.existsSync( dirname )) {
return true
} else {
if (mkdirsSync( path.dirname(dirname)) ) {
fs.mkdirSync( dirname )
return true
}
}
}
/**
* 获取上传文件的后缀名
* @param {string} fileName 获取上传文件的后缀名
* @return {string} 文件后缀名
*/
function getSuffixName( fileName ) {
let nameList = fileName.split('.')
return nameList[nameList.length - 1]
}
/**
* 上传文件
* @param {object} ctx koa上下文
* @param {object} options 文件上传参数 fileType文件类型, path文件存放路径
* @return {promise}
*/
function uploadFile( ctx, options) {
let req = ctx.req
let res = ctx.res
let busboy = new Busboy({headers: req.headers})
// 获取类型
let fileType = options.fileType || 'common'
let filePath = path.join( options.path, fileType)
let mkdirResult = mkdirsSync( filePath )
return new Promise((resolve, reject) => {
console.log('文件上传中...')
let result = {
success: false,
formData: {},
}
// 解析请求文件事件
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
let fileName = (options.fileName || Math.random().toString(16).substr(2)) + '.' + getSuffixName(filename);
result.fileName = fileName;
let _uploadFilePath = path.join( filePath, fileName )
let saveTo = path.join(_uploadFilePath)
// 文件保存到制定路径
file.pipe(fs.createWriteStream(saveTo))
// 文件写入事件结束
file.on('end', function() {
result.success = true
result.message = '文件上传成功'
console.log('文件上传成功!')
resolve(result)
})
})
// 解析表单中其他字段信息
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('表单字段数据 [' + fieldname + ']: value: ' + inspect(val));
result.formData[fieldname] = inspect(val);
});
// 解析结束事件
busboy.on('finish', function( ) {
console.log('文件上结束')
resolve(result)
})
// 解析错误事件
busboy.on('error', function(err) {
console.log('文件上出错')
reject(result)
})
req.pipe(busboy)
})
}
module.exports = {
uploadFile
}
\ No newline at end of file
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