lrf vor 1 Jahr
Ursprung
Commit
d499e7ce05

+ 50 - 1
README.md

@@ -12,4 +12,53 @@
 |注解名|类型|说明|
 |注解名|类型|说明|
 |:-:|:-:|:-:|
 |:-:|:-:|:-:|
 |before|string|获取原数据的函数名;该service下的函数名,纯自定义|
 |before|string|获取原数据的函数名;该service下的函数名,纯自定义|
-|after|string|获取新数据的函数名;该service下的函数名,纯自定义|
+|after|string|获取新数据的函数名;该service下的函数名,纯自定义|
+
+## 3.mongodb开启副本集
+* 1.conf配置文件中添加
+```
+replication:
+  replSetName: rs0
+```
+* 2.重启服务,进入mongodb控制台
+```rsconf = {
+   _id: "rs0",
+   members: [
+     {
+       _id: 0,
+       host: "localhost:27018"
+     },
+     {
+       _id: 1,
+       host: "localhost:27019"
+     },
+     {
+       _id: 2,
+       host: "localhost:27020"
+     }
+   ]
+}
+
+rs.initiate( rsconf )
+```
+* 3.重置副本集
+```
+1.停止所有实例,使用非主从复制模式启动,注释 replication 设置
+2.sh进入每个数据库后删除local库
+  use local
+  db.dropDatabase()
+3.停止所有实例,使用主从复制模式启动,打开注释
+4.初始化配置,sh连接1个库
+  rs.initate() 不输入参数
+  conf=rs.conf()
+  conf.members[0].host='xxx.xxx.xxx.xxx:xxx'
+  rs.reconfig(conf)
+  rs.status() 查看配置
+5.添加从节点
+  从节点: rs.add({ _id: x, host: 'xxx.xxx.xxx.xxx:xxx' })
+  选举节点: rs.add({ _id: x, host: 'xxx.xxx.xxx.xxx:xxx', priority: 1, arbiterOnly: true })
+  隐藏节点: 添加 hidden: true
+  延迟节点: slaveDelay: int(s秒)
+  非选举节点: priority: 0
+  仲裁节点: rs.addArb('xxx.xxx.xxx.xxx:xxx')
+```

+ 1 - 0
src/config/config.prod.ts

@@ -27,6 +27,7 @@ export default {
       password: 'NAjqFz_7tS2DkdpU7p*x',
       password: 'NAjqFz_7tS2DkdpU7p*x',
     },
     },
   },
   },
+  dbName: projectDB,
   mongoose: {
   mongoose: {
     dataSource: {
     dataSource: {
       default: {
       default: {

+ 7 - 4
src/controller/system/config.controller.ts

@@ -1,20 +1,23 @@
 import { Body, Controller, Del, Get, Inject, Param, Post } from '@midwayjs/decorator';
 import { Body, Controller, Del, Get, Inject, Param, Post } from '@midwayjs/decorator';
-import { BaseController, FrameworkErrorEnum, ServiceError } from 'free-midway-component';
+import { BaseController, ServiceError } from 'free-midway-component';
 import { ConfigService } from '../../service/system/config.service';
 import { ConfigService } from '../../service/system/config.service';
 import { CDTO_config, CVO_config, FVO_config, UDTO_config, UVAO_config } from '../../interface/system/config.interface';
 import { CDTO_config, CVO_config, FVO_config, UDTO_config, UVAO_config } from '../../interface/system/config.interface';
 import { ApiResponse, ApiTags, ApiQuery } from '@midwayjs/swagger';
 import { ApiResponse, ApiTags, ApiQuery } from '@midwayjs/swagger';
 import { Validate } from '@midwayjs/validate';
 import { Validate } from '@midwayjs/validate';
+import { I18nService } from '../../service/i18n.service';
+import { FrameErrorEnum } from '../../error/frame.error';
 @ApiTags(['设置表'])
 @ApiTags(['设置表'])
 @Controller('/config')
 @Controller('/config')
 export class ConfigController extends BaseController {
 export class ConfigController extends BaseController {
   @Inject()
   @Inject()
   service: ConfigService;
   service: ConfigService;
-
+  @Inject()
+  i18n: I18nService;
   @Post('/')
   @Post('/')
   @Validate()
   @Validate()
   @ApiResponse({ type: CVO_config })
   @ApiResponse({ type: CVO_config })
   async create(@Body() data: CDTO_config) {
   async create(@Body() data: CDTO_config) {
-    throw new ServiceError('功能暂不开放', FrameworkErrorEnum.SERVICE_FAULT);
+    throw new ServiceError(this.i18n.translateError(FrameErrorEnum.SERVICE_CANT_USE), FrameErrorEnum.SERVICE_CANT_USE);
     // const dbData = await this.service.create(data);
     // const dbData = await this.service.create(data);
     // const result = new CVO_config(dbData);
     // const result = new CVO_config(dbData);
     // return result;
     // return result;
@@ -31,7 +34,7 @@ export class ConfigController extends BaseController {
   @Get('/:id')
   @Get('/:id')
   @ApiResponse({ type: FVO_config })
   @ApiResponse({ type: FVO_config })
   async fetch(@Param('id') id: string) {
   async fetch(@Param('id') id: string) {
-    throw new ServiceError('功能暂不开放', FrameworkErrorEnum.SERVICE_FAULT);
+    throw new ServiceError(this.i18n.translateError(FrameErrorEnum.SERVICE_CANT_USE), FrameErrorEnum.SERVICE_CANT_USE);
     // const data = await this.service.fetch(id);
     // const data = await this.service.fetch(id);
     // const result = new FVO_config(data);
     // const result = new FVO_config(data);
     // return result;
     // return result;

+ 1 - 2
src/controller/system/role.controller.ts

@@ -1,4 +1,4 @@
-import { Body, Controller, Del, Get, Inject, Param, Post, Query, sleep } from '@midwayjs/decorator';
+import { Body, Controller, Del, Get, Inject, Param, Post, Query } from '@midwayjs/decorator';
 import { BaseController } from 'free-midway-component';
 import { BaseController } from 'free-midway-component';
 import { RoleService } from '../../service/system/role.service';
 import { RoleService } from '../../service/system/role.service';
 import { CDTO_role, CVO_role, FVO_role, QDTO_role, QVO_role, UDTO_role, UVAO_role } from '../../interface/system/role.interface';
 import { CDTO_role, CVO_role, FVO_role, QDTO_role, QVO_role, UDTO_role, UVAO_role } from '../../interface/system/role.interface';
@@ -20,7 +20,6 @@ export class RoleController extends BaseController {
   @Validate()
   @Validate()
   @ApiResponse({ type: CVO_role })
   @ApiResponse({ type: CVO_role })
   async create(@Body() data: CDTO_role) {
   async create(@Body() data: CDTO_role) {
-    await sleep(5000)
     const dbData = await this.service.create(data);
     const dbData = await this.service.create(data);
     const result = new CVO_role(dbData);
     const result = new CVO_role(dbData);
     return result;
     return result;

+ 5 - 3
src/decorator/checkPermissionCode.ts

@@ -1,7 +1,9 @@
 import { JoinPoint, MidwayDecoratorService, REQUEST_OBJ_CTX_KEY, createCustomMethodDecorator } from '@midwayjs/core';
 import { JoinPoint, MidwayDecoratorService, REQUEST_OBJ_CTX_KEY, createCustomMethodDecorator } from '@midwayjs/core';
-import { FrameworkErrorEnum, ServiceError } from 'free-midway-component';
+import { ServiceError } from 'free-midway-component';
 import { get } from 'lodash';
 import { get } from 'lodash';
 import { RoleService } from '../service/system/role.service';
 import { RoleService } from '../service/system/role.service';
+import { I18nService } from '../service/i18n.service';
+import { FrameErrorEnum } from '../error/frame.error';
 export const CHECKPERMISSIONCODE_KEY = 'decorator:check_permission_code';
 export const CHECKPERMISSIONCODE_KEY = 'decorator:check_permission_code';
 export const checkPermissionCode = options => {
 export const checkPermissionCode = options => {
   return createCustomMethodDecorator(CHECKPERMISSIONCODE_KEY, options);
   return createCustomMethodDecorator(CHECKPERMISSIONCODE_KEY, options);
@@ -31,8 +33,8 @@ export const CheckPermissionCodeInit = (decoratorService: MidwayDecoratorService
             let roleMenus = await roleService.getUserMenus(true);
             let roleMenus = await roleService.getUserMenus(true);
             roleMenus = resetRoleMenus(roleMenus);
             roleMenus = resetRoleMenus(roleMenus);
             if (!roleMenus.includes(roleCode)) {
             if (!roleMenus.includes(roleCode)) {
-              console.log(options);
-              throw new ServiceError('您没有当前功能的权限!', FrameworkErrorEnum.SERVICE_FAULT);
+              const i18n = await ctx.requestContext.getAsync(I18nService);
+              throw new ServiceError(i18n.translateError(FrameErrorEnum.NO_PERMISSION), FrameErrorEnum.NO_PERMISSION);
             }
             }
             const result = await joinPoint.proceed(...joinPoint.args);
             const result = await joinPoint.proceed(...joinPoint.args);
             return result;
             return result;

+ 16 - 0
src/error/frame.error.ts

@@ -0,0 +1,16 @@
+import { registerErrorCode } from '@midwayjs/core';
+
+export enum ErrorCode {
+  SERVICE_ERROR = '400',
+  SERVICE_CANT_USE = '400-1',
+
+  NO_PERMISSION = '401',
+  USER_NOT_FOUND = '401-1',
+  BAD_PASSWORD = '401-2',
+  NOT_LOGIN = '401-3',
+  ACCOUNT_HAS_EXPIRED = '401-4',
+  ACCOUNT_LOGGED_IN_ELESWHERE = '401-5',
+  USER_IS_DISABLED = '401-6',
+  ROLE_IS_DISABLED = '401-7',
+}
+export const FrameErrorEnum = registerErrorCode('FrameError', ErrorCode);

+ 15 - 9
src/locales/en_us/errors.ts

@@ -1,4 +1,4 @@
-const codes ={
+const codes = {
   '-1': 'unknown error',
   '-1': 'unknown error',
   '-2': 'need params',
   '-2': 'need params',
   '-20': 'params error',
   '-20': 'params error',
@@ -10,18 +10,24 @@ const codes ={
   '-50': 'bad args',
   '-50': 'bad args',
   '-10': 'data not found',
   '-10': 'data not found',
   '-100': 'service fault',
   '-100': 'service fault',
-  '-101': 'No login information detected, please log in again',
-  '-101-1': 'Account login has expired, please log in again!',
-  '-101-2': 'This account has been logged in elsewhere, please log in again!',
-  '-102': 'bad password',
   '-500': 'request falut',
   '-500': 'request falut',
   '-3000': 'ElasticSearch error',
   '-3000': 'ElasticSearch error',
   '-3001': 'ElasticSearch error, index not found',
   '-3001': 'ElasticSearch error, index not found',
-}
-const errCodes = {}
-const prefix = 'SERVICEERROR_'
+  '400': 'Service encountered an error',
+  '400-1': 'Function temporarily unavailable',
+  '401': 'You do not have permission for the current function!',
+  '401-1': 'User not found',
+  '401-2': 'Password error',
+  '401-3': 'No login information detected, please log in again!',
+  '401-4': 'Account login has expired, please log in again!',
+  '401-5': 'This account has been logged in elsewhere, please log in again!',
+  '401-6': 'The user has been disabled',
+  '401-7': 'Users in the current role are unable to use',
+};
+const errCodes = {};
+const prefix = 'FRAMEERROR_';
 for (const key in codes) {
 for (const key in codes) {
-  errCodes[`${prefix}${key}`] = codes[key]
+  errCodes[`${prefix}${key}`] = codes[key];
 }
 }
 export default {
 export default {
   test: 'error language is: {locale}',
   test: 'error language is: {locale}',

+ 15 - 10
src/locales/zh_cn/errors.ts

@@ -1,4 +1,4 @@
-const codes ={
+const codes = {
   '-1': '未知错误',
   '-1': '未知错误',
   '-2': '缺少params',
   '-2': '缺少params',
   '-20': 'params错误',
   '-20': 'params错误',
@@ -10,21 +10,26 @@ const codes ={
   '-50': '参数错误',
   '-50': '参数错误',
   '-10': '未找到数据',
   '-10': '未找到数据',
   '-100': '服务发生错误',
   '-100': '服务发生错误',
-  '-101': '未检测到登录信息,请重新登录!',
-  '-101-1': '账号登录已失效,请重新登录!',
-  '-101-2': '本账号已在其他地方登录,请重新登录!',
-  '-102': '密码错误',
   '-500': '请求错误',
   '-500': '请求错误',
   '-3000': 'ElasticSearch发生错误',
   '-3000': 'ElasticSearch发生错误',
   '-3001': 'ElasticSearch发生错误,未找到索引',
   '-3001': 'ElasticSearch发生错误,未找到索引',
-}
-const errCodes = {}
-const prefix = 'SERVICEERROR_'
+  '400': '服务发生错误',
+  '400-1': '功能暂不开放',
+  '401': '您没有当前功能的权限!',
+  '401-1': '未找到用户',
+  '401-2': '密码错误',
+  '401-3': '未检测到登录信息,请重新登录!',
+  '401-4': '账号登录已失效,请重新登录!',
+  '401-5': '本账号已在其他地方登录,请重新登录!',
+  '401-6': '该用户已被禁用',
+  '401-7': '当前角色下的用户无法使用',
+};
+const errCodes = {};
+const prefix = 'FRAMEERROR_';
 for (const key in codes) {
 for (const key in codes) {
-  errCodes[`${prefix}${key}`] = codes[key]
+  errCodes[`${prefix}${key}`] = codes[key];
 }
 }
 
 
-
 export default {
 export default {
   locale: '错误测试: {locale}',
   locale: '错误测试: {locale}',
   ...errCodes,
   ...errCodes,

+ 8 - 2
src/service/db.service.ts

@@ -32,7 +32,13 @@ export class DBService {
   @Init()
   @Init()
   async init() {
   async init() {
     const conns = mongoose.connections;
     const conns = mongoose.connections;
-    const conn = conns.find(f => f.name === this.dbName);
+    const conn = conns.find(f => {
+      const str = get(f, '_connectionString') as string;
+      if(!str) return false;
+      const arr = str.split('/')
+      const dbName = last(arr)
+      return dbName === this.dbName;
+    });
     console.log('change stream init');
     console.log('change stream init');
     conn.watch([], { fullDocument: 'updateLookup' }).on('change', async data => {
     conn.watch([], { fullDocument: 'updateLookup' }).on('change', async data => {
       const record_id: string = this.app.getAttr('record_id');
       const record_id: string = this.app.getAttr('record_id');
@@ -100,7 +106,7 @@ export class DBService {
       }
       }
       // 更新记录
       // 更新记录
       await this.dataRecordService.updateOne(record_id, record);
       await this.dataRecordService.updateOne(record_id, record);
-      this.logger.warn('record success')
+      this.logger.warn('record success');
     });
     });
   }
   }
 }
 }

+ 12 - 12
src/service/login.service.ts

@@ -1,5 +1,5 @@
 import { Config, Inject, Provide } from '@midwayjs/core';
 import { Config, Inject, Provide } from '@midwayjs/core';
-import { FrameworkErrorEnum, GetModel, ServiceError } from 'free-midway-component';
+import { GetModel, ServiceError } from 'free-midway-component';
 import { get, isEqual, upperFirst } from 'lodash';
 import { get, isEqual, upperFirst } from 'lodash';
 import { LoginDTO, LoginType, UPwdDTO } from '../interface/login.interface';
 import { LoginDTO, LoginType, UPwdDTO } from '../interface/login.interface';
 import { RoleService } from '../service/system/role.service';
 import { RoleService } from '../service/system/role.service';
@@ -7,11 +7,11 @@ import { RedisService } from '@midwayjs/redis';
 import * as Crypto from 'crypto-js';
 import * as Crypto from 'crypto-js';
 import { Context } from '@midwayjs/koa';
 import { Context } from '@midwayjs/koa';
 import { I18nService } from './i18n.service';
 import { I18nService } from './i18n.service';
+import { FrameErrorEnum } from '../error/frame.error';
 @Provide()
 @Provide()
 export class LoginService {
 export class LoginService {
   @Inject()
   @Inject()
   roleService: RoleService;
   roleService: RoleService;
-
   @Inject()
   @Inject()
   ctx: Context;
   ctx: Context;
   @Config('loginSign')
   @Config('loginSign')
@@ -41,9 +41,9 @@ export class LoginService {
 
 
   async onePointCheck() {
   async onePointCheck() {
     const user = this.ctx.user;
     const user = this.ctx.user;
-    if (!user) throw new ServiceError(this.i18n.translateError(FrameworkErrorEnum.NOT_LOGIN), FrameworkErrorEnum.NOT_LOGIN);
+    if (!user) throw new ServiceError(this.i18n.translateError(FrameErrorEnum.NOT_LOGIN), FrameErrorEnum.NOT_LOGIN);
     const { _id, role, login_code } = user;
     const { _id, role, login_code } = user;
-    if (!login_code) throw new ServiceError(this.i18n.translateError(FrameworkErrorEnum.NOT_LOGIN), FrameworkErrorEnum.NOT_LOGIN);
+    if (!login_code) throw new ServiceError(this.i18n.translateError(FrameErrorEnum.NOT_LOGIN), FrameErrorEnum.NOT_LOGIN);
     // 解密
     // 解密
     const decodeResult = Crypto.AES.decrypt(login_code, this.jwtSecret);
     const decodeResult = Crypto.AES.decrypt(login_code, this.jwtSecret);
     const decode = Crypto.enc.Utf8.stringify(decodeResult).toString();
     const decode = Crypto.enc.Utf8.stringify(decodeResult).toString();
@@ -54,13 +54,13 @@ export class LoginService {
     const rediskey = `${this.loginSign}:${role}:${_id}`;
     const rediskey = `${this.loginSign}:${role}:${_id}`;
     // 取出当前记录在案的 code
     // 取出当前记录在案的 code
     const redisCode = await this.redisService.get(rediskey);
     const redisCode = await this.redisService.get(rediskey);
-    if (!redisCode) throw new ServiceError(this.i18n.translateError(`${FrameworkErrorEnum.NOT_LOGIN}-1`), FrameworkErrorEnum.NOT_LOGIN);
+    if(!redisCode) throw new ServiceError(this.i18n.translateError(`${FrameErrorEnum.ACCOUNT_HAS_EXPIRED}`), FrameErrorEnum.ACCOUNT_HAS_EXPIRED);
     // 判断是否一致
     // 判断是否一致
     if (code === redisCode) {
     if (code === redisCode) {
       // 一致,延时
       // 一致,延时
       await this.redisService.expire(rediskey, this.jwtExpiresIn);
       await this.redisService.expire(rediskey, this.jwtExpiresIn);
     } else {
     } else {
-      throw new ServiceError(this.i18n.translateError(`${FrameworkErrorEnum.NOT_LOGIN}-2`), FrameworkErrorEnum.NOT_LOGIN);
+      throw new ServiceError(this.i18n.translateError(`${FrameErrorEnum.ACCOUNT_LOGGED_IN_ELESWHERE}`), FrameErrorEnum.ACCOUNT_LOGGED_IN_ELESWHERE);
     }
     }
   }
   }
 
 
@@ -73,9 +73,9 @@ export class LoginService {
   async loginByAccount(data: LoginDTO, type: LoginType) {
   async loginByAccount(data: LoginDTO, type: LoginType) {
     const model = GetModel(upperFirst(type));
     const model = GetModel(upperFirst(type));
     const user = await model.findOne({ account: data.account }, '+password').lean();
     const user = await model.findOne({ account: data.account }, '+password').lean();
-    if (!user) throw new ServiceError('未找到用户信息', FrameworkErrorEnum.NOT_FOUND_DATA);
+    if (!user) throw new ServiceError(this.i18n.translateError(FrameErrorEnum.USER_NOT_FOUND), FrameErrorEnum.USER_NOT_FOUND);
     await this.checkAccountCanLogin(user, type);
     await this.checkAccountCanLogin(user, type);
-    if (!isEqual(user.password.secret, data.password)) throw new ServiceError('密码错误', FrameworkErrorEnum.SERVICE_FAULT);
+    if (!isEqual(user.password.secret, data.password)) throw new ServiceError(this.i18n.translateError(FrameErrorEnum.BAD_PASSWORD), FrameErrorEnum.BAD_PASSWORD);
     return user;
     return user;
   }
   }
   /**
   /**
@@ -89,19 +89,19 @@ export class LoginService {
     // 其他用户需要看status是不是'1';
     // 其他用户需要看status是不是'1';
     if (type === 'Admin') {
     if (type === 'Admin') {
       if (get(user, 'is_super') === '1') {
       if (get(user, 'is_super') === '1') {
-        if (get(user, 'is_use') === '1') throw new ServiceError('该用户已被禁用', FrameworkErrorEnum.SERVICE_FAULT);
+        if (get(user, 'is_use') === '1') throw new ServiceError(this.i18n.translateError(FrameErrorEnum.USER_IS_DISABLED), FrameErrorEnum.USER_IS_DISABLED);
       }
       }
     } else {
     } else {
-      if (get(user, 'status') !== '1') throw new ServiceError('该用户已被禁用', FrameworkErrorEnum.SERVICE_FAULT);
+      if (get(user, 'status') !== '1') throw new ServiceError(this.i18n.translateError(FrameErrorEnum.USER_IS_DISABLED), FrameErrorEnum.USER_IS_DISABLED);
       const role = await this.roleService.findOne({ code: type, is_use: '0' });
       const role = await this.roleService.findOne({ code: type, is_use: '0' });
-      if (!role) throw new ServiceError('当前角色下的用户无法使用!', FrameworkErrorEnum.SERVICE_FAULT);
+      if (!role) throw new ServiceError(this.i18n.translateError(FrameErrorEnum.ROLE_IS_DISABLED), FrameErrorEnum.ROLE_IS_DISABLED);
     }
     }
   }
   }
 
 
   async updatePwd(data: UPwdDTO, type: LoginType) {
   async updatePwd(data: UPwdDTO, type: LoginType) {
     const model = GetModel(upperFirst(type));
     const model = GetModel(upperFirst(type));
     const user = await model.findById(data._id);
     const user = await model.findById(data._id);
-    if (!user) new ServiceError('未找到用户信息!', FrameworkErrorEnum.DATA_NOT_FOUND);
+    if (!user) new ServiceError(this.i18n.translateError(FrameErrorEnum.USER_NOT_FOUND), FrameErrorEnum.USER_NOT_FOUND);
     user.password = data.password;
     user.password = data.password;
     await user.save();
     await user.save();
   }
   }

+ 5 - 2
src/service/system/role.service.ts

@@ -7,6 +7,8 @@ import { Menus } from '../../entity/system/menus.entity';
 import { MenusService } from './menus.service';
 import { MenusService } from './menus.service';
 import { flattenDeep, uniq, get, lowerFirst, upperFirst, last } from 'lodash';
 import { flattenDeep, uniq, get, lowerFirst, upperFirst, last } from 'lodash';
 import { Context } from '@midwayjs/koa';
 import { Context } from '@midwayjs/koa';
+import { I18nService } from '../i18n.service';
+import { FrameErrorEnum } from '../../error/frame.error';
 type modelType = ReturnModelType<typeof Role>;
 type modelType = ReturnModelType<typeof Role>;
 @Provide()
 @Provide()
 export class RoleService extends BaseService<modelType> {
 export class RoleService extends BaseService<modelType> {
@@ -14,7 +16,8 @@ export class RoleService extends BaseService<modelType> {
   model: modelType;
   model: modelType;
   @InjectEntityModel(Menus)
   @InjectEntityModel(Menus)
   menusModel: ReturnModelType<typeof Menus>;
   menusModel: ReturnModelType<typeof Menus>;
-
+  @Inject()
+  i18n: I18nService;
   @Inject()
   @Inject()
   menusService: MenusService;
   menusService: MenusService;
   @Inject()
   @Inject()
@@ -35,7 +38,7 @@ export class RoleService extends BaseService<modelType> {
     }
     }
     const roleCode = [lowerFirst(user.role), upperFirst(user.role)];
     const roleCode = [lowerFirst(user.role), upperFirst(user.role)];
     const role = await this.model.findOne({ code: roleCode, is_use: '0' }).lean();
     const role = await this.model.findOne({ code: roleCode, is_use: '0' }).lean();
-    if (!role) throw new ServiceError('当前角色下的用户无法使用!', FrameworkErrorEnum.SERVICE_FAULT);
+    if (!role) throw new ServiceError(this.i18n.translateError(FrameErrorEnum.ROLE_IS_DISABLED), FrameErrorEnum.ROLE_IS_DISABLED);
     const roleMenu = get(role, 'menu', []);
     const roleMenu = get(role, 'menu', []);
     const menu = roleMenu.map(i => {
     const menu = roleMenu.map(i => {
       const arr = i.split('.');
       const arr = i.split('.');