// 测评 const util = require('../utils') const db = require('../data') const Token = require('../token') const dayjs = require('dayjs') const EnDeNum = require('../utils/encrypt-decrypt-number') let [sql, rs] = ['', null] /** * 获取测评记录(获取学校时,当前查询范围的path参数必需) * *get: /member/:id/tested(id为0或加密后) */ exports.List = async ctx => { const school = ctx.query.school const path = ctx.query.path const member = ctx.params.id === '0' ? Token.Decode(ctx).id : EnDeNum.decrypt(ctx.params.id) const number = ctx.query.number const realname = ctx.query.realname const lb = ctx.query.lb const date1 = ctx.query.date1 const date2 = ctx.query.date2 const valid = ctx.query.valid const normal = ctx.query.normal const agent = EnDeNum.decrypt(ctx.query.agent) const device = ctx.query.device const pagesize = ctx.query.pagesize const page = ctx.query.page const mini = ctx.query.mini // top建议至少为2,方便前端判断 const top = ctx.query.top if (util.isInteger(school)) { // 学校 sql = 'select' + (top ? (' top ' + top) : '') + ' id,member,number,realname,sexname,testage,lbnamech,datetime,valid,normal,howlong,money,mobile from v_test with (nolock) where ' if (path.endsWith(',' + school)) { sql += 'member_type_top=' + school } else { sql += `member_type_path+',' like '${path},%'` } if (number) { sql += ` and number='${number}'` } if (realname) { sql += ` and realname='${realname}'` } if (lb) { sql += ` and lb in (${lb})` } if (valid) { sql += ` and valid=${valid}` } if (normal) { sql += ` and normal=${normal}` } util.isDate(date1) && (sql += ` and datetime>='${date1}'`) util.isDate(date2) && (sql += ` and datetime<'${dayjs(date2.replace(/\//g, '-')).add(1, 'days').format('YYYY-MM-DD')}'`) if (device) { sql += ' and device=' + device } if (school !== '1') { sql += ' and [group]<5' } sql += ' order by id desc' if (top) { rs = await db.select(sql) } else { rs = await db.page(sql, pagesize, page) } ctx.body = { code: 0, data: rs } } else if (util.isInteger(member)) { // 个人(多个量表逗号隔开) sql = 'select ' + (top ? ('top ' + top) : '') if (mini) { sql += ' id,lb,datetime,valid,normal from test with (nolock)' } else { sql += ' id,lb,datetime,valid,normal,lbnamefr,lbnamech,permitview,picture,money,payment,member,testage,howlong from v_test with (nolock)' } sql += ` where member=${member}` util.isIdList(lb) && (sql += ` and lb in (${lb})`) if (valid) { sql += ` and valid=${valid}` } if (normal) { sql += ` and normal=${normal}` } if (date1) { sql += ` and datetime>='${date1}'` } if (date2) { sql += ` and datetime<'${dayjs(date2.replace(/\//g, '-')).add(1, 'days').format('YYYY-M-D')}'` } if (device) { sql += ' and device=' + device } sql += ' order by id desc' if (top) { rs = await db.select(sql) rs.forEach(item => item.key = EnDeNum.encrypt(item.id)) ctx.body = { code: 0, data: rs || [] } } else { rs = await db.page(sql, pagesize, page) rs.forEach(item => item.key = EnDeNum.encrypt(item.id)) ctx.body = { code: 0, data: rs } } } else if (util.isInteger(agent)) { // 代理获取 sql = 'select ' + (top ? ('top ' + top) : '') + ' id,picture,lbnamech as lbname,realname,datetime from v_test with (nolock) where agent=' + agent + ' order by datetime desc' if (top) { rs = await db.select(sql) ctx.body = { code: 0, data: rs || [] } } else { rs = await db.page(sql, pagesize, page) ctx.body = { code: 0, data: rs } } } else { throw { code: -2 } } } /** * 获取量表题目选项和答题 * get: /test/answer */ exports.Answer = async ctx => { const school = ctx.query.school const id = ctx.query.id const key = ctx.query.key if (!util.isInteger(school) || !util.isInteger(id) || !util.isMD5(key)) { throw { code: -2 } } else { rs = await db.select('select top 1 keystr from school where id=' + school) if (rs) { const keystr = rs.keystr if (keystr) { if (key === util.MD5(school + id + dayjs().format('YYYYMMDD') + keystr)) { rs = await db.select('select top 1 lb,answer from v_test with (nolock) where valid=1 and id=' + id + ' and member_type_top=' + school) if (rs) { const lb = rs.lb const select = rs.answer.split('|') rs = await db.select(`select top 1 answer from lb where available=1 and id=${lb}`) if (rs.answer) { sql = `SELECT question,'${rs.answer}' AS answer FROM lbquestion where lb=${lb} ORDER BY sort` } else { sql = `select question,answer from lbquestion where lb=${lb} order by sort` } rs = await db.select(sql) const data = [] rs.forEach((v, i) => { if (v.answer) { data.push({ id: i + 1, question: v.question, answer: lb === 271 ? v.answer.split('\r\n')[0].split('|') : v.answer.split('|'), select: isNaN(select[i]) ? select[i] : Number(select[i]) }) } else { data.push({ id: i + 1, question: v.question, select: select[i] }) } }) ctx.body = { code: 0, data } } else { throw { code: 4, message: '记录未找到' } } } else { throw { code: 3, message: 'KEY验证未通过' } } } else { throw { code: 2, message: '接口关闭' } } } else { throw { code: 1, message: '单位未找到' } } } } /** * 测评前处理记录,获取记录id * post: /test/start */ exports.Start = async ctx => { const member = Token.Decode(ctx).id const lbid = ctx.request.body.lbid let testtype = ctx.request.body.testtype let id = 0 if (util.isInteger(lbid)) { testtype !== '0' && testtype !== '1' && (testtype = 0) rs = await db.select('select top 1 id,valid,convert(varchar,datetime,20) as datetime from test with (nolock) where member=' + member + ' and lb=' + lbid + ' order by datetime desc') if (rs === null || rs.datetime < dayjs().subtract(12, 'hour').format('YYYY-MM-DD HH:mm:ss')) { // 不存在添加或存在且超过12小时添加 sql = 'insert into test(member,lb,ip,type,datetime,normal) output inserted.id values(' + member + ',' + lbid + `,'${util.GuestIP(ctx)}'` + ',' + testtype + ',getdate()' + ',1' + ')' try { id = await db.scalar(sql) ctx.body = { code: 0, data: id } } catch (err) { ctx.body = { code: 2, message: '系统繁忙' } } } else if (!rs.valid) { // 存在但无效则修改 id = rs.id sql = 'update test set' + ' advice=null' + `,ip='${util.GuestIP(ctx)}'` + ',type=' + testtype + ',datetime=getdate()' + ',normal=1' + ' where id=' + id try { db.execute(sql) ctx.body = { code: 0, data: id } } catch (err) { ctx.body = { code: 2, message: '系统繁忙' } } } else { throw { code: 1, message: '你(' + member + ')已经在 ' + rs.datetime + ' 测评过该问卷(' + lbid + ')。' } } } else { throw { code: -2 } } }