lrf 2 years ago
parent
commit
281aebeca6

+ 10 - 1
package.json

@@ -19,6 +19,14 @@
     "index.d.ts"
   ],
   "license": "MIT",
+  "dependencies": {
+    "@midwayjs/swagger": "^3.7.1",
+    "swagger-ui-dist": "^4.15.2",
+    "@midwayjs/typegoose": "^3.0.0",
+    "@typegoose/typegoose": "^9.0.0",
+    "lodash": "^4.17.21",
+    "mongoose": "^6.0.7"
+  },
   "devDependencies": {
     "@midwayjs/cli": "^2.0.0",
     "@midwayjs/core": "^3.0.0",
@@ -31,6 +39,7 @@
     "jest": "^29.2.2",
     "mwts": "^1.0.5",
     "ts-jest": "^29.0.3",
-    "typescript": "~4.8.0"
+    "typescript": "~4.8.0",
+    "@types/lodash": "^4.14.190"
   }
 }

+ 1 - 4
src/config/config.default.ts

@@ -1,4 +1 @@
-export const customKey = {
-  a: 1,
-  b: 'hello',
-};
+export const config = {};

+ 38 - 6
src/configuration.ts

@@ -1,18 +1,50 @@
-import { Configuration } from '@midwayjs/decorator';
+import { App, Configuration } from '@midwayjs/decorator';
 import * as DefaultConfig from './config/config.default';
 import * as koa from '@midwayjs/koa';
+// api文档
+import * as swagger from '@midwayjs/swagger';
+// 数据库
+import * as typegoose from '@midwayjs/typegoose';
+import * as Typegoose from '@typegoose/typegoose';
+import { ResponseMiddleware } from './middleware/response.middleware';
+import { IMidwayApplication, IMidwayContainer } from '@midwayjs/core';
 @Configuration({
-  namespace: 'book',
-  imports: [koa],
+  namespace: 'free',
+  imports: [
+    koa,
+    typegoose,
+    {
+      component: swagger,
+      enabledEnvironment: ['local'],
+    },
+  ],
   importConfigs: [
     {
       default: DefaultConfig,
     },
   ],
 })
-export class BookConfiguration {
-  async onReady() {
+export class FreeConfiguration {
+  @App()
+  app: koa.Application;
+  getApiUrl() {
+    const path = this.app.getConfig()?.swagger?.swaggerPath;
+    const port = this.app.getConfig()?.koa?.port;
+    if (path)
+      console.log(`api文档: http://127.0.0.1:${port}${path}/index.html`);
+  }
+  async onReady(container: IMidwayContainer, app: IMidwayApplication) {
     // TODO something
-    console.log('component book is ready');
+    app.getMiddleware().insertLast(ResponseMiddleware);
+    Typegoose.setGlobalOptions({
+      schemaOptions: {
+        id: true,
+        toJSON: { getters: true, virtuals: true },
+        toObject: { getters: true, virtuals: true },
+      },
+      options: { allowMixed: Typegoose.Severity.ALLOW },
+    });
+    this.getApiUrl();
+    console.log('free frame is ready');
   }
 }

+ 17 - 0
src/controller/BaseController.ts

@@ -0,0 +1,17 @@
+import { Application, Context } from '@midwayjs/koa';
+import { App, Inject } from '@midwayjs/decorator';
+export abstract class BaseController {
+  @App()
+  app: Application;
+  @Inject()
+  ctx: Context;
+
+  abstract query(...args);
+  abstract fetch(...args);
+  abstract update(...args);
+  abstract updateMany(...args);
+  abstract delete(...args);
+  abstract deleteMany(...args);
+  abstract create(...args);
+  abstract createMany(...args);
+}

+ 33 - 0
src/error/service.error.ts

@@ -0,0 +1,33 @@
+import { MidwayError, registerErrorCode } from '@midwayjs/core';
+
+export enum ErrorCode {
+  /** 未知错误 */
+  UNKNOWN = '-1',
+  /** 缺少地址参数 */
+  NEED_PARAMS = '-2',
+  /** 缺少地址后参数 */
+  NEED_QUERY = '-3',
+  /** 缺少body参数 */
+  NEED_BODY = '-4',
+  /** 缺少参数(函数调用中) */
+  NEED_ARGS = '-5',
+  /** 未找到数据 */
+  NOT_FOUND_DATA = '-10',
+  /** 业务错误 */
+  SERVICE_FAULT = '-100',
+  /** 用户没有登录 */
+  NOT_LOGIN = '-101',
+}
+
+/** 自定义错误枚举数据 */
+export const FrameworkErrorEnum = registerErrorCode('ServiceError', ErrorCode);
+/**
+ * @constructor 自定义异常类
+ * @param {string} str 异常说明
+ * @param {ErrorCode} errcode 错误代码
+ */
+export class ServiceError extends MidwayError {
+  constructor(str: string, errcode: string = ErrorCode.UNKNOWN) {
+    super(str, errcode);
+  }
+}

+ 1 - 2
src/index.ts

@@ -1,2 +1 @@
-export { BookConfiguration as Configuration } from './configuration';
-export * from './service/book.service';
+export { FreeConfiguration as Configuration } from './configuration';

+ 48 - 0
src/interface/SearchBase.ts

@@ -0,0 +1,48 @@
+import _ = require('lodash');
+
+/**
+ * @constructor
+ * 通过object传过来,名称需要匹配Param
+ * @param {Array} like_prop 范围查询字段数组
+ */
+export class SearchBase {
+  constructor({ like_prop = [] }) {
+    this.like_prop = like_prop;
+  }
+  /** 模糊查询字段数组 */
+  like_prop: Array<string>;
+
+  /**
+   * 此处将字段转换为使用的方式
+   */
+  getFilter() {
+    const exclude = ['like_prop'];
+    const keys = Object.keys(this).filter(f => !exclude.includes(f));
+    const result = {};
+    for (const i of keys) {
+      const value = this[i];
+      // 值不存在或者为空字符串,过滤掉
+      if (!value || value === '') continue;
+      if (this.like_prop.includes(i)) {
+        // 处理模糊查询
+        result[i] = new RegExp(value);
+      } else if (i.includes('@')) {
+        // 处理范围查询
+        const arr = i.split('@');
+        const prop = _.head(arr);
+        const pos = _.last(arr);
+        const pd = _.get(result, prop, {});
+        if (pos === 'start') {
+          Object.assign(pd, { $gte: value });
+        } else if (pos === 'end') {
+          Object.assign(pd, { $lte: value });
+        } else continue;
+        result[prop] = pd;
+      } else {
+        // 正常处理
+        result[i] = value;
+      }
+    }
+    return result;
+  }
+}

+ 20 - 0
src/interface/VOBase.ts

@@ -0,0 +1,20 @@
+import _ = require('lodash');
+export class VOBase {
+  constructor(response: object) {
+    this.errcode = _.get(response, 'errcode', 0);
+    this.errmsg = _.get(response, 'errmsg', 'ok');
+    this.details = _.get(response, 'details');
+    this.total = _.get(response, 'total');
+    // 查询列表和只返回结果的区分,根据total决定
+    if (this.total) {
+      this.data = _.get(response, 'data');
+    } else {
+      this.data = response;
+    }
+  }
+  errcode: number;
+  errmsg: string;
+  details?: string;
+  data?: any;
+  total?: number;
+}

+ 0 - 19
src/middleware/book.middleware.ts

@@ -1,19 +0,0 @@
-import { IMiddleware } from '@midwayjs/core';
-import { Middleware } from '@midwayjs/core';
-import { NextFunction, Context } from '@midwayjs/koa';
-@Middleware()
-export default class BookMiddleware
-  implements IMiddleware<Context, NextFunction>
-{
-  resolve() {
-    return async (ctx: Context, next: NextFunction) => {
-      console.log('in book middleware');
-      await next();
-      return 'ok';
-    };
-  }
-
-  static getName() {
-    return 'book_middleware';
-  }
-}

+ 21 - 0
src/middleware/response.middleware.ts

@@ -0,0 +1,21 @@
+import { IMiddleware } from '@midwayjs/core';
+import { Middleware } from '@midwayjs/decorator';
+import { NextFunction, Context } from '@midwayjs/koa';
+import _ = require('lodash');
+import { VOBase } from '../interface/VOBase';
+@Middleware()
+export class ResponseMiddleware implements IMiddleware<Context, NextFunction> {
+  resolve() {
+    return async (ctx: Context, next: NextFunction) => {
+      await next();
+      const response = ctx.response;
+      const body = response.body;
+      const nb = new VOBase(body as object);
+      return nb;
+    };
+  }
+
+  static getName(): string {
+    return 'response';
+  }
+}

+ 137 - 0
src/service/BaseService.ts

@@ -0,0 +1,137 @@
+import { ReturnModelType } from '@typegoose/typegoose';
+import { AnyParamConstructor } from '@typegoose/typegoose/lib/types';
+import { Application, Context } from '@midwayjs/koa';
+import { App, Inject } from '@midwayjs/decorator';
+import _ = require('lodash');
+import { FrameworkErrorEnum, ServiceError } from '../error/service.error';
+/**
+ * Service基类
+ */
+export abstract class BaseService<T extends AnyParamConstructor<any>> {
+  @App()
+  app: Application;
+  @Inject()
+  ctx: Context;
+
+  // 要求继承基类的service,必须给上默认的model
+  abstract model: ReturnModelType<T>;
+
+  /**
+   * 列表查询
+   * @param {object} filter 查询条件
+   * @param {object} pageOptions 分页条件
+   * @param {Boolean} lean 是否使用JavaScript形式数据;false为mongoose的模型实例数据
+   * @returns {Promise<object>} 返回列表
+   */
+  async query(
+    filter: object = {},
+    pageOptions: object = {},
+    lean = true
+  ): Promise<object> {
+    const dup = _.cloneDeep(filter);
+    const data = await this.model.find(dup, {}, { ...pageOptions }).lean(lean);
+    return data;
+  }
+
+  /**
+   * 数据总数查询
+   * @param {object} filter 查询条件
+   * @returns {number} 数据总数
+   */
+  async count(filter: object = {}): Promise<number> {
+    const dup = _.cloneDeep(filter);
+    const total = await this.model.count(dup);
+    return total;
+  }
+
+  /**
+   * 单查询-通过id
+   * @param {string} id 查询对象数据id
+   * @param {boolean} lean 是否使用JavaScript形式数据
+   * @returns {object|undefined}
+   */
+  async fetch(id: string, lean = true): Promise<object | undefined> {
+    const data = await this.model.findById(id).lean(lean);
+    return data;
+  }
+
+  /**
+   * 单修改-通过id
+   * @param {string} id 修改对象数据id
+   * @param {object} body 要修改的内容
+   * @returns {object}
+   */
+  async updateOne(id: string, body: object): Promise<string> {
+    if (!id)
+      throw new ServiceError('缺少查询信息', FrameworkErrorEnum.NEED_PARAMS);
+    const num = await this.model.count({ _id: id });
+    if (num <= 0)
+      throw new ServiceError(
+        '未找到要修改的数据',
+        FrameworkErrorEnum.NOT_FOUND_DATA
+      );
+    await this.model.updateOne({ _id: id }, body);
+    return 'ok';
+  }
+
+  /**
+   * 多修改
+   * @param {object} filter 要修改的对象查询条件
+   * @param {object} body 要修改的内容
+   * @returns {object}
+   */
+  async updateMany(filter: object = {}, body: object): Promise<string> {
+    if (!body)
+      throw new ServiceError('缺少修改信息', FrameworkErrorEnum.NEED_BODY);
+    await this.model.updateMany(filter, body);
+    return 'ok';
+  }
+
+  /**
+   * 单删除-通过id
+   * @param id 要删除的数据id
+   * @returns {object}
+   */
+  async delete(id: string): Promise<string> {
+    if (!id)
+      throw new ServiceError('缺少数据信息', FrameworkErrorEnum.NEED_PARAMS);
+    await this.model.deleteOne({ _id: id });
+    return 'ok';
+  }
+
+  /**
+   * 多删除
+   * @param filter 要删除的数据查询条件
+   * @returns {object}
+   */
+  async deleteMany(filter: object = {}): Promise<string> {
+    const keys = Object.keys(filter);
+    if (keys.length <= 0)
+      throw new ServiceError(
+        '暂不提供清库服务',
+        FrameworkErrorEnum.SERVICE_FAULT
+      );
+    await this.model.deleteMany(filter);
+    return 'ok';
+  }
+
+  /**
+   * 单创建
+   * @param body 要创建的数据内容
+   * @returns {object}
+   */
+  async create(body: object): Promise<object> {
+    const data = await this.model.create(body);
+    return data;
+  }
+
+  /**
+   * 多创建
+   * @param body 要创建的多个数据
+   * @returns {object[]}
+   */
+  async createMany(body: object[]): Promise<object> {
+    const data = await this.model.insertMany(body);
+    return data;
+  }
+}

+ 0 - 8
src/service/book.service.ts

@@ -1,8 +0,0 @@
-import { Provide } from '@midwayjs/decorator';
-
-@Provide()
-export class BookService {
-  async getBookById() {
-    return 'hello world book';
-  }
-}