移动app

This commit is contained in:
2023-09-24 17:55:19 +08:00
parent 736c5376e0
commit 59f7e39791
735 changed files with 80523 additions and 57 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
{
"name": "uni-im-co",
"dependencies": {
"jsonwebtoken": "^8.5.1",
"md5": "^2.3.0",
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-id-common": "file:../../../../uni-id-common/uniCloud/cloudfunctions/common/uni-id-common"
},
"extensions": {
"uni-cloud-jql": {},
"uni-cloud-push": {}
},
"version": "1.0.0",
"main": "index.obj.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"cloudfunction-config": {
"path": "/uni-im-co"
}
}

View File

@@ -0,0 +1,22 @@
// 本文件中的内容将在云对象【运行】时解析为运行参数
// 配置教程参考https://uniapp.dcloud.net.cn/uniCloud/rundebug.html#run-obj-param
// const clientInfo = { // 模拟clientInfo
// uniPlatform: 'web',
// appId:"__UNI__HelloUniApp",
// deviceId:"1672732026351278597",
// source: 'client', // 调用来源,不传时默认为 client
// clientIP: '127.0.0.1', // 客户端ip不传时默认为 127.0.0.1
// userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", // 客户端ua不传时默认为 HBuilderX
// uniIdToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI2M2FiZTVhNjkwYjI2ZDAwMDEyYzRkMjkiLCJyb2xlIjpbXSwicGVybWlzc2lvbiI6W10sInVuaUlkVmVyc2lvbiI6IjEuMC4xMyIsImlhdCI6MTY3MjgxOTEzOSwiZXhwIjoxNjcyODI2MzM5fQ.yxHlFOtr31UwUQ9FB56ZB2BoKNV6aJATEJ0xLZAZDUY'
// }
// chooseUserIntoGroup({
// user_ids:['63abe5d85125130001302e6b'],
// group_id:"63b5361b26b3d800018ace7f"
// })
chatCompletion({messages:[
{
"content": "请提供一个关于软件产品宣传文章的大纲",
"role": "user"
}
]})

View File

@@ -0,0 +1,130 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database();
const dbCmd = db.command
module.exports = {
trigger: {
async afterReadAsSecondaryCollection(e) {
await afterReadAction(e, true)
},
async afterRead(e) {
await afterReadAction(e)
}
}
}
async function afterReadAction({
field,
result,
userInfo: currentUserInfo,
primaryCollection
} = {}, asSecondaryCollection = false) {
if (result && field && field.includes("nickname")) {
//uni-im 处理查询nickname但值为空的情况
let {
data
} = result
if( !Array.isArray(data) ){
// 说明走了 getOne
data = [data]
}
// 为联查 且为副表时的字段
if (asSecondaryCollection && typeof(data[0]) == "object") {
let foreignKeysObj = {
"uni-im-group-member":"user_id",
"uni-im-friend":"friend_uid"
}
let foreignKey = foreignKeysObj[primaryCollection]
if(foreignKey in data[0]){
data = data.map(item => item[foreignKey][0])
}else{
return console.log('触发器uni-id-users.schema.ext.js未在当前操作生效。如需应用此触发器请补充主表表名及其foreignKey的值到触发器uni-id-users.schema.ext.js的变量foreignKeysObj内');
}
}
// console.log('data',data);
if (!Array.isArray(data)) {
data = [data]
}
// 记录没有nickname的用户id
let user_ids = [],
usersInfo = {};
data.forEach(item => {
if (item && !item.nickname) {
user_ids.push(item._id)
}
})
if (user_ids.length) {
console.info('注意uni-im项目用户数据依赖nickname。有' + user_ids.length +
`个用户数据 nickname 的值为空已多执行一次数据库查询将此用户的“用户名”或“邮箱”或“手机号”脱敏后作为nickname输出。请引导用户完善nickname减少查库次数`)
let res = await db.collection('uni-id-users')
.where({
_id: dbCmd.in(user_ids)
})
.field({
username: true,
email: true,
mobile: true
})
.limit(1000)
.get()
usersInfo = res.data.reduce((sum, current) => {
sum[current._id] = current
return sum
}, {})
}
let isUniImAdmin = currentUserInfo.role.includes('uni-im-admin') || currentUserInfo.role.includes('admin')
data.forEach(item => {
if (!item.nickname) {
let userInfo = usersInfo[item._id]
// 管理员可以看到不打码的
if (isUniImAdmin) {
item.nickname = userInfo.username || userInfo.email || userInfo.mobile
}else{
item.nickname = hideUsernameStr(userInfo.username) || hideEmailStr(userInfo.email) ||
hideMobileStr(userInfo.mobile)
}
}else if(!isUniImAdmin && item.nickname.includes('@')){
// 禁止昵称用邮箱 脱敏处理
item.nickname = hideEmailStr(item.nickname)
}
// 特殊处理某个用户xxx
if (item._id == "xxx") {
item.nickname = "xxx"
item.avatar_file = {
url: "xxx"
}
}
})
function hideUsernameStr(username) {
if (username == undefined) {
return false
}
let length = username.length
let n = parseInt(length / 2.5) * 2
return username.substr(0, length - n) + '**' + username.substr(-1 * n / 2)
}
function hideEmailStr(email) {
if (email == undefined) {
return false
}
const content = email.split("@")
return content[0].substr(0, content[0].length - 2) + '**' + content[1]
}
function hideMobileStr(mobile) {
if (mobile == undefined) {
return false
}
return mobile.substr(0, 3) + '****' + mobile.substr(-1 * 4)
}
}
}

View File

@@ -0,0 +1,273 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database();
module.exports = {
trigger: {
async beforeCreate({addDataList,userInfo}){
// 如无特殊修改 此查库校验可以在,上线后删除 -- 调试专用
if (addDataList.length === 1) {
let [data] = addDataList
let {user_id,friend_uid,group_id} = data
let where = {user_id}
if(friend_uid){
where.friend_uid = friend_uid
}else if(group_id){
where.group_id = group_id
}else{
throw new Error('uni-im-conversation.schema.ext.js beforeCreate:friend_uid或group_id必传')
}
data.type = friend_uid ? 1:2
const conversationId = getConversationId([user_id,friend_uid])
where.id = conversationId
data.id = conversationId
data.create_time = Date.now()
let res = await db.collection('uni-im-conversation')
.where(where)
.get()
if(res.data.length){
throw new Error('重复的会话记录')
}
} else {
throw new Error('非法参数,触发器阻止了批量添加')
}
},
async afterCreate({
addDataList,
clientInfo
}) {
if (addDataList.length === 1) {
let [data] = addDataList
let {user_id,friend_uid} = data
data.user_id = friend_uid
data.friend_uid = user_id
let res = await db.collection('uni-im-conversation').add(data)
// console.log(res,'同步添加会话');
} else {
throw new Error('非法参数')
}
},
async beforeDelete({
where
}) {
},
async afterUpdate({where,updateData,userInfo}){
// 只能更新未读数其他暂不开放
if( !(Object.keys(updateData).length === 1 && 'unread_count' in updateData ) ){
throw new Error('uni-im-conversation.schema.ext.js afterUpdate:限制只能更新 未读消息数')
}
// 设置当前会话的未读消息数为0则设置此会话发给当前用户的消息 是否已读为 true
if(where.user_id == userInfo.uid && updateData.unread_count === 0){
let res = await db.collection('uni-im-msg').where({
to_uid:userInfo.uid,
conversation_id:where.id,
is_read:false
}).update({
is_read:true
})
// console.log('uni-im-conversation afterUpdate res:',res);
}
}
}
}
function getConversationId(param) {
return 'single' + '_' + MD5(param.sort().toString())
}
function MD5(sMessage) {
function RotateLeft(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
function AddUnsigned(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
if (lX4 | lY4) {
if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
} else return (lResult ^ lX8 ^ lY8);
}
function F(x, y, z) {
return (x & y) | ((~x) & z);
}
function G(x, y, z) {
return (x & z) | (y & (~z));
}
function H(x, y, z) {
return (x ^ y ^ z);
}
function I(x, y, z) {
return (y ^ (x | (~z)));
}
function FF(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function GG(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function HH(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function II(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function ConvertToWordArray(sMessage) {
var lWordCount;
var lMessageLength = sMessage.length;
var lNumberOfWords_temp1 = lMessageLength + 8;
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (sMessage.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
}
function WordToHex(lValue) {
var WordToHexValue = "",
WordToHexValue_temp = "",
lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
}
return WordToHexValue;
}
var x = Array();
var k, AA, BB, CC, DD, a, b, c, d
var S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22;
var S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20;
var S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23;
var S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21;
x = ConvertToWordArray(sMessage);
a = 0x67452301;
b = 0xEFCDAB89;
c = 0x98BADCFE;
d = 0x10325476;
for (k = 0; k < x.length; k += 16) {
AA = a;
BB = b;
CC = c;
DD = d;
a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
a = AddUnsigned(a, AA);
b = AddUnsigned(b, BB);
c = AddUnsigned(c, CC);
d = AddUnsigned(d, DD);
}
var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);
return temp.toLowerCase();
}

View File

@@ -0,0 +1,63 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": [],
"permission": {
"read": "doc.user_id == auth.uid",
"create": true, // 触发器内限制
"update": "doc.user_id == auth.uid", // 触发器内限制只能更新 未读消息数
"delete": false
},
"properties": {
"_id": {
"description": "ID系统自动生成",
"permission": {
"write": false
}
},
"id": {
"description": "会话ID由会话双方用户的id按一定规律排序后的哈希值",
"permission": {
"write": false //由触发器生成,用户不能自定义
}
},
"type": {
"description": "会话类型,区分:群聊和单聊",
"bsonType": "int",
"label": "会话类型",
"permission": {
"write": false //由触发器生成,用户不能自定义
}
},
"user_id": {
"description": "所属用户id",
"bsonType": "string",
"forceDefaultValue":{
"$env": "uid"
},
"foreignKey": "uni-id-users._id"
},
"friend_uid": {
"description": "对话的好友的用户id"
},
"group_id": {
"description": "对话的群id",
"foreignKey": "uni-im-group._id"
},
"unread_count": {
"description": "未读消息数量",
"bsonType": "int",
"defaultValue":0
},
"last_msg_note": {
"description": "最后一条消息概述文本消息的前n个字消息为多媒体时只描述类型"
},
"update_time": {
"bsonType": "timestamp",
"description": "最后一次会话时间",
"defaultValue":{
"$env":"now"
}
}
}
}

View File

@@ -0,0 +1,178 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database();
module.exports = {
trigger: {
async beforeCreate({
addDataList,
userInfo,
clientInfo
}) {
if(!userInfo.role.includes('admin')){
throw new Error('没有权限操作')
}
/*
if (addDataList.length === 1) {
const [{
from_uid,
to_uid,
message
}] = addDataList
if (userInfo.uid == to_uid) {
throw new Error('不能加自己为好友')
}
let {
data: [has]
} = await db.collection('uni-im-friend').where({
user_id: from_uid,
friend_uid: to_uid
}).get()
console.error(has)
if (has) {
throw new Error('已经是好友')
}
let res = await db.collection('uni-im-friend-invite').where({
from_uid,
to_uid
}).get()
if (res.data.length) {
const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
dbJQL.setUser({
uid: from_uid, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})
await dbJQL.collection('uni-im-friend-invite').where({
from_uid,
to_uid
}).update(addDataList[0])
throw new Error('alreadyExists')
}
} else {
throw new Error('参数错误')
}
*/
},
async afterCreate({
result,
addDataList: [addData]
}) {
//发消息通知 被邀请加好友的用户
// addData._id = result.id
let {
to_uid: user_id,
message
} = addData
await NotifyUsers({
user_id,
message,
doc_id: result.id
})
},
async beforeUpdate({
where,
updateData,
userInfo
}) {
// schema权限已经控制只能由被邀请人操作。或者admin用户操作
},
async afterUpdate({
result,
updateData,
clientInfo,
where
}) {
console.error(result.updated);
if(result.updated === 0){
console.log('没有更新');
return
}
if (updateData.state == 100) { // cancel
let {
data: [friendInviteData]
} = await db.collection('uni-im-friend-invite')
.doc(where._id)
.get()
// console.log(friendInviteData);
const {
from_uid,
to_uid
} = friendInviteData
// 把相关的重复的加好友请求都设置为通过
await db.collection('uni-im-friend-invite')
.where(
db.command.or([
{
"from_uid":to_uid,
"to_uid":from_uid
},
{
to_uid,
from_uid
}
])
)
.update({
state:100
})
const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
dbJQL.setUser({
uid: to_uid, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})
let res = await dbJQL.collection('uni-im-friend').add({
friend_uid: from_uid
})
// console.log(res.data);
}
}
}
}
async function NotifyUsers({
user_id,
message,
doc_id
}) {
console.error('此逻辑已经废除')
throw new Error("次方法已废除")
let title = '好友请求通知',
content = '好友请求通知'
let pushParam = {
user_id,
payload: {
type: "uni-im-notification", // im消息通知比如加好友请求有用户退群等
subType: "uni-im-friend-invite", // 通知子类型(可选)
title: "用户名xxx申请加你为好友", // 标题
content: message || "附加信息xxx", // 描述
createTime: Date.now(), // 创建时间
confirmText: "同意", // 确认按钮的文字(可选)
cancelText: "拒绝", // 取消按钮的文字(可选)
state: false, // 是否已经处理过 false 未处理confirm已确认cancel已拒绝可选
unique: "from_uid", // 去重字段,比如同一个用户重复申请加好友,通知数据始终只显示一条,但是会通知多次(可选)
data: { // 自定义的其他参数(可选)
"_id": doc_id,
"from_uid": "xxx"
}
},
title, // "收到im消息离线时显示的标题",
content, //"离线时显示的内容"
path: false
}
const uniImCo = uniCloud.importObject("uni-im-co")
res = await uniImCo.sendPushMsg(pushParam,clientInfo.appId)
return res
}

View File

@@ -0,0 +1,69 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": [],
"permission": {
"read": "doc.to_uid == auth.uid || doc.from_uid == auth.uid",
"create": true,
"update": "doc.to_uid == auth.uid",
"delete": "doc.to_uid == auth.uid"
},
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"from_uid": {
"description": "发出邀请的用户id",
"bsonType": "string",
"forceDefaultValue": {
"$env": "uid"
},
"foreignKey": "uni-id-users._id"
},
"to_uid": {
"defaultValue": "接收邀请的用户id",
"bsonType": "string",
"enum": {
"collection": "uni-id-users",
"field": "_id as value,username as text"
},
"foreignKey": "uni-id-users._id"
},
"message": {
"bsonType": "string",
"description": "申请加群的验证或请求信息"
},
"creat_time": {
"bsonType": "timestamp",
"description": "申请入群时间",
"forceDefaultValue": {
"$env": "now"
}
},
"state": {
"bsonType": "int",
"description": "状态",
"enum": [{
"text": "待处理",
"value": 0
},
{
"text": "已同意",
"value": 100
},
{
"text": "已拒绝",
"value": -100
}
],
"forceDefaultValue": 0
},
"update_time": {
"bsonType": "timestamp",
"description": "更新申请入群时间(多次申请加入更新此字段)",
"forceDefaultValue": {
"$env": "now"
}
}
}
}

View File

@@ -0,0 +1,376 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database();
const dbCmd = db.command
module.exports = {
trigger: {
async afterCreate({
addDataList,
clientInfo
}) {
if (addDataList.length === 1) {
// a加b为好友 自动 将b加a为好友
let [data] = addDataList
let {
friend_uid,
user_id
} = data
data.friend_uid = user_id
data.user_id = friend_uid
const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
let {data:userList} = await dbJQL.collection('uni-id-users').where({
"_id":dbCmd.in([friend_uid,user_id])
})
.field('_id,nickname,avatar_file')
.get()
let friendInfo = userList.filter(i=>i._id == friend_uid)[0]
let userInfo = userList.filter(i=>i._id == user_id)[0]
// console.log(12313132131,{userList,friendInfo,userInfo})
// console.log('do uni-im-friend afterCreate');
// console.log(data);
let res = await db.collection('uni-im-friend').add(data)
// console.log('1231', res);
dbJQL.setUser({
uid: user_id, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})
let conversationId = getConversationId([user_id, friend_uid])
res = await db.collection('uni-im-conversation')
.where({id:conversationId,friend_uid})
.get()
// 查询是否存在,防止未加好友时发起过会话重复创建
if(res.data.length === 0){
res = await dbJQL.collection('uni-im-conversation').add({
id: conversationId,
user_id,
friend_uid,
type: 1,
unread_count: 0
})
}else{
console.log('会话已存在')
}
//发消息通知 被邀请加好友的用户
let pushParam = {
"user_id": friend_uid,
"payload": {
type: "uni-im-notification",
subType: "uni-im-friend-add",
// avatar_file: userInfo.avatar_file, // 头像或图标的图片地址支持Base64
data: {
from_uid: user_id,
to_uid: friend_uid,
},
unique:[user_id,friend_uid].sort().join('_')
},
title:"成功加为好友通知",
content:'你已成功添加"'+ userInfo.nickname +'"为好友',
}
// console.log(123, pushParam);
const uniImCo = uniCloud.importObject("uni-im-co")
res = await uniImCo.sendPushMsg(pushParam,clientInfo.appId)
// console.log(8989989, res);
pushParam.user_id = user_id
pushParam.content = '你已成功添加"'+ friendInfo.nickname +'"为好友'
res = await uniImCo.sendPushMsg(pushParam,clientInfo.appId)
} else {
throw new Error('非法参数')
}
},
async beforeDelete({
where,
clientInfo
}) {
console.log('where',{where});
if (where && where.friend_uid) {
let {
data: [friendData]
} = await db.collection('uni-im-friend').where(where).get()
if (friendData) {
let {
friend_uid,
user_id
} = friendData
const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
let {data:userList} = await dbJQL.collection('uni-id-users').where({
"_id":dbCmd.in([friend_uid,user_id])
})
.field('_id,nickname,avatar_file')
.get()
let friendInfo = userList.filter(i=>i._id == friend_uid)[0]
let userInfo = userList.filter(i=>i._id == user_id)[0]
// console.log(12313132131,{userList,friendInfo,userInfo})
let res = await db.collection('uni-im-friend')
.where({
friend_uid: user_id,
user_id: friend_uid
})
.remove()
console.log('同步删除好友',res);
dbJQL.setUser({
uid: user_id, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})
let conversationId = getConversationId([user_id, friend_uid])
res = await dbJQL.collection('uni-im-conversation')
.where({
"id": conversationId
})
.remove()
console.log('同步删除相关会话',res);
//发消息通知 用户成功删除好友
let pushParam = {
"user_id": friend_uid, //群创建人id后续升级为所有群管理员id
"payload": {
type: "uni-im-notification", // im消息通知比如加好友请求有用户退群等
subType: "uni-im-friend-delete", // 通知子类型(可选)
// avatar_file: userInfo.avatar_file, // 头像或图标的图片地址支持Base64
data: {
conversationId,
from_uid:user_id,
to_uid:friend_uid
},
unique:[user_id,friend_uid].sort().join('_')
},
title:"好友关系解除通知",
content:'"'+ userInfo.nickname +'"与你解除好友关系'
}
// console.log(123, pushParam);
const uniImCo = uniCloud.importObject("uni-im-co")
res = await uniImCo.sendPushMsg(pushParam,clientInfo.appId)
// console.log(8989989, res);
pushParam.user_id = user_id
pushParam.content = '你已成功与"'+ friendInfo.nickname +'"解除好友关系'
res = await uniImCo.sendPushMsg(pushParam,clientInfo.appId)
// console.log(8989989, res);
} else {
throw new Error('不是好友')
}
} else {
throw new Error('非法参数1')
}
},
async afterRead({result}){
// 数据脱敏处理
result.data.forEach(item=>{
let friendInfo = item.friend_uid[0]
})
}
}
}
function getConversationId(param) {
return 'single' + '_' + MD5(param.sort().toString())
}
function MD5(sMessage) {
function RotateLeft(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
function AddUnsigned(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
if (lX4 | lY4) {
if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
} else return (lResult ^ lX8 ^ lY8);
}
function F(x, y, z) {
return (x & y) | ((~x) & z);
}
function G(x, y, z) {
return (x & z) | (y & (~z));
}
function H(x, y, z) {
return (x ^ y ^ z);
}
function I(x, y, z) {
return (y ^ (x | (~z)));
}
function FF(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function GG(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function HH(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function II(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
}
function ConvertToWordArray(sMessage) {
var lWordCount;
var lMessageLength = sMessage.length;
var lNumberOfWords_temp1 = lMessageLength + 8;
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (sMessage.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
}
function WordToHex(lValue) {
var WordToHexValue = "",
WordToHexValue_temp = "",
lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
}
return WordToHexValue;
}
var x = Array();
var k, AA, BB, CC, DD, a, b, c, d
var S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22;
var S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20;
var S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23;
var S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21;
x = ConvertToWordArray(sMessage);
a = 0x67452301;
b = 0xEFCDAB89;
c = 0x98BADCFE;
d = 0x10325476;
for (k = 0; k < x.length; k += 16) {
AA = a;
BB = b;
CC = c;
DD = d;
a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
a = AddUnsigned(a, AA);
b = AddUnsigned(b, BB);
c = AddUnsigned(c, CC);
d = AddUnsigned(d, DD);
}
var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);
return temp.toLowerCase();
}

View File

@@ -0,0 +1,43 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": [],
"permission": {
"read": "doc.user_id == auth.uid",
"create": false,
"update": false,
"delete": "doc.user_id == auth.uid"
},
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"user_id":{
"description": "当前用户的id",
"foreignKey": "uni-id-users._id",
"forceDefaultValue":{
"$env": "uid"
}
},
"friend_uid":{
"description": "好友的用户id",
"foreignKey": "uni-id-users._id",
"enum": {
"collection": "uni-id-users",
"field": "_id as value,username as text"
}
},
"mark":{
"description": "标记备注"
},
"class_name":{
"description": "分组名称"
},
"create_time":{
"bsonType": "timestamp",
"forceDefaultValue":{
"$env": "now"
}
}
}
}

View File

@@ -0,0 +1,188 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database()
let t = Date.now() + parseInt(Math.random() * 999999)
module.exports = {
trigger: {
async beforeCreate({
addDataList,
clientInfo
}) {
const dbJQL = uniCloud.databaseForJQL({
clientInfo,
})
if (addDataList.length === 1) {
let [{
group_id
}] = addDataList
// 1. 群是否存在,并获取群信息
let res = await db.collection('uni-im-group').doc(group_id).get()
if (res.data.length == 0) {
throw new Error('非法群id')
}
// console.log('res.data', res.data);
const groupInfo = res.data[0]
if (groupInfo.join_option == "disableApply") {
throw new Error('此群禁止任何人申请加入')
}else{
//到after中处理
}
// 2. 判断是不是本身已经是群成员
res = await dbJQL.collection('uni-im-group-member')
.where(`"group_id" == "${group_id}" && "user_id" == $cloudEnv_uid`)
.get()
if (res.data.length != 0) {
throw new Error('已经是群成员')
}
} else {
throw new Error('非法参数')
}
},
async afterCreate({
addDataList,
clientInfo,
result
}) {
let [{
_id,user_id,group_id,message
}] = addDataList
// console.log('addDataList',addDataList);
// console.log('clientInfo',clientInfo);
let res = await db.collection('uni-im-group').doc(group_id).get()
if (res.data.length == 0) {
throw new Error('非法群id')
}
const groupInfo = res.data[0]
const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
if (groupInfo.join_option == "freeAccess") {
dbJQL.setUser({
uid: user_id, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})
//直接给通过
await dbJQL.collection('uni-im-group-join').where({
user_id,group_id
}).update({
state: 100
})
} else if(groupInfo.join_option == "needPermission"){
let {
data: [userInfo]
} = await dbJQL.collection('uni-id-users')
.where(`"_id" == $cloudEnv_uid`)
.field('nickname,_id,avatar_file')
.get()
console.log(userInfo);
let title = userInfo.nickname,
content = "申请加入 "+groupInfo.name + "\n" + message
let pushParam = {
"user_id": groupInfo.user_id, //群创建人id后续升级为所有群管理员id
"payload": {
type: "uni-im-notification", // im消息通知比如加好友请求有用户退群等
subType: "uni-im-group-join-request", // 通知子类型(可选)
confirmText: "同意", // 确认按钮的文字(可选)
cancelText: "拒绝", // 取消按钮的文字(可选)
state: false, // 是否已经处理过 false 未处理confirm已确认cancel已拒绝可选
unique: userInfo._id + '_' + groupInfo._id, // 去重字段,比如同一个用户重复申请加好友,通知数据始终只显示一条,但是会通知多次(可选)
data: { // 自定义的其他参数(可选)
userInfo,
groupInfo,
doc_id:result.id
},
avatar_file: userInfo.avatar_file, // 头像或图标的图片地址支持Base64
},
title,
content
}
// console.log(123, pushParam);
//发消息通知群主,有用户申请加入群聊
const uniImCo = uniCloud.importObject("uni-im-co")
res = await uniImCo.sendPushMsg(pushParam,clientInfo.appId)
// console.log(8989989, res);
// 删除之前提交的
// res = await db.collection('uni-im-group-join')
// .where({
// group_id,
// user_id: userInfo._id
// })
// .remove()
// console.log('res 把旧的删了',res);
}
},
async beforeRead({
where,
clientInfo
}) {
//获取自己的加群列表不走clientDB
/*
// let {group_id} = where
console.log('where:',where)
let {data:[item]} = await db.collection('uni-im-group-member').where({group_id}).get()
if(!item.role.includes('admin')){
throw new Error('仅群管理员可见')
}
where.group_id*/
},
async beforeUpdate({
where,
updateData,
clientInfo,
userInfo
}) {
// console.log(123,'where',where)
if (updateData.state == 100) {
let {
data: [item]
} = await db.collection('uni-im-group-join').where(where).get()
// console.log(item,clientInfo);
const {
user_id,
group_id
} = item
// console.log({group_id,user_id});
// 判断操作者必须是管理员由触发器触发时会设置role为admin或者群管理员
if(!userInfo.role.includes('admin') ){
let res = await db.collection('uni-im-group-member')
.where({group_id,user_id:userInfo.uid})
.get()
console.log('---',res.data);
if( !(res.data[0] && res.data[0].role.includes('admin')) ){
throw Error('没有权限')
}
}
const dbJQL = uniCloud.databaseForJQL({
clientInfo,
// skipTrigger:
})
// 添加操作权限
dbJQL.setUser({
uid: userInfo.uid, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})
//成为群成员
let res = await dbJQL.collection('uni-im-group-member').add({
group_id,
user_id,
})
// console.log('next', {
// res,
// updateData
// });
}
}
}
}

View File

@@ -0,0 +1,66 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": ["group_id"],
"permission": {
"read": true, // 在触发器内限制读的权限
"create": true,
"update": true,
"delete": false
},
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"group_id":{
"bsonType": "string",
"description": "群id",
"foreignKey": "uni-im-group._id"
},
"user_id":{
"bsonType": "string",
"description": "用户id",
"forceDefaultValue":{
"$env":"uid"
},
"foreignKey": "uni-id-users._id"
},
"message": {
"bsonType": "string",
"description": "申请加群的验证或请求信息"
},
"creat_time": {
"bsonType": "timestamp",
"description": "申请入群时间",
"forceDefaultValue": {
"$env": "now"
}
},
"state": {
"bsonType": "int",
"description": "状态",
"enum":[
{
"text":"待处理",
"value":0
},
{
"text":"已同意",
"value":100
},
{
"text":"已拒绝",
"value":-100
}
],
"forceDefaultValue": 0
},
"update_time": {
"bsonType": "timestamp",
"description": "更新申请入群时间(多次申请加入更新此字段)",
"forceDefaultValue": {
"$env": "now"
}
}
}
}

View File

@@ -0,0 +1,206 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database();
module.exports = {
trigger: {
async beforeRead({
where,
userInfo
}) {
if (where.user_id != userInfo.uid) {
if (where.group_id) {
let res = await db.collection('uni-im-group-member')
.where({
group_id: where.group_id,
user_id: userInfo.uid
})
.get()
console.log(res);
if (res.data.length === 0) {
throw new Error('不是群成员,不能查询')
}
}
}
},
async afterCreate({
addDataList: [addData],
clientInfo
}) {
// 仅管理员可操作
// console.log('addData', addData);
let {
group_id,
user_id
} = addData
// 1. 群是否存在
let res = await db.collection('uni-im-group').doc(group_id).get()
if (res.data.length == 0) {
throw new Error('非法群id')
}
// console.log('res.data', res.data);
const groupInfo = res.data[0]
res = await db.collection('uni-im-conversation').add({
group_id,
id: 'group_' + group_id,
user_id,
type: 2,
unread_count: 0,
update_time: Date.now()
})
// console.log('add uni-im-conversation:', res);
const uniImCo = uniCloud.importObject("uni-im-co")
const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
//推送时带上userInfo节省客户端查库
let {
data: [userInfo]
} = await dbJQL.collection('uni-id-users')
.doc(user_id)
.field('_id,nickname,avatar_file')
.get()
// 通知用户
let title = "新用户加群通知",
content = "新用户加群通知",
pushParam = {
payload: {
"type": "uni-im",
"data": {
type: "system",
action: "join-group-notice",
from_uid: "system",
//是否已读默认为false
is_read: false,
//创建时间
create_time: Date.now(),
conversation_id: "group_" + group_id,
group_id,
body: {
user_list: [userInfo]
}
},
title, // "收到im消息在线时显示的标题",
content, // "在线时显示的副标题",
},
title, // "收到im消息离线时显示的标题",
content //"离线时显示的内容"
}
//发消息通知所有群成员,有用户申请加入群聊
res = await uniImCo.sendMsgToGroup({
pushParam,
appId:clientInfo.appId
})
// console.log(8989989, res);
},
async beforeDelete({
where,
userInfo,
triggerContext
}) {
console.log('where---', where);
let {
group_id,
user_id
} = where
//查群相关信息
let res = await db.collection('uni-im-group').doc(group_id).get()
if(!triggerContext){
throw new Error('执行删除群失败你的HBuilderX版本过低请使用3.6.16及以上版本')
}
triggerContext.groupInfo = res.data[0]
console.log(res.data[0]);
console.log(res.data[0].user_id);
if (
!(res.data[0].user_id == userInfo.uid || userInfo.uid == user_id)
) {
throw Error('限群主和自己操作退群')
}
console.log(res.data, {
group_id,
user_id: user_id
});
if (res.data[0].user_id == user_id) {
throw Error('群主不能退群')
}
},
async afterDelete({
where,
userInfo,
clientInfo,
triggerContext
}) {
console.error('2 where---', where);
let {
group_id,
user_id
} = where
// 删除相关会话数据
let res = await db.collection('uni-im-conversation').where({
group_id,
user_id
}).remove()
console.error('Delete uni-im-conversation:', res, where);
const dbJQL = uniCloud.databaseForJQL({
clientInfo
})
let {
data: [currentUserInfo]
} = await dbJQL.collection('uni-id-users')
.doc(user_id)
.field('_id,nickname,avatar_file')
.get()
let title, content, type;
//自己操作的是 主动退出的 否则是被踢掉的
if (userInfo.uid == user_id) {
title = '用户退群通知'
content = currentUserInfo.nickname + ' 已退出群聊'
type = "uni-im-group-exit"
} else {
title = '用户被踢出群聊通知'
content = currentUserInfo.nickname + ' 已被踢出群聊'
type = "uni-im-group-expel"
}
let pushParam = {
payload: {
data: {
user_id,
group_id,
timestamp: Date.now()
},
type
},
title, // "收到im消息离线时显示的标题",
content, //"离线时显示的内容"
}
console.error(123, pushParam);
const uniImCo = uniCloud.importObject("uni-im-co")
//通知所有群成员,有用户退群
res = await uniImCo.sendMsgToGroup({
pushParam,
appId:clientInfo.appId
})
//通知 被出群的用户(此时他已经不是群成员收不到sendMsgToGroup的通知)
pushParam.content = (userInfo.uid == user_id ? '你已退出"':'你已被踢出"') + triggerContext.groupInfo.name +'"群'
pushParam.user_id = user_id
pushParam.payload.type = "uni-im-notification" // im消息通知比如加好友请求有用户退群等
pushParam.payload.subType = "uni-im-group-expel" // 通知子类型(可选)
pushParam.payload.state = false // 是否已经处理过 false 未处理confirm已确认cancel已拒绝可选
pushParam.payload.unique = user_id + '_' + group_id
res = await uniImCo.sendPushMsg(pushParam,clientInfo.appId)
}
}
}

View File

@@ -0,0 +1,46 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": [],
"permission": {
"read": true, //由触发器再次管理
"create": false,
"update": false,
"delete": true //由触发器再次管理
},
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"group_id":{
"bsonType": "string",
"description": "群id",
"foreignKey": "uni-im-group._id"
},
"user_id":{
"bsonType": "string",
"description": "用户id",
"foreignKey": "uni-id-users._id"
},
"role":{
"bsonType": "array",
"enum":[
{
"text":"创建者",
"value":"creator"
},
{
"text":"管理员",
"value":"admin"
}
]
},
"create_time": {
"bsonType": "timestamp",
"description": "入群时间",
"forceDefaultValue": {
"$env": "now"
}
}
}
}

View File

@@ -0,0 +1,89 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database();
module.exports = {
trigger: {
async afterCreate({
addDataList,
clientInfo,
result
}){
if(addDataList.length>1){
throw('禁止批量创建')
}
// console.log(result);
let res = await db.collection('uni-im-group').doc(result.id).get()
let data = res.data[0]
// console.log(data)
const dbJQL = uniCloud.databaseForJQL({
clientInfo,
})
// 添加操作权限
dbJQL.setUser({
uid: data.user_id, // 建议此处使用真实uid
role: ['admin'], // 指定当前执行用户的角色为admin。如果只希望指定为admin身份可以删除uid和permission节点
permission: []
})
res = await dbJQL.collection('uni-im-group-member').add({
"group_id":data._id,
"user_id":data.user_id,
"role":['creator','admin']
})
// console.log({res});
},
async beforeCreate({addDataList}){
},
async beforeDelete({where,userInfo,triggerContext}){
if(!triggerContext){
throw new Error('执行删除群失败你的HBuilderX版本过低请使用3.6.16及以上版本')
}
let {data:[groupInfo]} = await db.collection('uni-im-group').doc(where._id).get()
triggerContext.groupInfo = groupInfo
console.log('beforeDelete',where);
let {data:[has]} = await db.collection('uni-im-conversation')
.where({
group_id:where._id,
user_id:userInfo._id
})
.get()
if(!has){
throw new Error('限群创建者操作')
}
},
async afterDelete({where,clientInfo,triggerContext}){
console.log('beforeDelete',where,triggerContext);
const group_id = where._id
// 删除相关会话
let res = await db.collection('uni-im-conversation').where({group_id}).remove()
// 删除相关加群申请数据
res = await db.collection('uni-im-group-join').where({group_id}).remove()
// 通知所有群成员,注意:需要群成员列表清空之前发 要不然就收不到了
let title = "群聊被解散通知",
content = `群聊"${triggerContext.groupInfo.name}"已被解散`,
pushParam = {
payload: {
"type": "uni-im-notification",
"subType": "uni-im-group-cancellation",
"data": {
group_id
},
unique:group_id
},
title, // "收到im消息离线时显示的标题",
content //"离线时显示的内容"
}
const uniImCo = uniCloud.importObject("uni-im-co")
res = await uniImCo.sendMsgToGroup({pushParam,appId:clientInfo.appId})
// console.log(res);
// 删除相关群成员数据(注意:要先发群通知再解散,要不然消息发布出去“无法指定接收消息的人”)
res = await db.collection('uni-im-group-member').where({group_id}).remove()
console.log('beforeDelete',res);
}
}
}

View File

@@ -0,0 +1,69 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": ["name","join_option"],
"permission": {
"read": true,
"create": true,
"update": "auth.uid == doc.user_id",
"delete": "auth.uid == doc.user_id"
},
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"user_id":{
"bsonType": "string",
"description": "群主id",
"forceDefaultValue":{
"$env":"uid"
}
},
"name":{
"bsonType": "string",
"label": "群名称",
"maxLength": 30
},
"introduction":{
"bsonType": "string",
"label": "群简介",
"maxLength": 240
},
"notification":{
"bsonType": "string",
"label": "群公告",
"maxLength": 240
},
"avatar_file":{
"bsonType": "file",
"label": "群头像"
},
"join_option":{
"bsonType": "string",
"description": "申请加群选项",
"label": "申请加群方式",
"defaultValue":"needPermission",
"enum":[
{
"text": "需要验证权限",
"value": "needPermission"
},
{
"text": "自由加入",
"value": "freeAccess"
},
{
"text": "禁止加入",
"value": "disableApply"
}
]
},
"create_time": {
"bsonType": "timestamp",
"description": "群创建的时间戳",
"forceDefaultValue": {
"$env": "now"
}
}
}
}

View File

@@ -0,0 +1,43 @@
// schema扩展相关文档请参阅https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html
const db = uniCloud.database();
module.exports = {
trigger: {
async beforeRead({clientInfo,where,userInfo}){
// console.log('where',where);
const {conversation_id,to_uid} = where
if(conversation_id || to_uid){
if(to_uid == userInfo.uid){
//查发给当前用户的数据
}else if(conversation_id){
// console.log('conversation_id',conversation_id);
const dbJQL = uniCloud.databaseForJQL({
clientInfo,
skipTrigger: true
})
//判断当前用户id是否有这个会话否则无权接收此消息
let {data:conversations} = await dbJQL.collection('uni-im-conversation')
.where(`"id" == "${conversation_id}" && "user_id" == $cloudEnv_uid`)
.get()
// console.log('conversations',conversations);
if(conversations.length === 0){
throw new Error('会话id无效或此会话你无权服务user_id不等于当前用户')
}
// if(conversations[0].type == 2){ //2是群聊
// let {group_id} = conversations[0]
// let res = await dbJQL.collection('uni-im-group-member')
// .where(`"group_id" == "${group_id}" && "user_id" == $cloudEnv_uid`)
// .get()
// if(res.data.length == 0){
// throw new Error('不是此群人员,不能读取')
// }
// }
}else{
throw new Error('uni-im-msg触发器查询条件会话id或者to_uid错误')
}
}else{
throw new Error('触发器限制了查询条件必须包含会话id或者to_uid。如果要增加其他查询方式请自己扩充')
}
}
}
}

View File

@@ -0,0 +1,108 @@
{
"bsonType": "object",
"permission": {
"create": false,
"delete": false,
"read": true,// 在触发器中限制
"update": false
},
"required": [
"to_uid",
"body",
"type"
],
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"from_uid": {
"bsonType": "string",
"description": "消息发送方 UserID用于指定发送消息方帐号",
"forceDefaultValue": {
"$env": "uid"
}
},
"to_uid": {
"bsonType": "string",
"description": "消息接收方 UserID"
},
"conversation_id": {
"bsonType": "string",
"description": "conversation_id即消息的会话id",
"foreignKey": "uni-im-conversation.id"
},
"group_id": {
"bsonType": "string",
"description": "group_id即消息接收群的id"
},
"body": {
"description": "消息内容包含的键会随type变化。需要自己写valedateFunction验证"
},
"is_read": {
"bsonType": "bool",
"description": "是否已读",
"forceDefaultValue": false
},
"type": {
"bsonType": "string",
"enum": [
{
"text": "文本",
"value": "text"
},
{
"text": "图像",
"value": "image"
},
{
"text": "语音",
"value": "sound"
},
{
"text": "视频",
"value": "video"
},
{
"text": "文件",
"value": "file"
},
{
"text": "位置",
"value": "location"
}
]
},
"state": {
"bsonType": "int",
"description": "0 发送中100发送成功-100 发送失败,-200 禁止发送(内容不合法)"
},
"is_revoke":{
"bsonType": "bool",
"description": "是否被撤回",
"defaultValue": false
},
"about_msg_id":{
"bsonType": "string",
"description": "关于某条消息的id一般用于回复某一条消息",
"defaultValue": false
},
"appid":{
"bsonType": "string",
"description": "接收消息的appid"
},
"create_time": {
"bsonType": "timestamp",
"description": "消息发送时间戳",
"forceDefaultValue": {
"$env": "now"
}
},
"client_create_time": {
"bsonType": "timestamp",
"description": "客户端创建消息的时间戳",
"forceDefaultValue": {
"$env": "now"
}
}
}
}

View File

@@ -0,0 +1,23 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": [],
"permission": {
"read": true,
"create": false,
"update": "doc.user_id == auth.uid",
"delete": false
},
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"is_read":{
"bsonType": "bool",
"defaultValue":false
},
"payload":{
"state":{}
}
}
}

View File

@@ -0,0 +1,28 @@
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": [],
"permission": {
"read": true, //暂时就撤回消息任务,不做限制。后续在触发器内做相关限制
"create": false,
"update": false,
"delete": false
},
"properties": {
"_id": {
"description": "ID系统自动生成"
},
"type": {
"description": "任务名称"
},
"user_id": {
"description": "接收任务的用户id"
},
"group_id": {
"description": "接收任务的群id"
},
"payload":{
}
}
}