增加店铺自定义题库相关接口

This commit is contained in:
zhl 2021-05-31 15:47:22 +08:00
parent a6c3b1c081
commit 9b65560dd4
4 changed files with 298 additions and 1 deletions

View File

@ -0,0 +1,91 @@
import BaseController from '../../common/base.controller'
import { permission, router } from '../../decorators/router'
import { ShopPuzzle } from '../../models/shop/ShopPuzzle'
import { ZError } from '../../common/ZError'
export default class ShopPuzzleController extends BaseController {
@permission('shoppuzzle:read')
@router('post /api/:shop/puzzles')
async list(req, res) {
let { start, limit, page, shop } = req.params
limit = +limit || 10
start = +start || (+page - 1) * limit || 0
let { opt, sort } = ShopPuzzle.parseQueryParam(req.params)
let puzzles = await ShopPuzzle.find(opt).sort(sort).skip(start).limit(limit)
let count = await ShopPuzzle.countDocuments(opt)
let records = []
for (let record of puzzles) {
let data = record.toJson()
records.push(data)
}
return {
total: count,
start,
limit,
records,
}
}
@permission('shoppuzzle:read')
@router('get /api/:shop/puzzle/:id')
async detail(req, res) {
let { id } = req.params
const record = await ShopPuzzle.findById(id)
if (!record) {
throw new ZError(11, 'record not found')
}
return record.toJson()
}
@permission('shoppuzzle:edit')
@router('post /api/:shop/puzzle/save')
async save(req: any) {
let { _id, withNext, shop } = req.params
let user = req.user
let record
if (!_id) {
record = new ShopPuzzle(req.params)
record.createdBy = user.id
} else {
record = await ShopPuzzle.findById(_id)
record.updateFromReq(req.params)
}
await record.save()
if (withNext) {
let nextRecord = await ShopPuzzle.nextQuestion(record.id, shop)
return nextRecord.toJson()
}
return record.toJson()
}
@permission('shoppuzzle:delete')
@router('post /api/:shop/puzzle/:id/delete')
async delete(req: any) {
let { id } = req.params
if (!id) {
throw new ZError(11, 'params mismatch')
}
await ShopPuzzle.findByIdAndUpdate(id, {
$set: {
deleted: 1,
deleteTime: new Date(),
},
})
return {}
}
@permission('shoppuzzle:read')
@router('post /api/:shop/nextpuzzle')
async next(req: any) {
let { id, shop } = req.params
if (!id) {
throw new ZError(11, 'params mismatch')
}
let nextRecord = await ShopPuzzle.nextQuestion(id, shop)
return nextRecord.toJson()
}
@router('get /api/:shop/categorys')
async categoryList(req, res) {
const { shop } = req.params
return await ShopPuzzle.allTags(shop)
}
}

View File

@ -71,7 +71,7 @@ export class PuzzleClass extends BaseModule {
opt.sub_tag = sub_tag opt.sub_tag = sub_tag
} }
if (groups) { if (groups) {
Object.assign(opt, { groups }) Object.assign(opt, { groups: { $in: groups } })
} }
if (quality != undefined) { if (quality != undefined) {
opt.quality = quality opt.quality = quality

View File

@ -0,0 +1,59 @@
import { dbconn } from '../../decorators/dbconn'
import { getModelForClass, index, modelOptions, prop, ReturnModelType } from '@typegoose/typegoose'
import { BaseModule } from '../Base'
import { noJson } from '../../decorators/nojson'
/**
*
*/
class SubType {
@prop()
public _id: string
@prop()
public name: string
}
@dbconn('second')
@index({ shop: 1 }, { unique: false })
@modelOptions({ schemaOptions: { collection: 'question_category' } })
class ShopCategoryClass extends BaseModule {
@prop()
public _id: string
@prop()
public shop: string
@prop()
public name: string
@prop({ type: () => [SubType] })
public children: SubType[]
/**
*
* @type {boolean}
*/
@noJson()
@prop({ default: false })
public deleted: boolean
@noJson()
@prop()
public deleteTime: Date
public static async allCateMap(this: ReturnModelType<typeof ShopCategoryClass>, shop: string) {
let result: Map<string, string> = new Map()
let records = await this.find({ shop, deleted: false }).exec()
for (let record of records) {
result.set(record._id, record.name)
for (let sub of record.children) {
result.set(sub._id, sub.name)
}
}
return result
}
}
export const ShopCategory = getModelForClass(ShopCategoryClass, { existingConnection: ShopCategoryClass.db })

View File

@ -0,0 +1,147 @@
import { dbconn } from '../../decorators/dbconn'
import { getModelForClass, index, modelOptions, prop, ReturnModelType } from '@typegoose/typegoose'
import { BaseModule } from '../Base'
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
import { checkJson, noJson } from '../../decorators/nojson'
import { PuzzleClass } from '../content/Puzzle'
const jsonExcludeKeys = ['updatedAt', '__v']
/**
* , ,
*/
// @ts-ignore
export interface ShopPuzzleClass extends Base, TimeStamps {}
@dbconn()
@index({ shop: 1 }, { unique: false })
@index({ groups: 1 }, { unique: false })
@index({ shop: 1, tag: 1, sub_tag: 1 }, { unique: false })
@modelOptions({ schemaOptions: { collection: 'shop_puzzle', timestamps: true } })
export class ShopPuzzleClass extends BaseModule {
@prop()
public shop: string
@prop()
public question: string
@prop()
public a1: string
@prop()
public a2: string
@prop()
public a3: string
@prop()
public a4: string
/**
*
* @type {number}
*/
@prop({ default: 1 })
public quality: number
/**
*
* @type {string}
*/
@prop()
public tag: string
/**
*
* @type {string}
*/
@prop()
public sub_tag: string
/**
* tag
* @type {string}
*/
@prop({ type: () => [String] })
public groups: string[]
/**
*
* @type {boolean}
*/
@noJson()
@prop({ default: 0 })
public deleted: number
@noJson()
@prop()
public deleteTime: Date
@noJson()
@prop({ default: 0 })
public is_hide: number
public static parseQueryParam(params) {
let { key, timeBegin, timeEnd, tag, sub_tag, groups, dp, quality, sort, length, shop } = params
let opt: any = { deleted: 0, is_hide: 0 }
if (key) {
opt.question = { $regex: key, $options: 'i' }
}
if (tag) {
opt.tag = tag
}
if (sub_tag) {
opt.sub_tag = sub_tag
}
if (groups) {
Object.assign(opt, { groups: { $in: groups } })
}
if (quality != undefined) {
opt.quality = quality
}
if (dp != undefined) {
if (dp == 'none') {
opt.dp = { $exists: false }
} else {
opt.dp = dp
}
}
if (shop) {
opt.shop = shop
}
if (timeBegin && !timeEnd) {
opt.createdAt = { $gte: timeBegin }
} else if (timeBegin && timeEnd) {
opt['$and'] = [{ createdAt: { $gte: timeBegin } }, { createdAt: { $lte: timeEnd } }]
} else if (!timeBegin && timeEnd) {
opt.createdAt = { $lte: timeEnd }
}
if (length) {
opt.length = { $gte: length }
}
let sortObj = { _id: 1 }
if (sort) {
sortObj = sort
}
return { opt, sort: sortObj }
}
public toJson() {
let result: any = {}
// @ts-ignore
for (let key in this._doc) {
if (checkJson(this, key + '') && jsonExcludeKeys.indexOf(key) == -1) {
if (key === 'createdAt') {
result.createtime = this['createdAt']
} else {
result[key] = this[key]
}
}
}
return result
}
public static async nextQuestion(this: ReturnModelType<typeof ShopPuzzleClass>, id: string, shop: string) {
return this.findOne({ deleted: 0, shop, is_hide: 0, _id: { $gt: id } }).exec()
}
public static async allTags(shop: string) {
return ShopPuzzle.distinct('groups', { shop, deleted: 0 })
}
}
export const ShopPuzzle = getModelForClass(ShopPuzzleClass, { existingConnection: ShopPuzzleClass.db })