增加店铺自定义题库相关接口
This commit is contained in:
parent
a6c3b1c081
commit
9b65560dd4
91
src/admin/controllers/shop_puzzle.controller.ts
Normal file
91
src/admin/controllers/shop_puzzle.controller.ts
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
59
src/models/shop/ShopCategory.ts
Normal file
59
src/models/shop/ShopCategory.ts
Normal 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 })
|
147
src/models/shop/ShopPuzzle.ts
Normal file
147
src/models/shop/ShopPuzzle.ts
Normal 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 })
|
Loading…
x
Reference in New Issue
Block a user