import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; // const _ = require('underscore'); const Transaction = require('mongoose-transactions'); @index({ roleId: 1, id: 1 }) @index({ seqId: 1 }) @modelOptions({ schemaOptions: { id: false } }) export default class Item extends BaseModel { @prop({ required: true, default: '' }) roleId: string; // 角色 id @prop({ required: true, default: '' }) roleName: string; // 角色名称 @prop({ required: true, default: '' }) id: number; // 道具 id @prop({ required: true, default: '' }) type: number; // 道具类型 @prop({ required: true, default: '' }) itemName: string; // 道具名称 @prop({ required: true, default: 0 }) hid: number; // 将魂:武将id,其他:0 @prop({ required: true }) count: number; // 道具数量 public static async findbyRole(roleId: string, lean = true) { const items: ItemType[] = await ItemModel.find({ roleId }).select('id count type').lean(lean); return items; } public static async findbyRoleAndIds(roleId: string, ids: Array, lean = true) { const items: ItemType[] = await ItemModel.find({ roleId, id: { $in: ids } }).select('id count type').lean(lean); return items; } public static async findByRoleAndType(roleId: string, type: number, lean = true) { const items: ItemType[] = await ItemModel.find({ roleId, type }).select('id count type').sort({ id: 1 }).lean(lean); return items; } public static async findbyRoleAndGidAndCount(roleId: string, id: number, count: number, lean = true) { const items: ItemType = await ItemModel.findOne({ roleId, id, count: { $gte: count } }).select('id count type').lean(lean); return items; } public static async increaseItem(roleId: string, id: number, count: number, itemInfo: { roleId: string, roleName: string, id: number, itemName: string, type: number, hid?: number }, lean = true) { const doc = new ItemModel(); const setOnInsert = Object.assign(doc.toJSON(), itemInfo); const items: ItemType = await ItemModel.findOneAndUpdate({ roleId, id }, { $setOnInsert: setOnInsert, $inc: { count } }, { new: true, upsert: true }).lean(lean); return items; } // public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number }>, lean = true) { // let updateItems = new Array<{ id: number, count: number, ratio?: number }>(), hasError: boolean = false, result = new Array(); // for (let { id, count, ratio } of items) { // let rec: ItemType; // if (!ratio) { // rec = await ItemModel.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: -1 * count } }, { new: true }).lean(lean); // } else { // rec = await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: ratio * count } }, { new: true, upsert: true }).lean(lean); // } // if (!!rec) { // let index = _.findIndex(result,{id}) // if (!!result[index]) { // result[index] = { id: rec.id, count: rec.count } // } else { // result.push({ id: rec.id, count: rec.count }); // } // updateItems.push({ id, count, ratio }); // } else { // hasError = true; break; // } // } // if (hasError) { // 数量不足 // for (let { id, count, ratio } of updateItems) { // if (!ratio) ratio = -1; // await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: -ratio * count } }, { new: true }).lean(lean); // } // return { hasError: true } // } else { // return { hasError: false, result } // } // } public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number}>, lean = true) { const transaction = new Transaction(); let hasError: boolean = false, result = new Array(); try { for (let { id, count, ratio } of items) { if (ratio) ratio = -1; await transaction.update({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}); const rec: ItemType = await transaction.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}).lean(lean); if (!!rec) { result.push({ id: rec.id, count: rec.count }); } else { hasError = true; break; } } await transaction.run(); return {hasError, result}; } catch (error) { await transaction.rollback().catch(console.error); transaction.clean(); return {error}; } } public static async deleteAccount(roleId: string) { let result = await ItemModel.deleteMany({ roleId }); return result; } } export const ItemModel = getModelForClass(Item); export interface ItemType extends Pick, keyof Item> { id: number; };