first commit

master
4AMRayRay 5 years ago
commit 9063a7c689

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/koa.iml" filepath="$PROJECT_DIR$/.idea/koa.iml" />
</modules>
</component>
</project>

@ -0,0 +1,369 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="8dc86343-22bb-4ba4-9249-919cfe865668" name="Default Changelist" comment="" />
<ignored path="$PROJECT_DIR$/.tmp/" />
<ignored path="$PROJECT_DIR$/temp/" />
<ignored path="$PROJECT_DIR$/tmp/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/config.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="200">
<caret line="8" column="25" lean-forward="true" selection-start-line="8" selection-start-column="25" selection-end-line="8" selection-end-column="25" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="JavaScript File" />
</list>
</option>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>db</find>
<find>validator</find>
<find>to</find>
<find>toBuffer</find>
<find>toB</find>
<find>jpg</find>
<find>resizedImageData</find>
<find>resizedImageBuffer</find>
<find>arrBuffer</find>
</findStrings>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/confit.js" />
<option value="$PROJECT_DIR$/config.js" />
<option value="$PROJECT_DIR$/init/sql/user_info.sql" />
<option value="$PROJECT_DIR$/service/code.js" />
<option value="$PROJECT_DIR$/controller/code.js" />
<option value="$PROJECT_DIR$/init/util/db.js" />
<option value="$PROJECT_DIR$/utils/db-util.js" />
<option value="$PROJECT_DIR$/routers/index.js" />
<option value="$PROJECT_DIR$/node_modules/_gm@1.23.0@gm/lib/command.js" />
<option value="$PROJECT_DIR$/package.json" />
<option value="$PROJECT_DIR$/node_modules/gm/index.js" />
<option value="$PROJECT_DIR$/controllers/code.js" />
<option value="$PROJECT_DIR$/codes/user.js" />
<option value="$PROJECT_DIR$/routers/api.js" />
<option value="$PROJECT_DIR$/controllers/user.js" />
<option value="$PROJECT_DIR$/services/user.js" />
<option value="$PROJECT_DIR$/models/user-info.js" />
<option value="$PROJECT_DIR$/routers/code.js" />
<option value="$PROJECT_DIR$/index.js" />
<option value="$PROJECT_DIR$/services/code.js" />
</list>
</option>
</component>
<component name="PackageJsonUpdateNotifier">
<dismissed value="$PROJECT_DIR$/package.json" />
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="645" />
<option name="y" value="5" />
<option name="width" value="1215" />
<option name="height" value="1050" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="koa" type="b2602c69:ProjectViewProjectNode" />
<item name="koa" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$USER_HOME$/Desktop/Gracejs" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="nodejs_package_manager_path" value="npm" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\64616\WebstormProjects\验证码\koa\static" />
<recent name="C:\Users\64616\WebstormProjects\验证码\koa" />
<recent name="C:\Users\64616\WebstormProjects\验证码\koa\services" />
<recent name="C:\Users\64616\WebstormProjects\验证码\koa\controllers" />
<recent name="C:\Users\64616\WebstormProjects\验证码\koa\routers" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="8dc86343-22bb-4ba4-9249-919cfe865668" name="Default Changelist" comment="" />
<created>1576042694095</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1576042694095</updated>
<workItem from="1576042695631" duration="19791000" />
<workItem from="1576133470971" duration="3077000" />
<workItem from="1576137534400" duration="2632000" />
<workItem from="1576141293101" duration="1198000" />
<workItem from="1576142906574" duration="639000" />
<workItem from="1576143820439" duration="13874000" />
<workItem from="1576167095153" duration="9503000" />
<workItem from="1576217387661" duration="1619000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="52333000" />
</component>
<component name="ToolWindowManager">
<frame x="-7" y="-7" width="1550" height="838" extended-state="6" />
<editor active="true" />
<layout>
<window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.49375" visible="true" weight="0.168428" />
<window_info id="Structure" order="1" sideWeight="0.50625" side_tool="true" weight="0.1512118" />
<window_info id="Favorites" order="2" sideWeight="0.50161815" side_tool="true" weight="0.11116965" />
<window_info id="npm" order="3" side_tool="true" />
<window_info anchor="bottom" id="TypeScript" order="0" />
<window_info anchor="bottom" id="Message" order="1" />
<window_info anchor="bottom" id="Find" order="2" sideWeight="0.49947312" weight="0.04403409" />
<window_info anchor="bottom" id="Run" order="3" weight="0.329429" />
<window_info anchor="bottom" id="Debug" order="4" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="5" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="6" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="7" />
<window_info anchor="bottom" id="Docker" order="8" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" order="9" weight="0.329718" />
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.49947312" weight="0.47877014" />
<window_info anchor="bottom" id="Event Log" order="11" sideWeight="0.50052685" side_tool="true" weight="0.47995666" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
</layout>
<layout-to-restore>
<window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.49375" visible="true" weight="0.168428" />
<window_info id="Structure" order="1" sideWeight="0.50625" side_tool="true" weight="0.1512118" />
<window_info id="Favorites" order="2" sideWeight="0.50161815" side_tool="true" weight="0.11116965" />
<window_info id="npm" order="3" side_tool="true" />
<window_info anchor="bottom" id="TypeScript" order="0" />
<window_info anchor="bottom" id="Message" order="1" />
<window_info anchor="bottom" id="Find" order="2" sideWeight="0.49947312" weight="0.04403409" />
<window_info anchor="bottom" id="Run" order="3" weight="0.329429" />
<window_info anchor="bottom" id="Debug" order="4" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="5" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="6" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="7" />
<window_info anchor="bottom" id="Docker" order="8" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" order="9" weight="0.329718" />
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.49947312" weight="0.47877014" />
<window_info anchor="bottom" id="Event Log" order="11" sideWeight="0.50052685" side_tool="true" weight="0.47995666" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
</layout-to-restore>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/utils/type.js">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/_nodemailer@6.4.1@nodemailer/lib/nodemailer.js" />
<entry file="file://$PROJECT_DIR$/init/sql/user_info.sql">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="12" lean-forward="true" selection-start-line="12" selection-end-line="12" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/init/util/db.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="25">
<caret line="1" column="38" selection-start-line="1" selection-start-column="38" selection-end-line="1" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/init/util/get-sql-content-map.js">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/init/util/get-sql-map.js">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/init/util/walk-file.js">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/init/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="12" column="3" selection-start-line="12" selection-start-column="3" selection-end-line="12" selection-end-column="3" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/utils/upload.js">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/utils/datetime.js">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/static/images/4.jpg" />
<entry file="file://$PROJECT_DIR$/static/images/3.jpg" />
<entry file="file://$PROJECT_DIR$/static/images/2.jpg">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file://$PROJECT_DIR$/static/images/1.jpg">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.dom.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="201">
<caret line="5901" column="7" selection-start-line="5901" selection-start-column="7" selection-end-line="5901" selection-end-column="7" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/_gm@1.23.0@gm/package.json" />
<entry file="file://$PROJECT_DIR$/node_modules/_gm@1.23.0@gm/index.js" />
<entry file="file://$PROJECT_DIR$/node_modules/_gm@1.23.0@gm/lib/command.js" />
<entry file="file://$PROJECT_DIR$/node_modules/_gm@1.23.1@gm/index.js" />
<entry file="file://$PROJECT_DIR$/package-lock.json">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/gm/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-993" />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/gm/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="229">
<caret line="34" column="28" lean-forward="true" selection-start-line="34" selection-start-column="28" selection-end-line="34" selection-end-column="28" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-50">
<caret line="7" column="8" selection-start-line="7" selection-start-column="8" selection-end-line="7" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/codes/user.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="354">
<caret line="24" column="28" selection-start-line="24" selection-start-column="28" selection-end-line="24" selection-end-column="28" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/services/user.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="375">
<caret line="15" column="51" lean-forward="true" selection-start-line="15" selection-start-column="51" selection-end-line="15" selection-end-column="51" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/routers/api.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="200">
<caret line="8" column="47" selection-start-line="8" selection-start-column="47" selection-end-line="8" selection-end-column="47" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/controllers/user.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="19" column="47" selection-start-line="19" selection-start-column="47" selection-end-line="19" selection-end-column="47" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/utils/db-util.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="275">
<caret line="11" column="4" selection-start-line="11" selection-start-column="4" selection-end-line="11" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/models/user-info.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="325">
<caret line="13" column="35" selection-start-line="13" selection-start-column="35" selection-end-line="13" selection-end-column="35" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/controllers/code.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="100">
<caret line="4" column="40" selection-start-line="4" selection-start-column="40" selection-end-line="4" selection-end-column="40" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/services/code.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-775">
<caret line="8" column="7" lean-forward="true" selection-start-line="8" selection-start-column="7" selection-end-line="8" selection-end-column="7" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/routers/code.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="380">
<caret line="28" column="41" selection-start-line="28" selection-start-column="41" selection-end-line="28" selection-end-column="41" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/routers/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="6" column="24" lean-forward="true" selection-start-line="6" selection-start-column="24" selection-end-line="6" selection-end-column="24" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="355">
<caret line="51" column="11" lean-forward="true" selection-start-line="51" selection-start-column="11" selection-end-line="51" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/config.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="200">
<caret line="8" column="25" lean-forward="true" selection-start-line="8" selection-start-column="25" selection-end-line="8" selection-end-column="25" />
</state>
</provider>
</entry>
</component>
</project>

@ -0,0 +1,30 @@
/**
* 逻辑文案管理
*/
const userCode = {
ERROR_USER_NAME: '用户名格式为6-16位的小写字母包括-、_',
ERROR_EMAIL: '请输入正确的邮箱地址',
ERROR_PASSWORD: '密码长度应该为6-16',
ERROR_PASSWORD_CONFORM: '两次密码不一致',
ERROR_SYS: '系统错误',
FAIL_EMAIL_IS_EXIST: '邮箱已被注册',
FAIL_USER_NAME_IS_EXIST: '用户名已被注册',
FAIL_USER_NAME_OR_PASSWORD_ERROR: '用户名或登录密码错误',
FAIL_USER_NO_LOGIN: '用户未登录',
FAIL_USER_NO_EXIST: '用户不存在',
}
module.exports = userCode

@ -0,0 +1,13 @@
const config = {
port: 3002,
database: {
DATABASE: 'koa',
USERNAME: 'root',
PASSWORD: '',
PORT: '3306',
HOST: 'localhost'
}
}
module.exports = config

@ -0,0 +1,11 @@
const codeService = require('../services/code')
const getSlide = async (ctx) => {
const data = ctx.request.body
const result = await codeService.getSlide(data)
ctx.body = {data: result, success: true}
}
module.exports = {
getSlide
}

@ -0,0 +1,37 @@
const userInfoService = require('./../services/user')
const userCode = require('./../codes/user')
module.exports = {
/**
* 登录操作
* @param {obejct} ctx 上下文对象
*/
async signIn( ctx ) {
let formData = ctx.request.body
let result = {
success: false,
message: '',
data: null,
code: ''
}
let userResult = await userInfoService.signIn( formData )
if ( userResult ) {
if ( formData.userName === userResult.name ) {
result.success = true
} else {
result.message = userCode.FAIL_USER_NAME_OR_PASSWORD_ERROR
result.code = 'FAIL_USER_NAME_OR_PASSWORD_ERROR'
}
} else {
result.code = 'FAIL_USER_NAME_OR_PASSWORD_ERROR',
result.message = userCode.FAIL_USER_NAME_OR_PASSWORD_ERROR
}
ctx.body = result
},
}

@ -0,0 +1,56 @@
const Koa = require('koa')
const path = require('path')
const koaStatic = require('koa-static')
const bodyParser = require('koa-bodyparser')
const session = require('koa-session-minimal')
const MysqlStore = require('koa-mysql-session')
const cors = require('koa2-cors')
const config = require('./config')
const routers = require('./routers/index')
const app = new Koa()
//跨域处理
app.use(cors({
origin: function (ctx) {
if (ctx.url === '/cors') {
return "*"; // 允许来自所有域名请求
}
return 'http://localhost:8000';
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE'],//设置允许的HTTP请求类型
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}))
// session存储配置
const sessionMysqlConfig= {
user: config.database.USERNAME,
password: config.database.PASSWORD,
database: config.database.DATABASE,
host: config.database.HOST,
}
// 配置session中间件
app.use(session({
key: 'USER_SID',
store: new MysqlStore(sessionMysqlConfig)
}))
// 配置ctx.body解析中间件
app.use(bodyParser())
// 配置静态资源加载中间件
app.use(koaStatic(
path.join(__dirname , './static')
))
// 初始化路由中间件
app.use(routers.routes()).use(routers.allowedMethods())
// 监听启动端口
app.listen( config.port )
console.log(`the server is start at port ${config.port}`)

@ -0,0 +1,41 @@
const fs = require('fs');
const getSqlContentMap = require('./util/get-sql-content-map');
const { query } = require('./util/db');
// 打印脚本执行日志
const eventLog = function( err , sqlFile, index ) {
if( err ) {
console.log(`[ERROR] sql脚本文件: ${sqlFile}${index + 1}条脚本 执行失败 o(╯□╰)o `)
} else {
console.log(`[SUCCESS] sql脚本文件: ${sqlFile}${index + 1}条脚本 执行成功 O(∩_∩)O !`)
}
}
// 获取所有sql脚本内容
let sqlContentMap = getSqlContentMap()
// 执行建表sql脚本
const createAllTables = async () => {
for( let key in sqlContentMap ) {
let sqlShell = sqlContentMap[key]
let sqlShellList = sqlShell.split(';')
for ( let [ i, shell ] of sqlShellList.entries() ) {
if ( shell.trim() ) {
let result = await query( shell )
if ( result.serverStatus * 1 === 2 ) {
eventLog( null, key, i)
} else {
eventLog( true, key, i)
}
}
}
}
console.log('sql脚本执行结束')
console.log('请按 ctrl + c 键退出!')
}
createAllTables();

@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS `user_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`nick` varchar(255) DEFAULT NULL,
`detail_info` longtext DEFAULT NULL,
`create_time` varchar(20) DEFAULT NULL,
`modified_time` varchar(20) DEFAULT NULL,
`level` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `user_info` set name='admin', email='admin001@example.com', password='123456';

@ -0,0 +1,39 @@
const mysql = require('mysql')
const config = require('./../../config.js')
const dbConfig = config.database
const pool = mysql.createPool({
host : dbConfig.HOST,
user : dbConfig.USERNAME,
password : dbConfig.PASSWORD,
database : dbConfig.DATABASE
})
let query = function( sql, values ) {
return new Promise(( resolve, reject ) => {
pool.getConnection(function(err, connection) {
if (err) {
console.log( err )
resolve( err )
} else {
connection.query(sql, values, ( err, rows) => {
if ( err ) {
console.log( err )
reject( err )
} else {
resolve( rows )
}
connection.release()
})
}
})
})
}
module.exports = {
query
}

@ -0,0 +1,30 @@
const fs = require('fs')
const getSqlMap = require('./get-sql-map')
let sqlContentMap = {}
/**
* 读取sql文件内容
* @param {string} fileName 文件名称
* @param {string} path 文件所在的路径
* @return {string} 脚本文件内容
*/
function getSqlContent( fileName, path ) {
let content = fs.readFileSync( path, 'binary' )
sqlContentMap[ fileName ] = content
}
/**
* 封装所有sql文件脚本内容
* @return {object}
*/
function getSqlContentMap () {
let sqlMap = getSqlMap()
for( let key in sqlMap ) {
getSqlContent( key, sqlMap[key] )
}
return sqlContentMap
}
module.exports = getSqlContentMap

@ -0,0 +1,20 @@
const fs = require('fs')
const walkFile = require('./walk-file')
/**
* 获取sql目录下的文件目录数据
* @return {object}
*/
function getSqlMap () {
let basePath = __dirname
basePath = basePath.replace(/\\/g, '\/')
let pathArr = basePath.split('\/')
pathArr = pathArr.splice( 0, pathArr.length - 1 )
basePath = pathArr.join('/') + '/sql/'
let fileList = walkFile( basePath, 'sql' )
return fileList
}
module.exports = getSqlMap

@ -0,0 +1,28 @@
const fs = require('fs')
/**
* 遍历目录下的文件目录
* @param {string} pathResolve 需进行遍历的目录路径
* @param {string} mime 遍历文件的后缀名
* @return {object} 返回遍历后的目录结果
*/
const walkFile = function( pathResolve , mime ){
let files = fs.readdirSync( pathResolve )
let fileList = {}
for( let [ i, item] of files.entries() ) {
let itemArr = item.split('\.')
let itemMime = ( itemArr.length > 1 ) ? itemArr[ itemArr.length - 1 ] : 'undefined'
let keyName = item + ''
if( mime === itemMime ) {
fileList[ item ] = pathResolve + item
}
}
return fileList
}
module.exports = walkFile

@ -0,0 +1,24 @@
const dbUtils = require('./../utils/db-util')
const user = {
/**
* 根据用户名和密码查找用户
* @param {object} options 用户名密码对象
* @return {object|null} 查找结果
*/
async getOneByUserNameAndPassword( options ) {
let _sql = `
SELECT * from user_info
where password="${options.password}" and name="${options.name}"
limit 1`
let result = await dbUtils.query( _sql )
if ( Array.isArray(result) && result.length > 0 ) {
result = result[0]
} else {
result = null
}
return result
},
}
module.exports = user

733
koa/package-lock.json generated

@ -0,0 +1,733 @@
{
"name": "koa",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": {
"mime-types": "~2.1.24",
"negotiator": "0.6.2"
}
},
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
},
"array-parallel": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz",
"integrity": "sha1-j3hTCJJu1apHjEfmTRszS2wMlH0="
},
"array-series": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz",
"integrity": "sha1-3103v8XC7wdV4qpPkv6ufUtaly8="
},
"bignumber.js": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
"integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ=="
},
"bytes": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
},
"cache-content-type": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
"integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
"requires": {
"mime-types": "^2.1.18",
"ylru": "^1.2.0"
}
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"co-body": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/co-body/-/co-body-4.2.0.tgz",
"integrity": "sha1-dN8g+nMmISXcRUgq8E40LqjbNRU=",
"requires": {
"inflation": "~2.0.0",
"qs": "~4.0.0",
"raw-body": "~2.1.2",
"type-is": "~1.6.6"
}
},
"co-mysql": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/co-mysql/-/co-mysql-0.4.1.tgz",
"integrity": "sha1-cnPr/ydoHAPDivmAvH4o94p7GTk=",
"requires": {
"mysql": "*"
}
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookies": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
"integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
"requires": {
"depd": "~2.0.0",
"keygrip": "~1.1.0"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cross-spawn": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
"integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
"requires": {
"lru-cache": "^4.0.1",
"which": "^1.2.9"
}
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"error-inject": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/error-inject/-/error-inject-1.0.0.tgz",
"integrity": "sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
},
"gm": {
"version": "1.23.1",
"resolved": "https://registry.npmjs.org/gm/-/gm-1.23.1.tgz",
"integrity": "sha1-Lt7rlYCE0PjqeYjl2ZWxx9/BR3c=",
"requires": {
"array-parallel": "~0.1.3",
"array-series": "~0.1.5",
"cross-spawn": "^4.0.0",
"debug": "^3.1.0"
}
},
"http-assert": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz",
"integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==",
"requires": {
"deep-equal": "~1.0.1",
"http-errors": "~1.7.2"
}
},
"http-errors": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"iconv-lite": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
"integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI="
},
"inflation": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
"integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8="
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-generator-function": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
"integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"keygrip": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
"integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
"requires": {
"tsscmp": "1.0.6"
}
},
"koa": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/koa/-/koa-2.11.0.tgz",
"integrity": "sha512-EpR9dElBTDlaDgyhDMiLkXrPwp6ZqgAIBvhhmxQ9XN4TFgW+gEz6tkcsNI6BnUbUftrKDjVFj4lW2/J2aNBMMA==",
"requires": {
"accepts": "^1.3.5",
"cache-content-type": "^1.0.0",
"content-disposition": "~0.5.2",
"content-type": "^1.0.4",
"cookies": "~0.8.0",
"debug": "~3.1.0",
"delegates": "^1.0.0",
"depd": "^1.1.2",
"destroy": "^1.0.4",
"encodeurl": "^1.0.2",
"error-inject": "^1.0.0",
"escape-html": "^1.0.3",
"fresh": "~0.5.2",
"http-assert": "^1.3.0",
"http-errors": "^1.6.3",
"is-generator-function": "^1.0.7",
"koa-compose": "^4.1.0",
"koa-convert": "^1.2.0",
"on-finished": "^2.3.0",
"only": "~0.0.2",
"parseurl": "^1.3.2",
"statuses": "^1.5.0",
"type-is": "^1.6.16",
"vary": "^1.1.2"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"koa-bodyparser": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-3.2.0.tgz",
"integrity": "sha1-uRbeF+IDn+gmUEgZc9fClPELVxk=",
"requires": {
"co-body": "^4.2.0"
}
},
"koa-compose": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
},
"koa-convert": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz",
"integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=",
"requires": {
"co": "^4.6.0",
"koa-compose": "^3.0.0"
},
"dependencies": {
"koa-compose": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
"integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
"requires": {
"any-promise": "^1.1.0"
}
}
}
},
"koa-jsonp": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/koa-jsonp/-/koa-jsonp-2.0.2.tgz",
"integrity": "sha1-Q5QhRAP6z9YdffJGYpLJ+w9r8II="
},
"koa-mysql-session": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/koa-mysql-session/-/koa-mysql-session-0.0.2.tgz",
"integrity": "sha1-t/MvTdLDel95kiYXl8WTc3BO3Ik=",
"requires": {
"co": "^3.1.0",
"co-mysql": "^0.4.1"
},
"dependencies": {
"co": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz",
"integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g="
}
}
},
"koa-router": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/koa-router/-/koa-router-7.4.0.tgz",
"integrity": "sha512-IWhaDXeAnfDBEpWS6hkGdZ1ablgr6Q6pGdXCyK38RbzuH4LkUOpPqPw+3f8l8aTDrQmBQ7xJc0bs2yV4dzcO+g==",
"requires": {
"debug": "^3.1.0",
"http-errors": "^1.3.1",
"koa-compose": "^3.0.0",
"methods": "^1.0.1",
"path-to-regexp": "^1.1.1",
"urijs": "^1.19.0"
},
"dependencies": {
"koa-compose": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
"integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
"requires": {
"any-promise": "^1.1.0"
}
}
}
},
"koa-send": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.0.tgz",
"integrity": "sha512-90ZotV7t0p3uN9sRwW2D484rAaKIsD8tAVtypw/aBU+ryfV+fR2xrcAwhI8Wl6WRkojLUs/cB9SBSCuIb+IanQ==",
"requires": {
"debug": "^3.1.0",
"http-errors": "^1.6.3",
"mz": "^2.7.0",
"resolve-path": "^1.4.0"
}
},
"koa-session-minimal": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/koa-session-minimal/-/koa-session-minimal-3.0.4.tgz",
"integrity": "sha1-1qFb7u131dPiakIdu5imH2Oor80=",
"requires": {
"co": "^4.6.0",
"deep-equal": "^1.0.1",
"uid-safe": "^2.1.2"
}
},
"koa-static": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
"integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
"requires": {
"debug": "^3.1.0",
"koa-send": "^5.0.0"
}
},
"lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime-db": {
"version": "1.42.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
},
"mime-types": {
"version": "2.1.25",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
"integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
"requires": {
"mime-db": "1.42.0"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"mysql": {
"version": "2.17.1",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.17.1.tgz",
"integrity": "sha512-7vMqHQ673SAk5C8fOzTG2LpPcf3bNt0oL3sFpxPEEFp1mdlDcrLK0On7z8ZYKaaHrHwNcQ/MTUz7/oobZ2OyyA==",
"requires": {
"bignumber.js": "7.2.1",
"readable-stream": "2.3.6",
"safe-buffer": "5.1.2",
"sqlstring": "2.3.1"
}
},
"mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"requires": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
"thenify-all": "^1.0.0"
}
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"nodemailer": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.2.tgz",
"integrity": "sha512-g0n4nH1ONGvqYo1v72uSWvF/MRNnnq1LzmSzXb/6EPF3LFb51akOhgG3K2+aETAsJx90/Q5eFNTntu4vBCwyQQ=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"only": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path": {
"version": "0.12.7",
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
"integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=",
"requires": {
"process": "^0.11.1",
"util": "^0.10.3"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
}
}
},
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"qs": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz",
"integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc="
},
"random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
},
"raw-body": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
"integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
"requires": {
"bytes": "2.4.0",
"iconv-lite": "0.4.13",
"unpipe": "1.0.0"
}
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"resolve-path": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
"integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
"requires": {
"http-errors": "~1.6.2",
"path-is-absolute": "1.0.1"
},
"dependencies": {
"http-errors": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": ">= 1.4.0 < 2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
}
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"sqlstring": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"thenify": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
"integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=",
"requires": {
"any-promise": "^1.0.0"
}
},
"thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
"requires": {
"thenify": ">= 3.1.0 < 4"
}
},
"thunkify": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz",
"integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0="
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"tsscmp": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
"requires": {
"random-bytes": "~1.0.0"
}
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"urijs": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz",
"integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w=="
},
"util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"requires": {
"inherits": "2.0.3"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"validator": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-12.1.0.tgz",
"integrity": "sha512-gIC2RBuFRi574Rb9vewGCJ7TCLxHXNx6EKthEgs+Iz0pYa9a9Te1VLG/bGLsAyGWrqR5FfR7tbFUI7FEF2LiGA=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"requires": {
"isexe": "^2.0.0"
}
},
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
},
"ylru": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
"integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ=="
}
}
}

@ -0,0 +1,30 @@
{
"name": "koa",
"version": "1.0.0",
"description": "a koa2 project",
"main": "index.js",
"scripts": {
"init_sql": "node ./init/index.js",
"dev": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"fs": "^0.0.1-security",
"gm": "^1.23.1",
"gm-buffer": "^0.0.3",
"koa": "^2.11.0",
"koa-bodyparser": "^3.2.0",
"koa-jsonp": "^2.0.2",
"koa-mysql-session": "^0.0.2",
"koa-router": "^7.4.0",
"koa-session-minimal": "^3.0.4",
"koa-static": "^5.0.0",
"mysql": "^2.17.1",
"nodemailer": "^6.4.1",
"path": "^0.12.7",
"sharp": "^0.23.4",
"thunkify": "^2.1.2",
"validator": "^12.1.0"
}
}

@ -0,0 +1,11 @@
/**
* restful api 子路由
*/
const router = require('koa-router')()
const userController = require('./../controllers/user')
const routers = router
.post('/user/signIn.json', userController.signIn)
module.exports = routers

@ -0,0 +1,32 @@
const codeController = require('../controllers/code')
const koa_router = require('koa-router');
const router = koa_router();
/**
* @api {post} code/slide 获取滑块验证码
* @apiVersion 1.0.0
* @apiName getSlide
* @apiGroup code
* @apiHeader {String} authorization 用户授权token
* @apiSuccessExample Success-Response:
* HTTP/1.1 200 OK
* {
* "data": {
* "image": "", // 主图
* "fragment": "" // 滑块图
* },
* "success": true
* }
* @apiErrorExample Error-Response:
*
* {
* "success": false,
* "msg": "服务器错误..."
* }
*
*
*/
router.post('/slide', codeController.getSlide)
module.exports = router

@ -0,0 +1,13 @@
/**
* 整合所有子路由
*/
const router = require('koa-router')()
const code = require('./code')
const api = require('./api')
router.use('/code', code.routes(), code.allowedMethods())
router.use('/api', api.routes(), api.allowedMethods())
module.exports = router

@ -0,0 +1,67 @@
const path = require('path')
const sharp = require('sharp');
const sharp1 = require('sharp');
const getSlide = async () => {
const width = 334
const height = 140
const fragmentSize = 35
try {
// 随机选择某个图片
const filePath = getRandomPath()
//随机选择空缺部分的x y 坐标
const x = (Math.floor(Math.random() * 1000) % (width - 2 * fragmentSize)) + fragmentSize
const y = Math.floor(Math.random() * 1000) % (height - fragmentSize)
//获得大小图
const { image, fragment } = await createImage(filePath, width, height, fragmentSize, x, y)
console.log(image,fragment)
return { success: true, data: { image, fragment, x, y } }
} catch (err) {
return {success: false, msg: "服务器错误:" + err, data: null }
}
}
function getRandomPath() {
const fileLength = 2
const index = Math.floor(Math.random() * 1000) % fileLength
return path.resolve(__dirname, `../static/images/${index + 1}.jpg`)
}
// 生成大图和小图,返回base64
function createImage(filePath, w, h, s, x, y) {
return new Promise((resolve, reject) => {
const res = {image: "", fragment: ""}
const bg = `C:/Users/64616/WebstormProjects/验证码/koa/static/images/bg.jpg`
sharp(filePath)
.resize(w, h, "!")//调整成统一尺寸
.extract({left: x, top: y, width: s, height: s})//截取小图
.toBuffer()
.then(imageData => {
let data = imageData.toString('base64');//转换成base64的形式
res.fragment = "data:image/jpg;base64," + data
sharp1(filePath).resize(w, h, "!")
.composite([{input: bg, top: y, left: x, raw: {width: s, height: s, channels: 1}}])
//把与小图部分大小相同的灰色图片覆盖在大图上,形成大图空缺的样子
.toBuffer()
.then(imageData => {
let data = imageData.toString('base64');
res.image = "data:image/jpg;base64," + data
resolve(res)//返回结果
})
.catch(error => {
throw(error)
})
})
.catch(error => {
throw(error)
})
})
}
module.exports = {
getSlide,
check,
}

@ -0,0 +1,23 @@
/**
* 用户业务操作
*/
const validator = require('validator')
const userModel = require('./../models/user-info')
const userCode = require('./../codes/user')
const user = {
/**
* 登录业务操作
* @param {object} formData 登录表单信息
* @return {object} 登录业务操作结果
*/
async signIn( formData ) {
let resultData = await userModel.getOneByUserNameAndPassword({
'password': formData.password,
'name': formData.userName})
return resultData
},
}
module.exports = user

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@ -0,0 +1,66 @@
const monthEnum = [
'01','02','03','04','05','06',
'07','08','09','10','11','12',
]
const dayEnum = [
'01','02','03','04','05','06','07','08','09','10',
'11','12','13','14','15','16','17','18','19','20',
'21','22','23','04','25','26','27','28','29','30', '31',
]
const timeEnum = [
'00',
'01','02','03','04','05','06','07','08','09','10',
'11','12','13','14','15','16','17','18','19','20',
'21','22','23','04','25','26','27','28','29','30',
'31','32','33','34','35','36','37','38','39','40',
'41','42','43','44','45','46','47','48','49','50',
'51','52','53','54','55','56','57','58','59',
]
const datatime = {
parseStampToFormat( timestamp, type ) {
let _date
if ( timestamp ) {
_date = new Date(timestamp)
} else {
_date = new Date()
}
let parsedDate
let parseTime
let parseDatetime
let yearNum = _date.getFullYear()
let monthNum = monthEnum[_date.getMonth()]
let dayNum = dayEnum[_date.getDate()-1]
let hourNum = timeEnum[_date.getHours()]
let minNum = timeEnum[_date.getMinutes()]
let secNum = timeEnum[_date.getSeconds()]
type = type || 'YYYY/MM/DD/hh/mm/ss'
parseDatetime = type
.replace('YYYY', yearNum)
.replace('MM', monthNum)
.replace('DD', dayNum)
.replace('hh', hourNum)
.replace('mm', minNum)
.replace('ss', secNum)
return parseDatetime
},
getNowDatetime() {
let timestamp = new Date().getTime()
let nowDatetime = this.parseStampToFormat( timestamp )
return nowDatetime
},
}
module.exports = datatime

@ -0,0 +1,89 @@
const allConfig = require("./../config.js")
const config = allConfig.database
const mysql = require("mysql")
const pool = mysql.createPool({
host : config.HOST,
user : config.USERNAME,
password : config.PASSWORD,
database : config.DATABASE
})
let query = function( sql, values ) {
return new Promise(( resolve, reject ) => {
pool.getConnection(function(err, connection) {
if (err) {
resolve( err )
} else {
connection.query(sql, values, ( err, rows) => {
if ( err ) {
reject( err )
} else {
resolve( rows )
}
connection.release()
})
}
})
})
}
let createTable = function( sql ) {
return query( sql, [] )
}
let findDataById = function( table, id ) {
let _sql = "SELECT * FROM ?? WHERE id = ? "
return query( _sql, [ table, id, start, end ] )
}
let findDataByPage = function( table, keys, start, end ) {
let _sql = "SELECT ?? FROM ?? LIMIT ? , ?"
return query( _sql, [keys, table, start, end ] )
}
let insertData = function( table, values ) {
let _sql = "INSERT INTO ?? SET ?"
return query( _sql, [ table, values ] )
}
let updateData = function( table, values, id ) {
let _sql = "UPDATE ?? SET ? WHERE id = ?"
return query( _sql, [ table, values, id ] )
}
let deleteDataById = function( table, id ) {
let _sql = "DELETE FROM ?? WHERE id = ?"
return query( _sql, [ table, id ] )
}
let select = function( table, keys ) {
let _sql = "SELECT ?? FROM ?? "
return query( _sql, [ keys, table ] )
}
let count = function( table ) {
let _sql = "SELECT COUNT(*) AS total_count FROM ?? "
return query( _sql, [ table ] )
}
module.exports = {
query,
createTable,
findDataById,
findDataByPage,
deleteDataById,
insertData,
updateData,
select,
count,
}

@ -0,0 +1,37 @@
const Types = {
isPrototype( data ) {
return Object.prototype.toString.call(data).toLowerCase()
},
isArray( data ) {
return this.isPrototype( data ) === '[object array]'
},
isJSON( data ) {
return this.isPrototype( data ) === '[object object]'
},
isFunction( data ) {
return this.isPrototype( data ) === '[object function]'
},
isString( data ) {
return this.isPrototype( data ) === '[object string]'
},
isNumber( data ) {
return this.isPrototype( data ) === '[object number]'
},
isUndefined( data ) {
return this.isPrototype( data ) === '[object undefined]'
},
isNull( data ) {
return this.isPrototype( data ) === '[object null]'
}
}
module.exports = Types

@ -0,0 +1,102 @@
const inspect = require('util').inspect
const path = require('path')
const os = require('os')
const fs = require('fs')
const Busboy = require('busboy')
const UtilType = require('./type')
const UtilDatetime = require('./datetime')
function mkdirsSync(dirname) {
// console.log(dirname)
if (fs.existsSync(dirname)) {
return true
} else {
if (mkdirsSync(path.dirname(dirname))) {
fs.mkdirSync(dirname)
return true
}
}
}
function getSuffixName( fileName ) {
let nameList = fileName.split('.')
return nameList[nameList.length - 1]
}
function uploadPicture( ctx, options) {
let req = ctx.req
let res = ctx.res
let busboy = new Busboy({headers: req.headers})
let pictureType = 'common'
if ( UtilType.isJSON( options ) && UtilType.isString( options.pictureType ) ) {
pictureType = options.pictureType
}
let picturePath = path.join(
__dirname,
'/../../static/output/upload/',
pictureType,
UtilDatetime.parseStampToFormat(null, 'YYYY/MM/DD'))
console.log( path.sep, picturePath )
let mkdirResult = mkdirsSync( picturePath )
return new Promise((resolve, reject) => {
let result = {
success: false,
code: '',
message: '',
data: null
}
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
console.log('File-file [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype)
let pictureName = Math.random().toString(16).substr(2) + '.' + getSuffixName(filename)
let _uploadFilePath = path.join( picturePath, pictureName )
console.log(_uploadFilePath)
let saveTo = path.join(_uploadFilePath)
file.pipe(fs.createWriteStream(saveTo))
// file.on('data', function(data) {
// console.log('File-data [' + fieldname + '] got ' + data.length + ' bytes')
// })
file.on('end', function() {
console.log('File-end [' + fieldname + '] Finished')
result.success = true
resolve(result)
})
})
// busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
// console.log('Field-field [' + fieldname + ']: value: ' + inspect(val))
// })
// busboy.on('finish', function() {
// console.log('Done parsing form!')
// })
busboy.on('error', function(err) {
console.log('File-error')
reject(result)
})
req.pipe(busboy)
})
}
module.exports = {
uploadPicture,
}

@ -0,0 +1,11 @@
# editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

@ -0,0 +1,3 @@
{
"extends": "eslint-config-umi"
}

5
react/.gitignore vendored

@ -0,0 +1,5 @@
.umi
node_modules
.idea
dist
course-demo-bigfish

@ -0,0 +1,3 @@
# Ant Design 实战课程配套代码
<img src="https://gw.alipayobjects.com/zos/rmsportal/DReQIejdcJPeaXWEDKDe.png" />

@ -0,0 +1,38 @@
export default {
singular: true,
plugins: [
['umi-plugin-react', {
antd: true,
dva: true,
locale: {
enable: true,
},
}],
],
routes: [
{
path: '/',
component: '../layout',
routes: [
{
path: '/',
component: './index'
},
{
path: 'user',
component: './user'
},
{
path: 'work',
component: './work'
},
]
}
],
proxy: {
'/dev': {
target: 'https://08ad1pao69.execute-api.us-east-1.amazonaws.com',
changeOrigin: true,
},
},
};

@ -0,0 +1,3 @@
module.exports = {
testURL: 'http://localhost:7001',
};

@ -0,0 +1,61 @@
let data = [
{
id: 1,
name: 'umi',
desc: '极快的类 Next.js 的 React 应用框架。',
url: 'https://umijs.org'
},
{
id: 2,
name: 'antd',
desc: '一个服务于企业级产品的设计体系。',
url: 'https://ant.design/index-cn'
},
{
id: 3,
name: 'antd-pro',
desc: '一个服务于企业级产品的设计体系。',
url: 'https://ant.design/index-cn'
}
];
export default {
'get /api/cards': function (req, res, next) {
setTimeout(() => {
res.json({
result: data,
})
}, 250)
},
'delete /api/cards/:id': function (req, res, next) {
data = data.filter(v => v.id !== parseInt(req.params.id));
console.log(req.params.id);
console.log(data);
setTimeout(() => {
res.json({
success: true,
})
}, 250)
},
'post /api/cards/add': function (req, res, next) {
data = [...data, {
...req.body,
id: data[data.length - 1].id + 1,
}];
res.json({
success: true,
});
},
'get /api/cards/:id/statistic': function (req, res, next) {
res.json({
result: [
{ genre: 'Sports', sold: 275 },
{ genre: 'Strategy', sold: 1150 },
{ genre: 'Action', sold: 120 },
{ genre: 'Shooter', sold: 350 },
{ genre: 'Other', sold: 150 },
]
});
},
}

@ -0,0 +1,28 @@
/*
const random_jokes = [
{
setup: 'What is the object oriented way to get wealthy ?',
punchline: 'Inheritance',
},
{
setup: 'To understand what recursion is...',
punchline: "You must first understand what recursion is",
},
{
setup: 'What do you call a factory that sells passable products?',
punchline: 'A satisfactory',
},
];
let random_joke_call_count = 0;
export default {
'get /dev/random_joke': function (req, res) {
const responseObj = random_jokes[random_joke_call_count % random_jokes.length];
random_joke_call_count += 1;
setTimeout(() => {
res.json(responseObj);
}, 3000);
},
};
*/

@ -0,0 +1,30 @@
{
"dependencies": {
"@antv/g2": "^3.1.2",
"@types/react": "^16.4.6",
"@types/react-dom": "^16.0.6",
"ant-design-pro": "^1.3.0",
"antd": "^3.6.3",
"classnames": "^2.2.6",
"eslint": "^4.19.1",
"install": "^0.12.1",
"lodash": "^4.17.10",
"lodash-decorators": "^5.0.0",
"moment": "^2.22.1",
"path-to-regexp": "^1.7.0",
"rc-drawer-menu": "^0.5.7",
"react-intl": "^2.4.0",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.13.0",
"tslint-react": "^3.6.0",
"umi": "^2.0.0",
"umi-plugin-react": "^1.0.0",
"umi-request": "^1.2.14"
},
"scripts": {
"dev": "umi dev",
"lint": "eslint --ext .js src",
"test": "umi test",
"_sync": "sh tool/tobigfish.sh"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576169371749" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="785" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M749.30410196 301.06220698l105.46816421 0c7.27775703 0 13.18315449-5.90539668 13.18461907-13.18315448l0-105.46816419-26.36777351 0L841.58911173 251.6191535C764.07931134 166.430287 658.01064809 116.49218751 551.55092804 116.49218751 333.46719408 116.49218751 156.04311553 293.91626683 156.04311553 512s177.42407933 395.50781249 395.50781248 395.50781249c123.82000558 0 238.17409324-56.37369291 313.71689267-154.66955314l-20.90908905-16.05822745c-70.50592942 91.73137914-177.24100015 144.36000704-292.80780284 144.36000704-203.55458221 0-369.14003895-165.58545675-369.14003896-369.14003894S347.99488127 142.85996105 551.55092804 142.85996105c101.26467009 0 202.39166407 48.83962521 275.3157012 131.83447314l-77.56106266 0L749.30556658 301.06220698z" fill="#707070" p-id="786"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#505050" d="M536.228571 489.485714L244.457143 116.685714c-3.428571-4.457143-8.8-6.971429-14.4-6.971428H141.714286c-7.657143 0-11.885714 8.8-7.2 14.742857L437.828571 512 134.514286 899.542857A9.12 9.12 0 0 0 141.714286 914.285714h88.342857c5.6 0 10.971429-2.628571 14.4-6.971428l291.771428-372.685715c10.4-13.371429 10.4-31.885714 0-45.142857z m347.428572 0L591.885714 116.685714c-3.428571-4.457143-8.8-6.971429-14.4-6.971428H489.142857c-7.657143 0-11.885714 8.8-7.2 14.742857L785.257143 512 481.942857 899.542857A9.12 9.12 0 0 0 489.142857 914.285714h88.342857c5.6 0 10.971429-2.628571 14.4-6.971428l291.771429-372.685715c10.4-13.371429 10.4-31.885714 0-45.142857z" /></svg>

After

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#FF4500" d="M512 39.384615C252.061538 39.384615 39.384615 252.061538 39.384615 512s212.676923 472.615385 472.615385 472.615385 472.615385-212.676923 472.615385-472.615385S771.938462 39.384615 512 39.384615zM157.538462 512c0-194.953846 159.507692-354.461538 354.461538-354.461538 76.8 0 147.692308 23.630769 204.8 64.984615L222.523077 716.8C181.169231 659.692308 157.538462 588.8 157.538462 512z m354.461538 354.461538c-76.8 0-147.692308-23.630769-204.8-64.984615l494.276923-494.276923C842.830769 364.307692 866.461538 435.2 866.461538 512c0 194.953846-159.507692 354.461538-354.461538 354.461538z" /></svg>

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#505050" d="M965.828571 166.057143l-64.457142 50.4C813.485714 104.114286 676.8 32 523.314286 32 258.285714 32 43.771429 246.285714 43.428571 511.428571 43.085714 776.8 258.057143 992 523.314286 992c207.2 0 383.771429-131.428571 450.971428-315.542857 1.714286-4.8-0.8-10.171429-5.6-11.771429l-64.8-22.285714a9.142857 9.142857 0 0 0-11.542857 5.485714c-2.057143 5.714286-4.342857 11.428571-6.742857 17.028572-19.771429 46.857143-48.114286 88.914286-84.228571 125.028571A394.022857 394.022857 0 0 1 676.457143 874.285714c-48.342857 20.457143-99.885714 30.857143-152.914286 30.857143-53.142857 0-104.571429-10.4-152.914286-30.857143A390.285714 390.285714 0 0 1 245.714286 789.942857a391.04 391.04 0 0 1-84.228572-125.028571c-20.457143-48.457143-30.857143-99.885714-30.857143-153.028572s10.4-104.571429 30.857143-153.028571c19.771429-46.857143 48.114286-88.914286 84.228572-125.028572 36.114286-36.114286 78.171429-64.457143 124.914285-84.342857 48.342857-20.457143 99.885714-30.857143 152.914286-30.857143 53.142857 0 104.571429 10.4 152.914286 30.857143a390.285714 390.285714 0 0 1 124.914286 84.342857c11.314286 11.314286 21.942857 23.314286 31.771428 35.885715l-68.8 53.714285a9.142857 9.142857 0 0 0 3.428572 16.114286l200.685714 49.142857c5.714286 1.371429 11.314286-2.971429 11.314286-8.8l0.914285-206.742857c-0.114286-7.542857-8.914286-11.771429-14.857143-7.085714z" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#00B060" d="M512 39.384615C250.092308 39.384615 39.384615 250.092308 39.384615 512s210.707692 472.615385 472.615385 472.615385 472.615385-210.707692 472.615385-472.615385S773.907692 39.384615 512 39.384615z m263.876923 354.461539L474.584615 699.076923c-11.815385 11.815385-31.507692 11.815385-43.323077 0L265.846154 531.692308c-11.815385-11.815385-11.815385-31.507692 0-43.323077l43.323077-43.323077c11.815385-11.815385 31.507692-11.815385 43.323077 0l86.646154 88.615384c7.876923 7.876923 21.661538 7.876923 29.538461 0L689.230769 305.230769c11.815385-11.815385 31.507692-11.815385 43.323077 0l43.323077 43.323077c13.784615 11.815385 13.784615 31.507692 0 45.292308z" /></svg>

After

Width:  |  Height:  |  Size: 947 B

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<title>Group 28 Copy 5</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="62.1023273%" y1="0%" x2="108.19718%" y2="37.8635764%" id="linearGradient-1">
<stop stop-color="#4285EB" offset="0%"></stop>
<stop stop-color="#2EC7FF" offset="100%"></stop>
</linearGradient>
<linearGradient x1="69.644116%" y1="0%" x2="54.0428975%" y2="108.456714%" id="linearGradient-2">
<stop stop-color="#29CDFF" offset="0%"></stop>
<stop stop-color="#148EFF" offset="37.8600687%"></stop>
<stop stop-color="#0A60FF" offset="100%"></stop>
</linearGradient>
<linearGradient x1="69.6908165%" y1="-12.9743587%" x2="16.7228981%" y2="117.391248%" id="linearGradient-3">
<stop stop-color="#FA816E" offset="0%"></stop>
<stop stop-color="#F74A5C" offset="41.472606%"></stop>
<stop stop-color="#F51D2C" offset="100%"></stop>
</linearGradient>
<linearGradient x1="68.1279872%" y1="-35.6905737%" x2="30.4400914%" y2="114.942679%" id="linearGradient-4">
<stop stop-color="#FA8E7D" offset="0%"></stop>
<stop stop-color="#F74A5C" offset="51.2635191%"></stop>
<stop stop-color="#F51D2C" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="logo" transform="translate(-20.000000, -20.000000)">
<g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)">
<g id="Group-27-Copy-3">
<g id="Group-25" fill-rule="nonzero">
<g id="2">
<path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-1)"></path>
<path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-2)"></path>
</g>
<path d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z" id="Shape" fill="url(#linearGradient-3)"></path>
</g>
<ellipse id="Combined-Shape" fill="url(#linearGradient-4)" cx="100.519339" cy="100.436681" rx="23.6001926" ry="23.580786"></ellipse>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

@ -0,0 +1,50 @@
/* eslint no-useless-escape:0 */
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/g;
export function isUrl(path) {
return reg.test(path);
}
const menuData = [
{
name: 'Pages',
icon: 'dashboard',
path: 'dashboard',
children: [
{
name: '分析页',
path: 'analysis',
},
{
name: '监控页',
path: 'monitor',
},
{
name: '工作台',
path: 'workplace',
// hideInBreadcrumb: true,
// hideInMenu: true,
},
],
},
];
function formatter(data, parentPath = '/', parentAuthority) {
return data.map(item => {
let { path } = item;
if (!isUrl(path)) {
path = parentPath + item.path;
}
const result = {
...item,
path,
authority: item.authority || parentAuthority,
};
if (item.children) {
result.children = formatter(item.children, `${parentPath}${item.path}/`, item.authority);
}
return result;
});
}
export const getMenuData = () => formatter(menuData);

@ -0,0 +1,53 @@
.image-code {
padding: 10px;
margin: 20px;
background-color: #fff;
box-shadow: 0 0 5px #333;
user-select: none;
}
.imagecodeimage {
position: relative;
background: no-repeat;
}
.imagecodefragment {
position: absolute;
display: block;
background-color: #fff;
}
.image-code__reload {
display: inline-flex;
align-items: center;
margin: 20px 0;
font-size: 14px;
color: #666;
cursor: pointer;
}
.imagecodereloadico {
width: 20px;
height: 20px;
margin-right: 10px;
background: url("../assets/icons/reload.jpg") center/cover no-repeat;
}
.image-code__slide-bar {
position: relative;
background-color: #ddd;
text-align: center;
font-size: 14px;
color: #666;
}
.image-code__slide-button {
position: absolute;
top: 0;
left: 0;
border: 1px solid #505050;
box-sizing: border-box;
background: #fff url("../assets/icons/double-right.jpg") center/60% no-repeat;
cursor: pointer;
}

@ -0,0 +1,24 @@
body, html {
height: 100%!important;
margin: 0!important;
}
::-webkit-scrollbar{
width: 2px;/* 纵向滚动条*/
height: 2px;/* 横向滚动条 */
background-color: #fff;
}
/*定义滚动条轨道 内阴影*/
::-webkit-scrollbar-track{
-webkit-box-shadow: inset 0 0 2px rgba(0,0,0,0);
background-color: #fff;
}
/*定义滑块 内阴影*/
::-webkit-scrollbar-thumb{
-webkit-box-shadow: inset 0 0 2px rgba(0,0,0,0);
background-color: #99b4f7;
}

@ -0,0 +1,24 @@
import { Component } from 'react';
import { Layout } from 'antd';
import './index.css';
const { Content } = Layout;
class BasicLayout extends Component {
constructor(props) {
super(props);
}
render() {
const { children } = this.props;
return (
<Layout style={{height: '100%',backgroundColor: 'white' }}>
<Content style={{height: '100%' }}>
{ children }
</Content>
</Layout>
);
}
}
export default BasicLayout;

@ -0,0 +1,94 @@
import * as service from '../service/service';
import router from 'umi/router';
export default {
namespace: 'user',
state: {
image: "",
fragment: "",
x: 0,
y: 0,
},
effects: {
*toWork ( action, sagaEffects ) {
if (!localStorage.user) {
router.push({
pathname: '/user'
})
} else {
router.push({
pathname: '/work'
})
}
},
//获得大小图
*getCode (action, sagaEffects) {
const {call, put, select} = sagaEffects;
let result = yield call(service.getCode);
console.log(result)
if (result.success) {
if (result.data.data.image && result.data.data.fragment) {
yield put({type: 'returnImage', payload: result.data.data.image});
yield put({type: 'returnFragment', payload: result.data.data.fragment});
yield put({type: 'returnX', payload: result.data.data.x});
yield put({type: 'returnY', payload: result.data.data.y});
}
}
},
//请求登录
*signIn(action, sagaEffects) {
const {call, put, select} = sagaEffects
let values = action.payload
let result = yield call(service.signIn, values)
console.log(result)
let {success, code, message} = result
if (success) {
router.push({
pathname: '/work'
})
}
}
},
reducers: {
returnImage (state,{payload: image}) {
return {
...state,
image: image
}
},
returnFragment (state,{payload: fragment}) {
return {
...state,
fragment: fragment
}
},
returnX(state,{payload: x}) {
return {
...state,
x: x
}
},
returnY(state,{payload: y}) {
return {
...state,
y: y
}
},
},
subscriptions: {
setup({dispatch,history}) {
history.listen((location) => {
if (location.pathname === '/user') {
dispatch({
type: 'getCode'
})
}
})
}
}
};

@ -0,0 +1,205 @@
/**
* @param {String} imageUrl 底图
* @param {String} fragmentUrl 小图片
* @param {Number} width
* @param {Number} height
* @param {Number} fragmentSize 小图片尺寸
* @param {Number} y 小图片y
* @param {Function} onReload 加载和重新加载的回调
* @param {Function} onMoveEnd 滑动完成之后的回调
*/
import React from "react"
import * as myStyles from './styles.less'
export default class ImageCode extends React.Component {
constructor(props) {
super(props)
this.state = {
oldX: 0, //旧x坐标值
currX: 0, //当前x坐标值
startX: 0,
isMovable: false, //滑块是否在滑动
once: false, //滑块是否滑动过一次了
success: 0 //0:未验证 1成功 2失败
}
}
componentDidUpdate(prevProps) {
if (this.props.imageUrl !== prevProps.imageUrl) {
this.setState({ oldX: 0, currX: 0, isMovable: false })
}
}
//重新加载图片要重新初始化,并且请求新的大小图
onReload = () => {
this.setState({ oldX: 0, currX: 0, startX: 0, isMovable: false , once: false, success: 0})
console.log(1)
this.props.onReload()
}
//对滑块按下鼠标时意味着开始滑动
onMoveStart = e => {
if (!this.state.once) this.setState({ isMovable: true, startX: e.clientX })
}
//滑块滑动时
onMoving = e => {
if (!this.state.isMovable) {
return
}
const distance = e.clientX - this.state.startX
let currX = this.state.oldX + distance
//min 和 max 用来限制滑块能滑动的范围
const min = 0
const max = parseInt(this.props.width) - parseInt(this.props.fragmentSize)
currX = currX < min ? 0 : currX > max ? max : currX
this.setState({ currX })
}
//鼠标松开时意味着滑动结束
onMoveEnd = () => {
if (!this.state.isMovable) {
return
}
this.setState(prev => ({ isMovable: false, oldX: prev.currX, once: true }))
//如果滑块的x坐标与小图对应在大图的x坐标 在误差范围以内则判断验证成功
if (Math.abs(this.state.currX - this.props.x) < 5) {
this.props.onSuccess()
this.setState({
success: 1
})
} else {
this.setState({
success: 2
})
}
}
render() {
const { imageUrl, fragmentUrl, width, height, fragmentSize, y } = this.props
const { currX } = this.state
return (
<div className="image-code" style={{ width,boxShadow: "0 0 5px #333"}}>
<div className="image-code__image" style={{ backgroundImage: `url("${imageUrl}") `, height, position: "relative",}}>
<div
className="image-code__fragment"
style={{
backgroundImage: `url("${fragmentUrl}")`,
width: fragmentSize + "px",
height: fragmentSize + "px",
left: currX,
top: y + 'px',
position: "absolute",
display: "block",
backgroundColor: "#fff"
}}
>
</div>
</div>
<div style={{
display: "inline-flex",
alignItems: "center",
fontSize: "13px",
color: "rgba(0, 0, 0, 0.5)",
margin: "3px 0px 0px 3px",
cursor: "pointer",
}} onClick={() => this.onReload()}>
<i
className={myStyles.reload}
style={{
width: "18px",
height: "18px",
marginRight: "3px",
}}/>
<span>重新加载</span>
</div>
{
this.state.success === 1?
<div style={{
float: "right",
display: "inline-flex",
alignItems: "center",
fontSize: "13px",
color: "rgba(0, 0, 0, 0.5)",
margin: "3px 0px 0px 3px",
}}>
<i
className={myStyles.success}
style={{
width: "18px",
height: "18px",
marginRight: "3px",
}}/>
<span>验证成功您的速度超过了99.9%的用户</span>
</div>
:
this.state.success === 2 ?
<div style={{
float: "right",
display: "inline-flex",
alignItems: "center",
fontSize: "13px",
color: "rgba(0, 0, 0, 0.5)",
margin: "3px 0px 0px 3px",
}}>
<i
className={myStyles.error}
style={{
width: "18px",
height: "18px",
marginRight: "3px",
}}/>
<span>验证失败</span>
</div>
: null
}
<div
className={myStyles.imagecodeslidebar}
style={{ height: 0.8 * fragmentSize + "px", lineHeight: 0.8 * fragmentSize + "px" }}
onMouseMove={this.onMoving}
onMouseUp={this.onMoveEnd}
onMouseLeave={this.onMoveEnd}
>
{
this.state.currX === 0?
<span>按住滑块拖动完成拼图</span>
:
<span></span>
}
<div
style={{
position: "absolute",
height: 0.8 * fragmentSize + "px",
width: currX,
backgroundColor: "#22C32E"
}}
>
</div>
<div
className={myStyles.imagecodeslidebutton}
style={{
width: 1 * fragmentSize + "px",
height: 0.8 * fragmentSize + "px",
left: currX,
}}
onMouseDown={this.onMoveStart}
></div>
</div>
</div>
)
}
}

@ -0,0 +1,150 @@
import { Form, Icon, Input, Button, Checkbox, Row, Col, notification } from 'antd';
import React from 'react';
import { connect } from 'dva'
import myStyles from './styles.less';
import ImageCode from "./ImageCode"
import * as service from "../service/service"
const namespace = 'user'
const mapStateToProps = (state) => {
const image = state[namespace].image
const fragment = state[namespace].fragment
const x = state[namespace].x
const y = state[namespace].y
return {
image, fragment, x, y
}
}
const mapDispatchToProps = (dispatch) => {
return {
getCode: () => {
dispatch({
type: `${namespace}/getCode`,
})
},
signIn: (values) => {
dispatch({
type: `${namespace}/signIn`,
payload: values
})
},
}
};
@connect(mapStateToProps, mapDispatchToProps)
class NormalLoginForm extends React.Component {
constructor(props) {
super(props)
this.state = {
captcha: false
}
}
openNotification = ()=> {
notification['error']({
message: 'Please finish your verification',
duration: 1,
});
};
captchaSuccess = () => {
console.log('success')
this.setState({
captcha: true
})
}
onReload = () => {
this.props.getCode()
}
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
if (this.state.captcha) {
this.props.signIn(values)
} else {
this.openNotification()
}
}
});
};
render() {
const { getFieldDecorator } = this.props.form;
return (
<Row>
<Form onSubmit={this.handleSubmit} className="login-form">
<Col span={6} offset={1}>
<span style={{color: 'rgba(0,0,0,.50)'}}>Username</span>
</Col>
<Col span={24}>
<Form.Item>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input
className={myStyles["override-ant-input"]}
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }}
/>}
/>,
)}
</Form.Item>
</Col>
<Col span={6} offset={1}>
<span style={{color: 'rgba(0,0,0,.50)'}}>Password</span>
</Col>
<Col span={24}>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input
className={myStyles["override-ant-input"]}
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
type="password"
/>,
)}
</Form.Item>
</Col>
<Col span={6} offset={1} style={{marginBottom:"4px"}}>
<span style={{color: 'rgba(0,0,0,.50)'}}>Verification</span>
</Col>
<Col span={24}>
{
(this.props.image && this.props.fragment)?
<ImageCode
imageUrl={this.props.image}
fragmentUrl={this.props.fragment}
x={this.props.x}
y={this.props.y}
width="334px"
height="140px"
fragmentSize="35"
onReload={() => this.onReload()}
onSuccess={() => this.captchaSuccess()}
/>
:
null
}
</Col>
<Col span={24} style={{display: "flex", justifyContent:"center", marginTop:"25px"}}>
<Form.Item className={myStyles["override-ant-btn"]}>
<Button htmlType="submit">
Sign in
</Button>
</Form.Item>
</Col>
</Form>
</Row>
);
}
}
const WrappedNormalLoginForm = Form.create({ name: 'normal_login' })(NormalLoginForm);
export default WrappedNormalLoginForm

@ -0,0 +1,47 @@
import { Row, Col } from 'antd';
import React from 'react';
import myStyles from './styles.less';
import { connect } from 'dva'
const namespace = 'user'
const mapDispatchToProps = (dispatch) => {
return {
toWork: () => {
dispatch({
type: `${namespace}/toWork`,
})
},
}
};
@connect(null, mapDispatchToProps)
export default class index extends React.Component {
constructor(props) {
super(props)
}
toWork = () => {
this.props.toWork()
}
render() {
return (
<Row>
<Col span={24} className={myStyles.index}>
<Row style={{paddingTop: "20px"}}>
<Col className={myStyles.flex} span={7}>
<span className={myStyles.h1}>React</span>
<span className={myStyles.h2}>+</span>
<span className={myStyles.h3}>Koa2</span>
</Col>
</Row>
<div style={{marginTop: "20%",paddingBottom:"9%"}}>
<a className={myStyles.h4} onClick={this.toWork}>>>查看详情</a>
</div>
</Col>
</Row>
)
}
}

@ -0,0 +1,113 @@
.index {
background: url("../assets/2555689.jpg") no-repeat ;
background-size: 100% 100%;
}
.user {
height: 100%;
}
.flex {
display: flex;
flex-direction: column;
align-items: center;
}
.border{
border-radius: 10px
}
.h1 {
color: #F08080;
font-size: 60px;
text-shadow: 1.5px 1.5px 1.5px black;
}
.h2 {
color: #B399FF;
font-size: 60px;
text-shadow: 1.5px 1.5px 1.5px black;
}
.h3 {
color: #48D1CC;
font-size: 60px;
text-shadow: 1.5px 1.5px 1.5px black;
}
.h4 {
float: right;
padding-right: 100px;
color: #79827f;
font-size: 30px;
}
.welcome {
display: flex;
justify-content: center;
margin-top: 25%;
margin-bottom: 8%;
color: #8A2BE2;
font-size: 35px;
font-family: "Microsoft YaHei UI Light";
font-weight: lighter;
letter-spacing:2px;
}
.override-ant-input {
:global(.ant-input) {
border-color: #b078e3;
border-radius: 20px;
box-shadow: none;
}
:global(.ant-input:focus) {
border: 1px solid #8A2BE2!important;
box-shadow: none;
}
:global(.ant-input:hover) {
border: 1px solid #8A2BE2!important;
box-shadow: 0 0 1px #8A2BE2;
}
}
.override-ant-btn {
:global(.ant-btn) {
background-color: #ac5df5;
border-radius: 20px;
color: white;
}
:global(.ant-btn:hover) {
background-color: #8A2BE2;
border-radius: 20px;
color: white;
}
}
.reload {
background: url("../assets/icons/reload.jpg") center/contain no-repeat;
}
.success {
background: url("../assets/icons/success.jpg") center/contain no-repeat;
}
.error {
background: url("../assets/icons/error.jpg") center/contain no-repeat;
}
.imagecodeslidebar {
position: relative;
background-color: rgba(0, 0, 0, 0.08);
text-align: center;
font-size: 14px;
color: #666;
}
.imagecodeslidebutton {
position: absolute;
top: 0;
left: 0;
border: 1px solid #505050;
box-sizing: border-box;
background: #fff url("../assets/icons/double-right.jpg") center/60% no-repeat;
cursor: pointer;
}

@ -0,0 +1,48 @@
import { Row, Col } from 'antd';
import React from 'react';
import myStyles from './styles.less';
import { connect } from 'dva'
import img from '../assets/2669474.png'
import WrappedNormalLoginForm from './LoginForm'
const namespace = 'user'
const mapDispatchToProps = (dispatch) => {
return {
toWork: () => {
dispatch({
type: `${namespace}/toWork`,
})
},
}
};
@connect(null, mapDispatchToProps)
export default class user extends React.Component {
constructor(props) {
super(props)
}
toWork = () => {
this.props.toWork()
}
render() {
return (
<div className={myStyles.user}>
<Row>
<Col span={15}>
<img src={img} style={{ width:"100%", padding: 0, borderBottomRightRadius:"140px"}}></img>
</Col>
<Col span={9}>
<Col span={14} offset={5}>
<div className={myStyles.welcome}>WELCOME</div>
<WrappedNormalLoginForm/>
</Col>
</Col>
</Row>
</div>
)
}
}

@ -0,0 +1,6 @@
import Link from 'umi/link';
export default () =>
<>
<h1>Work Page</h1>
</>

@ -0,0 +1,36 @@
import request from '../util/request';
export function getCode() {
return request('http://localhost:3002/code/slide',{
method: 'POST',
header: {Origin: "http://localhost:8000"}
})
}
export function signIn(params) {
return request('http://localhost:3002/api/user/signIn.json',{
method: 'POST',
data: params,
header: {Origin: "http://localhost:8000"}
})
}
/*
export function getResult(params) {
return request('http://127.0.0.1:3000/api/index',{
method: 'POST',
data: params,
header: {Origin: "http://localhost:8000","Content-Type":"application/json"}
})
}
export function addOne(data) {
return request('/api/cards/add', {
headers: {
'content-type': 'application/json',
},
method: 'POST',
body: JSON.stringify(data),
});
}
*/

@ -0,0 +1,72 @@
/**
* request 网络请求工具
* 更详细的api文档: https://bigfish.alipay.com/doc/api#request
*/
import { extend } from 'umi-request';
import { notification } from 'antd';
import router from 'umi/router';
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
/**
* 异常处理程序
*/
const errorHandler = error => {
const { response = {} } = error;
const errortext = codeMessage[response.status] || response.statusText;
const { status, url } = response;
if (status === 401) {
notification.error({
message: '未登录或登录已过期,请重新登录。',
});
// @HACK
/* eslint-disable no-underscore-dangle */
window.g_app._store.dispatch({
type: 'login/logout',
});
return;
}
notification.error({
message: `请求错误 ${status}: ${url}`,
description: errortext,
});
// environment should not be used
if (status === 403) {
router.push('/exception/403');
return;
}
if (status <= 504 && status >= 500) {
router.push('/exception/500');
return;
}
if (status >= 404 && status < 422) {
router.push('/exception/404');
}
};
/**
* 配置request请求时的默认参数
*/
const request = extend({
errorHandler, // 默认错误处理
credentials: 'include', // 默认请求是否带上cookie
});
export default request;

@ -0,0 +1,15 @@
import { mount } from 'enzyme';
import TestDemo from '../src/component/TestDemo';
const sum = function (a, b) {
return a + b;
};
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('TestDemo', () => {
const wrapper = mount(<TestDemo />);
expect(wrapper.find('div').text()).toBe('test');
});

@ -0,0 +1,90 @@
// 代码参考 http://gitlab.alipay-inc.com/bigfish/bigfish-antdpro-adapter
const executeRule = require('./executeRule');
const rules = [
// copy 代码
{
pattern: '!(dist|node_modules|tool|.git|.gitlab-ci.yml)',
operation: 'cp',
target: 'dist/',
},
// 修改代码从 umi 到 bigfish
{
pattern: 'dist/package.json',
operation: 'modify',
ops: [{
match: '"umi": "^2.0.0",',
replace: '"@alipay/bigfish": "^2.0.0",'
}, {
match: `,
"umi-plugin-react": "^1.0.0"`,
replace: ''
}, {
match: /umi/g,
replace: 'bigfish',
}],
},
// 修改配置
{
pattern: 'dist/config/config.js',
operation: 'modify',
ops: [{
match: `
singular: true,
plugins: [
['umi-plugin-react', {
antd: true,
dva: true,
locale: {
enable: true,
},
}],
],`,
replace: `
locale: {
enable: true,
},`,
}],
},
// 修改组件中的依赖路径
{
pattern: 'dist/src/**/*.js',
operation: 'modify',
ops: [{
match: '\'react\'',
replace: '\'@alipay/bigfish/react\'',
}, {
match: '\'dva\'',
replace: '\'@alipay/bigfish/sdk\'',
}, {
match: /'antd/g,
replace: '\'@alipay/bigfish/antd',
}, {
match: '\'classnames\'',
replace: '\'@alipay/bigfish/util/classnames\'',
}, {
match: 'import { routerRedux } from \'dva/router\'',
replace: 'import history from \'@alipay/bigfish/sdk/history\';',
}, {
match: '\'dva/router\'',
replace: '\'@alipay/bigfish/sdk/router\'',
}, {
match: '\'prop-types\'',
replace: '\'@alipay/bigfish/util/prop-types\'',
}, {
match: '\'umi/locale\'',
replace: '\'@alipay/bigfish/locale\'',
}, {
match: 'import Link from \'umi/link\';',
replace: 'import { Link } from \'@alipay/bigfish/sdk/router\';',
}]
}
]
rules.forEach((rule) => {
executeRule(rule, true);
});
console.log('done');
process.exit(0);

@ -0,0 +1,64 @@
const glob = require('glob');
const fs = require('fs-extra');
const { join, basename } = require('path');
const getRealPath = (p) => {
return join(__dirname, '..', p);
};
const rfRule = (path) => {
fs.removeSync(path);
};
const cpRule = (path, { target }) => {
let realPath = getRealPath(target);
if (target.endsWith('/')) {
realPath = join(realPath, basename(path))
}
fs.copySync(path, realPath);
};
const modifyRule = (path, { ops }) => {
let fileContent = '' + fs.readFileSync(path);
ops.forEach(({ match, replace }) => {
fileContent = fileContent.replace(match, replace);
});
fs.writeFileSync(path, fileContent);
};
const renamRule = (path, { name }) => {
const oldName = basename(path);
if (typeof name === 'function') {
name = name(oldName);
}
fs.moveSync(path, path.replace(oldName, name));
};
function executeRule(rule, dot) {
const { pattern, operation } = rule;
const files = glob.sync(pattern, { dot });
console.log(`find ${files.length} matched for ${pattern}`);
files.forEach((f => {
const realPath = getRealPath(f);
let op = () => { console.warn(`not find operation: ${operation}`); };
switch(operation) {
case 'rf':
op = rfRule;
break;
case 'cp':
op = cpRule;
break;
case 'modify':
op = modifyRule;
break;
case 'rename':
op = renamRule;
break;
}
console.log(`start execute ${operation} for ${realPath} ...`);
op(realPath, rule);
}));
};
module.exports = executeRule;

@ -0,0 +1,15 @@
# 将 umi 的代码转换为 bigfish(蚂蚁金服基于 umi 封装的内部框架)
rm -rf dist
node tool/bigfish.js
## sync to git http://gitlab.alipay-inc.com/bigfish/course-demo-bigfish
git clone git@gitlab.alipay-inc.com:bigfish/course-demo-bigfish.git
cd course-demo-bigfish
rm -rf ./*
rm .editorconfig .eslintrc .gitignore
cp -r ../dist/* ./
cp ../dist/.* ./
git add -A
git commit -m 'commit for bigfish'
git push

@ -0,0 +1,29 @@
{
"compilerOptions": {
"outDir": "build/dist",
"module": "esnext",
"target": "es2016",
"lib": ["es6", "dom"],
"sourceMap": true,
"jsx": "react",
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"rootDir": "src",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules",
"build",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts",
"tslint:latest",
"tslint-config-prettier"
]
}

@ -0,0 +1,10 @@
{
"extends": ["tslint:latest", "tslint-react", "tslint-config-prettier"],
"rules": {
"no-var-requires": false,
"no-submodule-imports": false,
"object-literal-sort-keys": false,
"jsx-no-lambda": false,
"no-implicit-dependencies": false
}
}
Loading…
Cancel
Save