├── key ├── alipay-public-key.pem ├── apiclient_key.pem ├── apiclient_cert.pem ├── apiclient_cert.p12 ├── alipayCertPublicKey_RSA2.crt ├── alipay-private-key.pem ├── appCertPublicKey_2021001193638066.crt └── alipayRootCert.crt ├── views ├── error.ejs └── index.ejs ├── public ├── export │ └── 用户列表-20201220133328.xlsx └── stylesheets │ └── style.css ├── config ├── index.js ├── prod.js └── dev.js ├── routes ├── upload.js ├── index.js ├── log.js ├── sms.js ├── times.js ├── register.js ├── update.js ├── system.js ├── score.js ├── favorite.js ├── entries.js ├── banners.js ├── administrator.js ├── address.js ├── money.js ├── sign.js ├── statistics.js ├── certifications.js ├── refresh.js ├── help.js ├── user.js ├── messages.js ├── withdraw.js ├── goods.js ├── login.js ├── order.js └── tasks.js ├── schedule └── index.js ├── service ├── message.js └── user.js ├── middlewares ├── times.js ├── upload.js ├── export.js ├── register.js ├── update.js ├── sms.js ├── log.js ├── score.js ├── banners.js ├── address.js ├── favorite.js ├── administrator.js ├── entries.js ├── sign.js ├── money.js ├── certifications.js ├── help.js ├── refresh.js ├── statistics.js ├── messages.js └── system.js ├── package.json ├── README.md ├── bin └── www ├── utils ├── pool.js ├── function.js ├── download.js ├── avatar.js ├── wepay.js └── md5.js └── app.js /key/alipay-public-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /key/apiclient_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /key/apiclient_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 3 | -----END CERTIFICATE----- 4 | -------------------------------------------------------------------------------- /key/apiclient_cert.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xigupro/SharkTask_Server/HEAD/key/apiclient_cert.p12 -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /public/export/用户列表-20201220133328.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xigupro/SharkTask_Server/HEAD/public/export/用户列表-20201220133328.xlsx -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | const dev = require('./dev'); 2 | const prod = require('./prod'); 3 | module.exports = process.env.NODE_ENV === 'development' ? dev : prod; 4 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /routes/upload.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { upload } = require('../middlewares/upload.js'); 4 | 5 | // 获取七牛上传token 6 | router.post('/token', upload.img); 7 | 8 | module.exports = router; -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: '鲨鱼任务' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /routes/log.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { log } = require('../middlewares/log.js'); 4 | 5 | router.post('/list', log.list, function(req, res, next) { 6 | res.json(req.body); 7 | }); 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /routes/sms.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { sms } = require('../middlewares/sms.js'); 4 | 5 | router.post('/send', sms.send, function(req, res, next) { 6 | res.json(req.body); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /routes/times.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { times } = require('../middlewares/times.js'); 4 | 5 | router.post('/list', times.list, function(req, res, next) { 6 | res.json(req.body); 7 | }); 8 | 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 |

<%= title %>

9 |

欢迎来到 <%= title %>

10 | 11 | 12 | -------------------------------------------------------------------------------- /routes/register.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { register } = require('../middlewares/register.js'); 4 | 5 | router.post('/', register.add, function(req, res, next) { 6 | res.json(req.body); 7 | }); 8 | 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /routes/update.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { update } = require('../middlewares/update.js'); 4 | 5 | router.post('/userTasks', update.userTasks, function(req, res, next) { 6 | res.json(req.body); 7 | }); 8 | 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /schedule/index.js: -------------------------------------------------------------------------------- 1 | const schedule = require('node-schedule') 2 | const { UserService } = require('../service/user') 3 | 4 | const scheduleCronstyle = () => { 5 | console.info('定时任务启动') 6 | 7 | schedule.scheduleJob('0 0 4 1 * *', async () => { 8 | console.info('每月1号凌晨4点执行定时任务:', new Date().toLocaleString()) 9 | // 每月1号凌晨4点发放用户等级奖金 10 | await UserService.sendAward() 11 | }) 12 | } 13 | 14 | scheduleCronstyle() 15 | -------------------------------------------------------------------------------- /routes/system.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { system } = require('../middlewares/system.js'); 6 | 7 | // 获取系统配置 8 | router.post('/get', system.get, function(req, res, next) { 9 | res.json(req.body); 10 | }); 11 | 12 | // 更新系统配置 13 | router.post('/update', login.check, system.update, log.add, function(req, res, next) { 14 | res.json(req.body); 15 | }); 16 | 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /service/message.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const MessageService = {}; 9 | exports.MessageService = MessageService; 10 | 11 | // 添加客户端首页动态 12 | MessageService.addDynamic = async function(title) { 13 | const created_at = Date.now(); 14 | const sql = `insert into messages(type,user_id,title,content,business_id,created_at) 15 | values(8,0,'${title}','','','${created_at}')`; 16 | const result = await query(sql, null, null, '新增动态') 17 | console.info('新增动态返回', result) 18 | } -------------------------------------------------------------------------------- /routes/score.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { score } = require('../middlewares/score.js'); 6 | 7 | router.post('/stream', score.stream, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | 11 | router.post('/add', login.check, score.add, log.add, function(req, res, next) { 12 | res.json(req.body); 13 | }); 14 | 15 | router.post('/getLuckyDrawList', login.check, score.getLuckyDrawList, function(req, res, next) { 16 | res.json(req.body); 17 | }); 18 | 19 | 20 | module.exports = router; 21 | -------------------------------------------------------------------------------- /routes/favorite.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { favorite } = require('../middlewares/favorite.js'); 5 | 6 | router.post('/list', login.check, favorite.list, function(req, res, next) { 7 | res.json(req.body); 8 | }); 9 | 10 | router.post('/add', login.check, favorite.add, function(req, res, next) { 11 | res.json(req.body); 12 | }); 13 | 14 | router.post('/remove', login.check, favorite.remove, function(req, res, next) { 15 | res.json(req.body); 16 | }); 17 | 18 | router.post('/isFavorite', login.check, favorite.isFavorite, function(req, res, next) { 19 | res.json(req.body); 20 | }); 21 | 22 | 23 | module.exports = router; 24 | -------------------------------------------------------------------------------- /middlewares/times.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const times = {}; 9 | exports.times = times; 10 | 11 | times.list = function(req, res, next) { 12 | const sql = `SELECT * FROM time_step order by sort desc`; 13 | console.info("查询时间步骤", sql); 14 | query(sql, (err, vals) => { 15 | if (!err && vals instanceof Array) { 16 | req.body.data = vals; 17 | req.body.code = '10000'; 18 | req.body.message = '操作成功'; 19 | req.body.success = true; 20 | return next(); 21 | } else { 22 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 23 | } 24 | }) 25 | } -------------------------------------------------------------------------------- /routes/entries.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { entries } = require('../middlewares/entries.js'); 6 | 7 | router.post('/list', entries.get, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | router.post('/add', login.check, entries.add, log.add, function(req, res, next) { 11 | res.json(req.body); 12 | }); 13 | router.post('/update', login.check, entries.update, log.add, function(req, res, next) { 14 | res.json(req.body); 15 | }); 16 | router.post('/remove', login.check, entries.remove, log.add, function(req, res, next) { 17 | res.json(req.body); 18 | }); 19 | 20 | 21 | module.exports = router; 22 | -------------------------------------------------------------------------------- /routes/banners.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { banners } = require('../middlewares/banners.js'); 6 | 7 | // 获取轮播图 8 | router.post('/', banners.get, function(req, res, next) { 9 | res.json(req.body); 10 | }); 11 | router.post('/add', login.check, banners.add, log.add, function(req, res, next) { 12 | res.json(req.body); 13 | }); 14 | router.post('/update', login.check, banners.update, log.add, function(req, res, next) { 15 | res.json(req.body); 16 | }); 17 | router.post('/remove', login.check, banners.remove, log.add, function(req, res, next) { 18 | res.json(req.body); 19 | }); 20 | 21 | 22 | module.exports = router; 23 | -------------------------------------------------------------------------------- /routes/administrator.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { administrator } = require('../middlewares/administrator.js'); 6 | 7 | router.post('/list', administrator.list, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | router.post('/add', login.check, administrator.add, log.add, function(req, res, next) { 11 | res.json(req.body); 12 | }); 13 | router.post('/update', login.check, administrator.update, log.add, function(req, res, next) { 14 | res.json(req.body); 15 | }); 16 | router.post('/remove', login.check, administrator.remove, log.add, function(req, res, next) { 17 | res.json(req.body); 18 | }); 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /routes/address.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { address } = require('../middlewares/address.js'); 5 | 6 | router.post('/list', login.check, address.list, function(req, res, next) { 7 | res.json(req.body); 8 | }); 9 | 10 | router.post('/detail', login.check, address.detail, function(req, res, next) { 11 | res.json(req.body); 12 | }); 13 | 14 | router.post('/add', login.check, address.add, function(req, res, next) { 15 | res.json(req.body); 16 | }); 17 | 18 | router.post('/update', login.check, address.update, function(req, res, next) { 19 | res.json(req.body); 20 | }); 21 | 22 | router.post('/remove', login.check, address.remove, function(req, res, next) { 23 | res.json(req.body); 24 | }); 25 | 26 | module.exports = router; 27 | -------------------------------------------------------------------------------- /routes/money.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { exportFile } = require('../middlewares/export'); 4 | const { login } = require('../middlewares/login.js'); 5 | const { log } = require('../middlewares/log.js'); 6 | const { money } = require('../middlewares/money.js'); 7 | 8 | router.post('/add', login.check, money.add, log.add, function(req, res, next) { 9 | res.json(req.body); 10 | }); 11 | 12 | router.post('/reduce', login.check, money.reduce, log.add, function(req, res, next) { 13 | res.json(req.body); 14 | }); 15 | 16 | router.post('/stream', login.check, money.stream, function(req, res, next) { 17 | res.json(req.body); 18 | }); 19 | 20 | router.post('/exportAll', login.check, money.exportAll, exportFile.excel, function(req, res, next) { 21 | res.json(req.body); 22 | }); 23 | 24 | 25 | 26 | module.exports = router; 27 | -------------------------------------------------------------------------------- /routes/sign.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { sign } = require('../middlewares/sign.js'); 6 | 7 | router.post('/list', sign.list, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | 11 | router.post('/do', login.check, sign.do, function(req, res, next) { 12 | res.json(req.body); 13 | }); 14 | 15 | router.post('/add', login.check, sign.add, log.add, function(req, res, next) { 16 | res.json(req.body); 17 | }); 18 | 19 | router.post('/update', login.check, sign.update, log.add, function(req, res, next) { 20 | res.json(req.body); 21 | }); 22 | 23 | router.post('/remove', login.check, sign.remove, log.add, function(req, res, next) { 24 | res.json(req.body); 25 | }); 26 | 27 | 28 | module.exports = router; 29 | -------------------------------------------------------------------------------- /middlewares/upload.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const qiniu = require('qiniu'); 8 | const config = require('../config/index'); 9 | const upload = {}; 10 | exports.upload = upload; 11 | 12 | //图片上传 13 | upload.img = function(req, res, next) { 14 | const mac = new qiniu.auth.digest.Mac( 15 | config.qiniu.accessKey, 16 | config.qiniu.secretKey, 17 | ); 18 | const options = { 19 | scope: config.qiniu.bucket, 20 | }; 21 | const putPolicy = new qiniu.rs.PutPolicy(options); 22 | const uploadToken = putPolicy.uploadToken(mac); 23 | if (uploadToken) { 24 | return res.json({ 25 | code: '10000', 26 | message: '操作成功', 27 | success: true, 28 | data: { 29 | uptoken: uploadToken 30 | }, 31 | }); 32 | } else { 33 | return res.json({ 34 | code: '10001', 35 | message: '服务器异常', 36 | success: false, 37 | data: null, 38 | }); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /middlewares/export.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const moment = require('moment'); 8 | const fs = require('fs'); 9 | const nodeExcel = require('excel-export'); 10 | const exportFile = {}; 11 | exports.exportFile = exportFile; 12 | 13 | // 导出Excel文件 14 | exportFile.excel = async function (req, res, next) { 15 | const { exportConfig, prefix } = req.body.excelData; 16 | const result = nodeExcel.execute(exportConfig); 17 | const timestamp = moment().format('YYYYMMDDHHmmss'); 18 | const uploadDir = `/export/${prefix}-${timestamp}.xlsx`; 19 | const filePath = `./public${uploadDir}`; 20 | fs.writeFile(filePath, result, 'binary', function (err) { 21 | if (err) { 22 | return res.json({ code: '10001', message: err, success: false, data: null }); 23 | } 24 | delete req.body.excelData; 25 | req.body.data = uploadDir; 26 | req.body.code = '10000'; 27 | req.body.message = '操作成功'; 28 | req.body.success = true; 29 | return next(); 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /routes/statistics.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { statistics } = require('../middlewares/statistics.js'); 5 | 6 | // 统计当前用户各个状态的任务数量 7 | router.post('/getTaskCount', statistics.getTaskCount, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | 11 | // 统计当前用户指定状态下任务的总金额 12 | router.post('/getMoneyByTaskStatus', statistics.getMoneyByTaskStatus, function(req, res, next) { 13 | res.json(req.body); 14 | }); 15 | 16 | // 统计当前用户金额数据 17 | router.post('/getUserMoneyStatistics', statistics.getUserMoneyStatistics, function(req, res, next) { 18 | res.json(req.body); 19 | }); 20 | 21 | // 用户任务完成排行榜 22 | router.post('/getUserRankList', statistics.getUserRankList, function(req, res, next) { 23 | res.json(req.body); 24 | }); 25 | 26 | // 用户邀请排行榜 27 | router.post('/getInviteRankList', statistics.getInviteRankList, function(req, res, next) { 28 | res.json(req.body); 29 | }); 30 | 31 | // 获取后台仪表盘统计 32 | router.post('/getDashboardData', login.check, statistics.getDashboardData, function(req, res, next) { 33 | res.json(req.body); 34 | }); 35 | 36 | module.exports = router; 37 | -------------------------------------------------------------------------------- /routes/certifications.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { certifications } = require('../middlewares/certifications.js'); 6 | const { messages } = require('../middlewares/messages.js'); 7 | 8 | // 获取认证列表 9 | router.post('/get', login.check, certifications.get, function(req, res, next) { 10 | res.json(req.body); 11 | }); 12 | // 获取认证详情 13 | router.post('/detail', login.check, certifications.detail, function(req, res, next) { 14 | res.json(req.body); 15 | }); 16 | // 用户提交认证资料 17 | router.post('/add', login.check, certifications.add, messages.add, function(req, res, next) { 18 | res.json(req.body); 19 | }); 20 | // 管理员审核认证资料 21 | router.post('/review', login.check, certifications.review, log.add, function(req, res, next) { 22 | res.json(req.body); 23 | }); 24 | // 用户更新认证资料 25 | router.post('/update', login.check, certifications.update, function(req, res, next) { 26 | res.json(req.body); 27 | }); 28 | // 删除用户认证资料 29 | router.post('/remove', login.check, certifications.remove, log.add, function(req, res, next) { 30 | res.json(req.body); 31 | }); 32 | 33 | module.exports = router; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "task-paradise", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "npm run dev", 7 | "watch": "nodemon --watch", 8 | "dev": "node ./bin/www" 9 | }, 10 | "nodemonConfig": { 11 | "ignore": [ 12 | "node_modules/**/node_modules" 13 | ], 14 | "env": { 15 | "NODE_ENV": "development" 16 | } 17 | }, 18 | "dependencies": { 19 | "@alicloud/pop-core": "^1.7.9", 20 | "alipay-sdk": "^3.1.2", 21 | "body-parser": "^1.18.3", 22 | "body-parser-xml": "^1.1.0", 23 | "connect-redis": "^3.4.0", 24 | "cookie-parser": "~1.4.3", 25 | "crypto": "^1.0.1", 26 | "debug": "~2.6.9", 27 | "ejs": "~2.5.7", 28 | "excel-export": "^0.5.1", 29 | "express": "~4.16.0", 30 | "express-session": "^1.15.6", 31 | "express-xml-bodyparser": "^0.3.0", 32 | "http-errors": "~1.6.2", 33 | "moment": "^2.27.0", 34 | "morgan": "~1.9.0", 35 | "mysql": "^2.16.0", 36 | "node-schedule": "^2.0.0", 37 | "qiniu": "^7.2.1", 38 | "qs": "^6.9.4", 39 | "redis": "^2.8.0", 40 | "request": "^2.88.0", 41 | "xml2js": "^0.4.22", 42 | "xmlreader": "^0.2.3" 43 | }, 44 | "devDependencies": { 45 | "nodemon": "^1.18.9" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /routes/refresh.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { refresh } = require('../middlewares/refresh.js'); 6 | 7 | router.post('/list', refresh.list, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | 11 | router.post('/add', login.check, refresh.add, log.add, function(req, res, next) { 12 | res.json(req.body); 13 | }); 14 | 15 | router.post('/update', login.check, refresh.update, log.add, function(req, res, next) { 16 | res.json(req.body); 17 | }); 18 | 19 | router.post('/remove', login.check, refresh.remove, log.add, function(req, res, next) { 20 | res.json(req.body); 21 | }); 22 | 23 | router.post('/buy', login.check, refresh.buy, function(req, res, next) { 24 | res.json(req.body); 25 | }); 26 | 27 | router.post('/do', login.check, refresh.do, function(req, res, next) { 28 | res.json(req.body); 29 | }); 30 | 31 | router.post('/recommend', login.check, refresh.recommend, function(req, res, next) { 32 | res.json(req.body); 33 | }); 34 | 35 | router.post('/top', login.check, refresh.top, function(req, res, next) { 36 | res.json(req.body); 37 | }); 38 | 39 | module.exports = router; 40 | -------------------------------------------------------------------------------- /config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | wechat: { 3 | appId: '', 4 | appSecret: '', 5 | mchId: '', 6 | mchAppId: '', 7 | mchKey: '', 8 | officialAccount: { 9 | appId: '', 10 | appSecret: '', 11 | }, 12 | open: { 13 | appId: '', 14 | appSecret: '', 15 | } 16 | }, 17 | image: 'https://img.xigu.pro', 18 | domain: 'https://shark-api.xigu.pro', 19 | mysql: { 20 | host: '', 21 | port: 3306, 22 | user: '', 23 | database: '', 24 | }, 25 | redis: { 26 | host: '127.0.0.1', 27 | port: 6379, 28 | password: 'xigu.pro', 29 | prefix: 'xigu:', 30 | }, 31 | qiniu: { 32 | accessKey: '', 33 | secretKey: '', 34 | bucket: '', 35 | }, 36 | aliyun: { 37 | accessKey: '', 38 | secretKey: '', 39 | sms: { 40 | signName: "鲨鱼任务", 41 | templateCode: "SMS_189763152", 42 | }, 43 | }, 44 | alipay: { 45 | appId: '2021001146644054', 46 | }, 47 | xianwan: { 48 | '5395': 'lf6ycxkk9p4vajxe', // 安卓 49 | '5526': 'tuhuwh4340rkirsn', // iOS 50 | }, 51 | yuwan: { 52 | appId: '1540', 53 | appSecret: '25jdovqsq0khowsmo5nir0mx9m30gk41', 54 | }, 55 | duoyou: { 56 | 'dy_59634076': '9ef2f1dd1c913d9057eb5b544b4512ef', // 安卓 57 | 'dy_59634077': '4745bef81ca46a035ac0998505f7f6f0', // iOS 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | wechat: { 3 | appId: '', 4 | appSecret: '', 5 | mchId: '', 6 | mchAppId: '', 7 | mchKey: '', 8 | officialAccount: { 9 | appId: '', 10 | appSecret: '', 11 | }, 12 | open: { 13 | appId: '', 14 | appSecret: '', 15 | } 16 | }, 17 | image: 'https://img.xigu.pro', 18 | domain: 'https://shark-api.xigu.pro', 19 | mysql: { 20 | host: 'localhost', 21 | port: 3306, 22 | user: 'root', 23 | password: 'TAMMENY', 24 | database: 'task_paradise', 25 | }, 26 | redis: { 27 | host: '127.0.0.1', 28 | port: 6379, 29 | password: '123456', 30 | prefix: 'xigu:', 31 | }, 32 | qiniu: { 33 | accessKey: '', 34 | secretKey: '', 35 | bucket: '', 36 | }, 37 | aliyun: { 38 | accessKey: '', 39 | secretKey: '', 40 | sms: { 41 | signName: "鲨鱼任务", 42 | templateCode: "SMS_189763152", 43 | }, 44 | }, 45 | alipay: { 46 | appId: '2021001146644054', 47 | }, 48 | xianwan: { 49 | '5395': 'lf6ycxkk9p4vajxe', // 安卓 50 | '5526': 'tuhuwh4340rkirsn', // iOS 51 | }, 52 | yuwan: { 53 | appId: '1540', 54 | appSecret: '25jdovqsq0khowsmo5nir0mx9m30gk41', 55 | }, 56 | duoyou: { 57 | 'dy_59634076': '9ef2f1dd1c913d9057eb5b544b4512ef', // 安卓 58 | 'dy_59634077': '4745bef81ca46a035ac0998505f7f6f0', // iOS 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /key/alipayCertPublicKey_RSA2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDuDCCAqCgAwIBAgIQICAJB6OY+OfBsjVjijqJ/zANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE 3 | BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0 4 | aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs 5 | YXNzIDIgUjEwHhcNMjAwOTA3MDkzNDMyWhcNMjIwOTA3MDkzNDMyWjCBmDELMAkGA1UEBhMCQ04x 6 | MzAxBgNVBAoMKuatpuaxieS6kuWKqOe+juS8oOaWh+WMluS8oOWqkuaciemZkOWFrOWPuDEPMA0G 7 | A1UECwwGQWxpcGF5MUMwQQYDVQQDDDrmlK/ku5jlrp0o5Lit5Zu9Kee9kee7nOaKgOacr+aciemZ 8 | kOWFrOWPuC0yMDg4ODIxMTMyOTYzOTI0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 9 | kxYnV+y/jTKKyN+vPEz1aLINqmeRUeIlfLEsWYP/bGuL3Q9LgFcwmSaR5E5ewr69SCrMvH8smHoT 10 | QN2wl0g1s/KGkQjb9GJarpu/xZ3i10Tn2597PLlBs/MwV9tmR5RRCjxv4SzJaHvKrjuX5nsYETcJ 11 | H5SFcAKhkHjlJWTqtNFmwaMmgg7781UuATA669oOOJEqiNTsTYV40hfabpMpITL6n28Yjq9jpbz5 12 | vTrSo8y/KvrQZn8KBLaP6zwbIYohtoSiFAE5uagJp2pWbyImQUbFrGl7FQXs1o3cYYQ2sHhPovrg 13 | u2cLTSo3kDzgkMYGn+27mMq/45B3cs2/ousHgQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCA/gwDQYJ 14 | KoZIhvcNAQELBQADggEBAASvy08zokviQjsXiBt7qpHQtO5UDPQpqZ+Q798CmZoxPoBIU3Mok448 15 | km+90uXzZQmnowqIraZ9v9tDRg1CDnX2I54Fvv7F+rZAwDgpCckHMmXD6ETMV1lU51mdyAa45oU6 16 | u5OBQhMwO9UxoYb9d9+r3/dP4LbAaDSp/l2+Cqig71/tbR0a5O4dE1qlzE4pvLT2qz9J+WjbnsLR 17 | 5NRcmWje0uN3CmuItSuQxvaKi3hTH3u24m5Hxxr+yD+Yn3L5dbYleMIB6PvH7Znw07zfOYflHuv0 18 | zZLB0vqXKeym8wkj3Pmvds+iWbAc72RUQwn8eInerLDGt75ZRz7OE2b6IKw= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /routes/help.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { help } = require('../middlewares/help.js'); 6 | 7 | router.post('/list', help.list, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | 11 | router.post('/typeList', help.typeList, function(req, res, next) { 12 | res.json(req.body); 13 | }); 14 | 15 | router.post('/detail', login.check, help.detail, log.add, function(req, res, next) { 16 | res.json(req.body); 17 | }); 18 | 19 | router.post('/add', login.check, help.add, log.add, function(req, res, next) { 20 | res.json(req.body); 21 | }); 22 | 23 | router.post('/update', login.check, help.update, log.add, function(req, res, next) { 24 | res.json(req.body); 25 | }); 26 | 27 | router.post('/remove', login.check, help.remove, log.add, function(req, res, next) { 28 | res.json(req.body); 29 | }); 30 | 31 | // 删除分类 32 | router.post('/removeType', login.check, help.removeType, log.add, function(req, res, next) { 33 | res.json(req.body); 34 | }); 35 | 36 | // 添加分类 37 | router.post('/addType', login.check, help.addType, log.add, function(req, res, next) { 38 | res.json(req.body); 39 | }); 40 | 41 | // 更新分类 42 | router.post('/updateType', login.check, help.updateType, log.add, function(req, res, next) { 43 | res.json(req.body); 44 | }); 45 | 46 | 47 | module.exports = router; 48 | -------------------------------------------------------------------------------- /routes/user.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { exportFile } = require('../middlewares/export.js'); 6 | const { user } = require('../middlewares/user.js'); 7 | const { messages } = require('../middlewares/messages.js'); 8 | 9 | // 获取用户信息 10 | router.post('/info', login.check, user.info, function(req, res, next) { 11 | res.json(req.body); 12 | }); 13 | // 根据用户ID获取用户信息 14 | router.post('/getInfoByID', login.check, user.getInfoByID, function(req, res, next) { 15 | res.json(req.body); 16 | }); 17 | // 获取用户列表 18 | router.post('/all', login.check, user.all, function(req, res, next) { 19 | res.json(req.body); 20 | }); 21 | // 用户列表导出Excel 22 | router.post('/exportAll', login.check, user.exportAll, exportFile.excel, function(req, res, next) { 23 | res.json(req.body); 24 | }); 25 | 26 | // 更新用户 27 | router.post('/update', login.check, user.update, log.add, function(req, res, next) { 28 | res.json(req.body); 29 | }); 30 | // 获取用户等级列表 31 | router.post('/getLevelList', user.getLevelList, function(req, res, next) { 32 | res.json(req.body); 33 | }); 34 | // 更新用户等级 35 | router.post('/updateLevel', login.check, user.updateLevel, log.add, function(req, res, next) { 36 | res.json(req.body); 37 | }); 38 | 39 | // 根据手机号重置密码 40 | router.post('/updateUserPassword', user.updateUserPassword, function(req, res, next) { 41 | res.json(req.body); 42 | }); 43 | 44 | module.exports = router; 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 鲨鱼任务悬赏平台 2 | 3 | 注: 此仓库为后端服务,需配合[H5端](https://github.com/xigupro/SharkTask_H5)、[管理端](https://github.com/xigupro/SharkTask_Admin)使用 4 | 5 | [查看演示](https://shark-m.xigu.pro) 6 | [公司官网](https://www.xigu.pro/products/task.html) 7 | 8 | ### 为什么开源 9 | 到目前已有300+的付费客户选择了我们,考虑到有一部分小公司或个人可能前期没有太多的预算投入到平台的开发建设方面来,加上近两年口罩原因大家都非常困难,为了能帮助到这部分客户,所以将此项目开源,希望各位创业者能够飞黄腾达,早日成功。 10 | 11 | ### 介绍 12 | 鲨鱼任务是广州西谷科技自主研发的一款悬赏平台。适合一切想赚钱的人群,如上班族,家庭主妇,自由职业者,创业者等,平台搭建后即可作为你的副业去发展,也可以成为主业去拼搏。 凡是“给钱办事”的业务,如任务悬赏,应用试玩,拉新注册,抖音点赞,购物返利,威客众包,兼职,跑腿,拉票,中介等都适合。 13 | 14 | ### 技术栈 15 | * nodejs v14.16.1 16 | * expressjs 4.16.0 17 | * mysql v5.7 18 | * redis v6.2.6 19 | 20 | ### 配置 21 | 22 | 开发环境配置文件路径`/config/dev.js` 23 | 生产环境配置文件路径`/config/prod.js` 24 | 语义化命名一看就懂,不需要过多解释。 25 | 26 | ### 安装 27 | 1. 安装依赖 `npm i` 28 | 2. 将根目录的sql脚本导入到数据库 29 | 3. 修改配置文件 30 | 4. 启动服务 `npm run watch` 31 | 32 | ### 功能 33 | | 功能 | 开源版 | 商业版(3888元) | 34 | | ---- | ---- | ---- | 35 | | 任务 | ✅ | ✅ | 36 | | 积分城 | ✅ | ✅ | 37 | | 合伙人 | ✅ | ✅ | 38 | | 财务 | ✅ | ✅ | 39 | | 消息 | ✅ | ✅ | 40 | | 超级会员 | ❌ | ✅ | 41 | | 三级分销 | ❌ | ✅ | 42 | | 活动 | ❌ | ✅ | 43 | | 福利 | ❌ | ✅ | 44 | 45 | ### 提供服务 46 | 如果你搞不定,可以找我们提供一条龙服务 47 | * 部署上线,一条龙部署程序到服务器, 直到可以正常使用 48 | * 运维服务,免费BUG修复, 一对一解决问题 49 | * 定制开发,根据你的需求进行二次开发 50 | 51 | ### 联系 or 申请入群 52 | 微信xiguio 53 | 54 | ### 打赏 55 | 如果项目对你有用,请不要吝啬请我喝杯咖啡呗哈哈哈。 56 | 57 | 微信xiguio 58 | 微信xiguio 59 | 60 | ### 版权 61 | 本平台已申请著作权,请勿侵权。 -------------------------------------------------------------------------------- /key/alipay-private-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEAiuyiac9W9tsYU0JlK9WSstskcgGTrpy3UG8A6p5MPneMczcfuL3/v9gjP/yn17mw4eApH3UqDkyZTrcUrN+UHan7YVlLBU+DyfPnmzVSRPs23RtRq8xtqEiANXoKUQa1c1nu7TRAC6dEfqagrdYS5s7ceFGqhuY+lZjkM945/jhB9gYdcxQyF1QoyXQKlT83wwyaJ6wr51rBS4P7/s6kxvvWVX72ynokVh+fe38R8jNAtXFcAIIPCJgNCC/VncYoEg/7qCXOpOZJcMX9ml0ob3PD+EOtMEmQR9YAQpoHSgp3AxCpGx+w2/a128QICA1zcHKkWnEb3mfFBS0VAUqsHQIDAQABAoIBAFDdlVyJ+FERD4PHbiSp2Q6LSRejm1dUmdAUDTCEnFTwOa0HNUvQLQJ6yWoBo6GK0U9psAZDqQtRwxtyrnJCYnEx9MWhuG2K72eqtfI+g3jr0e+6azvZbys5qId4VnD7urs+ajlg5Lbj0pb2XylRJwd6+hJ/VwfXFi72JD+c55z2OYM0bDmNMX4yRubZUD3JCvFf7Cp0/7qeSXBBZ8tiDmlFz43FARcxeEITuWZvr1lmj7N/Eft5uc6Qxgc1WTtmrNs/JuCIza3McXVmq6cVVt3YoG+8iW6+j56eRpHQ+Tpl+3V+WAqzJL76pZ4PiZmg4Ga9rRK92WRbf8MUxCxepnECgYEA6pHuxKHCUg9hXl9O6QHfWxymve9zVkfuy4Fg7qk4SVwAXkSctFq6ldW4cl08BjmiZALyL/VzkFqmVUlIrST0euQwLMBipNT2+zwTQYLDC/UBmT3CzvbiIXu0RXn+3tpXKtfa4brIJAYLzpoSV1vie0z1I9fZLMJ+0fPigS0sXXcCgYEAl53DcKrs0XyAYRNqGLJeiq7A7XatbM3YpXV0oIj6ml5rGk6JvVJWk/sFaw6UEoFBv7hUdIdQYqdS1MNPMqrNDsssUqbpiKFm5S8xzTTGA1UA7bZc8cwnXrXrhqd8MBBcJzyQtkU8eC3itlggf+QsFUQCgmnFZ6U0fACXbvc8mAsCgYEA4pEkI+7uJ57NeH7sVClH2NRaxdhz+eGu6AfGXZ87S7g+bs8s4RNFZ5Yv+t7NLGIc1Sb3UJVvEv5L7NLFDOBF+DFRytfkL7u390C2hK9Nv83dxmseMBPMpXS70eOc5xnT2gD2XNOxnwHsA5lTn+eTYW8a1I0XKqGOJzK/E/BTCs8CgYEAhXvFTNV/aDQHxu/T0eiAKfMPMkHxD8DvQ0T0qD3Q/MWx39hTllX+mYxASe/s15nrLAL6gBl94U1VNLK7cG1F2gdwf1gqdTs8nvx9CSC0UMyu45pRnCRUaSMbOFMOmDZfG8BL2917Doe/eTB/dHmLgjF9UBoVTVn6qk3PBUgwld8CgYEAid7km6akWQDymfRqCcRHFUpXrCsg3Ghnh8eo00U2i2iIlzjj6+EUm5PkrjaBsEhznpQT1b7PzhCqLaQPh8PuEgqZvAqF7YFtuRxpLosPztrETr5Q7+xquyUjc8pbQXLTEyndykRxsO28s1zN9Vthd5T4kbh/m3YUHeGS3vdH7bQ= 3 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /routes/messages.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log'); 5 | const { messages } = require('../middlewares/messages.js'); 6 | 7 | router.post('/getNoticeList', messages.getNoticeList, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | router.post('/list', messages.list, function(req, res, next) { 11 | res.json(req.body); 12 | }); 13 | router.post('/getDynamicList', messages.getDynamicList, function(req, res, next) { 14 | res.json(req.body); 15 | }); 16 | router.post('/unreadCount', login.check, messages.unreadCount, function(req, res, next) { 17 | res.json(req.body); 18 | }); 19 | router.post('/add', login.check, messages.add, function(req, res, next) { 20 | res.json(req.body); 21 | }); 22 | router.post('/addNotice', login.check, messages.addNotice, log.add, function(req, res, next) { 23 | res.json(req.body); 24 | }); 25 | router.post('/updateNotice', login.check, messages.updateNotice, log.add, function(req, res, next) { 26 | res.json(req.body); 27 | }); 28 | router.post('/getNoticeDetail', login.check, messages.getNoticeDetail, function(req, res, next) { 29 | res.json(req.body); 30 | }); 31 | router.post('/detail', login.check, messages.detail, function(req, res, next) { 32 | res.json(req.body); 33 | }); 34 | router.post('/read', login.check, messages.read, function(req, res, next) { 35 | res.json(req.body); 36 | }); 37 | router.post('/remove', login.check, messages.remove, log.add, function(req, res, next) { 38 | res.json(req.body); 39 | }); 40 | 41 | 42 | module.exports = router; 43 | -------------------------------------------------------------------------------- /routes/withdraw.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { exportFile } = require('../middlewares/export.js'); 6 | const { withdraw } = require('../middlewares/withdraw.js'); 7 | const { user } = require('../middlewares/user.js'); 8 | const { messages } = require('../middlewares/messages.js'); 9 | const { order } = require('../middlewares/order.js'); 10 | const wepay = require('../utils/wepay'); 11 | 12 | // 用户提现 13 | router.post('/submit', login.check, user.info, withdraw.submit, function(req, res, next) { 14 | res.json({ 15 | data: req.body.data, 16 | message: '操作成功', 17 | code: '10000', 18 | success: true 19 | }); 20 | }); 21 | // 用户提现列表 22 | router.post('/list', withdraw.list, function(req, res, next) { 23 | res.json(req.body); 24 | }); 25 | // 导出提现列表 26 | router.post('/exportAll', withdraw.exportAll, exportFile.excel, function(req, res, next) { 27 | res.json(req.body); 28 | }); 29 | // 用户提现详情 30 | router.post('/detail', withdraw.detail, function(req, res, next) { 31 | res.json(req.body); 32 | }); 33 | // 用户提现驳回 34 | router.post('/reject', login.check, withdraw.reject, messages.add, log.add, function(req, res, next) { 35 | res.json(req.body); 36 | }); 37 | // 用户提现通过,付款到微信方式 38 | router.post('/resolve', login.check, wepay.wxcompay, withdraw.resolve, messages.add, log.add, function(req, res, next) { 39 | res.json(req.body); 40 | }); 41 | // 用户提现通过,付款到支付宝方式 42 | router.post('/resolveByAlipay', login.check, order.alipayPayToAccount, withdraw.resolve, messages.add, log.add, function(req, res, next) { 43 | res.json(req.body); 44 | }); 45 | module.exports = router; -------------------------------------------------------------------------------- /key/appCertPublicKey_2021001193638066.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEtzCCA5+gAwIBAgIQICAJE/eXc3TlCMayl/tgKTANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE 3 | BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0 4 | aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs 5 | YXNzIDEgUjEwHhcNMjAwOTEzMDk0MzIzWhcNMjIwOTEzMDk0MzIzWjB/MQswCQYDVQQGEwJDTjEz 6 | MDEGA1UECgwq5q2m5rGJ5LqS5Yqo576O5Lyg5paH5YyW5Lyg5aqS5pyJ6ZmQ5YWs5Y+4MQ8wDQYD 7 | VQQLDAZBbGlwYXkxKjAoBgNVBAMMITIwODg4MjExMzI5NjM5MjQtMjAyMTAwMTE5MzYzODA2NjCC 8 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIrsomnPVvbbGFNCZSvVkrLbJHIBk66ct1Bv 9 | AOqeTD53jHM3H7i9/7/YIz/8p9e5sOHgKR91Kg5MmU63FKzflB2p+2FZSwVPg8nz55s1UkT7Nt0b 10 | UavMbahIgDV6ClEGtXNZ7u00QAunRH6moK3WEubO3HhRqobmPpWY5DPeOf44QfYGHXMUMhdUKMl0 11 | CpU/N8MMmiesK+dawUuD+/7OpMb71lV+9sp6JFYfn3t/EfIzQLVxXACCDwiYDQgv1Z3GKBIP+6gl 12 | zqTmSXDF/ZpdKG9zw/hDrTBJkEfWAEKaB0oKdwMQqRsfsNv2tdvECAgNc3BypFpxG95nxQUtFQFK 13 | rB0CAwEAAaOCASkwggElMB8GA1UdIwQYMBaAFHEH4gRhFuTl8mXrMQ/J4PQ8mtWRMB0GA1UdDgQW 14 | BBRSRHKYrd6lMtISAevnizWicHjPVTBABgNVHSAEOTA3MDUGB2CBHAFuAQEwKjAoBggrBgEFBQcC 15 | ARYcaHR0cDovL2NhLmFsaXBheS5jb20vY3BzLnBkZjAOBgNVHQ8BAf8EBAMCBsAwLwYDVR0fBCgw 16 | JjAkoCKgIIYeaHR0cDovL2NhLmFsaXBheS5jb20vY3JsNDUuY3JsMGAGCCsGAQUFBwEBBFQwUjAo 17 | BggrBgEFBQcwAoYcaHR0cDovL2NhLmFsaXBheS5jb20vY2E2LmNlcjAmBggrBgEFBQcwAYYaaHR0 18 | cDovL2NhLmFsaXBheS5jb206ODM0MC8wDQYJKoZIhvcNAQELBQADggEBAFSYoCUn+PqP+Rjy35kw 19 | 3teck98Ay6O3o4J4XMp9LTN2H1QOU9+DSQwjFkJo3k0+0e67ttSssNoRbgC3XgITFuL5epArr5xm 20 | BxgV8pyLz6Ml8R7L0WSbSREUi5A1lwqkI/TVCyctzEoMltYlJXg9ehqQQVH1caMpddJp8GErDPf5 21 | BpnC08uFVvNaxGl52d7s2nEWAskLd2I3o9BM84gZSGDGAqCIalUW/MeGNQY21gcQAITaStbyNCZH 22 | 4xLUXtr94lQzZ+83vwgcpWPEe9v9IZ+51swWONS81EUWIMoQU0WyhsYzERgursbZTXn6G3iDf5Rz 23 | TvLhODUcKy0OQDqmYQ0= 24 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('task-paradise:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /middlewares/register.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const register = {}; 9 | exports.register = register; 10 | 11 | register.add = async function(req, res, next) { 12 | const username = req.body.username; 13 | const password = req.body.password; 14 | const inviter = req.body.inviter || null; 15 | const createdAt = new Date().getTime(); 16 | // 初始用户赠送的账户金额 17 | const baseAmountSql = 'select base_amount from system'; 18 | const baseAmountResult = await query(baseAmountSql); 19 | let baseAmount = 0; 20 | if (!baseAmountResult.fail && baseAmountResult instanceof Array) { 21 | baseAmount = baseAmountResult[0].base_amount || 0; 22 | } 23 | const sql = `insert into users(username, password, created_at, inviter, task_limit, account_amount, refresh_count) 24 | values(?,?,?,?, (select task_limit from growth_levels where level=1), ${baseAmount}, (select refresh_count from system))`; 25 | const sqlValue = [username, password, createdAt, inviter]; 26 | const result = await query(sql, null, sqlValue, '新增用户'); 27 | if (!result.fail && result instanceof Object && result.insertId) { 28 | if (baseAmount) { 29 | query(`insert into money_stream(type,money,balance,user_id,is_income,created_at,remark) 30 | values(3,${baseAmount},${baseAmount},${result.insertId},1,"${createdAt}","新用户红包");`, null, null, '发放新用户红包'); 31 | } 32 | req.body.data = result.insertId; 33 | req.body.userId = inviter; 34 | req.body.taskType = 5; 35 | req.body.code = '10000'; 36 | req.body.message = '操作成功'; 37 | req.body.success = true; 38 | return next(); 39 | } else { 40 | if (result.sqlState === '23000') { 41 | return res.json({ code: '10007', message: '已存在此用户名,请更换', success: false, data: null }); 42 | } 43 | return res.json({ code: '10001', message: result.sqlMessage, success: false, data: null }); 44 | } 45 | } -------------------------------------------------------------------------------- /routes/goods.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { log } = require('../middlewares/log.js'); 4 | const { login } = require('../middlewares/login.js'); 5 | const { goods } = require('../middlewares/goods.js'); 6 | 7 | router.post('/list', goods.list, function(req, res, next) { 8 | res.json(req.body); 9 | }); 10 | 11 | router.post('/orders', login.check, goods.orders, function(req, res, next) { 12 | res.json(req.body); 13 | }); 14 | 15 | router.post('/exchange', login.check, goods.exchange, function(req, res, next) { 16 | res.json(req.body); 17 | }); 18 | 19 | router.post('/orderDetail', login.check, goods.orderDetail, function(req, res, next) { 20 | res.json(req.body); 21 | }); 22 | 23 | router.post('/cancelOrder', login.check, goods.cancelOrder, log.add, function(req, res, next) { 24 | res.json(req.body); 25 | }); 26 | 27 | router.post('/deliver', login.check, goods.deliver, log.add, function(req, res, next) { 28 | res.json(req.body); 29 | }); 30 | 31 | router.post('/detail', goods.detail, function(req, res, next) { 32 | res.json(req.body); 33 | }); 34 | 35 | router.post('/updateStatus', goods.updateStatus, log.add, function(req, res, next) { 36 | res.json(req.body); 37 | }); 38 | 39 | router.post('/add', login.check, goods.add, log.add, function(req, res, next) { 40 | res.json(req.body); 41 | }); 42 | 43 | router.post('/update', login.check, goods.update, log.add, function(req, res, next) { 44 | res.json(req.body); 45 | }); 46 | 47 | router.post('/remove', goods.remove, log.add, function(req, res, next) { 48 | res.json(req.body); 49 | }); 50 | 51 | router.post('/types', goods.types, function(req, res, next) { 52 | res.json(req.body); 53 | }); 54 | 55 | // 删除分类 56 | router.post('/removeType', login.check, goods.removeType, log.add, function(req, res, next) { 57 | res.json(req.body); 58 | }); 59 | 60 | // 添加分类 61 | router.post('/addType', login.check, goods.addType, log.add, function(req, res, next) { 62 | res.json(req.body); 63 | }); 64 | 65 | // 更新分类 66 | router.post('/updateType', login.check, goods.updateType, log.add, function(req, res, next) { 67 | res.json(req.body); 68 | }); 69 | 70 | module.exports = router; 71 | -------------------------------------------------------------------------------- /utils/pool.js: -------------------------------------------------------------------------------- 1 | const mysql = require('mysql'); 2 | const config = require('../config/index'); 3 | 4 | // 创建连接池 5 | const pool = mysql.createPool({ 6 | host : config.mysql.host, 7 | user : config.mysql.user, 8 | password : config.mysql.password, 9 | database : config.mysql.database, 10 | charset : 'utf8mb4', 11 | connectionLimit: 10, 12 | multipleStatements: true 13 | }); 14 | 15 | const query = (sql, callback, data, tips) => { 16 | if (callback) { 17 | pool.getConnection((err, conn) => { 18 | if (err) { 19 | callback && callback(err, null, null) 20 | } else { 21 | conn.query(sql, data, (qerr, vals, fields) => { 22 | // 释放连接 23 | conn.release() 24 | // 回调函数 25 | callback && callback(qerr, vals, fields) 26 | }); 27 | } 28 | }) 29 | } else { 30 | // 使用async await 31 | return new Promise((resolve, reject) => { 32 | pool.getConnection((err, conn) => { 33 | if (err) { 34 | reject(err); 35 | } else { 36 | const query = conn.query(sql, data, (qerr, vals, fields) => { 37 | // 释放连接 38 | conn.release(); 39 | if (qerr) { 40 | qerr.fail = true; 41 | console.warn(tips, '出错', query.sql, qerr); 42 | resolve(qerr); 43 | } else { 44 | console.info(tips, '成功', query.sql); 45 | resolve(vals); 46 | } 47 | }) 48 | } 49 | }) 50 | }); 51 | } 52 | } 53 | 54 | module.exports = query 55 | 56 | // 1、使用连接池示例 57 | 58 | // const query = require(./pool); 59 | // query("SELECT * FROM `user_info`", (err, vals, fields) => { }) 60 | 61 | // ------------------------------------------------------------------------------------ 62 | 63 | // 2、创建多条查询语句 64 | 65 | // 启用多条语句查询 66 | // var connection = mysql.creatConnection({ multipleStatements: true}); 67 | // 新建多条语句实例 68 | // connection.query('sql statementq; sql statement2; sql statement3;', (err, data) => { 69 | // if (err) { 70 | // throw new Error(err); 71 | // } else { 72 | // console.dir(data[0], data[1], data[2]); 73 | // } 74 | // }) 75 | 76 | // ------------------------------------------------------------------------------------ -------------------------------------------------------------------------------- /middlewares/update.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const update = {}; 9 | exports.update = update; 10 | 11 | // 更新user_tasks表中的textStep,reviewStep,reviewField字段,从对应的表拼装数据塞进去 12 | update.userTasks = function(req, res, next) { 13 | const taskSql = `SELECT * FROM user_tasks`; 14 | query(taskSql, (taskErr, taskVals) => { 15 | if (!taskErr && taskVals instanceof Array) { 16 | taskVals.forEach((item) => { 17 | const textStepSql = `select * from task_text_step where task_id=${item.task_id}`; 18 | query(textStepSql, (textStepErr, textStepVals) => { 19 | if (!textStepErr && textStepVals instanceof Array) { 20 | textStepVals.forEach((stepItem) => { 21 | const updateTextStepSql = `update user_tasks set textStep='${JSON.stringify(stepItem)}' where id=${item.id}` 22 | query(updateTextStepSql); 23 | }) 24 | } 25 | }) 26 | 27 | const reviewStepSql = `select * from task_review_step where task_id=${item.task_id}`; 28 | query(reviewStepSql, (reviewStepErr, reviewStepVals) => { 29 | if (!reviewStepErr && reviewStepVals instanceof Array) { 30 | reviewStepVals.forEach((stepItem) => { 31 | const updateReviewStepSql = `update user_tasks set reviewStep='${JSON.stringify(stepItem)}' where id=${item.id}` 32 | query(updateReviewStepSql); 33 | }) 34 | } 35 | }) 36 | 37 | const reviewFieldSql = `select * from task_review_field where task_id=${item.task_id}`; 38 | query(reviewFieldSql, (reviewFieldErr, reviewFieldVals) => { 39 | if (!reviewFieldErr && reviewFieldVals instanceof Array) { 40 | reviewFieldVals.forEach((fieldItem) => { 41 | const updateReviewFieldSql = `update user_tasks set reviewField='${JSON.stringify(fieldItem)}' where id=${item.id}` 42 | query(updateReviewFieldSql); 43 | }) 44 | } 45 | }) 46 | }) 47 | return next(); 48 | } else { 49 | return res.json({ code: '10001', message: taskErr.message, success: false, data: taskErr }); 50 | } 51 | }) 52 | } 53 | -------------------------------------------------------------------------------- /utils/function.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | const qs = require('qs'); 3 | const config = require('../config/index'); 4 | 5 | module.exports = { 6 | /** 7 | * randomWord 产生任意长度随机字母数字组合 8 | * @param randomFlag 是否任意长度 min-任意长度最小位[固定位数] max-任意长度最大位 9 | * @param min 10 | * @param max 11 | * @returns {string} 12 | */ 13 | randomWord: function(randomFlag, min, max) { 14 | var str = "", 15 | range = min, 16 | arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; 17 | // 随机产生 18 | if(randomFlag){ 19 | range = Math.round(Math.random() * (max-min)) + min; 20 | } 21 | for(var i=0; i { 51 | console.log('发送验证码返回', JSON.stringify(res)); 52 | if (res.Code === 'OK') { 53 | req.body.data = true; 54 | req.body.code = '10000'; 55 | req.body.message = '操作成功'; 56 | req.body.success = true; 57 | return next(); 58 | } else { 59 | return res.json({ code: '10012', message: res.Message, success: false, data: null }); 60 | } 61 | }, (ex) => { 62 | console.info('验证码发送失败', ex); 63 | return res.json({ code: '10012', message: '发送失败', success: false, data: ex }); 64 | }) 65 | } 66 | } 67 | 68 | sms.check = function(req, res, next) { 69 | const phone = req.body.phone || req.body.phone; 70 | const code = req.body.code || req.body.code; 71 | global.redisClient.get(phone, function(err, reply) { 72 | if (reply && reply.toString() && reply.toString() === code) { 73 | // 验证码正确 74 | return next(); 75 | } else { 76 | return res.json({ 77 | code: '10013', 78 | message: '验证码不正确', 79 | success: false, 80 | data: false, 81 | }); 82 | } 83 | }); 84 | } -------------------------------------------------------------------------------- /routes/order.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | var xmlparser = require('express-xml-bodyparser'); 3 | const router = express.Router(); 4 | const { login } = require('../middlewares/login.js'); 5 | const { system } = require('../middlewares/system.js'); 6 | const { order } = require('../middlewares/order.js'); 7 | const { user } = require('../middlewares/user.js'); 8 | 9 | router.post('/getDetail', order.getDetail, function(req, res, next) { 10 | res.json(req.body); 11 | }); 12 | 13 | // 充值 14 | router.post('/rechargeMoney', 15 | login.check, 16 | system.get, 17 | order.rechargeMoney, 18 | order.session, 19 | order.add, 20 | function(req, res, next) { 21 | res.json(req.body); 22 | }); 23 | 24 | // 充值支付回调 25 | router.post('/rechargeMoneyNotify', 26 | xmlparser({ trim: false, explicitArray: false }), 27 | order.rechargeMoneyNotify, 28 | function(req, res, next) { 29 | res.json(req.body); 30 | }); 31 | 32 | // APP下单接口 33 | router.post('/appAdd', 34 | login.check, 35 | order.appAdd, 36 | function(req, res, next) { 37 | res.json(req.body); 38 | }); 39 | 40 | // 公众号获取openid 41 | router.post('/publicSession', 42 | login.check, 43 | order.officialSession, 44 | function(req, res, next) { 45 | res.json(req.body); 46 | }); 47 | 48 | // 公众号下单接口 49 | router.post('/publicAdd', 50 | login.check, 51 | order.publicAdd, 52 | function(req, res, next) { 53 | res.json(req.body); 54 | }); 55 | 56 | // 支付宝下单接口 57 | router.post('/alipayAdd', 58 | login.check, 59 | order.alipayAdd, 60 | function(req, res, next) { 61 | res.json(req.body); 62 | }); 63 | 64 | // 支付宝充值支付回调 65 | router.post('/alipayRechargeNotify', 66 | order.alipayRechargeNotify, 67 | function(req, res, next) { 68 | res.json(req.body); 69 | }); 70 | 71 | // 接收闲玩订单 72 | router.get('/xianwan', 73 | order.xianwan, 74 | function(req, res, next) { 75 | res.json(req.body); 76 | }); 77 | 78 | // 接收鱼玩订单 79 | router.post('/yuwan', 80 | order.yuwan, 81 | function(req, res, next) { 82 | res.json(req.body); 83 | }); 84 | 85 | // 接收多游订单 86 | router.get('/duoyou', 87 | order.duoyou, 88 | function(req, res, next) { 89 | res.json(req.body); 90 | }); 91 | 92 | // 发红包订单 93 | router.post('/redAdd', 94 | login.check, 95 | user.info, 96 | order.red, 97 | function(req, res, next) { 98 | res.json(req.body); 99 | }); 100 | 101 | // 获取红包订单详情 102 | router.post('/redDetail', 103 | login.check, 104 | order.redDetail, 105 | function(req, res, next) { 106 | res.json(req.body); 107 | }); 108 | 109 | // 领取红包 110 | router.post('/redReceive', 111 | login.check, 112 | order.redReceive, 113 | function(req, res, next) { 114 | res.json(req.body); 115 | }); 116 | 117 | module.exports = router; 118 | -------------------------------------------------------------------------------- /middlewares/log.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const log = {}; 9 | exports.log = log; 10 | 11 | //后台管理》分页获取操作日志列表 12 | log.list = async function(req, res, next) { 13 | var param = req.body; 14 | //分页实现 15 | var currentPage = 1; //默认为1 16 | var size = 10; //每页条数 17 | if (param.page) { 18 | currentPage = parseInt(param.page); 19 | } 20 | if (param.size) { 21 | size = parseInt(param.size); 22 | } 23 | //设置最后一页页码 24 | var lastPage = currentPage - 1; 25 | //假如目前仅有一页,则最后一页则为1 26 | if (currentPage <= 1) { 27 | lastPage = 1; 28 | } 29 | //如果需要下一页,则开启 30 | //var nextPage = currentPage + 1; 31 | var offset = (currentPage - 1) * size; 32 | const { content, user, createDateRange } = param; 33 | const filters = []; 34 | content && filters.push(`content like "%${content}%"`); 35 | user && filters.push(`user='${user}'`); 36 | createDateRange && createDateRange.length === 2 && filters.push(`created_at >= ${createDateRange[0]} and created_at <= ${createDateRange[1]}`); 37 | const filterString = filters.length ? `where ${filters.join(' and ')}` : ''; 38 | var sql = `SELECT count(*) FROM logs ${filterString}; 39 | select * FROM logs ${filterString} order by created_at desc limit ${size} offset ${offset}`; 40 | console.info('查询操作日志', sql);; 41 | query(sql, (err, vals) => { 42 | if (!err && vals instanceof Array) { 43 | const totalCount = vals[0][0]['count(*)']; 44 | const totalPage = Math.ceil(parseInt(totalCount) / size); 45 | req.body.data = { 46 | list: vals[1], 47 | size: size, 48 | page: currentPage, 49 | totalPage: totalPage, 50 | totalCount: totalCount, 51 | }; 52 | req.body.code = '10000'; 53 | req.body.message = '操作成功'; 54 | req.body.success = true; 55 | return next(); 56 | } else { 57 | return res.json({ 58 | code: '10001', 59 | message: err, 60 | success: false, 61 | data: null, 62 | }); 63 | } 64 | }); 65 | }; 66 | 67 | // 添加操作日志 68 | log.add = async function(req, res, next) { 69 | if (!req.body.log) { 70 | return next(); 71 | } 72 | const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress; 73 | const { user, client, content } = req.body.log; 74 | if (!user || !client || !content) { 75 | return next(); 76 | } 77 | const created_at = new Date().getTime(); 78 | const sql = `insert into logs(user,client,ip,content,created_at) values(?,?,?,?,?)`; 79 | await query(sql, null, [user, client, ip, content, created_at], '添加操作日志'); 80 | // 清空日志 81 | delete req.body.log; 82 | return next(); 83 | } -------------------------------------------------------------------------------- /utils/download.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 下载演员图片 3 | */ 4 | 5 | var fs = require('fs'); 6 | var request = require('request'); 7 | 8 | // 1. 获取图片src 9 | var data = require('../public/data/film_origin_all.json'); 10 | // var url = './public/data/films_all.json'; 11 | 12 | console.log(data.count); 13 | 14 | downloadImage(data) 15 | // 2. 下载图片 16 | function downloadImage(data) { 17 | console.log('收到 ' + data.subjects.length+ ' 条数据'); 18 | var subjects = data.subjects; 19 | 20 | // casts 21 | for (let i = 0; i < subjects.length; i ++) { 22 | for (let x = 0; x < subjects[i].casts.length; x ++) { 23 | var id = subjects[i].casts[x].id; 24 | if (id == null) { 25 | break; 26 | } 27 | var src = subjects[i].casts[x].avatars.small; 28 | console.log('casts'); 29 | console.log(i, x); 30 | console.log(src); 31 | // return; 32 | let tail = null; 33 | if ( src.indexOf('.webp') > -1 ) { 34 | tail = '.webp' 35 | } else if ( src.indexOf('.jpg') > -1 ) { 36 | tail = '.jpg' 37 | } else if ( src.indexOf('.jpeg') > -1 ) { 38 | tail = '.jpeg' 39 | } else { 40 | tail = '.png' 41 | } 42 | var writeStream = fs.createWriteStream('./public/images/test/'+ subjects[i].casts[x].id + tail); 43 | var readStream = request(src); 44 | readStream.pipe(writeStream); 45 | 46 | readStream.on('end', function() { 47 | console.log(i + ' 文件下载成功'); 48 | }); 49 | readStream.on('error', function() { 50 | console.log("错误信息:" + err) 51 | }) 52 | writeStream.on("finish", function() { 53 | console.log(i + " 文件写入成功"); 54 | // writeStream.end(); 55 | }) 56 | } 57 | } 58 | 59 | // directors 60 | for (let i = 0; i < subjects.length; i ++) { 61 | for (let x = 0; x < subjects[i].directors.length; x ++) { 62 | var id = subjects[i].directors[x].id; 63 | if (id == null) { 64 | break; 65 | } 66 | var src = subjects[i].directors[x].avatars.small; 67 | console.log('directors'); 68 | console.log(i, x); 69 | console.log(src); 70 | // return; 71 | let tail = null; 72 | if ( src.indexOf('.webp') > -1 ) { 73 | tail = '.webp' 74 | } else if ( src.indexOf('.jpg') > -1 ) { 75 | tail = '.jpg' 76 | } else if ( src.indexOf('.jpeg') > -1 ) { 77 | tail = '.jpeg' 78 | } else { 79 | tail = '.png' 80 | } 81 | var writeStream = fs.createWriteStream('./public/images/test/'+ subjects[i].directors[x].id + tail); 82 | var readStream = request(src); 83 | readStream.pipe(writeStream); 84 | 85 | readStream.on('end', function() { 86 | console.log(i + ' 文件下载成功'); 87 | }); 88 | readStream.on('error', function() { 89 | console.log("错误信息:" + err) 90 | }) 91 | writeStream.on("finish", function() { 92 | console.log(i + " 文件写入成功"); 93 | // writeStream.end(); 94 | }) 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /middlewares/score.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const score = {}; 9 | exports.score = score; 10 | 11 | // 给用户加减积分 12 | score.add = function(req, res, next) { 13 | const user_id = req.body.user_id; 14 | const score = req.body.score || 0; 15 | // 积分获得来源。1签到;2发任务;3完成任务;4实名认证;5加入会员;6充值;7平台赠送/扣除;8转盘 16 | const type = req.body.type; 17 | const remark = req.body.remark || ''; 18 | const created_at = new Date().getTime(); 19 | const is_income = score > 0; 20 | const sql = `begin; 21 | update users set score=score+${score} where id=${user_id}; 22 | insert into score_stream(type,score,balance,user_id,is_income,created_at,remark) 23 | values(${type},${Math.abs(score)},(select score from users where id=${user_id}),${user_id},${is_income},'${created_at}','${remark}'); 24 | commit;` 25 | console.info("加积分", sql); 26 | query(sql, (err, vals) => { 27 | console.info('加积分返回', vals) 28 | if (!err && vals instanceof Array) { 29 | req.body.data = true; 30 | req.body.code = '10000'; 31 | req.body.message = '操作成功'; 32 | req.body.success = true; 33 | // 记录操作日志 34 | req.body.log = Object.assign(req.body.log || {}, { 35 | client: 1, 36 | content: `给ID为${user_id}的用户${is_income ? '发放' : '扣除'}了${score}积分`, 37 | }); 38 | return next(); 39 | } else { 40 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 41 | } 42 | }) 43 | } 44 | 45 | // 获取用户积分流水 46 | score.stream = function(req, res, next) { 47 | var param = req.body; 48 | //分页实现 49 | var currentPage = 1; //默认为1 50 | var size = 10; //每页条数 51 | if (param.page) { 52 | currentPage = parseInt(param.page); 53 | } 54 | if (param.size) { 55 | size = parseInt(param.size); 56 | } 57 | //设置最后一页页码 58 | var lastPage = currentPage - 1; 59 | //假如目前仅有一页,则最后一页则为1 60 | if (currentPage <= 1) { 61 | lastPage = 1; 62 | } 63 | //如果需要下一页,则开启 64 | //var nextPage = currentPage + 1; 65 | var offset = (currentPage - 1) * size; 66 | 67 | const type = param.type; 68 | const userId = param.userId; 69 | const isSearch = type || userId; 70 | let filters = []; 71 | type && filters.push(`type=${type}`); 72 | userId && filters.push(`user_id=${userId}`); 73 | filters = isSearch ? filters.join(' and ') : ''; 74 | 75 | var sql = `SELECT COUNT(*) FROM score_stream where ${filters}; 76 | select * FROM score_stream where ${filters} 77 | order by created_at desc limit ${size} offset ${offset}`; 78 | 79 | console.info('查询用户积分流水', sql);; 80 | query(sql, (err, vals) => { 81 | if (!err && vals instanceof Array) { 82 | const totalCount = vals[0][0]['COUNT(*)']; 83 | const totalPage = Math.ceil(parseInt(totalCount) / size); 84 | req.body.data = { 85 | list: vals[1], 86 | size: size, 87 | page: currentPage, 88 | totalPage: totalPage, 89 | totalCount: totalCount, 90 | }; 91 | req.body.code = '10000'; 92 | req.body.message = '操作成功'; 93 | req.body.success = true; 94 | return next(); 95 | } else { 96 | return res.json({ 97 | code: '10001', 98 | message: err.message, 99 | success: false, 100 | data: err, 101 | }); 102 | } 103 | }); 104 | } 105 | 106 | // 获取转盘列表 107 | score.getLuckyDrawList = async function(req, res, next) { 108 | const sql = `SELECT * FROM lucky_draw order by sort desc`; 109 | const result = await query(sql, null, null, '查询转盘列表'); 110 | if (!result.fail && result instanceof Array) { 111 | req.body.data = result; 112 | req.body.code = '10000'; 113 | req.body.message = '操作成功'; 114 | req.body.success = true; 115 | return next(); 116 | } else { 117 | return res.json({ code: '10001', message: '', success: false, data: 'err' }); 118 | } 119 | } -------------------------------------------------------------------------------- /utils/avatar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 下载演员图片 3 | */ 4 | 5 | var fs = require('fs'); 6 | var request = require('request'); 7 | 8 | // 1. 获取图片src 9 | var data = require('../public/data/200_films_top250.json'); 10 | var url = './public/data/200_films_top250.json'; 11 | 12 | console.log(data.count); 13 | 14 | fs.readFile(url, 'utf-8', function (err, data) { 15 | if (err) { 16 | console.error(err); 17 | } 18 | 19 | data = JSON.parse(data); 20 | console.log(typeof data); 21 | 22 | for (let i = 0; i < data.subjects.length; i ++) { 23 | 24 | delete data.subjects[i].rating; 25 | delete data.subjects[i].genres; 26 | delete data.subjects[i].title; 27 | delete data.subjects[i].collect_count; 28 | delete data.subjects[i].original_title; 29 | delete data.subjects[i].subtype; 30 | delete data.subjects[i].year; 31 | delete data.subjects[i].id; 32 | delete data.subjects[i].cover; 33 | 34 | // casts 35 | for (let m = 0; m < data.subjects[i].casts.length; m ++) { 36 | let id = data.subjects[i].casts[m].id; 37 | 38 | if (id === null) { 39 | data.subjects[i].casts[m].id = ''; 40 | data.subjects[i].casts[m].avatar = ""; 41 | } 42 | } 43 | 44 | // directors 45 | for (let n = 0; n < data.subjects[i].directors.length; n ++) { 46 | let id = data.subjects[i].directors[n].id; 47 | 48 | if (id === null) { 49 | data.subjects[i].directors[n].id = ''; 50 | data.subjects[i].directors[n].avatar = ""; 51 | } else { 52 | let src = data.subjects[i].directors[n].small; 53 | 54 | if (src == null) { 55 | data.subjects[i].directors[n].avatar = '' 56 | } else { 57 | data.subjects[i].directors[n].avatar = src; 58 | } 59 | } 60 | } 61 | } 62 | 63 | // 2. 下载图片 64 | downloadImage(data); 65 | 66 | data = JSON.stringify(data); 67 | fs.writeFile('./public/data/avatar/200_249.json', data, 'utf-8', err => { 68 | if (err) { 69 | console.error(err); 70 | } 71 | 72 | console.log('write success'); 73 | }) 74 | }) 75 | 76 | // 2. 下载图片 77 | function downloadImage(data, start) { 78 | console.log('收到 ' + data.subjects.length+ ' 条数据'); 79 | start = 1*start; 80 | var subjects = data.subjects; 81 | 82 | // casts 83 | for (let i = 0; i < subjects.length; i ++) { 84 | for (let x = 0; x < subjects[i].casts.length; x ++) { 85 | var src = subjects[i].casts[x].avatar; 86 | if (src == '') { 87 | break; 88 | } 89 | console.log(i, x); 90 | console.log(src); 91 | // return; 92 | var writeStream = fs.createWriteStream('./public/images/avatars/'+ subjects[i].casts[x].id + '.jpg'); 93 | var readStream = request(src); 94 | readStream.pipe(writeStream); 95 | 96 | readStream.on('end', function() { 97 | console.log(i + ' 文件下载成功'); 98 | }); 99 | readStream.on('error', function() { 100 | console.log("错误信息:" + err) 101 | }) 102 | writeStream.on("finish", function() { 103 | console.log(i + " 文件写入成功"); 104 | // writeStream.end(); 105 | }) 106 | } 107 | } 108 | 109 | // directors 110 | for (let i = 0; i < subjects.length; i ++) { 111 | for (let x = 0; x < subjects[i].directors.length; x ++) { 112 | var src = subjects[i].directors[x].avatar; 113 | if (src == '') { 114 | break; 115 | } 116 | console.log(i, x); 117 | console.log(src); 118 | // return; 119 | var writeStream = fs.createWriteStream('./public/images/avatars/'+ subjects[i].directors[x].id + '.jpg'); 120 | var readStream = request(src); 121 | readStream.pipe(writeStream); 122 | 123 | readStream.on('end', function() { 124 | console.log(i + ' 文件下载成功'); 125 | }); 126 | readStream.on('error', function() { 127 | console.log("错误信息:" + err) 128 | }) 129 | writeStream.on("finish", function() { 130 | console.log(i + " 文件写入成功"); 131 | // writeStream.end(); 132 | }) 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /middlewares/banners.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const banners = {}; 9 | exports.banners = banners; 10 | 11 | //获取轮播图 12 | banners.get = async function(req, res, next) { 13 | const client = req.body.client || ''; 14 | const type = req.body.type || ''; 15 | const values = []; 16 | const filters = ['deleted=0']; 17 | client && filters.push(`client like "%?%"`) && values.push(+client); 18 | type && filters.push(`type=?`) && values.push(type); 19 | const filterString = filters.length ? `where ${filters.join(' and ')}` : ''; 20 | const sql = `SELECT * FROM banners ${filterString} order by sort desc`; 21 | const result = await query(sql, null, values, '查询图片轮播'); 22 | if (!result.fail && result instanceof Array) { 23 | req.body.data = result; 24 | req.body.code = '10000'; 25 | req.body.message = '操作成功'; 26 | req.body.success = true; 27 | return next(); 28 | } else { 29 | return res.json({ code: '10001', message: '', success: false, data: 'err' }); 30 | } 31 | } 32 | banners.add = function(req, res, next) { 33 | const image = req.body.image; 34 | const title = req.body.title; 35 | const type = req.body.type || 1; 36 | const url = req.body.url; 37 | const mpUrl = req.body.mpUrl; 38 | let client = req.body.client; 39 | client = client instanceof Array ? client.join(',') : client; 40 | const createdAt = new Date().getTime(); 41 | const createdBy = req.body.createdBy; 42 | const sql = `insert into banners(type,client,image,title,url,mp_url,created_at,created_by) 43 | values(${type},'${client}',"${image}","${title}","${url}","${mpUrl}","${createdAt}","${createdBy}")`; 44 | console.info("新增轮播图", sql); 45 | query(sql, (err, vals) => { 46 | if (!err && vals instanceof Object) { 47 | req.body.data = vals.insertId; 48 | req.body.code = '10000'; 49 | req.body.message = '操作成功'; 50 | req.body.success = true; 51 | // 记录操作日志 52 | req.body.log = Object.assign(req.body.log || {}, { 53 | client: 1, 54 | content: `添加了ID为${vals.insertId}的图片轮播`, 55 | }); 56 | return next(); 57 | } else { 58 | return res.json({ code: '10001', message: err, success: false, data: null }); 59 | } 60 | }) 61 | } 62 | banners.update = function(req, res, next) { 63 | const id = req.body.id; 64 | const image = req.body.image; 65 | const title = req.body.title; 66 | const type = req.body.type || 1; 67 | const url = req.body.url; 68 | const mpUrl = req.body.mpUrl; 69 | let client = req.body.client; 70 | client = client instanceof Array ? client.join(',') : client; 71 | const updated_at = new Date().getTime(); 72 | const sql = `update banners set 73 | client='${client}', 74 | type=${type}, 75 | image="${image}", 76 | title="${title}", 77 | url="${url}", 78 | mp_url="${mpUrl}", 79 | updated_at="${updated_at}" 80 | where id=${id};`; 81 | console.info("更新轮播", sql); 82 | query(sql, (err, vals) => { 83 | if (!err && vals instanceof Object) { 84 | req.body.data = true; 85 | req.body.code = '10000'; 86 | req.body.message = '操作成功'; 87 | req.body.success = true; 88 | // 记录操作日志 89 | req.body.log = Object.assign(req.body.log || {}, { 90 | client: 1, 91 | content: `更新了ID为${id}的图片轮播`, 92 | }); 93 | return next(); 94 | } else { 95 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 96 | } 97 | }) 98 | } 99 | banners.remove = function(req, res, next) { 100 | const id = req.body.id || req.body.id; 101 | const updatedAt = new Date().getTime(); 102 | const sql = `update banners set deleted=1,updated_at=${updatedAt} where id=${id}`; 103 | console.info("删除轮播图", sql); 104 | query(sql, (err, vals) => { 105 | if (!err && vals instanceof Object) { 106 | req.body.data = true; 107 | req.body.code = '10000'; 108 | req.body.message = '操作成功'; 109 | req.body.success = true; 110 | // 记录操作日志 111 | req.body.log = Object.assign(req.body.log || {}, { 112 | client: 1, 113 | content: `删除了ID为${id}的图片轮播`, 114 | }); 115 | return next(); 116 | } else { 117 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 118 | } 119 | }) 120 | } -------------------------------------------------------------------------------- /service/user.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const { MessageService } = require('./message'); 9 | const UserService = {}; 10 | exports.UserService = UserService; 11 | 12 | /** 13 | * 查询用户信息 14 | * @param {Number} userId 用户ID 15 | * @returns Object 16 | */ 17 | UserService.getUserInfo = async function(userId) { 18 | const userSql = `select * from users where id=${userId}`; 19 | const userResult = await query(userSql, null, null, '查询用户信息'); 20 | console.info('用户信息', userResult) 21 | if (!userResult.fail && userResult instanceof Array) { 22 | return userResult[0] || {} 23 | } 24 | return {} 25 | } 26 | 27 | /** 28 | * 查询等级信息 29 | * @param {Number} level 用户等级 30 | * @returns 31 | */ 32 | UserService.getLevelInfo = async function(level) { 33 | const levelSql = `select * from growth_levels where level=${level}`; 34 | const levelResult = await query(levelSql, null, null, '查询等级信息'); 35 | console.info('等级信息', levelResult) 36 | if (!levelResult.fail && levelResult instanceof Array) { 37 | return levelResult[0] || {} 38 | } 39 | return {} 40 | } 41 | 42 | /** 43 | * 给指定用户升级 44 | * @param {Number} userId 用户ID 45 | * @returns 46 | */ 47 | UserService.growthLevel = async function(userId) { 48 | // 查询用户信息 49 | const userInfo = await UserService.getUserInfo(userId) 50 | // 下一等级信息 51 | const nextLevelInfo = await UserService.getLevelInfo(userInfo.level + 1) 52 | 53 | const taskSql = `SELECT count(*) as task_count FROM user_tasks where user_id=${userId} and status=3`; 54 | const taskResult = await query(taskSql, null, null, '查询用户已完成任务数'); 55 | console.info('用户已完成任务数', taskResult) 56 | let taskCount = 0 57 | if (!taskResult.fail && taskResult instanceof Array && taskResult[0]) { 58 | taskCount = taskResult[0].task_count 59 | } 60 | 61 | const inviteSql = `SELECT count(*) as invite_count FROM users where inviter=${userId}`; 62 | const inviteResult = await query(inviteSql, null, null, '查询用户直属下级数'); 63 | console.info('用户已完成任务数', inviteResult) 64 | let inviteCount = 0 65 | if (!inviteResult.fail && inviteResult instanceof Array && inviteResult[0]) { 66 | inviteCount = inviteResult[0].invite_count 67 | } 68 | 69 | // 当直属下级数量和已完成任务数满足升级 70 | if (nextLevelInfo 71 | && nextLevelInfo.task_count 72 | && taskCount >= nextLevelInfo.task_count 73 | && nextLevelInfo.invite_count 74 | && inviteCount >= nextLevelInfo.invite_count ) { 75 | const growthSql = `update users set level=level+1 where id=${userId}` 76 | const growthResult = await query(growthSql, null, null, '用户升级') 77 | console.info('用户升级返回', growthResult) 78 | if (!growthResult.fail && growthResult instanceof Object && growthResult.affectedRows) { 79 | // 添加动态 80 | 81 | const { phone, nick_name, username } = userInfo 82 | await MessageService.addDynamic(`恭喜用户${phone || nick_name || username}成功晋级到${nextLevelInfo.name}`) 83 | } 84 | } 85 | } 86 | 87 | /** 88 | * 给用户按等级发放奖金 89 | */ 90 | UserService.sendAward = async function() { 91 | const sql = `select u.id,u.account_amount,u.level,g.money_monthly from users u left join growth_levels g on u.level=g.level where u.deleted=0 and u.status=1 and g.money_monthly > 0` 92 | const userResult = await query(sql, null, null, '查询用户等级每月奖励') 93 | if (!userResult.fail && userResult instanceof Array) { 94 | userResult.forEach(async (item) => { 95 | await UserService.addMoney(item.id, item.money_monthly, 3, '发放用户等级奖金') 96 | }) 97 | } 98 | } 99 | 100 | /** 101 | * 给用户加钱 102 | * @param {Number} userId 用户ID 103 | * @param {Number} money 加的金额 104 | * @param {Number} type 类型,1充值;2提现;3收入;4支出 105 | * @param {String} remark 备注 106 | * @returns Boolean 107 | */ 108 | UserService.addMoney = async function(userId, money, type, remark) { 109 | money = +money 110 | if (money < 0 || !userId) { 111 | return false 112 | } 113 | const sql = `begin; 114 | update users set account_amount=account_amount+${money} where id=${userId}; 115 | insert into money_stream(type,money,balance,user_id,is_income,created_at,remark) 116 | values(${type},${money},(select account_amount from users where id=${userId}),${userId},1,'${Date.now()}','${remark}'); 117 | commit;` 118 | console.info("加钱", sql); 119 | const addResult = await query(sql, null, null, `给用户${userId}加${money}元,备注:${remark}`) 120 | return !addResult.fail 121 | } -------------------------------------------------------------------------------- /middlewares/address.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const address = {}; 9 | exports.address = address; 10 | 11 | //获取收货地址列表 12 | address.list = async function(req, res, next) { 13 | const values = [req.body.userId]; 14 | const filters = ['deleted=0', `user_id=?`]; 15 | const filterString = filters.length ? `where ${filters.join(' and ')}` : ''; 16 | const sql = `SELECT * FROM address ${filterString} order by is_default desc`; 17 | const result = await query(sql, null, values, '查询收货地址'); 18 | if (!result.fail && result instanceof Array) { 19 | req.body.data = result; 20 | req.body.code = '10000'; 21 | req.body.message = '操作成功'; 22 | req.body.success = true; 23 | return next(); 24 | } else { 25 | return res.json({ code: '10001', message: '', success: false, data: 'err' }); 26 | } 27 | } 28 | 29 | address.detail = async function(req, res, next) { 30 | const id = req.body.id; 31 | const sql = `select * from address where deleted=0 and id=${id}`; 32 | const result = await query(sql, null, null, '获取收货地址详情'); 33 | if (!result.fail && result instanceof Array) { 34 | req.body.data = result[0]; 35 | req.body.code = '10000'; 36 | req.body.message = '操作成功'; 37 | req.body.success = true; 38 | return next(); 39 | } else { 40 | return res.json({ code: '10001', message: result.message, success: false, data: result }); 41 | } 42 | } 43 | 44 | address.add = async function(req, res, next) { 45 | const userId = req.body.userId; 46 | const province = req.body.province; 47 | const city = req.body.city; 48 | const area = req.body.county; 49 | const area_code = req.body.area_code; 50 | const postal_code = req.body.postal_code; 51 | const address = req.body.addressDetail; 52 | const name = req.body.name; 53 | const tel = req.body.tel; 54 | const is_default = req.body.is_default === 'true' ? 1 : 0; 55 | const createdAt = new Date().getTime(); 56 | const values = [userId, name, tel, province, city, area, area_code, postal_code, address, is_default, createdAt]; 57 | const sql = `insert into address(user_id,name,tel,province,city,area,area_code,postal_code,address,is_default,created_at) values(?,?,?,?,?,?,?,?,?,?,?)`; 58 | const result = await query(sql, null, values, '新增收货地址'); 59 | if (!result.fail && result instanceof Object) { 60 | req.body.data = result.insertId; 61 | req.body.code = '10000'; 62 | req.body.message = '操作成功'; 63 | req.body.success = true; 64 | return next(); 65 | } else { 66 | return res.json({ code: '10001', message: result.message, success: false, data: null }); 67 | } 68 | } 69 | 70 | address.update = async function(req, res, next) { 71 | const id = req.body.id; 72 | const province = req.body.province; 73 | const city = req.body.city; 74 | const area = req.body.county; 75 | const area_code = req.body.area_code; 76 | const postal_code = req.body.postal_code; 77 | const address = req.body.addressDetail; 78 | const name = req.body.name; 79 | const tel = req.body.tel; 80 | const is_default = req.body.is_default === 'true' ? 1 : 0; 81 | const updated_at = new Date().getTime(); 82 | const values = [name, tel, province, city, area, area_code, postal_code, address, is_default, updated_at, id]; 83 | const sql = `update address set name=?,tel=?,province=?,city=?,area=?,area_code=?,postal_code=?,address=?,is_default=?,updated_at=? where id=?;`; 84 | const result = await query(sql, null, values, '更新收货地址'); 85 | if (!result.fail && result instanceof Object) { 86 | req.body.data = true; 87 | req.body.code = '10000'; 88 | req.body.message = '操作成功'; 89 | req.body.success = true; 90 | return next(); 91 | } else { 92 | return res.json({ code: '10001', message: result.message, success: false, data: result }); 93 | } 94 | } 95 | 96 | address.remove = async function(req, res, next) { 97 | const id = req.body.id; 98 | const updatedAt = new Date().getTime(); 99 | const values = [updatedAt, id] 100 | const sql = `update address set deleted=1,updated_at=? where id=?`; 101 | const result = await query(sql, null, values, '删除收货地址'); 102 | if (!result.fail && result instanceof Object) { 103 | req.body.data = true; 104 | req.body.code = '10000'; 105 | req.body.message = '操作成功'; 106 | req.body.success = true; 107 | return next(); 108 | } else { 109 | return res.json({ code: '10001', message: result.message, success: false, data: result }); 110 | } 111 | } -------------------------------------------------------------------------------- /middlewares/favorite.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const favorite = {}; 9 | exports.favorite = favorite; 10 | 11 | // 收藏列表 12 | favorite.list = function(req, res, next) { 13 | var param = req.body; 14 | //分页实现 15 | var currentPage = 1; //默认为1 16 | var size = 10; //每页条数 17 | if (param.page) { 18 | currentPage = parseInt(param.page); 19 | } 20 | if (param.size) { 21 | size = parseInt(param.size); 22 | } 23 | //设置最后一页页码 24 | var lastPage = currentPage - 1; 25 | //假如目前仅有一页,则最后一页则为1 26 | if (currentPage <= 1) { 27 | lastPage = 1; 28 | } 29 | //如果需要下一页,则开启 30 | //var nextPage = currentPage + 1; 31 | var offset = (currentPage - 1) * size; 32 | // 类型 33 | var type = req.body.type || 1; 34 | // 类型 35 | var user_id = req.body.user_id; 36 | 37 | var sql = `SELECT COUNT(*) FROM favorite where type=${type} and user_id=${user_id}; 38 | select tasks.id,tasks.money,tasks.title,tasks.thumbnail,favorite.created_at 39 | FROM favorite left join tasks on favorite.task_id=tasks.id 40 | where favorite.type=${type} and favorite.user_id=${user_id} 41 | order by favorite.created_at desc limit ${size} offset ${offset}`; 42 | 43 | console.info('查询收藏', sql); 44 | query(sql, (err, vals) => { 45 | if (!err && vals instanceof Array) { 46 | const totalCount = vals[0][0]['COUNT(*)']; 47 | const totalPage = Math.ceil(parseInt(totalCount) / size); 48 | req.body.data = { 49 | list: vals[1], 50 | size: size, 51 | page: currentPage, 52 | totalPage: totalPage, 53 | totalCount: totalCount, 54 | }; 55 | req.body.code = '10000'; 56 | req.body.message = '操作成功'; 57 | req.body.success = true; 58 | return next(); 59 | } else { 60 | return res.json({ 61 | code: '10001', 62 | message: err, 63 | success: false, 64 | data: null, 65 | }); 66 | } 67 | }); 68 | }; 69 | 70 | // 添加收藏 71 | favorite.add = function(req, res, next) { 72 | const type = req.body.type; 73 | const user_id = req.body.user_id; 74 | const task_id = req.body.task_id; 75 | const created_at = new Date().getTime(); 76 | const sql = `insert into favorite(user_id,task_id,type,created_at) 77 | values(${user_id}, 78 | ${task_id}, 79 | ${type}, 80 | '${created_at}')`; 81 | console.info('添加收藏', sql); 82 | query(sql, (err, vals) => { 83 | if (!err && vals instanceof Object) { 84 | req.body.data = vals.insertId; 85 | req.body.code = '10000'; 86 | req.body.message = '操作成功'; 87 | req.body.success = true; 88 | return next(); 89 | } else { 90 | return res.json({ 91 | code: '10001', 92 | message: err, 93 | success: false, 94 | data: null, 95 | }); 96 | } 97 | }); 98 | }; 99 | 100 | 101 | // 添加收藏 102 | favorite.isFavorite = function(req, res, next) { 103 | const type = req.body.type; 104 | const user_id = req.body.user_id; 105 | const task_id = req.body.task_id; 106 | const sql = `select * from favorite where type=${type} and user_id=${user_id} and task_id=${task_id}`; 107 | console.info('是否已收藏', sql); 108 | query(sql, (err, vals) => { 109 | if (!err && vals instanceof Object) { 110 | req.body.data = !!vals.length; 111 | req.body.code = '10000'; 112 | req.body.message = '操作成功'; 113 | req.body.success = true; 114 | return next(); 115 | } else { 116 | return res.json({ 117 | code: '10001', 118 | message: err, 119 | success: false, 120 | data: null, 121 | }); 122 | } 123 | }); 124 | }; 125 | 126 | // 删除收藏 127 | favorite.remove = function(req, res, next) { 128 | const type = req.body.type; 129 | const user_id = req.body.user_id; 130 | const task_id = req.body.task_id; 131 | const sql = `delete from favorite where type=${type} and user_id=${user_id} and task_id=${task_id}`; 132 | console.info('删除收藏', sql); 133 | query(sql, (err, vals) => { 134 | if (!err && vals instanceof Object) { 135 | req.body.data = true; 136 | req.body.code = '10000'; 137 | req.body.message = '操作成功'; 138 | req.body.success = true; 139 | return next(); 140 | } else { 141 | return res.json({ 142 | code: '10001', 143 | message: err, 144 | success: false, 145 | data: null, 146 | }); 147 | } 148 | }); 149 | }; -------------------------------------------------------------------------------- /middlewares/administrator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const administrator = {}; 9 | exports.administrator = administrator; 10 | 11 | //后台管理》分页获取管理员列表 12 | administrator.list = function(req, res, next) { 13 | var param = req.body; 14 | //分页实现 15 | var currentPage = 1; //默认为1 16 | var size = 10; //每页条数 17 | if (param.page) { 18 | currentPage = parseInt(param.page); 19 | } 20 | if (param.size) { 21 | size = parseInt(param.size); 22 | } 23 | //设置最后一页页码 24 | var lastPage = currentPage - 1; 25 | //假如目前仅有一页,则最后一页则为1 26 | if (currentPage <= 1) { 27 | lastPage = 1; 28 | } 29 | //如果需要下一页,则开启 30 | //var nextPage = currentPage + 1; 31 | var offset = (currentPage - 1) * size; 32 | var sql = `SELECT COUNT(*) FROM administrators; 33 | select * FROM administrators where deleted=0 34 | order by created_at desc limit ${size} offset ${offset}`; 35 | 36 | console.info('查询管理员', sql);; 37 | query(sql, (err, vals) => { 38 | if (!err && vals instanceof Array) { 39 | const totalCount = vals[0][0]['COUNT(*)']; 40 | const totalPage = Math.ceil(parseInt(totalCount) / size); 41 | req.body.data = { 42 | list: vals[1], 43 | size: size, 44 | page: currentPage, 45 | totalPage: totalPage, 46 | totalCount: totalCount, 47 | }; 48 | req.body.code = '10000'; 49 | req.body.message = '操作成功'; 50 | req.body.success = true; 51 | return next(); 52 | } else { 53 | return res.json({ 54 | code: '10001', 55 | message: err, 56 | success: false, 57 | data: null, 58 | }); 59 | } 60 | }); 61 | }; 62 | 63 | // 添加管理员 64 | administrator.add = function(req, res, next) { 65 | const username = req.body.username; 66 | const password = req.body.password; 67 | const powers = req.body.powers instanceof Object ? JSON.stringify(req.body.powers) : ''; 68 | const created_at = new Date().getTime(); 69 | const updated_at = created_at; 70 | const sql = `insert into administrators(username,password,role,powers,created_at,updated_at) values("${username}","${password}",2,'${powers}',"${created_at}","${updated_at}")`; 71 | console.info("添加管理员", sql); 72 | query(sql, (err, vals) => { 73 | if (!err && vals instanceof Object) { 74 | req.body.data = vals.insertId; 75 | req.body.code = '10000'; 76 | req.body.message = '操作成功'; 77 | req.body.success = true; 78 | // 记录操作日志 79 | req.body.log = Object.assign(req.body.log || {}, { 80 | client: 1, 81 | content: `添加了ID为${vals.insertId}的管理员`, 82 | }); 83 | return next(); 84 | } else { 85 | return res.json({ code: '10001', message: err, success: false, data: null }); 86 | } 87 | }) 88 | } 89 | 90 | // 修改管理员 91 | administrator.update = function(req, res, next) { 92 | const username = req.body.username; 93 | const password = req.body.password; 94 | const powers = req.body.powers instanceof Object ? JSON.stringify(req.body.powers) : ''; 95 | const id = req.body.id; 96 | const updated_at = new Date().getTime(); 97 | const sql = `update administrators set powers='${powers}',username="${username}",password="${password}",updated_at="${updated_at}" where id=${id}`; 98 | console.info("修改管理员", sql); 99 | query(sql, (err, vals) => { 100 | if (!err && vals.affectedRows) { 101 | req.body.data = true; 102 | req.body.code = '10000'; 103 | req.body.message = '操作成功'; 104 | req.body.success = true; 105 | // 记录操作日志 106 | req.body.log = Object.assign(req.body.log || {}, { 107 | client: 1, 108 | content: `修改了ID为${id}的管理员`, 109 | }); 110 | return next(); 111 | } else { 112 | return res.json({ code: '10001', message: err, success: false, data: null }); 113 | } 114 | }) 115 | } 116 | 117 | // 删除管理员 118 | administrator.remove = function(req, res, next) { 119 | const id = req.body.id; 120 | const updated_at = new Date().getTime(); 121 | const sql = `update administrators set deleted=1,updated_at="${updated_at}" where id=${id}`; 122 | console.info("更新用户信息", sql); 123 | query(sql, (err, vals) => { 124 | if (!err && vals instanceof Object) { 125 | req.body.data = true; 126 | req.body.code = '10000'; 127 | req.body.message = '操作成功'; 128 | req.body.success = true; 129 | // 记录操作日志 130 | req.body.log = Object.assign(req.body.log || {}, { 131 | client: 1, 132 | content: `删除了ID为${id}的管理员`, 133 | }); 134 | return next(); 135 | } else { 136 | return res.json({ code: '10001', message: err, success: false, data: null }); 137 | } 138 | }) 139 | } -------------------------------------------------------------------------------- /middlewares/entries.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const entries = {}; 9 | exports.entries = entries; 10 | 11 | //获取菜单 12 | entries.get = function(req, res, next) { 13 | const client = req.body.client || ''; 14 | const type = req.body.type || ''; 15 | let condition = client ? `and client like '%${client}%'` : ''; 16 | condition += type ? ` and type like '%${type}%'` : ''; 17 | const sql = `SELECT * FROM entries where deleted=0 ${condition} order by sort desc`; 18 | console.info("查询菜单", sql); 19 | query(sql, (err, vals) => { 20 | if (!err && vals instanceof Array) { 21 | req.body.data = vals; 22 | req.body.code = '10000'; 23 | req.body.message = '操作成功'; 24 | req.body.success = true; 25 | return next(); 26 | } else { 27 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 28 | } 29 | }) 30 | } 31 | entries.add = function(req, res, next) { 32 | const sort = req.body.sort; 33 | const is_show = req.body.is_show; 34 | const name = req.body.name; 35 | const sub_name = req.body.sub_name; 36 | const url = req.body.url; 37 | const mpUrl = req.body.mpUrl; 38 | let client = req.body.client; 39 | client = client instanceof Array ? client.join(',') : client; 40 | let type = req.body.type; 41 | type = type instanceof Array ? type.join(',') : type; 42 | const icon = req.body.icon; 43 | const font_color = req.body.font_color; 44 | const createdAt = new Date().getTime(); 45 | const sql = `insert into entries(type,is_show,client,icon,name,sub_name,url,mp_url,created_at,sort,font_color) 46 | values('${type}',${is_show},'${client}','${icon}','${name}','${sub_name}','${url}','${mpUrl}','${createdAt}',${sort},'${font_color}')`; 47 | console.info("新增菜单", sql); 48 | query(sql, (err, vals) => { 49 | if (!err && vals instanceof Object) { 50 | req.body.data = vals.insertId; 51 | req.body.code = '10000'; 52 | req.body.message = '操作成功'; 53 | req.body.success = true; 54 | // 记录操作日志 55 | req.body.log = Object.assign(req.body.log || {}, { 56 | client: 1, 57 | content: `添加了ID为${vals.insertId}的菜单`, 58 | }); 59 | return next(); 60 | } else { 61 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 62 | } 63 | }) 64 | } 65 | entries.update = async function(req, res, next) { 66 | const id = req.body.id; 67 | const sort = req.body.sort; 68 | const is_show = req.body.is_show; 69 | const name = req.body.name; 70 | const sub_name = req.body.sub_name; 71 | const url = req.body.url; 72 | const mpUrl = req.body.mpUrl; 73 | let client = req.body.client; 74 | client = client instanceof Array ? client.join(',') : client; 75 | let type = req.body.type; 76 | type = type instanceof Array ? type.join(',') : type; 77 | const icon = req.body.icon; 78 | const font_color = req.body.font_color; 79 | const updated_at = new Date().getTime(); 80 | const sql = `update entries set 81 | client=?, 82 | icon=?, 83 | name=?, 84 | sub_name=?, 85 | url=?, 86 | mp_url=?, 87 | updated_at=?, 88 | sort=?, 89 | is_show=?, 90 | type=?, 91 | font_color=? 92 | where id=?;`; 93 | const sqlValue = [client, icon, name, sub_name, url, mpUrl, updated_at, sort, is_show, type, font_color, id]; 94 | const result = await query(sql, null, sqlValue, '更新菜单'); 95 | if (!result.fail && result instanceof Object) { 96 | req.body.data = true; 97 | req.body.code = '10000'; 98 | req.body.message = '操作成功'; 99 | req.body.success = true; 100 | // 记录操作日志 101 | req.body.log = Object.assign(req.body.log || {}, { 102 | client: 1, 103 | content: `更新了ID为${id}的菜单`, 104 | }); 105 | console.info(req.body); 106 | return next(); 107 | } else { 108 | return res.json({ code: '10001', message: result.message, success: false, data: result }); 109 | } 110 | } 111 | entries.remove = function(req, res, next) { 112 | const id = req.body.id || req.body.id; 113 | const updatedAt = new Date().getTime(); 114 | const sql = `update entries set deleted=1,updated_at=${updatedAt} where id=${id}`; 115 | console.info("删除菜单", sql); 116 | query(sql, (err, vals) => { 117 | if (!err && vals instanceof Object) { 118 | req.body.data = true; 119 | req.body.code = '10000'; 120 | req.body.message = '操作成功'; 121 | req.body.success = true; 122 | // 记录操作日志 123 | req.body.log = Object.assign(req.body.log || {}, { 124 | client: 1, 125 | content: `删除了ID为${id}的菜单`, 126 | }); 127 | return next(); 128 | } else { 129 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 130 | } 131 | }) 132 | } -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const createError = require('http-errors'); 2 | const express = require('express'); 3 | const path = require('path'); 4 | const cookieParser = require('cookie-parser'); 5 | const bodyParser = require('body-parser'); 6 | const logger = require('morgan'); 7 | const { validateData, isEmptyObject } = require('./utils/function'); 8 | global.redis = require('redis'); 9 | const config = require('./config/index'); 10 | global.redisClient = redis.createClient({ 11 | password: config.redis.password, 12 | host: config.redis.host, 13 | port: config.redis.port, 14 | prefix: config.redis.prefix, 15 | }); 16 | 17 | // 定时任务 18 | require('./schedule/index'); 19 | 20 | const indexRouter = require('./routes/index'); 21 | const userRouter = require('./routes/user'); 22 | const loginRouter = require('./routes/login'); 23 | const registerRouter = require('./routes/register'); 24 | const bannersRouter = require('./routes/banners'); 25 | const tasksRouter = require('./routes/tasks'); 26 | const uploadRouter = require('./routes/upload'); 27 | const statisticsRouter = require('./routes/statistics'); 28 | const withdrawRouter = require('./routes/withdraw'); 29 | const administratorRouter = require('./routes/administrator'); 30 | const systemRouter = require('./routes/system'); 31 | const certificationsRouter = require('./routes/certifications'); 32 | const orderRouter = require('./routes/order'); 33 | const moneyRouter = require('./routes/money'); 34 | const entriesRouter = require('./routes/entries'); 35 | const updateRouter = require('./routes/update'); 36 | const refreshRouter = require('./routes/refresh'); 37 | const timesRouter = require('./routes/times'); 38 | const smsRouter = require('./routes/sms'); 39 | const favoriteRouter = require('./routes/favorite'); 40 | const messagesRouter = require('./routes/messages'); 41 | const signRouter = require('./routes/sign'); 42 | const scoreRouter = require('./routes/score'); 43 | const logRouter = require('./routes/log'); 44 | const helpRouter = require('./routes/help'); 45 | const goodsRouter = require('./routes/goods'); 46 | const addressRouter = require('./routes/address'); 47 | 48 | const app = express(); 49 | 50 | // view engine setup 51 | app.set('views', path.join(__dirname, 'views')); 52 | app.set('view engine', 'ejs'); 53 | 54 | app.use(logger('dev')); 55 | app.use(bodyParser.urlencoded({ limit: 1024 * 1024 * 1024, extended: true })); 56 | app.use(bodyParser.json()); 57 | app.use(cookieParser()); 58 | app.use(express.static(path.join(__dirname, 'public'))); 59 | 60 | //设置跨域访问 61 | app.all('*', function(req, res, next) { 62 | res.header('Access-Control-Allow-Origin', '*'); 63 | res.header('Access-Control-Allow-Headers', 'skey'); 64 | res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS'); 65 | res.header('X-Powered-By', ' 3.2.1'); 66 | if (req.method.toLocaleLowerCase() === 'options'){ 67 | res.status(204); 68 | return res.json({}) 69 | }else { 70 | next(); 71 | } 72 | }); 73 | 74 | app.use(function(req, res, next) { 75 | if (req.method.toUpperCase() === 'POST') { 76 | const whiteList = [ 77 | '/order/rechargeMoneyNotify', 78 | '/order/alipayRechargeNotify', 79 | '/order/yuwan', 80 | '/order/duoyou', 81 | '/order/xianwan' 82 | ]; 83 | if (!whiteList.includes(req.url) && !isEmptyObject(req.body)) { 84 | if (!req.body.encryptedResult || !validateData(req.body)) { 85 | return res.json({ code: '10001', message: '非法请求', success: false, data: '' }); 86 | } 87 | } 88 | } 89 | next(); 90 | }) 91 | 92 | app.use('/', indexRouter); 93 | app.use('/user', userRouter); 94 | app.use('/login', loginRouter); 95 | app.use('/register', registerRouter); 96 | app.use('/banners', bannersRouter); 97 | app.use('/tasks', tasksRouter); 98 | app.use('/upload', uploadRouter); 99 | app.use('/statistics', statisticsRouter); 100 | app.use('/withdraw', withdrawRouter); 101 | app.use('/administrator', administratorRouter); 102 | app.use('/system', systemRouter); 103 | app.use('/certifications', certificationsRouter); 104 | app.use('/order', orderRouter); 105 | app.use('/money', moneyRouter); 106 | app.use('/entries', entriesRouter); 107 | app.use('/update', updateRouter); 108 | app.use('/refresh', refreshRouter); 109 | app.use('/times', timesRouter); 110 | app.use('/sms', smsRouter); 111 | app.use('/favorite', favoriteRouter); 112 | app.use('/messages', messagesRouter); 113 | app.use('/sign', signRouter); 114 | app.use('/score', scoreRouter); 115 | app.use('/log', logRouter); 116 | app.use('/help', helpRouter); 117 | app.use('/goods', goodsRouter); 118 | app.use('/address', addressRouter); 119 | 120 | // catch 404 and forward to error handler 121 | app.use(function(req, res, next) { 122 | next(createError(404)); 123 | }); 124 | 125 | // error handler 126 | app.use(function(err, req, res, next) { 127 | // set locals, only providing error in development 128 | res.locals.message = err.message; 129 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 130 | 131 | // render the error page 132 | res.status(err.status || 500); 133 | res.render('error'); 134 | }); 135 | 136 | module.exports = app; 137 | -------------------------------------------------------------------------------- /key/alipayRootCert.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG 3 | EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw 4 | MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO 5 | UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE 6 | MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT 7 | V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti 8 | W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ 9 | MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b 10 | 53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI 11 | pDoiVhsLwg== 12 | -----END CERTIFICATE----- 13 | 14 | -----BEGIN CERTIFICATE----- 15 | MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE 16 | BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj 17 | YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj 18 | YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0 19 | MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV 20 | BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j 21 | aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF 22 | AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk 23 | rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2 24 | xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp 25 | dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6 26 | vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl 27 | YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1 28 | Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H 29 | DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98 30 | SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG 31 | PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe 32 | 9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC 33 | AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90 34 | tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy 35 | nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf 36 | tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq 37 | JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3 38 | IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW 39 | 05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41 40 | T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI 41 | kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop 42 | PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N 43 | 1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y 44 | jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02 45 | 77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi 46 | kT9qhqn+lw== 47 | -----END CERTIFICATE----- 48 | 49 | -----BEGIN CERTIFICATE----- 50 | MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG 51 | EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh 52 | dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh 53 | dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0 54 | WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE 55 | CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp 56 | YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA 57 | IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU 58 | WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt 59 | rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ 60 | 4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2 61 | zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg 62 | wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH 63 | Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA== 64 | -----END CERTIFICATE----- 65 | 66 | -----BEGIN CERTIFICATE----- 67 | MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF 68 | BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM 69 | E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg 70 | MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq 71 | MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp 72 | bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv 73 | b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV 74 | nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5 75 | 4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg 76 | wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw 77 | WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN 78 | z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g 79 | KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA 80 | uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF 81 | MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp 82 | emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3 83 | U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I 84 | UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn 85 | DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU 86 | 1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX 87 | Yf4Zr0fJsGuv 88 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /middlewares/sign.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const moment = require('moment'); 8 | const query = require('../utils/pool'); 9 | const sign = {}; 10 | exports.sign = sign; 11 | 12 | // 获取签到规则列表 13 | sign.list = function(req, res, next) { 14 | const sql = `SELECT * FROM sign order by sort`; 15 | console.info("查询签到列表", sql); 16 | query(sql, (err, vals) => { 17 | if (!err && vals instanceof Array) { 18 | req.body.data = vals; 19 | req.body.code = '10000'; 20 | req.body.message = '操作成功'; 21 | req.body.success = true; 22 | return next(); 23 | } else { 24 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 25 | } 26 | }) 27 | } 28 | 29 | // 用户签到 30 | sign.do = async function(req, res, next) { 31 | const user_id = req.body.user_id; 32 | // 本次签到积分 33 | const sign_score = req.body.sign_score; 34 | // 签到id 35 | const sign_id = req.body.sign_id; 36 | // 上次签到次数 37 | let sign_count = req.body.sign_count; 38 | // 上次签到时间 39 | const now = new Date().getTime(); 40 | const sign_at = req.body.sign_at; // 如果为null,则说明没签过到days < 1为false 41 | 42 | // 判断此用户今天是否已签到过 43 | const checkResult = await query(`select sign_at from users where id=${user_id}`); 44 | if (!checkResult.fail && checkResult instanceof Array) { 45 | if(!isNaN(checkResult[0].sign_at) && moment(new Date(+checkResult[0].sign_at)).isSame(moment(), 'day')) { 46 | return res.json({ code: '10001', message: '今天已签到,明天再来吧', success: false, data: '' }); 47 | } 48 | } 49 | 50 | // 现在和上次签到时间相差的天数 51 | const start = moment(moment(new Date(+sign_at), 'YYYY-MM-DD')).set({ 52 | hour: 0, 53 | minute: 0, 54 | second: 0, 55 | millisecond: 0, 56 | }); 57 | const end = moment(moment(new Date(), 'YYYY-MM-DD')); 58 | const days = end.diff(start, 'days'); 59 | console.info('距离上次签到天数', days); 60 | if (days < 1) { 61 | return res.json({ code: '10001', message: '今天已签到,明天再来吧', success: false, data: '' }); 62 | } 63 | const sql = `begin; 64 | update users set 65 | ${days > 1 ? `sign_count=1` : `sign_count=sign_count+1`}, 66 | sign_at='${now}', 67 | score=score+${sign_score} where id=${user_id}; 68 | insert into score_stream(business_id,type,score,balance,user_id,is_income,created_at,remark) 69 | values(${sign_id},1,${sign_score},(select score from users where id=${user_id}),${user_id},1,'${now}','签到'); 70 | commit;`; 71 | console.info("用户签到", sql); 72 | query(sql, (err, vals) => { 73 | if (!err && vals instanceof Array) { 74 | req.body = { 75 | data: { 76 | sign_at: now, 77 | sign_count: days > 1 ? 1 : (+sign_count + 1), 78 | }, 79 | code: '10000', 80 | message: '操作成功', 81 | success: true, 82 | } 83 | return next(); 84 | } else { 85 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 86 | } 87 | }) 88 | } 89 | 90 | // 添加签到规则 91 | sign.add = function(req, res, next) { 92 | const sort = req.body.sort; 93 | const name = req.body.name; 94 | const score = req.body.score; 95 | const sql = `insert into sign(sort,name,score) 96 | values(${sort},'${name}',${score})`; 97 | console.info("新增签到规则", sql); 98 | query(sql, (err, vals) => { 99 | if (!err && vals instanceof Object) { 100 | req.body.data = vals.insertId; 101 | req.body.code = '10000'; 102 | req.body.message = '操作成功'; 103 | req.body.success = true; 104 | // 记录操作日志 105 | req.body.log = Object.assign(req.body.log || {}, { 106 | client: 1, 107 | content: `添加了ID为${vals.insertId}的签到规则`, 108 | }); 109 | return next(); 110 | } else { 111 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 112 | } 113 | }) 114 | } 115 | 116 | // 更新签到规则 117 | sign.update = function(req, res, next) { 118 | const id = req.body.id; 119 | const sort = req.body.sort; 120 | const name = req.body.name; 121 | const score = req.body.score; 122 | const sql = `update sign set sort=${sort},name='${name}',score=${score} where id=${id}`; 123 | console.info("更新签到规则", sql); 124 | query(sql, (err, vals) => { 125 | if (!err && vals instanceof Object) { 126 | req.body.data = true; 127 | req.body.code = '10000'; 128 | req.body.message = '操作成功'; 129 | req.body.success = true; 130 | // 记录操作日志 131 | req.body.log = Object.assign(req.body.log || {}, { 132 | client: 1, 133 | content: `修改了ID为${id}的签到规则`, 134 | }); 135 | return next(); 136 | } else { 137 | return res.json({ code: '10001', message: err.message, success: false, data: message }); 138 | } 139 | }) 140 | } 141 | 142 | // 删除签到规则 143 | sign.remove = function(req, res, next) { 144 | const id = req.body.id; 145 | const sql = `delete from sign where id=${id}`; 146 | console.info("删除签到规则", sql); 147 | query(sql, (err, vals) => { 148 | if (!err && vals instanceof Object) { 149 | req.body.data = true; 150 | req.body.code = '10000'; 151 | req.body.message = '操作成功'; 152 | req.body.success = true; 153 | // 记录操作日志 154 | req.body.log = Object.assign(req.body.log || {}, { 155 | client: 1, 156 | content: `删除了ID为${id}的签到规则`, 157 | }); 158 | return next(); 159 | } else { 160 | return res.json({ code: '10001', message: err.message, success: false, data: message }); 161 | } 162 | }) 163 | } -------------------------------------------------------------------------------- /routes/tasks.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { login } = require('../middlewares/login.js'); 4 | const { log } = require('../middlewares/log.js'); 5 | const { tasks } = require('../middlewares/tasks.js'); 6 | const { money } = require('../middlewares/money.js'); 7 | const { messages } = require('../middlewares/messages.js'); 8 | 9 | // 获取任务,不返回下架的 10 | router.post('/', tasks.updateAutoend, tasks.getAll, function(req, res, next) { 11 | res.json(req.body); 12 | }); 13 | 14 | // 获取任务,下架的也返回 15 | router.post('/admin', tasks.getAllUnlimited, function(req, res, next) { 16 | res.json(req.body); 17 | }); 18 | 19 | // 抢任务 20 | router.post('/grab', login.check, tasks.isVip, tasks.detail, tasks.grab, function(req, res, next) { 21 | res.json(req.body); 22 | }); 23 | 24 | // 查询单个任务,带判断是否已抢 25 | router.post('/detailForUser', tasks.updateTimeoutTask, tasks.getDetail, function(req, res, next) { 26 | res.json(req.body); 27 | }); 28 | 29 | // 用户领取的任务详情(任务快照) 30 | router.post('/userTaskDetail', tasks.updateTimeoutTask, tasks.userTaskDetail, function(req, res, next) { 31 | res.json(req.body); 32 | }); 33 | 34 | // 获取任务提交审核的步骤 35 | router.post('/getReviewStep', tasks.getReviewStep, function(req, res, next) { 36 | res.json(req.body); 37 | }); 38 | 39 | // 获取任务提交审核的字段 40 | router.post('/getReviewField', tasks.getReviewField, function(req, res, next) { 41 | res.json(req.body); 42 | }); 43 | 44 | // 获取任务审核列表 45 | router.post('/getReviewList', tasks.getReviewList, function(req, res, next) { 46 | res.json(req.body); 47 | }); 48 | 49 | // 获取申诉列表 50 | router.post('/getAppealList', tasks.getAppealList, function(req, res, next) { 51 | res.json(req.body); 52 | }); 53 | 54 | // 驳回审核请求 55 | router.post('/reviewReject', login.check, tasks.reviewReject, messages.add, log.add, function(req, res, next) { 56 | res.json(req.body); 57 | }); 58 | 59 | // 删除提交的审核 60 | router.post('/reviewRemove', login.check, tasks.reviewRemove, log.add, function(req, res, next) { 61 | res.json(req.body); 62 | }); 63 | 64 | // 通过审核请求 65 | router.post( 66 | '/reviewResolve', 67 | login.check, 68 | tasks.money, 69 | tasks.reviewResolve, 70 | messages.add, 71 | money.add, 72 | log.add, 73 | function(req, res, next) { 74 | res.json({ 75 | data: true, 76 | code: '10000', 77 | message: '操作成功', 78 | success: true 79 | }); 80 | } 81 | ); 82 | 83 | // 获取当前任务审核列表 84 | router.post('/getTaskGrabList', tasks.getTaskGrabList, function(req, res, next) { 85 | res.json(req.body); 86 | }); 87 | 88 | // 获取当前用户参与的任务 89 | router.post('/getUserTasks', login.check, tasks.getUserTasks, function(req, res, next) { 90 | res.json(req.body); 91 | }); 92 | 93 | // 回收任务数量 94 | router.post('/updateTimeoutTask', login.check, tasks.updateTimeoutTask, function(req, res, next) { 95 | res.json(req.body); 96 | }); 97 | 98 | // 处理审核超时的任务 99 | router.post('/updateReviewTimeoutTask', 100 | login.check, 101 | tasks.money, 102 | tasks.updateReviewTimeoutTask, 103 | money.add, 104 | function(req, res, next) { 105 | res.json({ 106 | data: true, 107 | code: '10000', 108 | message: '操作成功', 109 | success: true 110 | }); 111 | }, 112 | ); 113 | 114 | 115 | // 获取当前用户发布的任务 116 | router.post('/getUserPublishedTasks', login.check, tasks.getUserPublishedTasks, function(req, res, next) { 117 | res.json(req.body); 118 | }); 119 | 120 | // 获取任务类型 121 | router.post('/getTypes', tasks.getTypes, function(req, res, next) { 122 | res.json(req.body); 123 | }); 124 | 125 | // 用户提交任务审核 126 | router.post('/submitReview', login.check, tasks.submitReview, messages.add, function(req, res, next) { 127 | res.json({ 128 | data: req.body.data, 129 | message: '操作成功', 130 | code: '10000', 131 | success: true 132 | }); 133 | }); 134 | 135 | // 用户提交申诉 136 | router.post('/addAppeal', login.check, tasks.addAppeal, function(req, res, next) { 137 | res.json(req.body); 138 | }); 139 | 140 | // 申诉详情 141 | router.post('/getAppeal', login.check, tasks.getAppeal, function(req, res, next) { 142 | res.json(req.body); 143 | }); 144 | 145 | // 更新申诉 146 | router.post('/updateAppeal', login.check, tasks.updateAppeal, log.add, function(req, res, next) { 147 | res.json(req.body); 148 | }); 149 | 150 | // 用户修改任务审核 151 | router.post('/updateReview', login.check, tasks.updateReview, function(req, res, next) { 152 | res.json(req.body); 153 | }); 154 | 155 | // 删除任务 156 | router.post('/remove', login.check, tasks.remove, log.add, function(req, res, next) { 157 | res.json(req.body); 158 | }); 159 | 160 | // 管理员发布任务 161 | router.post('/adminAdd', login.check, tasks.add, log.add, function(req, res, next) { 162 | res.json(req.body); 163 | }); 164 | 165 | // 用户发布任务 166 | router.post('/add', login.check, tasks.add, function(req, res, next) { 167 | res.json(req.body); 168 | }); 169 | 170 | // 更新任务 171 | router.post('/update', login.check, tasks.update, log.add, function(req, res, next) { 172 | res.json(req.body); 173 | }); 174 | 175 | // 根据ID获取审核的任务 176 | router.post('/getReviewDetail', tasks.getReviewDetail, function(req, res, next) { 177 | res.json(req.body); 178 | }); 179 | 180 | // 根据ID获取审核详情,用户端审核 181 | router.post('/getReviewDetailForUser', tasks.getReviewDetailForUser, function(req, res, next) { 182 | res.json(req.body); 183 | }); 184 | 185 | // 根据任务ID获取任务详情 186 | router.post('/getDetail', tasks.detail, function(req, res, next) { 187 | res.json(req.body); 188 | }); 189 | 190 | // 修改任务状态 191 | router.post('/updateStatus', login.check, tasks.updateStatus, messages.add, log.add, function(req, res, next) { 192 | res.json(req.body); 193 | }); 194 | 195 | // 删除分类 196 | router.post('/removeType', login.check, tasks.removeType, log.add, function(req, res, next) { 197 | res.json(req.body); 198 | }); 199 | 200 | // 添加分类 201 | router.post('/addType', login.check, tasks.addType, log.add, function(req, res, next) { 202 | res.json(req.body); 203 | }); 204 | 205 | // 更新分类 206 | router.post('/updateType', login.check, tasks.updateType, log.add, function(req, res, next) { 207 | res.json(req.body); 208 | }); 209 | 210 | module.exports = router; 211 | -------------------------------------------------------------------------------- /middlewares/money.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const moment = require('moment'); 8 | const query = require('../utils/pool'); 9 | const money = {}; 10 | exports.money = money; 11 | 12 | // 给用户加钱 13 | money.add = function(req, res, next) { 14 | const userId = req.body.userId || req.body.userId; 15 | let money = req.body.money || req.body.money || 0; 16 | money = +money; 17 | 18 | // 加钱类型,1充值;2提现;3收入;4支出 19 | const type = req.body.type; 20 | const remark = req.body.remark || ''; 21 | const created_at = new Date().getTime(); 22 | if (money < 0) { 23 | return res.json({ code: '10010', message: '金额不合法', success: false, data: money }); 24 | } 25 | const sql = `begin; 26 | update users set account_amount=account_amount+${money} where id=${userId}; 27 | insert into money_stream(type,money,balance,user_id,is_income,created_at,remark) 28 | values(${type},${money},(select account_amount from users where id=${userId}),${userId},1,'${created_at}','${remark}'); 29 | commit;` 30 | console.info("加钱", sql); 31 | query(sql, (err, vals) => { 32 | console.info('加钱返回', vals) 33 | if (!err && vals instanceof Array) { 34 | req.body.data = true; 35 | req.body.code = '10000'; 36 | req.body.message = '操作成功'; 37 | req.body.success = true; 38 | return next(); 39 | } else { 40 | return res.json({ code: '10001', message: err, success: false, data: err }); 41 | } 42 | }) 43 | } 44 | // 给用户减钱 45 | money.reduce = function(req, res, next) { 46 | const userId = req.body.userId || req.body.userId; 47 | let money = req.body.money || req.body.money || 0; 48 | money = +money; 49 | if (money < 0) { 50 | return res.json({ code: '10010', message: '金额不合法', success: false, data: money }); 51 | } 52 | const remark = req.body.remark; 53 | const created_at = new Date().getTime(); 54 | const sql = `begin; 55 | update users set account_amount=account_amount-${money}, 56 | finished_amount=finished_amount+${money} where id=${userId}; 57 | insert into money_stream(type,money,balance,user_id,is_income,created_at,remark) 58 | values(4,${money},(select account_amount from users where id=${userId}),${userId},0,"${created_at}","${remark || ''}"); 59 | commit;` 60 | console.info("减钱", sql); 61 | query(sql, (err, vals) => { 62 | if (!err && vals instanceof Object) { 63 | req.body.data = true; 64 | req.body.code = '10000'; 65 | req.body.message = '操作成功'; 66 | req.body.success = true; 67 | // 记录操作日志 68 | req.body.log = Object.assign(req.body.log || {}, { 69 | client: 1, 70 | content: `给用户${userId}账户余额减去了${money}元`, 71 | }); 72 | return next(); 73 | } else { 74 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 75 | } 76 | }) 77 | } 78 | 79 | // 获取用户金额流水 80 | money.stream = function(req, res, next) { 81 | var param = req.body; 82 | //分页实现 83 | var currentPage = 1; //默认为1 84 | var size = 10; //每页条数 85 | if (param.page) { 86 | currentPage = parseInt(param.page); 87 | } 88 | if (param.size) { 89 | size = parseInt(param.size); 90 | } 91 | //设置最后一页页码 92 | var lastPage = currentPage - 1; 93 | //假如目前仅有一页,则最后一页则为1 94 | if (currentPage <= 1) { 95 | lastPage = 1; 96 | } 97 | //如果需要下一页,则开启 98 | //var nextPage = currentPage + 1; 99 | var offset = (currentPage - 1) * size; 100 | 101 | const { type, userId, createDateRange } = param; 102 | let filters = []; 103 | type && filters.push(`type=${type}`); 104 | userId && filters.push(`user_id=${userId}`); 105 | createDateRange && createDateRange.length === 2 && filters.push(`created_at >= ${createDateRange[0]} and created_at <= ${createDateRange[1]}`); 106 | const filterString = filters.length ? `where ${filters.join(' and ')}` : ''; 107 | 108 | var sql = `SELECT count(*) FROM money_stream ${filterString}; 109 | select * FROM money_stream ${filterString} 110 | order by created_at desc limit ${size} offset ${offset}`; 111 | 112 | console.info('查询用户流水', sql);; 113 | query(sql, (err, vals) => { 114 | if (!err && vals instanceof Array) { 115 | const totalCount = vals[0][0]['count(*)']; 116 | const totalPage = Math.ceil(parseInt(totalCount) / size); 117 | req.body.data = { 118 | list: vals[1], 119 | size: size, 120 | page: currentPage, 121 | totalPage: totalPage, 122 | totalCount: totalCount, 123 | }; 124 | req.body.code = '10000'; 125 | req.body.message = '操作成功'; 126 | req.body.success = true; 127 | return next(); 128 | } else { 129 | return res.json({ 130 | code: '10001', 131 | message: err.message, 132 | success: false, 133 | data: err, 134 | }); 135 | } 136 | }); 137 | } 138 | 139 | // 导出用户金额流水 140 | money.exportAll = async function(req, res, next) { 141 | const { type, userId, createDateRange } = req.body; 142 | const filters = []; 143 | type && filters.push(`type=${type}`); 144 | userId && filters.push(`user_id=${userId}`); 145 | createDateRange && createDateRange.length === 2 && filters.push(`created_at >= ${createDateRange[0]} and created_at <= ${createDateRange[1]}`); 146 | const filterString = filters.length ? `where ${filters.join(' and ')}` : ''; 147 | const sql = `select * FROM money_stream ${filterString} order by created_at desc`; 148 | const result = await query(sql); 149 | if (!result.fail && result instanceof Array) { 150 | const exportConfig = {}; 151 | exportConfig.cols = [ 152 | { 153 | caption: 'id', 154 | type: 'number', 155 | }, { 156 | caption: '用户ID', 157 | type: 'number', 158 | }, { 159 | caption: '类型(1.充值;2.提现;3.收入;4.支出;)', 160 | type: 'number', 161 | }, { 162 | caption: '金额', 163 | type: 'number', 164 | }, { 165 | caption: '账户余额', 166 | type: 'number', 167 | }, { 168 | caption: '备注', 169 | type: 'string', 170 | }, { 171 | caption: '创建时间', 172 | type: 'string', 173 | }, 174 | ]; 175 | const temp = []; 176 | result.forEach((item) => { 177 | temp.push([ 178 | item.id, 179 | item.user_id, 180 | item.type, 181 | item.money, 182 | item.balance, 183 | item.remark, 184 | item.created_at ? moment(+item.created_at).format('YYYY-MM-DD HH:mm:ss') : '', 185 | ]); 186 | }); 187 | exportConfig.rows = temp; 188 | req.body.excelData = { exportConfig, prefix: '金额流水' }; 189 | return next(); 190 | } else { 191 | return res.json({ code: '10001', message: result.message, success: false, data: null }); 192 | } 193 | }; -------------------------------------------------------------------------------- /middlewares/certifications.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const certifications = {}; 9 | exports.certifications = certifications; 10 | 11 | //获取认证列表 12 | certifications.get = async function(req, res, next) { 13 | var param = req.body; 14 | //分页实现 15 | var currentPage = 1; //默认为1 16 | var size = 10; //每页条数 17 | if (param.page) { 18 | currentPage = parseInt(param.page); 19 | } 20 | if (param.size) { 21 | size = parseInt(param.size); 22 | } 23 | //设置最后一页页码 24 | var lastPage = currentPage - 1; 25 | //假如目前仅有一页,则最后一页则为1 26 | if (currentPage <= 1) { 27 | lastPage = 1; 28 | } 29 | //如果需要下一页,则开启 30 | //var nextPage = currentPage + 1; 31 | var offset = (currentPage - 1) * size; 32 | const { createdAt, userId, truename, phone, status } = param; 33 | const filters = []; 34 | truename && filters.push(`truename like "%${truename}%"`); 35 | phone && filters.push(`phone like "%${phone}%"`); 36 | userId && filters.push(`user_id=${userId}`); 37 | [0,1,2,'0','1','2'].includes(status) && filters.push(`status=${status}`); 38 | createdAt && filters.push(`TO_DAYS(FROM_UNIXTIME(created_at/1000))=TO_DAYS(FROM_UNIXTIME(${new Date(createdAt).getTime()/1000}))`); 39 | const filterString = filters.length ? `where ${filters.join(' and ')}` : ''; 40 | var sql = `SELECT count(*) FROM certifications ${filterString}; 41 | SELECT * FROM certifications ${filterString} 42 | order by created_at desc limit ? offset ?`; 43 | const queryResult = await query(sql, null, [size, offset], '查询认证列表'); 44 | if (!queryResult.fail && queryResult instanceof Array) { 45 | const totalCount = queryResult[0][0]['count(*)']; 46 | const totalPage = Math.ceil(parseInt(totalCount) / size); 47 | req.body.data = { 48 | list: queryResult[1], 49 | size: size, 50 | page: currentPage, 51 | totalPage: totalPage, 52 | totalCount: totalCount, 53 | }; 54 | req.body.code = '10000'; 55 | req.body.message = '操作成功'; 56 | req.body.success = true; 57 | return next(); 58 | } else { 59 | return res.json({ code: '10001', message: queryResult.message, success: false, data: null}); 60 | } 61 | } 62 | 63 | // 获取认证详情 64 | certifications.detail = function(req, res, next) { 65 | const userId = req.body.userId; 66 | const sql = `SELECT * FROM certifications where user_id=${userId}`; 67 | console.info("获取认证详情", sql); 68 | query(sql, (err, vals) => { 69 | if (!err && vals instanceof Array) { 70 | req.body.data = vals[0]; 71 | req.body.code = '10000'; 72 | req.body.message = '操作成功'; 73 | req.body.success = true; 74 | return next(); 75 | } else { 76 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 77 | } 78 | }) 79 | } 80 | 81 | // 用户提交认证资料 82 | certifications.add = async function(req, res, next) { 83 | const certificate = req.body.certificate; 84 | const wxpay_code = req.body.wxpay_code; 85 | const alipay_code = req.body.alipay_code; 86 | const userId = req.body.userId; 87 | const truename = req.body.truename; 88 | const phone = req.body.phone; 89 | const remark = req.body.remark; 90 | const idCard = req.body.idCard; 91 | const createdAt = new Date().getTime(); 92 | const checkResult = await query(`select id from certifications where user_id=?`, null, [userId], '查询认证详情'); 93 | if (!checkResult.fail && checkResult instanceof Array) { 94 | if (checkResult[0] && checkResult[0].id) { 95 | return res.json({ code: '10001', message: '请勿重复提交', success: false, data: null }); 96 | } 97 | } 98 | const sql = `insert into certifications(certificate,wxpay_code,alipay_code,user_id,truename,phone,remark,status,created_at,id_card) 99 | values("${certificate}","${wxpay_code}","${alipay_code}",${userId},"${truename}","${phone}","${remark}",0,"${createdAt}","${idCard}")`; 100 | console.info("用户提交认证资料", sql); 101 | query(sql, (err, vals) => { 102 | if (!err && vals instanceof Object) { 103 | req.body.data = vals.insertId; 104 | req.body.code = '10000'; 105 | req.body.message = '操作成功'; 106 | req.body.success = true; 107 | // 设置消息内容 108 | req.body.message_add = { 109 | type: 1, 110 | user_id: 1, 111 | business_id: {certification_id: vals.insertId}, 112 | title: '用户申请认证', 113 | content: `ID为${userId}的用户提交了认证资料给你审核,认证ID为${vals.insertId}`, 114 | } 115 | return next(); 116 | } else { 117 | return res.json({ code: '10001', message: err, success: false, data: null }); 118 | } 119 | }) 120 | } 121 | 122 | // 管理员审核认证资料 123 | certifications.review = function(req, res, next) { 124 | const certificate = req.body.certificate; 125 | const wxpay_code = req.body.wxpay_code; 126 | const alipay_code = req.body.alipay_code; 127 | const userId = req.body.userId; 128 | const truename = req.body.truename; 129 | const phone = req.body.phone; 130 | const remark = req.body.remark; 131 | const result = req.body.result; 132 | const status = req.body.status; 133 | const idCard = req.body.idCard; 134 | const updatedAt = new Date().getTime(); 135 | const reviewedAt = req.body.reviewedAt; 136 | const sql = `update certifications set 137 | certificate="${certificate}", 138 | wxpay_code="${wxpay_code}", 139 | alipay_code="${alipay_code}", 140 | truename="${truename}", 141 | phone="${phone}", 142 | remark="${remark}", 143 | status=${status}, 144 | updated_at="${updatedAt}", 145 | reviewed_at="${reviewedAt}", 146 | result="${result || ''}", 147 | id_card="${idCard}" 148 | where user_id=${userId}; 149 | update users set is_certified=${status == 1 ? 1 : 0} where id=${userId};`; 150 | console.info("用户更新认证资料", sql); 151 | query(sql, (err, vals) => { 152 | if (!err) { 153 | req.body.data = true; 154 | req.body.code = '10000'; 155 | req.body.message = '操作成功'; 156 | req.body.success = true; 157 | // 记录操作日志 158 | req.body.log = Object.assign(req.body.log || {}, { 159 | client: 1, 160 | content: `${status == 1 ? '通过' : '驳回'}了用户ID为${userId}的认证申请`, 161 | }); 162 | return next(); 163 | } else { 164 | return res.json({ code: '10001', message: err, success: false, data: null }); 165 | } 166 | }) 167 | } 168 | 169 | // 用户更新认证资料 170 | certifications.update = function(req, res, next) { 171 | const certificate = req.body.certificate; 172 | const wxpay_code = req.body.wxpay_code; 173 | const alipay_code = req.body.alipay_code; 174 | const userId = req.body.userId; 175 | const truename = req.body.truename; 176 | const phone = req.body.phone; 177 | const remark = req.body.remark; 178 | const idCard = req.body.idCard; 179 | const updatedAt = new Date().getTime(); 180 | const sql = `update certifications set 181 | certificate="${certificate}", 182 | wxpay_code="${wxpay_code}", 183 | alipay_code="${alipay_code}", 184 | truename="${truename}", 185 | phone="${phone}", 186 | remark="${remark}", 187 | updated_at="${updatedAt}", 188 | reviewed_at="", 189 | id_card="${idCard}", 190 | status=0 191 | where user_id=${userId}`; 192 | console.info("用户更新认证资料", sql); 193 | query(sql, (err, vals) => { 194 | if (!err) { 195 | req.body.data = true; 196 | req.body.code = '10000'; 197 | req.body.message = '操作成功'; 198 | req.body.success = true; 199 | return next(); 200 | } else { 201 | return res.json({ code: '10001', message: err, success: false, data: null }); 202 | } 203 | }) 204 | } 205 | 206 | // 删除用户认证资料 207 | certifications.remove = function(req, res, next) { 208 | const id = req.body.id; 209 | const userId = req.body.userId; 210 | const sql = `delete from certifications where id=${id}; 211 | update users set is_certified=0 where id=${userId}`; 212 | console.info("删除用户认证资料", sql); 213 | query(sql, (err, vals) => { 214 | if (!err && vals instanceof Object) { 215 | req.body.data = true; 216 | req.body.code = '10000'; 217 | req.body.message = '操作成功'; 218 | req.body.success = true; 219 | // 记录操作日志 220 | req.body.log = Object.assign(req.body.log || {}, { 221 | client: 1, 222 | content: `删除了用户ID为${userId}的认证资料`, 223 | }); 224 | return next(); 225 | } else { 226 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 227 | } 228 | }) 229 | } -------------------------------------------------------------------------------- /middlewares/help.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const help = {}; 9 | exports.help = help; 10 | 11 | // 帮助文章列表 12 | help.list = async function(req, res, next) { 13 | var param = req.body; 14 | //分页实现 15 | var currentPage = 1; //默认为1 16 | var size = 10; //每页条数 17 | if (param.page) { 18 | currentPage = parseInt(param.page); 19 | } 20 | if (param.size) { 21 | size = parseInt(param.size); 22 | } 23 | //设置最后一页页码 24 | var lastPage = currentPage - 1; 25 | //假如目前仅有一页,则最后一页则为1 26 | if (currentPage <= 1) { 27 | lastPage = 1; 28 | } 29 | //如果需要下一页,则开启 30 | //var nextPage = currentPage + 1; 31 | var offset = (currentPage - 1) * size; 32 | const { type, title } = param; 33 | const filters = ['a.deleted=0']; 34 | title && filters.push(`a.title like "%${title}%"`); 35 | type && filters.push(`a.type=${type}`); 36 | const filterString = filters.length ? `where ${filters.join(' and ')}` : ''; 37 | var sql = `SELECT count(*) FROM help_articles a ${filterString}; 38 | SELECT a.id,a.title,a.type,t.name as type_name,a.created_at,a.updated_at FROM help_articles a 39 | left join help_type t on t.id=a.type ${filterString} 40 | order by a.created_at desc limit ? offset ?`; 41 | const queryResult = await query(sql, null, [size, offset], '查询帮助文章列表'); 42 | if (!queryResult.fail && queryResult instanceof Array) { 43 | const totalCount = queryResult[0][0]['count(*)']; 44 | const totalPage = Math.ceil(parseInt(totalCount) / size); 45 | req.body.data = { 46 | list: queryResult[1], 47 | size: size, 48 | page: currentPage, 49 | totalPage: totalPage, 50 | totalCount: totalCount, 51 | }; 52 | req.body.code = '10000'; 53 | req.body.message = '操作成功'; 54 | req.body.success = true; 55 | return next(); 56 | } else { 57 | return res.json({ code: '10001', message: queryResult.message, success: false, data: null}); 58 | } 59 | } 60 | 61 | // 帮助文章详情 62 | help.detail = async function(req, res, next) { 63 | const id = req.body.id; 64 | const sql = `select * from help_articles where id=${id}`; 65 | console.info('活动详情', sql); 66 | query(sql, (err, vals) => { 67 | if (!err && vals instanceof Object) { 68 | req.body.data = vals[0]; 69 | req.body.code = '10000'; 70 | req.body.message = '操作成功'; 71 | req.body.success = true; 72 | return next(); 73 | } else { 74 | return res.json({ 75 | code: '10001', 76 | message: err, 77 | success: false, 78 | data: null, 79 | }); 80 | } 81 | }); 82 | }; 83 | 84 | // 添加帮助文章 85 | help.add = async function(req, res, next) { 86 | const title = req.body.title; 87 | const content = req.body.content; 88 | const type = req.body.type; 89 | const createdAt = new Date().getTime(); 90 | const sql = `insert into help_articles(type,title,content,created_at) 91 | values(?,?,?,?)`; 92 | const result = await query(sql, null, [type, title, content, createdAt], '新增帮助文章'); 93 | if (!result.fail && result instanceof Object) { 94 | req.body.data = result.insertId; 95 | req.body.code = '10000'; 96 | req.body.message = '操作成功'; 97 | req.body.success = true; 98 | // 记录操作日志 99 | req.body.log = Object.assign(req.body.log || {}, { 100 | client: 1, 101 | content: `添加了ID为${result.insertId}的帮助文章`, 102 | }); 103 | return next(); 104 | } else { 105 | return res.json({ code: '10001', message: result.message, success: false, data: null }); 106 | } 107 | } 108 | 109 | // 更新帮助文章 110 | help.update = async function(req, res, next) { 111 | const id = req.body.id; 112 | const title = req.body.title; 113 | const content = req.body.content; 114 | const type = req.body.type; 115 | const updated_at = new Date().getTime(); 116 | const sql = `update help_articles set type=?,title=?,content=?,updated_at=? where id=?;`; 117 | const result = await query(sql, null, [type, title, content, updated_at, id], '更新帮助文章'); 118 | if (!result.fail && result.affectedRows) { 119 | req.body.data = true; 120 | req.body.code = '10000'; 121 | req.body.message = '操作成功'; 122 | req.body.success = true; 123 | // 记录操作日志 124 | req.body.log = Object.assign(req.body.log || {}, { 125 | client: 1, 126 | content: `更新了ID为${id}的帮助文章`, 127 | }); 128 | return next(); 129 | } else { 130 | return res.json({ code: '10001', message: result.message, success: false, data: null }); 131 | } 132 | } 133 | 134 | // 删除帮助文章 135 | help.remove = async function(req, res, next) { 136 | const id = req.body.id; 137 | const updated_at = new Date().getTime(); 138 | const sql = `update help_articles set deleted=1,updated_at=? where id=?`; 139 | const result = await query(sql, null, [updated_at, id], '删除帮助文章'); 140 | if (!result.fail && result.affectedRows) { 141 | req.body.data = true; 142 | req.body.code = '10000'; 143 | req.body.message = '操作成功'; 144 | req.body.success = true; 145 | // 记录操作日志 146 | req.body.log = Object.assign(req.body.log || {}, { 147 | client: 1, 148 | content: `删除了ID为${id}的帮助文章`, 149 | }); 150 | return next(); 151 | } else { 152 | return res.json({ code: '10001', message: result.message, success: false, data: null }); 153 | } 154 | } 155 | 156 | // 分类列表 157 | help.typeList = async function(req, res, next) { 158 | const sql = `SELECT * FROM help_type order by created_at desc`; 159 | const result = await query(sql, null, null, '查询帮助文章分类'); 160 | if (!result.fail && result instanceof Array) { 161 | req.body.data = result; 162 | req.body.code = '10000'; 163 | req.body.message = '操作成功'; 164 | req.body.success = true; 165 | return next(); 166 | } else { 167 | return res.json({ code: '10001', message: '', success: false, data: 'err' }); 168 | } 169 | } 170 | 171 | // 删除分类 172 | help.removeType = function(req, res, next) { 173 | const id = req.body.id; 174 | // 先查找是否有帮助文章在使用此分类 175 | const checkSql = `select count(*) from help_articles where type=${id} and deleted=0`; 176 | const sql = `delete from help_type where id=${id}`; 177 | console.info('删除帮助文章分类', sql); 178 | query(checkSql, (helpErr, helpVals) => { 179 | console.info('查询分类下的帮助文章数返回', helpVals); 180 | if (!helpErr && helpVals instanceof Array) { 181 | if (helpVals[0]['count(*)'] > 0) { 182 | return res.json({ code: '10001', message: '删除失败,有帮助文章在使用此分类', success: false, data: null }); 183 | } else { 184 | query(sql, (err, vals) => { 185 | console.info('删除帮助文章分类返回', vals); 186 | if (!err && vals instanceof Object) { 187 | req.body.data = vals; 188 | req.body.code = '10000'; 189 | req.body.message = '操作成功'; 190 | req.body.success = true; 191 | // 记录操作日志 192 | req.body.log = Object.assign(req.body.log || {}, { 193 | client: 1, 194 | content: `删除了ID为${id}的帮助文章分类`, 195 | }); 196 | return next(); 197 | } else { 198 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 199 | } 200 | }); 201 | } 202 | } 203 | }); 204 | 205 | } 206 | 207 | // 添加分类 208 | help.addType = function(req, res, next) { 209 | const name = req.body.name; 210 | const created_at = new Date().getTime(); 211 | const sql = `insert into help_type(name, created_at) values("${name}","${created_at}")`; 212 | console.info('添加分类', sql); 213 | query(sql, (err, vals) => { 214 | console.info('添加分类返回', vals, err); 215 | if (!err && vals instanceof Object) { 216 | req.body.data = vals.insertId; 217 | req.body.code = '10000'; 218 | req.body.message = '操作成功'; 219 | req.body.success = true; 220 | // 记录操作日志 221 | req.body.log = Object.assign(req.body.log || {}, { 222 | client: 1, 223 | content: `添加了ID为${vals.insertId}的帮助文章分类`, 224 | }); 225 | return next(); 226 | } else { 227 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 228 | } 229 | }); 230 | } 231 | 232 | // 更新分类 233 | help.updateType = function(req, res, next) { 234 | const id = req.body.id; 235 | const name = req.body.name; 236 | const updated_at = new Date().getTime(); 237 | const sql = `update help_type set name="${name}",updated_at="${updated_at}" where id=${id}`; 238 | console.info('更新帮助文章分类', sql); 239 | query(sql, (err, vals) => { 240 | console.info('更新帮助文章分类返回', vals, err); 241 | if (!err && vals instanceof Object) { 242 | req.body.data = vals; 243 | req.body.code = '10000'; 244 | req.body.message = '操作成功'; 245 | req.body.success = true; 246 | // 记录操作日志 247 | req.body.log = Object.assign(req.body.log || {}, { 248 | client: 1, 249 | content: `更新了ID为${id}的帮助文章分类`, 250 | }); 251 | return next(); 252 | } else { 253 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 254 | } 255 | }); 256 | } -------------------------------------------------------------------------------- /middlewares/refresh.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const refresh = {}; 9 | exports.refresh = refresh; 10 | 11 | // 获取价格表 12 | refresh.list = function(req, res, next) { 13 | var param = req.body; 14 | //分页实现 15 | var currentPage = 1; //默认为1 16 | var size = 10; //每页条数 17 | if (param.page) { 18 | currentPage = parseInt(param.page); 19 | } 20 | if (param.size) { 21 | size = parseInt(param.size); 22 | } 23 | //设置最后一页页码 24 | var lastPage = currentPage - 1; 25 | //假如目前仅有一页,则最后一页则为1 26 | if (currentPage <= 1) { 27 | lastPage = 1; 28 | } 29 | //如果需要下一页,则开启 30 | //var nextPage = currentPage + 1; 31 | var offset = (currentPage - 1) * size; 32 | var sql = `SELECT COUNT(*) FROM refresh_price where deleted=0; 33 | select * FROM refresh_price where deleted=0 34 | order by count desc limit ${size} offset ${offset}`; 35 | 36 | console.info('查询管理员', sql);; 37 | query(sql, (err, vals) => { 38 | if (!err && vals instanceof Array) { 39 | const totalCount = vals[0][0]['COUNT(*)']; 40 | const totalPage = Math.ceil(parseInt(totalCount) / size); 41 | req.body.data = { 42 | list: vals[1], 43 | size: size, 44 | page: currentPage, 45 | totalPage: totalPage, 46 | totalCount: totalCount, 47 | }; 48 | req.body.code = '10000'; 49 | req.body.message = '操作成功'; 50 | req.body.success = true; 51 | return next(); 52 | } else { 53 | return res.json({ 54 | code: '10001', 55 | message: err, 56 | success: false, 57 | data: null, 58 | }); 59 | } 60 | }); 61 | }; 62 | 63 | // 添加刷新价格 64 | refresh.add = function(req, res, next) { 65 | const original_price = req.body.original_price; 66 | const price = req.body.price; 67 | const count = req.body.count; 68 | const is_show = req.body.is_show; 69 | const created_at = new Date().getTime(); 70 | const sql = `insert into refresh_price(original_price,price,count,is_show,created_at) values(${original_price},${price},${count},${is_show},"${created_at}")`; 71 | console.info("添加刷新价格", sql); 72 | query(sql, (err, vals) => { 73 | if (!err && vals instanceof Object) { 74 | req.body.data = vals.insertId; 75 | req.body.code = '10000'; 76 | req.body.message = '操作成功'; 77 | req.body.success = true; 78 | // 记录操作日志 79 | req.body.log = Object.assign(req.body.log || {}, { 80 | client: 1, 81 | content: `添加了ID为${vals.insertId}的刷新套餐`, 82 | }); 83 | return next(); 84 | } else { 85 | return res.json({ code: '10001', message: err, success: false, data: null }); 86 | } 87 | }) 88 | } 89 | 90 | // 修改刷新价格 91 | refresh.update = function(req, res, next) { 92 | const id = req.body.id; 93 | const original_price = req.body.original_price; 94 | const price = req.body.price; 95 | const count = req.body.count; 96 | const is_show = req.body.is_show; 97 | const updated_at = new Date().getTime(); 98 | const sql = `update refresh_price set original_price=${original_price},price=${price},count=${count},is_show=${is_show},updated_at="${updated_at}" where id=${id}`; 99 | console.info("修改刷新价格", sql); 100 | query(sql, (err, vals) => { 101 | if (!err && vals.affectedRows) { 102 | req.body.data = true; 103 | req.body.code = '10000'; 104 | req.body.message = '操作成功'; 105 | req.body.success = true; 106 | // 记录操作日志 107 | req.body.log = Object.assign(req.body.log || {}, { 108 | client: 1, 109 | content: `修改了ID为${id}的刷新套餐`, 110 | }); 111 | return next(); 112 | } else { 113 | return res.json({ code: '10001', message: err, success: false, data: null }); 114 | } 115 | }) 116 | } 117 | 118 | // 删除刷新价格 119 | refresh.remove = function(req, res, next) { 120 | const id = req.body.id; 121 | const updated_at = new Date().getTime(); 122 | const sql = `update refresh_price set deleted=1,updated_at="${updated_at}" where id=${id}`; 123 | console.info("删除刷新价格", sql); 124 | query(sql, (err, vals) => { 125 | if (!err && vals instanceof Object) { 126 | req.body.data = true; 127 | req.body.code = '10000'; 128 | req.body.message = '操作成功'; 129 | req.body.success = true; 130 | // 记录操作日志 131 | req.body.log = Object.assign(req.body.log || {}, { 132 | client: 1, 133 | content: `删除了ID为${id}的刷新套餐`, 134 | }); 135 | return next(); 136 | } else { 137 | return res.json({ code: '10001', message: err, success: false, data: null }); 138 | } 139 | }) 140 | } 141 | 142 | // 用户付费购买刷新次数 143 | refresh.buy = function(req, res, next) { 144 | const id = req.body.id; 145 | const user_id = req.body.user_id; 146 | const created_at = new Date().getTime(); 147 | const sql = `begin; 148 | update users set refresh_count=refresh_count+(select count from refresh_price where id=${id}), 149 | account_amount=account_amount-(select price from refresh_price where id=${id}) where id=${user_id}; 150 | insert into money_stream(type,money,balance,user_id,is_income,created_at,remark) 151 | values(4,(select price from refresh_price where id=${id}),(select account_amount from users where id=${user_id}),${user_id},0,"${created_at}","购买任务刷新次数"); 152 | commit`; 153 | console.info("用户付费购买刷新次数", sql); 154 | query(sql, (err, vals) => { 155 | if (!err && vals instanceof Object) { 156 | req.body.data = true; 157 | req.body.code = '10000'; 158 | req.body.message = '操作成功'; 159 | req.body.success = true; 160 | return next(); 161 | } else { 162 | return res.json({ code: '10001', message: err, success: false, data: null }); 163 | } 164 | }) 165 | } 166 | 167 | // 付费刷新 168 | refresh.do = function(req, res, next) { 169 | const id = req.body.id; 170 | const user_id = req.body.user_id; 171 | const sql = `begin; 172 | update tasks set sort=( 173 | select ub.newsort from ( 174 | select (MAX(ua.sort)+1) newsort from tasks ua where ua.id=${id} and ua.created_by=${user_id} 175 | ) ub 176 | ) where id=${id} and created_by=${user_id} and (select refresh_count from users where id=${user_id}) > 0; 177 | update users set refresh_count=refresh_count-1 where id=${user_id} and refresh_count>0; 178 | commit`; 179 | console.info('付费刷新', sql); 180 | query(sql, (err, vals) => { 181 | console.info('付费刷新返回', vals, err); 182 | if (!err && vals instanceof Object) { 183 | req.body.data = true; 184 | req.body.code = '10000'; 185 | req.body.message = '操作成功'; 186 | req.body.success = true; 187 | return next(); 188 | } else { 189 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 190 | } 191 | }); 192 | } 193 | 194 | // 推荐上首页 195 | refresh.recommend = function(req, res, next) { 196 | const id = req.body.id; 197 | const user_id = req.body.user_id; 198 | const time = req.body.time; 199 | const money = req.body.money; 200 | if (money <= 0) { 201 | return res.json({ code: '10010', message: '金额不合法', success: false, data: money }); 202 | } 203 | const now = new Date().getTime(); 204 | const sql = `begin; 205 | update tasks set recommend=1,recommend_timeout="${time}" 206 | where id=${id} 207 | and (select account_amount from users where id=${user_id}) >= ${money}; 208 | update users set account_amount=account_amount-${money} where id=${user_id} and account_amount>=${money}; 209 | insert into money_stream(type,money,balance,user_id,is_income,created_at,remark) 210 | values(4,${money},(select account_amount from users where id=${user_id}),${user_id},0,"${now}","推荐任务上首页"); 211 | commit`; 212 | console.info('推荐上首页', sql); 213 | query(sql, (err, vals) => { 214 | console.info('推荐上首页返回', vals, err); 215 | if (!err && vals instanceof Object) { 216 | req.body.data = true; 217 | req.body.code = '10000'; 218 | req.body.message = '操作成功'; 219 | req.body.success = true; 220 | return next(); 221 | } else { 222 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 223 | } 224 | }); 225 | } 226 | 227 | // 任务置顶 228 | refresh.top = function(req, res, next) { 229 | const id = req.body.id; 230 | const user_id = req.body.user_id; 231 | const time = req.body.time; 232 | const money = req.body.money; 233 | if (money <= 0) { 234 | return res.json({ code: '10010', message: '金额不合法', success: false, data: money }); 235 | } 236 | const now = new Date().getTime(); 237 | const sql = `begin; 238 | update tasks set top_timeout="${time}" 239 | where id=${id} 240 | and (select account_amount from users where id=${user_id}) >= ${money}; 241 | update users set account_amount=account_amount-${money} where id=${user_id} and account_amount>=${money}; 242 | insert into money_stream(type,money,balance,user_id,is_income,created_at,remark) 243 | values(4,${money},(select account_amount from users where id=${user_id}),${user_id},0,"${now}","任务置顶"); 244 | commit`; 245 | console.info('任务置顶', sql); 246 | query(sql, (err, vals) => { 247 | console.info('任务置顶返回', vals, err); 248 | if (!err && vals instanceof Object) { 249 | req.body.data = true; 250 | req.body.code = '10000'; 251 | req.body.message = '操作成功'; 252 | req.body.success = true; 253 | return next(); 254 | } else { 255 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 256 | } 257 | }); 258 | } -------------------------------------------------------------------------------- /utils/wepay.js: -------------------------------------------------------------------------------- 1 | var xmlreader = require('xmlreader'); 2 | let xml2js = require('xml2js'); 3 | let fs = require('fs'); 4 | const request = require('request'); 5 | const query = require('../utils/pool'); 6 | const config = require('../config/index'); 7 | const { userInfo } = require('os'); 8 | 9 | var wepay = { 10 | // 把json转为xml 11 | json2Xml: function (json) { 12 | let _xml = ''; 13 | Object.keys(json).map((key) => { 14 | _xml += `<${key}>${json[key]}`; 15 | }); 16 | return `${_xml}`; 17 | }, 18 | //把金额转为分 19 | getmoney: function (money) { 20 | return Math.floor(parseFloat(money) * 100); 21 | }, 22 | 23 | // 随机字符串产生函数 24 | createNonceStr: function () { 25 | return Math.random().toString(36).substr(2, 15); 26 | }, 27 | 28 | // 时间戳产生函数 29 | createTimeStamp: function () { 30 | return parseInt(new Date().getTime() / 1000) + ''; 31 | }, 32 | 33 | //签名加密算法 34 | paysignjsapi: function ( 35 | appid, 36 | body, 37 | mch_id, 38 | nonce_str, 39 | notify_url, 40 | openid, 41 | out_trade_no, 42 | spbill_create_ip, 43 | total_fee, 44 | trade_type, 45 | mchkey, 46 | ) { 47 | var ret = { 48 | appid: appid, 49 | mch_id: mch_id, 50 | nonce_str: nonce_str, 51 | body: body, 52 | notify_url: notify_url, 53 | out_trade_no: out_trade_no, 54 | spbill_create_ip: spbill_create_ip, 55 | total_fee: total_fee, 56 | trade_type: trade_type, 57 | }; 58 | if (openid) { 59 | ret.openid = openid; 60 | } 61 | console.log('ret==', ret); 62 | var string = raw(ret); 63 | var key = mchkey; 64 | string = string + '&key=' + key; 65 | console.log('string=', string); 66 | var crypto = require('crypto'); 67 | return crypto 68 | .createHash('md5') 69 | .update(string, 'utf8') 70 | .digest('hex') 71 | .toUpperCase(); 72 | }, 73 | // 小程序签名 74 | paysignjsapimini: function ( 75 | appId, 76 | nonceStr, 77 | package, 78 | signType, 79 | timestamp, 80 | mchkey, 81 | ) { 82 | var ret = { 83 | appId: appId, 84 | nonceStr: nonceStr, 85 | package: package, 86 | signType: signType, 87 | timeStamp: timestamp, 88 | }; 89 | console.log('Miniret==', ret); 90 | var string = raw(ret); 91 | var key = mchkey; 92 | string = string + '&key=' + key; 93 | console.log('Ministring>>>>>>', string); 94 | var crypto = require('crypto'); 95 | return crypto 96 | .createHash('md5') 97 | .update(string, 'utf8') 98 | .digest('hex') 99 | .toUpperCase(); 100 | }, 101 | // app签名 102 | paysignjsapiapp: function ( 103 | appid, 104 | partnerid, 105 | prepayid, 106 | noncestr, 107 | timestamp, 108 | package, 109 | mchkey, 110 | ) { 111 | var ret = { 112 | appid: appid, 113 | partnerid: partnerid, 114 | prepayid: prepayid, 115 | noncestr: noncestr, 116 | timestamp: timestamp, 117 | package: package, 118 | }; 119 | console.log('Miniret==', ret); 120 | var string = raw(ret); 121 | var key = mchkey; 122 | string = string + '&key=' + key; 123 | console.log('Ministring>>>>>>', string); 124 | var crypto = require('crypto'); 125 | return crypto 126 | .createHash('md5') 127 | .update(string, 'utf8') 128 | .digest('hex') 129 | .toUpperCase(); 130 | }, 131 | getXMLNodeValue: function (xml) { 132 | xmlreader.read(xml, function (errors, response) { 133 | if (null !== errors) { 134 | console.log(errors); 135 | return; 136 | } 137 | console.log('长度===', response.xml.prepay_id.text().length); 138 | var prepay_id = response.xml.prepay_id.text(); 139 | console.log('解析后的prepay_id==', prepay_id); 140 | return prepay_id; 141 | }); 142 | }, 143 | // 以下是企业付款到微信余额相关方法 144 | /*生成url串用于微信md5校验*/ 145 | fnCreateUrlParam: function (json) { 146 | let _arr = []; 147 | for (let key in json) { 148 | _arr.push(key + '=' + json[key]); 149 | } 150 | return _arr.join('&'); 151 | }, 152 | /*生成付款xml参数数据*/ 153 | fnGetWeixinBonus: function (option) { 154 | console.log('option===', option); 155 | let amount = option.amount || 100; //红包总金额 156 | let openid = option.openid; // '可以修改成你自己的openid,这样如果出错就会发送到你的账户上面了';//红包发送的目标用户 157 | let openid_type = option.openid_type; 158 | let now = new Date(); 159 | let clientIp = option.clientIp; //ip地址 160 | let desc = option.wishing; //企业付款备注 161 | let mch_id = config.wechat.mchId; //商户号 162 | let mch_appid = ''; //appid 163 | switch (Number(openid_type)) { 164 | case 1: 165 | // 小程序 166 | mch_appid = config.wechat.appId; 167 | break; 168 | case 2: 169 | // 公众号 170 | mch_appid = config.wechat.officialAccount.appId; 171 | break; 172 | case 3: 173 | // APP 174 | mch_appid = config.wechat.open.appId; 175 | break; 176 | default: 177 | // 此配置是旧版本遗留 178 | mch_appid = config.wechat.mchAppId; 179 | break; 180 | } 181 | let wxkey = config.wechat.mchKey; //key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 182 | let date_time = 183 | now.getFullYear() + '' + (now.getMonth() + 1) + '' + now.getDate(); 184 | let date_no = (now.getTime() + '').substr(-8); //生成8为日期数据,精确到毫秒 185 | let random_no = Math.floor(Math.random() * 99); 186 | if (random_no < 10) { 187 | //生成位数为2的随机码 188 | random_no = '0' + random_no; 189 | } 190 | 191 | let nonce_str = Math.random().toString(36).substr(2, 15); //生成随机字符串 192 | let partner_trade_no = mch_id + date_time + date_no + random_no; //生成商户订单号 193 | 194 | let contentJson = {}; 195 | contentJson.amount = amount; // '100'; 196 | contentJson.check_name = 'NO_CHECK'; // '强制验证名字';FORCE_CHECK 197 | contentJson.desc = desc; //'恭喜发财'; 198 | contentJson.mch_appid = mch_appid; //商户appid 199 | contentJson.mchid = mch_id; 200 | contentJson.nonce_str = nonce_str; 201 | contentJson.openid = openid; // 'oovyt4u9yTamaCAxlZ-U2HjH-Z'; //墨色梧桐的openid // 'oovyt4u9yTamaCAxlZ-U2HjH-Z'; 202 | contentJson.partner_trade_no = partner_trade_no; //订单号为 mch_id + yyyymmdd+10位一天内不能重复的数字; //+201502041234567893'; 203 | contentJson.spbill_create_ip = clientIp; //IP地址 204 | contentJson.key = wxkey; //微信安全密钥 205 | 206 | /*生成url串用于微信md5校验*/ 207 | let contentStr = wepay.fnCreateUrlParam(contentJson); 208 | console.log('content=' + contentStr); 209 | //生成签名 210 | let crypto = require('crypto'); 211 | contentJson.sign = crypto 212 | .createHash('md5') 213 | .update(contentStr, 'utf8') 214 | .digest('hex') 215 | .toUpperCase(); 216 | 217 | //删除 contentJson对象中的key (key不参与签名) 218 | delete contentJson.key; 219 | //生成xml函数 220 | let xmlData = wepay.json2Xml(contentJson); 221 | return xmlData; 222 | }, 223 | //微信企业支付到零钱中间件 224 | wxcompay: async (req, res, next) => { 225 | let id = req.body.id; // 提现列表的ID 226 | let amount = req.body.money; //金额 227 | let openid = req.body.openid; 228 | let openid_type = req.body.openid_type; 229 | let user_id = req.body.userId; 230 | let wishing = req.body.wishing || `${id}:用户${user_id}提现到余额`; // 备注 231 | let clientIp = 232 | req.body.clientIp || req.ip.match(/\d+\.\d+\.\d+\.\d+/) || '127.0.0.1'; 233 | const result = await query('select pay_to_wechat from system'); 234 | if (result instanceof Object) { 235 | if (result[0].pay_to_wechat && openid) { 236 | if (!(user_id && amount)) { 237 | return res.json({ code: '10001', message: '参数不正确', success: false, data: null}); 238 | } 239 | } else { 240 | return next(); 241 | } 242 | } 243 | // 提现金额精确到角 244 | amount = Number(amount).toFixed(1); 245 | // 按微信要求转化成分 246 | amount = amount * 100; 247 | // 解决js浮点运算问题 248 | amount = amount.toFixed(); 249 | let sendData = wepay.fnGetWeixinBonus({ 250 | amount: Number(amount), 251 | openid, 252 | openid_type, 253 | wishing, 254 | clientIp, 255 | }); 256 | let now = new Date().getTime(); 257 | console.log('付款到余额sendData=====', sendData); 258 | //读取微信生成的证书用作加密 259 | let opt = { 260 | url: 261 | 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers', 262 | body: sendData, 263 | key: fs.readFileSync(`${process.cwd()}/key/apiclient_key.pem`), //将微信生成的证书放入 cert目录下 264 | cert: fs.readFileSync(`${process.cwd()}/key/apiclient_cert.pem`), 265 | }; 266 | request.post(opt, function (err, response, body) { 267 | console.log('付款到余额err==', err); 268 | console.log('付款到余额body==', body); 269 | let parser = new xml2js.Parser({ 270 | trim: true, 271 | explicitArray: false, 272 | explicitRoot: false, 273 | }); //解析签名结果xml转json 274 | parser.parseString(body, async (error, result) => { 275 | console.log('付款到余额res==', result); 276 | if (result && result.result_code == 'SUCCESS') { 277 | await query(`insert into orders(order_id,user_id,paid,money,created_at,direction) 278 | values('${result.partner_trade_no}',${user_id},1,${amount},'${now}',2)`); 279 | return next(); 280 | } else { 281 | return res.json({ 282 | code: '10016', 283 | message: result.err_code_des, 284 | success: false, 285 | data: result, 286 | }); 287 | } 288 | }); 289 | }); 290 | }, 291 | }; 292 | function raw(args) { 293 | var keys = Object.keys(args); 294 | keys = keys.sort(); 295 | var newArgs = {}; 296 | keys.forEach(function(key) { 297 | newArgs[key] = args[key]; 298 | }); 299 | var string = ''; 300 | for (var k in newArgs) { 301 | string += '&' + k + '=' + newArgs[k]; 302 | } 303 | string = string.substr(1); 304 | return string; 305 | } 306 | 307 | module.exports = wepay; 308 | -------------------------------------------------------------------------------- /middlewares/statistics.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const statistics = {}; 9 | exports.statistics = statistics; 10 | 11 | // 统计当前用户各个状态的任务数量 12 | statistics.getTaskCount = function(req, res, next) { 13 | console.info("统计当前用户各个状态的任务数量"); 14 | // 用户ID查询条件 15 | const userId = req.body.userId; 16 | // 发布人ID查询条件 17 | const creatorId = req.body.creatorId; 18 | // 任务状态查询条件 19 | const taskStatus = req.body.taskStatus; 20 | const sql = `SELECT COUNT(*) FROM user_tasks where deleted=0 and ${creatorId?`created_by=${creatorId}`:`user_id=${userId}`}${taskStatus ? ` and status = ${taskStatus}` : ''};` 21 | query(sql, (err, vals) => { 22 | if (!err && vals instanceof Array) { 23 | console.info('统计当前用户各个状态的任务数量', vals) 24 | if (req.body.data instanceof Object) { 25 | req.body.data.taskCount = vals[0]['COUNT(*)'] 26 | } else { 27 | req.body.data = { 28 | taskCount: vals[0]['COUNT(*)'] 29 | } 30 | } 31 | req.body.code = '10000'; 32 | req.body.message = '操作成功'; 33 | req.body.success = true; 34 | return next(); 35 | } else { 36 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 37 | } 38 | }) 39 | } 40 | // 统计当前用户指定状态下任务的总金额 41 | statistics.getMoneyByTaskStatus = function(req, res, next) { 42 | console.info("统计当前用户指定状态下任务的总金额"); 43 | // 用户ID查询条件 44 | const userId = req.body.userId; 45 | // 发布人ID查询条件 46 | const creatorId = req.body.creatorId; 47 | // 任务状态查询条件 48 | let taskStatus = req.body.taskStatus; 49 | taskStatus = taskStatus.split(','); 50 | let taskStatusSql = ''; 51 | if (taskStatus.length > 1){ 52 | // 如果是数组,即查询多个状态下的数据 53 | taskStatusSql = ' and ('; 54 | taskStatus.map((item, index)=>{ 55 | const isLastOne = index === taskStatus.length-1; 56 | taskStatusSql += `status = ${item} ${isLastOne ? '' : 'or '}` 57 | }); 58 | taskStatusSql += ')'; 59 | } else { 60 | // 只有一个元素的数组 61 | taskStatusSql = ` and status = ${taskStatus[0]}`; 62 | } 63 | 64 | const sql = `select sum(money) 65 | from user_tasks where 66 | ${creatorId?`created_by=${creatorId}`:`user_id=${userId}`} and deleted=0 67 | ${taskStatusSql}` 68 | console.info(sql); 69 | query(sql, (err, vals) => { 70 | if (!err && vals instanceof Array) { 71 | console.info('统计当前用户未完成任务的总金额', vals) 72 | if (req.body.data instanceof Object) { 73 | req.body.data.money = vals[0]['sum(money)'] 74 | } else { 75 | req.body.data = { 76 | money: vals[0]['sum(money)'] 77 | } 78 | } 79 | req.body.code = '10000'; 80 | req.body.message = '操作成功'; 81 | req.body.success = true; 82 | return next(); 83 | } else { 84 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 85 | } 86 | }) 87 | } 88 | // 统计当前用户金额数据 89 | statistics.getUserMoneyStatistics = function(req, res, next) { 90 | const userId = req.body.userId; 91 | const sql = `select sum(money) from money_stream where user_id=${userId} and type=1; 92 | select sum(money) from money_stream where user_id=${userId} and type=4; 93 | select sum(money) from money_stream where user_id=${userId} and type=3; 94 | select sum(money) from withdraw_money where status=2 and user_id=${userId}; 95 | select sum(account_amount) from users where id=${userId}; 96 | select sum(money) from money_stream where user_id=${userId} and type=3 and DATE_FORMAT(FROM_UNIXTIME(created_at/1000),'%Y-%m-%d') = DATE_FORMAT(NOW(),'%Y-%m-%d'); 97 | select sum(money) from money_stream where user_id=${userId} and type=3 and DATEDIFF(now(), FROM_UNIXTIME(created_at/1000)) = 1; 98 | select sum(money) as totalTaskIncome from user_tasks where user_id=${userId} and status=3; 99 | select sum(money) as totalTaskExpend from user_tasks where created_by=${userId} and status=3;` 100 | query(sql, (err, vals, fields) => { 101 | if (!err && vals instanceof Array) { 102 | console.info('获取用户金额数据返回', vals); 103 | req.body.data = { 104 | taskTotalRechargeSum: +vals[0][0]['sum(money)'], // 总充值金额 105 | taskTotalPaySum: +vals[1][0]['sum(money)'], // 总发放佣金 106 | totalIncomeSum: +vals[2][0]['sum(money)'], // 总收入佣金 107 | withdrawTotalMoney: +vals[3][0]['sum(money)'], // 总提现金额 108 | userTotalMoney: +vals[4][0]['sum(account_amount)'], // 未提现总金额 109 | todayIncomeSum: +vals[5][0]['sum(money)'], // 今天收益 110 | yesterdayIncomeSum: +vals[6][0]['sum(money)'], // 昨天收益 111 | totalTaskIncome: +vals[7][0]['totalTaskIncome'], // 总获得的任务佣金 112 | totalTaskExpend: +vals[8][0]['totalTaskExpend'], // 总发放的任务佣金,不含服务费 113 | }; 114 | req.body.code = '10000'; 115 | req.body.message = '操作成功'; 116 | req.body.success = true; 117 | return next(); 118 | } else { 119 | console.info('获取用户金额数据出错', err); 120 | return res.json({ code: '10001', message: err.code, success: false, data: err }); 121 | } 122 | }) 123 | } 124 | // 获取任务完成最多的十个用户 125 | statistics.getUserRankList = function(req, res, next) { 126 | query( `select u.id,u.nick_name,u.avatar,u.username,count(t.task_id) as task_count 127 | from users u left join user_tasks t on t.user_id = u.id 128 | where t.status = 3 and t.deleted=0 group by u.id order by task_count desc limit 10`, 129 | (err, vals, fields) => { 130 | if (!err && vals instanceof Array) { 131 | req.body.data = vals; 132 | req.body.code = '10000'; 133 | req.body.message = '操作成功'; 134 | req.body.success = true; 135 | return next(); 136 | } else { 137 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 138 | } 139 | }) 140 | }; 141 | // 获取邀请最多的十个用户 142 | statistics.getInviteRankList = function(req, res, next) { 143 | query( `select count(u.id) as count,u.inviter,s.avatar,s.username,s.nick_name from users u left join users s on s.id=u.inviter where u.inviter is not null GROUP BY u.inviter order by count desc limit 10`, 144 | (err, vals, fields) => { 145 | if (!err && vals instanceof Array) { 146 | req.body.data = vals; 147 | req.body.code = '10000'; 148 | req.body.message = '操作成功'; 149 | req.body.success = true; 150 | return next(); 151 | } else { 152 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 153 | } 154 | }) 155 | }; 156 | 157 | // 获取后台仪表盘统计 158 | statistics.getDashboardData = function(req, res, next) { 159 | const sql = `select count(*) from user_reviews where status=1 and deleted=0 and task_creator in (select id from administrators); 160 | select count(*) from withdraw_money where status=1; 161 | select count(*) from users where DATE_FORMAT(FROM_UNIXTIME(created_at/1000),'%Y-%m-%d') = DATE_FORMAT(NOW(),'%Y-%m-%d'); 162 | select count(*) from user_reviews where status=2 and deleted=0 and DATE_FORMAT(FROM_UNIXTIME(updated_at/1000),'%Y-%m-%d') = DATE_FORMAT(NOW(),'%Y-%m-%d'); 163 | select sum(t.money) from user_reviews u left join user_tasks t on t.task_id = u.task_id where u.status=2 and u.deleted=0 and u.task_creator in (select id from administrators) and DATE_FORMAT(FROM_UNIXTIME(u.updated_at/1000),'%Y-%m-%d') = DATE_FORMAT(NOW(),'%Y-%m-%d'); 164 | select count(*) from users where deleted=0; 165 | select count(*) from tasks where deleted=0; 166 | select sum(t.money) from user_reviews u left join user_tasks t on t.task_id = u.task_id where u.status=2 and u.deleted=0 and u.task_creator in (select id from administrators); 167 | select sum(money) from withdraw_money where status=2; 168 | select sum(account_amount) from users; 169 | select count(*) from user_tasks where status=3 and deleted=0; 170 | select count(*) from user_tasks where status=1 and deleted=0; 171 | select count(*) from user_tasks where status=2 and deleted=0; 172 | select count(*) from user_tasks where status=4 and deleted=0; 173 | select count(*) from user_tasks where status=5 and deleted=0; 174 | select count(*) from user_tasks where deleted=0; 175 | select count(*) from certifications where status=0; 176 | select count(*) from users where deleted=0 and is_vip=1; 177 | select sum(money) from money_stream where is_income=1; 178 | select count(*) from tasks where status=3 and deleted=0; 179 | select sum(service_price) from tasks where DATE_FORMAT(FROM_UNIXTIME(created_at/1000),'%Y-%m-%d') = DATE_FORMAT(NOW(),'%Y-%m-%d'); 180 | select sum(account_amount+finished_amount+withdraw_amount) from users; 181 | select sum(money) from money_stream where is_income=0; 182 | select count(*) from users where is_certified=1; 183 | select sum(score) from users;`; 184 | query(sql, (err, vals, fields) => { 185 | if (!err && vals instanceof Array) { 186 | console.info('获取数据统计返回', vals); 187 | req.body.data = { 188 | taskTobeReviewCount: +vals[0][0]['count(*)'], // 任务待审核数 189 | withdrawTobeReviewCount: +vals[1][0]['count(*)'], // 提现待审核数 190 | todayNewUserCount: +vals[2][0]['count(*)'], // 今日新增用户数 191 | todayTaskFinishCount: +vals[3][0]['count(*)'], // 今日完成任务数 192 | todayTaskPaySum: +vals[4][0]['sum(t.money)'], // 官方今日发放佣金 193 | userTotalCount: +vals[5][0]['count(*)'], // 用户总数 194 | taskTotalCount: +vals[6][0]['count(*)'], // 任务总数 195 | taskTotalPaySum: +vals[7][0]['sum(t.money)'], // 官方总发放佣金 196 | withdrawTotalMoney: +vals[8][0]['sum(money)'], // 总提现金额 197 | userTotalMoney: +vals[9][0]['sum(account_amount)'], // 未提现总金额 198 | finishTaskTotalCount: +vals[10][0]['count(*)'], // 完成任务总数 199 | onGoingTaskCount: +vals[11][0]['count(*)'], // 进行中的任务总数 200 | onReviewingTaskCount: +vals[12][0]['count(*)'], // 审核中的任务总数 201 | expiredTaskCount: +vals[13][0]['count(*)'], // 过期的任务总数 202 | rejectTaskCount: +vals[14][0]['count(*)'], // 审核失败的任务总数 203 | grabTaskCount: +vals[15][0]['count(*)'], // 领取的任务总数 204 | certificationTobeReviewCount: +vals[16][0]['count(*)'], // 认证待审核数量 205 | vipUserTotalCount: +vals[17][0]['count(*)'], // 会员总数 206 | totalIncome: +vals[18][0]['sum(money)'], // 平台总收入 207 | onSellReviewCount: +vals[19][0]['count(*)'], // 待审核上架 208 | todayServicePrice: +vals[20][0]['sum(service_price)'], // 今日任务佣金 209 | totalMoney: +vals[21][0]['sum(account_amount+finished_amount+withdraw_amount)'], // 平台总金额(包括已提现,提现中,用户账户中) 210 | totalOutcome: +vals[22][0]['sum(money)'], // 平台总支出 211 | totalCertifiedUser: +vals[23][0]['count(*)'], // 总实名认证人数 212 | totalUserScore: +vals[24][0]['sum(score)'], // 平台总积分 213 | }; 214 | req.body.code = '10000'; 215 | req.body.message = '操作成功'; 216 | req.body.success = true; 217 | return next(); 218 | } else { 219 | console.info('获取数据统计出错', err); 220 | return res.json({ code: '10001', message: err.code, success: false, data: err }); 221 | } 222 | }) 223 | } -------------------------------------------------------------------------------- /middlewares/messages.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const messages = {}; 9 | exports.messages = messages; 10 | 11 | // 获取公告 12 | messages.getNoticeList = function(req, res, next) { 13 | var param = req.body; 14 | //分页实现 15 | var currentPage = 1; //默认为1 16 | var size = 10; //每页条数 17 | if (param.page) { 18 | currentPage = parseInt(param.page); 19 | } 20 | if (param.size) { 21 | size = parseInt(param.size); 22 | } 23 | //设置最后一页页码 24 | var lastPage = currentPage - 1; 25 | //假如目前仅有一页,则最后一页则为1 26 | if (currentPage <= 1) { 27 | lastPage = 1; 28 | } 29 | //如果需要下一页,则开启 30 | //var nextPage = currentPage + 1; 31 | // 分类 32 | var offset = (currentPage - 1) * size; 33 | var sql = `SELECT count(*) FROM messages where deleted=0 and type=7; 34 | select * FROM messages where deleted=0 and type=7 order by created_at desc limit ${size} offset ${offset}`; 35 | console.info('获取公告列表', sql); 36 | query(sql, (err, vals) => { 37 | if (!err && vals instanceof Array) { 38 | const totalCount = vals[0][0]['count(*)']; 39 | const totalPage = Math.ceil(parseInt(totalCount) / size); 40 | req.body.data = { 41 | list: vals[1], 42 | size: size, 43 | page: currentPage, 44 | totalPage: totalPage, 45 | totalCount: totalCount, 46 | }; 47 | req.body.code = '10000'; 48 | req.body.message = '操作成功'; 49 | req.body.success = true; 50 | return next(); 51 | } else { 52 | return res.json({ 53 | code: '10001', 54 | message: err.message, 55 | success: false, 56 | data: err, 57 | }); 58 | } 59 | }); 60 | } 61 | 62 | // 获取动态 63 | messages.getDynamicList = function(req, res, next) { 64 | var param = req.body; 65 | //分页实现 66 | var currentPage = 1; //默认为1 67 | var size = 10; //每页条数 68 | if (param.page) { 69 | currentPage = parseInt(param.page); 70 | } 71 | if (param.size) { 72 | size = parseInt(param.size); 73 | } 74 | //设置最后一页页码 75 | var lastPage = currentPage - 1; 76 | //假如目前仅有一页,则最后一页则为1 77 | if (currentPage <= 1) { 78 | lastPage = 1; 79 | } 80 | //如果需要下一页,则开启 81 | //var nextPage = currentPage + 1; 82 | // 分类 83 | var offset = (currentPage - 1) * size; 84 | var sql = `SELECT count(*) FROM messages where deleted=0 and type=8; 85 | select * FROM messages where deleted=0 and type=8 order by created_at desc limit ${size} offset ${offset}`; 86 | console.info('获取动态列表', sql); 87 | query(sql, (err, vals) => { 88 | if (!err && vals instanceof Array) { 89 | const totalCount = vals[0][0]['count(*)']; 90 | const totalPage = Math.ceil(parseInt(totalCount) / size); 91 | req.body.data = { 92 | list: vals[1], 93 | size: size, 94 | page: currentPage, 95 | totalPage: totalPage, 96 | totalCount: totalCount, 97 | }; 98 | req.body.code = '10000'; 99 | req.body.message = '操作成功'; 100 | req.body.success = true; 101 | return next(); 102 | } else { 103 | return res.json({ 104 | code: '10001', 105 | message: err.message, 106 | success: false, 107 | data: err, 108 | }); 109 | } 110 | }); 111 | } 112 | 113 | // 获取消息 114 | messages.list = function(req, res, next) { 115 | var param = req.body; 116 | //分页实现 117 | var currentPage = 1; //默认为1 118 | var size = 10; //每页条数 119 | if (param.page) { 120 | currentPage = parseInt(param.page); 121 | } 122 | if (param.size) { 123 | size = parseInt(param.size); 124 | } 125 | //设置最后一页页码 126 | var lastPage = currentPage - 1; 127 | //假如目前仅有一页,则最后一页则为1 128 | if (currentPage <= 1) { 129 | lastPage = 1; 130 | } 131 | //如果需要下一页,则开启 132 | //var nextPage = currentPage + 1; 133 | // 分类 134 | const userId = param.userId; 135 | var offset = (currentPage - 1) * size; 136 | var sql = `SELECT COUNT(*) FROM messages where deleted=0 and user_id in (0, ${userId}) and type!=8; 137 | select m.id,m.type,m.business_id,m.title,m.content,m.created_at,s.is_read FROM messages as m 138 | left join (select message_id,is_read from messages_state group by message_id,is_read) as s 139 | on m.id=s.message_id 140 | where m.deleted=0 and m.user_id in (0, ${userId}) and type!=8 141 | order by m.created_at desc 142 | limit ${size} offset ${offset}`; 143 | console.info('获取消息列表', sql); 144 | query(sql, (err, vals) => { 145 | if (!err && vals instanceof Array) { 146 | const totalCount = vals[0][0]['COUNT(*)']; 147 | const totalPage = Math.ceil(parseInt(totalCount) / size); 148 | req.body.data = { 149 | list: vals[1], 150 | size: size, 151 | page: currentPage, 152 | totalPage: totalPage, 153 | totalCount: totalCount, 154 | }; 155 | req.body.code = '10000'; 156 | req.body.message = '操作成功'; 157 | req.body.success = true; 158 | return next(); 159 | } else { 160 | return res.json({ 161 | code: '10001', 162 | message: err.message, 163 | success: false, 164 | data: err, 165 | }); 166 | } 167 | }); 168 | } 169 | // 获取未读消息数 170 | messages.unreadCount = async function(req, res, next) { 171 | const user_id = req.body.userId; 172 | const sql = `SELECT COUNT(*) as message_count FROM messages where deleted=0 and user_id in (0, ?) and type!=8; 173 | SELECT COUNT(*) as read_count FROM messages_state where user_id in (0, ?);`; 174 | const result = await query(sql, null, [+user_id, +user_id], '获取未读消息数'); 175 | if (!result.fail && result instanceof Array) { 176 | req.body.data = result[0][0]['message_count']-result[1][0]['read_count']; 177 | req.body.code = '10000'; 178 | req.body.message = '操作成功'; 179 | req.body.success = true; 180 | return next(); 181 | } else { 182 | return res.json({ code: '10001', message: '', success: false, data: 'err' }); 183 | } 184 | } 185 | // 添加公告 186 | messages.addNotice = async function(req, res, next) { 187 | const title = req.body.title; 188 | const content = req.body.content; 189 | const created_at = new Date().getTime(); 190 | const sql = `insert into messages(type,title,content,created_at) 191 | values(?,?,?,?)`; 192 | const result = await query(sql, null, [7, title, content, created_at], '添加公告'); 193 | if (!result.fail && result instanceof Object) { 194 | req.body.data = true; 195 | req.body.code = '10000'; 196 | req.body.message = '操作成功'; 197 | req.body.success = true; 198 | // 记录操作日志 199 | req.body.log = Object.assign(req.body.log || {}, { 200 | client: 1, 201 | content: `添加了ID为${result.insertId}的公告`, 202 | }); 203 | return next(); 204 | } else { 205 | return res.json({ 206 | code: '10001', 207 | message: '添加公告失败', 208 | success: false, 209 | data: result.message, 210 | }); 211 | } 212 | } 213 | // 添加消息 214 | messages.add = function(req, res, next) { 215 | if (!(req.body.message_add instanceof Object)) { 216 | return next(); 217 | } 218 | const type = req.body.message_add.type; 219 | const user_id = req.body.message_add.user_id; 220 | // 业务id,是个json,主要用于页面跳转,如: 221 | // { 222 | // task_id: '', 223 | // user_id: '', 224 | // review_id: '', 225 | // user_task: '', 226 | // withdraw_id: '', 227 | // } 228 | const business_id = req.body.message_add.business_id instanceof Object ? JSON.stringify(req.body.message_add.business_id) : req.body.message_add.business_id; 229 | const title = req.body.message_add.title; 230 | const content = req.body.message_add.content; 231 | const created_at = new Date().getTime(); 232 | const sql = `insert into messages(type,user_id,title,content,business_id,created_at) 233 | values(${type},${user_id},'${title}','${content}','${business_id}','${created_at}')`; 234 | console.info("新增消息", sql); 235 | query(sql, () => { 236 | delete req.body.message_add; 237 | return next(); 238 | }) 239 | } 240 | // 修改公告 241 | messages.updateNotice = async function(req, res, next) { 242 | const id = req.body.id; 243 | const title = req.body.title; 244 | const content = req.body.content; 245 | const updated_at = new Date().getTime(); 246 | const sql = `update messages set title=?,content=?,updated_at=? where id=?`; 247 | const result = await query(sql, null, [title, content, updated_at, id], '修改公告'); 248 | if (!result.fail && result instanceof Object) { 249 | req.body.data = true; 250 | req.body.code = '10000'; 251 | req.body.message = '操作成功'; 252 | req.body.success = true; 253 | // 记录操作日志 254 | req.body.log = Object.assign(req.body.log || {}, { 255 | client: 1, 256 | content: `修改了ID为${id}的公告`, 257 | }); 258 | return next(); 259 | } else { 260 | return res.json({ 261 | code: '10001', 262 | message: '修改公告失败', 263 | success: false, 264 | data: result.message, 265 | }); 266 | } 267 | } 268 | // 公告详情 269 | messages.getNoticeDetail = async function(req, res, next) { 270 | const id = req.body.id; 271 | const sql = `select * from messages where id=${id} and deleted=0`; 272 | console.info("获取公告详情", sql); 273 | query(sql, (err, vals) => { 274 | if (!err && vals instanceof Object) { 275 | req.body.data = vals[0]; 276 | req.body.code = '10000'; 277 | req.body.message = '操作成功'; 278 | req.body.success = true; 279 | return next(); 280 | } else { 281 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 282 | } 283 | }) 284 | } 285 | // 获取消息详情 286 | messages.detail = function(req, res, next) { 287 | const id = req.body.id; 288 | const user_id = req.body.user_id; 289 | const sql = `select * from messages where id=${id} and deleted=0 and user_id in (0, ${user_id});`; 290 | console.info("获取消息详情", sql); 291 | query(sql, (err, vals) => { 292 | if (!err && vals instanceof Object) { 293 | req.body.data = vals[0]; 294 | req.body.code = '10000'; 295 | req.body.message = '操作成功'; 296 | req.body.success = true; 297 | return next(); 298 | } else { 299 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 300 | } 301 | }) 302 | } 303 | // 设为已读 304 | messages.read = function(req, res, next) { 305 | const id = req.body.id; 306 | const user_id = req.body.user_id; 307 | const created_at = new Date().getTime(); 308 | const sql = `insert into messages_state(message_id,is_read,user_id,created_at) values(${id},1,${user_id},${created_at})`; 309 | console.info("设为已读", sql); 310 | query(sql, (err, vals) => { 311 | if (!err && vals instanceof Object) { 312 | req.body.data = true; 313 | req.body.code = '10000'; 314 | req.body.message = '操作成功'; 315 | req.body.success = true; 316 | return next(); 317 | } else { 318 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 319 | } 320 | }) 321 | } 322 | // 删除消息 323 | messages.remove = function(req, res, next) { 324 | const id = req.body.id; 325 | const updated_at = new Date().getTime(); 326 | const sql = `update messages set deleted=1,updated_at='${updated_at}' where id=${id};`; 327 | console.info("删除消息", sql); 328 | query(sql, (err, vals) => { 329 | if (!err && vals instanceof Object) { 330 | req.body.data = true; 331 | req.body.code = '10000'; 332 | req.body.message = '操作成功'; 333 | req.body.success = true; 334 | return next(); 335 | } else { 336 | return res.json({ code: '10001', message: err.message, success: false, data: err }); 337 | } 338 | }) 339 | } -------------------------------------------------------------------------------- /middlewares/system.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 唐文雍 3 | * @Date: 2019-01-16 10:17:32 4 | * @Last Modified by: 唐文雍 5 | * @Last Modified time: 2019-01-16 10:17:32 6 | */ 7 | const query = require('../utils/pool'); 8 | const system = {}; 9 | exports.system = system; 10 | 11 | // 获取系统配置 12 | system.get = function(req, res, next) { 13 | const sql = "SELECT * FROM `system`"; 14 | console.info("查询系统配置", sql); 15 | query(sql, (err, vals) => { 16 | if (!err && vals instanceof Array) { 17 | req.body.data = Object.assign(vals[0], req.body.data); 18 | req.body.code = '10000'; 19 | req.body.message = '操作成功'; 20 | req.body.success = true; 21 | return next(); 22 | } else { 23 | return res.json({ code: '10001', message: err.code, success: false, data: null }); 24 | } 25 | }) 26 | } 27 | // 更新系统配置 28 | system.update = function(req, res, next) { 29 | const program_name = req.body.program_name; 30 | const show_certification = req.body.show_certification; 31 | const show_vip = req.body.show_vip; 32 | const show_publish = req.body.show_publish; 33 | const show_wallet = req.body.show_wallet; 34 | const withdraw_min = req.body.withdraw_min; 35 | const first_withdraw_min = req.body.first_withdraw_min; 36 | const withdraw_max = req.body.withdraw_max; 37 | const withdraw_notice = req.body.withdraw_notice; 38 | const is_review = req.body.is_review; 39 | const contact = req.body.contact; 40 | const h5 = req.body.h5; 41 | const share_title = req.body.share_title; 42 | const share_image = req.body.share_image; 43 | const commission_ratio = req.body.commission_ratio; 44 | const first_commission_ratio = req.body.first_commission_ratio; 45 | const commission_ratio_vip = req.body.commission_ratio_vip; 46 | const agreement_title = req.body.agreement_title; 47 | const agreement_content = req.body.agreement_content; 48 | const need_certification = req.body.need_certification; 49 | const publish_need_certification = req.body.publish_need_certification; 50 | const need_vip = req.body.need_vip; 51 | const vip_unlimited = req.body.vip_unlimited; 52 | const alipay_code = req.body.alipay_code; 53 | const wepay_code = req.body.wepay_code; 54 | const vip_description = req.body.vip_description; 55 | const online_pay = req.body.online_pay || 0; 56 | const use_apppay = req.body.use_apppay || 0; 57 | const use_publicpay = req.body.use_publicpay || 0; 58 | const use_app_alipay = req.body.use_app_alipay || 0; 59 | const mch_id = req.body.mch_id || ''; 60 | const mch_key = req.body.mch_key || ''; 61 | const task_price = req.body.task_price; 62 | const task_price_vip = req.body.task_price_vip; 63 | const invite_rule = req.body.invite_rule; 64 | const show_withdraw = req.body.show_withdraw; 65 | const show_recharge = req.body.show_recharge; 66 | const show_invite = req.body.show_invite; 67 | const show_contact = req.body.show_contact; 68 | const show_connect = req.body.show_connect; 69 | const is_ratio = req.body.is_ratio; 70 | const need_review = req.body.need_review; 71 | const show_about = req.body.show_about; 72 | const about_us = req.body.about_us; 73 | const show_recommend = req.body.show_recommend; 74 | const show_high = req.body.show_high; 75 | const show_simple = req.body.show_simple; 76 | const show_member = req.body.show_member; 77 | const base_amount = req.body.base_amount; 78 | const max_review_time = req.body.max_review_time; 79 | const open_appeal = req.body.open_appeal; 80 | const min_task_price = req.body.min_task_price; 81 | const max_task_price = req.body.max_task_price; 82 | const min_limit_time = req.body.min_limit_time; 83 | const max_limit_time = req.body.max_limit_time; 84 | const android_download_url = req.body.android_download_url; 85 | const ios_download_url = req.body.ios_download_url; 86 | const android_download_code = req.body.android_download_code; 87 | const ios_download_code = req.body.ios_download_code; 88 | const refresh_count = req.body.refresh_count; 89 | const show_refresh = req.body.show_refresh; 90 | const recommend_price = req.body.recommend_price; 91 | const vip_recommend_price = req.body.vip_recommend_price; 92 | const top_price = req.body.top_price; 93 | const vip_top_price = req.body.vip_top_price; 94 | const withdraw_need_certificate = req.body.withdraw_need_certificate; 95 | const show_certification_IDcard = req.body.show_certification_IDcard; 96 | const show_certification_card_number = req.body.show_certification_card_number; 97 | const show_register_entry = req.body.show_register_entry; 98 | const show_phone_login = req.body.show_phone_login; 99 | const vip_award_ratio = req.body.vip_award_ratio; 100 | const vip_award_ratio_two = req.body.vip_award_ratio_two; 101 | const need_bind_phone = req.body.need_bind_phone; 102 | const score_rate = req.body.score_rate; 103 | const score_for_task = req.body.score_for_task; 104 | const app_version = req.body.app_version; 105 | const app_version_name = req.body.app_version_name; 106 | const app_update_description = req.body.app_update_description; 107 | const app_update_rule = req.body.app_update_rule; 108 | const invite_text = req.body.invite_text; 109 | const invite_poster = req.body.invite_poster; 110 | const poster_code_width = req.body.poster_code_width; 111 | const poster_code_height = req.body.poster_code_height; 112 | const poster_code_left = req.body.poster_code_left; 113 | const poster_code_top = req.body.poster_code_top; 114 | const download_page = req.body.download_page; 115 | const pay_to_wechat = req.body.pay_to_wechat || 0; 116 | const pay_to_alipay = req.body.pay_to_alipay || 0; 117 | const withdraw_need_bind_wechat = req.body.withdraw_need_bind_wechat || 0; 118 | const policy_title = req.body.policy_title || ''; 119 | const policy_content = req.body.policy_content || ''; 120 | const use_phone_register = req.body.use_phone_register; 121 | const show_app_wechat_login = req.body.show_app_wechat_login; 122 | const show_find_password = req.body.show_find_password; 123 | const show_bind_phone = req.body.show_bind_phone || 0; 124 | const show_wallet_recharge = req.body.show_wallet_recharge || 0; 125 | const show_app_apple_login = req.body.show_app_apple_login || 0; 126 | const grab_btn_ad = req.body.grab_btn_ad || ''; 127 | const withdraw_btn_ad = req.body.withdraw_btn_ad || ''; 128 | const show_alipay_withdraw = req.body.show_alipay_withdraw || 0; 129 | const show_wechat_withdraw = req.body.show_wechat_withdraw || 0; 130 | const show_bank_withdraw = req.body.show_bank_withdraw || 0; 131 | const recharge_rate = req.body.recharge_rate || 100; 132 | const enable_location = req.body.enable_location || 0; 133 | 134 | const sql = `update system set 135 | grab_btn_ad="${grab_btn_ad}", 136 | withdraw_btn_ad="${withdraw_btn_ad}", 137 | program_name="${program_name}", 138 | android_download_url="${android_download_url}", 139 | ios_download_url="${ios_download_url}", 140 | android_download_code="${android_download_code}", 141 | ios_download_code="${ios_download_code}", 142 | min_task_price=${min_task_price}, 143 | max_task_price=${max_task_price}, 144 | min_limit_time="${min_limit_time}", 145 | max_limit_time="${max_limit_time}", 146 | show_certification=${show_certification}, 147 | show_vip=${show_vip}, 148 | show_publish=${show_publish}, 149 | show_wallet=${show_wallet}, 150 | withdraw_min=${withdraw_min}, 151 | first_withdraw_min=${first_withdraw_min}, 152 | withdraw_max=${withdraw_max}, 153 | withdraw_notice="${withdraw_notice}", 154 | contact="${contact}", 155 | h5="${h5}", 156 | share_title="${share_title}", 157 | share_image="${share_image}", 158 | commission_ratio=${commission_ratio}, 159 | first_commission_ratio=${first_commission_ratio}, 160 | commission_ratio_vip=${commission_ratio_vip}, 161 | agreement_title="${agreement_title}", 162 | agreement_content="${agreement_content}", 163 | need_certification=${need_certification}, 164 | publish_need_certification=${publish_need_certification}, 165 | enable_location=${enable_location}, 166 | need_vip=${need_vip}, 167 | vip_unlimited=${vip_unlimited}, 168 | alipay_code="${alipay_code}", 169 | wepay_code="${wepay_code}", 170 | vip_description="${vip_description}", 171 | online_pay=${online_pay}, 172 | use_apppay=${use_apppay}, 173 | mch_id="${mch_id}", 174 | mch_key="${mch_key}", 175 | task_price=${task_price}, 176 | task_price_vip=${task_price_vip}, 177 | invite_rule="${invite_rule}", 178 | show_withdraw=${show_withdraw}, 179 | show_recharge=${show_recharge}, 180 | show_invite=${show_invite}, 181 | show_contact=${show_contact}, 182 | show_connect=${show_connect}, 183 | is_ratio=${is_ratio}, 184 | need_review=${need_review}, 185 | show_about=${show_about}, 186 | about_us="${about_us}", 187 | show_recommend=${show_recommend}, 188 | show_high=${show_high}, 189 | show_simple=${show_simple}, 190 | show_member=${show_member}, 191 | base_amount=${base_amount}, 192 | max_review_time=${max_review_time}, 193 | open_appeal=${open_appeal}, 194 | refresh_count=${refresh_count}, 195 | show_refresh=${show_refresh}, 196 | recommend_price=${recommend_price}, 197 | vip_recommend_price=${vip_recommend_price}, 198 | top_price=${top_price}, 199 | vip_top_price=${vip_top_price}, 200 | withdraw_need_certificate=${withdraw_need_certificate}, 201 | show_certification_IDcard=${show_certification_IDcard}, 202 | show_certification_card_number=${show_certification_card_number}, 203 | show_register_entry=${show_register_entry}, 204 | show_phone_login=${show_phone_login}, 205 | use_publicpay=${use_publicpay}, 206 | use_app_alipay=${use_app_alipay}, 207 | vip_award_ratio=${vip_award_ratio}, 208 | vip_award_ratio_two=${vip_award_ratio_two}, 209 | need_bind_phone=${need_bind_phone}, 210 | score_rate=${score_rate}, 211 | score_for_task=${score_for_task}, 212 | app_version=${app_version}, 213 | app_version_name='${app_version_name}', 214 | app_update_description='${app_update_description}', 215 | app_update_rule=${app_update_rule}, 216 | invite_text='${invite_text}', 217 | invite_poster='${invite_poster}', 218 | poster_code_width=${poster_code_width}, 219 | poster_code_height=${poster_code_height}, 220 | poster_code_left=${poster_code_left}, 221 | poster_code_top=${poster_code_top}, 222 | download_page='${download_page}', 223 | pay_to_wechat=${pay_to_wechat}, 224 | pay_to_alipay=${pay_to_alipay}, 225 | withdraw_need_bind_wechat=${withdraw_need_bind_wechat}, 226 | policy_title='${policy_title}', 227 | policy_content='${policy_content}', 228 | use_phone_register=${use_phone_register}, 229 | show_app_wechat_login=${show_app_wechat_login}, 230 | show_find_password=${show_find_password}, 231 | show_bind_phone=${show_bind_phone}, 232 | show_wallet_recharge=${show_wallet_recharge}, 233 | show_app_apple_login=${show_app_apple_login}, 234 | show_alipay_withdraw=${show_alipay_withdraw}, 235 | show_wechat_withdraw=${show_wechat_withdraw}, 236 | show_bank_withdraw=${show_bank_withdraw}, 237 | recharge_rate=${recharge_rate}, 238 | is_review=${is_review}`; 239 | query(sql, (err, vals) => { 240 | if (!err && vals instanceof Object) { 241 | console.info('更新系统配置返回', vals); 242 | req.body.data = true; 243 | req.body.code = '10000'; 244 | req.body.message = '操作成功'; 245 | req.body.success = true; 246 | // 记录操作日志 247 | req.body.log = Object.assign(req.body.log || {}, { 248 | client: 1, 249 | content: `修改了系统设置`, 250 | }); 251 | return next(); 252 | } else { 253 | return res.json({ code: '10001', message: err.code, success: false, data: err }); 254 | } 255 | }) 256 | } -------------------------------------------------------------------------------- /utils/md5.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript MD5 3 | * https://github.com/blueimp/JavaScript-MD5 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | * 11 | * Based on 12 | * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 13 | * Digest Algorithm, as defined in RFC 1321. 14 | * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 15 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 16 | * Distributed under the BSD License 17 | * See http://pajhome.org.uk/crypt/md5 for more info. 18 | */ 19 | 20 | /* global define */ 21 | 22 | /* eslint-disable strict */ 23 | 24 | ;(function($) { 25 | 'use strict' 26 | 27 | /** 28 | * Add integers, wrapping at 2^32. 29 | * This uses 16-bit operations internally to work around bugs in interpreters. 30 | * 31 | * @param {number} x First integer 32 | * @param {number} y Second integer 33 | * @returns {number} Sum 34 | */ 35 | function safeAdd(x, y) { 36 | var lsw = (x & 0xffff) + (y & 0xffff) 37 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16) 38 | return (msw << 16) | (lsw & 0xffff) 39 | } 40 | 41 | /** 42 | * Bitwise rotate a 32-bit number to the left. 43 | * 44 | * @param {number} num 32-bit number 45 | * @param {number} cnt Rotation count 46 | * @returns {number} Rotated number 47 | */ 48 | function bitRotateLeft(num, cnt) { 49 | return (num << cnt) | (num >>> (32 - cnt)) 50 | } 51 | 52 | /** 53 | * Basic operation the algorithm uses. 54 | * 55 | * @param {number} q q 56 | * @param {number} a a 57 | * @param {number} b b 58 | * @param {number} x x 59 | * @param {number} s s 60 | * @param {number} t t 61 | * @returns {number} Result 62 | */ 63 | function md5cmn(q, a, b, x, s, t) { 64 | return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b) 65 | } 66 | /** 67 | * Basic operation the algorithm uses. 68 | * 69 | * @param {number} a a 70 | * @param {number} b b 71 | * @param {number} c c 72 | * @param {number} d d 73 | * @param {number} x x 74 | * @param {number} s s 75 | * @param {number} t t 76 | * @returns {number} Result 77 | */ 78 | function md5ff(a, b, c, d, x, s, t) { 79 | return md5cmn((b & c) | (~b & d), a, b, x, s, t) 80 | } 81 | /** 82 | * Basic operation the algorithm uses. 83 | * 84 | * @param {number} a a 85 | * @param {number} b b 86 | * @param {number} c c 87 | * @param {number} d d 88 | * @param {number} x x 89 | * @param {number} s s 90 | * @param {number} t t 91 | * @returns {number} Result 92 | */ 93 | function md5gg(a, b, c, d, x, s, t) { 94 | return md5cmn((b & d) | (c & ~d), a, b, x, s, t) 95 | } 96 | /** 97 | * Basic operation the algorithm uses. 98 | * 99 | * @param {number} a a 100 | * @param {number} b b 101 | * @param {number} c c 102 | * @param {number} d d 103 | * @param {number} x x 104 | * @param {number} s s 105 | * @param {number} t t 106 | * @returns {number} Result 107 | */ 108 | function md5hh(a, b, c, d, x, s, t) { 109 | return md5cmn(b ^ c ^ d, a, b, x, s, t) 110 | } 111 | /** 112 | * Basic operation the algorithm uses. 113 | * 114 | * @param {number} a a 115 | * @param {number} b b 116 | * @param {number} c c 117 | * @param {number} d d 118 | * @param {number} x x 119 | * @param {number} s s 120 | * @param {number} t t 121 | * @returns {number} Result 122 | */ 123 | function md5ii(a, b, c, d, x, s, t) { 124 | return md5cmn(c ^ (b | ~d), a, b, x, s, t) 125 | } 126 | 127 | /** 128 | * Calculate the MD5 of an array of little-endian words, and a bit length. 129 | * 130 | * @param {Array} x Array of little-endian words 131 | * @param {number} len Bit length 132 | * @returns {Array} MD5 Array 133 | */ 134 | function binlMD5(x, len) { 135 | /* append padding */ 136 | x[len >> 5] |= 0x80 << len % 32 137 | x[(((len + 64) >>> 9) << 4) + 14] = len 138 | 139 | var i 140 | var olda 141 | var oldb 142 | var oldc 143 | var oldd 144 | var a = 1732584193 145 | var b = -271733879 146 | var c = -1732584194 147 | var d = 271733878 148 | 149 | for (i = 0; i < x.length; i += 16) { 150 | olda = a 151 | oldb = b 152 | oldc = c 153 | oldd = d 154 | 155 | a = md5ff(a, b, c, d, x[i], 7, -680876936) 156 | d = md5ff(d, a, b, c, x[i + 1], 12, -389564586) 157 | c = md5ff(c, d, a, b, x[i + 2], 17, 606105819) 158 | b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330) 159 | a = md5ff(a, b, c, d, x[i + 4], 7, -176418897) 160 | d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426) 161 | c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341) 162 | b = md5ff(b, c, d, a, x[i + 7], 22, -45705983) 163 | a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416) 164 | d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417) 165 | c = md5ff(c, d, a, b, x[i + 10], 17, -42063) 166 | b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162) 167 | a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682) 168 | d = md5ff(d, a, b, c, x[i + 13], 12, -40341101) 169 | c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290) 170 | b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329) 171 | 172 | a = md5gg(a, b, c, d, x[i + 1], 5, -165796510) 173 | d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632) 174 | c = md5gg(c, d, a, b, x[i + 11], 14, 643717713) 175 | b = md5gg(b, c, d, a, x[i], 20, -373897302) 176 | a = md5gg(a, b, c, d, x[i + 5], 5, -701558691) 177 | d = md5gg(d, a, b, c, x[i + 10], 9, 38016083) 178 | c = md5gg(c, d, a, b, x[i + 15], 14, -660478335) 179 | b = md5gg(b, c, d, a, x[i + 4], 20, -405537848) 180 | a = md5gg(a, b, c, d, x[i + 9], 5, 568446438) 181 | d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690) 182 | c = md5gg(c, d, a, b, x[i + 3], 14, -187363961) 183 | b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501) 184 | a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467) 185 | d = md5gg(d, a, b, c, x[i + 2], 9, -51403784) 186 | c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473) 187 | b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734) 188 | 189 | a = md5hh(a, b, c, d, x[i + 5], 4, -378558) 190 | d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463) 191 | c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562) 192 | b = md5hh(b, c, d, a, x[i + 14], 23, -35309556) 193 | a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060) 194 | d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353) 195 | c = md5hh(c, d, a, b, x[i + 7], 16, -155497632) 196 | b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640) 197 | a = md5hh(a, b, c, d, x[i + 13], 4, 681279174) 198 | d = md5hh(d, a, b, c, x[i], 11, -358537222) 199 | c = md5hh(c, d, a, b, x[i + 3], 16, -722521979) 200 | b = md5hh(b, c, d, a, x[i + 6], 23, 76029189) 201 | a = md5hh(a, b, c, d, x[i + 9], 4, -640364487) 202 | d = md5hh(d, a, b, c, x[i + 12], 11, -421815835) 203 | c = md5hh(c, d, a, b, x[i + 15], 16, 530742520) 204 | b = md5hh(b, c, d, a, x[i + 2], 23, -995338651) 205 | 206 | a = md5ii(a, b, c, d, x[i], 6, -198630844) 207 | d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415) 208 | c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905) 209 | b = md5ii(b, c, d, a, x[i + 5], 21, -57434055) 210 | a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571) 211 | d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606) 212 | c = md5ii(c, d, a, b, x[i + 10], 15, -1051523) 213 | b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799) 214 | a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359) 215 | d = md5ii(d, a, b, c, x[i + 15], 10, -30611744) 216 | c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380) 217 | b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649) 218 | a = md5ii(a, b, c, d, x[i + 4], 6, -145523070) 219 | d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379) 220 | c = md5ii(c, d, a, b, x[i + 2], 15, 718787259) 221 | b = md5ii(b, c, d, a, x[i + 9], 21, -343485551) 222 | 223 | a = safeAdd(a, olda) 224 | b = safeAdd(b, oldb) 225 | c = safeAdd(c, oldc) 226 | d = safeAdd(d, oldd) 227 | } 228 | return [a, b, c, d] 229 | } 230 | 231 | /** 232 | * Convert an array of little-endian words to a string 233 | * 234 | * @param {Array} input MD5 Array 235 | * @returns {string} MD5 string 236 | */ 237 | function binl2rstr(input) { 238 | var i 239 | var output = '' 240 | var length32 = input.length * 32 241 | for (i = 0; i < length32; i += 8) { 242 | output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff) 243 | } 244 | return output 245 | } 246 | 247 | /** 248 | * Convert a raw string to an array of little-endian words 249 | * Characters >255 have their high-byte silently ignored. 250 | * 251 | * @param {string} input Raw input string 252 | * @returns {Array} Array of little-endian words 253 | */ 254 | function rstr2binl(input) { 255 | var i 256 | var output = [] 257 | output[(input.length >> 2) - 1] = undefined 258 | for (i = 0; i < output.length; i += 1) { 259 | output[i] = 0 260 | } 261 | var length8 = input.length * 8 262 | for (i = 0; i < length8; i += 8) { 263 | output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32 264 | } 265 | return output 266 | } 267 | 268 | /** 269 | * Calculate the MD5 of a raw string 270 | * 271 | * @param {string} s Input string 272 | * @returns {string} Raw MD5 string 273 | */ 274 | function rstrMD5(s) { 275 | return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)) 276 | } 277 | 278 | /** 279 | * Calculates the HMAC-MD5 of a key and some data (raw strings) 280 | * 281 | * @param {string} key HMAC key 282 | * @param {string} data Raw input string 283 | * @returns {string} Raw MD5 string 284 | */ 285 | function rstrHMACMD5(key, data) { 286 | var i 287 | var bkey = rstr2binl(key) 288 | var ipad = [] 289 | var opad = [] 290 | var hash 291 | ipad[15] = opad[15] = undefined 292 | if (bkey.length > 16) { 293 | bkey = binlMD5(bkey, key.length * 8) 294 | } 295 | for (i = 0; i < 16; i += 1) { 296 | ipad[i] = bkey[i] ^ 0x36363636 297 | opad[i] = bkey[i] ^ 0x5c5c5c5c 298 | } 299 | hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8) 300 | return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)) 301 | } 302 | 303 | /** 304 | * Convert a raw string to a hex string 305 | * 306 | * @param {string} input Raw input string 307 | * @returns {string} Hex encoded string 308 | */ 309 | function rstr2hex(input) { 310 | var hexTab = '0123456789abcdef' 311 | var output = '' 312 | var x 313 | var i 314 | for (i = 0; i < input.length; i += 1) { 315 | x = input.charCodeAt(i) 316 | output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f) 317 | } 318 | return output 319 | } 320 | 321 | /** 322 | * Encode a string as UTF-8 323 | * 324 | * @param {string} input Input string 325 | * @returns {string} UTF8 string 326 | */ 327 | function str2rstrUTF8(input) { 328 | return unescape(encodeURIComponent(input)) 329 | } 330 | 331 | /** 332 | * Encodes input string as raw MD5 string 333 | * 334 | * @param {string} s Input string 335 | * @returns {string} Raw MD5 string 336 | */ 337 | function rawMD5(s) { 338 | return rstrMD5(str2rstrUTF8(s)) 339 | } 340 | /** 341 | * Encodes input string as Hex encoded string 342 | * 343 | * @param {string} s Input string 344 | * @returns {string} Hex encoded string 345 | */ 346 | function hexMD5(s) { 347 | return rstr2hex(rawMD5(s)) 348 | } 349 | /** 350 | * Calculates the raw HMAC-MD5 for the given key and data 351 | * 352 | * @param {string} k HMAC key 353 | * @param {string} d Input string 354 | * @returns {string} Raw MD5 string 355 | */ 356 | function rawHMACMD5(k, d) { 357 | return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)) 358 | } 359 | /** 360 | * Calculates the Hex encoded HMAC-MD5 for the given key and data 361 | * 362 | * @param {string} k HMAC key 363 | * @param {string} d Input string 364 | * @returns {string} Raw MD5 string 365 | */ 366 | function hexHMACMD5(k, d) { 367 | return rstr2hex(rawHMACMD5(k, d)) 368 | } 369 | 370 | /** 371 | * Calculates MD5 value for a given string. 372 | * If a key is provided, calculates the HMAC-MD5 value. 373 | * Returns a Hex encoded string unless the raw argument is given. 374 | * 375 | * @param {string} string Input string 376 | * @param {string} [key] HMAC key 377 | * @param {boolean} [raw] Raw output switch 378 | * @returns {string} MD5 output 379 | */ 380 | function md5(string, key, raw) { 381 | if (!key) { 382 | if (!raw) { 383 | return hexMD5(string) 384 | } 385 | return rawMD5(string) 386 | } 387 | if (!raw) { 388 | return hexHMACMD5(key, string) 389 | } 390 | return rawHMACMD5(key, string) 391 | } 392 | 393 | if (typeof define === 'function' && define.amd) { 394 | define(function() { 395 | return md5 396 | }) 397 | } else if (typeof module === 'object' && module.exports) { 398 | module.exports = md5 399 | } else { 400 | $.md5 = md5 401 | } 402 | })(this) 403 | --------------------------------------------------------------------------------