/**
* 提交表单
*/
submitForm(value) {
// 使用 clientDB 提交数据
const thisTime = Date.parse(new Date()) //获取时间戳
console.log(thisTime)
//新增主表数据
return db.collection(dbCollectionName).add(value).then((res) => {
//新增中间表数据
db.collection('answer-level-question').add({level_id:this.formData.level_id,question_id:res.result.id,update_date:thisTime})
uni.showToast({
title: '新增成功'
})
this.getOpenerEventChannel().emit('refreshData')
setTimeout(() => uni.navigateBack(), 500)
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
})
}
}
const que = db.collection('answer-question').where('level_id == "'+this.level_id+'"').getTemp()
db.collection(que,'answer-option')
.get()
.then((res)=>{
// res 为数据库查询结果
this.quest = res.result.data
console.log(res.result.data)
}).catch((err)=>{
// err.message 错误信息
// err.code 错误码
// console.log(err.message)
})
查询筛选数组中的条件时:
where: '_id["answer-level-question"].status == 1',
拼接
this.where = "level_id == '" + this.level_id + "'&& _id['answer-level-question'].status == 1"
js判断字符串是否为空的方法:1、判断字符串是否为空,代码为【if (string.length == 0)】;2、判断字符串是否为“空”字符即用户输入了空格,代码为【if (strings.replace(/(^s*)|(s*$)…】。
输出来是这样的
promies对象要使用.then输出:
this.option_id.forEach((item, index, arr) => {
console.log(item.option_id)
//新增中间表option数据
db.collection('answer-question-option')
.add({
question_id: res.result.id,
option_id: item.option_id,
update_date: thisTime,
status: 1
})
})
创建云函数:首先,创建一个云函数,用于执行连表查询。在云函数中,你可以使用 uniCloud 的数据库操作 API 进行查询。
javascript
Copy code
// 云函数名:queryTables
const db = uniCloud.database()
exports.main = async (event, context) => {
try {
// 执行连表查询
const result = await db.collection('table1')
.aggregate()
.match({status:1}) //查询条件
.lookup({
from: 'table2',
localField: 'field1', // table1 中的关联字段
foreignField: 'field2', // table2 中的关联字段
as: 'result' // 查询结果的字段名
})
.end()
return result.data
} catch (err) {
return err
}
}
要将数组中的对象按照某个字段分组,结果为数组,你可以使用 JavaScript 的 reduce() 函数来实现。以下是一个示例,演示如何按照某个字段将数组中的对象分组,并将结果存储为一个数组:
假设你有一个包含对象的数组,每个对象都有一个字段 category,你想要按照 category 字段将它们分组,并将结果存储为一个数组:
const data = [
{ name: 'Item 1', category: 'A' },
{ name: 'Item 2', category: 'B' },
{ name: 'Item 3', category: 'A' },
{ name: 'Item 4', category: 'C' },
{ name: 'Item 5', category: 'B' }
];
const grouped = data.reduce((result, item) => {
const category = item.category;
//通过group.key循环判断是否一致 这里面的key为category属性 也可以灵活使用对象
let group = result.find(group => group.key === category);
// 如果该分类还不存在,则创建一个新的分类
if (!group) {
group = { key: category, items: [] };
result.push(group);
}
// 将当前对象添加到该分类下
group.items.push(item);
return result;
}, []);
console.log(grouped);
在这个示例中,我们使用 reduce() 函数来迭代数组中的每个对象。对于每个对象,我们提取 category 字段的值,并检查是否已经存在该分类的数组项,如果不存在就创建一个新的分类项,然后将当前对象添加到该分类项中。最终,我们得到了一个包含各个分类的数组,每个分类对应一个包含相关对象的数组。
输出结果将会是一个数组,每个数组项包含了一个分类的对象集合,例如:
[
{
key: 'A',
items: [
{ name: 'Item 1', category: 'A' },
{ name: 'Item 3', category: 'A' }
]
},
{
key: 'B',
items: [
{ name: 'Item 2', category: 'B' },
{ name: 'Item 5', category: 'B' }
]
},
{
key: 'C',
items: [
{ name: 'Item 4', category: 'C' }
]
}
]
灵活使用对象:
res = rest.data.reduce((result, item) => {
//拿到question对象
const category = item.question[0];
// const level_order = item.result[0].level_order;
//将对象中的_id作为比较的值 相同则分为一组(直接比较对象是不成功的)
let group = result.find(group => group.key._id === category._id);
// 如果该分类还不存在,则创建一个新的分类
if (!group) {
group = {
key: category,
newoptions: []
};
result.push(group);
}
// 将当前对象(item)的options对象添加到该分类下
group.newoptions.push(item.options);
return result;
}, []);
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
const db = uniCloud.database()
module.exports = {
_before: function() { // 通用预处理器
},
/**
* @param {Object} userId 用户id
* 获取大纲预览
*/
async getSchedule(userId) {
let quest = null
let guanka = null
//查询进度
let jindu = await db.collection("answer-level-schedule")
.where({
user_id: userId
})
// .orderBy('level_num', 'desc')
.limit(1)
.get()
// 查询最新关卡
// 执行连表查询
guanka = await db.collection('answer-level-question')
.aggregate()
.lookup({
from: 'answer-level',
localField: 'level_id', // table1 中的关联字段
foreignField: '_id', // table2 中的关联字段
as: 'result' // 查询结果的字段名
// cond: {status: 1}
})
.match({
status: 1
}) // 添加第二个表的查询条件
.end()
const guankaGroup = guanka.data.reduce((result, item) => {
const category = item.level_id;
const level_order = item.result[0].level_order;
let group = result.find(group => group.key === category);
// 如果该分类还不存在,则创建一个新的分类
if (!group) {
group = {
key: category,
level_order: level_order,
items: []
};
result.push(group);
}
// 将当前对象添加到该分类下
group.items.push(item);
return result;
}, []);
// 进度为0 第一次进入 则创建
if (jindu.data.length == 0) {
//判断题库是否为空
if (guankaGroup.length > 0) {
//循环新增
guankaGroup.forEach((item, index, arr) => {
if (item.level_order == 1) {
//新增中间表option数据
db.collection('answer-level-schedule')
.add({
level_id: item.key,
question_id: null,
level_allsche: item.items.length, //进度数
level_thissche: 0,
level_num: 1, //答题轮数
status: 1, //可以答题
user_id: userId,
level_order: item.level_order
})
} else {
//新增中间表option数据
db.collection('answer-level-schedule')
.add({
level_id: item.key,
question_id: null,
level_allsche: item.items.length, //进度数
level_thissche: 0,
level_num: 1, //答题轮数
status: 0, //未开始
user_id: userId,
level_order: item.level_order
})
}
})
}
}
//查询进度概览
let zongjindu = await db.collection('answer-level-schedule')
.aggregate()
.lookup({
from: 'answer-level',
localField: 'level_id', // table1 中的关联字段
foreignField: '_id', // table2 中的关联字段
as: 'result' // 查询结果的字段名
})
.match({
user_id: userId //进行中
// level_num: jinduLun.data[0].level_num
})
.end()
zongjindu.data.sort((a, b) => a.result[0].level_order - b.result[0].level_order)
return zongjindu
},
// *
// * 开始闯关 查询该关卡的题目
// * @param {Object} levelId 关卡id
// *
async getLevelInfo(levelId) {
let res = null;
let levelQuestion = await db.collection("answer-level-question")
.where({
level_id: levelId,
// status: 1
})
.get()
if (levelQuestion.data.length > 0) {
let questionIds = []
//循环查找
levelQuestion.data.forEach((item, index, arr) => {
questionIds.push(item.question_id)
})
//查找
// 使用聚合查询进行联查 查询问题对应的选项id
// let wenti = await db.collection('answer-question-option')
// .aggregate()
// .lookup({
// from: 'answer-question',
// localField: 'question_id', // table1 中的关联字段
// foreignField: '_id', // table2 中的关联字段
// as: 'result' // 查询结果的字段名
// // cond: {status: 1}
// })
// .match({
// status: 1
// }) // 添加第二个表的查询条件
// .end()
// res = wenti.data.reduce((result, item) => {
// const category = item.question_id;
// const question_order = item.result[0].question_order;
// let group = result.find(group => group.key === category);
// // 如果该分类还不存在,则创建一个新的分类
// if (!group) {
// group = {
// key: category,
// question_order: question_order,
// items: []
// };
// result.push(group);
// }
// // 将当前对象添加到该分类下
// group.items.push(item);
// return result;
// }, []);
let rest = await db.collection('answer-question-option')
.aggregate()
.lookup({
from: 'answer-question',
localField: 'question_id',
foreignField: '_id',
as: 'question',
})
.match({
question_id: {
$in: questionIds
}, //查询中的in语句
status: 1
})
.lookup({
from: 'answer-option',
localField: 'option_id',
foreignField: '_id',
as: 'options',
})
.end(); //三表联查
res = rest.data.reduce((result, item) => {
const category = item.question[0];
// const level_order = item.result[0].level_order;
let group = result.find(group => group.key._id === category._id);
// 如果该分类还不存在,则创建一个新的分类
if (!group) {
group = {
key: category,
// level_order: level_order,
newoptions: []
};
result.push(group);
}
// 将当前对象的options对象添加到该分类下
group.newoptions.push(item.options);
return result;
}, []);
}
if (res != null && res.length > 0) {
res.sort((a, b) => a.key.question_order - b.key.question_order)
}
// db.collection("answer-level-question", "answer-question")
//2将该关卡的进度设置为进行中 status->1
return res
},
/**
* 用户提交答案
*
* @param {Object} scheId 进度id
* @param {Object} levelId
* @param {Object} questionId
* @param {Object} optionId
* @param {Object} userId
* @param {Object} isTrue 用户是否选择正确 0 错误 1 正确
*/
async submitOption(scheId, levelId, questionId, optionId, userId, isTrue) {
let code = 0
let message = "成功"
let result = null
if (isTrue == 1) { //回答正确
//1修改进度表
const res = await db.collection('answer-level-schedule')
.where({
_id: scheId
})
.update({
question_id: questionId
});
}
//2添加到答题记录
//获取当前进度
let Sche = await db.collection('answer-level-schedule')
.where({
_id: scheId
})
.get();
//同一轮有没有重复新增
let currSche = await db.collection('answer-details')
.where({
schedul_id: scheId,
question_id: questionId,
user_id: userId,
level_num: 1,
this_num: Sche.data[0].level_num //当前答题轮数
})
.get();
if (currSche.data.length == 0) {
await db.collection("answer-details")
.add({
schedul_id: scheId,
level_id: levelId,
question_id: questionId,
option_id: optionId,
level_num: isTrue, //0错误 1 正确
user_id: userId,
this_num: Sche.data[0].level_num //答题轮数
})
}
//3 刷新当前进度记录
//获取当前记录总数
let thisSche = await db.collection('answer-details')
.where({
schedul_id: scheId,
level_id: levelId,
user_id: userId,
level_num: 1,
this_num: Sche.data[0].level_num //答题轮数
})
.get();
// 修改进度表当前进度
const res = await db.collection('answer-level-schedule')
.where({
_id: scheId
})
.update({
level_thissche: thisSche.data.length
});
//4 答题错误扣除分数
if (isTrue == 0) { //回答错误
//判断是否已经扣了两分
let scoreNum = await db.collection("answer-deduct-record")
.where({
schedul_id: scheId,
level_id: levelId,
question_id: questionId,
user_id: userId,
is_statistic: 1 //统计分数
}).get()
if (scoreNum.data.length < 2) { //最多扣两分
//添加到答题记录
await db.collection("answer-deduct-record")
.add({
schedul_id: scheId,
level_id: levelId,
question_id: questionId,
score_num: 1, //0错误 1 正确
user_id: userId,
is_statistic: 1 //统计分数
})
}
}
//5 判断当前关卡是否完成
//获取当前进度
let thisScheAll = await db.collection('answer-level-schedule')
.where({
_id: scheId
})
.get();
if (thisScheAll.data.length > 0 && thisScheAll.data[0].level_allsche <= thisScheAll.data[0]
.level_thissche) {
//当前关卡已完成 修改状态
await db.collection('answer-level-schedule')
.where({
_id: scheId
})
.update({
status: 2 //已结束
});
//下一关修改为可以答题 1
let nextScheAll = await db.collection('answer-level-schedule')
.where({
user_id: userId,
status: db.command.neq(2)
// level_num:1
})
.orderBy('level_order', 'asc')
.limit(1)
.get();
if (nextScheAll.data.length > 0) {
await db.collection('answer-level-schedule')
.where({
_id: nextScheAll.data[0]._id
})
.update({
status: 1 //可以答题
});
}
}
//6 如果当前为第一轮 并且都已经完成 获得证书
//查询最新轮数
let jinduLunAll = await db.collection("answer-level-schedule")
.where({
user_id: userId,
level_num: 1,
status: db.command.neq(2)
})
.count()
if (jinduLunAll.total == 0) {
//完成 是否有证书 没有则增加证书及时间
let timee = null
let user = await db.collection("uni-id-users")
.where({
_id: userId,
is_certificate: 1
})
.limit(1)
.get()
const thisTime = Date.parse(new Date());
if (user.data.length == 0) {
await db.collection("uni-id-users")
.where({
_id: userId
})
.update({
is_certificate: 1
})
// 添加到证书表
let cert = await db.collection("answer-certificate")
.orderBy('ranking', 'desc')
.limit(1)
.get()
// 添加到证书表
if (cert.data.length == 0) {
await db.collection("answer-certificate")
.add({
ranking: 1,
user_id: userId
})
code = 200
message = 1
} else {
await db.collection("answer-certificate")
.add({
ranking: (cert.data[0].ranking + 1),
user_id: userId
})
code = 200
message = (cert.data[0].ranking + 1)
}
} else {
let cert = await db.collection("answer-certificate")
.where({
user_id: userId
})
.get()
if (cert.data.length > 0) {
code = 200
message = cert.data[0].ranking
}
}
}
return {
code: code, // 200:已经通关 message为排名 0:未通关 返回结果
message: message //
};
// return res
},
/**
* 重新闯关
* @param {Object} userId
*/
async againAnswer(scheduleId, userId, levelNum) {
await db.collection("answer-level-schedule")
.where({
_id: scheduleId
})
.update({
question_id: "",
level_num: levelNum + 1,
status: 1
})
return await db.collection('answer-deduct-record')
.where({
schedul_id: scheduleId,
user_id: userId
})
.update({
is_statistic: 0 //不统计
});
//查询最新轮数
// let jinduLun = await db.collection("answer-level-schedule")
// .where({
// user_id: userId
// })
// .orderBy('level_num', 'desc')
// .limit(1)
// .get()
// 查询最新关卡
// 执行连表查询
// let guanka = await db.collection('answer-level-question')
// .aggregate()
// .lookup({
// from: 'answer-level',
// localField: 'level_id', // table1 中的关联字段
// foreignField: '_id', // table2 中的关联字段
// as: 'result' // 查询结果的字段名
// // cond: {status: 1}
// })
// .match({
// status: 1
// }) // 添加第二个表的查询条件
// .end()
// const guankaGroup = guanka.data.reduce((result, item) => {
// const category = item.level_id;
// const level_order = item.result[0].level_order;
// let group = result.find(group => group.key === category);
// // 如果该分类还不存在,则创建一个新的分类
// if (!group) {
// group = {
// key: category,
// level_order: level_order,
// items: []
// };
// result.push(group);
// }
// // 将当前对象添加到该分类下
// group.items.push(item);
// return result;
// }, []);
// //判断题库是否为空
// if (guankaGroup.length > 0) {
// //循环新增
// guankaGroup.forEach((item, index, arr) => {
// if (item.level_order == 1) {
// //新增中间表option数据
// db.collection('answer-level-schedule')
// .add({
// level_id: item.key,
// question_id: null,
// level_allsche: item.items.length, //进度数
// level_thissche: 0,
// level_num: jinduLun.data[0].level_num, //答题轮数
// status: 1, //可以答题
// user_id: userId,
// level_order: item.level_order
// })
// } else {
// //新增中间表option数据
// db.collection('answer-level-schedule')
// .add({
// level_id: item.key,
// question_id: null,
// level_allsche: item.items.length, //进度数
// level_thissche: 0,
// level_num: jinduLun.data[0].level_num, //答题轮数
// status: 0, //未开始
// user_id: userId,
// level_order: item.level_order
// })
// }
// })
// }
},
/**
* 获得用户该地区的分数的排行榜
* @param {Object} useId
*/
async getRanking(useId) {
const result = await db.collection("uni-id-users").aggregate()
.lookup({
from: 'answer-deduct-record',
localField: '_id',
foreignField: 'user_id',
as: 'fenshu'
})
.match({
is_certificate: 1
})
.lookup({
from: 'opendb-city-china',
localField: 'adress',
foreignField: 'code',
as: 'city',
})
.end();
//查询市级
let allShi = await db.collection("opendb-city-china")
.where({
type: 1
})
.get()
//联查
const resultusers = result.data.map(user => {
const userOrders = allShi.data.filter(order => order.code === user.city[0].parent_code);
return {
...user,
userOrders //市区
};
});
//分组
const guankaGroup = resultusers.reduce((result, item) => {
const code = item.userOrders[0].code;
const name = item.userOrders[0].name;
let koufenshu = 0;
if (item.fenshu != null && item.fenshu.length > 0) {
koufenshu = item.fenshu.filter(sc => sc.is_statistic == 1).length
// koufenshu = 3koufenshu
}
let fen = item.fenshu //分数的集合
let group = result.find(group => group.key === code);
// 如果该分类还不存在,则创建一个新的分类
if (!group) {
group = {
key: code,
name: name,
isUser: 0,
zongkoufen: 0,
persionSize: 0,
items: []
};
result.push(group);
}
group.zongkoufen += koufenshu
// 将当前对象添加到该分类下
group.items.push(item);
group.persionSize++;
return result;
}, []);
guankaGroup.sort((a, b) => (a.zongkoufen / a.persionSize) - (b.zongkoufen / b.persionSize))
//查询用户的市
let user = await db.collection("uni-id-users")
.where({
_id: useId
})
.get()
let shicode = null
if (user != null && user.data[0].adress != null) {
let userAddress = await db.collection("opendb-city-china")
.where({
code: user.data[0].adress
})
.get()
shicode = userAddress.data[0].parent_code
}
if (shicode != null) {
guankaGroup.forEach((item, index, arr) => {
if (item.key == shicode) {
item.isUser = 1;
}
})
}
// return rest
// let filteredData = result.data.filter(item => item._idbangding.length > 0 && item.level_numbangding
// .length > 0);
//按照用户分组
// const guankaGroup = result.reduce((result, item) => {
// const category = item.level_id;
// const level_order = item.result[0].level_order;
// let group = result.find(group => group.key === category);
// // 如果该分类还不存在,则创建一个新的分类
// if (!group) {
// group = {
// key: category,
// level_order: level_order,
// items: []
// };
// result.push(group);
// }
// // 将当前对象添加到该分类下
// group.items.push(item);
// return result;
// }, []);
return guankaGroup
// let rest = await db.collection('uni-id-users')
// .aggregate()
// .lookup({
// from: 'opendb-city-china',
// localField: 'adress',
// foreignField: 'code',
// as: 'users',
// })
// .match({
// is_certificate: 1
// })
// .lookup({
// from: 'opendb-city-china',
// localField: 'adress',
// foreignField: 'code',
// as: 'users',
// })
// .match({
// is_certificate: 1
// })
// // .sort({
// // users:-1
// // })
// .end(); //联查
// let filteredData = rest.data.filter(item => item.users.length > 0 && item.users[0].type == 2);
// //查询市级
// let allShi = await db.collection("opendb-city-china")
// .where({
// type: 1
// })
// .get()
// //联查
// const result = filteredData.map(user => {
// const userOrders = allShi.data.filter(order => order.code === user.users[0].parent_code);
// return {
// ...user,
// userOrders
// };
// });
// //分组
// const guankaGroup = result.reduce((result, item) => {
// const code = item.userOrders[0].code;
// const name = item.userOrders[0].name;
// let group = result.find(group => group.key === code);
// // 如果该分类还不存在,则创建一个新的分类
// if (!group) {
// group = {
// key: code,
// name: name,
// isUser: 0,
// items: []
// };
// result.push(group);
// }
// // 将当前对象添加到该分类下
// group.items.push(item);
// return result;
// }, []);
// guankaGroup.sort((a, b) => b.items.length - a.items.length)
// //查询用户的市
// let user = await db.collection("uni-id-users")
// .where({
// _id: useId
// })
// .get()
// let shicode = null
// if (user != null && user.data[0].adress != null) {
// let userAddress = await db.collection("opendb-city-china")
// .where({
// code: user.data[0].adress
// })
// .get()
// shicode = userAddress.data[0].parent_code
// }
// if (shicode != null) {
// guankaGroup.forEach((item, index, arr) => {
// if (item.key == shicode) {
// item.isUser = 1;
// }
// })
// }
// return rest
},
/**
* 获取城市获奖数量排行榜
* @param {Object} useId
*/
async getRankingNum(useId) {
let rest = await db.collection('uni-id-users')
.aggregate()
.lookup({
from: 'opendb-city-china',
localField: 'adress',
foreignField: 'code',
as: 'citys',
})
.match({
is_certificate: 1
})
.end(); //联查
let filteredData = rest.data.filter(item => item.citys.length > 0 && item.citys[0].type == 2);
//查询市级
let allShi = await db.collection("opendb-city-china")
.where({
type: 1
})
.get()
//联查
const result = filteredData.map(user => {
const cityshis = allShi.data.filter(order => order.code === user.citys[0].parent_code);
return {
...user,
cityshis
};
});
//分组
const guankaGroup = result.reduce((result, item) => {
const code = item.cityshis[0].code;
const name = item.cityshis[0].name;
let group = result.find(group => group.key === code);
// 如果该分类还不存在,则创建一个新的分类
if (!group) {
group = {
key: code,
name: name,
isUser: 0,
items: []
};
result.push(group);
}
// 将当前对象添加到该分类下
group.items.push(item);
return result;
}, []);
guankaGroup.sort((a, b) => b.items.length - a.items.length)
//查询用户的市
let user = await db.collection("uni-id-users")
.where({
_id: useId
})
.get()
let shicode = null
if (user != null &&user.data.length > 0 && user.data[0].adress != null) {
let userAddress = await db.collection("opendb-city-china")
.where({
code: user.data[0].adress
})
.get()
shicode = userAddress.data[0].parent_code
}
if (shicode != null) {
guankaGroup.forEach((item, index, arr) => {
if (item.key == shicode) {
item.isUser = 1;
}
})
}
return guankaGroup
},
/**
* 获取城市获奖数量排行榜分页
* @param {Object} useId
*/
async getRankingNumPage(useId, pageNum, pageSize) {
let bangdans = this.getRankingNum(userId);
//手动分页
const startIndex = (pageNum - 1) * pageSize;
const endIndex = startIndex + pageSize;
return bangdans.slice(startIndex, endIndex);
}
}