增加excel导入时的审核
This commit is contained in:
parent
502253c369
commit
2915c6301c
@ -46,6 +46,7 @@
|
|||||||
"node-html-to-image": "^3.1.0",
|
"node-html-to-image": "^3.1.0",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.4.4",
|
||||||
"querystring": "^0.2.1",
|
"querystring": "^0.2.1",
|
||||||
|
"queue": "^6.0.2",
|
||||||
"redis": "^3.1.2",
|
"redis": "^3.1.2",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"svg-captcha": "^1.4.0",
|
"svg-captcha": "^1.4.0",
|
||||||
|
@ -2,6 +2,8 @@ import BaseController from '../../common/base.controller'
|
|||||||
import { permission, router } from '../../decorators/router'
|
import { permission, router } from '../../decorators/router'
|
||||||
import { ShopPuzzle } from '../../models/shop/ShopPuzzle'
|
import { ShopPuzzle } from '../../models/shop/ShopPuzzle'
|
||||||
import { ZError } from '../../common/ZError'
|
import { ZError } from '../../common/ZError'
|
||||||
|
import { AuditTask } from '../../models/AuditTask'
|
||||||
|
import { AuditSvr } from '../../services/AuditSvr'
|
||||||
|
|
||||||
export default class ShopPuzzleController extends BaseController {
|
export default class ShopPuzzleController extends BaseController {
|
||||||
@permission('shoppuzzle:read')
|
@permission('shoppuzzle:read')
|
||||||
@ -111,7 +113,8 @@ export default class ShopPuzzleController extends BaseController {
|
|||||||
delete data.status
|
delete data.status
|
||||||
}
|
}
|
||||||
let result: any = {}
|
let result: any = {}
|
||||||
const initStatus = { status: 1, deleted: 0, is_hide: 0, quality: 1 }
|
const batchTag = Date.now()
|
||||||
|
const initStatus = { status: 0, deleted: 0, is_hide: 0, quality: 1, batchTag }
|
||||||
try {
|
try {
|
||||||
datas.map(data => Object.assign(data, initStatus))
|
datas.map(data => Object.assign(data, initStatus))
|
||||||
let results = await ShopPuzzle.bulkWrite(
|
let results = await ShopPuzzle.bulkWrite(
|
||||||
@ -127,6 +130,10 @@ export default class ShopPuzzleController extends BaseController {
|
|||||||
result.insert = results.upsertedCount + results.insertedCount
|
result.insert = results.upsertedCount + results.insertedCount
|
||||||
result.update = results.modifiedCount
|
result.update = results.modifiedCount
|
||||||
result.skip = 0
|
result.skip = 0
|
||||||
|
let records = await ShopPuzzle.find({ batchTag })
|
||||||
|
let ids = records.map(data => data._id + '')
|
||||||
|
let id = await AuditTask.addOneTask('shop_puzzle', ids)
|
||||||
|
new AuditSvr().addTask(id)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
result.insert = err.upsertedCount + err.insertedCount
|
result.insert = err.upsertedCount + err.insertedCount
|
||||||
|
36
src/models/AuditTask.ts
Normal file
36
src/models/AuditTask.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { dbconn } from '../decorators/dbconn'
|
||||||
|
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
|
||||||
|
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||||
|
import { BaseModule } from './Base'
|
||||||
|
|
||||||
|
@dbconn()
|
||||||
|
@index({ status: 1 }, { unique: false })
|
||||||
|
@modelOptions({
|
||||||
|
schemaOptions: { collection: 'audit_task', timestamps: true },
|
||||||
|
options: { allowMixed: Severity.ALLOW },
|
||||||
|
})
|
||||||
|
export class AuditTaskClass extends BaseModule {
|
||||||
|
@prop()
|
||||||
|
public tableName: string
|
||||||
|
@prop({ type: () => [String] })
|
||||||
|
public ids: string[]
|
||||||
|
|
||||||
|
@prop({ default: 0 })
|
||||||
|
public status: number
|
||||||
|
|
||||||
|
@prop({ default: 0 })
|
||||||
|
public processNum: number
|
||||||
|
|
||||||
|
@prop({ default: 0 })
|
||||||
|
public failNum: number
|
||||||
|
|
||||||
|
public static async addOneTask(tableName: string, datas: string[]) {
|
||||||
|
let record = new AuditTask({})
|
||||||
|
record.tableName = tableName
|
||||||
|
record.ids = datas
|
||||||
|
await record.save()
|
||||||
|
return record._id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AuditTask = getModelForClass(AuditTaskClass, { existingConnection: AuditTaskClass.db })
|
@ -1,11 +1,10 @@
|
|||||||
import { dbconn } from '../../decorators/dbconn'
|
import { dbconn } from '../../decorators/dbconn'
|
||||||
import { getModelForClass, index, modelOptions, prop, ReturnModelType } from '@typegoose/typegoose'
|
import { getModelForClass, index, modelOptions, mongoose, prop, ReturnModelType } from '@typegoose/typegoose'
|
||||||
import { BaseModule } from '../Base'
|
import { BaseModule } from '../Base'
|
||||||
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
|
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
|
||||||
import { checkJson, noJson } from '../../decorators/nojson'
|
import { checkJson, noJson } from '../../decorators/nojson'
|
||||||
import { Puzzle, PuzzleClass } from '../content/Puzzle'
|
|
||||||
import { QCategoryCache } from '../../services/QCategoryCache'
|
|
||||||
import { CompactPuzzleClass } from '../match/PuzzleSession'
|
import { CompactPuzzleClass } from '../match/PuzzleSession'
|
||||||
|
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||||
|
|
||||||
const jsonExcludeKeys = ['updatedAt', '__v']
|
const jsonExcludeKeys = ['updatedAt', '__v']
|
||||||
|
|
||||||
@ -20,7 +19,10 @@ export interface ShopPuzzleClass extends Base, TimeStamps {}
|
|||||||
@index({ shop: 1, question: 1 }, { unique: true })
|
@index({ shop: 1, question: 1 }, { unique: true })
|
||||||
@index({ groups: 1 }, { unique: false })
|
@index({ groups: 1 }, { unique: false })
|
||||||
@index({ shop: 1, tag: 1, sub_tag: 1 }, { unique: false })
|
@index({ shop: 1, tag: 1, sub_tag: 1 }, { unique: false })
|
||||||
@modelOptions({ schemaOptions: { collection: 'shop_puzzle', timestamps: true } })
|
@modelOptions({
|
||||||
|
schemaOptions: { collection: 'shop_puzzle', timestamps: true },
|
||||||
|
options: { allowMixed: Severity.ALLOW },
|
||||||
|
})
|
||||||
export class ShopPuzzleClass extends BaseModule {
|
export class ShopPuzzleClass extends BaseModule {
|
||||||
@prop()
|
@prop()
|
||||||
public shop: string
|
public shop: string
|
||||||
@ -68,6 +70,9 @@ export class ShopPuzzleClass extends BaseModule {
|
|||||||
|
|
||||||
@prop({ type: () => [String] })
|
@prop({ type: () => [String] })
|
||||||
public groups: string[]
|
public groups: string[]
|
||||||
|
|
||||||
|
@prop()
|
||||||
|
public batchTag: number
|
||||||
/**
|
/**
|
||||||
* 是否删除
|
* 是否删除
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
@ -87,8 +92,11 @@ export class ShopPuzzleClass extends BaseModule {
|
|||||||
@prop({ default: 0 })
|
@prop({ default: 0 })
|
||||||
public status: number
|
public status: number
|
||||||
|
|
||||||
|
@prop({ type: mongoose.Schema.Types.Mixed })
|
||||||
|
public auditResult: {}
|
||||||
|
|
||||||
public static parseQueryParam(params) {
|
public static parseQueryParam(params) {
|
||||||
let { key, timeBegin, timeEnd, tag, sub_tag, groups, dp, quality, sort, length, shop } = params
|
let { key, timeBegin, timeEnd, tag, sub_tag, groups, dp, quality, sort, length, shop, status } = params
|
||||||
let opt: any = { deleted: 0, is_hide: 0 }
|
let opt: any = { deleted: 0, is_hide: 0 }
|
||||||
if (key) {
|
if (key) {
|
||||||
opt.question = { $regex: key, $options: 'i' }
|
opt.question = { $regex: key, $options: 'i' }
|
||||||
@ -125,6 +133,9 @@ export class ShopPuzzleClass extends BaseModule {
|
|||||||
if (length) {
|
if (length) {
|
||||||
opt.length = { $gte: length }
|
opt.length = { $gte: length }
|
||||||
}
|
}
|
||||||
|
if (status !== undefined && status !== 9) {
|
||||||
|
opt.status = status
|
||||||
|
}
|
||||||
let sortObj = { _id: 1 }
|
let sortObj = { _id: 1 }
|
||||||
if (sort) {
|
if (sort) {
|
||||||
sortObj = sort
|
sortObj = sort
|
||||||
|
67
src/services/AuditSvr.ts
Normal file
67
src/services/AuditSvr.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import axios, { AxiosRequestConfig } from 'axios'
|
||||||
|
import { singleton } from '../decorators/singleton'
|
||||||
|
import Queue from 'queue'
|
||||||
|
import { AuditTask } from '../models/AuditTask'
|
||||||
|
import { ShopPuzzle } from '../models/shop/ShopPuzzle'
|
||||||
|
|
||||||
|
export async function auditTxt(txt: string) {
|
||||||
|
let data = { content: txt }
|
||||||
|
const url = 'http://127.0.0.1:8019/check_all'
|
||||||
|
let reqConfig: AxiosRequestConfig = {
|
||||||
|
method: 'post',
|
||||||
|
url,
|
||||||
|
headers: {
|
||||||
|
'Cache-Control': 'no-cache',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
return axios(reqConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
@singleton
|
||||||
|
export class AuditSvr {
|
||||||
|
private q
|
||||||
|
constructor() {
|
||||||
|
this.q = new Queue({ concurrency: 1, autostart: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
addTask(taskId: string) {
|
||||||
|
this.q.push(async function (cb) {
|
||||||
|
let taskRecord = await AuditTask.findById(taskId)
|
||||||
|
if (!taskRecord) {
|
||||||
|
cb()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let failCount = 0
|
||||||
|
let processNum = 0
|
||||||
|
let riskNum = 0
|
||||||
|
for (let id of taskRecord.ids) {
|
||||||
|
let record = await ShopPuzzle.findById(id)
|
||||||
|
if (record.status === 1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
processNum++
|
||||||
|
let txt = `${record.question},${record.a1},${record.a2},${record.a3},${record.a4}`
|
||||||
|
let { data } = await auditTxt(txt)
|
||||||
|
record.auditResult = data
|
||||||
|
if (data.errcode) {
|
||||||
|
failCount++
|
||||||
|
} else {
|
||||||
|
if (data.wx || data.bd || data.local) {
|
||||||
|
record.status = -1
|
||||||
|
riskNum++
|
||||||
|
} else {
|
||||||
|
record.status = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await record.save()
|
||||||
|
}
|
||||||
|
taskRecord.processNum = processNum
|
||||||
|
taskRecord.failNum = failCount
|
||||||
|
await taskRecord.save()
|
||||||
|
console.log(`audit task finished: ${taskId}, found ${riskNum} risk`)
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2648,6 +2648,13 @@ queue-microtask@^1.1.2, queue-microtask@^1.2.2:
|
|||||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||||
|
|
||||||
|
queue@^6.0.2:
|
||||||
|
version "6.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65"
|
||||||
|
integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==
|
||||||
|
dependencies:
|
||||||
|
inherits "~2.0.3"
|
||||||
|
|
||||||
quick-format-unescaped@^4.0.3:
|
quick-format-unescaped@^4.0.3:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz#6d6b66b8207aa2b35eef12be1421bb24c428f652"
|
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz#6d6b66b8207aa2b35eef12be1421bb24c428f652"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user