添加后台连接用的后端

This commit is contained in:
luying
2020-09-22 11:09:15 +08:00
parent 6e891ec756
commit bcbed5959f
48 changed files with 14845 additions and 2076 deletions

28
gm-server/.autod.conf.js Normal file
View File

@@ -0,0 +1,28 @@
'use strict';
module.exports = {
write: true,
plugin: 'autod-egg',
prefix: '^',
devprefix: '^',
exclude: [
'test/fixtures',
'coverage',
],
dep: [
'egg',
'egg-scripts',
],
devdep: [
'autod',
'autod-egg',
'egg-bin',
'tslib',
'typescript',
],
keep: [
],
semver: [
],
test: 'scripts',
};

2
gm-server/.eslintignore Normal file
View File

@@ -0,0 +1,2 @@
**/*.d.ts
node_modules/

6
gm-server/.eslintrc Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": "eslint-config-egg/typescript",
"parserOptions": {
"project": "./tsconfig.json"
}
}

42
gm-server/.github/workflows/nodejs.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node.js CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: '0 2 * * *'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
node-version: [8]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout Git Source
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install Dependencies
run: npm i -g npminstall && npminstall
- name: Continuous Integration
run: npm run ci
- name: Code Coverage
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}

20
gm-server/.gitignore vendored Normal file
View File

@@ -0,0 +1,20 @@
logs/
npm-debug.log
node_modules/
coverage/
.idea/
run/
logs/
.DS_Store
.vscode
*.swp
*.lock
*.js
!.autod.conf.js
app/**/*.js
test/**/*.js
config/**/*.js
app/**/*.map
test/**/*.map
config/**/*.map

12
gm-server/.travis.yml Normal file
View File

@@ -0,0 +1,12 @@
language: node_js
node_js:
- '8'
before_install:
- npm i npminstall -g
install:
- npminstall
script:
- npm run ci
after_script:
- npminstall codecov && codecov

33
gm-server/README.md Normal file
View File

@@ -0,0 +1,33 @@
# hackernews-async-ts
[Hacker News](https://news.ycombinator.com/) showcase using typescript && egg
## QuickStart
### Development
```bash
$ npm i
$ npm run dev
$ open http://localhost:7001/
```
Don't tsc compile at development mode, if you had run `tsc` then you need to `npm run clean` before `npm run dev`.
### Deploy
```bash
$ npm run tsc
$ npm start
```
### Npm Scripts
- Use `npm run lint` to check code style
- Use `npm test` to run unit test
- se `npm run clean` to clean compiled js at development mode once
### Requirement
- Node.js 8.x
- Typescript 2.8+

58
gm-server/app.ts Normal file
View File

@@ -0,0 +1,58 @@
import 'reflect-metadata'
import * as mongoose from 'mongoose';
import { Application, IBoot } from 'egg';
export default class FooBoot implements IBoot {
private readonly app: Application;
constructor(app: Application) {
this.app = app;
}
async configWillLoad() {
// Ready to call configDidLoad,`
// Config, plugin files are referred,`
// this is the last chance to modify the config.
await this.connectDB(this.app)
}
configDidLoad() {
// Config, plugin files have loaded.
}
async didLoad() {
// All files have loaded, start plugin here.
}
async willReady() {
// All plugins have started, can do some thing before app ready.
// await this.customLoadModel();
}
async didReady() {
// Worker is ready, can do some things
// don't need to block the app boot.
}
async serverDidReady() {
// Server is listening.
}
async beforeClose() {
// Do some thing before app close.
}
//#region 手动挂载model测试需要ctx.model
public async connectDB(app: Application) {
const { url, options } = app.config.mongoose
if (url) {
const connection = await mongoose.connect(url, options)
app.context.connection = connection
}
}
//#endregion
}
module.exports = FooBoot;

1
gm-server/app/consts Symbolic link
View File

@@ -0,0 +1 @@
../../shared/consts

View File

@@ -0,0 +1,8 @@
import { Controller } from 'egg';
export default class HomeController extends Controller {
public async index() {
const { ctx } = this;
ctx.body = await ctx.service.test.sayHi('egg');
}
}

View File

@@ -0,0 +1,24 @@
import { Controller } from 'egg';
export default class LoginController extends Controller {
public async login() {
const { ctx } = this;
const {username, password} = ctx.request.body;
ctx.body = await ctx.service.gmUser.login(username, password);
}
public async currentUser() {
const { ctx } = this;
ctx.body = {
"status": "ok",
"data": ctx.user
};
}
public async createGmAccount() {
const { ctx } = this;
const {password, name, username, group} = ctx.request.body;
ctx.body = await ctx.service.gmUser.createGmAccount(name, username, password, group);
}
}

View File

@@ -0,0 +1,41 @@
import { Controller } from 'egg';
export default class UserController extends Controller {
public async getuserlist() {
const { ctx } = this;
const { field, value } = ctx.request.body;
ctx.body = await ctx.service.users.getuserlist(field, value);
}
public async createRole() {
const { ctx } = this;
const { uid, roleName } = ctx.request.body;
const serverId = 1;
ctx.body = await ctx.service.users.createRole(uid, serverId, roleName);
}
public async getrolelist() {
const { ctx } = this;
const { field, value } = ctx.request.body;
ctx.body = await ctx.service.users.getrolelist(field, value);
}
public async createRoleData() {
const { ctx } = this;
console.log(ctx.request.body)
const { hid, hlv, eid, elv, ecount, ehid, itemid, itemcount, selectedRowKeys: uids, optType } = ctx.request.body;
if(optType == 'hero') {
ctx.body = await ctx.service.users.createHero(uids, hid, hlv);
} else if(optType == 'equip') {
ctx.body = await ctx.service.users.createEquip(uids, eid, elv, ecount, ehid);
} else if (optType == 'item') {
ctx.body = await ctx.service.users.createItem(uids, itemid, itemcount);
} else {
ctx.body = {
status: 'error',
data: '参数错误'
}
}
}
}

1
gm-server/app/db Symbolic link
View File

@@ -0,0 +1 @@
../../shared/db

View File

@@ -0,0 +1,27 @@
import { GMUserModel } from '@db/GMUser';
module.exports = () => {
return async function tokenParser(ctx, next) {
console.log(ctx.request.headers)
if (!ctx.request.headers || !ctx.request.headers.token) {
console.error('token not found');
ctx.body = {
"status": "error",
"data": "账号未登录"
};
return;
}
const user = await GMUserModel.getGmAccountByToken(ctx.request.headers.token);
if (!user) {
console.error('token invalid');
ctx.body = {
"status": "error",
"data": "账号未登录"
};
return;
}
ctx.user = user;
await next();
};
};

1
gm-server/app/resource Symbolic link
View File

@@ -0,0 +1 @@
../../shared/resource

17
gm-server/app/router.ts Normal file
View File

@@ -0,0 +1,17 @@
import { Application } from 'egg';
export default (app: Application) => {
const { controller, router } = app;
const tokenParser = app.middleware.tokenParser();
router.get('/', controller.home.index);
router.post('/api/login/account', controller.login.login);
router.get('/api/currentUser', tokenParser, controller.login.currentUser);
router.post('/api/gmaccount/createaccount', controller.login.createGmAccount);
router.post('/api/users/getuserlist', controller.users.getuserlist);
router.post('/api/users/createrole', controller.users.createRole);
router.post('/api/users/getrolelist', controller.users.getrolelist);
router.post('/api/users/createroledata', controller.users.createRoleData);
};

View File

@@ -0,0 +1,50 @@
import { GMUserModel } from '@db/GMUser';
import { Service } from 'egg';
/**
* Test Service
*/
export default class GMUsers extends Service {
/**
* 后台账号登录
*/
public async login(username: string, password: string) {
// const {ctx} = this;
let user = await GMUserModel.login(username, password);
if(user) {
return {
"status": "ok",
"data": user
}
} else {
return {
"status": "error",
"data": "账号或密码错误"
}
}
}
/**
* 创建后台账号
*/
public async createGmAccount(name: string, username: string, password: string, group: string) {
const {ctx} = this;
let token = ctx.service.utils.genCode(256);
let user = await GMUserModel.getGmAccountByUsername(username);
if(user) {
return {
"status": "error",
"data": "该账号已使用"
}
} else {
user = await GMUserModel.createGmAccount(username, password, name, token, group);
return {
"status": "ok",
"data": user
};
}
}
}

View File

@@ -0,0 +1,15 @@
import { Service } from 'egg';
/**
* Test Service
*/
export default class Test extends Service {
/**
* sayHi to you
* @param name - your name
*/
public async sayHi(name: string) {
return `hi, ${name}`;
}
}

View File

@@ -0,0 +1,94 @@
import { Service } from 'egg';
const csprng = require('csprng');
const fs = require('fs');
const path = require('path');
var gamedata = {};
function initData () {
fs.readdirSync(__dirname + '/../resource')
.filter(function(file) {
return (file.indexOf(".") !== 0) && (file !== "index.js");
})
//筛选有文件名且不是index进行遍历
.forEach(function(file) {
var name = file.split('.')[0];
try {
gamedata[name] = JSON.parse(
fs.readFileSync(path.resolve(__dirname, "../resource/" + file))
);
} catch(e) {
console.error('【文件缺少】:' + file);
gamedata[name] = [];
}
});
}
initData();
/**
* Utils Service
*/
export default class Utils extends Service {
/**
* 生成 len 长度的随机字符串
* @param len 长度
* @param radix 基数
*/
public generateStr(len: number, radix = 36) {
return `${csprng(len, radix)}`;
}
public genCode(len) {
const chars = '123456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijklmnopqrstuvwxyz';
const charArr = chars.split('');
let code = '';
for (let i = 0; i < len; i++) {
code += charArr[Math.floor(Math.random() * charArr.length)];
}
return code;
}
/**
* 生成指定长度的随机数
* @param len 随机数长度
*/
public generateNum(len: number) {
let code = '';
for (let i = 0; i < len; i++) {
code += parseInt(`${Math.random() * 10}`);
}
return code;
}
public exceptionResult(status) {
const { code, simStr } = status;
return { status: code, data: simStr };
}
public getGamedata(key) {
return gamedata[key];
}
public getHeroById(hid) {
let heros = gamedata['dic_zyz_hero']||[];
return heros.find(cur => {
return cur.heroId == hid;
});
}
public getWarById(warid) {
let warInfo = gamedata['dic_zyz_gk']||[];
return warInfo.find(cur => {
return cur.war_id == warid
});
}
public getGoodById(gid) {
console.log(gid)
let goodsInfo = gamedata['goods']||[];
return goodsInfo.find(cur => {
return cur.good_id == gid
});
}
}

View File

@@ -0,0 +1,285 @@
import { UserModel } from '@db/User';
import { RoleModel } from '@db/Role';
import { HeroModel } from '@db/Hero';
import { EquipModel } from '@db/Equip';
import { ItemModel } from '@db/Item';
import { CounterModel } from '@db/Counter';
import { Service } from 'egg';
import Counter from '@db/Counter';
/**
* Test Service
*/
export default class GMUsers extends Service {
/**
* 根据类型等搜索玩家
*/
public async getuserlist(field, value) {
// const {ctx} = this;
let arr = new Array(), flag = 0;
value = value.split(',');
for(let i of value) {
if(field == 'uid') {
let d = parseInt(i);
if(isNaN(d)) {
flag = 1; break;
} else {
arr.push(d);
}
} else if(field == 'username'||field == 'tel') {
arr.push(i);
} else if (field == 'all') {
break;
} else {
flag = 1; break;
}
}
if(flag) {
return {
"status": "error",
"data": "参数错误"
}
}
let users = await UserModel.findUserByField(field, value);
if(users) {
let list = new Array();
for(let user of users) {
let role = await RoleModel.findByUid(user.uid, 1);
list.push({...user, hasRole: role?true: false, role});
}
return {
"status": "ok",
"data": list
}
} else {
return {
"status": "error",
"data": "未找到玩家"
}
}
}
public async createRole(uid:number, serverId: number, roleName: string) {
console.log('enter Auth createRole');
const ctx = this.ctx;
const roleId = ctx.service.utils.genCode(10);
const code = ctx.service.utils.genCode(6);
const seqId = await Counter.getNewCounter('role') || -1;
const role = await RoleModel.createRole(uid, serverId, { roleId, code, roleName, seqId });
if (role) {
return { status: "ok", data: { roleId: role.roleId } };
}
return {
"status": "error",
"data": "创建失败"
};
}
/**
* 根据类型等搜索玩家
*/
public async getrolelist(field, value) {
// const {ctx} = this;
let arr = new Array(), flag = 0;
value = value.split(',');
for(let i of value) {
if(field == 'uid') {
let d = parseInt(i);
if(isNaN(d)) {
flag = 1; break;
} else {
arr.push(d);
}
field = 'userInfo.uid';
} else if(field == 'roleName') {
arr.push(i);
} else if (field == 'tel') {
arr.push(i);
field = 'userInfo.tel';
} else if (field == 'all') {
break;
} else {
flag = 1; break;
}
}
if(flag) {
return {
"status": "error",
"data": "参数错误"
}
}
let roles = await RoleModel.findRoleByField(field, value);
if(roles) {
let result = new Array();
for(let role of roles) {
let heroCount = await HeroModel.count({roleId: role.roleId}).lean();
let equipCount = await EquipModel.count({roleId: role.roleId}).lean();
let itemCount = await ItemModel.count({roleId: role.roleId}).lean();
let {roleId, roleName, serverId, lv, vLv} = role;
let {uid, tel} = role.userInfo;
result.push({
key: roleId, roleId, roleName, serverId, lv, vLv, uid, tel, heroCount, equipCount, itemCount
});
}
return {
"status": "ok",
"data": result
}
} else {
return {
"status": "error",
"data": "未找到玩家"
}
}
}
public async createHero(uids: Array<string>, hid: number, hlv: number) {
const {ctx} = this;
console.log('gm createHero', uids, hid, hlv);
let flag = 0, msg = '创建失败';
for(let roleId of uids) {
let role = await RoleModel.findByRoleId(roleId);
if(role) {
let hero = await HeroModel.findByHidAndRole(hid, roleId);
if(hero) {
flag = 1, msg = "角色" + roleId + "已拥有武将" + hid;
break;
}
const seqId = await CounterModel.getNewCounter('hid')||-1;
let dicHero = ctx.service.utils.getHeroById(hid);
if(!dicHero) {
flag = 1, msg = "未找到武将" + hid;
break;
}
const heroInfo = {
roleId,
roleName: role.roleName,
hid: hid,
hName: dicHero.name,
seqId,
lv: hlv
}
await HeroModel.createHero(heroInfo);
} else {
flag = 1, msg = '未找到角色' + roleId;
}
}
if (flag) {
return {
"status": "error",
"data": msg
}
} else {
return {
"status": "ok",
"data": uids
};
}
}
public async createEquip(uids: Array<string>, eid: number, elv: number, ecount: number, ehid: number) {
const {ctx} = this;
console.log('gm createEquip');
let flag = 0, msg = '创建失败';
for(let roleId of uids) {
let role = await RoleModel.findByRoleId(roleId);
if(role) {
for(let i = 0; i <ecount; i++) {
let dicEquip = ctx.service.utils.getGoodById(eid);
if(!dicEquip) {
flag = 1, msg = "未找到装备" + eid;
break;
}
const seqId = await CounterModel.getNewCounter('eid')||-1;
const equipInfo = {
roleId,
roleName: role.roleName,
eid,
eName: dicEquip.name,
seqId,
type: 1,
lv: elv
}
const equip = await EquipModel.createEquip(equipInfo);
if(ehid > 0 && equip) {
await HeroModel.addEquip(roleId, ehid, equip._id);
}
}
} else {
flag = 1, msg = '未找到角色' + roleId;
}
}
if (flag) {
return {
"status": "error",
"data": msg
}
} else {
return {
"status": "ok",
"data": uids
};
}
}
public async createItem(uids: Array<string>, itemid: number, itemcount: number) {
console.log('gm createEquip');
let flag = 0;
for(let roleId of uids) {
let role = await RoleModel.findByRoleId(roleId);
if(role) {
let item = await ItemModel.findbyItemid(itemid, roleId);
if(item) {
await ItemModel.changeItemCount(item.seqId, itemcount);
} else {
const seqId = await CounterModel.getNewCounter('itemid')||-1;
const itemInfo = {
roleId,
roleName: role.roleName,
itemid,
itemName: '包子',
seqId,
type: 1,
count: itemcount
}
await ItemModel.createItem(itemInfo);
}
} else {
flag = 1;
}
}
if (flag) {
return {
"status": "error",
"data": "创建失败"
}
} else {
return {
"status": "ok",
"data": uids
};
}
}
}

14
gm-server/appveyor.yml Normal file
View File

@@ -0,0 +1,14 @@
environment:
matrix:
- nodejs_version: '8'
install:
- ps: Install-Product node $env:nodejs_version
- npm i npminstall && node_modules\.bin\npminstall
test_script:
- node --version
- npm --version
- npm run test
build: off

View File

@@ -0,0 +1,48 @@
import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;
// override config from framework / plugin
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1600244957952_7142';
// add your egg config in here
config.middleware = [];
config.cluster = {
listen: {
port: 7500
}
};
// add your special config in here
const bizConfig = {
sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`,
};
config.mongoose = {
url: 'mongodb://dbop:zyzdbopbantu@dds-8vbdb47c6fb58a541.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbdb47c6fb58a542.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-500808098', // 内网
options: { useNewUrlParser: true, useUnifiedTopology: true },
};
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: ['http://localhost:9000']
};
config.alinode = {
appid: '86043',
secret: '54ef0364995b0c4f2ab42150e29ad30df8327a3a',
error_log: [ '/root/logs/zyz/zyz-web.log', '/root/logs/zyz/common-error.log', '/root/logs/zyz/egg-agent.log' ],
packages: [ '/root/zyz/web-server/package.json' ],
};
// the return config will combines to EggAppConfig
return {
...config,
...bizConfig,
};
};

View File

@@ -0,0 +1,48 @@
import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;
// override config from framework / plugin
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1600244957952_7142';
// add your egg config in here
config.middleware = [];
config.cluster = {
listen: {
port: 7500
}
};
// add your special config in here
const bizConfig = {
sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`,
};
config.mongoose = {
url: 'mongodb://127.0.0.1:27017/admin', // 内网
options: { useNewUrlParser: true, useUnifiedTopology: true },
};
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: ['http://localhost:9000']
};
config.alinode = {
appid: '86043',
secret: '54ef0364995b0c4f2ab42150e29ad30df8327a3a',
error_log: [ '/root/logs/zyz/zyz-web.log', '/root/logs/zyz/common-error.log', '/root/logs/zyz/egg-agent.log' ],
packages: [ '/root/zyz/web-server/package.json' ],
};
// the return config will combines to EggAppConfig
return {
...config,
...bizConfig,
};
};

View File

@@ -0,0 +1,6 @@
import { EggAppConfig, PowerPartial } from 'egg';
export default () => {
const config: PowerPartial<EggAppConfig> = {};
return config;
};

View File

@@ -0,0 +1,20 @@
import { EggPlugin } from 'egg';
import 'tsconfig-paths/register';
const plugin: EggPlugin = {
// static: true,
// nunjucks: {
// enable: true,
// package: 'egg-view-nunjucks',
// },
cors: {
enable: true,
package: 'egg-cors',
},
alinode: {
enable: true,
package: 'egg-alinode',
},
};
export default plugin;

11359
gm-server/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

64
gm-server/package.json Normal file
View File

@@ -0,0 +1,64 @@
{
"name": "gm-server",
"version": "1.0.0",
"description": "gm",
"private": true,
"egg": {
"typescript": true,
"declarations": true
},
"scripts": {
"start": "egg-scripts start --daemon --title=egg-server-gm-server",
"stop": "egg-scripts stop --title=egg-server-gm-server",
"dev": "egg-bin dev",
"debug": "egg-bin debug",
"test-local": "egg-bin test",
"test": "npm run lint -- --fix && npm run test-local",
"cov": "egg-bin cov",
"tsc": "ets && tsc -p tsconfig.json",
"ci": "npm run lint && npm run cov && npm run tsc",
"autod": "autod",
"lint": "eslint . --ext .ts",
"clean": "ets clean",
"local": "EGG_SERVER_ENV=local npm run dev",
"prod": "EGG_SERVER_ENV=prod npm run dev"
},
"dependencies": {
"bcrypt": "^5.0.0",
"csprng": "^0.1.2",
"egg": "^2.6.1",
"egg-alinode": "^2.0.1",
"egg-cors": "^2.2.3",
"egg-scripts": "^2.6.0",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
"@types/mocha": "^2.2.40",
"@types/node": "^7.0.12",
"@types/supertest": "^2.0.0",
"autod": "^3.0.1",
"autod-egg": "^1.1.0",
"egg-ci": "^1.8.0",
"egg-bin": "^4.11.0",
"egg-mock": "^3.16.0",
"tslib": "^1.9.0",
"eslint": "^6.7.2",
"eslint-config-egg": "^8.0.0",
"typescript": "^3.0.0"
},
"engines": {
"node": ">=8.9.0"
},
"ci": {
"version": "8"
},
"repository": {
"type": "git",
"url": ""
},
"eslintIgnore": [
"coverage"
],
"author": "ly",
"license": "MIT"
}

View File

@@ -0,0 +1,9 @@
import * as assert from 'assert';
import { app } from 'egg-mock/bootstrap';
describe('test/app/controller/home.test.ts', () => {
it('should GET /', async () => {
const result = await app.httpRequest().get('/').expect(200);
assert(result.text === 'hi, egg');
});
});

View File

@@ -0,0 +1,16 @@
import * as assert from 'assert';
import { Context } from 'egg';
import { app } from 'egg-mock/bootstrap';
describe('test/app/service/Test.test.js', () => {
let ctx: Context;
before(async () => {
ctx = app.mockContext();
});
it('sayHi', async () => {
const result = await ctx.service.test.sayHi('egg');
assert(result === 'hi, egg');
});
});

35
gm-server/tsconfig.json Normal file
View File

@@ -0,0 +1,35 @@
{
"compileOnSave": true,
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"strict": true,
"noImplicitAny": false,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"charset": "utf8",
"allowJs": false,
"pretty": true,
"noEmitOnError": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"strictPropertyInitialization": false,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"inlineSourceMap": true,
"importHelpers": true,
"baseUrl": ".",
"paths": {
"@db/*": ["app/db/*"],
"@consts/*": ["app/consts/*"]
},
},
"exclude": [
"app/public",
"app/views",
"node_modules*"
]
}

View File

@@ -0,0 +1,15 @@
// This file is created by egg-ts-helper@1.25.8
// Do not modify this file!!!!!!!!!
import 'egg';
import ExportHome from '../../../app/controller/home';
import ExportLogin from '../../../app/controller/login';
import ExportUsers from '../../../app/controller/users';
declare module 'egg' {
interface IController {
home: ExportHome;
login: ExportLogin;
users: ExportUsers;
}
}

6
gm-server/typings/app/index.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
// This file is created by egg-ts-helper@1.25.8
// Do not modify this file!!!!!!!!!
import 'egg';
export * from 'egg';
export as namespace Egg;

View File

@@ -0,0 +1,11 @@
// This file is created by egg-ts-helper@1.25.8
// Do not modify this file!!!!!!!!!
import 'egg';
import ExportTokenParser from '../../../app/middleware/tokenParser';
declare module 'egg' {
interface IMiddleware {
tokenParser: typeof ExportTokenParser;
}
}

View File

@@ -0,0 +1,21 @@
// This file is created by egg-ts-helper@1.25.8
// Do not modify this file!!!!!!!!!
import 'egg';
type AnyClass = new (...args: any[]) => any;
type AnyFunc<T = any> = (...args: any[]) => T;
type CanExportFunc = AnyFunc<Promise<any>> | AnyFunc<IterableIterator<any>>;
type AutoInstanceType<T, U = T extends CanExportFunc ? T : T extends AnyFunc ? ReturnType<T> : T> = U extends AnyClass ? InstanceType<U> : U;
import ExportGmUser from '../../../app/service/GmUser';
import ExportTest from '../../../app/service/Test';
import ExportUtils from '../../../app/service/Utils';
import ExportUsers from '../../../app/service/users';
declare module 'egg' {
interface IService {
gmUser: AutoInstanceType<typeof ExportGmUser>;
test: AutoInstanceType<typeof ExportTest>;
utils: AutoInstanceType<typeof ExportUtils>;
users: AutoInstanceType<typeof ExportUsers>;
}
}

11
gm-server/typings/config/index.d.ts vendored Normal file
View File

@@ -0,0 +1,11 @@
// This file is created by egg-ts-helper@1.25.8
// Do not modify this file!!!!!!!!!
import 'egg';
import { EggAppConfig } from 'egg';
import ExportConfigDefault from '../../config/config.default';
type ConfigDefault = ReturnType<typeof ExportConfigDefault>;
type NewEggAppConfig = ConfigDefault;
declare module 'egg' {
interface EggAppConfig extends NewEggAppConfig { }
}

37
gm-server/typings/config/plugin.d.ts vendored Normal file
View File

@@ -0,0 +1,37 @@
// This file is created by egg-ts-helper@1.25.8
// Do not modify this file!!!!!!!!!
import 'egg';
import 'egg-onerror';
import 'egg-session';
import 'egg-i18n';
import 'egg-watcher';
import 'egg-multipart';
import 'egg-security';
import 'egg-development';
import 'egg-logrotator';
import 'egg-schedule';
import 'egg-static';
import 'egg-jsonp';
import 'egg-view';
import 'egg-cors';
import 'egg-alinode';
import { EggPluginItem } from 'egg';
declare module 'egg' {
interface EggPlugin {
onerror?: EggPluginItem;
session?: EggPluginItem;
i18n?: EggPluginItem;
watcher?: EggPluginItem;
multipart?: EggPluginItem;
security?: EggPluginItem;
development?: EggPluginItem;
logrotator?: EggPluginItem;
schedule?: EggPluginItem;
static?: EggPluginItem;
jsonp?: EggPluginItem;
view?: EggPluginItem;
cors?: EggPluginItem;
alinode?: EggPluginItem;
}
}

5
gm-server/typings/index.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
import 'egg';
declare module 'egg' {
}

View File

@@ -4,3 +4,6 @@ echo '============ game-server npm installed ============'
cd ..
cd ./web-server && npm install -d
echo '============ web-server npm installed ============'
cd ..
cd ./gm-server && npm install -d
echo '============ gm-server npm installed ============'

View File

@@ -6,6 +6,7 @@
"dependencies": {
"@typegoose/typegoose": "^7.3.5",
"@types/mongoose": "^5.7.36",
"bcrypt": "^5.0.0",
"moment": "^2.27.0",
"mongoose": "^5.10.4"
},

View File

@@ -9,4 +9,5 @@ export const AUTH_SMS_CNT_PER_DAY = 8;
export const COUNTER = {
UID: 'uid',
GMUID: 'gmuid'
};

View File

@@ -43,8 +43,8 @@ export default class Equip extends BaseModel {
const equips = await EquipModel.find({ roleId }).lean(lean);
return equips;
}
public static async createEquip(equipInfo: {roleId: string, roleName: string, eid: number, seqId: number, type: number, eName: string}, lean = true) {
public static async createEquip(equipInfo: {roleId: string, roleName: string, eid: number, seqId: number, type: number, eName: string, lv?: number}, lean = true) {
const doc = new EquipModel();
const update = Object.assign(equipInfo, doc.toJSON());
const equip = await EquipModel.findOneAndUpdate({ seqId: equipInfo.seqId }, update, {upsert: true, new: true}).lean(lean);

85
shared/db/GMUser.ts Normal file
View File

@@ -0,0 +1,85 @@
import { COUNTER } from './../consts/consts';
import { CounterModel } from './Counter';
import BaseModel from './BaseModel';
import { index, getModelForClass, prop } from '@typegoose/typegoose';
const bcrypt = require('bcrypt');
const SALT_WORK_FACTOR = 5
/**
* 用户字段接口
*/
@index({ tel: 1 })
@index({ uid: 1 })
export default class GMUser extends BaseModel {
@prop({ required: true })
uid: number;
@prop({ required: true })
name: string;
@prop({ required: true })
username: string;
@prop({ required: true })
password: string;
@prop({ required: true })
salt: string;
@prop({ required: true })
token: string;
@prop({ required: true, default: '' })
group: string;
private static async encryptPass(password: string, salt?: string) {
console.log(salt)
if(!salt) {
salt = await bcrypt.genSalt(SALT_WORK_FACTOR);
}
console.log(salt)
let npassword = await bcrypt.hash(password, salt);
return {npassword, salt};
}
public static async getGmAccountByToken(token: string, lean = true) {
const user = await GMUserModel.findOne({token}).select('uid username name token group').lean(lean);
return user;
}
public static async getGmAccountByUid(uid: number, lean = true) {
const user = await GMUserModel.findOne({uid}).select('uid username name token group').lean(lean);
return user;
}
public static async getGmAccountByUsername(username: string, lean = true) {
const user = await GMUserModel.findOne({username}).select('uid username name token group').lean(lean);
return user;
}
public static async login(username: string, password: string, lean = true) {
const user = await GMUserModel.findOne({username}).select('salt').lean();
if(user) {
let { salt } = user;
console.log(salt)
let { npassword } = await this.encryptPass(password, salt);
console.log(username, npassword)
const checkUser = await GMUserModel.findOne({username, password: npassword}).select('uid username name token group').lean(lean);
return checkUser;
} else {
return null
}
}
public static async createGmAccount(username: string, password: string, name: string, token: string, group: string, lean = true) {
const uid = await CounterModel.getNewCounter(COUNTER.GMUID);
let r = await this.encryptPass(password);
const user = await GMUserModel.findOneAndUpdate({username}, {uid, password: r.npassword, salt: r.salt, name, token, group}, {upsert: true, new: true}).select('uid username name group').lean(lean);
return user;
}
}
export const GMUserModel = getModelForClass(GMUser);

View File

@@ -55,6 +55,11 @@ export default class Hero extends BaseModel {
return heros || [];
}
public static async findByHidAndRole(hid: number, roleId: string, lean = true) {
const hero = await HeroModel.findOne({ hid, roleId }).lean(lean);
return hero;
}
public static async addEquip(roleId: string, hid: number, equipId: string, lean = true) {
const hero = await HeroModel.findOneAndUpdate({ roleId, hid }, {$push: {equips: equipId}}, {new: true}).lean(lean);
if (hero) {
@@ -63,7 +68,7 @@ export default class Hero extends BaseModel {
return hero;
}
public static async createHero(heroInfo: {roleId: string, roleName: string, hid: number, hName: string, seqId: number}, lean = true) {
public static async createHero(heroInfo: {roleId: string, roleName: string, hid: number, hName: string, seqId: number, lv?:number}, lean = true) {
const doc = new HeroModel();
const update = Object.assign(heroInfo, doc.toJSON());
const hero = await HeroModel.findOneAndUpdate({roleId: heroInfo.roleId, hid: heroInfo.hid}, update, {upsert: true, new: true}).lean(lean);

47
shared/db/Item.ts Normal file
View File

@@ -0,0 +1,47 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop } from '@typegoose/typegoose';
@index({ roleId: 1, hid: 1, eid: 1 })
@index({ seqId: 1 })
export default class Item extends BaseModel {
@prop({ required: true })
roleId: string; // 角色 id
@prop({ required: true })
roleName: string; // 角色名称
@prop({ required: true })
itemid: number; // 道具 id
@prop({ required: true })
itemName: string; // 道具名称
@prop({ required: true })
seqId: number; // 道具表自增 id
@prop({ required: true, default: 0 })
count: number; // 道具数量
public static async findbyRole(roleId: string, lean = true) {
const items = await ItemModel.find({ roleId }).lean(lean);
return items;
}
public static async findbyItemid(itemid: number, roleId: string, lean = true) {
const equips = await ItemModel.findOne({ itemid, roleId }).lean(lean);
return equips;
}
public static async changeItemCount(seqId: number, count: number, lean = true) {
const equips = await ItemModel.findOneAndUpdate({ seqId }, {$inc:{count}}).lean(lean);
return equips;
}
public static async createItem(itemInfo: {roleId: string, roleName: string, itemid: number, seqId: number, itemName: string, count: number}, lean = true) {
const doc = new ItemModel();
const update = Object.assign(itemInfo, doc.toJSON());
const item = await ItemModel.findOneAndUpdate({ seqId: itemInfo.seqId }, update, {upsert: true, new: true}).lean(lean);
return item;
}
}
export const ItemModel = getModelForClass(Item);

View File

@@ -96,6 +96,11 @@ export default class Role extends BaseModel {
return role;
}
public static async findByRoleId(roleId: string, lean = true) {
const role = await RoleModel.findOne({ roleId }).lean(lean);
return role;
}
public static async createRole(uid: number, serverId: number, roleInfo: {roleId: string; roleName: string; seqId: number; code: string}, lean = true) {
const user = await User.findUserByUid(uid);
if (!user) return null;
@@ -104,6 +109,18 @@ export default class Role extends BaseModel {
const role = await RoleModel.findOneAndUpdate({ 'userInfo.uid': uid, serverId }, update, { upsert: true, new: true }).lean(lean);
return role;
}
public static async findRoleByField(field: string, value?: Array<number|string>, lean = true) {
let searchObj = {};
if(field != 'all') {
searchObj[field] = {
$in: value
};
}
//.select('uid tel username')
const user = await RoleModel.find(searchObj).lean(lean);
return user;
}
}
export const RoleModel = getModelForClass(Role);

View File

@@ -87,6 +87,18 @@ export default class User extends BaseModel {
const user = await UserModel.findOne({ uid }).select('uid tel').lean(lean);
return user;
}
public static async findUserByField(field: string, value?: Array<number|string>, lean = true) {
let searchObj = {};
if(field != 'all') {
searchObj[field] = {
$in: value
};
}
const user = await UserModel.find(searchObj).select('uid tel username').lean(lean);
return user;
}
}
export const UserModel = getModelForClass(User);

View File

@@ -8,24 +8,35 @@ on:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: '0 2 * * *'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
node-version: [8.x]
node-version: [8]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v2
- name: Checkout Git Source
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm i -g npminstall && npminstall
- run: npm run ci
env:
CI: true
- name: Install Dependencies
run: npm i -g npminstall && npminstall
- name: Continuous Integration
run: npm run ci
- name: Code Coverage
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}

File diff suppressed because it is too large Load Diff