Skip to content

Commit

Permalink
mock接口数据
Browse files Browse the repository at this point in the history
自选、行情页面切换时自动订阅
  • Loading branch information
amirliu committed Jul 23, 2021
1 parent 65fca5a commit a7bf6cd
Show file tree
Hide file tree
Showing 26 changed files with 531 additions and 53 deletions.
5 changes: 5 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# just a flag
ENV = 'development'

# base api
VUE_APP_BASE_API = '/dev-api'
6 changes: 6 additions & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# just a flag
ENV = 'production'

# base api
VUE_APP_BASE_API = ''

60 changes: 60 additions & 0 deletions mock/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const Mock = require('mockjs')
const { param2Obj } = require('./utils')

const user = require('./user')
// const role = require('./role')
// const article = require('./article')
// const search = require('./remote-search')

const mocks = [
...user,
// ...role,
// ...article,
// ...search
]

// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
function mockXHR () {
// mock patch
// https://github.com/nuysoft/Mock/issues/300
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function () {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false

if (this.responseType) {
this.custom.xhr.responseType = this.responseType
}
}
this.proxy_send(...arguments)
}

function XHR2ExpressReqWrap (respond) {
return function (options) {
let result = null
if (respond instanceof Function) {
const { body, type, url } = options
// https://expressjs.com/en/4x/api.html#req
result = respond({
method: type,
body: JSON.parse(body),
query: param2Obj(url)
})
} else {
result = respond
}
return Mock.mock(result)
}
}

for (const i of mocks) {
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
}
}

module.exports = {
mocks,
mockXHR
}
81 changes: 81 additions & 0 deletions mock/mock-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
const path = require('path')
const Mock = require('mockjs')

const mockDir = path.join(process.cwd(), 'mock')

function registerRoutes(app) {
let mockLastIndex
const { mocks } = require('./index.js')
const mocksForServer = mocks.map(route => {
return responseFake(route.url, route.type, route.response)
})
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response)
mockLastIndex = app._router.stack.length
}
const mockRoutesLength = Object.keys(mocksForServer).length
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength
}
}

function unregisterRoutes() {
Object.keys(require.cache).forEach(i => {
if (i.includes(mockDir)) {
delete require.cache[require.resolve(i)]
}
})
}

// for mock server
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
type: type || 'get',
response(req, res) {
console.log('request invoke:' + req.path)
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
}
}
}

module.exports = app => {
// parse app.body
// https://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))

const mockRoutes = registerRoutes(app)
var mockRoutesLength = mockRoutes.mockRoutesLength
var mockStartIndex = mockRoutes.mockStartIndex

// watch files, hot reload mock server
chokidar.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true
}).on('all', (event, path) => {
if (event === 'change' || event === 'add') {
try {
// remove mock routes stack
app._router.stack.splice(mockStartIndex, mockRoutesLength)

// clear routes cache
unregisterRoutes()

const mockRoutes = registerRoutes(app)
mockRoutesLength = mockRoutes.mockRoutesLength
mockStartIndex = mockRoutes.mockStartIndex

console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
} catch (error) {
console.log(chalk.redBright(error))
}
}
})
}
165 changes: 165 additions & 0 deletions mock/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@

const tokens = {
admin: {
token: 'admin-token'
},
editor: {
token: 'editor-token'
}
}

const users = {
'admin-token': {
roles: ['admin'],
introduction: 'I am a super administrator',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Super Admin'
},
'editor-token': {
roles: ['editor'],
introduction: 'I am an editor',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Normal Editor'
}
}

module.exports = [
// user login
{
url: '/vue-element-admin/user/login',
type: 'post',
response: config => {
const { username } = config.body
const token = tokens[username]

// mock error
if (!token) {
return {
code: 60204,
message: 'Account and password are incorrect.'
}
}

return {
code: 20000,
data: token
}
}
},

// get user info
{
url: '/global/customer.app.CustomerWebApiService.queryCustomerAssetsInfo',
type: 'post',
response: config => {
return {
code: '0',
msg: '',
data: {
currency: 'USD',
totalBalance: '9999999.888',
totalNetAssets: '1000.000',
totalAvailable: '1231.123',
digits: 3,
totalLiabilities: '-31.123',
totalLiabilitiesPrincipal: '500.000',
totalInterest: '0.000',
accountInfoMap: {
'USD': {
companyId: 209,
tradeType: 1,
accountId: 49,
status: 2,
activateStatus: 2,
currency: 'USD',
digits: 3,
balance: '1231231.234',
netAssets: '12123456.234',
available: '1231231.234',
equity: '1231231.234',
withdrawAmount: '1231231.234',
lockAmount: '11.234',
profit: '11.234',
margin: '11.234',
notWithdrawAmount: '11.234',
lockMargin: '11.234',
liabilities: '11.234',
liabilitiesPrincipal: '11.234',
interest: '11.234',
frozen: '11.234',
}
},
}
}
}
},
{
url: '/global/customer.app.CustomerWebApiService.queryAccountAssetsInfo',
type: 'post',
response: config => {
return {
code: '0',
msg: '',
data: {
companyId: 209,
tradeType: 1,
accountId: 49,
status: 2,
activateStatus: 2,
currency: 'USD',
digits: 3,
balance: '1231231.234',
netAssets: '12123456.234',
available: '1231231.234',
equity: '1231231.234',
withdrawAmount: '1231231.234',
lockAmount: '11.234',
profit: '11.234',
margin: '11.234',
notWithdrawAmount: '11.234',
lockMargin: '11.234',
liabilities: '11.234',
liabilitiesPrincipal: '11.234',
interest: '11.234',
frozen: '11.234',
availableLoan: '999999.999',
}
}
}
},
// get user info
{
url: '/vue-element-admin/user/info\.*',
type: 'get',
response: config => {
const { token } = config.query
const info = users[token]

// mock error
if (!info) {
return {
code: 50008,
message: 'Login failed, unable to get user details.'
}
}

return {
code: 20000,
msg: '',
data: info
}
}
},

// user logout
{
url: '/vue-element-admin/user/logout',
type: 'post',
response: _ => {
return {
code: 20000,
data: 'success'
}
}
}
]
48 changes: 48 additions & 0 deletions mock/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* @param {string} url
* @returns {Object}
*/
function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}

/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}

module.exports = {
param2Obj,
deepClone
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"js-md5": "^0.7.3",
"jsonlint": "^1.6.3",
"lightweight-charts": "^3.3.0",
"mockjs": "^1.1.0",
"mousetrap": "^1.6.5",
"pako": "^1.0.11",
"reconnectingwebsocket": "^1.0.0",
Expand All @@ -50,6 +51,7 @@
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.13.3",
"chalk": "^4.1.1",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
Expand Down
Loading

0 comments on commit a7bf6cd

Please sign in to comment.