Browse Source

readme

master
xsx 1 year ago
parent
commit
b761c7f8c4
  1. 27
      README.md
  2. 2
      im-admin-ui/.env.development
  3. 2
      im-admin-ui/.env.production
  4. 51
      im-admin-ui/src/components/im/ImSmSelect/index.vue
  5. 2
      im-admin-ui/src/views/im/message/group/index.vue
  6. 2
      im-admin-ui/src/views/im/message/private/index.vue
  7. 128
      im-admin-ui/src/views/im/message/task/SmTaskInfo.vue
  8. 2
      im-admin/ruoyi-im/src/main/java/org/dromara/im/service/impl/ImUserServiceImpl.java
  9. BIN
      截图/1.jpg
  10. BIN
      截图/2.jpg
  11. BIN
      截图/3.jpg
  12. BIN
      截图/4.jpg
  13. BIN
      截图/5.jpg

27
README.md

@ -3,19 +3,17 @@
#### 介绍 #### 介绍
本项目为盒子IM后台管理,主要为盒子IM提供用户管理、群组管理、消息管理、敏感词管理等后台功能。 本项目为盒子IM后台管理,主要为盒子IM提供用户管理、群组管理、消息管理、敏感词管理等后台功能。
盒子IM前台代码地址:https://gitee.com/bluexsx/box-im 缺少后台管理基本不影响盒子IM的业务功能,建议先把业务服务跑起来,再来搭建后台服务:
业务代码地址:https://gitee.com/bluexsx/box-im
详细文档: https://www.yuque.com/u1475064/mufu2a 详细文档: https://www.yuque.com/u1475064/mufu2a
#### 基于RuoYi-Vue-Plus框架
为了减少重复工作,达到快速开发目的,本项目选择了一款优秀的开源脚手架RuoYi-Vue-Plus进行二次开发。
#### 基于maku框架 RuoYi-Vue-Plus的仓库:
为了减少重复工作,达到快速开发目的,本项目选择了一款优秀的开源脚手架-maku进行二次开发。 后端:https://gitee.com/dromara/RuoYi-Vue-Plus
前端: https://gitee.com/JavaLionLi/plus-ui
maku的仓库:
https://gitee.com/makunet/maku-boot
https://gitee.com/makunet/maku-admin
maku的文档:
https://maku.net/docs/maku-boot/index
#### 框架改造说明 #### 框架改造说明
为了更好地与盒子IM的业务相结合,同时保持代码的简洁性,对ruoyi-vue-plus框架进行了以下改造: 为了更好地与盒子IM的业务相结合,同时保持代码的简洁性,对ruoyi-vue-plus框架进行了以下改造:
@ -40,11 +38,11 @@ https://maku.net/docs/maku-boot/index
进入 im-admin目录,打开控制台 进入 im-admin目录,打开控制台
``` ```
mvn clean package mvn clean package
java -jar ./maku-server/target/im-admin.jar java -jar ./ruoyi-admin/target/im-admin.jar
``` ```
3.启动前端 3.启动前端
进入 maku-admin目录,打开控制台 进入 im-admin-ui目录,打开控制台
``` ```
npm install npm install
npm run dev npm run dev
@ -52,15 +50,8 @@ npm run dev
访问 http://localhost:3000 访问 http://localhost:3000
#### 界面截图: #### 界面截图:
![输入图片说明](%E6%88%AA%E5%9B%BE/1.png)
![输入图片说明](%E6%88%AA%E5%9B%BE/2.png)
![输入图片说明](%E6%88%AA%E5%9B%BE/3.png)
![输入图片说明](%E6%88%AA%E5%9B%BE/4.png)
![输入图片说明](%E6%88%AA%E5%9B%BE/5.png)
#### 点下star吧 #### 点下star吧

2
im-admin-ui/.env.development

@ -10,7 +10,7 @@ VITE_APP_BASE_API = '/api'
# 应用访问路径 例如使用前缀 /admin/ # 应用访问路径 例如使用前缀 /admin/
VITE_APP_CONTEXT_PATH = '/' VITE_APP_CONTEXT_PATH = '/'
VITE_APP_PORT = 80 VITE_APP_PORT = 3000
# 客户端id # 客户端id
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e' VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'

2
im-admin-ui/.env.production

@ -8,7 +8,7 @@ VITE_APP_ENV = 'production'
VITE_APP_CONTEXT_PATH = '/admin' VITE_APP_CONTEXT_PATH = '/admin'
# 生产环境 # 生产环境
VITE_APP_BASE_API = '/adm/api' VITE_APP_BASE_API = 'https://www.boxim.online/adm/api'
# 客户端id # 客户端id
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e' VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'

51
im-admin-ui/src/components/im/ImSmSelect/index.vue

@ -0,0 +1,51 @@
<template>
<el-select v-model="messageIds" :multiple="multiple" filterable remote clearable
:placeholder="placeholder" :remote-method="handleRemote" :loading="loading">
<el-option v-for="message in options" :key="message.id" :label="message.title" :value="message.id" />
</el-select>
</template>
<script setup lang="ts" name="ImSmSelect">
import { computed } from 'vue'
import { ref } from 'vue'
import { findSystemMessageByTitle } from '@/api/im/systemMessage'
const props = defineProps({
multiple: {
type: Boolean,
required: false,
default: () => false
},
placeholder: {
type: String,
required: false,
default: () => ''
}
})
const loading = ref(false)
const options = ref()
const model = defineModel<number | Array<Number> | string | Array<String>>()
const messageIds = computed({
get() {
if(model.value != undefined){
return model.value
}else if(props.multiple){
return []
}
},
set(value) {
model.value = value
}
})
const handleRemote = (title: string)=>{
loading.value = true
findSystemMessageByTitle(title).then((res) => {
loading.value = false;
options.value = res.data;
});
}
</script>

2
im-admin-ui/src/views/im/message/group/index.vue

@ -41,7 +41,7 @@
<el-table v-loading="loading" :data="groupMessageList" > <el-table v-loading="loading" :data="groupMessageList" >
<el-table-column label="群名" align="center" prop="groupName" /> <el-table-column label="群名" align="center" prop="groupName" />
<el-table-column label="发送用户" align="center" prop="sendUserName" /> <el-table-column label="发送用户" align="center" prop="sendUserName" />
<el-table-column label="发送内容" align="center" prop="content" > <el-table-column label="发送内容" align="center" prop="content" width="400">
<template #default="scope"> <template #default="scope">
<im-message-content :message="scope.row" ></im-message-content> <im-message-content :message="scope.row" ></im-message-content>
</template> </template>

2
im-admin-ui/src/views/im/message/private/index.vue

@ -47,7 +47,7 @@
<el-table v-loading="loading" :data="privateMessageList" > <el-table v-loading="loading" :data="privateMessageList" >
<el-table-column label="发送用户" align="center" prop="sendUserName" /> <el-table-column label="发送用户" align="center" prop="sendUserName" />
<el-table-column label="接收用户" align="center" prop="recvUserName" /> <el-table-column label="接收用户" align="center" prop="recvUserName" />
<el-table-column label="发送内容" align="center" prop="content" > <el-table-column label="发送内容" align="center" prop="content" width="400" >
<template #default="scope"> <template #default="scope">
<im-message-content :message="scope.row" ></im-message-content> <im-message-content :message="scope.row" ></im-message-content>
</template> </template>

128
im-admin-ui/src/views/im/message/task/SmTaskInfo.vue

@ -0,0 +1,128 @@
<template>
<!-- 添加或修改系统消息推送任务对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="80px">
<el-form-item label="系统消息" prop="messageId">
<im-sm-select v-model="form.messageId"></im-sm-select>
</el-form-item>
<el-form-item label="推送时间" prop="sendTime">
<el-date-picker clearable v-model="form.sendTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择推送时间">
</el-date-picker>
</el-form-item>
<el-form-item label="接收用户" prop="sendToAll">
<el-radio-group v-model="form.sendToAll">
<el-radio :value="true">全体用户</el-radio>
<el-radio :value="false">指定用户</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="!form.sendToAll">
<im-user-select v-model="recvIds" :multiple="true" placeholder="请选择最多20个用户"></im-user-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="SmTaskInfo" lang="ts">
import { getSmPushTask, addSmPushTask, updateSmPushTask } from '@/api/im/smPushTask';
import { SmPushTaskForm, SmPushTaskVO } from '@/api/im/smPushTask/types';
import { parseTime } from '@/utils/ruoyi';
const emit = defineEmits(['refreshDataList'])
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const recvIds = ref<Array<number>>([]);
const dataFormRef = ref<ElFormInstance>();
const dataRules = ref()
const buttonLoading = ref(false);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const form: SmPushTaskForm = reactive({
id: undefined,
messageId: null,
sendTime: null,
sendToAll: true,
recvIds: ''
})
/** 提交按钮 */
const submitForm = () => {
buttonLoading.value = true;
dataFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
form.recvIds = recvIds.value.join(",");
if (form.id) {
updateSmPushTask(form).finally(() => buttonLoading.value = false);
} else {
await addSmPushTask(form).finally(() => buttonLoading.value = false);
}
proxy?.$modal.msgSuccess("操作成功");
dialog.visible = false;
emit('refreshDataList')
}
});
}
const init = async (id?: number) => {
dialog.visible = true;
form.id = id;
recvIds.value = [];
//
dataFormRef.value?.resetFields()
if (id) {
const res = await getSmPushTask(id);
Object.assign(form, res.data);
if (res.data.recvIds) {
recvIds.value = res.data.recvIds.split(",").map(Number);
}
dialog.title = "修改推送任务";
} else {
dialog.title = "添加推送任务";
}
}
const initByTask = (task?: SmPushTaskVO) => {
dialog.visible = true;
dataFormRef.value?.resetFields()
form.id = undefined;
form.messageId = task.messageId;
form.sendToAll = task.sendToAll;
form.recvIds = task.recvIds;
form.sendTime = parseTime(new Date(),'{y}-{m}-{d} {h}:{i}:{s}');
recvIds.value = [];
if (task.recvIds) {
recvIds.value = task.recvIds.split(",").map(Number);
}
dialog.title = "添加推送任务";
}
const initByMessage = (messageId: number) => {
dialog.visible = true;
dialog.title = "添加推送任务";
dataFormRef.value?.resetFields()
form.id = undefined;
form.messageId = messageId;
form.sendToAll = true;
form.recvIds = '';
form.sendTime = parseTime(new Date(),'{y}-{m}-{d} {h}:{i}:{s}');
console.log(form.sendTime)
}
const cancel = () => {
dialog.visible = false;
}
defineExpose({
init, initByTask, initByMessage
})
</script>

2
im-admin/ruoyi-im/src/main/java/org/dromara/im/service/impl/ImUserServiceImpl.java

@ -101,7 +101,7 @@ public class ImUserServiceImpl implements IImUserService {
LambdaQueryWrapper<ImUser> wrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<ImUser> wrapper = Wrappers.lambdaQuery();
wrapper.like(StringUtils.isNotBlank(bo.getUserName()), ImUser::getUserName, bo.getUserName()); wrapper.like(StringUtils.isNotBlank(bo.getUserName()), ImUser::getUserName, bo.getUserName());
wrapper.like(StringUtils.isNotBlank(bo.getNickName()), ImUser::getNickName, bo.getNickName()); wrapper.like(StringUtils.isNotBlank(bo.getNickName()), ImUser::getNickName, bo.getNickName());
wrapper.orderByDesc(ImUser::getCreatedTime); wrapper.orderByDesc(ImUser::getId);
return wrapper; return wrapper;
} }

BIN
截图/1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

BIN
截图/2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
截图/3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
截图/4.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

BIN
截图/5.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Loading…
Cancel
Save