✨ feat(gvg): 准备期:千机阁以及获取物品
This commit is contained in:
@@ -1,20 +1,23 @@
|
||||
import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus";
|
||||
import { GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_JOB, STATUS } from "../../../consts";
|
||||
import { BATTLE_FEAT_ID, DATA_NAME, GVG_ACTIVE_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, LEAGUE_MANAGE_TYPE, STATUS } from "../../../consts";
|
||||
import { GVGLeagueModel } from "../../../db/GVGLeague";
|
||||
import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare";
|
||||
import { GVGMainData, LeagueDistributeInfo, LeagueMemberDistributeInfo, LeagueMemberListInfo } from "../../../domain/gvgField/returnData";
|
||||
import { resResult } from "../../../pubUtils/util";
|
||||
import { getGVGConfig, getGVGPeriodData, getGVGServerType } from "../../../services/gvg/gvgService";
|
||||
import { autoCreateLeague, checkCanChooseJob, checkCanPrepare, getMyAuth } from "../../../services/gvg/gvgTeamService";
|
||||
import { autoCreateLeague, checkCanChooseJob, checkCanPrepare, checkLeagueAuth, getMyAuth } from "../../../services/gvg/gvgTeamService";
|
||||
import { getAllServerName } from "../../../services/redisService";
|
||||
import { Distribute, GVGUserDataModel } from "../../../db/GVGUserData";
|
||||
import { GVGUserItemModel } from "../../../db/GVGUserItem";
|
||||
import { GVGUserTaskModel } from "../../../db/GVGUserTask";
|
||||
import { GVG } from "../../../pubUtils/dicParam";
|
||||
import { RoleModel } from "../../../db/Role";
|
||||
import { calProduce } from "../../../services/gvg/gvgPrepareService";
|
||||
import { nowSeconds } from "../../../pubUtils/timeUtil";
|
||||
import { GVGUserDailyDistributeModel } from "../../../db/GVGUserDailyDistribute";
|
||||
import { addGVGActive, calProduce, checkPreTech, checkTechIsIng } from "../../../services/gvg/gvgPrepareService";
|
||||
import { GVGUserDailyDataModel } from "../../../db/GVGUserDailyData";
|
||||
import { gameData } from "../../../pubUtils/data";
|
||||
import { lockLeagueData } from "../../../services/redLockService";
|
||||
import { addGVGReward, handleGVGCost } from "../../../services/gvg/gvgItemService";
|
||||
import { RewardInter } from "../../../pubUtils/interface";
|
||||
|
||||
export default function (app: Application) {
|
||||
new HandlerService(app, {});
|
||||
@@ -146,7 +149,7 @@ export class GVGHandler {
|
||||
result.push(disObj)
|
||||
}
|
||||
|
||||
const myDistribute = await GVGUserDailyDistributeModel.findByRole(configId, myLeague.leagueCode, roleId);
|
||||
const myDistribute = await GVGUserDailyDataModel.findByRole(configId, myLeague.leagueCode, roleId);
|
||||
|
||||
return resResult(STATUS.SUCCESS, {
|
||||
myDistribute: {
|
||||
@@ -159,9 +162,150 @@ export class GVGHandler {
|
||||
});
|
||||
}
|
||||
|
||||
// 千机阁数据
|
||||
async getTech(msg: {}, session: BackendSession) {
|
||||
const roleId = session.get('roleId');
|
||||
const guildCode = session.get('guildCode');
|
||||
|
||||
async test(msg: { }, session: BackendSession) {
|
||||
const time = getGVGConfig();
|
||||
return resResult(STATUS.SUCCESS, { time });
|
||||
let { configId, period } = getGVGPeriodData();
|
||||
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||
|
||||
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||
const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
||||
|
||||
return resResult(STATUS.SUCCESS, {
|
||||
activeTech: leaguePrepare?.activeTech||[],
|
||||
queue: leaguePrepare?.techQueue||[]
|
||||
});
|
||||
}
|
||||
|
||||
// 千机阁解锁
|
||||
async unlockTech(msg: { techId: number }, session: BackendSession) {
|
||||
const roleId = session.get('roleId');
|
||||
const guildCode = session.get('guildCode');
|
||||
const { techId } = msg;
|
||||
|
||||
let { configId, period } = getGVGPeriodData();
|
||||
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||
|
||||
const dicTech = gameData.gvgTech.get(techId);
|
||||
if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||||
|
||||
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||
|
||||
// 权限
|
||||
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.UNLOCK_TECH);
|
||||
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
|
||||
|
||||
// 并发锁
|
||||
let res: any = await lockLeagueData(DATA_NAME.LEAGUE_TECH, myLeague.leagueCode);//加锁
|
||||
if (!!res.err) return resResult(STATUS.REDLOCK_ERR);
|
||||
|
||||
let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
||||
if(!leaguePrepare || leaguePrepare.lv < dicTech.levelLimit) {
|
||||
res.releaseCallback();
|
||||
return resResult(STATUS.GVG_TECH_LV_NOT_ENOUGH);
|
||||
}
|
||||
|
||||
if(checkTechIsIng(techId, leaguePrepare?.activeTech||[], leaguePrepare?.techQueue||[])) {
|
||||
res.releaseCallback();
|
||||
return resResult(STATUS.GVG_TECH_HAS_UNLOCKED);
|
||||
}
|
||||
|
||||
if(!checkPreTech(techId, leaguePrepare?.activeTech||[], leaguePrepare?.techQueue||[])) {
|
||||
res.releaseCallback();
|
||||
return resResult(STATUS.GVG_TECH_PRE_POSITION_NOT_UNLOCK);
|
||||
}
|
||||
|
||||
leaguePrepare = await GVGLeaguePrepareModel.unlockTech(configId, myLeague.leagueCode, techId, dicTech.consume);
|
||||
if(!leaguePrepare) {
|
||||
res.releaseCallback();
|
||||
return resResult(STATUS.GVG_TECH_QUEUECNT_MAX);
|
||||
}
|
||||
|
||||
res.releaseCallback();
|
||||
return resResult(STATUS.SUCCESS, {
|
||||
queue: leaguePrepare?.techQueue||[]
|
||||
});
|
||||
}
|
||||
|
||||
// 千机阁解锁
|
||||
async activate(msg: { techId: number, battleFeats: number }, session: BackendSession) {
|
||||
const roleId = session.get('roleId');
|
||||
const guildCode = session.get('guildCode');
|
||||
const sid = session.get('sid');
|
||||
const { techId, battleFeats } = msg;
|
||||
|
||||
let { configId, period } = getGVGPeriodData();
|
||||
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
|
||||
|
||||
const dicTech = gameData.gvgTech.get(techId);
|
||||
if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||||
|
||||
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||
|
||||
// 权限
|
||||
const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ACTIVATE_TECH);
|
||||
if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH);
|
||||
|
||||
let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode);
|
||||
if(!checkTechIsIng(techId, [], leaguePrepare?.techQueue||[])) {
|
||||
return resResult(STATUS.GVG_TECH_NOT_QUEUE);
|
||||
}
|
||||
|
||||
// 扣战功
|
||||
const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: BATTLE_FEAT_ID, count: battleFeats }], [], ITEM_CHANGE_REASON.GVG_ACTIVE_TECH);
|
||||
if(!costResult) return resResult(STATUS.GVG_BATTLE_FEAT_NOT_ENOUGH);
|
||||
|
||||
leaguePrepare = await GVGLeaguePrepareModel.addProgress(configId, myLeague.leagueCode, techId, battleFeats);
|
||||
if(!leaguePrepare) {
|
||||
return resResult(STATUS.GVG_TECH_NOT_QUEUE);
|
||||
}
|
||||
let curQueue = leaguePrepare.techQueue.find(cur => cur.id == techId);
|
||||
if(curQueue.progress >= curQueue.maxProgress) {
|
||||
leaguePrepare = await GVGLeaguePrepareModel.activate(configId, myLeague.leagueCode, techId);
|
||||
}
|
||||
|
||||
// 添加 活跃
|
||||
let active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.TECH_ACTIVATE);
|
||||
|
||||
return resResult(STATUS.SUCCESS, {
|
||||
active,
|
||||
activeTech: leaguePrepare?.activeTech||[],
|
||||
queue: leaguePrepare?.techQueue||[]
|
||||
});
|
||||
}
|
||||
|
||||
// 获取道具
|
||||
async debugAddLeagueItem(msg: { id: number, count: number }, session: BackendSession) {
|
||||
const roleId = session.get('roleId');
|
||||
const roleName = session.get('roleName');
|
||||
const sid = session.get('sid');
|
||||
const guildCode = session.get('guildCode');
|
||||
const { id, count } = msg;
|
||||
let dicGVGItem = gameData.gvgItem.get(id);
|
||||
if(!dicGVGItem) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||||
|
||||
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||
const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, [{ id, count }], [], ITEM_CHANGE_REASON.DEBUG);
|
||||
|
||||
return resResult(STATUS.SUCCESS, { leagueGoods });
|
||||
}
|
||||
|
||||
async debugHandleCost(msg: { items: RewardInter[], leagueItems: RewardInter[] }, session: BackendSession) {
|
||||
const roleId = session.get('roleId');
|
||||
const guildCode = session.get('guildCode');
|
||||
const sid = session.get('sid');
|
||||
const { items, leagueItems } = msg;
|
||||
|
||||
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
|
||||
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||
|
||||
const result = await handleGVGCost(roleId, myLeague.leagueCode, sid, leagueItems, items, ITEM_CHANGE_REASON.DEBUG);
|
||||
return resResult(STATUS.SUCCESS, { result });
|
||||
}
|
||||
}
|
||||
@@ -211,8 +211,6 @@ export class GVGManageHandler {
|
||||
let data = new LeagueGuildInfo(guild, serverNames);
|
||||
let hasInvited = !!invitations.find(cur => cur.guildCode == guild.code);
|
||||
data.setHasInvited(hasInvited);
|
||||
// TODO
|
||||
// data.setActive
|
||||
return data
|
||||
});
|
||||
|
||||
@@ -319,10 +317,23 @@ export class GVGManageHandler {
|
||||
const league = await GVGLeagueModel.findByCode(targetLeagueCode);
|
||||
if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
|
||||
|
||||
let { configId } = getGVGPeriodData();
|
||||
const guilds = await GuildModel.findByCodes(league.guildCodes);
|
||||
const members = league.members||[];
|
||||
let roleIds = members.map(member => member.roleId);
|
||||
const serverNames = await getAllServerName();
|
||||
const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds);
|
||||
const result = guilds.map(guild => {
|
||||
return new LeagueGuildInfo(guild, serverNames)
|
||||
let obj = new LeagueGuildInfo(guild, serverNames);
|
||||
let active = userdatas.reduce((pre, userdata) => {
|
||||
let member = members.find(cur => cur.roleId == userdata.roleId);
|
||||
if(member && member.guildCode == guild.code) {
|
||||
return pre + userdata.active;
|
||||
}
|
||||
return pre;
|
||||
}, 0);
|
||||
obj.setActive(active);
|
||||
return obj;
|
||||
});
|
||||
|
||||
// 返回
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { isArray, isBoolean, isNumber, isString } from "underscore";
|
||||
import { BLOCK_OPEATE, DEBUG_MAGIC_WORD, GM_MAIL_TYPE, GUILD_AUTH, GUILD_STRUCTURE, LEAGUE_JOB, LINEUP_NUM, MSG_TYPE } from "../consts";
|
||||
import { GVG } from "../pubUtils/dicParam";
|
||||
import { pvpEndParamInter } from "../pubUtils/interface";
|
||||
import { isDevelopEnv } from "./utilService";
|
||||
|
||||
@@ -1229,7 +1230,11 @@ export function checkRouteParam(route: string, msg: any) {
|
||||
if(msg.job != LEAGUE_JOB.FIGHTER && msg.job != LEAGUE_JOB.PRODUCER) return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case "guild.gvgHandler.unlockTech":
|
||||
{
|
||||
if(!isNumber(msg.techId)) return false;
|
||||
break;
|
||||
}
|
||||
case "order.orderHandler.applyOrder":
|
||||
{
|
||||
let { productID, payType, activityId, paramStr, useVoucher } = msg;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { GVG_RETURN_ITEM_TYPE, ITEM_CHANGE_REASON, LEAGUE_ITEM_REFRESH_TYPE, PUSH_ROUTE } from "../../consts";
|
||||
import { GVGUserItemModel } from "../../db/GVGUserItem";
|
||||
import { gameData } from "../../pubUtils/data";
|
||||
import { RewardInter } from "../../pubUtils/interface";
|
||||
import { DAY_TO_SECOND, getZeroPoint } from "../../pubUtils/timeUtil";
|
||||
import { getFutureTime } from "../gmService";
|
||||
import { sendMessageToUserWithSuc } from "../pushService";
|
||||
import { addItems, handleCost } from "../role/rewardService";
|
||||
import { getGVGConfig } from "./gvgService";
|
||||
|
||||
/**
|
||||
* 获取道具(必须在guild进程下使用)
|
||||
* @param roleId
|
||||
* @param roleName
|
||||
* @param leagueCode
|
||||
* @param sid
|
||||
* @param leagueItems GVG内专用道具
|
||||
* @param items 普通道具
|
||||
* @param reason
|
||||
* @returns
|
||||
*/
|
||||
export async function addGVGReward(roleId: string, roleName: string, leagueCode: string, sid: string, leagueItems: RewardInter[], items: RewardInter[], reason: ITEM_CHANGE_REASON) {
|
||||
let returnGoods: { id: number, count: number, itemType: number }[] = [], pushGoods: { id: number, count: number, expireTime: number }[] = [];
|
||||
let { configId } = getGVGConfig();
|
||||
if(items.length > 0) {
|
||||
const goods = await addItems(roleId, roleName, sid, items, reason);
|
||||
for(let { id, count } of goods) {
|
||||
returnGoods.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.NORMAL_ITEM });
|
||||
}
|
||||
}
|
||||
for(let { id, count } of leagueItems) {
|
||||
let dicItem = gameData.gvgItem.get(id);
|
||||
if(!dicItem) continue;
|
||||
let item = await GVGUserItemModel.increaseItem(configId, leagueCode, roleId, id, count, getExpireTime(dicItem.refreshType));
|
||||
returnGoods.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.GVG_ITEM });
|
||||
pushGoods.push({ id, count: item.count, expireTime: item.expireTime });
|
||||
}
|
||||
if(pushGoods.length > 0) {
|
||||
await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.LEAGUE_ITEM_UPDATE, { goods: pushGoods }, sid);
|
||||
}
|
||||
return returnGoods;
|
||||
}
|
||||
|
||||
function getExpireTime(refreshType: number) {
|
||||
if(refreshType == LEAGUE_ITEM_REFRESH_TYPE.DAILY) {
|
||||
return getZeroPoint() + DAY_TO_SECOND;
|
||||
}
|
||||
return getFutureTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 消耗道具
|
||||
* @param roleId
|
||||
* @param leagueCode
|
||||
* @param sid
|
||||
* @param leagueItems GVG内专用道具
|
||||
* @param items 普通背包道具
|
||||
* @param reason
|
||||
* @returns
|
||||
*/
|
||||
export async function handleGVGCost(roleId: string, leagueCode: string, sid: string, leagueItems: RewardInter[], items: RewardInter[], reason: ITEM_CHANGE_REASON) {
|
||||
let { configId } = getGVGConfig();
|
||||
// 检查本地道具数量
|
||||
const curItems = await GVGUserItemModel.findByRoleAndIds(configId, leagueCode, roleId, leagueItems.map(cur => cur.id));
|
||||
for(let { id, count } of leagueItems) {
|
||||
let curItem = curItems.find(cur => cur.id == id);
|
||||
if(!curItem || curItem.count < count) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const itemResult = await handleCost(roleId, sid, items, reason);
|
||||
if(!itemResult) return false;
|
||||
|
||||
const decreaseResult = await GVGUserItemModel.decreaseItem(configId, leagueCode, roleId, leagueItems);
|
||||
return decreaseResult;
|
||||
}
|
||||
@@ -1,5 +1,55 @@
|
||||
import { GVG_ACTIVE_TYPE } from "../../consts";
|
||||
import { Tech } from "../../db/GVGLeaguePrepare";
|
||||
import { GVGUserDailyDataModel } from "../../db/GVGUserDailyData";
|
||||
import { GVGUserDataModel } from "../../db/GVGUserData";
|
||||
import { gameData } from "../../pubUtils/data";
|
||||
import { getGVGConfig } from "./gvgService";
|
||||
|
||||
export function checkPreTech(techId: number, activeQueue: number[], techQueue: Tech[]) {
|
||||
const dicTech = gameData.gvgTech.get(techId);
|
||||
if(!dicTech) return false;
|
||||
|
||||
let hasOrUnlock = dicTech.prepositionId.length == 0;
|
||||
for(let andArr of dicTech.prepositionId) { // or关系
|
||||
let hasAndUnlock = true;
|
||||
for(let id of andArr) { // and关系
|
||||
if(!checkTechIsIng(id, activeQueue, techQueue)) {
|
||||
hasAndUnlock = false; break;
|
||||
}
|
||||
}
|
||||
if(hasAndUnlock) hasOrUnlock = true;
|
||||
}
|
||||
return hasOrUnlock;
|
||||
}
|
||||
|
||||
export function checkTechIsIng(techId: number, activeQueue: number[], techQueue: Tech[]) {
|
||||
return techQueue.findIndex(cur => cur.id == techId) != -1 || activeQueue.indexOf(techId) != -1
|
||||
}
|
||||
|
||||
export function calProduce(obj: { food: number, mineral: number, wood: number }) {
|
||||
let { food = 0, mineral = 0, wood = 0 } = obj||{};
|
||||
return food + mineral + wood;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得活跃
|
||||
* @param leagueCode
|
||||
* @param roleId
|
||||
* @param type GVG_ACTIVE_TYPE
|
||||
* @returns
|
||||
*/
|
||||
export async function addGVGActive(leagueCode: string, roleId: string, type: GVG_ACTIVE_TYPE) {
|
||||
let { configId } = getGVGConfig();
|
||||
|
||||
let add = gameData.gvgActive.get(type)||0;
|
||||
if(type == GVG_ACTIVE_TYPE.TECH_ACTIVATE) {
|
||||
let check = await GVGUserDailyDataModel.checkGetTechActive(configId, leagueCode, roleId);
|
||||
if(!check) {
|
||||
await GVGUserDailyDataModel.setHasGetTechActive(configId, leagueCode, roleId);
|
||||
} else {
|
||||
add = 0;
|
||||
}
|
||||
}
|
||||
let result = await GVGUserDataModel.addActive(configId, leagueCode, roleId, type, add);
|
||||
return result.active;
|
||||
}
|
||||
@@ -69,6 +69,10 @@ export async function setGVGConfig(config?: GVGConfigType) {
|
||||
pinus.app.set('gvgScheduleTime', config.scheduleTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的赛期id
|
||||
* @returns
|
||||
*/
|
||||
export function getGVGConfig() {
|
||||
let configId = pinus.app.get('gvgConfigId');
|
||||
let teamTime = pinus.app.get('gvgTeamTime');
|
||||
|
||||
@@ -197,13 +197,16 @@ function getAuthFromManageType(type: LEAGUE_MANAGE_TYPE) {
|
||||
return [LEAGUE_AUTH.SUB_LEADER];
|
||||
case LEAGUE_MANAGE_TYPE.SET_INFO:
|
||||
case LEAGUE_MANAGE_TYPE.SEND_MAIL:
|
||||
case LEAGUE_MANAGE_TYPE.UNLOCK_TECH:
|
||||
return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER];
|
||||
case LEAGUE_MANAGE_TYPE.ACTIVATE_TECH:
|
||||
return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER, LEAGUE_AUTH.MEMBER];
|
||||
}
|
||||
}
|
||||
|
||||
export async function memberJoinGuildToLeague(guild: GuildType, role: RoleType) {
|
||||
if(!guild.leagueCode) return;
|
||||
let league = await GVGLeagueModel.joinMember(guild.leagueCode, role.roleId, role.ce);
|
||||
let league = await GVGLeagueModel.joinMember(guild.leagueCode, guild.code, role.roleId, role.ce);
|
||||
// TODO redis联军更新
|
||||
console.log(league);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,13 @@ export async function lockData(serverId: number, dataName: string, id: string )
|
||||
return await lock(lockKey);
|
||||
}
|
||||
|
||||
export async function lockLeagueData(dataName: string, leagueCode: string) {
|
||||
let key = dataName+'_'+ leagueCode;
|
||||
let lockKey = 'locks:' + key;
|
||||
console.log(' lockKey = '+ lockKey);
|
||||
return await lock(lockKey);
|
||||
}
|
||||
|
||||
export async function lockDataWithNoParam(dataName: string) {
|
||||
let key = `${dataName}`;
|
||||
return await lock(key);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
'development': {
|
||||
'mongo': 'mongodb://127.0.0.1/zyz',
|
||||
'mongo': 'mongodb://127.0.0.1/zyz?replicaSet=rs0',
|
||||
'gmmongo': 'mongodb://127.0.0.1/zyzgm',
|
||||
'redis': '127.0.0.1',
|
||||
'redispw': 'zyz_2020'
|
||||
|
||||
Reference in New Issue
Block a user