├── public ├── images │ ├── b2.jpeg │ ├── bg1.jpeg │ ├── 404.png │ ├── arrow.png │ ├── logo.png │ ├── step1.png │ ├── step2.png │ ├── step3.png │ ├── step4.png │ ├── wxpay.png │ ├── favicon.ico │ ├── success1.png │ ├── success2.png │ ├── zhifubao.png │ ├── renrenpay.ico │ ├── partner_wxpay.jpg │ └── partner_alipay.jpg ├── dist │ ├── static │ │ ├── css │ │ │ ├── chunk-f779.79af9e6e.css │ │ │ ├── chunk-5743.8cad7bcd.css │ │ │ ├── chunk-b69e.de0b32b4.css │ │ │ ├── chunk-27db.6a1661a5.css │ │ │ ├── chunk-0224.f01dfcab.css │ │ │ ├── chunk-26f3.a8b3c6c5.css │ │ │ ├── chunk-fc3b.b79580c9.css │ │ │ ├── chunk-3200.6e36a35c.css │ │ │ ├── chunk-7e70.92d696e8.css │ │ │ ├── chunk-280b.7469e992.css │ │ │ ├── chunk-libs.e73a8678.css │ │ │ ├── chunk-6929.486b8768.css │ │ │ └── app.cab2c720.css │ │ ├── img │ │ │ ├── 404.a57b6f3.png │ │ │ └── bg.cf0887a.jpg │ │ ├── fonts │ │ │ └── element-icons.6f0a763.ttf │ │ └── js │ │ │ ├── eej3.42f74184.js │ │ │ ├── EwA2.cf227d21.js │ │ │ ├── chunk-27db.8a51fb19.js │ │ │ ├── chunk-f779.74ec5683.js │ │ │ ├── chunk-54db.2bca911d.js │ │ │ ├── chunk-0224.e4d32421.js │ │ │ ├── chunk-5743.e739dad9.js │ │ │ ├── chunk-3200.30d05b08.js │ │ │ ├── chunk-7e70.17b6490e.js │ │ │ ├── chunk-280b.82d6890b.js │ │ │ ├── chunk-6929.2461bbf3.js │ │ │ └── chunk-fc3b.827b4c52.js │ ├── favicon.ico │ └── index.html ├── stylesheets │ └── style.css ├── css │ └── normalize.css └── font │ └── iconfont.js ├── dump.rdb ├── playground.js ├── utils ├── md5.js ├── fileIO.js ├── logger.js ├── jwt.js ├── sendSms.js ├── sendEmail.js ├── callback.js ├── verifyParams.js ├── errorCode.js ├── verifyToken.js ├── websocket.js ├── redisClient.js ├── errorHandler.js ├── timeformatter.js ├── returnJson.js └── statistic.js ├── keys ├── master-public.pem └── master-privatekey.pem ├── test.js ├── .gitignore ├── README.md ├── db ├── index.js ├── models │ ├── withdraws.js │ ├── logs.js │ ├── statistic.js │ ├── payCode.js │ ├── trades.js │ ├── deposits.js │ ├── paychecks.js │ ├── orders.js │ ├── apps.js │ └── users.js ├── schema │ ├── logs.js │ ├── paycode.js │ ├── withdraws.js │ ├── trades.js │ ├── deposits.js │ ├── paychecks.js │ ├── apps.js │ ├── orders.js │ ├── statistic.js │ └── users.js └── sqlTable.js ├── conf └── default.js ├── views └── 404.ejs ├── package.json ├── app.js ├── bin └── www ├── init └── index.js └── controllers ├── withdrawsController.js ├── ordersController.js ├── index.js ├── paychecksController.js └── tradeController.js /public/images/b2.jpeg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/bg1.jpeg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/dist/static/css/chunk-f779.79af9e6e.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dump.rdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/dump.rdb -------------------------------------------------------------------------------- /public/dist/static/css/chunk-5743.8cad7bcd.css: -------------------------------------------------------------------------------- 1 | .orders-index-page[data-v-07355ba6]{padding:32px} -------------------------------------------------------------------------------- /public/images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/404.png -------------------------------------------------------------------------------- /public/dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/dist/favicon.ico -------------------------------------------------------------------------------- /public/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/arrow.png -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/logo.png -------------------------------------------------------------------------------- /public/images/step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/step1.png -------------------------------------------------------------------------------- /public/images/step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/step2.png -------------------------------------------------------------------------------- /public/images/step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/step3.png -------------------------------------------------------------------------------- /public/images/step4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/step4.png -------------------------------------------------------------------------------- /public/images/wxpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/wxpay.png -------------------------------------------------------------------------------- /playground.js: -------------------------------------------------------------------------------- 1 | 2 | let a = "pay" + 100 + "wechat" + 2 + Math.random().toString().slice(-8); 3 | console.log(a) -------------------------------------------------------------------------------- /public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/favicon.ico -------------------------------------------------------------------------------- /public/images/success1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/success1.png -------------------------------------------------------------------------------- /public/images/success2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/success2.png -------------------------------------------------------------------------------- /public/images/zhifubao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/zhifubao.png -------------------------------------------------------------------------------- /public/images/renrenpay.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/renrenpay.ico -------------------------------------------------------------------------------- /public/images/partner_wxpay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/partner_wxpay.jpg -------------------------------------------------------------------------------- /public/images/partner_alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/images/partner_alipay.jpg -------------------------------------------------------------------------------- /public/dist/static/img/404.a57b6f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/dist/static/img/404.a57b6f3.png -------------------------------------------------------------------------------- /public/dist/static/img/bg.cf0887a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/dist/static/img/bg.cf0887a.jpg -------------------------------------------------------------------------------- /public/dist/static/fonts/element-icons.6f0a763.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verylove/renrenpay-server/HEAD/public/dist/static/fonts/element-icons.6f0a763.ttf -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /utils/md5.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto') 2 | 3 | const MD5 = data => { 4 | const md5 = crypto.createHash('md5') 5 | md5.update(data) 6 | return md5.digest('hex') 7 | } 8 | 9 | module.exports = MD5 10 | -------------------------------------------------------------------------------- /keys/master-public.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKx57/DKGMVaPrCm9dewigq/uV 3 | 3/LvmD8gA9OkcG3Tfd/V4yrLqqBH3eH0Qkfi3SbYo2mo6sFYhvZI1Cg0jlPUwT1m 4 | NedGDNJsEugXujeNMDAEc2xpjwCvuAO7XGWUmyEynGbS+t4APX1vR0eqZ1XtVDFc 5 | WD+Si5EoLcJ+9zcSbQIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | let crypto = require('crypto'); 2 | const md5 = info => { 3 | const md5 = crypto.createHash('md5') 4 | md5.update(info) 5 | return md5.digest('hex') 6 | } 7 | 8 | // console.log(md5("qwerty")) 9 | let dbInfo = { 10 | }; 11 | const pwd = md5(md5(dbInfo.password) + dbInfo.salt); 12 | console.log(pwd) -------------------------------------------------------------------------------- /public/dist/static/js/eej3.42f74184.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["eej3"],{eej3:function(e,n,t){"use strict";t.r(n);var i=t("KHd+"),s=Object(i.a)({},function(){var e=this.$createElement;return(this._self._c||e)("div",{staticClass:"api-index-page"},[this._v("\n API 文档\n")])},[],!1,null,null,null);s.options.__file="Index.vue";n.default=s.exports}}]); -------------------------------------------------------------------------------- /public/dist/static/js/EwA2.cf227d21.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["EwA2"],{EwA2:function(n,e,t){"use strict";t.r(e);var s=t("KHd+"),i=Object(s.a)({},function(){var n=this.$createElement;return(this._self._c||n)("div",{staticClass:"download-index-page"},[this._v("\n 软件下载页面\n")])},[],!1,null,null,null);i.options.__file="Index.vue";e.default=i.exports}}]); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.db 2 | dapps/ 3 | .DS_Store 4 | .ed25519-node 5 | .idea/ 6 | *.log 7 | __MACOSX/ 8 | nodejs/ 9 | node_modules 10 | logs 11 | .project 12 | release 13 | sqlite/ 14 | ssl/ 15 | stacktrace* 16 | tmp 17 | *.pid 18 | package-lock.json 19 | .vs/ 20 | .vscode 21 | public/bower_components 22 | public/npm-debug.log 23 | public/.sass-cache 24 | public/.tmp 25 | public/.gulp 26 | public/*.css 27 | public/node_modules 28 | *.save 29 | accountKey.json 30 | 31 | -------------------------------------------------------------------------------- /utils/fileIO.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const { 4 | loggerHttp 5 | } = require('./logger.js') 6 | 7 | const fileIO = { 8 | // write into a file 9 | async writeFile(filename, data) { 10 | try { 11 | fs.writeFileSync(path.join(__dirname, filename), data) 12 | return true 13 | } catch (err) { 14 | loggerHttp.error(`writeFile -- ${err}`) 15 | } 16 | } 17 | } 18 | 19 | module.exports = fileIO 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 利用xposed框架监听支付宝微信的收付款服务端 2 | 安卓端地址:https://github.com/cxyxxx0924/renrenpay-android.git 3 | ## 说明 4 | 服务端和客户端需要配合使用,不然客户端都无法打开 5 | 6 | ## 安装步骤 7 | ``` 8 | 下载node环境 http://nodejs.cn/ (版本最好新一点,我使用的是10.14.2) 9 | 10 | git clone https://github.com/cxyxxx0924/renrenpay-server.git 11 | cd renrenpay-server 12 | npm i 13 | 下载redis 14 | 下载mysql 15 | 修改./conf/default.js下的user和password为mysql的用户名和密码 16 | 添加 数据库:db_renrenpay 17 | 运行 bin/www 既可以运行项目 18 | 打开浏览器 127.0.0.1:3000 既可以看到项目运行 19 | 确保运行后在打开安卓客户端 20 | ``` 21 | -------------------------------------------------------------------------------- /public/dist/static/js/chunk-27db.8a51fb19.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-27db"],{mS28:function(e,n,t){"use strict";var i=t("z+hT");t.n(i).a},r2dA:function(e,n,t){"use strict";t.r(n);var i={components:{Membership:t("I8ep").a}},s=(t("mS28"),t("KHd+")),c=Object(s.a)(i,function(){var e=this.$createElement,n=this._self._c||e;return n("div",{staticClass:"admin-member-index"},[n("Membership",{attrs:{mode:"edit"}})],1)},[],!1,null,"51c447f2",null);c.options.__file="Index.vue";n.default=c.exports},"z+hT":function(e,n,t){}}]); -------------------------------------------------------------------------------- /public/dist/static/css/chunk-b69e.de0b32b4.css: -------------------------------------------------------------------------------- 1 | .pay-comp[data-v-549a193a]{text-align:center}.pay-comp.wepay .deposit-title[data-v-549a193a]{color:#09bb07}.pay-comp.alipay .deposit-title[data-v-549a193a]{color:#00aae8}.pay-comp .deposit-title[data-v-549a193a]{font-size:24px}.pay-comp .deposit-num[data-v-549a193a]{font-size:40px;font-weight:700;margin-top:30px;color:#606266}.app-index-page[data-v-00346527]{padding:32px}.app-index-page .input-hint[data-v-00346527]{font-size:12px;line-height:1.7;color:#909399;margin-top:5px}.app-index-page .input-hint a[data-v-00346527]{text-decoration:underline} -------------------------------------------------------------------------------- /db/index.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const SqlTable = require('./sqlTable.js') 3 | const config = require('../conf/default.js') 4 | 5 | let sequelize, sqlTable 6 | 7 | async function init() { 8 | sequelize = new Sequelize(config.db.db, config.db.user, config.db.password, { 9 | host: config.db.host, 10 | port: config.db.port, 11 | dialect: config.db.dialect, 12 | pool: { 13 | max: 100, 14 | min: 0, 15 | acquire: 30000, 16 | idle: 10000, 17 | }, 18 | timezone: '+08:00' 19 | }) 20 | // init 21 | sqlTable = new SqlTable(Sequelize, sequelize) 22 | } 23 | 24 | init() 25 | module.exports = {Sequelize, sequelize, sqlTable} 26 | -------------------------------------------------------------------------------- /db/models/withdraws.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const { 3 | sqlTable, 4 | } = require('../index.js') 5 | 6 | const withdraws = { 7 | async addWithdraw(data) { 8 | return sqlTable.withdraws.create({ 9 | userid: data.userid, 10 | uuid: data.uuid, 11 | type: data.type || '', 12 | amount: data.amount || 0, 13 | memo: data.memo || '', 14 | status: 1 15 | }) 16 | }, 17 | 18 | async updateWithdrawInfo(data) { 19 | return sqlTable.withdraws.update({ 20 | status: data.status || 0 21 | }, { 22 | where: { 23 | id: data.userid || 0 24 | } 25 | }) 26 | }, 27 | } 28 | 29 | module.exports = withdraws 30 | -------------------------------------------------------------------------------- /utils/logger.js: -------------------------------------------------------------------------------- 1 | const log4js = require('log4js') 2 | 3 | log4js.configure({ 4 | appenders: { 5 | out: { type: 'stdout' }, 6 | httpError: { type: 'dateFile', filename: `${__dirname}/../logs/http/httpError.log`, alwaysIncludePattern: true }, 7 | httpInfo: { type: 'dateFile', filename: `${__dirname}/../logs/httpInfo/httpInfo.log`, alwaysIncludePattern: true } 8 | }, 9 | categories: { 10 | default: { appenders: ['out'], level: 'error' }, 11 | httpError: { appenders: ['httpError'], level: 'error' }, 12 | httpInfo: { appenders: ['httpInfo'], level: 'info' } 13 | } 14 | }) 15 | 16 | const loggerHttp = log4js.getLogger('httpError') 17 | const loggerHttpInfo = log4js.getLogger('httpInfo') 18 | 19 | module.exports = { loggerHttp, loggerHttpInfo } 20 | -------------------------------------------------------------------------------- /db/models/logs.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const { 3 | sqlTable, 4 | } = require('../index.js') 5 | 6 | const logs = { 7 | async setLog(data){ 8 | return await sqlTable.logs.create({ 9 | userid:data.userid, 10 | content:data.content, 11 | timestamps:data.timestamps 12 | }) 13 | }, 14 | async setLogs(data){ 15 | return await sqlTable.logs.bulkCreate(data.list) 16 | }, 17 | async queryLog(data){ 18 | let limit = data.page_size*1; 19 | let offset = data.page_size * (data.page - 1); 20 | return sqlTable.deposits.findAndCountAll({ 21 | limit, 22 | offset, 23 | where: { 24 | userid:data.userid 25 | } 26 | }) 27 | } 28 | } 29 | 30 | module.exports=logs -------------------------------------------------------------------------------- /public/dist/static/css/chunk-27db.6a1661a5.css: -------------------------------------------------------------------------------- 1 | .admin-member-index .combo-list[data-v-51c447f2]{font-size:0;margin-left:-20px}.admin-member-index .combo-list .combo-item[data-v-51c447f2]{display:inline-block;width:150px;height:150px;padding:0 10px;border:1px solid #e4e7ed;border-radius:4px;text-align:center;overflow:hidden;margin-left:20px;cursor:pointer}.admin-member-index .combo-list .combo-item.active[data-v-51c447f2]{border:1px solid #f56c6c}.admin-member-index .combo-list .item-title[data-v-51c447f2]{height:50px;line-height:50px;border-bottom:1px dashed #dcdfe6;font-size:18px;color:#333}.admin-member-index .combo-list .item-num[data-v-51c447f2]{font-size:18px;margin-top:15px}.admin-member-index .combo-list .primary[data-v-51c447f2]{font-size:30px;color:#f56c6c;font-weight:700;margin-right:5px}.admin-member-index .combo-list .item-desc[data-v-51c447f2]{font-size:14px;margin-top:15px} -------------------------------------------------------------------------------- /db/schema/logs.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | // columns 3 | static logs(Sequelize) { 4 | return { 5 | id: { 6 | type: Sequelize.BIGINT, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | allowNull: false 10 | }, 11 | userid: { 12 | type: Sequelize.STRING, 13 | allowNull: false, 14 | }, 15 | content: { 16 | type: Sequelize.STRING 17 | }, 18 | timestamps: { 19 | type: Sequelize.BIGINT, 20 | }, 21 | } 22 | } 23 | 24 | static publicSet() { 25 | return { 26 | freezeTableName: true, 27 | paranoid: true, 28 | timestamps: true, 29 | } 30 | } 31 | } 32 | 33 | module.exports = sqlTable 34 | -------------------------------------------------------------------------------- /keys/master-privatekey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQDKx57/DKGMVaPrCm9dewigq/uV3/LvmD8gA9OkcG3Tfd/V4yrL 3 | qqBH3eH0Qkfi3SbYo2mo6sFYhvZI1Cg0jlPUwT1mNedGDNJsEugXujeNMDAEc2xp 4 | jwCvuAO7XGWUmyEynGbS+t4APX1vR0eqZ1XtVDFcWD+Si5EoLcJ+9zcSbQIDAQAB 5 | AoGAecgfLe+pCb3ZHux6a3rbeJsxEhaYMNqPdqu1rHk1DCH5jtvKNNy5O8/+xpIT 6 | 2CSXEt45M5AhJAiR2rVHnCCqKPdjCK0vNef4dI3Q1ngkn7f9pFd/n7QklIUj5HXC 7 | 1I+ucylCVGEHkb6MAV4lya2KWORAgBIm5PYeDVr2bxV+Z4UCQQDlw8EvJZZikI37 8 | 3b8HCMUuHJRSUM4VNCITW67OKUin1GfUy6qdQq5Zqrh/PEM6lUfjrRbraGuMPQba 9 | uSoVfZXrAkEA4e8SVBy0r2ZYqr4QIeJWhK9eRjigvT1TaaJmQ6L6FAx3XxEgk+eE 10 | tpZ6lxy5lM6Z/PkVxwWV1fzXH77Wm+yrBwJAKm2ZkOE6Af17mpT6H4xpDPjOEt1F 11 | EPlNiZGWmA9bkVJR0iPB38ReecRiyWwRZhIG8m4WG2Zu5binOWCT+t/z/QJAWdfk 12 | 1PfZTgqH5dXQuniz6O2HsqrgGICjg9Ulj23mvkQ6z94Ss14UYzsxope0oJ0LlRJD 13 | +7GX5NE3hpMv6i9RzwJBAIZdi6bw53IsMH63KfmIBhfoXSrdma1TrLet6nwDD5b1 14 | 1nC39Y30zzIY9BXKy7Vpc/tPyQRQXfUtPfQAdSVwYWU= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /db/models/statistic.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const Op = Sequelize.Op 3 | const { 4 | sqlTable,sequelize 5 | } = require('../index.js') 6 | 7 | const statistic={ 8 | async set_statistic(data){ 9 | return sqlTable.statistic.bulkCreate(data.list) 10 | }, 11 | 12 | async getToday(data) { 13 | return sequelize.query(`select w_count,p_count,w_total1,p_total1,w_total2,p_total2 from statistic where userid=? and date=?`,{ 14 | type: Sequelize.QueryTypes.SELECT, 15 | replacements:[data.userid,data.day] 16 | }) 17 | }, 18 | 19 | async getWeek(data) { 20 | return sequelize.query(`select w_count,p_count,w_total1,p_total1,w_total2,p_total2,date from statistic where userid=? and date>=? and date<=? order by date`,{ 21 | type: Sequelize.QueryTypes.SELECT, 22 | replacements:[data.userid,data.startDate,data.endDate] 23 | }) 24 | }, 25 | 26 | } 27 | 28 | module.exports = statistic -------------------------------------------------------------------------------- /utils/jwt.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const jwt = require('jsonwebtoken') 4 | 5 | class Jwt { 6 | constructor(data) { 7 | this.data = data 8 | } 9 | 10 | generateToken() { 11 | let data = this.data 12 | let now = Math.floor(Date.now() / 1000) 13 | let cert = fs.readFileSync(path.join(__dirname, '../keys/master-privatekey.pem')) 14 | let token = jwt.sign({ 15 | data, 16 | exp: now + 60 * 60 / 2, 17 | }, cert, { algorithm: 'RS256' }) 18 | 19 | return token 20 | } 21 | 22 | verifyToken() { 23 | let token = this.data 24 | let cert = fs.readFileSync(path.join(__dirname, '../keys/master-public.pem')) 25 | let res 26 | try { 27 | let result = jwt.verify(token, cert, { algorithm: ['RS256'] }) || {} 28 | let {exp = 0} = result, current = Math.floor(Date.now() / 1000) 29 | if (current <= exp) { 30 | res = result.data || {} 31 | } 32 | } catch (err) { 33 | res = 'err' 34 | } 35 | return res 36 | } 37 | } 38 | 39 | module.exports = Jwt 40 | -------------------------------------------------------------------------------- /utils/sendSms.js: -------------------------------------------------------------------------------- 1 | const SMS = require('@alicloud/sms-sdk') 2 | 3 | /** 4 | * 短信相关 5 | * */ 6 | const accessKeyId = 'accessKeyId' 7 | const secretAccessKey = 'secretAccessKey' 8 | const sign_name = 'sign_name' 9 | 10 | const tp1 = 'tp1' // 注册模板 11 | 12 | const sendSms = async (mobile_phone, code, type) => { 13 | let cli = new SMS({accessKeyId, secretAccessKey}) 14 | 15 | try { 16 | cli.sendSMS({ 17 | PhoneNumbers: mobile_phone, //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000” 18 | SignName: sign_name, //必填:短信签名-可在短信控制台中找到 19 | TemplateCode: tp1, //必填:短信模板-可在短信控制台中找到,发送国际/港澳台消息时,请使用国际/港澳台短信模版 20 | TemplateParam: `{"code": "${code}"}` //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时。 21 | }).then(res => { 22 | let {Code} = res 23 | if (Code === 'OK') { 24 | return true 25 | } else { 26 | return false 27 | } 28 | }) 29 | return true 30 | } catch (err) { 31 | console.info(err,'error'); 32 | } 33 | } 34 | 35 | module.exports = sendSms 36 | 37 | -------------------------------------------------------------------------------- /utils/sendEmail.js: -------------------------------------------------------------------------------- 1 | const Mailer = require('nodemailer') 2 | 3 | // 邮箱服务 4 | const host = ''; 5 | const port = 80; 6 | const user = ''; 7 | const pass = ''; 8 | 9 | const sendEmail = async (email, code, type) => { 10 | const transport = Mailer.createTransport({ 11 | host:host, // 服务 12 | port:port, // smtp端口 13 | secureConnection: true, // 使用ssl 14 | auth: { 15 | user, 16 | pass 17 | } 18 | }) 19 | 20 | try { 21 | let html1 = `

欢迎使用人人收付平台,您本次注册的验证码为

您的验证码是:${code}

请将以上验证码输入注册页面中的验证码输入框内以完成注册;

如非本人操作,请忽略

`;//注册 22 | 23 | transport.sendMail({ 24 | from: user, // 发件邮箱 25 | to: email, // 收件列表 26 | subject: '来自人人收付平台的邮件', // 标题 27 | // text:'ass', 28 | html: html1 // html 内容 29 | }, function (err, data) { 30 | if (err) { 31 | console.info(err,'error'); 32 | } 33 | transport.close(); // 如果没用,关闭连接池 34 | }) 35 | 36 | return true 37 | } catch (err) { 38 | console.info(err,'error'); 39 | } 40 | } 41 | 42 | module.exports = sendEmail 43 | 44 | -------------------------------------------------------------------------------- /utils/callback.js: -------------------------------------------------------------------------------- 1 | let request = require('request') 2 | 3 | let callback = (callurl,data)=>{ 4 | return new Promise((resolve,reject)=>{ 5 | request.get({url: callurl+`?orderid=${data.orderid}&appid=${data.appid}&amount=${data.amount}&sign=${data.sign}`},(err, _, body)=>{ 6 | if(err){ 7 | reject(); 8 | }else{ 9 | resolve() 10 | } 11 | }) 12 | }) 13 | } 14 | let callPost = (callurl,data)=>{ 15 | var options = { 16 | method: 'POST', 17 | url: callurl, 18 | form: { 19 | sign: data.sign, 20 | appid:data.appid, 21 | orderid:data.orderid, 22 | payway:data.payway, 23 | amount:data.amount 24 | }, 25 | headers: { 26 | 'Content-Type': 'text/plain; charset=utf-8' 27 | }, 28 | timeout: 50000 29 | }; 30 | return new Promise((resolve,reject)=>{ 31 | request.post(options,(err, response, body)=>{ 32 | if(err){ 33 | reject(); 34 | }else{ 35 | resolve() 36 | } 37 | }) 38 | }) 39 | } 40 | 41 | module.exports={ 42 | callPost, 43 | callback 44 | } -------------------------------------------------------------------------------- /db/models/payCode.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const Op = Sequelize.Op 3 | const { 4 | sqlTable, 5 | } = require('../index.js') 6 | 7 | const paycodes = { 8 | async addPayCode(data) { 9 | return sqlTable.paycodes.create({ 10 | userid: data.userid, 11 | qrcode: data.qrcode, 12 | pay_code: data.pay_code, 13 | amount: data.amount, 14 | use_num: 0 15 | }) 16 | }, 17 | async getPayCode(data) { 18 | return sqlTable.paycodes.findOne({ 19 | where: { 20 | userid: data.userid, 21 | amount: data.amount, 22 | pay_code:{$notIn:data.qrcode} 23 | }, 24 | order: ["use_num"], 25 | }, Op.notIn[{qrcode: data.qrcode}]) 26 | }, 27 | async addPayCodeNum(data) { 28 | return sqlTable.paycodes.update({ 29 | num: data.num + 1 30 | }, { 31 | where: { 32 | id: data.id 33 | } 34 | }) 35 | }, 36 | async deletePayCode(data){ 37 | return sqlTable.paycodes.destroy( { 38 | where: { 39 | userid: data.userid 40 | } 41 | }) 42 | } 43 | }; 44 | 45 | module.exports = paycodes 46 | -------------------------------------------------------------------------------- /db/schema/paycode.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | static paycodes(Sequelize) { 3 | return { 4 | id: { 5 | type: Sequelize.BIGINT, 6 | primaryKey: true, 7 | autoIncrement: true, 8 | allowNull: false 9 | }, 10 | // 用户id 11 | userid: { 12 | type: Sequelize.INTEGER, 13 | allowNull: false 14 | }, 15 | // 付款码 16 | qrcode: { 17 | type: Sequelize.STRING, 18 | allowNull: false 19 | }, 20 | // 付款信息备注 21 | pay_code: { 22 | type: Sequelize.STRING, 23 | allowNull: false 24 | }, 25 | // 金额 26 | amount: { 27 | type: Sequelize.INTEGER, 28 | allowNull: false 29 | }, 30 | // 使用次数 31 | use_num: { 32 | type: Sequelize.INTEGER, 33 | defaultValue: 0 34 | } 35 | } 36 | } 37 | 38 | static publicSet() { 39 | return { 40 | freezeTableName: true, 41 | paranoid: true, 42 | timestamps: true, 43 | } 44 | } 45 | } 46 | 47 | 48 | module.exports = sqlTable -------------------------------------------------------------------------------- /db/schema/withdraws.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | // columns 3 | static withdraws(Sequelize) { 4 | return { 5 | id: { 6 | type: Sequelize.BIGINT, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | allowNull: false 10 | }, 11 | userid: { 12 | type: Sequelize.STRING, 13 | allowNull: false, 14 | }, 15 | uuid: { 16 | type: Sequelize.STRING, 17 | allowNull: false, 18 | unique: true 19 | }, 20 | type: { 21 | type: Sequelize.STRING, 22 | allowNull: false, 23 | unique: true 24 | }, 25 | amount: { 26 | type: Sequelize.FLOAT 27 | }, 28 | memo: { 29 | type: Sequelize.STRING 30 | }, 31 | status: { 32 | type: Sequelize.TINYINT(1), 33 | defaultValue: 1 34 | } 35 | } 36 | } 37 | 38 | static publicSet() { 39 | return { 40 | freezeTableName: true, 41 | paranoid: true, 42 | timestamps: true, 43 | } 44 | } 45 | } 46 | 47 | module.exports = sqlTable 48 | -------------------------------------------------------------------------------- /db/schema/trades.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | // 系统商品表 3 | static trades(Sequelize) { 4 | return { 5 | id: { 6 | type: Sequelize.BIGINT, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | allowNull: false 10 | }, 11 | name: { // 产品名称 12 | type: Sequelize.STRING, 13 | allowNull: false, 14 | }, 15 | amount: { // 产品金额 16 | type: Sequelize.INTEGER, 17 | allowNull: false 18 | }, 19 | create_account_id: { 20 | type: Sequelize.INTEGER, 21 | allowNull: false 22 | }, 23 | desc: { // 商品描述 24 | type: Sequelize.STRING, 25 | allowNull: false 26 | }, 27 | day: { //充值天数 28 | type: Sequelize.INTEGER, 29 | defaultValue: 0 30 | }, 31 | lv: { //充值等级 32 | type: Sequelize.INTEGER, 33 | defaultValue: 0 34 | } 35 | } 36 | }; 37 | 38 | static publicSet() { 39 | return { 40 | freezeTableName: true, 41 | paranoid: true, 42 | timestamps: true, 43 | }; 44 | } 45 | } 46 | 47 | module.exports = sqlTable; -------------------------------------------------------------------------------- /conf/default.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | 3 | let config = { 4 | port: 3000, 5 | db: { 6 | host: process.env.host || '127.0.0.1', 7 | port: process.env.port || 3306, 8 | db: process.env.db ||'db_renrenpay', 9 | dialect: 'mysql', 10 | user: process.env.username || 'root', 11 | password: process.env.password || '123456' 12 | }, 13 | redis: { 14 | host: '127.0.0.1', 15 | port: 6379 16 | }, 17 | websocket: { 18 | port: 7234 19 | }, 20 | appid: process.env.appid || '15c821df1e52', 21 | adminPwd: process.env.adminpwd || '123456', 22 | userid: '1', 23 | pay_userid: process.env.pay_userid ||'2088112172418889' 24 | } 25 | 26 | const init = () => { 27 | if (process.env.NODE_ENV === 'development') { 28 | const localConfig = { 29 | db: _.extend(config.db, { 30 | user: config.user, 31 | password: db.password 32 | }) 33 | } 34 | config = _.extend(config, localConfig) 35 | } 36 | 37 | if (process.env.NODE_ENV === 'production') { 38 | const localConfig = { 39 | db: _.extend(config.db, { 40 | user: '', 41 | password: '' 42 | }) 43 | } 44 | config = _.extend(config, localConfig) 45 | } 46 | 47 | return config 48 | } 49 | 50 | module.exports = init() 51 | -------------------------------------------------------------------------------- /views/404.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 6 | 49 | 50 | 51 | 52 |
53 |


54 |
55 | 56 |
57 |
58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /db/models/trades.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const Op = Sequelize.Op 3 | const { 4 | sqlTable, 5 | } = require('../index.js') 6 | const trades = { 7 | //添加充值订单 8 | async addTrades(data) { 9 | return sqlTable.trades.create({ 10 | name: data.name, 11 | amount: data.amount, 12 | create_account_id: data.userid, 13 | desc: data.desc, 14 | day: data.day, 15 | lv: data.lv 16 | }); 17 | }, 18 | // 修改商品 19 | async modifyTrades(data) { 20 | return sqlTable.trades.update(data, { 21 | where: { 22 | id: data.tradeid 23 | } 24 | }) 25 | }, 26 | /** 27 | * deleteTrades 28 | * 删除商品 29 | * */ 30 | async deleteTrades(data) { 31 | return sqlTable.trades.destroy({ 32 | where: { 33 | id: data.tradeid 34 | } 35 | }) 36 | }, 37 | /** 38 | * 查询订单列表 39 | * start 开始条数 40 | * size 查询页面大小 41 | */ 42 | async getTrades(data) { 43 | return sqlTable.trades.findAndCountAll({ 44 | attributes:[['id', 'tradeid'], 'name', 'desc', 'amount', 'day', 'lv'], 45 | limit: data.page_size * 1, 46 | offset: data.start 47 | }) 48 | }, 49 | /** 50 | * 查找指定的商品 51 | * */ 52 | async findTradeById(trade_id) { 53 | return sqlTable.trades.findById(trade_id); 54 | } 55 | }; 56 | 57 | module.exports = trades; -------------------------------------------------------------------------------- /db/schema/deposits.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | // columns 3 | static deposits(Sequelize) { 4 | return { 5 | id: { 6 | type: Sequelize.BIGINT, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | allowNull: false 10 | }, 11 | userid: { 12 | type: Sequelize.STRING, 13 | allowNull: false, 14 | }, 15 | orderid: { 16 | type: Sequelize.STRING, 17 | allowNull: false, 18 | unique: true 19 | }, 20 | tradeid: { 21 | type: Sequelize.INTEGER, 22 | allowNull: false, 23 | defaultValue: 0 24 | }, 25 | //1支付宝充值,2微信充值,3购买会员,4平台消费 26 | type: { 27 | type: Sequelize.TINYINT(6), 28 | allowNull: false, 29 | }, 30 | amount: {// 31 | type: Sequelize.INTEGER 32 | }, 33 | memo: { 34 | type: Sequelize.STRING 35 | }, 36 | status: {//0生成订单 1订单成功 37 | type: Sequelize.TINYINT(1), 38 | defaultValue: 1 39 | } 40 | } 41 | } 42 | 43 | static publicSet() { 44 | return { 45 | freezeTableName: true, 46 | paranoid: true, 47 | timestamps: true, 48 | } 49 | } 50 | } 51 | 52 | module.exports = sqlTable 53 | -------------------------------------------------------------------------------- /db/schema/paychecks.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | static paychecks(Sequelize){ 3 | return { 4 | id: { 5 | type: Sequelize.BIGINT, 6 | primaryKey: true, 7 | autoIncrement: true, 8 | allowNull: false 9 | }, 10 | userid: {//用户id 11 | type: Sequelize.STRING, 12 | allowNull: false, 13 | }, 14 | appid: {// 15 | type: Sequelize.STRING, 16 | }, 17 | orderid: {//订单的id 18 | type:Sequelize.STRING, 19 | unique: true 20 | }, 21 | transid:{//支付宝,微信平台获取的交易id 22 | type: Sequelize.STRING, 23 | unique: true 24 | }, 25 | amount: {//金额 26 | type: Sequelize.FLOAT, 27 | defaultValue: 0.0 28 | }, 29 | payway:{//收款方式 30 | type: Sequelize.TINYINT(1), 31 | defaultValue: 1 32 | }, 33 | memo:{//备注 34 | type:Sequelize.STRING 35 | }, 36 | status: {//订单状态 37 | type: Sequelize.TINYINT(1), 38 | defaultValue: 1, 39 | } 40 | } 41 | } 42 | static publicSet() { 43 | return { 44 | freezeTableName: true, 45 | paranoid: true, 46 | timestamps: true, 47 | } 48 | } 49 | } 50 | 51 | module.exports = sqlTable -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "renrenpay", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node bin/www", 7 | "dev": "./node_modules/.bin/nodemon bin/www", 8 | "prd": "pm2 start bin/www", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "dependencies": { 12 | "@alicloud/sms-sdk": "^1.1.6", 13 | "async": "^2.6.2", 14 | "debug": "^2.6.3", 15 | "decimal.js": "^10.1.1", 16 | "ejs": "~2.3.3", 17 | "ioredis": "^4.9.0", 18 | "jsonwebtoken": "^8.5.0", 19 | "koa": "^2.2.0", 20 | "koa-bodyparser": "^3.2.0", 21 | "koa-convert": "^1.2.0", 22 | "koa-cors": "0.0.16", 23 | "koa-json": "^2.0.2", 24 | "koa-logger": "^2.0.1", 25 | "koa-onerror": "^1.2.1", 26 | "koa-router": "^7.1.1", 27 | "koa-session": "^5.10.1", 28 | "koa-simple-router": "^0.2.0", 29 | "koa-static": "^3.0.0", 30 | "koa-views": "^5.2.1", 31 | "lodash": "^4.17.11", 32 | "log4js": "^4.0.2", 33 | "mysql2": "^1.6.5", 34 | "nanoid": "^2.0.1", 35 | "node-fetch": "^2.3.0", 36 | "node-schedule": "^1.3.2", 37 | "nodemailer": "^5.1.1", 38 | "redis": "^2.8.0", 39 | "request": "^2.88.0", 40 | "sequelize": "^4.43.0", 41 | "shelljs": "^0.8.3", 42 | "uuid": "^3.3.2", 43 | "websocket": "^1.0.28" 44 | }, 45 | "devDependencies": { 46 | "babel-core": "^6.26.3", 47 | "babel-preset-es2015": "^6.24.1", 48 | "cross-env": "^5.2.0", 49 | "gulp": "^4.0.0", 50 | "gulp-babel": "^8.0.0", 51 | "nodemon": "^1.8.1" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /db/schema/apps.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | // columns 3 | static apps(Sequelize) { 4 | return { 5 | id: { 6 | type: Sequelize.BIGINT, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | allowNull: false 10 | }, 11 | userid: { 12 | type: Sequelize.STRING, 13 | allowNull: false, 14 | }, 15 | name: { 16 | type: Sequelize.STRING, 17 | allowNull: false 18 | // unique: true 19 | }, 20 | callback_url: { 21 | type: Sequelize.STRING 22 | }, 23 | whitelist: { 24 | type: Sequelize.STRING 25 | }, 26 | appid: { 27 | type: Sequelize.STRING, 28 | allowNull: false, 29 | unique: true 30 | }, 31 | appsecret: { 32 | type: Sequelize.STRING, 33 | allowNull: false, 34 | }, 35 | pay_userid:{ 36 | type: Sequelize.STRING, 37 | // allowNull: false 38 | }, 39 | status: { 40 | type: Sequelize.TINYINT(1), 41 | defaultValue: 1 42 | } 43 | } 44 | } 45 | 46 | static publicSet() { 47 | return { 48 | freezeTableName: true, 49 | paranoid: true, 50 | timestamps: true, 51 | } 52 | } 53 | } 54 | 55 | module.exports = sqlTable 56 | -------------------------------------------------------------------------------- /db/schema/orders.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | static orders(Sequelize){ 3 | return { 4 | id: { 5 | type: Sequelize.BIGINT, 6 | primaryKey: true, 7 | autoIncrement: true, 8 | allowNull: false 9 | }, 10 | userid: { 11 | type: Sequelize.STRING, 12 | }, 13 | appid: {//用户应用的id 14 | type: Sequelize.STRING, 15 | }, 16 | orderid: {//订单的id 17 | type:Sequelize.STRING, 18 | unique: true 19 | }, 20 | amount: {//金额 21 | type: Sequelize.BIGINT, 22 | defaultValue: 0.0 23 | }, 24 | payway:{//1支付宝,2微信 25 | type: Sequelize.INTEGER, 26 | defaultValue: 1 27 | }, 28 | qrcode:{ 29 | type:Sequelize.STRING, 30 | }, 31 | memo:{//备注 32 | type:Sequelize.STRING 33 | }, 34 | state:{//0生成订单,订单成功 35 | type: Sequelize.TINYINT(1), 36 | defaultValue: 0 37 | }, 38 | //付款码备注 39 | pay_code: { 40 | type:Sequelize.STRING, 41 | allowNull: false 42 | } 43 | } 44 | } 45 | static publicSet() { 46 | return { 47 | freezeTableName: true, 48 | paranoid: true, 49 | timestamps: true, 50 | } 51 | } 52 | } 53 | 54 | module.exports = sqlTable -------------------------------------------------------------------------------- /public/dist/static/css/chunk-0224.f01dfcab.css: -------------------------------------------------------------------------------- 1 | .login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#eee;height:47px}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #2d3a4b inset!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-b6901faa]{position:fixed;height:100%;width:100%;background-color:#2d3a4b;background:url(/static/img/bg.cf0887a.jpg) no-repeat;background-size:100% 100%}.login-container .login-form[data-v-b6901faa]{position:absolute;top:20%;left:50%;right:0;width:520px;max-width:100%;-webkit-transform:translate(-50%);transform:translate(-50%);padding:35px 35px 15px;background:rgba(0,0,0,.3);border-radius:8px}.login-container .tips[data-v-b6901faa]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips a[data-v-b6901faa]{color:#409eff}.login-container .tips-line[data-v-b6901faa]{color:hsla(0,0%,100%,.8);margin:0 10px}.login-container .svg-container[data-v-b6901faa]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title[data-v-b6901faa]{font-size:26px;font-weight:400;color:#eee;margin:0 auto 40px;text-align:center;font-weight:700}.login-container .show-pwd[data-v-b6901faa]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa') 2 | const app = new Koa() 3 | const router = require('koa-simple-router') 4 | const views = require('koa-views') 5 | const json = require('koa-json') 6 | const onerror = require('koa-onerror') 7 | const bodyparser = require('koa-bodyparser') 8 | const logger = require('koa-logger') 9 | const cors = require('koa-cors') 10 | const errorHandler = require('./utils/errorHandler.js') 11 | const controllers = require('./controllers/index.js'); 12 | let websocket = require('./utils/websocket.js'); 13 | const events = require('events'); 14 | let event = new events.EventEmitter(); 15 | require('./utils/statistic.js').scheduleCronstyle() 16 | let socket = new websocket(); 17 | 18 | require('./db/index.js') 19 | require('./init'); 20 | // error handler 21 | onerror(app) 22 | 23 | // middlewares 24 | app.use(cors()) 25 | app.use(bodyparser({ 26 | enableTypes:['json', 'form', 'text'] 27 | })) 28 | app.use(json()) 29 | app.use(logger()) 30 | app.use(require('koa-static')(__dirname + '/public/dist')) 31 | 32 | app.use(views(__dirname + '/views', { 33 | extension: 'ejs' 34 | })) 35 | 36 | // logger 37 | app.use(async (ctx, next) => { 38 | const start = new Date() 39 | await next() 40 | const ms = new Date() - start 41 | 42 | if ((/\/api\/*/).test(ctx.url)){ 43 | console.log(`${ctx.method} ${ctx.url} - ${ms}ms`) 44 | // await next() 45 | // return 46 | } 47 | 48 | }) 49 | 50 | 51 | // error handler 52 | errorHandler.error(app) 53 | // routers 54 | controllers.getAllRouters(app, router,socket,event) 55 | 56 | // error-handling 57 | app.on('error', (err, ctx) => { 58 | console.error('server error', err, ctx) 59 | }); 60 | 61 | module.exports = app 62 | -------------------------------------------------------------------------------- /utils/verifyParams.js: -------------------------------------------------------------------------------- 1 | const nonEmpty = data => { 2 | if (typeof data == 'number') { 3 | return true 4 | } 5 | 6 | if (typeof data == 'boolean') { 7 | return true 8 | } 9 | 10 | if (data && data.length > 0) { 11 | return true 12 | } 13 | 14 | return false 15 | } 16 | 17 | const verifyParams = async (data, ...params) => { 18 | let result = true 19 | 20 | params.forEach(item => { 21 | if (item === 'mobile_phone_or_email') { 22 | result = nonEmpty(data['mobile_phone']) || nonEmpty(data['email']) 23 | } else if (item === 'lv') { 24 | if (nonEmpty(data['lv'])) { 25 | if (parseInt(data['lv']) === 1 || 26 | parseInt(data['lv']) === 2) { 27 | result = true 28 | } else { 29 | result = false 30 | } 31 | } else { 32 | result = false 33 | } 34 | } else if (item === 'membership_expired') { 35 | if (nonEmpty(data['membership_expired'])) { 36 | if (parseInt(data['membership_expired']) === 30 || 37 | parseInt(data['membership_expired']) === 90 || 38 | parseInt(data['membership_expired']) === 180 || 39 | parseInt(data['membership_expired']) === 365) { 40 | result = true 41 | } else { 42 | result = false 43 | } 44 | } else { 45 | result = false 46 | } 47 | } else if (!nonEmpty(data[item])) { 48 | result = false 49 | } 50 | }) 51 | 52 | return result 53 | } 54 | 55 | module.exports = verifyParams 56 | -------------------------------------------------------------------------------- /public/dist/static/css/chunk-26f3.a8b3c6c5.css: -------------------------------------------------------------------------------- 1 | .membership-comp.edit .combo-item:hover .item-del[data-v-1fb68bb0]{-webkit-transform:translate(0);transform:translate(0)}.membership-comp .dead-line[data-v-1fb68bb0]{margin:15px 0}.membership-comp .dead-line .dead-line_member[data-v-1fb68bb0]{color:#e6a23c;margin-left:10px}.membership-comp .dead-line .dead-line_primary[data-v-1fb68bb0]{color:#333;margin-left:10px}.membership-comp .dead-line .dead-line_desc[data-v-1fb68bb0]{margin-left:10px;color:#909399;font-size:12px}.membership-comp .combo-list[data-v-1fb68bb0]{font-size:0;margin-left:-20px}.membership-comp .combo-item[data-v-1fb68bb0]{display:inline-block;width:150px;height:150px;padding:0 10px;border:1px solid #e4e7ed;border-radius:4px;text-align:center;overflow:hidden;margin-left:20px;cursor:pointer;position:relative}.membership-comp .combo-item.active[data-v-1fb68bb0]{border:1px solid #f56c6c}.membership-comp .combo-plus[data-v-1fb68bb0]{font-size:40px;line-height:150px;color:#e4e7ed}.membership-comp .item-title[data-v-1fb68bb0]{height:50px;line-height:50px;border-bottom:1px dashed #dcdfe6;font-size:18px;color:#333}.membership-comp .item-num[data-v-1fb68bb0]{font-size:18px;margin-top:15px}.membership-comp .primary[data-v-1fb68bb0]{font-size:30px;color:#f56c6c;font-weight:700;margin-right:5px}.membership-comp .item-desc[data-v-1fb68bb0]{font-size:14px;margin-top:15px}.membership-comp .item-del[data-v-1fb68bb0]{position:absolute;top:0;left:0;right:0;bottom:0;z-index:9;background:rgba(0,0,0,.8);text-align:center;font-size:30px;color:hsla(0,0%,100%,.7);padding:0 15px;-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition:all .3s;transition:all .3s}.membership-comp .item-del div[data-v-1fb68bb0]{height:75px;line-height:75px;cursor:pointer}.membership-comp .item-del div[data-v-1fb68bb0]:first-child{border-bottom:1px dashed hsla(0,0%,100%,.3)} -------------------------------------------------------------------------------- /db/sqlTable.js: -------------------------------------------------------------------------------- 1 | const appsTable = require('./schema/apps.js') 2 | const depositsTable = require('./schema/deposits.js') 3 | const usersTable = require('./schema/users.js') 4 | const withdrawsTable = require('./schema/withdraws.js') 5 | const ordersTable = require('./schema/orders.js') 6 | const paychecksTable = require('./schema/paychecks.js') 7 | const paycodeTable = require('./schema/paycode.js') 8 | const tradesTable = require('./schema/trades.js') 9 | const logsTable = require('./schema/logs.js') 10 | const statisticTable = require('./schema/statistic.js') 11 | 12 | class sqlTable { 13 | constructor(Sequelize, sequelize) { 14 | this.apps = sequelize.define('apps', appsTable.apps(Sequelize), appsTable.publicSet()) 15 | this.deposits = sequelize.define('deposits', depositsTable.deposits(Sequelize), depositsTable.publicSet()) 16 | this.users = sequelize.define('users', usersTable.users(Sequelize), usersTable.publicSet()) 17 | this.withdraws = sequelize.define('withdraws', withdrawsTable.withdraws(Sequelize), withdrawsTable.publicSet()) 18 | this.orders = sequelize.define('orders', ordersTable.orders(Sequelize), ordersTable.publicSet()) 19 | this.paychecks = sequelize.define('paychecks', paychecksTable.paychecks(Sequelize), paychecksTable.publicSet()) 20 | this.paycodes = sequelize.define('paycodes', paycodeTable.paycodes(Sequelize), paycodeTable.publicSet()) 21 | this.trades = sequelize.define('trades', tradesTable.trades(Sequelize), tradesTable.publicSet()) 22 | this.logs = sequelize.define('logs', logsTable.logs(Sequelize), logsTable.publicSet()) 23 | this.statistic = sequelize.define('statistic', statisticTable.statistic(Sequelize),statisticTable.publicSet()) 24 | sequelize.sync({ 25 | logging: false 26 | }) 27 | } 28 | } 29 | 30 | module.exports = sqlTable 31 | -------------------------------------------------------------------------------- /db/models/deposits.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const { 3 | sqlTable, 4 | } = require('../index.js') 5 | 6 | const deposits = { 7 | async addDeposit(data) { 8 | return sqlTable.deposits.create({ 9 | userid: data.userid, 10 | orderid: data.orderid, 11 | type: data.type || 0, 12 | amount: data.amount || 0, 13 | memo: data.memo || data.pay_code || data.orderid || '', 14 | status:data.status || 0 15 | }) 16 | }, 17 | 18 | async updateDepositInfo(data) { 19 | return sqlTable.deposits.update({ 20 | status: data.status || 0 21 | }, { 22 | where: { 23 | orderid: data.orderid || '0', 24 | } 25 | }) 26 | }, 27 | 28 | async getDepositList(data) { 29 | let limit = data.page_size*1; 30 | let offset = data.page_size * (data.page - 1); 31 | let w = {}; 32 | if(data.state == 1){//充值的记录 33 | w = { 34 | userid: data.userid, 35 | status:1, 36 | $or:[{type:1},{type:2}] 37 | } 38 | }else if(data.state == 2){ //购买会员的记录 39 | w = { 40 | userid: data.userid, 41 | status:1, 42 | type:3 43 | } 44 | }else if(data.state == 3){//手续费记录 45 | w = { 46 | userid: data.userid, 47 | status:1, 48 | type:4 49 | } 50 | }else{ 51 | w = { 52 | userid: data.userid, 53 | status:1 54 | } 55 | } 56 | return sqlTable.deposits.findAndCountAll({ 57 | limit, 58 | offset, 59 | where: w 60 | }) 61 | }, 62 | 63 | } 64 | 65 | module.exports = deposits 66 | -------------------------------------------------------------------------------- /public/dist/static/css/chunk-fc3b.b79580c9.css: -------------------------------------------------------------------------------- 1 | .login-container .el-input{height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#eee;height:47px}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #2d3a4b inset!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container .el-input-group__append{background:transparent;color:#eee;border:none}.login-container[data-v-b89682e8]{position:fixed;height:100%;width:100%;background-color:#2d3a4b;background:url(/static/img/bg.cf0887a.jpg) no-repeat;background-size:100% 100%}.login-container .login-form[data-v-b89682e8]{position:absolute;top:20%;left:50%;right:0;-webkit-transform:translate(-50%);transform:translate(-50%);width:520px;max-width:100%;padding:35px 35px 15px;background:rgba(0,0,0,.3);border-radius:8px}.login-container .verify-btn[data-v-b89682e8]{position:absolute;z-index:9;right:20px;top:50%;color:#fff;-webkit-transform:translateY(-50%);transform:translateY(-50%);cursor:pointer;text-align:right}.login-container .tips[data-v-b89682e8]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips a[data-v-b89682e8]{color:#409eff}.login-container .tips-line[data-v-b89682e8]{color:hsla(0,0%,100%,.5);margin:0 10px}.login-container .svg-container[data-v-b89682e8]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title[data-v-b89682e8]{font-size:26px;font-weight:400;color:#eee;margin:0 auto 40px;text-align:center;font-weight:700}.login-container .show-pwd[data-v-b89682e8]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} -------------------------------------------------------------------------------- /db/models/paychecks.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const { 3 | sqlTable,sequelize 4 | } = require('../index.js') 5 | 6 | const paychecks = { 7 | async addPaychecks(data){ 8 | return sqlTable.paychecks.create({ 9 | userid:data.userid || '', 10 | appid:data.appid || '', 11 | orderid:data.orderid || null, 12 | amount:data.amount || 0, 13 | payway:data.payway || 1, 14 | memeo:data.memeo || '', 15 | transid:data.transid || null 16 | }) 17 | }, 18 | 19 | async getList(data){ 20 | let limit = data.page_size*1; 21 | let offset = data.page_size * (data.page - 1); 22 | let w = {} 23 | if(data.state*1 === 1){//订单支付成功来源 24 | w = { 25 | userid: data.userid, 26 | orderid:{$ne:null}, 27 | } 28 | }else if(data.state*1 === 0){ //其他来源 29 | w = { 30 | userid: data.userid, 31 | orderid:{$eq:null} 32 | } 33 | }else{ 34 | w = { 35 | userid: data.userid 36 | } 37 | } 38 | return sqlTable.paychecks.findAndCountAll({ 39 | limit, 40 | offset, 41 | order: [['createdAt', 'DESC']] , 42 | where: w 43 | }) 44 | }, 45 | 46 | async totalAmount(data){ 47 | // return sequelize.query(`select amount,payway,appid from paychecks where userid=? and dayofyear(createdAt)=?`,{ 48 | return sequelize.query(`SELECT amount,payway,appid FROM paychecks WHERE userid=? and DATE_FORMAT( createdAt,'%Y-%m-%d') = DATE_FORMAT(CURDATE(),'%Y-%m-%d') ORDER BY createdAt DESC;`,{ 49 | type:Sequelize.QueryTypes.SELECT, 50 | replacements:[data.userid], 51 | }) 52 | }, 53 | } 54 | module.exports = paychecks -------------------------------------------------------------------------------- /public/dist/static/css/chunk-3200.6e36a35c.css: -------------------------------------------------------------------------------- 1 | .forget-container .el-input{height:47px;width:85%}.forget-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#eee;height:47px}.forget-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #2d3a4b inset!important;-webkit-text-fill-color:#fff!important}.forget-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.forget-container .el-input-group__append{background:transparent;color:#eee;border:none}.forget-container[data-v-6227c914]{position:fixed;height:100%;width:100%;background-color:#2d3a4b;background:url(/static/img/bg.cf0887a.jpg) no-repeat;background-size:100% 100%}.forget-container .login-form[data-v-6227c914]{position:absolute;top:20%;left:50%;right:0;-webkit-transform:translate(-50%);transform:translate(-50%);width:520px;max-width:100%;padding:35px 35px 15px;background:rgba(0,0,0,.3);border-radius:8px}.forget-container .verify-btn[data-v-6227c914]{position:absolute;z-index:9;right:20px;top:50%;color:#fff;-webkit-transform:translateY(-50%);transform:translateY(-50%);cursor:pointer;text-align:right}.forget-container .tips[data-v-6227c914]{font-size:14px;color:#fff;margin-bottom:10px}.forget-container .tips a[data-v-6227c914]{color:#409eff}.forget-container .tips-line[data-v-6227c914]{color:hsla(0,0%,100%,.5);margin:0 10px}.forget-container .svg-container[data-v-6227c914]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.forget-container .title[data-v-6227c914]{font-size:26px;font-weight:400;color:#eee;margin:0 auto 40px;text-align:center;font-weight:700}.forget-container .show-pwd[data-v-6227c914]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} -------------------------------------------------------------------------------- /db/schema/statistic.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | static statistic(Sequelize) { 3 | return { 4 | id: { 5 | type: Sequelize.BIGINT, 6 | primaryKey: true, 7 | autoIncrement: true, 8 | allowNull: false 9 | }, 10 | userid: { 11 | type: Sequelize.STRING, 12 | allowNull: false, 13 | }, 14 | appid:{ 15 | type: Sequelize.STRING, 16 | // allowNull: false, 17 | }, 18 | w_count:{//微信订单数量 19 | type: Sequelize.BIGINT, 20 | defaultValue: 0, 21 | }, 22 | p_count:{//支付宝订单数量 23 | type: Sequelize.BIGINT, 24 | defaultValue: 0, 25 | }, 26 | w_total1:{//微信已知来源总额 27 | type: Sequelize.BIGINT, 28 | defaultValue: 0, 29 | }, 30 | p_total1:{//支付宝已知来源总额 31 | type: Sequelize.BIGINT, 32 | defaultValue: 0, 33 | }, 34 | w_total2:{//微信未知来源总额 35 | type: Sequelize.BIGINT, 36 | defaultValue: 0, 37 | }, 38 | p_total2:{//支付宝未知来源总额 39 | type: Sequelize.BIGINT, 40 | defaultValue: 0, 41 | }, 42 | // payway:{ 43 | // type: Sequelize.TINYINT(1), 44 | // // defaultValue: 1 45 | // }, 46 | // status:{ 47 | // type: Sequelize.TINYINT(1), 48 | // defaultValue: 1 49 | // }, 50 | date:{ 51 | type: Sequelize.STRING, 52 | } 53 | } 54 | } 55 | static publicSet() { 56 | return { 57 | freezeTableName: true, 58 | paranoid: true, 59 | timestamps: true, 60 | } 61 | } 62 | } 63 | 64 | module.exports = sqlTable -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('demo:server'); 9 | var http = require('http'); 10 | var config = require('../conf/default.js') 11 | 12 | /** 13 | * Get port from environment and store in Express. 14 | */ 15 | 16 | var port = normalizePort(process.env.PORT || config.port); 17 | // app.set('port', port); 18 | 19 | /** 20 | * Create HTTP server. 21 | */ 22 | 23 | var server = http.createServer(app.callback()); 24 | 25 | /** 26 | * Listen on provided port, on all network interfaces. 27 | */ 28 | 29 | server.listen(port); 30 | server.on('error', onError); 31 | server.on('listening', onListening); 32 | 33 | /** 34 | * Normalize a port into a number, string, or false. 35 | */ 36 | 37 | function normalizePort(val) { 38 | var port = parseInt(val, 10); 39 | 40 | if (isNaN(port)) { 41 | // named pipe 42 | return val; 43 | } 44 | 45 | if (port >= 0) { 46 | // port number 47 | return port; 48 | } 49 | 50 | return false; 51 | } 52 | 53 | /** 54 | * Event listener for HTTP server "error" event. 55 | */ 56 | 57 | function onError(error) { 58 | if (error.syscall !== 'listen') { 59 | throw error; 60 | } 61 | 62 | var bind = typeof port === 'string' 63 | ? 'Pipe ' + port 64 | : 'Port ' + port; 65 | 66 | // handle specific listen errors with friendly messages 67 | switch (error.code) { 68 | case 'EACCES': 69 | console.error(bind + ' requires elevated privileges'); 70 | process.exit(1); 71 | break; 72 | case 'EADDRINUSE': 73 | console.error(bind + ' is already in use'); 74 | process.exit(1); 75 | break; 76 | default: 77 | throw error; 78 | } 79 | } 80 | 81 | /** 82 | * Event listener for HTTP server "listening" event. 83 | */ 84 | 85 | function onListening() { 86 | var addr = server.address(); 87 | var bind = typeof addr === 'string' 88 | ? 'pipe ' + addr 89 | : 'port ' + addr.port; 90 | console.log('Listening on ' + bind); 91 | } 92 | -------------------------------------------------------------------------------- /db/models/orders.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const { 3 | sqlTable, 4 | } = require('../index.js') 5 | 6 | const orders = { 7 | async addOrder(data) { 8 | return sqlTable.orders.create({ 9 | userid: data.userid, 10 | appid: data.appid, 11 | orderid: data.orderid || '', 12 | amount: data.amount || '', 13 | payway: data.payway || '', 14 | memo:data.memo || '', 15 | qrcode:data.qrcode || '', 16 | pay_code: data.pay_code || '' 17 | }) 18 | }, 19 | 20 | async findOne(data){ 21 | return sqlTable.orders.findOne({ 22 | where:{orderid:data.orderid} 23 | }) 24 | }, 25 | 26 | async findOne2(data){ 27 | return sqlTable.orders.findOne({ 28 | where:{memo:data.memo,userid:data.userid} 29 | }) 30 | }, 31 | 32 | async update(data){ 33 | return sqlTable.orders.update({ 34 | qrcode:data.qrcode 35 | },{ 36 | where:{ 37 | orderid:data.orderid 38 | } 39 | }) 40 | }, 41 | 42 | async update2(data){ 43 | return sqlTable.orders.update({ 44 | state:1 45 | },{ 46 | where:{ 47 | orderid:data.orderid 48 | } 49 | }) 50 | }, 51 | 52 | async getList(data){ 53 | let limit = data.page_size*1; 54 | let offset = data.page_size * (data.page - 1); 55 | let w = {} 56 | if(data.state === 0){ 57 | w = { 58 | userid: data.userid, 59 | status:0 60 | } 61 | }else if(data.state === 1){ 62 | w = { 63 | userid: data.userid, 64 | status:1 65 | } 66 | }else{ 67 | w = { 68 | userid: data.userid 69 | } 70 | } 71 | return sqlTable.deposits.findAndCountAll({ 72 | limit, 73 | offset, 74 | where: w 75 | }) 76 | } 77 | } 78 | 79 | module.exports=orders -------------------------------------------------------------------------------- /db/schema/users.js: -------------------------------------------------------------------------------- 1 | class sqlTable { 2 | // columns 3 | static users(Sequelize) { 4 | return { 5 | id: { 6 | type: Sequelize.BIGINT, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | allowNull: false 10 | }, 11 | mobile_phone: { 12 | type: Sequelize.STRING, 13 | unique: true 14 | }, 15 | email: { 16 | type: Sequelize.STRING, 17 | unique: true 18 | }, 19 | password: { 20 | type: Sequelize.STRING, 21 | allowNull: false, 22 | }, 23 | salt: { 24 | type: Sequelize.STRING, 25 | defaultValue: '' 26 | }, 27 | balance: { 28 | type: Sequelize.BIGINT, 29 | defaultValue: 100 30 | }, 31 | lv: { 32 | type: Sequelize.INTEGER, 33 | allowNull: false, 34 | defaultValue: 0 35 | }, 36 | membership_expired: { 37 | type: Sequelize.BIGINT(13), 38 | defaultValue: 0 39 | }, 40 | status: { 41 | type: Sequelize.TINYINT(1), 42 | defaultValue: 1 43 | }, 44 | nickname: { 45 | type: Sequelize.STRING, 46 | defaultValue: '' 47 | }, 48 | weixin: { 49 | type: Sequelize.STRING, 50 | defaultValue: '' 51 | }, 52 | qq: { 53 | type: Sequelize.STRING, 54 | defaultValue: '' 55 | }, 56 | address: { 57 | type: Sequelize.STRING, 58 | defaultValue: '' 59 | } 60 | } 61 | } 62 | 63 | static publicSet() { 64 | return { 65 | freezeTableName: true, 66 | paranoid: true, 67 | timestamps: true, 68 | } 69 | } 70 | } 71 | 72 | module.exports = sqlTable 73 | -------------------------------------------------------------------------------- /utils/errorCode.js: -------------------------------------------------------------------------------- 1 | const ErrorCode = { 2 | 3 | // 系统相关 4 | ERRORCODE_SERVER_INSIDE_ERROR: 1001, // 服务器错误 5 | ERRORCODE_DATABASE: 1002, // 数据库操作异常 6 | ERRORCODE_MISSING_PARAMS: 1003, // 缺少参数 7 | ERRORCODE_INVALID_PARAMS: 1004, // 参数验证失败 8 | ERRORCODE_DATA_STORAGE: 1005, // 数据保存失败 9 | ERRORCODE_SEND_SMS_FAIED: 1006, // 发送短信失败 10 | ERRORCODE_VERIFY_SMS_FAIED: 1007, // 验证短信失败 11 | ERRORCODE_SEND_EMAILCODE_FAIED: 1008, // 发送邮箱验证码失败 12 | ERRORCODE_VERIFY_EMAILCODE_FAIED: 1009, // 验证邮箱验证码失败 13 | 14 | // 应用相关 15 | ERRORCODE_APP_NOT_EXIST: 2001, // 应用不存在 16 | ERRORCODE_APP_ALREADY_EXIST: 2002, // 应用已存在 17 | ERRORCODE_APP_CREATE_FAIED: 2003, // 应用创建失败 18 | ERRORCODE_APP_OVER_LIMIT: 2004, // 应用超过上限 19 | ERRORCODE_APP_NO_CALLBACK: 2005, // 应用没有回调函数 20 | ERRORCODE_APP_GET_APPINFO_FAIED: 2006, // 应用列表获取失败 21 | ERRORCODE_APP_UPDATE_APPINFO_FAIED: 2007, // 应用信息更新失败 22 | ERRORCODE_APP_NOT_ME:2008,//应用不是本人 23 | 24 | // 用户相关 25 | ERRORCODE_USER_NOT_EXIST: 3001, // 用户不存在 26 | ERRORCODE_USER_ALREADY_EXIST: 3002, // 用户已存在 27 | ERRORCODE_USER_REGISTER_FAIED: 3003, // 用户注册失败 28 | ERRORCODE_USER_GET_SALT_FAIED: 3004, // 用户取盐失败 29 | ERRORCODE_USER_LOGIN_FAIED: 3005, // 用户登录失败 30 | ERRORCODE_USER_LOGOUT_FAIED: 3006, // 用户退出失败 31 | ERRORCODE_USER_NOT_ENOUGH_BALANCE: 3007, // 用户余额不足 32 | ERRORCODE_USER_INVALID_USERNAME_OR_PASSWORD: 3008, // 用户名/邮箱/手机号码或密码不正确 33 | ERRORCODE_USER_INVALID_TOKEN: 3009, // 用户Token错误 34 | ERRORCODE_USER_PERMISSION_DENIED: 3010, // 用户权限不足 35 | ERRORCODE_USER_INVALID_SIGNATURE: 3011, // 用户签名错误 36 | ERRORCODE_USER_GET_USERINFO_FAIED: 3012, // 用户信息获取失败 37 | ERRORCODE_USER_DEPOSIT_FAILED: 3013, // 用户充值不足 38 | ERRORCODE_USER_WITHDRAW_FAILED: 3014, // 用户提现不足 39 | ERRORCODE_USER_UPDATE_USERINFO_FAIED: 3015, // 用户信息更新失败 40 | ERRORCODE_USER_RECHARGE_MEMBERSHIP_FAILED: 3016, // 用户购买会员失败 41 | ERRORCODE_USER_BALANCE_NOT_ENOUGH: 3017, // 用户余额不足 42 | ERRORCODE_USER_PASSWORD_ERR: 3018, // 密码正确 43 | 44 | ERRORCODE_SIGN_ERROR:4001,//签名错误 45 | ERRORCODE_APPID_NOT_EXIST:4002,//appid 不存在 46 | NOT_FIND_PHONE:4003,//设备不存在 47 | 48 | ERRORCODE_PERMISSIONS_DENIED: 5001, //权限不足 49 | ERRORCODE_OVER_LOAD_LIMIT: 5002, //会员等级异常 50 | 51 | 52 | } 53 | 54 | module.exports = ErrorCode 55 | -------------------------------------------------------------------------------- /public/dist/static/css/chunk-7e70.92d696e8.css: -------------------------------------------------------------------------------- 1 | .dashboard-container[data-v-604c748c]{padding:32px}.dashboard-container .panel-group[data-v-604c748c]{margin-top:18px}.dashboard-container .panel-group .card-panel-col[data-v-604c748c]{margin-bottom:32px}.dashboard-container .panel-group .card-panel[data-v-604c748c]{display:block;height:108px;cursor:pointer;font-size:12px;position:relative;overflow:hidden;color:#666;background:#fff;-webkit-box-shadow:4px 4px 40px rgba(0,0,0,.05);box-shadow:4px 4px 40px rgba(0,0,0,.05);border-color:rgba(0,0,0,.05)}.dashboard-container .panel-group .card-panel:hover .card-panel-icon-wrapper[data-v-604c748c]{color:#fff}.dashboard-container .panel-group .card-panel:hover .icon-people[data-v-604c748c]{background:#40c9c6}.dashboard-container .panel-group .card-panel:hover .icon-message[data-v-604c748c]{background:#36a3f7}.dashboard-container .panel-group .card-panel:hover .icon-money[data-v-604c748c]{background:#f4516c}.dashboard-container .panel-group .card-panel:hover .icon-shopping[data-v-604c748c]{background:#34bfa3}.dashboard-container .panel-group .card-panel .icon-people[data-v-604c748c]{color:#40c9c6}.dashboard-container .panel-group .card-panel .icon-message[data-v-604c748c]{color:#36a3f7}.dashboard-container .panel-group .card-panel .icon-money[data-v-604c748c]{color:#f4516c}.dashboard-container .panel-group .card-panel .icon-shopping[data-v-604c748c]{color:#34bfa3}.dashboard-container .panel-group .card-panel .card-panel-icon-wrapper[data-v-604c748c]{float:left;margin:14px 0 0 14px;padding:16px;-webkit-transition:all .38s ease-out;transition:all .38s ease-out;border-radius:6px}.dashboard-container .panel-group .card-panel .card-panel-icon[data-v-604c748c]{float:left;font-size:48px}.dashboard-container .panel-group .card-panel .card-panel-description[data-v-604c748c]{float:right;font-weight:700;padding:0 30px;margin:26px 0;text-align:right}.dashboard-container .panel-group .card-panel .card-panel-description.primary[data-v-604c748c]{border-right:1px solid #ccc}.dashboard-container .panel-group .card-panel .card-panel-description .card-panel-text[data-v-604c748c]{line-height:18px;color:rgba(0,0,0,.45);font-size:14px;margin-bottom:12px;font-weight:400}.dashboard-container .panel-group .card-panel .card-panel-description .card-panel-num[data-v-604c748c]{font-size:20px}.dashboard-container .chart-title[data-v-604c748c]{text-align:center;font-size:20px;color:#36a3f7;margin:30px 0 20px} -------------------------------------------------------------------------------- /init/index.js: -------------------------------------------------------------------------------- 1 | const users = require("../db/models/users"); 2 | const apps = require("../db/models/apps"); 3 | const crypto = require('crypto'); 4 | const MD5 = require('../utils/md5.js'); 5 | const config = require('../conf/default') 6 | const initController = { 7 | // 初始化用户信息 8 | async initAdmin() { 9 | try { 10 | let sum = 1; 11 | const pwd = MD5(config.adminPwd); 12 | let data = { 13 | mobile_phone: 'admin', 14 | password: pwd, 15 | lv: 99, 16 | // nick_name: 'Rick Chen', 17 | amount: 1000000000, 18 | pay_userid:'2088112172418889', 19 | membership_expired:'9999999999999' 20 | // e_mail: '573099498@qq.com', 21 | // wechart: 'cxyxxx0924', 22 | }; 23 | // 添加用户 24 | const admin = await users.getUserById({userid: 1}); 25 | if(!admin) 26 | await users.addUser(data); 27 | } catch (err) { 28 | console.log(err) 29 | console.error(`initAdmin--${err}`); 30 | } 31 | }, 32 | async initApps() { 33 | const uuidv1 = require('uuid/v1') 34 | // const appid = uuidv1().substring(24, 36) 35 | const appid = config.appid; 36 | console.info(appid); 37 | const appsecret = MD5(appid + Date.now()).toUpperCase() 38 | console.info(appsecret, '--'); 39 | try { 40 | let data = { 41 | userid: config.userid, 42 | name: 'renrenpay', 43 | callback_url: 'http://127.0.0.1:3000/api/deposits/verbCall', 44 | whitelist: '', 45 | appid: appid, 46 | appsecret: appsecret, 47 | pay_userid: config.pay_userid 48 | }; 49 | await apps.chkAppExist(data).then(result => { 50 | if (result.count > 0) { 51 | throw { 52 | code: 3000 53 | } 54 | } 55 | }) 56 | await apps.addApplication(data); 57 | } catch (err) { 58 | console.log(err); 59 | console.error(`initApps--${err}`); 60 | } 61 | } 62 | } 63 | setTimeout(item => { 64 | initController.initAdmin(); 65 | initController.initApps(); 66 | }, 3000) 67 | -------------------------------------------------------------------------------- /utils/verifyToken.js: -------------------------------------------------------------------------------- 1 | const errorCode = require('./errorCode.js') 2 | const redisClient = require('./redisClient.js') 3 | const returnCodesAndMessages = require('./returnJson.js') 4 | const Jwt = require('./jwt.js') 5 | const { 6 | loggerHttp 7 | } = require('./logger.js') 8 | 9 | const verifyToken = async (ctx, rank = 0) => { 10 | try { 11 | const token = ctx.request.header.token 12 | 13 | if (token) { 14 | // 验证Token 15 | let jwt = new Jwt(token) 16 | let result = jwt.verifyToken() 17 | if (!result || result === 'err') { 18 | throw { 19 | code: errorCode.ERRORCODE_USER_INVALID_TOKEN 20 | } 21 | } 22 | ctx.state.user = result 23 | // 判断用户等级 24 | if (rank <= result.lv) { 25 | return result 26 | } else { 27 | throw { 28 | code: errorCode.ERRORCODE_USER_PERMISSION_DENIED 29 | } 30 | } 31 | } else { 32 | throw { 33 | code: errorCode.ERRORCODE_USER_INVALID_TOKEN 34 | } 35 | } 36 | } catch (err) { 37 | if (err.code) { 38 | returnCodesAndMessages.err(ctx, err.code, err.message) 39 | } else { 40 | returnCodesAndMessages.err(ctx, errorCode.ERRORCODE_SERVER_INSIDE_ERROR, '') 41 | loggerHttp.error(`verifyToken -- ${err}`) 42 | } 43 | } 44 | } 45 | 46 | const verifyToken2 = async (ctx, rank = 0)=>{ 47 | try { 48 | const token = ctx.request.header.token 49 | 50 | if (token) { 51 | let result = await redisClient.get('3', token); 52 | if(result){ 53 | ctx.state.user = JSON.parse(result); 54 | return JSON.parse(result); 55 | }else { 56 | throw { 57 | code: errorCode.ERRORCODE_USER_PERMISSION_DENIED 58 | } 59 | } 60 | } else { 61 | throw { 62 | code: errorCode.ERRORCODE_USER_INVALID_TOKEN 63 | } 64 | } 65 | } catch (err) { 66 | if (err.code) { 67 | returnCodesAndMessages.err(ctx, err.code, err.message) 68 | } else { 69 | returnCodesAndMessages.err(ctx, errorCode.ERRORCODE_SERVER_INSIDE_ERROR, '') 70 | loggerHttp.error(`verifyToken -- ${err}`) 71 | } 72 | } 73 | } 74 | 75 | module.exports = { 76 | verifyToken, 77 | verifyToken2 78 | } 79 | -------------------------------------------------------------------------------- /public/dist/static/js/chunk-f779.74ec5683.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-f779"],{DmCF:function(e,r,s){"use strict";var t=s("gEW1");s.n(t).a},gEW1:function(e,r,s){},nIie:function(e,r,s){"use strict";s.r(r);var t=s("14Xm"),a=s.n(t),o=s("D3Ub"),n=s.n(o),i=s("wk8/"),l=s("gjeX"),p=s.n(l),d=s("QqA1"),u=s.n(d),c={data:function(){var e=this;return{active:"first",loading:!1,form:{old_password:"",new_password:"",new_password_confirm:""},rules:{old_password:[{required:!0,message:"请输入旧密码",trigger:"blur"}],new_password:[{required:!0,message:"请输入新密码",trigger:"blur"},{min:6,message:"密码长度不低于6位",trigger:"blur"}],new_password_confirm:[{required:!0,message:"请再次输入密码",trigger:"blur"},{validator:function(r,s,t){s!==e.form.new_password?t(new Error("两次输入密码不一致!")):t()},trigger:"blur"}]}}},methods:{submit:function(){var e=this;this.$refs.form.validate(function(){var r=n()(a.a.mark(function r(s){var t;return a.a.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:if(!s){r.next=12;break}return e.loading=!0,(t=u()({},e.form)).old_password=p()(t.old_password),t.new_password=p()(t.new_password),r.next=7,Object(i.i)(t);case 7:if(null!==r.sent){r.next=10;break}return r.abrupt("return");case 10:e.loading=!1,e.$message({type:"success",message:"修改密码成功"});case 12:case"end":return r.stop()}},r,e)}));return function(e){return r.apply(this,arguments)}}())}}},m=(s("DmCF"),s("KHd+")),w=Object(m.a)(c,function(){var e=this,r=e.$createElement,s=e._self._c||r;return s("div",{staticClass:"settings-index-page"},[s("el-tabs",{model:{value:e.active,callback:function(r){e.active=r},expression:"active"}},[s("el-tab-pane",{attrs:{label:"修改密码",name:"first"}},[s("el-form",{ref:"form",staticStyle:{"max-width":"600px"},attrs:{model:e.form,rules:e.rules,"label-width":"100px"}},[s("el-form-item",{attrs:{label:"旧密码",prop:"old_password"}},[s("el-input",{attrs:{type:"password"},model:{value:e.form.old_password,callback:function(r){e.$set(e.form,"old_password",r)},expression:"form.old_password"}})],1),e._v(" "),s("el-form-item",{attrs:{label:"新密码",prop:"new_password"}},[s("el-input",{attrs:{type:"password"},model:{value:e.form.new_password,callback:function(r){e.$set(e.form,"new_password",r)},expression:"form.new_password"}})],1),e._v(" "),s("el-form-item",{attrs:{label:"新密码确认",prop:"new_password_confirm"}},[s("el-input",{attrs:{type:"password"},model:{value:e.form.new_password_confirm,callback:function(r){e.$set(e.form,"new_password_confirm",r)},expression:"form.new_password_confirm"}})],1),e._v(" "),s("el-form-item",[s("el-button",{attrs:{loading:e.loading,type:"primary"},on:{click:e.submit}},[e._v("提交")])],1)],1)],1)],1)],1)},[],!1,null,"3815b536",null);w.options.__file="Index.vue";r.default=w.exports}}]); -------------------------------------------------------------------------------- /controllers/withdrawsController.js: -------------------------------------------------------------------------------- 1 | const nanoid = require('nanoid') 2 | const _ = require('lodash') 3 | const { 4 | loggerHttp 5 | } = require('../utils/logger.js') 6 | const ErrorCode = require('../utils/errorCode.js') 7 | const returnJson = require('../utils/returnJson.js') 8 | const redisCli = require('../utils/redisClient.js') 9 | const MD5 = require('../utils/md5.js') 10 | const Jwt = require('../utils/jwt.js') 11 | const verifyParams = require('../utils/verifyParams.js') 12 | const verifyToken = require('../utils/verifyToken.js') 13 | const sendSms = require('../utils/sendSms.js') 14 | const sendEmail = require('../utils/sendEmail.js') 15 | const withdraws = require('../db/models/withdraws.js') 16 | const users = require('../db/models/users.js') 17 | const uuidv1 = require('uuid/v1') 18 | 19 | const withdrawsController = { 20 | withdraw() { 21 | return async (ctx, next) => { 22 | try { 23 | const data = ctx.request.body 24 | data.userid = ctx.state.user.id 25 | data.action = 'withdraw' 26 | data.uuid = uuidv1() 27 | data.memo = '' 28 | 29 | // 判断参数是否缺少 30 | await verifyParams(data, 'type', 'amount', 'memo').then(result => { 31 | if (!result) { 32 | throw { 33 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 34 | message: '或者参数错误' 35 | } 36 | } 37 | }) 38 | 39 | // 添加提现记录 40 | await withdraws.addWithdraw(data).then(result => { 41 | if (!result) { 42 | throw { 43 | code: ErrorCode.ERRORCODE_USER_WITHDRAW_FAILED, 44 | message: '添加提现记录错误' 45 | } 46 | } 47 | }) 48 | 49 | // 更新balance 50 | await users.updateBalance(data).then(result => { 51 | if (result[0]) { 52 | returnJson.success(ctx) 53 | } else { 54 | throw { 55 | code: ErrorCode.ERRORCODE_USER_NOT_EXIST 56 | } 57 | } 58 | }) 59 | } catch (err) { 60 | console.info(`${ctx.url} -- `,err) 61 | if (err.code) { 62 | returnJson.err(ctx, err.code, err.message) 63 | } else { 64 | returnJson.err(ctx, ErrorCode.ERRORCODE_USER_WITHDRAW_FAILED) 65 | } 66 | } 67 | } 68 | }, 69 | } 70 | 71 | module.exports = withdrawsController 72 | -------------------------------------------------------------------------------- /public/dist/static/js/chunk-54db.2bca911d.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-54db"],{"4XeK":function(t,e,a){"use strict";a.d(e,"a",function(){return o}),a.d(e,"b",function(){return r});var n=a("t3Un"),o=function(t){var e=t.payway,a=t.amount;return Object(n.a)({url:"/api/deposits/qrcode",method:"post",data:{payway:e,amount:a}})},r=function(t){var e=t.page,a=void 0===e?1:e,o=t.page_size,r=void 0===o?10:o,i=t.state,s=void 0===i?"":i;return Object(n.a)({url:"/api/deposits/list",method:"get",data:{page:a,page_size:r,state:s}})}},E8qc:function(t,e,a){"use strict";a.r(e);var n=a("14Xm"),o=a.n(n),r=a("D3Ub"),i=a.n(r),s=a("4XeK"),c={data:function(){return{form:{page:1,page_size:10},total:0,loading:!1,list:[]}},created:function(){this.fetch()},methods:{fetch:function(){var t=this;return i()(o.a.mark(function e(){var a;return o.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t.loading=!0,e.next=3,Object(s.b)(t.form);case 3:if(a=e.sent,t.loading=!1,null!==a){e.next=7;break}return e.abrupt("return");case 7:a.rows.forEach(function(t){t._createdAt=new Date(t.createdAt).toLocaleString()}),t.list=a.rows,t.total=a.count;case 10:case"end":return e.stop()}},e,t)}))()}}},l=a("KHd+"),u=Object(l.a)(c,function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"bill-index-page"},[a("el-table",{staticStyle:{width:"100%","margin-top":"20px"},attrs:{data:t.list,loading:t.loading,stripe:""}},[a("el-table-column",{attrs:{prop:"orderid",label:"id","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{prop:"_createdAt",label:"时间","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{prop:"amount",label:"类型","min-width":"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[a("div",[1==e.row.type?a("div",{staticStyle:{color:"#00aae8"}},[a("svg-icon",{attrs:{"icon-class":"zhifubao"}}),t._v(" 支付宝充值")],1):t._e(),t._v(" "),2==e.row.type?a("div",{staticStyle:{color:"#09bb07"}},[a("svg-icon",{attrs:{"icon-class":"wepay"}}),t._v(" 微信充值")],1):t._e(),t._v(" "),3==e.row.type?a("el-tag",{attrs:{type:"success"}},[t._v("购买会员")]):t._e(),t._v(" "),4==e.row.type?a("el-tag",{attrs:{type:"success"}},[t._v("手续费扣除")]):t._e()],1)]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"amount",label:"金额(元)","min-width":"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[1==e.row.type||2==e.row.type?a("div",[a("b",{staticStyle:{color:"#409EFF","font-size":"16px","font-weight":"400"}},[t._v("+ "+t._s(e.row.amount/100)+" ")])]):a("div",[a("span",{staticStyle:{color:"#909399"}},[t._v("- "+t._s(e.row.amount/100))])])]}}])})],1),t._v(" "),a("el-pagination",{staticStyle:{"text-align":"right","margin-top":"20px"},attrs:{background:"",layout:"prev, pager, next",total:t.total,"current-page":t.form.page},on:{"update:currentPage":function(e){t.$set(t.form,"page",e)},"current-change":t.fetch}})],1)},[],!1,null,null,null);u.options.__file="index.vue";e.default=u.exports}}]); -------------------------------------------------------------------------------- /utils/websocket.js: -------------------------------------------------------------------------------- 1 | const WebsocketServer = require('websocket').server 2 | const http = require('http') 3 | const wsMap = new Map() 4 | const ErrorCode = require('../utils/errorCode.js') 5 | const config = require('../conf/default.js') 6 | 7 | 8 | const httpServer = http.createServer(function (req, res) { 9 | console.log((new Date()) + ' Received request for ' + req.url) 10 | res.writeHead(404) 11 | res.end() 12 | }) 13 | 14 | function websocket() { 15 | httpServer.listen(config.websocket.port, function () { 16 | console.log((new Date()) + ' Server is listening on port ' + config.websocket.port) 17 | }) 18 | 19 | let wsServer = new WebsocketServer({ 20 | httpServer: httpServer, 21 | autoAcceptConnections: false 22 | }) 23 | 24 | wsServer.on('request', async function (req) { 25 | // let connection = req.accept('echo-protocol', req.origin); 26 | console.info(req.resourceURL.query.user) 27 | console.log((new Date()) + ' Origin: ' + req.origin) 28 | if (!originIsAllowed(req.origin)) { 29 | req.reject() 30 | console.log((new Date()) + ' Connection from origin ' + req.origin + ' rejected.') 31 | return 32 | } 33 | let conn; 34 | try { 35 | conn = req.accept('echo-protocol', req.origin); 36 | } catch (error) { 37 | wsMap.delete(req.origin) 38 | return error 39 | } 40 | let key = req.resourceURL.query.user; 41 | if(key) { 42 | console.info('--->',key); 43 | wsMap.set(key.toString(), conn) 44 | } else { 45 | return 46 | } 47 | 48 | console.log((new Date()) + ' Connection from origin ' + req.origin + ' accepted.') 49 | 50 | conn.on('message', async function (msg) { 51 | console.log(req.origin + ' >>>',req.resourceURL.query.user) 52 | console.log('Received message: ' + msg.utf8Data) 53 | }) 54 | 55 | conn.on('close', function (reasonCode, desc) { 56 | console.log(req.origin + ' >>>') 57 | console.log('Received close: ' + reasonCode + ' desc: ' + desc) 58 | 59 | wsMap.delete(req.origin) 60 | console.log((new Date()) + ' Peer ' + conn.remoteAddrress + ' disconnected.') 61 | }) 62 | }) 63 | } 64 | 65 | function originIsAllowed(origin) { 66 | return true 67 | } 68 | 69 | websocket.prototype.sendMsg = function(useId, msg) { 70 | try { 71 | console.info(useId,msg); 72 | const connection = wsMap.get(useId + ""); 73 | if(!connection) 74 | throw {code: ErrorCode.NOT_FIND_PHONE, message: "没有找到设备"} 75 | connection.sendUTF(msg); 76 | } catch (error) { 77 | console.log(error) 78 | throw {code: ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR, message: "sendMsg error"} 79 | } 80 | 81 | }; 82 | 83 | module.exports = websocket 84 | -------------------------------------------------------------------------------- /public/dist/static/js/chunk-0224.e4d32421.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-0224"],{B30W:function(t,n,e){},"Yq+K":function(t,n,e){"use strict";var s=e("B30W");e.n(s).a},c11S:function(t,n,e){"use strict";var s=e("gTgX");e.n(s).a},gTgX:function(t,n,e){},ntYl:function(t,n,e){"use strict";e.r(n);var s=e("14Xm"),o=e.n(s),a=e("D3Ub"),i=e.n(a),r=(e("gjeX"),{name:"Login",data:function(){return{account:"",loginForm:{password:"",mobile_phone:"",email:""},loading:!1,pwdType:"password",redirect:void 0}},watch:{$route:{handler:function(t){this.redirect=t.query&&t.query.redirect},immediate:!0}},methods:{showPwd:function(){"password"===this.pwdType?this.pwdType="":this.pwdType="password"},handleLogin:function(){var t=this;return i()(o.a.mark(function n(){var e;return o.a.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:return t.account||t.$message({type:"warning",message:"请输入邮箱或者手机号"}),/\d{11}/.test(t.account)||"admin"==t.account?t.loginForm.mobile_phone=t.account:t.loginForm.email=t.account,t.loading=!0,n.next=5,t.$store.dispatch("Login",t.loginForm);case 5:e=n.sent,t.loading=!1,null!==e&&(t.$message({type:"success",message:"登录成功"}),t.$router.push({path:"/"}));case 8:case"end":return n.stop()}},n,t)}))()}}}),c=(e("c11S"),e("Yq+K"),e("KHd+")),l=Object(c.a)(r,function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{staticClass:"login-container"},[e("el-form",{ref:"loginForm",staticClass:"login-form",attrs:{model:t.loginForm,"auto-complete":"on","label-position":"left"}},[e("h3",{staticClass:"title"},[t._v("人人收付")]),t._v(" "),e("el-form-item",[e("span",{staticClass:"svg-container"},[e("svg-icon",{attrs:{"icon-class":"phone"}})],1),t._v(" "),e("el-input",{attrs:{name:"phone",type:"text","auto-complete":"on",placeholder:"邮箱/手机号"},model:{value:t.account,callback:function(n){t.account=n},expression:"account"}})],1),t._v(" "),e("el-form-item",{attrs:{prop:"password"}},[e("span",{staticClass:"svg-container"},[e("svg-icon",{attrs:{"icon-class":"password"}})],1),t._v(" "),e("el-input",{attrs:{type:t.pwdType,name:"password","auto-complete":"on",placeholder:"请输入密码"},nativeOn:{keyup:function(n){return"button"in n||!t._k(n.keyCode,"enter",13,n.key,"Enter")?t.handleLogin(n):null}},model:{value:t.loginForm.password,callback:function(n){t.$set(t.loginForm,"password",n)},expression:"loginForm.password"}}),t._v(" "),e("span",{staticClass:"show-pwd",on:{click:t.showPwd}},[e("svg-icon",{attrs:{"icon-class":"password"===t.pwdType?"eye":"eye-open"}})],1)],1),t._v(" "),e("el-form-item",[e("el-button",{staticStyle:{width:"100%"},attrs:{loading:t.loading,type:"primary"},on:{click:t.handleLogin}},[t._v("\n 登录\n ")])],1),t._v(" "),e("div",{staticClass:"tips"},[e("router-link",{staticClass:"tips-link",attrs:{to:{path:"forget"}}},[t._v("忘记密码?")]),t._v(" "),e("span",{staticClass:"tips-line"},[t._v("|")]),t._v(" "),e("router-link",{staticClass:"tips-link",attrs:{to:{path:"register"}}},[t._v(" 注册")])],1)],1)],1)},[],!1,null,"b6901faa",null);l.options.__file="index.vue";n.default=l.exports}}]); -------------------------------------------------------------------------------- /db/models/apps.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const { 3 | sqlTable, 4 | } = require('../index.js') 5 | 6 | const apps = { 7 | async addApplication(data) { 8 | return sqlTable.apps.create({ 9 | userid: data.userid, 10 | name: data.name, 11 | callback_url: data.callback_url || '', 12 | whitelist: data.whitelist || '', 13 | appid: data.appid, 14 | appsecret: data.appsecret, 15 | pay_userid:data.pay_userid, 16 | status: 1 17 | }) 18 | }, 19 | 20 | async chkAppExist(data) { 21 | return sqlTable.apps.findAndCountAll({ 22 | where: { 23 | userid: data.userid, 24 | name: data.name 25 | } 26 | }) 27 | }, 28 | async chkAppExist2(data) { 29 | return sqlTable.apps.findAndCountAll({ 30 | where: { 31 | userid: data.userid, 32 | name: data.name, 33 | id:{$ne:data.id} 34 | } 35 | }) 36 | }, 37 | async getAppCount(data) { 38 | return sqlTable.apps.findAndCountAll({ 39 | where: { 40 | userid: data.userid, 41 | } 42 | }) 43 | }, 44 | 45 | async getApps(data) { 46 | let limit = data.page_size*1; 47 | let offset = data.page_size * (data.page - 1); 48 | return sqlTable.apps.findAndCount({ 49 | limit, 50 | offset, 51 | where: { 52 | userid: data.userid, 53 | } 54 | }) 55 | }, 56 | 57 | async queryApps(data) { 58 | return sqlTable.apps.findAll({ 59 | where: { 60 | appid: data.appid, 61 | } 62 | }) 63 | }, 64 | 65 | async updateAppInfo(data) { 66 | return sqlTable.apps.update({ 67 | callback_url: data.callback_url || '', 68 | whitelist: data.whitelist || '', 69 | name: data.name, 70 | pay_userid:data.pay_userid 71 | }, { 72 | where: { 73 | id: data.id || 0, 74 | userid: data.userid 75 | } 76 | }) 77 | }, 78 | 79 | async deleteApp(data) { 80 | return sqlTable.apps.destroy({ 81 | where: { 82 | id: data.id, 83 | userid: data.userid 84 | } 85 | }) 86 | }, 87 | 88 | async allApps(data) { 89 | return sqlTable.apps.findAll({ 90 | where: { 91 | userid: data.userid, 92 | } 93 | }) 94 | }, 95 | 96 | async isMeApp(data) { 97 | return sqlTable.apps.findAll({ 98 | where: { 99 | userid: data.userid, 100 | appid: data.appid 101 | } 102 | }) 103 | } 104 | } 105 | 106 | module.exports = apps 107 | -------------------------------------------------------------------------------- /public/dist/static/css/chunk-280b.7469e992.css: -------------------------------------------------------------------------------- 1 | .pay-comp[data-v-549a193a]{text-align:center}.pay-comp.wepay .deposit-title[data-v-549a193a]{color:#09bb07}.pay-comp.alipay .deposit-title[data-v-549a193a]{color:#00aae8}.pay-comp .deposit-title[data-v-549a193a]{font-size:24px}.pay-comp .deposit-num[data-v-549a193a]{font-size:40px;font-weight:700;margin-top:30px;color:#606266}.deposit-comp[data-v-3258e044]{padding:0 20px 20px;-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04);box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04);border:1px solid #dcdfe6;color:#606266;font-size:14px}.deposit-comp .balance-cell[data-v-3258e044]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:60px;border-bottom:1px solid #dcdfe6}.deposit-comp .balance-cell .cell-bd[data-v-3258e044]{margin-left:10px}.deposit-comp .balance-cell .primary[data-v-3258e044]{color:#f56c6c}.deposit-comp .balance-cell .cell-ft[data-v-3258e044]{margin-left:30px}.deposit-comp .amount-list[data-v-3258e044]{margin-left:-15px}.deposit-comp .amount-item[data-v-3258e044]{display:inline-block;width:100px;height:100px;line-height:100px;vertical-align:middle;border:1px solid #e4e7ed;border-radius:4px;text-align:center;cursor:pointer;margin-left:15px;margin-bottom:20px;font-size:20px;color:#606266;font-weight:400}.deposit-comp .amount-item[data-v-3258e044]:hover{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.deposit-comp .amount-item.hover[data-v-3258e044]{border:1px solid #409eff;color:#409eff}.deposit-comp .amount-item .desc[data-v-3258e044]{font-size:16px}.deposit-comp .num-widget[data-v-3258e044]{font-size:24px;vertical-align:super}.deposit-comp .combo-list[data-v-3258e044]{font-size:0;margin-left:-20px}.deposit-comp .combo-list .combo-item[data-v-3258e044]{display:inline-block;width:150px;height:150px;padding:0 10px;border:1px solid #e4e7ed;border-radius:4px;text-align:center;overflow:hidden;margin-left:20px;cursor:pointer}.deposit-comp .combo-list .combo-item.active[data-v-3258e044]{border:1px solid #f56c6c}.deposit-comp .combo-list .item-title[data-v-3258e044]{height:50px;line-height:50px;border-bottom:1px dashed #dcdfe6;font-size:18px;color:#333}.deposit-comp .combo-list .item-num[data-v-3258e044]{font-size:18px;margin-top:15px}.deposit-comp .combo-list .primary[data-v-3258e044]{font-size:30px;color:#f56c6c;font-weight:700;margin-right:5px}.deposit-comp .combo-list .item-desc[data-v-3258e044]{font-size:14px;margin-top:15px}.intro-index-page .sec[data-v-63a081ac]{padding:0 20px 20px;-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04);box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04);border:1px solid #dcdfe6;color:#606266;font-size:14px;margin-top:20px}.intro-index-page .sec-title[data-v-63a081ac]{height:60px;line-height:60px;font-size:16px;border-bottom:1px solid #dcdfe6;color:#303133}.intro-index-page .title[data-v-63a081ac]{font-size:15px;margin:20px 0}.intro-index-page .text[data-v-63a081ac]{font-size:14px;margin:10px 0;line-height:1.8} -------------------------------------------------------------------------------- /controllers/ordersController.js: -------------------------------------------------------------------------------- 1 | const nanoid = require('nanoid') 2 | const _ = require('lodash') 3 | const { 4 | loggerHttp 5 | } = require('../utils/logger.js') 6 | const ErrorCode = require('../utils/errorCode.js') 7 | const returnJson = require('../utils/returnJson.js') 8 | const redisCli = require('../utils/redisClient.js') 9 | const MD5 = require('../utils/md5.js') 10 | const Jwt = require('../utils/jwt.js') 11 | const verifyParams = require('../utils/verifyParams.js') 12 | const verifyToken = require('../utils/verifyToken.js') 13 | const sendSms = require('../utils/sendSms.js') 14 | const sendEmail = require('../utils/sendEmail.js') 15 | const deposits = require('../db/models/deposits.js') 16 | const users = require('../db/models/users.js') 17 | const uuidv1 = require('uuid/v1') 18 | const orders = require('../db/models/orders.js') 19 | 20 | const ordersController={ 21 | getList(){//查询订单列表 22 | return async (ctx, next)=>{ 23 | try { 24 | const data = ctx.query 25 | data.userid = ctx.state.user.id 26 | data.page = data.page || 1 27 | data.page_size = data.page_size || 10 28 | 29 | await verifyParams(data, 'userid').then(result => {// 30 | if (!result) { 31 | throw { 32 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 33 | message: '或者参数错误' 34 | } 35 | } 36 | }) 37 | await orders.getList(data).then(result=>{ 38 | returnJson.success(ctx, result); 39 | }) 40 | } catch (err) { 41 | console.info(`${ctx.url} -- `, err) 42 | if(err.code) { 43 | returnJson.err(ctx, err.code, err.message); 44 | } else { 45 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR) 46 | } 47 | } 48 | 49 | 50 | } 51 | }, 52 | 53 | getDetail(){//查询订单详情 54 | return async(ctx,next)=>{ 55 | try { 56 | const data = ctx.query 57 | data.userid = ctx.state.user.id 58 | await verifyParams(data, 'orderid').then(result => { 59 | if (!result) { 60 | throw { 61 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 62 | message: '或者参数错误' 63 | } 64 | } 65 | }) 66 | 67 | await orders.findOne(data).then(result=>{ 68 | returnJson.success(ctx, result); 69 | }) 70 | } catch (err) { 71 | console.info(`${ctx.url} -- `, err) 72 | if(err.code) { 73 | returnJson.err(ctx, err.code, err.message); 74 | } else { 75 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR) 76 | } 77 | } 78 | } 79 | } 80 | } 81 | 82 | module.exports = ordersController; -------------------------------------------------------------------------------- /utils/redisClient.js: -------------------------------------------------------------------------------- 1 | // const redis = require('redis') 2 | // const bluebird = require('bluebird') 3 | // const config = require('../conf/default.js') 4 | // const { 5 | // loggerHttp 6 | // } = require('./logger.js') 7 | 8 | // const redis_client = redis.createClient(config.redis.port, config.redis.host) 9 | 10 | // bluebird.promisifyAll(redis.RedisClient.prototype) 11 | // bluebird.promisifyAll(redis.Multi.prototype) 12 | 13 | // redis_client.on('error', err => { 14 | // loggerHttp.error(`redis -- ${err}`) 15 | // }) 16 | 17 | // const redis_cli = { 18 | 19 | // async set (db, key, value, expired) { 20 | 21 | // await redis_client.selectAsync(db) 22 | 23 | // await redis_client.setAsync(key, value) 24 | 25 | // return redis_client.expireAsync(key, expired) 26 | // }, 27 | 28 | // async get (db, key) { 29 | // await redis_client.selectAsync(db) 30 | 31 | // return await redis_client.getAsync(key) 32 | // }, 33 | 34 | // async del(db, key) { 35 | // await redis_client.selectAsync(db) 36 | 37 | // return await redis_client.delAsync(key) 38 | // }, 39 | // async push(key, value, expired) { 40 | // await redis_client.selectAsync(7) 41 | // await redis_client.lpush(key, value); 42 | // return await redis_client.expireAsync(key, expired); 43 | // }, 44 | // async getList(key) { 45 | // await redis_client.selectAsync(7) 46 | // return await redis_client.lrange(key, 0, 100); 47 | // } 48 | // } 49 | 50 | 51 | 52 | const Redis = require('ioredis') 53 | const bluebird = require('bluebird') 54 | const config = require('../conf/default.js') 55 | 56 | const redis_client = new Redis({ 57 | port: config.redis.port, 58 | host: config.redis.host, 59 | family: 4, 60 | // password:settings.ioredis.password, 61 | db: 0 62 | }); 63 | redis_client.on('connect', function () { 64 | // console.info('Reids connect success') 65 | }); 66 | redis_client.on('end', function () { 67 | console.error('Redis connect error') 68 | }); 69 | 70 | const redis_cli = { 71 | 72 | async set (db, key, value, expired) { 73 | await redis_client.select(db) 74 | // await redis_client.set(key, value,'EX',expired) 75 | await redis_client.set(key, value) 76 | return redis_client.expire(key, expired) 77 | }, 78 | 79 | async get (db, key) { 80 | await redis_client.select(db) 81 | return await redis_client.get(key) 82 | }, 83 | 84 | async del(db, key) { 85 | await redis_client.select(db) 86 | return await redis_client.del(key) 87 | }, 88 | 89 | async push(key, value, expired) { 90 | await redis_client.select(4) 91 | await redis_client.lpush(key, value); 92 | return await redis_client.expire(key, expired); 93 | }, 94 | async getList(key) { 95 | await redis_client.select(4) 96 | return await redis_client.lrange(key, 0, 100); 97 | }, 98 | async remove(key,value){ 99 | await redis_client.select(4) 100 | await redis_client.lrem(key,0,value) 101 | } 102 | 103 | } 104 | 105 | module.exports = redis_cli -------------------------------------------------------------------------------- /utils/errorHandler.js: -------------------------------------------------------------------------------- 1 | const { 2 | loggerHttp, 3 | loggerHttpInfo 4 | } = require('./logger.js') 5 | const verify = require('./verifyToken.js') 6 | const ErrorCode = require('../utils/errorCode.js') 7 | const returnJson = require('../utils/returnJson.js') 8 | const errorHandler = { 9 | error(app) { 10 | // 判断Token 11 | app.use(async (ctx, next) => { 12 | try { 13 | if (ctx.url === '/') { 14 | await next() 15 | return 16 | } 17 | if ((/\/api\/users\/sms\?mobile_phone=.*/ ).test(ctx.url)) { 18 | await next() 19 | return 20 | } 21 | if ((/\/api\/users\/email\?email=.*/ ).test(ctx.url)) { 22 | await next() 23 | return 24 | } 25 | if ((/\/api3\/*/).test(ctx.url)){ 26 | await next() 27 | return 28 | } 29 | if (ctx.url === '/api/users/register') { 30 | await next() 31 | return 32 | } 33 | if (ctx.url === '/api/users/forget') { 34 | await next() 35 | return 36 | } 37 | if ((/\/api\/users\/salt\?mobile_phone=.*/).test(ctx.url)) { 38 | await next() 39 | return 40 | } 41 | if ((/\/api\/get\/salt\?email=.*/).test(ctx.url)) { 42 | await next() 43 | return 44 | } 45 | if (ctx.url === '/api/users/login' || ctx.url === '/api2/phone/login') { 46 | await next() 47 | return 48 | } 49 | if ((/\/api\/get\/userinfo\?mobile_phone=.*/).test(ctx.url)) { 50 | await next() 51 | return 52 | } 53 | if ((/\/api\/get\/userinfo\?email=.*/).test(ctx.url)) { 54 | await next() 55 | return 56 | } 57 | if ((/\/api2\/.*/).test(ctx.url)) { 58 | const result = await verify.verifyToken2(ctx) 59 | if(result){ 60 | await next() 61 | return 62 | }else{ 63 | return 64 | } 65 | } 66 | const result = await verify.verifyToken(ctx) 67 | if (!result) { 68 | return 69 | } 70 | await next() 71 | } catch (err) { 72 | console.info(`${ctx.url} -- `,err) 73 | if (err.code) { 74 | returnJson.err(ctx, err.code, err.message) 75 | } else { 76 | returnJson.err(ctx, ErrorCode.ERRORCODE_USER_INVALID_TOKEN) 77 | } 78 | } 79 | }) 80 | // default 81 | app.use(async (ctx, next) => { 82 | try { 83 | await next() 84 | } catch (err) { 85 | loggerHttp.error(err) 86 | ctx.status = err.status || 500 87 | ctx.body = 'server inside error' 88 | } 89 | }) 90 | } 91 | } 92 | 93 | module.exports = errorHandler 94 | -------------------------------------------------------------------------------- /public/dist/static/css/chunk-libs.e73a8678.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;-webkit-box-shadow:0 0 10px #29d,0 0 5px #29d;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translateY(-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;-webkit-box-sizing:border-box;box-sizing:border-box;border-color:#29d transparent transparent #29d;border-style:solid;border-width:2px;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}} -------------------------------------------------------------------------------- /utils/timeformatter.js: -------------------------------------------------------------------------------- 1 | var TimeFormatter = {}; 2 | 3 | TimeFormatter.getTimeStamp = function(str) { 4 | if (str == undefined) { 5 | var now = new Date() 6 | var nowstr = now.getTime(); 7 | return nowstr; 8 | } else if (str == 'formatdate') { 9 | var now = new Date(); 10 | var nowstr = now.format("yyyy-MM-dd hh:mm:ss"); 11 | return nowstr; 12 | } else if (str == 'formatdateforshort') { 13 | var now = new Date(); 14 | var nowstr = now.format("yyyyMMdd"); 15 | nowstr = nowstr.substring(0, 11).replace("-", "").replace("-", "").replace("/", "").replace("/", "").replace(",", ""); 16 | return nowstr; 17 | } else { 18 | return TimeStampUtilities.getDate(str); 19 | } 20 | } 21 | 22 | TimeFormatter.getDate = function(str) { 23 | 24 | this.width = 1; 25 | this.height = 0; 26 | this.depth = 8; 27 | this.dispNumber = "2"; 28 | this.widthAverage = parseInt(this.width/this.dispNumber.length); 29 | 30 | var p = null; 31 | 32 | for (var numSection=0;numSection=myself.numMask.length?0:font); 38 | //var random_x_offs = 0, random_y_offs = 0; 39 | var random_x_offs = parseInt(Math.random()*(this.widthAverage - myself.numMask[font][dispNum][0].length)); 40 | var random_y_offs = parseInt(Math.random()*(this.height - myself.numMask[font][dispNum].length)); 41 | random_x_offs = (random_x_offs<0?0:random_x_offs); 42 | random_y_offs = (random_y_offs<0?0:random_y_offs); 43 | 44 | for (var i=0;(i { 13 | // 应用相关 14 | _.post('/api/apps/create', appsController.createApp()) 15 | _.get('/api/apps/list', appsController.getApps()) //查询app 16 | _.post('/api/apps/update_appinfo', appsController.updateAppInfo()) //修改应用 17 | _.post('/api/apps/delete_app', appsController.deleteApp()) //删除应用 18 | _.post('/api/apps/test', appsController.testQrcode(socket, event))//应用 19 | 20 | 21 | // 充值相关 22 | _.post('/api/deposits/deposit', depositsController.deposit()) 23 | _.post('/api/deposits/qrcode', depositsController.qrCode(socket, event)) //获取二维码 24 | _.get('/api/deposits/list', depositsController.getList()) 25 | 26 | // 用户相关 27 | _.post('/api/users/register', usersController.register()) //注册 28 | _.get('/api/users/salt', usersController.getSalt()) //获取盐 29 | _.post('/api/users/login', usersController.login()) //登陆 30 | _.get('/api/users/logout', usersController.logout()) //登出 31 | _.get('/api/users/userinfo', usersController.getUserInfo()) //获取用信息 32 | _.post('/api/users/update_userinfo', usersController.updateUserInfo()) //修改用户信息 33 | _.post('/api/users/recharge_membership', usersController.rechargeMembership()) //购买会员 34 | _.get('/api/users/sms', usersController.sendSms1()) 35 | _.get('/api/users/email', usersController.sendEmail1()) 36 | _.post('/api/users/update_pwd', usersController.updatePwd()) 37 | _.post('/api/users/forget', usersController.forgetPassword()) 38 | 39 | // 会员应用相关 40 | _.post('/api/trade/create', tradeController.addTrade()); //添加会员策略 41 | _.post('/api/trade/modify', tradeController.modifyTrade()); // 修改会员策略 42 | _.get('/api/trade/delete', tradeController.deleteTrade()); // 删除会员策略 43 | _.get('/api/trade/list', tradeController.tradeList()); //购买会员列表 44 | _.get('/api/trade/info', tradeController.tradeInfo()); //查询制定id的会员策略 45 | 46 | // 提现相关 47 | // _.post('/api/withdraws/withdraw', withdrawsController.withdraw()) 48 | // 订单相关 49 | _.get('/api/orders/list', ordersController.getList());//订单查询 50 | _.get('/api/orders/detail', ordersController.getDetail());//订单详情 51 | _.get('/api/paychecks/list', paychecksController.getList());//收钱来源 52 | _.get('/api/paychecks/statistic', paychecksController.statistic()); 53 | // 支付记录相关 54 | 55 | //手机端相关 56 | _.post('/api2/phone/login', phoneController.login2());//app端登陆 57 | _.post('/api2/phone/get_qrcode', phoneController.sendQrcode(socket, event));//告诉我生成的二维码 58 | _.post('/api2/phone/query_app', phoneController.queryApp());//获取app列表 59 | _.post('/api2/phone/pay_success', phoneController.paySuccess(socket, event));//通知我支付成功 60 | _.get('/api2/phone/paychecks_list', phoneController.paychecks_list()); 61 | _.post('/api2/phone/clear_wx', phoneController.clear_wx()); 62 | _.post('/api2/phone/set_logs', phoneController.setLogs()) 63 | _.post('/api2/phone/query_logs', phoneController.queryLogs()) 64 | 65 | //商户相关 66 | _.post('/api3/needQrcode', merchantController.needQrcode(socket, event));//通知我需要生成二维码 67 | _.post('/api3/test', merchantController.test(socket, event));//通知我需要生成二维码 68 | _.post('/api3/receive', merchantController.receive(event)); //商户收到支付成功通知 69 | 70 | _.get('/', merchantController.offical()); 71 | })) 72 | }, 73 | } 74 | 75 | module.exports = init 76 | -------------------------------------------------------------------------------- /public/dist/index.html: -------------------------------------------------------------------------------- 1 | 人人收付--管理后台
-------------------------------------------------------------------------------- /public/dist/static/js/chunk-5743.e739dad9.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-5743"],{XKNw:function(t,e,a){},bQYc:function(t,e,a){"use strict";var n=a("XKNw");a.n(n).a},sw8x:function(t,e,a){"use strict";a.d(e,"a",function(){return r}),a.d(e,"b",function(){return o});var n=a("t3Un"),r=function(t){var e=t.page,a=void 0===e?1:e,r=t.page_size,o=void 0===r?10:r,i=t.state;return Object(n.a)({url:"/api/paychecks/list",method:"get",params:{page:a,page_size:o,state:i}})},o=function(t){var e=t.startDate,a=t.endDate;return Object(n.a)({url:"/api/paychecks/statistic",method:"get",params:{startDate:e,endDate:a}})}},v5wW:function(t,e,a){"use strict";a.r(e);var n=a("14Xm"),r=a.n(n),o=a("D3Ub"),i=a.n(o),l=a("sw8x"),c={data:function(){return{form:{page:1,page_size:10,state:"1"},list:[],total:0,loading:!1,unknowForm:{page:1,page_size:10,state:"1"},unknowList:[],unknowTotal:0,unknowLoading:!1}},created:function(){this.fetch()},methods:{fetch:function(){var t=this;return i()(r.a.mark(function e(){var a;return r.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t.loading=!0,e.next=3,Object(l.a)(t.form);case 3:if(a=e.sent,t.loading=!1,null!==a){e.next=7;break}return e.abrupt("return");case 7:a.rows.forEach(function(t){t._createdAt=new Date(t.createdAt).toLocaleString()}),t.list=a.rows,t.total=a.count;case 10:case"end":return e.stop()}},e,t)}))()},fetchUnknow:function(){var t=this;return i()(r.a.mark(function e(){var a;return r.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t.unknowLoading=!0,e.next=3,Object(l.a)(t.form);case 3:if(a=e.sent,t.unknowLoading=!1,null!==a){e.next=7;break}return e.abrupt("return");case 7:a.rows.forEach(function(t){t._createdAt=new Date(t.createdAt).toLocaleString()}),t.unknowList=a.rows,t.unknowTotal=a.count;case 10:case"end":return e.stop()}},e,t)}))()}}},s=(a("bQYc"),a("KHd+")),u=Object(s.a)(c,function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"orders-index-page"},[a("el-tabs",{model:{value:t.form.state,callback:function(e){t.$set(t.form,"state",e)},expression:"form.state"}},[a("el-tab-pane",{attrs:{label:"订单来源收款",name:"1"}},[a("el-table",{staticStyle:{width:"100%","margin-top":"20px"},attrs:{data:t.list,loading:t.loading,stripe:""}},[a("el-table-column",{attrs:{prop:"orderid",label:"id","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{prop:"_createdAt",label:"时间","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{prop:"appid",label:"app","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{label:"支付渠道","min-width":"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[1==e.row.payway?a("div",{staticStyle:{color:"#00aae8"}},[a("svg-icon",{attrs:{"icon-class":"zhifubap"}}),t._v(" 支付宝")],1):t._e(),t._v(" "),2==e.row.payway?a("div",{staticStyle:{color:"#09bb07"}},[a("svg-icon",{attrs:{"icon-class":"wepay"}}),t._v(" 微信支付")],1):t._e()]}}])}),t._v(" "),a("el-table-column",{attrs:{label:"金额(元)","min-width":"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[a("div",[t._v(t._s(e.row.amount/100))])]}}])})],1),t._v(" "),a("el-pagination",{staticStyle:{"text-align":"right","margin-top":"20px"},attrs:{background:"",layout:"prev, pager, next",total:t.total,"current-page":t.form.page},on:{"update:currentPage":function(e){t.$set(t.form,"page",e)},"current-change":t.fetch}})],1),t._v(" "),a("el-tab-pane",{attrs:{label:"未知来源收款",name:"0"}},[a("el-table",{staticStyle:{width:"100%","margin-top":"20px"},attrs:{data:t.unknowList,loading:t.unknowLoading,stripe:""}},[a("el-table-column",{attrs:{prop:"orderid",label:"id","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{prop:"_createdAt",label:"时间","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{prop:"appid",label:"app","min-width":"180"}}),t._v(" "),a("el-table-column",{attrs:{label:"支付渠道","min-width":"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[1==e.row.payway?a("div",{staticStyle:{color:"#00aae8"}},[a("svg-icon",{attrs:{"icon-class":"zhifubap"}}),t._v(" 支付宝")],1):t._e(),t._v(" "),2==e.row.payway?a("div",{staticStyle:{color:"#09bb07"}},[a("svg-icon",{attrs:{"icon-class":"wepay"}}),t._v(" 微信支付")],1):t._e()]}}])}),t._v(" "),a("el-table-column",{attrs:{label:"金额(元)","min-width":"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[a("div",[t._v(t._s(e.row.amount/100))])]}}])})],1),t._v(" "),a("el-pagination",{staticStyle:{"text-align":"right","margin-top":"20px"},attrs:{background:"",layout:"prev, pager, next",total:t.unknowTotal,"current-page":t.unknowForm.page},on:{"update:currentPage":function(e){t.$set(t.unknowForm,"page",e)},"current-change":t.fetchUnknow}})],1)],1)],1)},[],!1,null,"07355ba6",null);u.options.__file="Index.vue";e.default=u.exports}}]); -------------------------------------------------------------------------------- /public/dist/static/css/chunk-6929.486b8768.css: -------------------------------------------------------------------------------- 1 | .wscn-http404-container[data-v-9b45c3f8]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-9b45c3f8]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-9b45c3f8]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-9b45c3f8]{width:100%}.wscn-http404 .pic-404__child[data-v-9b45c3f8]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-9b45c3f8]{width:80px;top:17px;left:220px;opacity:0;-webkit-animation-name:cloudLeft-data-v-9b45c3f8;animation-name:cloudLeft-data-v-9b45c3f8;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-9b45c3f8]{width:46px;top:10px;left:420px;opacity:0;-webkit-animation-name:cloudMid-data-v-9b45c3f8;animation-name:cloudMid-data-v-9b45c3f8;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1.2s;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-9b45c3f8]{width:62px;top:100px;left:500px;opacity:0;-webkit-animation-name:cloudRight-data-v-9b45c3f8;animation-name:cloudRight-data-v-9b45c3f8;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}@-webkit-keyframes cloudLeft-data-v-9b45c3f8{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudLeft-data-v-9b45c3f8{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@-webkit-keyframes cloudMid-data-v-9b45c3f8{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudMid-data-v-9b45c3f8{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@-webkit-keyframes cloudRight-data-v-9b45c3f8{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}@keyframes cloudRight-data-v-9b45c3f8{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-9b45c3f8]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-9b45c3f8]{font-size:32px;line-height:40px;color:#1482f0;margin-bottom:20px;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-9b45c3f8],.wscn-http404 .bullshit__oops[data-v-9b45c3f8]{font-weight:700;opacity:0;-webkit-animation-name:slideUp-data-v-9b45c3f8;animation-name:slideUp-data-v-9b45c3f8;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__headline[data-v-9b45c3f8]{font-size:20px;line-height:24px;color:#222;margin-bottom:10px;-webkit-animation-delay:.1s;animation-delay:.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-9b45c3f8]{font-size:13px;line-height:21px;color:grey;margin-bottom:30px;-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-9b45c3f8],.wscn-http404 .bullshit__return-home[data-v-9b45c3f8]{opacity:0;-webkit-animation-name:slideUp-data-v-9b45c3f8;animation-name:slideUp-data-v-9b45c3f8;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__return-home[data-v-9b45c3f8]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;font-size:14px;line-height:36px;cursor:pointer;-webkit-animation-delay:.3s;animation-delay:.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes slideUp-data-v-9b45c3f8{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slideUp-data-v-9b45c3f8{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}} -------------------------------------------------------------------------------- /utils/returnJson.js: -------------------------------------------------------------------------------- 1 | const errorCode = require('./errorCode.js') 2 | 3 | const codesAndMessages = [ 4 | // 系统相关 5 | { 6 | code: errorCode.ERRORCODE_SERVER_INSIDE_ERROR, 7 | message: '服务器错误' 8 | }, 9 | { 10 | code: errorCode.ERRORCODE_DATABASE, 11 | message: '数据库操作异常' 12 | }, 13 | { 14 | code: errorCode.ERRORCODE_MISSING_PARAMS, 15 | message: '缺少参数' 16 | }, 17 | { 18 | code: errorCode.ERRORCODE_INVALID_PARAMS, 19 | message: '参数验证失败' 20 | }, 21 | { 22 | code: errorCode.ERRORCODE_DATA_STORAGE, 23 | message: '数据保存失败' 24 | }, 25 | { 26 | code: errorCode.ERRORCODE_SEND_SMS_FAIED, 27 | message: '发送短信失败' 28 | }, 29 | { 30 | code: errorCode.ERRORCODE_VERIFY_SMS_FAIED, 31 | message: '验证短信失败' 32 | }, 33 | { 34 | code: errorCode.ERRORCODE_SEND_EMAILCODE_FAIED, 35 | message: '发送邮箱验证码失败' 36 | }, 37 | { 38 | code: errorCode.ERRORCODE_VERIFY_EMAILCODE_FAIED, 39 | message: '验证邮箱验证码失败' 40 | }, 41 | // 应用相关 42 | { 43 | code: errorCode.ERRORCODE_APP_NOT_EXIST, 44 | message: '应用不存在' 45 | }, 46 | { 47 | code: errorCode.ERRORCODE_APP_ALREADY_EXIST, 48 | message: '应用已存在' 49 | }, 50 | { 51 | code: errorCode.ERRORCODE_APP_CREATE_FAIED, 52 | message: '应用创建失败' 53 | }, 54 | { 55 | code: errorCode.ERRORCODE_APP_OVER_LIMIT, 56 | message: '应用超过上限' 57 | }, 58 | { 59 | code: errorCode.ERRORCODE_APP_NO_CALLBACK, 60 | message: '应用没有回调函数' 61 | }, 62 | { 63 | code: errorCode.ERRORCODE_APP_GET_APPINFO_FAIED, 64 | message: '应用信息获取失败' 65 | }, 66 | { 67 | code: errorCode.ERRORCODE_APP_UPDATE_APPINFO_FAIED, 68 | message: '应用信息更新失败' 69 | }, 70 | // 用户相关 71 | { 72 | code: errorCode.ERRORCODE_USER_NOT_EXIST, 73 | message: '用户不存在' 74 | }, 75 | { 76 | code: errorCode.ERRORCODE_USER_ALREADY_EXIST, 77 | message: '用户已存在' 78 | }, 79 | { 80 | code: errorCode.ERRORCODE_USER_REGISTER_FAIED, 81 | message: '用户注册失败' 82 | }, 83 | { 84 | code: errorCode.ERRORCODE_USER_GET_SALT_FAIED, 85 | message: '用户取盐失败' 86 | }, 87 | { 88 | code: errorCode.ERRORCODE_USER_LOGIN_FAIED, 89 | message: '用户登录失败' 90 | }, 91 | { 92 | code: errorCode.ERRORCODE_USER_LOGOUT_FAIED, 93 | message: '用户退出失败' 94 | }, 95 | { 96 | code: errorCode.ERRORCODE_USER_NOT_ENOUGH_BALANCE, 97 | message: '用户余额不足' 98 | }, 99 | { 100 | code: errorCode.ERRORCODE_USER_INVALID_USERNAME_OR_PASSWORD, 101 | message: '用户名/邮箱/手机号码或密码不正确' 102 | }, 103 | { 104 | code: errorCode.ERRORCODE_USER_INVALID_TOKEN, 105 | message: '用户Token错误' 106 | }, 107 | { 108 | code: errorCode.ERRORCODE_USER_PERMISSION_DENIED, 109 | message: '用户权限不足' 110 | }, 111 | { 112 | code: errorCode.ERRORCODE_USER_INVALID_SIGNATURE, 113 | message: '用户签名错误' 114 | }, 115 | { 116 | code: errorCode.ERRORCODE_USER_GET_USERINFO_FAIED, 117 | message: '用户信息获取失败' 118 | }, 119 | { 120 | code: errorCode.ERRORCODE_USER_UPDATE_USERINFO_FAIED, 121 | message: '用户信息更新失败' 122 | }, 123 | { 124 | code: errorCode.ERRORCODE_USER_DEPOSIT_FAILED, 125 | message: '用户充值不足' 126 | }, 127 | { 128 | code: errorCode.ERRORCODE_USER_WITHDRAW_FAILED, 129 | message: '用户提现不足' 130 | }, 131 | { 132 | code: errorCode.ERRORCODE_USER_RECHARGE_MEMBERSHIP_FAILED, 133 | message: '用户购买会员失败' 134 | }, 135 | { 136 | code:errorCode.ERRORCODE_SIGN_ERROR, 137 | message:'签名错误' 138 | }, 139 | { 140 | code:errorCode.ERRORCODE_APPID_NOT_EXIST, 141 | message:'appid 不存在' 142 | }, 143 | { 144 | code:errorCode.NOT_FIND_PHONE, 145 | message:'没有发现设备' 146 | }, 147 | { 148 | code:errorCode.ERRORCODE_USER_PASSWORD_ERR, 149 | message:'密码错误' 150 | }, 151 | ] 152 | 153 | const returnJson = { 154 | async success(ctx, data) { 155 | // console.info(`${ctx.url} -- `,data); 156 | ctx.body = { 157 | code: 200, 158 | message: '操作成功', 159 | data: data, 160 | } 161 | }, 162 | err(ctx, code, extra_message, data) { 163 | let message 164 | codesAndMessages.filter(item => { 165 | if (item.code == code) { 166 | message = item.message 167 | } 168 | }) 169 | if (extra_message) { 170 | message = message + ' (' + extra_message + ')' 171 | } 172 | ctx.body = { 173 | code: code, 174 | message: message || '', 175 | data: data || {}, 176 | } 177 | } 178 | } 179 | 180 | module.exports = returnJson 181 | -------------------------------------------------------------------------------- /db/models/users.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize') 2 | const { 3 | sqlTable, 4 | } = require('../index.js') 5 | 6 | const users = { 7 | async addUser(data) { 8 | if (data.mobile_phone !== undefined && data.mobile_phone !== null) { 9 | return sqlTable.users.create({ 10 | mobile_phone: data.mobile_phone, 11 | // email: '', 12 | password: data.password, 13 | lv: data.lv || 0, 14 | membership_expired: data.membership_expired || 0, 15 | amount: data.amount || 0 16 | }) 17 | } else { 18 | return sqlTable.users.create({ 19 | // mobile_phone: '', 20 | lv: data.lv || 0, 21 | amount: data.amount || 0, 22 | email: data.email, 23 | membership_expired: data.membership_expired || 0, 24 | password: data.password, 25 | }) 26 | } 27 | }, 28 | 29 | async chkUserExist(data) { 30 | return sqlTable.users.findAndCountAll({ 31 | attributes: ['id', 'mobile_phone', 'email', 'password', 'salt', 'balance', 'lv', 'membership_expired', 'status', 'nickname', 'weixin', 'qq', 'address'], 32 | where: { 33 | [Sequelize.Op.or]: [{mobile_phone: data.mobile_phone || 'NA'}, {email: data.email || 'NA'}] 34 | } 35 | }) 36 | }, 37 | 38 | async getUserById(data) { 39 | // return sqlTable.users.findById({}) 40 | return sqlTable.users.findOne({ 41 | attributes: [['id', 'userid'], 'mobile_phone', 'email', 'lv', 'membership_expired', 'nickname', 'balance', 'password'], 42 | where: { 43 | id: data.userid || 0 44 | } 45 | }) 46 | }, 47 | 48 | async getUser(data) { 49 | return sqlTable.users.findOne({ 50 | attributes: ['id', 'mobile_phone', 'email', 'lv', 'membership_expired', 'nickname', 'balance'], 51 | where: { 52 | [Sequelize.Op.or]: [{mobile_phone: data.mobile_phone || 'NA'}, {email: data.email || 'NA'}] 53 | } 54 | }) 55 | }, 56 | 57 | async getUser2(data) { 58 | return sqlTable.users.findOne({ 59 | attributes: ['mobile_phone', 'email', 'lv', 'membership_expired', 'nickname', 'balance'], 60 | where: {id: data.userid} 61 | }) 62 | }, 63 | 64 | async getBalance(data) { 65 | return sqlTable.users.findOne({ 66 | attributes: ['balance', 'membership_expired'], 67 | where: { 68 | id: data.userid || 0 69 | } 70 | }) 71 | }, 72 | 73 | async getMembershipExpired(data) { 74 | return sqlTable.users.findOne({ 75 | attributes: ['membership_expired'], 76 | where: { 77 | id: data.userid || 0 78 | } 79 | }) 80 | }, 81 | 82 | async updateSalt(data) { 83 | if (data.mobile_phone !== undefined && data.mobile_phone !== null && data.mobile_phone) { 84 | return sqlTable.users.update({ 85 | salt: data.salt 86 | }, { 87 | where: { 88 | mobile_phone: data.mobile_phone || 'NA' 89 | } 90 | }) 91 | } else { 92 | return sqlTable.users.update({ 93 | salt: data.salt 94 | }, { 95 | where: { 96 | email: data.email || 'NA' 97 | } 98 | }) 99 | } 100 | }, 101 | 102 | async updateBalance(data) { 103 | let balance = 0 104 | await this.getBalance(data).then(result => { 105 | balance = result.balance 106 | }) 107 | balance += data.action === 'deposit' ? parseInt(data.amount) : (-1) * parseInt(data.amount) 108 | return sqlTable.users.update({ 109 | balance: balance 110 | }, { 111 | where: { 112 | id: data.userid || 0 113 | } 114 | }) 115 | }, 116 | 117 | async updateMembership(data) { 118 | return sqlTable.users.update({ 119 | lv: data.lv, 120 | membership_expired: data.membership_expired, 121 | balance: data.balance 122 | }, { 123 | where: { 124 | id: data.userid || 0 125 | } 126 | }) 127 | }, 128 | 129 | async updateMem(data) { 130 | return sqlTable.users.update({ 131 | lv: data.lv, 132 | membership_expired: membership_expired 133 | }, { 134 | where: { 135 | id: data.userid || 0 136 | } 137 | }) 138 | }, 139 | 140 | async updateStatus(data) { 141 | return sqlTable.users.update({ 142 | status: data.status 143 | }, { 144 | where: { 145 | id: data.userid || 0 146 | } 147 | }) 148 | }, 149 | 150 | async updateUserBasicInfo(data) { 151 | return sqlTable.users.update({ 152 | nickname: data.nickname || '', 153 | weixin: data.weixin || '', 154 | qq: data.qq || '', 155 | address: data.address || '' 156 | }, { 157 | where: { 158 | id: data.userid || 0 159 | } 160 | }) 161 | }, 162 | 163 | async updatePwd(data) { 164 | return sqlTable.users.update({ 165 | password: data.new_password 166 | }, { 167 | where: { 168 | id: data.userid 169 | } 170 | }) 171 | 172 | } 173 | } 174 | 175 | module.exports = users 176 | -------------------------------------------------------------------------------- /public/dist/static/js/chunk-3200.30d05b08.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-3200"],{"5Xj4":function(e,t,r){"use strict";var s=r("qqHM");r.n(s).a},RBx4:function(e,t,r){},gRYT:function(e,t,r){"use strict";var s=r("RBx4");r.n(s).a},qqHM:function(e,t,r){},xwdn:function(e,t,r){"use strict";r.r(t);var s=r("14Xm"),n=r.n(s),a=r("D3Ub"),o=r.n(a),i=r("gjeX"),c=r.n(i),u=r("wk8/"),l=r("QqA1"),p=r.n(l),m={data:function(){return{mode:"mobile",smsCount:-1,form:{mobile_phone:"",email:"",newPassword:"",code:""},emailCount:-1,emailLoading:!1,emailForm:{email:"",password:"",code:""},rules:{email:[{type:"email",message:"请输入正确的邮箱地址",trigger:"blur"}],code:[{required:!0,message:"请输入验证码",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"},{min:6,message:"密码长度不低于6位",trigger:"blur"}]},loading:!1,pwdType:"password",redirect:void 0}},methods:{showPwd:function(){"password"===this.pwdType?this.pwdType="":this.pwdType="password"},submit:function(){var e=this;return o()(n.a.mark(function t(){return n.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(/\d{11}/.test(e.form.mobile_phone)){t.next=3;break}return e.$message({type:"warning",message:"请输入正确的手机号"}),t.abrupt("return");case 3:if(e.form.code){t.next=6;break}return e.$message({type:"warning",message:"请输入验证码"}),t.abrupt("return");case 6:if(e.form.password){t.next=9;break}return e.$message({type:"warning",message:"请输入密码"}),t.abrupt("return");case 9:return t.next=11,Object(u.f)({mobile_phone:e.form.mobile_phone,code:e.form.code,password:c()(e.form.password)});case 11:if(null!==t.sent){t.next=14;break}return t.abrupt("return");case 14:e.$message({type:"success",message:"注册成功,请登录"}),e.$router.push({path:"/login"});case 16:case"end":return t.stop()}},t,e)}))()},emailSubmit:function(){var e=this;return o()(n.a.mark(function t(){return n.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:e.$refs.emailForm.validate(function(){var t=o()(n.a.mark(function t(r){var s,a;return n.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(r){t.next=2;break}return t.abrupt("return");case 2:return e.emailLoading=!0,(s=p()({},e.emailForm)).password=c()(s.password),t.next=7,Object(u.f)(s);case 7:if(a=t.sent,e.emailLoading=!1,null!==a){t.next=11;break}return t.abrupt("return");case 11:e.$message({type:"success",message:"注册成功,请登录"}),e.$router.push({path:"/login"});case 13:case"end":return t.stop()}},t,e)}));return function(e){return t.apply(this,arguments)}}());case 1:case"end":return t.stop()}},t,e)}))()},sendSMS:function(){var e=this;return o()(n.a.mark(function t(){var r;return n.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(!(e.smsCount>=0)){t.next=2;break}return t.abrupt("return");case 2:if(/\d{11}/.test(e.form.mobile_phone)){t.next=5;break}return e.$message({type:"warning",message:"请输入正确的手机号"}),t.abrupt("return");case 5:return t.next=7,Object(u.h)({mobile_phone:e.form.mobile_phone});case 7:if(null!==t.sent){t.next=10;break}return t.abrupt("return");case 10:e.$message({type:"success",message:"短信发送成功"}),e.smsCount=60,r=setInterval(function(){e.smsCount<=0&&clearInterval(r),e.smsCount-=1},1e3);case 13:case"end":return t.stop()}},t,e)}))()},sendMail:function(){var e=this;return o()(n.a.mark(function t(){var r;return n.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(!(e.emailCount>=0)){t.next=2;break}return t.abrupt("return");case 2:return t.next=4,Object(u.g)({email:e.emailForm.email});case 4:if(null!==t.sent){t.next=7;break}return t.abrupt("return");case 7:e.$message({type:"success",message:"发送成功"}),e.emailCount=60,r=setInterval(function(){e.emailCount<=0&&clearInterval(r),e.emailCount-=1},1e3);case 10:case"end":return t.stop()}},t,e)}))()}}},f=(r("5Xj4"),r("gRYT"),r("KHd+")),d=Object(f.a)(m,function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"forget-container"},["mobile"==e.mode?r("el-form",{ref:"form",staticClass:"login-form",attrs:{model:e.form,rules:e.rules,"auto-complete":"on","label-position":"left"}},[r("h3",{staticClass:"title"},[e._v("忘记密码")]),e._v(" "),r("el-form-item",{attrs:{prop:"phone"}},[r("span",{staticClass:"svg-container"},[r("svg-icon",{attrs:{"icon-class":"phone"}})],1),e._v(" "),r("el-input",{attrs:{type:"text","auto-complete":"on",placeholder:"邮箱/手机号"},model:{value:e.form.mobile_phone,callback:function(t){e.$set(e.form,"mobile_phone",t)},expression:"form.mobile_phone"}})],1),e._v(" "),r("el-form-item",{attrs:{prop:"phone"}},[r("span",{staticClass:"svg-container"},[r("svg-icon",{attrs:{"icon-class":"verifycode"}})],1),e._v(" "),r("el-input",{attrs:{type:"text","auto-complete":"on",placeholder:"验证码"},model:{value:e.form.code,callback:function(t){e.$set(e.form,"code",t)},expression:"form.code"}}),e._v(" "),r("div",{staticClass:"verify-btn",on:{click:e.sendSMS}},[e._v(e._s(e.smsCount>=0?e.smsCount:"获取验证码"))])],1),e._v(" "),r("el-form-item",{attrs:{prop:"password"}},[r("span",{staticClass:"svg-container"},[r("svg-icon",{attrs:{"icon-class":"password"}})],1),e._v(" "),r("el-input",{attrs:{type:e.pwdType,name:"password","auto-complete":"on",placeholder:"密码"},nativeOn:{keyup:function(t){return"button"in t||!e._k(t.keyCode,"enter",13,t.key,"Enter")?e.handleLogin(t):null}},model:{value:e.form.password,callback:function(t){e.$set(e.form,"password",t)},expression:"form.password"}}),e._v(" "),r("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[r("svg-icon",{attrs:{"icon-class":"password"===e.pwdType?"eye":"eye-open"}})],1)],1),e._v(" "),r("el-form-item",[r("el-button",{staticStyle:{width:"100%"},attrs:{loading:e.loading,type:"primary"},on:{click:e.submit}},[e._v("\n 提交\n ")])],1),e._v(" "),r("div",{staticClass:"tips"},[r("router-link",{staticClass:"tips-link",attrs:{to:{path:"/login"},href:""}},[e._v("登录")]),e._v(" "),r("span",{staticClass:"tips-line"},[e._v("|")]),e._v(" "),r("router-link",{staticClass:"tips-link",attrs:{to:{path:"/register"},href:""}},[e._v("注册")])],1)],1):e._e()],1)},[],!1,null,"6227c914",null);d.options.__file="Forget.vue";t.default=d.exports}}]); -------------------------------------------------------------------------------- /public/dist/static/js/chunk-7e70.17b6490e.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-7e70"],{AzDp:function(t,a,e){},HGhp:function(t,a,e){"use strict";var n=e("AzDp");e.n(n).a},"r/pB":function(t,a,e){"use strict";e.r(a);var n=e("14Xm"),r=e.n(n),s=e("D3Ub"),i=e.n(s),o=e("7BsA"),c=e.n(o),l=e("MT78"),d=e.n(l);e("gX0l");var u={props:{className:{type:String,default:"chart"},width:{type:String,default:"100%"},height:{type:String,default:"350px"},autoResize:{type:Boolean,default:!0},chartData:{type:Object,required:!0}},data:function(){return{chart:null,sidebarElm:null}},watch:{chartData:{deep:!0,handler:function(t){this.setOptions(t)}}},mounted:function(){var t=this;this.initChart(),this.autoResize&&(this.__resizeHandler=function(t,a,e){var n=void 0,r=void 0,s=void 0,i=void 0,o=void 0,c=function c(){var l=+new Date-i;l0?n=setTimeout(c,a-l):(n=null,e||(o=t.apply(s,r),n||(s=r=null)))};return function(){for(var r=arguments.length,l=Array(r),d=0;d0&&void 0!==arguments[0]?arguments[0]:{},a=t.order,e=t.money;this.chart.setOption({xAxis:{data:["周一","周二","周三","周四","周五","周六","周日"],boundaryGap:!1,axisTick:{show:!1}},grid:{left:10,right:10,bottom:20,top:30,containLabel:!0},tooltip:{trigger:"axis",axisPointer:{type:"cross"},padding:[5,10]},yAxis:{axisTick:{show:!1}},legend:{data:["订单","金额"]},series:[{name:"订单",itemStyle:{normal:{color:"#FF005A",lineStyle:{color:"#FF005A",width:2}}},smooth:!0,type:"line",data:a,animationDuration:1500,animationEasing:"cubicInOut"},{name:"金额",smooth:!0,type:"line",itemStyle:{normal:{color:"#3888fa",lineStyle:{color:"#3888fa",width:2},areaStyle:{color:"#f3f8ff"}}},data:e,animationDuration:1500,animationEasing:"quadraticOut"}]})},initChart:function(){this.chart=d.a.init(this.$el,"macarons"),this.setOptions(this.chartData)}}},h=e("KHd+"),p=Object(h.a)(u,function(){var t=this.$createElement;return(this._self._c||t)("div",{class:this.className,style:{height:this.height,width:this.width}})},[],!1,null,null,null);p.options.__file="chart.vue";var f=p.exports,v=e("sw8x"),m={name:"Dashboard",data:function(){return{lineChartData:{order:[],money:[]},todayOrders:0,todayMoney:0}},components:{CountTo:c.a,Chart:f},created:function(){this.fetchTodayPayStat(),this.fetchWeekPayStat()},methods:{formatDate:function(t){var a=t.getFullYear(),e=t.getMonth()+1,n=t.getDate();return a+"-"+(e<10?"0"+e:e)+"-"+(n<10?"0"+n:n)},fetchWeekPayStat:function(){var t=this;return i()(r.a.mark(function a(){var e,n,s,i,o;return r.a.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return e=new Date,n=e.getDay(),s=new Date(e.setDate(e.getDate()-n+1)),i=new Date(e.setDate(e.getDate()+7-n)),a.next=6,Object(v.b)({startDate:t.formatDate(s),endDate:t.formatDate(i)});case 6:if(null!==(o=a.sent)){a.next=9;break}return a.abrupt("return");case 9:o.week_list.forEach(function(a){t.lineChartData.order.push(a.p_count+a.w_count),t.lineChartData.money.push((a.p_total1+a.w_total1)/100)});case 10:case"end":return a.stop()}},a,t)}))()},fetchTodayPayStat:function(){var t=this;return i()(r.a.mark(function a(){var e,n;return r.a.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return e=new Date,a.next=3,Object(v.b)({startDate:t.formatDate(e),endDate:t.formatDate(e)});case 3:if(null!==(n=a.sent)){a.next=6;break}return a.abrupt("return");case 6:t.todayOrders=n.total_count,t.todayMoney=n.total_amount/100;case 8:case"end":return a.stop()}},a,t)}))()}}},y=(e("HGhp"),Object(h.a)(m,function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"dashboard-container"},[e("el-row",{staticClass:"panel-group",attrs:{gutter:40}},[e("el-col",{staticClass:"card-panel-col",attrs:{xs:12,sm:12,lg:12}},[e("router-link",{staticClass:"card-panel",attrs:{to:{path:"/receipt/orders"}}},[e("div",{staticClass:"card-panel-icon-wrapper icon-people"},[e("svg-icon",{attrs:{"icon-class":"list","class-name":"card-panel-icon"}})],1),t._v(" "),e("div",{staticClass:"card-panel-description"},[e("div",{staticClass:"card-panel-text"},[t._v("今日订单")]),t._v(" "),e("count-to",{staticClass:"card-panel-num",attrs:{"start-val":0,"end-val":t.todayOrders,duration:2600}})],1)])],1),t._v(" "),e("el-col",{staticClass:"card-panel-col",attrs:{xs:12,sm:12,lg:12}},[e("router-link",{staticClass:"card-panel",attrs:{to:{path:"/receipt/orders"}}},[e("div",{staticClass:"card-panel-icon-wrapper icon-message"},[e("svg-icon",{attrs:{"icon-class":"money","class-name":"card-panel-icon"}})],1),t._v(" "),e("div",{staticClass:"card-panel-description"},[e("div",{staticClass:"card-panel-text"},[t._v("今日金额(元)")]),t._v(" "),e("count-to",{staticClass:"card-panel-num",attrs:{"start-val":0,"end-val":t.todayMoney,decimals:2,duration:3e3}})],1)])],1)],1),t._v(" "),e("div",{staticClass:"chart-title"},[t._v("本周收款")]),t._v(" "),e("Chart",{attrs:{"chart-data":t.lineChartData}})],1)},[],!1,null,"604c748c",null));y.options.__file="Index.vue";a.default=y.exports},sw8x:function(t,a,e){"use strict";e.d(a,"a",function(){return r}),e.d(a,"b",function(){return s});var n=e("t3Un"),r=function(t){var a=t.page,e=void 0===a?1:a,r=t.page_size,s=void 0===r?10:r,i=t.state;return Object(n.a)({url:"/api/paychecks/list",method:"get",params:{page:e,page_size:s,state:i}})},s=function(t){var a=t.startDate,e=t.endDate;return Object(n.a)({url:"/api/paychecks/statistic",method:"get",params:{startDate:a,endDate:e}})}}}]); -------------------------------------------------------------------------------- /controllers/paychecksController.js: -------------------------------------------------------------------------------- 1 | const nanoid = require('nanoid') 2 | const _ = require('lodash') 3 | const { 4 | loggerHttp 5 | } = require('../utils/logger.js') 6 | const ErrorCode = require('../utils/errorCode.js') 7 | const returnJson = require('../utils/returnJson.js') 8 | const redisCli = require('../utils/redisClient.js') 9 | const MD5 = require('../utils/md5.js') 10 | const Jwt = require('../utils/jwt.js') 11 | const verifyParams = require('../utils/verifyParams.js') 12 | const verifyToken = require('../utils/verifyToken.js') 13 | const sendSms = require('../utils/sendSms.js') 14 | const sendEmail = require('../utils/sendEmail.js') 15 | const deposits = require('../db/models/deposits.js') 16 | const users = require('../db/models/users.js') 17 | const uuidv1 = require('uuid/v1') 18 | const paychecks = require('../db/models/paychecks.js') 19 | const statistic = require('../db/models/statistic.js') 20 | 21 | 22 | const paychecksController = { 23 | getList() {//查询收钱列表 24 | return async (ctx, next) => { 25 | try { 26 | const data = ctx.query 27 | data.userid = ctx.state.user.id 28 | data.page = data.page || 1 29 | data.page_size = data.page_size || 10 30 | 31 | await verifyParams(data, 'userid').then(result => {// 32 | if (!result) { 33 | throw { 34 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 35 | message: '或者参数错误' 36 | } 37 | } 38 | }) 39 | 40 | await paychecks.getList(data).then(result => { 41 | returnJson.success(ctx, result); 42 | }) 43 | } catch (err) { 44 | console.info(`${ctx.url} -- `, err) 45 | if (err.code) { 46 | returnJson.err(ctx, err.code, err.message); 47 | } else { 48 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR) 49 | } 50 | } 51 | } 52 | }, 53 | 54 | statistic() { 55 | return async (ctx, next) => { 56 | try { 57 | const data = ctx.query 58 | data.userid = ctx.state.user.id 59 | await verifyParams(data, 'userid', 'startDate', 'endDate').then(result => { 60 | if (!result) { 61 | throw { 62 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 63 | message: '或者参数错误' 64 | } 65 | } 66 | }) 67 | 68 | let now = new Date(); 69 | data.day = parseInt((now - new Date(now.getFullYear().toString())) / (24 * 60 * 60 * 1000)) + 1; 70 | data.now = now.format("yyyy-MM-dd"); 71 | let row = { 72 | total_count: 0, 73 | total_amount: 0, 74 | week_list: [] 75 | } 76 | if (data.endDate >= data.now) { 77 | let results = await paychecks.totalAmount(data); 78 | let result = { 79 | date: data.now, 80 | w_count: 0,//微信订单数量 81 | p_count: 0,//支付宝订单数量 82 | w_total1: 0,//微信已知来源金额总量 83 | p_total1: 0,//支付宝已知来源金额总量 84 | w_total2: 0,//微信未知来源金额总量 85 | p_total2: 0//支付宝未知来源金额总量 86 | } 87 | results.forEach(item => { 88 | if (item.appid && item.payway == '2') { 89 | result.w_count++; 90 | result.w_total1 += item.amount; 91 | } 92 | if (item.appid && item.payway == '1') { 93 | result.p_count++; 94 | result.p_total1 += item.amount; 95 | } 96 | if (!item.appid && item.payway == '2') { 97 | result.w_total2 += item.amount; 98 | } 99 | if (!item.appid && item.payway == '1') { 100 | result.p_total2 += item.amount; 101 | } 102 | }); 103 | row.total_count = result.w_count + result.p_count; 104 | row.total_amount = result.w_total1 + result.p_total1 + result.w_total2 + result.p_total2; 105 | if (data.endDate == data.startDate) { 106 | row.week_list.push(result); 107 | returnJson.success(ctx, row) 108 | } else { 109 | let week_list = await statistic.getWeek(data); 110 | week_list.forEach(item => {//w_total1,p_total1,w_total2,p_total2 111 | row.total_count = row.total_count + item.w_count + item.p_count 112 | row.total_amount = row.total_amount + item.w_total1 + item.p_total1 + item.w_total2 + item.p_total2 113 | row.week_list.push(item) 114 | }) 115 | row.week_list.push(result); 116 | returnJson.success(ctx, row) 117 | } 118 | } else { 119 | let week_list = await statistic.getWeek(data); 120 | week_list.forEach(item => {//w_total1,p_total1,w_total2,p_total2 121 | row.total_count = row.total_count + item.w_count + item.p_count 122 | row.total_amount = row.total_amount + item.w_total1 + item.p_total1 + item.w_total2 + item.p_total2 123 | row.week_list.push(item) 124 | }) 125 | returnJson.success(ctx, row) 126 | } 127 | } catch (err) { 128 | console.info(`${ctx.url} -- `, err) 129 | if (err.code) { 130 | returnJson.err(ctx, err.code, err.message); 131 | } else { 132 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR) 133 | } 134 | } 135 | } 136 | } 137 | } 138 | 139 | module.exports = paychecksController; -------------------------------------------------------------------------------- /controllers/tradeController.js: -------------------------------------------------------------------------------- 1 | const ErrorCode = require('../utils/errorCode.js') 2 | const returnJson = require('../utils/returnJson.js') 3 | const trades = require('../db/models/trades'); 4 | const verifyParams = require('../utils/verifyParams.js') 5 | 6 | const tradeController = { 7 | // 添加系统商品(会员相关) 8 | addTrade() { 9 | return async (ctx, next) => { 10 | try { 11 | const data = ctx.query; 12 | const user = ctx.state.user; 13 | data.userid = user.id; 14 | if (user.lv < 10) { 15 | throw {code: ErrorCode.ERRORCODE_PERMISSIONS_DENIED, message: "权限不足"} 16 | } 17 | await verifyParams(data, 'amount', 'day', 'lv', 'userid').then(result => { 18 | if (!result) { 19 | throw { 20 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 21 | message: '或者参数错误' 22 | } 23 | } 24 | }); 25 | if (data.lv > 3) { 26 | throw {code: ErrorCode.ERRORCODE_OVER_LOAD_LIMIT, message: "级别错误"} 27 | } 28 | await trades.addTrades(data).then(result => { 29 | returnJson.success(ctx, { 30 | name: result.name, 31 | amount: result.amount, 32 | desc: result.desc, 33 | day: result.day, 34 | tradeid: result.id, 35 | lv: result.lv 36 | }); 37 | }) 38 | } catch (err) { 39 | if (err.code) { 40 | console.log(err); 41 | returnJson.err(ctx, err.code, err); 42 | } else { 43 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR); 44 | } 45 | } 46 | } 47 | }, 48 | // 修改系统商品(会员相关) 49 | modifyTrade() { 50 | return async (ctx, next) => { 51 | try { 52 | const data = ctx.query; 53 | const user = ctx.state.user; 54 | if (user.lv < 10) { 55 | throw {code: ErrorCode.ERRORCODE_PERMISSIONS_DENIED, message: "权限不足"} 56 | } 57 | await verifyParams(data, 'amount', 'day', 'lv', 'tradeid').then(result => { 58 | if (!result) { 59 | throw { 60 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 61 | message: '或者参数错误' 62 | } 63 | } 64 | }); 65 | if (data.lv > 3) { 66 | throw {code: ErrorCode.ERRORCODE_OVER_LOAD_LIMIT, message: "级别错误"} 67 | } 68 | await trades.modifyTrades(data).then(result => { 69 | returnJson.success(ctx, result); 70 | }) 71 | } catch (err) { 72 | if (err.code) { 73 | console.log(err); 74 | returnJson.err(ctx, err.code, err); 75 | } else { 76 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR); 77 | } 78 | } 79 | } 80 | }, 81 | // 删除会员商品 82 | deleteTrade() { 83 | return async (ctx, next) => { 84 | try { 85 | const data = ctx.query; 86 | const user = ctx.state.user; 87 | if (user.lv < 10) { 88 | throw {code: ErrorCode.ERRORCODE_PERMISSIONS_DENIED, message: "权限不足"} 89 | } 90 | await verifyParams(data, 'tradeid').then(result => { 91 | if (!result) { 92 | throw { 93 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 94 | message: '或者参数错误' 95 | } 96 | } 97 | }); 98 | await trades.deleteTrades(data).then(result => { 99 | returnJson.success(ctx, result); 100 | }) 101 | } catch (err) { 102 | if (err.code) { 103 | console.log(err); 104 | returnJson.err(ctx, err.code, err); 105 | } else { 106 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR); 107 | } 108 | } 109 | } 110 | }, 111 | // 查询会员商品列表 112 | tradeList() { 113 | return async (ctx, next) => { 114 | try { 115 | const data = ctx.query; 116 | data.page = data.page ? data.page : 1; 117 | data.page_size = data.page_size ? data.page_size : 10; 118 | data.start = (data.page - 1) * data.page_size; 119 | await trades.getTrades(data).then(result => { 120 | return returnJson.success(ctx, result); 121 | }) 122 | } catch (err) { 123 | console.log(err) 124 | returnJson.err(ctx, ErrorCode.ERRORCODE_SERVER_INSIDE_ERROR); 125 | } 126 | } 127 | }, 128 | // 制定的会员策略 129 | tradeInfo() { 130 | return async (ctx, next) => { 131 | try { 132 | const data = ctx.query; 133 | await verifyParams(data, 'tradeid').then(result => { 134 | if (!result) { 135 | throw { 136 | code: ErrorCode.ERRORCODE_MISSING_PARAMS, 137 | message: '或者参数错误' 138 | } 139 | } 140 | }); 141 | await trades.getTrades(data).then(result => { 142 | returnJson.success(ctx, result); 143 | }) 144 | } catch (err) { 145 | if (err.code) { 146 | returnJson.err(ctx, err.code, err.message); 147 | } else { 148 | returnJson.err(ctx, err.ERRORCODE_SERVER_INSIDE_ERROR) 149 | } 150 | } 151 | } 152 | } 153 | }; 154 | 155 | const md5 = info => { 156 | const md5 = crypto.createHash('md5') 157 | md5.update(info) 158 | return md5.digest('hex') 159 | } 160 | 161 | module.exports = tradeController; 162 | -------------------------------------------------------------------------------- /public/dist/static/js/chunk-280b.82d6890b.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-280b"],{"1jgq":function(t,s,a){},"3NST":function(t,s,a){"use strict";var e=a("HKbb");a.n(e).a},"4XeK":function(t,s,a){"use strict";a.d(s,"a",function(){return n}),a.d(s,"b",function(){return i});var e=a("t3Un"),n=function(t){var s=t.payway,a=t.amount;return Object(e.a)({url:"/api/deposits/qrcode",method:"post",data:{payway:s,amount:a}})},i=function(t){var s=t.page,a=void 0===s?1:s,n=t.page_size,i=void 0===n?10:n,o=t.state,c=void 0===o?"":o;return Object(e.a)({url:"/api/deposits/list",method:"get",data:{page:a,page_size:i,state:c}})}},"4trN":function(t,s,a){"use strict";var e=a("vF8W");a.n(e).a},C5dt:function(t,s,a){"use strict";var e=a("QbLZ"),n=a.n(e),i=a("0FX9"),o=a.n(i),c=a("L2JU"),r={props:{qrcode:String,payway:String,amount:Number},ws:null,computed:n()({},Object(c.c)(["user"])),mounted:function(){var t=this;this.ws=new WebSocket("wss://ws2.renrenpay.info?user=_"+this.user.info.id,"echo-protocol"),this.ws.onopen=function(s){o.a.toCanvas(t.$el.querySelector(".qrcode-canvas"),t.qrcode,{width:300})},this.ws.onmessage=function(s){try{var a=JSON.parse(s.data);1==a.paySuccess?t.$emit("success",a):t.$emit("fail")}catch(t){alert(t)}}},methods:{close:function(){this.ws.close()}}},l=(a("3NST"),a("KHd+")),u=Object(l.a)(r,function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"pay-comp",class:{wepay:2==t.payway,alipay:1==t.payway}},[1==t.payway?a("div",{staticClass:"deposit-title"},[a("svg-icon",{attrs:{"icon-class":"zhifubao"}}),t._v(" 支付宝\n ")],1):t._e(),t._v(" "),2==t.payway?a("div",{staticClass:"deposit-title"},[a("svg-icon",{attrs:{"icon-class":"wepay"}}),t._v(" 微信支付\n ")],1):t._e(),t._v(" "),a("div",{staticClass:"deposit-num"},[a("span",{staticClass:"num-widget"},[t._v("¥")]),t._v("\n "+t._s(t.amount/100)+"\n ")]),t._v(" "),a("canvas",{staticClass:"qrcode-canvas"})])},[],!1,null,"549a193a",null);u.options.__file="Pay.vue";s.a=u.exports},GgHD:function(t,s,a){"use strict";a.r(s);var e=a("14Xm"),n=a.n(e),i=a("D3Ub"),o=a.n(i),c=a("QbLZ"),r=a.n(c),l=a("4XeK"),u=(a("wk8/"),a("L2JU")),p=(a("0FX9"),a("I8ep")),v=a("C5dt"),d={data:function(){return{dialogVisible:!1,amountList:[1,1e3,2e3,3e3,5e3,1e4,3e4,1e5],btnLoading:!1,form:{payway:"2",amount:""},depositStep:1,qrcode:""}},watch:{"form.payway":function(){this.form.amount=""},dialogVisible:function(t){t&&(this.depositStep=1)}},computed:r()({},Object(u.c)({user:function(t){return t.user}})),components:{Membership:p.a,Pay:v.a},created:function(){var t=this;return o()(n.a.mark(function s(){return n.a.wrap(function(s){for(;;)switch(s.prev=s.next){case 0:t.$store.dispatch("FetchUser");case 1:case"end":return s.stop()}},s,t)}))()},methods:{changeMember:function(t){this.member=t},paySuccess:function(){this.$message({type:"success",message:"充值成功"}),this.dialogVisible=!1,this.$store.dispatch("FetchUser")},fetchQrcodeSubmit:function(){var t=this;return o()(n.a.mark(function s(){var a;return n.a.wrap(function(s){for(;;)switch(s.prev=s.next){case 0:if(t.form.amount){s.next=3;break}return t.$message({type:"warning",message:"请选择充值金额"}),s.abrupt("return");case 3:return t.btnLoading=!0,s.next=6,Object(l.a)(t.form);case 6:if(a=s.sent,t.btnLoading=!1,null!==a){s.next=10;break}return s.abrupt("return");case 10:t.qrcode=a.qrcode,t.depositStep=2;case 12:case"end":return s.stop()}},s,t)}))()}}},m=(a("rOdO"),a("KHd+")),f=Object(m.a)(d,function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"deposit-comp"},[a("div",{staticClass:"balance-cell"},[a("div",{staticClass:"cell-hd"},[t._v("账户余额 : ")]),t._v(" "),a("div",{staticClass:"cell-bd"},[a("b",{staticClass:"primary"},[t._v(t._s(t.user.info.balance/100||0))]),t._v("\n 元\n ")]),t._v(" "),a("div",{staticClass:"cell-ft"},[a("el-button",{attrs:{size:"small",type:"primary"},on:{click:function(s){t.dialogVisible=!0}}},[t._v("充值")])],1)]),t._v(" "),a("Membership",{on:{change:t.changeMember}}),t._v(" "),a("el-dialog",{attrs:{title:"充值",visible:t.dialogVisible,width:"40%"},on:{"update:visible":function(s){t.dialogVisible=s}}},[1==t.depositStep?[a("el-tabs",{model:{value:t.form.payway,callback:function(s){t.$set(t.form,"payway",s)},expression:"form.payway"}},[a("el-tab-pane",{attrs:{name:"2"}},[a("span",{attrs:{slot:"label"},slot:"label"},[a("svg-icon",{attrs:{"icon-class":"wepay"}}),t._v(" 微信支付\n ")],1),t._v(" "),a("div",{staticClass:"amount-list"},t._l(t.amountList,function(s,e){return a("div",{key:e,staticClass:"amount-item",class:{hover:t.form.amount==s},on:{click:function(a){t.form.amount=s}}},[t._v("\n "+t._s(s/100)+" \n "),a("span",{staticClass:"desc"},[t._v("元")])])}))]),t._v(" "),a("el-tab-pane",{attrs:{name:"1"}},[a("span",{attrs:{slot:"label"},slot:"label"},[a("svg-icon",{attrs:{"icon-class":"zhifubao"}}),t._v(" 支付宝\n ")],1),t._v(" "),a("div",{staticClass:"amount-list"},t._l(t.amountList,function(s,e){return a("div",{key:e,staticClass:"amount-item",class:{hover:t.form.amount==s},on:{click:function(a){t.form.amount=s}}},[t._v("\n "+t._s(s/100)+" \n "),a("span",{staticClass:"desc"},[t._v("元")])])}))])],1),t._v(" "),a("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(s){t.dialogVisible=!1}}},[t._v("取 消")]),t._v(" "),a("el-button",{attrs:{type:"primary",loading:t.btnLoading},on:{click:t.fetchQrcodeSubmit}},[t._v("确 定")])],1)]:t._e(),t._v(" "),2==t.depositStep?a("pay",{attrs:{amount:t.form.amount,payway:t.form.payway,qrcode:t.qrcode},on:{success:t.paySuccess}}):t._e()],2)],1)},[],!1,null,"3258e044",null);f.options.__file="Deposit.vue";var _={components:{Deposit:f.exports}},b=(a("4trN"),Object(m.a)(_,function(){var t=this.$createElement,s=this._self._c||t;return s("div",{staticClass:"intro-index-page"},[s("deposit"),this._v(" "),this._m(0)],1)},[function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"sec"},[a("div",{staticClass:"sec-title"},[a("b",[t._v("使用教程")])]),t._v(" "),a("div",{staticClass:"title"},[a("b",[t._v("第一步: 创建应用")])]),t._v(" "),a("div",{staticClass:"text"},[t._v("\n 点击左侧菜单栏 ”应用管理“,进入界面,然后点击里面的”创建应用“按钮,开始创建您的第一个应用。 "),a("br"),t._v("创建成功后,就会为你生成AppID和AppSecret,这两个字段后面用于手机上的app配置\n ")]),t._v(" "),a("div",{staticClass:"title"},[a("b",[t._v("第二步: 下载App")])]),t._v(" "),a("div",{staticClass:"text"},[t._v("\n 点击左侧菜单栏 ”软件下载“,进入界面,按照要求依次下载里面的软件。如果手机内预先安装了其他版本的微信、支付宝,请卸载后再安装\n ")]),t._v(" "),a("div",{staticClass:"title"},[a("b",[t._v("第三步: 配置App")])]),t._v(" "),a("div",{staticClass:"text"},[t._v("\n 点击左侧菜单栏 ”软件下载“,进入界面,按照要求依次下载里面的软件。如果手机内预先安装了其他版本的微信、支付宝,请卸载后再安装\n ")]),t._v(" "),a("div",{staticClass:"title"},[a("b",[t._v("第四步: 测试支付")])]),t._v(" "),a("div",{staticClass:"text"},[t._v("\n 点击左侧菜单栏 ”软件下载“,进入界面,按照要求依次下载里面的软件。如果手机内预先安装了其他版本的微信、支付宝,请卸载后再安装\n ")])])}],!1,null,"63a081ac",null));b.options.__file="Index.vue";s.default=b.exports},HKbb:function(t,s,a){},rOdO:function(t,s,a){"use strict";var e=a("1jgq");a.n(e).a},vF8W:function(t,s,a){}}]); -------------------------------------------------------------------------------- /public/dist/static/css/app.cab2c720.css: -------------------------------------------------------------------------------- 1 | .fade-enter-active,.fade-leave-active{-webkit-transition:opacity .28s;transition:opacity .28s}.fade-enter,.fade-leave-active{opacity:0}.fade-transform-enter-active,.fade-transform-leave-active{-webkit-transition:all .5s;transition:all .5s}.fade-transform-enter{opacity:0;-webkit-transform:translateX(-30px);transform:translateX(-30px)}.fade-transform-leave-to{opacity:0;-webkit-transform:translateX(30px);transform:translateX(30px)}.breadcrumb-enter-active,.breadcrumb-leave-active{-webkit-transition:all .5s;transition:all .5s}.breadcrumb-enter,.breadcrumb-leave-active{opacity:0;-webkit-transform:translateX(20px);transform:translateX(20px)}.breadcrumb-move{-webkit-transition:all .5s;transition:all .5s}.breadcrumb-leave-active{position:absolute}.el-upload input[type=file]{display:none!important}.el-upload__input{display:none}.el-dialog{-webkit-transform:none;transform:none;left:0;position:relative;margin:0 auto}.upload-container .el-upload{width:100%}.upload-container .el-upload .el-upload-dragger{width:100%;height:200px}#app .main-container{min-height:100%;-webkit-transition:margin-left .28s;transition:margin-left .28s;margin-left:180px;position:relative}#app .sidebar-container{-webkit-transition:width .28s;transition:width .28s;width:180px!important;height:100%;position:fixed;font-size:0;top:0;bottom:0;left:0;z-index:1001;overflow:hidden}#app .sidebar-container .horizontal-collapse-transition{-webkit-transition:width 0s ease-in-out,padding-left 0s ease-in-out,padding-right 0s ease-in-out;transition:width 0s ease-in-out,padding-left 0s ease-in-out,padding-right 0s ease-in-out}#app .sidebar-container .scrollbar-wrapper{overflow-x:hidden!important}#app .sidebar-container .scrollbar-wrapper .el-scrollbar__view{height:100%}#app .sidebar-container .el-scrollbar__bar.is-vertical{right:0}#app .sidebar-container .is-horizontal{display:none}#app .sidebar-container a{display:inline-block;width:100%;overflow:hidden}#app .sidebar-container .svg-icon{margin-right:16px}#app .sidebar-container .el-menu{border:none;height:100%;width:100%!important}#app .sidebar-container .el-submenu__title:hover,#app .sidebar-container .submenu-title-noDropdown:hover{background-color:#263445!important}#app .sidebar-container .is-active>.el-submenu__title{color:#f4f4f5!important}#app .sidebar-container .el-submenu .el-menu-item,#app .sidebar-container .nest-menu .el-submenu>.el-submenu__title{min-width:180px!important;background-color:#1f2d3d!important}#app .sidebar-container .el-submenu .el-menu-item:hover,#app .sidebar-container .nest-menu .el-submenu>.el-submenu__title:hover{background-color:#001528!important}#app .hideSidebar .sidebar-container{width:36px!important}#app .hideSidebar .main-container{margin-left:36px}#app .hideSidebar .submenu-title-noDropdown{padding-left:10px!important;position:relative}#app .hideSidebar .submenu-title-noDropdown .el-tooltip{padding:0 10px!important}#app .hideSidebar .el-submenu{overflow:hidden}#app .hideSidebar .el-submenu>.el-submenu__title{padding-left:10px!important}#app .hideSidebar .el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}#app .hideSidebar .el-menu--collapse .el-submenu>.el-submenu__title>span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}#app .el-menu--collapse .el-menu .el-submenu{min-width:180px!important}#app .mobile .main-container{margin-left:0}#app .mobile .sidebar-container{-webkit-transition:-webkit-transform .28s;transition:-webkit-transform .28s;transition:transform .28s;transition:transform .28s,-webkit-transform .28s;width:180px!important}#app .mobile.hideSidebar .sidebar-container{pointer-events:none;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:translate3d(-180px,0,0);transform:translate3d(-180px,0,0)}#app .withoutAnimation .main-container,#app .withoutAnimation .sidebar-container{-webkit-transition:none;transition:none}.el-menu--vertical>.el-menu .svg-icon{margin-right:16px}.el-menu--vertical .el-menu-item:hover,.el-menu--vertical .nest-menu .el-submenu>.el-submenu__title:hover{background-color:#263445!important}.el-menu--vertical>.el-menu--popup{max-height:100vh;overflow-y:auto}.el-menu--vertical>.el-menu--popup::-webkit-scrollbar-track-piece{background:#d3dce6}.el-menu--vertical>.el-menu--popup::-webkit-scrollbar{width:6px}.el-menu--vertical>.el-menu--popup::-webkit-scrollbar-thumb{background:#99a9bf;border-radius:20px}body{height:100%;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;font-family:Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial,sans-serif}label{font-weight:700}html{-webkit-box-sizing:border-box;box-sizing:border-box}#app,html{height:100%}*,:after,:before{-webkit-box-sizing:inherit;box-sizing:inherit}a,a:active,a:focus,a:hover,div:focus{outline:none}a,a:focus,a:hover{cursor:pointer;color:inherit;text-decoration:none}.clearfix:after{visibility:hidden;display:block;font-size:0;content:" ";clear:both;height:0}.app-main{min-height:100%}.app-container{padding:20px}.cell{display:-webkit-box;display:-ms-flexbox;display:flex}.cell .primary{-webkit-box-flex:1;-ms-flex:1;flex:1}.app-breadcrumb.el-breadcrumb[data-v-6eeb655c]{display:inline-block;font-size:14px;line-height:50px;margin-left:10px}.app-breadcrumb.el-breadcrumb .no-redirect[data-v-6eeb655c]{color:#97a8be;cursor:text}.hamburger[data-v-68efea28]{display:inline-block;cursor:pointer;width:20px;height:20px}.hamburger.is-active[data-v-68efea28]{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.navbar[data-v-9bbe2cc8]{height:50px;line-height:50px;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.12),0 0 3px 0 rgba(0,0,0,.04);box-shadow:0 1px 3px 0 rgba(0,0,0,.12),0 0 3px 0 rgba(0,0,0,.04)}.navbar .hamburger-container[data-v-9bbe2cc8]{line-height:58px;height:50px;float:left;padding:0 10px}.navbar .screenfull[data-v-9bbe2cc8]{position:absolute;right:90px;top:16px;color:red}.navbar .avatar-container[data-v-9bbe2cc8]{height:50px;display:inline-block;position:absolute;right:35px}.navbar .avatar-container .avatar-wrapper[data-v-9bbe2cc8]{cursor:pointer;margin-top:5px;position:relative;line-height:normal;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:40px}.navbar .avatar-container .avatar-wrapper .user-avatar[data-v-9bbe2cc8]{width:40px;height:40px;border-radius:50%}.navbar .avatar-container .avatar-wrapper .user-nickname[data-v-9bbe2cc8]{margin:0 10px}.navbar .avatar-container .avatar-wrapper .el-icon-caret-bottom[data-v-9bbe2cc8]{font-size:12px}.contact-us[data-v-5e16de72]{background:#263445;cursor:pointer;font-size:14px;color:#bfcbd9;position:absolute;left:0;right:0;height:70px;line-height:70px;text-align:center;bottom:0}.app-main[data-v-dfcc6c68]{min-height:calc(100vh - 50px);position:relative;overflow:hidden;padding:32px}.app-wrapper[data-v-6ec8cb25]{position:relative;height:100%;width:100%}.app-wrapper[data-v-6ec8cb25]:after{content:"";display:table;clear:both}.app-wrapper.mobile.openSidebar[data-v-6ec8cb25]{position:fixed;top:0}.drawer-bg[data-v-6ec8cb25]{background:#000;opacity:.3;width:100%;top:0;height:100%;position:absolute;z-index:999}.svg-icon[data-v-77a1c50c]{width:1em;height:1em;vertical-align:-.15em;fill:currentColor;overflow:hidden} -------------------------------------------------------------------------------- /utils/statistic.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: hechao 3 | * @Date: 2019-04-01 16:46:36 4 | * @describe: 定时任务,跑统计结果 5 | */ 6 | 7 | const { 8 | sqlTable,sequelize 9 | } = require('../db/index.js') 10 | const Sequelize = require('sequelize') 11 | const schedule = require('node-schedule'); 12 | 13 | Date.prototype.format = function (fmt) { 14 | var o = { 15 | "M+": this.getMonth() + 1, //月份 16 | "d+": this.getDate(), //日 17 | "h+": this.getHours(), //小时 18 | "m+": this.getMinutes(), //分 19 | "s+": this.getSeconds(), //秒 20 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度 21 | "S": this.getMilliseconds() //毫秒 22 | }; 23 | if (/(y+)/.test(fmt)) { 24 | fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 25 | } 26 | for (var k in o) { 27 | if (new RegExp("(" + k + ")").test(fmt)) { 28 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 29 | } 30 | } 31 | return fmt; 32 | }; 33 | //今日统计更新 34 | async function day_statistic(){ 35 | // setInterval(()=>{ 36 | try { 37 | let now = new Date(); 38 | let date = now.format("yyyy-MM-dd"); 39 | let day =parseInt(( now - new Date(now.getFullYear().toString()))/(24*60*60*1000))+1; 40 | let result = await sequelize.query(`select * from paychecks where dayofyear(createdAt)=?`,{ 41 | type: Sequelize.QueryTypes.SELECT, 42 | replacements:[day] 43 | }) 44 | let obj={} 45 | result.forEach(item => { 46 | if(obj[item['userid']] || (obj[item['userid']] = [])) { 47 | obj[item['userid']].push(item) 48 | } 49 | }); 50 | console.info(obj) 51 | for(var p in obj){ 52 | let w_count=0,p_count=0,w_total1=0,p_total1=0,w_total2=0,p_total2=0;//微信订单数量,支付宝订单数量,微信已知来源收款总额.. 53 | obj[p].forEach(item=>{ 54 | if(item.appid && item.payway == 1){ 55 | p_count++; 56 | p_total1+=item.amount; 57 | } 58 | if(item.appid && item.payway == 2){ 59 | w_count++; 60 | w_total1+=item.amount; 61 | } 62 | if(!item.appid && item.payway == 1){ 63 | p_total2+=item.amount; 64 | } 65 | if(!item.appid && item.payway == 2){ 66 | w_total2+=item.amount; 67 | } 68 | }) 69 | let statistics = await sequelize.query(`select id from statistic where userid=? and date=?`,{ 70 | type: Sequelize.QueryTypes.SELECT, 71 | replacements:[p,date] 72 | }) 73 | if(statistics.length>0){ 74 | await sequelize.query(`update statistic set w_count=?,p_count=?,w_total1=?,p_total1=?, 75 | w_total2=?,p_total2=? where userid=? and date=?`,{ 76 | type: Sequelize.QueryTypes.UPDATE, 77 | replacements:[w_count,p_count,w_total1,p_total1,w_total2,p_total2,p,date] 78 | }) 79 | }else{ 80 | await sqlTable.statistic.create({ 81 | userid:p, 82 | w_count, 83 | p_count, 84 | w_total1, 85 | p_total1, 86 | w_total2, 87 | p_total2, 88 | date 89 | }) 90 | } 91 | } 92 | } catch (error) { 93 | console.info('error----->',error) 94 | } 95 | 96 | // },10000) 97 | 98 | 99 | } 100 | 101 | //昨天统计 102 | async function yesterday_statistic(){ 103 | try { 104 | let now = new Date(); 105 | // let date = now.format("yyyy-MM-dd"); 106 | let yesterday = new Date(now.getTime()-24*60*60*1000); 107 | let day =parseInt(( yesterday - new Date(yesterday.getFullYear().toString()))/(24*60*60*1000))+1; 108 | let date= yesterday.format("yyyy-MM-dd") 109 | let result = await sequelize.query(`select * from paychecks where dayofyear(createdAt)=?`,{ 110 | type: Sequelize.QueryTypes.SELECT, 111 | replacements:[day] 112 | }) 113 | let users = await sequelize.query(`select id from users`,{ 114 | type: Sequelize.QueryTypes.SELECT, 115 | }) 116 | let obj={} 117 | users.forEach(item=>{ 118 | obj[item['id']]=[] 119 | }) 120 | result.forEach(item => { 121 | if(obj[item['userid']] || (obj[item['userid']] = [])) { 122 | obj[item['userid']].push(item) 123 | } 124 | }); 125 | console.info(obj) 126 | for(var p in obj){ 127 | let w_count=0,p_count=0,w_total1=0,p_total1=0,w_total2=0,p_total2=0;//微信订单数量,支付宝订单数量,微信已知来源收款总额.. 128 | obj[p].forEach(item=>{ 129 | if(item.appid && item.payway == 1){ 130 | p_count++; 131 | p_total1+=item.amount; 132 | } 133 | if(item.appid && item.payway == 2){ 134 | w_count++; 135 | w_total1+=item.amount; 136 | } 137 | if(!item.appid && item.payway == 1){ 138 | p_total2+=item.amount; 139 | } 140 | if(!item.appid && item.payway == 2){ 141 | w_total2+=item.amount; 142 | } 143 | }) 144 | let statistics = await sequelize.query(`select id from statistic where userid=? and date=?`,{ 145 | type: Sequelize.QueryTypes.SELECT, 146 | replacements:[p,date] 147 | }) 148 | if(statistics.length>0){ 149 | await sequelize.query(`update statistic set w_count=?,p_count=?,w_total1=?,p_total1=?, 150 | w_total2=?,p_total2=? where userid=? and date=?`,{ 151 | type: Sequelize.QueryTypes.UPDATE, 152 | replacements:[w_count,p_count,w_total1,p_total1,w_total2,p_total2,p,date] 153 | }) 154 | }else{ 155 | await sqlTable.statistic.create({ 156 | userid:p, 157 | w_count, 158 | p_count, 159 | w_total1, 160 | p_total1, 161 | w_total2, 162 | p_total2, 163 | date 164 | }) 165 | } 166 | } 167 | } catch (error) { 168 | console.info('err---->=',error) 169 | } 170 | } 171 | 172 | 173 | function scheduleCronstyle(){ 174 | // yesterday_statistic(); 175 | // day_statistic() 176 | schedule.scheduleJob('0 0 10 * * *', yesterday_statistic); 177 | // schedule.scheduleJob('0 5 * * * *', day_statistic); 178 | } 179 | module.exports={ 180 | scheduleCronstyle 181 | } -------------------------------------------------------------------------------- /public/dist/static/js/chunk-6929.2461bbf3.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-6929"],{Jvyq:function(s,t){s.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJgAAACKCAYAAABW3IOxAAAAAXNSR0IArs4c6QAAElhJREFUeAHtnXuQHMV9x7tndvdOQkgCWZKxkITEQ5YB87AVCT9iEqgyTsXlyA42QVRcScXYzvOPkKeJLSrOy8RVxMSVBNuVqrhIxS7KJk5BKlWpQKiKX4hgwOII6CzLAk6H0Pt0e/uY6Xx+p7vT3Gl2b2e3Z2d2t7vqdzuP7l//+tvf6+75dU+PVi5kioAxZl01UDtMEG43Wu/AmOuUUYeVVqNKmVGjvX2+HAdqX6mkfqS1Pp2pwQkz1wnju+gdIACZlpTr6npU7FChETIh5uJkKvWYPkO+fUp7oyZUowWt9hWLahTyHU2mK/3YjmApYjxlzGWmSuukQ4iktwP2NZCsmFqWWh9D96hWZp+nvb2lgvompNubWn4tKHYEawGkVqJAnBWVutpmZlono2mdjFnVSlqbcTytnynSpHlaXYPeV5F3QLIDNvNIossRLAlaM3Ehk1etqitDIZGidTKMnbTayvVM8IRAZQj1dNHXF9N9blhQpBc4f2dW3WcmgCwAIPenEGdNJVDbGYhDpOmB+DaunZ+14VrpV31fjxb96dZqeRN7vs29m4WITeKkcssRbAGsEKdUq6lrQ7o6M9M6GWU2LYiW6Snd4HO+p8sFX70dQ7wWjfkW8T4IyYIW41uJNvAEKxuzUQbiSocMwqdbp+sh2ZAVdC0qgRhVur8nS75+A79b2lT9AHo+3mbatpINHMEgz/JKqH7ZmPBtJtA3J3cTtIVz+4m0PsyYfS8D9ytRsrp9RXMpd0Oye+bOUj4YOIJNVsJvQKqdgitAh8aocQbIr/P0d4pLNbmMDOPsXKk9tSYMzUrOux6wbaTg6SN0g9vI3HaLeif6v9SNQg0UwSZr5ndVGP51EmCpiJPEH4OAxwFLBskyhilyvozBzyp+L5JxWxKdjeKSl+j+Xqmgl0D66xrFs3Bd8tlJfv9mQVdTFQNDMMj1Tm3M45Ch0BSRhDeppBqtnXjXZXrnlApV1TAKxwe2hHsreEBYw/015NsYazzwdIM/KBT0ZURa6GZIaFHL0eWf5SZs/E7LKdqI2LjQbSjLaxIqd3W5ap6ma1yXiY2MowB6nLyPQbZJ7dE1Kzz6Ri2hG6zMdINZuD2OYNO7IJn4ylIJfU8wyOVN1cx/8MuAPj+BSq0PFabnFddnbNUB8r8Be8bSsKNVH0oaeXdF51Q13J03cknB8WM9TUeaNbnElI3Iv4NRM0etxGsr9HULRsv1XoAT8HJVToZozw8V9VvaqrH0Ej2G6ltoyao2s+jbFmzSmPX4IB7MG7mowIlSUa+xWYmWdP0Mev7JNl59STBAKqqa+XoWqxkWq+yCr1+iOX3DYvEyuv8R8r3bZt59SbByDV+XmV7QZxOrjnUx7tpT8FL1b3VsIwq22lAyq6PvCDZZMbfy+P/bswXMz68ew4FqtfLyU7bGlvQVwVhBeoXW5iuNi5vNHcZdhkH9cXI/LxsLssu1bwjGuGuJqZmH+M3CYdm0Bnlp49tM/Qxc6yWgWJ02aYpyyjenauHfMXF9dcrZJFZP6/UiKyG2J07YJwn6ogVjGujXINdH81YnkGuKrlFWQvTNP3JSjHueYNWquZY5xvuTFrwb8Zln3INLQjzlAxt6n2BBeBdPjaxm0CZPtYg9e5jEfleebMrClp5vuk9Vwl1CLqZf9nuePljy1YTvqxKku4iB9eUM+m0v1lu8nrR+fbioB7rlmgWp5wkmBYFEOjBmcxCqzbX6bNFkaao+4fvmh3RVRwu+Z3iau5CLl5LggrOx7B/h7xpF68AO7KOI9gXBogWKHrPmakU9UG+rB/SetWD6Fq1dQEv3Eu8QjtHCVYueWso4aT1xraxsQPcTEPmno3YM8nFfEyyuYmnt/CAwlweBujx6n0WARwqe9+OCF55kOodDbzXE20z8lpdD02LuZ42X7D3hwgwCA0ewRjVvQrOqFgar5K2PMyGQl0JqdK//xxzi6wzYA1qmFazhugTSrZiNNfsrcSHXBOebZq+53wH2z7RS+RCpWAvMFnrXLdPvG80kohscLxW8l30dln3PG+ZR/E2QcATy3dSK3kGK41qwNmqbV9nWTlWDtWeSnhnbrT6/kNclOG2U0F6SnveD2YOiY03unzUGQkewGFDcJXsIOILZw9JpikHAESwGFHfJHgKOYPawdJpiEHAEiwHFXbKHgCOYPSydphgEHMFiQHGX7CHgCGYPS6cpBgFHsBhQ3CV7CDiC2cPSaYpBwE1vxIAy4Jd+gUn+V1rA4Ani3CHr65rFdQRrhs5g3ltCsUUWC7cRQbYX/XiziK6LbIaOu7cYAnfS2t3TLJIjWDN03L1WEPg0JPtko4iOYI2QcdeTIPC3kOxDcQkcweJQcdeSIiA8ks3+blyY0BFsISLuvF0E5P3ThyGZfEZwLjiCzUHhDiwgIC/DyJ64cy++OIJZQNWpmIfARZzJtvHT31VyBJuHjTuxhIC8c/ooJJPP7bjgEEgFAfmW5UOOYKlg65TOIHCTI5jjQqoIOIKlCq9T7gjmOJAqAo5gqcLrlDuCOQ6kikBPEww/yw2+7z3FvlynU0XJKW8bgZ5bcAipZDHcLyG/gVy/+owrr16tq2fLNXO0UgtWhopPtmSxN2vb1dC/CdnErzcCxLoUSz+B/Cpy4SJWlys1M1KuhyeqdcP3svWbSe8vkqaj22zfFPqe6ukeoSMA4hPXc00wSCEVdgsirdX7kLbsZYfWE3yc9AW+fltmQ7mLjNJXoLstXdgQGxzBYmHJJ8GofGmhfgX5dWRzrOkdXOSrIIf5OsiLtHB1NgneQH6bOlA3ndQRLBbBfBGMipYNdKW1kjFWKy8exJYq6cXQqJch3GilFupqIIQ2FyfV4QgWi1j2BINUsovzrchvIjtizezyRfbb38cDw0E+sFXgeAs2LvoJZEew2ErKjmBU2gZMkleePoZMrx2KNTH7i2EtVCO0cIdo4ZaGodrKnvorF5rlCLYQkenz7hMMYt1M1tINvh9J9cluuoj2/9T4msjeybo5DOFWmFBdCeHOcwSLBbo7BINUy8n+o4gQa0usKb17cbJSV4+VCurneCy1+mTau5DMWZ4uwSDWVWQlpLoDWTaXbf8cvERR5FPJ2/qnSFZLUrfuyYdUonMnIsR6j1Vz86PsJ5jyMnID4lqtJvViDRyIJYv975yRNzXJs5dvjWO8tFrytGv9n7OXgWlg+2sdEwxivRvl0lp9ECk2yKjXL0s3+CwiXWHX/HM9DNppbL8PubdtgkGsN/INn78s+upnUbS+h8FoZroAtQe5DpEHFReaI1Dl9j8gn2Vbp9ckatsEK1eDrzHl8mEUhSj5AR+D4qOf6gp0in+r14MA9T1kK+K+QbR4bcoeYV9FdsOHA9HobRFsqm7eFwbho1FFcoxymUF+Zubzd/Ju3MaFcXJ+HmLfd5FLkH4dR1I0q+EbaLubuh+J05qYYHSNS6eqZi/OxUviFM5emyHbs0I2vqF9KRk1jT+bLsPf75P3amRThjb0Utb/ibF/RD3LEKJhSEywqUpwL//mdzXUGHNDyMaSmef4uOdhutG8ke1pTF6K9JsDOKYmrFySoYMQ67FWtCUiWLVqrgmU2UMr1tEjOsb9kJZtHLJtwgDry3FaKThx9iIydnhri/EHPZrgJV3hw0mAaJlgkMpjhcF3WIr8U0kyWCwuBu+dIdslXSLbPmwSt4O82u7C4gjsJ8pnkAepKxmjJgotE4xx12+FJvxCIu0JI1OAEcg2Rsu2EcNkibTNcBBlryDbkZbLbdOAHtN1CHs/izxAvZz9lHnCQrQENK3XOpYcj/B7fkL9bUenUPIx9lch24YOySb+GPG+C7E66trbLkxvJZTW/XPI31AHk52a3hLBJishj6JG5hczCRT0Rcj2CmRbj8GXtWiEAPUcsg0ZbjHNIEcTMkkP9VfgLdhZCYsSrFI3HwiC8GEruVlQQuH3QbaDBQ+y6ViyCVBPIdciXWtxLRQtKxXS/T2AiPddukWroSnB6BKXMfZ6Hp9XLqeCeOF2lFfFDhZ8vQ6ybQQZ8WWJ932VVZT6U5kM2B9EPgOxZCCfSmhKsMlqcJ8y6ndSydmiUgAKhor6dQqz1qLaflb1rxTuU+AmrodUQ0OC4fN6Oz6v79KK5X5Zs+/rl0u+TvwmUKrI5lP5f2HWH0MscZZ2JcQSTEiFz+tJfF6yiiDXAbAmhou6H1fL2sT9SZQJsWR6p6sh9rG9XKdb7AFyCVJFv30fTVeRziYzmYAW77tMSGcSzmnByvI6WY2BvTHnZWJRgkw1c5vDBb06QZJBiXqAgu5Gvgq5ZDoss3BOC2aq5ov4vHJPLkGMcZds/O/CWQTEqfxnyN9DLFnTlnmYRzB8Xr+Iz+vnM7eqBQM8Tx/ytHpjC1EHIcoJCnkvch/EOp2nAs91kXSJK3h7mT57+uWNPNl4ji2AWMMtUZwz/pwYA3OhTEnvR8T7fjSPpZ5rwdiH4S8wUN4Myn3Ai38Kcl2Ye0PTM1C8719B/hRivZpeNp1rnm4E8HntwOf1P7RiXucq09UAoCdxSyxPN5fcajdY9i/In4DDaG6tjBhWgFQFVko80AvkErtxSwxF7B+kw/+msHdBrKZLlPMGiDdVV3dBrqvzZlicPbgljjD3OGgEE1/WByDWjb1GLqlDjy3+buR1oCNxFZqna4Brhnw9SJPYsrLhE8jVlP1beaqLJLboseM1tizV1VLB+9+SH0762mM1Qv6eJFkxcYzu8YIkhevRuOJm+DzyOYiVK5dDO3ieIVgkJYUKqcxn8JAfw890GWTbELmdySE2VRjY93vXKB73f0RkAG99XVYmFUem5xBsoSG4BEaGCvpQ0ffWsy4MwnU/FAteGTuWdD/nruX4CDn9PsR6vms5dimjRQkWtcMvePuHff0TXqRdw5uOsrAv9eBpfQqnar+uTH0KAOXJ8PHUgcwog0QEi9rIVM3YkqLH8mVzASR4S1pujqGiZ+iq+81p/2OwvBv5Z8glvq2+DW0TLIqI53tHadle4KWMpZDhKvGtRe+3e8za+xOlQl9NaB8Diz9H7odYlXZx6aV0VggWLTBPoRNF34yUitBOs0Fum98MogJCxn40jlHtPXssKxu+iMjUjpBsYIJ1gkWRgx7VkqefZ1lNnXHbVsjW8jIgnmQncUssjerrwWPp/r6OyF4O+3vQ/o5NTpVgUeukRYIwI7gbJmnZ5FtBDddyEXeKeMPR9D14LFM7v0dZnuxB262Z3DWCLbQYx+5LeOaPez6bnxgzz0PPvYApody/bLKwTDPnMrXzhxCrZ73vDcrV1uXMCBa1tljQB0u+GmfItR7CLWPs1XJXGtWT8bE4R+9BvgS5Ml2mnDEO87LPBcGiFp0/7KvzhnpqZD87tXMvxJqIlsUd53AzEGYLqJeeIFhfTu3Y/qew4q+ybVQP6OvbqR3b2DuCJUNUpnbkyfCxZMkGN3bul0jnpGoOYMcdyDZHrmQ14lqw5njJPlkytfMFiDUQUzvN4Uh+1xEsHrPZqR3ZMyuXr4PFm52/q45g8+tk4Kd25sPR+Zkj2FkMn+BQ1mYN9NTOWTjsHDmCKfUCUP4BxHJTO3Y4NU/LID9FjoPEJ5GrHLnmccLqySC2YG5qxyqFmisrsBp5gumZQdghcHZq59O0WGPNYXF3bSHgrV3hrwXwXcgjSNtfdLBlUEp6HkXvNZTvY4gjV0ogx6mdN6t88qRZVQ7DDxsd7mLC+R0sCpx3P06B7WvLhj3W61gbGrqpHdsVlFBfQwIdK5uNlUp4u1Lh7TiHrkqot+3olggmUzufQvr+rZ22ge5SwoYEi+Y/PmHequr1XaHSt6X9pneHBHNTO9GKy8FxSwSbtVO6zMMT6t2hCW7nC6O3stTZ+iZwbRLMTe3MVlLOfhMRLGo7ZCuOnwpuYX3gLsj2flo2K28AJSTY7NSO7AH/o6h97jgfCLRNsKj5r/FNI3My2MnHb3ah8GbI1/YLGwkIJlM7sjbr+1Fb3HG+ELBCsGiRDp0ya1QYfmT64cCoHdF7rRy3QDA3tdMKkDmJY51g0XKNHzebcXnwFIrbw6g3R+81Om5CMJna2Y18mVar3ii9u54vBFIlWLSoh0+b6+u1+u3MHNzGzMG66L3ocQzB5PuPn0dkQzb31k4UrB447hrBZrFgfOYdmqi/RwcaZ676EGRbOXtPfiMEc1M7UWDccXIEINvQ+Mn6zrHj9YfGTtTLsp3nqamAy+YR5MrkGl0Kh0ADBI4Ys/zUVPj4sdPBPQ2iuMsOAYeAQ2A+Av8Pby5Qwk3kUm8AAAAASUVORK5CYII="},jNvO:function(s,t,i){"use strict";i.r(t);var n=[function(){var s=this.$createElement,t=this._self._c||s;return t("div",{staticClass:"pic-404"},[t("img",{staticClass:"pic-404__parent",attrs:{src:i("o2sD"),alt:"404"}}),this._v(" "),t("img",{staticClass:"pic-404__child left",attrs:{src:i("Jvyq"),alt:"404"}}),this._v(" "),t("img",{staticClass:"pic-404__child mid",attrs:{src:i("Jvyq"),alt:"404"}}),this._v(" "),t("img",{staticClass:"pic-404__child right",attrs:{src:i("Jvyq"),alt:"404"}})])},function(){var s=this.$createElement,t=this._self._c||s;return t("div",{staticClass:"bullshit__info"},[this._v("版权所有\n "),t("a",{staticClass:"link-type",attrs:{href:"https://wallstreetcn.com",target:"_blank"}},[this._v("华尔街见闻")])])}],r={name:"Page404",computed:{message:function(){return"网管说这个页面你不能进......"}}},l=(i("yGHO"),i("KHd+")),e=Object(l.a)(r,function(){var s=this,t=s.$createElement,i=s._self._c||t;return i("div",{staticClass:"wscn-http404-container"},[i("div",{staticClass:"wscn-http404"},[s._m(0),s._v(" "),i("div",{staticClass:"bullshit"},[i("div",{staticClass:"bullshit__oops"},[s._v("OOPS!")]),s._v(" "),s._m(1),s._v(" "),i("div",{staticClass:"bullshit__headline"},[s._v(s._s(s.message))]),s._v(" "),i("div",{staticClass:"bullshit__info"},[s._v("请检查您输入的网址是否正确,请点击以下按钮返回主页或者发送错误报告")]),s._v(" "),i("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[s._v("返回首页")])])])])},n,!1,null,"9b45c3f8",null);e.options.__file="404.vue";t.default=e.exports},o2sD:function(s,t,i){s.exports=i.p+"static/img/404.a57b6f3.png"},oBSS:function(s,t,i){},yGHO:function(s,t,i){"use strict";var n=i("oBSS");i.n(n).a}}]); -------------------------------------------------------------------------------- /public/dist/static/js/chunk-fc3b.827b4c52.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-fc3b"],{"2uYv":function(e,t,s){"use strict";var a=s("UDD5");s.n(a).a},Timz:function(e,t,s){"use strict";var a=s("qvc3");s.n(a).a},UDD5:function(e,t,s){},qeMi:function(e,t,s){"use strict";s.r(t);var a=s("14Xm"),r=s.n(a),n=s("D3Ub"),o=s.n(n),i=s("gjeX"),l=s.n(i),c=s("wk8/"),m=s("QqA1"),p=s.n(m),u={data:function(){return{mode:"mobile",smsCount:-1,mobileForm:{mobile_phone:"",password:"",code:""},emailCount:-1,emailLoading:!1,emailForm:{email:"",password:"",code:""},emailRules:{email:[{required:!0,message:"请输入邮箱",trigger:"blur"},{type:"email",message:"请输入正确的邮箱地址",trigger:"blur"}],code:[{required:!0,message:"请输入验证码",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"},{min:6,message:"密码长度不低于6位",trigger:"blur"}]},loading:!1,pwdType:"password",redirect:void 0}},methods:{showPwd:function(){"password"===this.pwdType?this.pwdType="":this.pwdType="password"},mobileSubmit:function(){var e=this;return o()(r.a.mark(function t(){return r.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(/\d{11}/.test(e.mobileForm.mobile_phone)){t.next=3;break}return e.$message({type:"warning",message:"请输入正确的手机号"}),t.abrupt("return");case 3:if(e.mobileForm.code){t.next=6;break}return e.$message({type:"warning",message:"请输入验证码"}),t.abrupt("return");case 6:if(e.mobileForm.password){t.next=9;break}return e.$message({type:"warning",message:"请输入密码"}),t.abrupt("return");case 9:return t.next=11,Object(c.f)({mobile_phone:e.mobileForm.mobile_phone,code:e.mobileForm.code,password:l()(e.mobileForm.password)});case 11:if(null!==t.sent){t.next=14;break}return t.abrupt("return");case 14:e.$message({type:"success",message:"注册成功,请登录"}),e.$router.push({path:"/login"});case 16:case"end":return t.stop()}},t,e)}))()},emailSubmit:function(){var e=this;return o()(r.a.mark(function t(){return r.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:e.$refs.emailForm.validate(function(){var t=o()(r.a.mark(function t(s){var a,n;return r.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(s){t.next=2;break}return t.abrupt("return");case 2:return e.emailLoading=!0,(a=p()({},e.emailForm)).password=l()(a.password),t.next=7,Object(c.f)(a);case 7:if(n=t.sent,e.emailLoading=!1,null!==n){t.next=11;break}return t.abrupt("return");case 11:e.$message({type:"success",message:"注册成功,请登录"}),e.$router.push({path:"/login"});case 13:case"end":return t.stop()}},t,e)}));return function(e){return t.apply(this,arguments)}}());case 1:case"end":return t.stop()}},t,e)}))()},sendSMS:function(){var e=this;return o()(r.a.mark(function t(){var s;return r.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(!(e.smsCount>=0)){t.next=2;break}return t.abrupt("return");case 2:if(/\d{11}/.test(e.mobileForm.mobile_phone)){t.next=5;break}return e.$message({type:"warning",message:"请输入正确的手机号"}),t.abrupt("return");case 5:return t.next=7,Object(c.h)({mobile_phone:e.mobileForm.mobile_phone});case 7:if(null!==t.sent){t.next=10;break}return t.abrupt("return");case 10:e.$message({type:"success",message:"短信发送成功"}),e.smsCount=60,s=setInterval(function(){e.smsCount<=0&&clearInterval(s),e.smsCount-=1},1e3);case 13:case"end":return t.stop()}},t,e)}))()},sendMail:function(){var e=this;return o()(r.a.mark(function t(){var s;return r.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(!(e.emailCount>=0)){t.next=2;break}return t.abrupt("return");case 2:return t.next=4,Object(c.g)({email:e.emailForm.email});case 4:if(null!==t.sent){t.next=7;break}return t.abrupt("return");case 7:e.$message({type:"success",message:"发送成功"}),e.emailCount=60,s=setInterval(function(){e.emailCount<=0&&clearInterval(s),e.emailCount-=1},1e3);case 10:case"end":return t.stop()}},t,e)}))()}}},d=(s("Timz"),s("2uYv"),s("KHd+")),v=Object(d.a)(u,function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"login-container"},["mobile"==e.mode?s("el-form",{ref:"mobileForm",staticClass:"login-form",attrs:{model:e.mobileForm,"auto-complete":"on","label-position":"left"}},[s("h3",{staticClass:"title"},[e._v("手机注册")]),e._v(" "),s("el-form-item",{attrs:{prop:"phone"}},[s("span",{staticClass:"svg-container"},[s("svg-icon",{attrs:{"icon-class":"phone"}})],1),e._v(" "),s("el-input",{attrs:{type:"text","auto-complete":"on",placeholder:"请输入手机号"},model:{value:e.mobileForm.mobile_phone,callback:function(t){e.$set(e.mobileForm,"mobile_phone",t)},expression:"mobileForm.mobile_phone"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"phone"}},[s("span",{staticClass:"svg-container"},[s("svg-icon",{attrs:{"icon-class":"verifycode"}})],1),e._v(" "),s("el-input",{attrs:{type:"text","auto-complete":"on",placeholder:"验证码"},model:{value:e.mobileForm.code,callback:function(t){e.$set(e.mobileForm,"code",t)},expression:"mobileForm.code"}}),e._v(" "),s("div",{staticClass:"verify-btn",on:{click:e.sendSMS}},[e._v(e._s(e.smsCount>=0?e.smsCount:"获取验证码"))])],1),e._v(" "),s("el-form-item",{attrs:{prop:"password"}},[s("span",{staticClass:"svg-container"},[s("svg-icon",{attrs:{"icon-class":"password"}})],1),e._v(" "),s("el-input",{attrs:{type:e.pwdType,name:"password","auto-complete":"on",placeholder:"密码"},nativeOn:{keyup:function(t){return"button"in t||!e._k(t.keyCode,"enter",13,t.key,"Enter")?e.handleLogin(t):null}},model:{value:e.mobileForm.password,callback:function(t){e.$set(e.mobileForm,"password",t)},expression:"mobileForm.password"}}),e._v(" "),s("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[s("svg-icon",{attrs:{"icon-class":"password"===e.pwdType?"eye":"eye-open"}})],1)],1),e._v(" "),s("el-form-item",[s("el-button",{staticStyle:{width:"100%"},attrs:{loading:e.loading,type:"primary"},on:{click:e.mobileSubmit}},[e._v("\n 注册\n ")])],1),e._v(" "),s("div",{staticClass:"tips"},[s("a",{on:{click:function(t){e.mode="email"}}},[e._v("邮箱注册")]),e._v(" "),s("span",{staticClass:"tips-line"},[e._v("|")]),e._v(" "),s("router-link",{staticClass:"tips-link",attrs:{to:{path:"/login"},href:""}},[e._v("登录")])],1)],1):s("el-form",{ref:"emailForm",staticClass:"login-form",attrs:{model:e.emailForm,rules:e.emailRules,"auto-complete":"on","label-position":"left"}},[s("h3",{staticClass:"title"},[e._v("邮箱注册")]),e._v(" "),s("el-form-item",{attrs:{prop:"email"}},[s("span",{staticClass:"svg-container"},[s("svg-icon",{attrs:{"icon-class":"email"}})],1),e._v(" "),s("el-input",{attrs:{type:"text","auto-complete":"on",placeholder:"请输入邮箱"},model:{value:e.emailForm.email,callback:function(t){e.$set(e.emailForm,"email",t)},expression:"emailForm.email"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"code"}},[s("span",{staticClass:"svg-container"},[s("svg-icon",{attrs:{"icon-class":"verifycode"}})],1),e._v(" "),s("el-input",{attrs:{type:"text","auto-complete":"on",placeholder:"验证码"},model:{value:e.emailForm.code,callback:function(t){e.$set(e.emailForm,"code",t)},expression:"emailForm.code"}}),e._v(" "),s("div",{staticClass:"verify-btn",on:{click:e.sendMail}},[e._v(e._s(e.emailCount>=0?e.emailCount:"获取验证码"))])],1),e._v(" "),s("el-form-item",{attrs:{prop:"password"}},[s("span",{staticClass:"svg-container"},[s("svg-icon",{attrs:{"icon-class":"password"}})],1),e._v(" "),s("el-input",{attrs:{type:e.pwdType,name:"password","auto-complete":"on",placeholder:"密码"},nativeOn:{keyup:function(t){return"button"in t||!e._k(t.keyCode,"enter",13,t.key,"Enter")?e.emailSubmit(t):null}},model:{value:e.emailForm.password,callback:function(t){e.$set(e.emailForm,"password",t)},expression:"emailForm.password"}}),e._v(" "),s("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[s("svg-icon",{attrs:{"icon-class":"password"===e.pwdType?"eye":"eye-open"}})],1)],1),e._v(" "),s("el-form-item",[s("el-button",{staticStyle:{width:"100%"},attrs:{loading:e.emailLoading,type:"primary"},on:{click:e.emailSubmit}},[e._v("\n 注册\n ")])],1),e._v(" "),s("div",{staticClass:"tips"},[s("a",{on:{click:function(t){e.mode="mobile"}}},[e._v("手机注册")]),e._v(" "),s("span",{staticClass:"tips-line"},[e._v("|")]),e._v(" "),s("router-link",{staticClass:"tips-link",attrs:{to:{path:"/login"},href:""}},[e._v("登录")])],1)],1)],1)},[],!1,null,"b89682e8",null);v.options.__file="Register.vue";t.default=v.exports},qvc3:function(e,t,s){}}]); -------------------------------------------------------------------------------- /public/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { /* 1 */ 178 | overflow: visible; 179 | } 180 | 181 | /** 182 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 183 | * 1. Remove the inheritance of text transform in Firefox. 184 | */ 185 | 186 | button, 187 | select { /* 1 */ 188 | text-transform: none; 189 | } 190 | 191 | /** 192 | * Correct the inability to style clickable types in iOS and Safari. 193 | */ 194 | 195 | button, 196 | [type="button"], 197 | [type="reset"], 198 | [type="submit"] { 199 | -webkit-appearance: button; 200 | } 201 | 202 | /** 203 | * Remove the inner border and padding in Firefox. 204 | */ 205 | 206 | button::-moz-focus-inner, 207 | [type="button"]::-moz-focus-inner, 208 | [type="reset"]::-moz-focus-inner, 209 | [type="submit"]::-moz-focus-inner { 210 | border-style: none; 211 | padding: 0; 212 | } 213 | 214 | /** 215 | * Restore the focus styles unset by the previous rule. 216 | */ 217 | 218 | button:-moz-focusring, 219 | [type="button"]:-moz-focusring, 220 | [type="reset"]:-moz-focusring, 221 | [type="submit"]:-moz-focusring { 222 | outline: 1px dotted ButtonText; 223 | } 224 | 225 | /** 226 | * Correct the padding in Firefox. 227 | */ 228 | 229 | fieldset { 230 | padding: 0.35em 0.75em 0.625em; 231 | } 232 | 233 | /** 234 | * 1. Correct the text wrapping in Edge and IE. 235 | * 2. Correct the color inheritance from `fieldset` elements in IE. 236 | * 3. Remove the padding so developers are not caught out when they zero out 237 | * `fieldset` elements in all browsers. 238 | */ 239 | 240 | legend { 241 | box-sizing: border-box; /* 1 */ 242 | color: inherit; /* 2 */ 243 | display: table; /* 1 */ 244 | max-width: 100%; /* 1 */ 245 | padding: 0; /* 3 */ 246 | white-space: normal; /* 1 */ 247 | } 248 | 249 | /** 250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 251 | */ 252 | 253 | progress { 254 | vertical-align: baseline; 255 | } 256 | 257 | /** 258 | * Remove the default vertical scrollbar in IE 10+. 259 | */ 260 | 261 | textarea { 262 | overflow: auto; 263 | } 264 | 265 | /** 266 | * 1. Add the correct box sizing in IE 10. 267 | * 2. Remove the padding in IE 10. 268 | */ 269 | 270 | [type="checkbox"], 271 | [type="radio"] { 272 | box-sizing: border-box; /* 1 */ 273 | padding: 0; /* 2 */ 274 | } 275 | 276 | /** 277 | * Correct the cursor style of increment and decrement buttons in Chrome. 278 | */ 279 | 280 | [type="number"]::-webkit-inner-spin-button, 281 | [type="number"]::-webkit-outer-spin-button { 282 | height: auto; 283 | } 284 | 285 | /** 286 | * 1. Correct the odd appearance in Chrome and Safari. 287 | * 2. Correct the outline style in Safari. 288 | */ 289 | 290 | [type="search"] { 291 | -webkit-appearance: textfield; /* 1 */ 292 | outline-offset: -2px; /* 2 */ 293 | } 294 | 295 | /** 296 | * Remove the inner padding in Chrome and Safari on macOS. 297 | */ 298 | 299 | [type="search"]::-webkit-search-decoration { 300 | -webkit-appearance: none; 301 | } 302 | 303 | /** 304 | * 1. Correct the inability to style clickable types in iOS and Safari. 305 | * 2. Change font properties to `inherit` in Safari. 306 | */ 307 | 308 | ::-webkit-file-upload-button { 309 | -webkit-appearance: button; /* 1 */ 310 | font: inherit; /* 2 */ 311 | } 312 | 313 | /* Interactive 314 | ========================================================================== */ 315 | 316 | /* 317 | * Add the correct display in Edge, IE 10+, and Firefox. 318 | */ 319 | 320 | details { 321 | display: block; 322 | } 323 | 324 | /* 325 | * Add the correct display in all browsers. 326 | */ 327 | 328 | summary { 329 | display: list-item; 330 | } 331 | 332 | /* Misc 333 | ========================================================================== */ 334 | 335 | /** 336 | * Add the correct display in IE 10+. 337 | */ 338 | 339 | template { 340 | display: none; 341 | } 342 | 343 | /** 344 | * Add the correct display in IE 10. 345 | */ 346 | 347 | [hidden] { 348 | display: none; 349 | } -------------------------------------------------------------------------------- /public/font/iconfont.js: -------------------------------------------------------------------------------- 1 | !function(l){var t,o='',e=(t=document.getElementsByTagName("script"))[t.length-1].getAttribute("data-injectcss");if(e&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}!function(t){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(t,0);else{var e=function(){document.removeEventListener("DOMContentLoaded",e,!1),t()};document.addEventListener("DOMContentLoaded",e,!1)}else document.attachEvent&&(o=t,n=l.document,i=!1,c=function(){i||(i=!0,o())},(s=function(){try{n.documentElement.doScroll("left")}catch(t){return void setTimeout(s,50)}c()})(),n.onreadystatechange=function(){"complete"==n.readyState&&(n.onreadystatechange=null,c())});var o,n,i,c,s}(function(){var t,e;(t=document.createElement("div")).innerHTML=o,o=null,(e=t.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",function(t,e){e.firstChild?function(t,e){e.parentNode.insertBefore(t,e)}(t,e.firstChild):e.appendChild(t)}(e,document.body))})}(window); --------------------------------------------------------------------------------