Browse Source

敏感词管理

master
xsx 1 year ago
parent
commit
0745b6457c
  1. 8
      db/im-admin.sql
  2. 4
      im-admin-ui/index.html
  3. 13
      im-admin-ui/src/api/im/sensitiveWord/index.ts
  4. 8
      im-admin-ui/src/api/im/sensitiveWord/types.ts
  5. BIN
      im-admin-ui/src/assets/images/login-background.jpg
  6. 26
      im-admin-ui/src/views/im/group/index.vue
  7. 6
      im-admin-ui/src/views/im/message/group/index.vue
  8. 2
      im-admin-ui/src/views/im/message/private/index.vue
  9. 67
      im-admin-ui/src/views/im/sensitiveWord/index.vue
  10. 6
      im-admin-ui/src/views/im/user/index.vue
  11. 3
      im-admin-ui/src/views/index.vue
  12. 24
      im-admin-ui/src/views/login.vue
  13. 8
      im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/ImSensitiveWordController.java
  14. 10
      im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/ImSensitiveWord.java
  15. 18
      im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/bo/ImSensitiveWordBo.java
  16. 32
      im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/vo/ImSensitiveWordVo.java
  17. 7
      im-admin/ruoyi-im/src/main/java/org/dromara/im/service/IImSensitiveWordService.java
  18. 32
      im-admin/ruoyi-im/src/main/java/org/dromara/im/service/impl/ImSensitiveWordServiceImpl.java
  19. 4
      im-admin/ruoyi-modules/ruoyi-system/pom.xml
  20. 3
      im-admin/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java

8
db/im-admin.sql

@ -353,6 +353,14 @@ insert into sys_menu values('6001', '私聊消息查询', '60', '1', '#', '', '
insert into sys_menu values('61', '群聊消息', '6', '2', 'group', 'im/message/group/index', '', 1, 0, 'C', '0', '0', 'im:groupMessage:list', 'category', 103, 1, sysdate(), null, null, 'IM群聊消息'); insert into sys_menu values('61', '群聊消息', '6', '2', 'group', 'im/message/group/index', '', 1, 0, 'C', '0', '0', 'im:groupMessage:list', 'category', 103, 1, sysdate(), null, null, 'IM群聊消息');
insert into sys_menu values('6101', '群聊消息查询', '61', '1', '#', '', '', 1, 0, 'F', '0', '0', 'im:groupMessage:query', '#', 103, 1, sysdate(), null, null, ''); insert into sys_menu values('6101', '群聊消息查询', '61', '1', '#', '', '', 1, 0, 'F', '0', '0', 'im:groupMessage:query', '#', 103, 1, sysdate(), null, null, '');
-- IM-敏感词管理
insert into sys_menu values('7', '敏感词管理', '0', '2', 'im/sensitiveWord', 'im/sensitiveWord/index', '', 1, 0, 'C', '0', '0', 'im:sensitiveWord:list', 'documentation', 103, 1, sysdate(), null, null, 'IM敏感词管理');
insert into sys_menu values('7001', '敏感词查询', '7', '1', '#', '', '', 1, 0, 'F', '0', '0', 'im:sensitiveWord:query', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('7002', '敏感词添加', '7', '2', '#', '', '', 1, 0, 'F', '0', '0', 'im:sensitiveWord:add', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('7003', '敏感词删除', '7', '3', '#', '', '', 1, 0, 'F', '0', '0', 'im:sensitiveWord:remove', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('7004', '敏感词修改', '7', '4', '#', '', '', 1, 0, 'F', '0', '0', 'im:sensitiveWord:edit', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('7005', '敏感词导出', '7', '5', '#', '', '', 1, 0, 'F', '0', '0', 'im:sensitiveWord:export', '#', 103, 1, sysdate(), null, null, '');
-- ---------------------------- -- ----------------------------
-- 6、用户和角色关联表 用户N-1角色 -- 6、用户和角色关联表 用户N-1角色
-- ---------------------------- -- ----------------------------

4
im-admin-ui/index.html

@ -202,12 +202,12 @@
<body> <body>
<div id="app"> <div id="app">
<div id="loader-wrapper"> <!-- <div id="loader-wrapper">
<div id="loader"></div> <div id="loader"></div>
<div class="loader-section section-left"></div> <div class="loader-section section-left"></div>
<div class="loader-section section-right"></div> <div class="loader-section section-right"></div>
<div class="load_title">正在加载系统资源,请耐心等待</div> <div class="load_title">正在加载系统资源,请耐心等待</div>
</div> </div> -->
</div> </div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>

13
im-admin-ui/src/api/im/sensitiveWord/index.ts

@ -61,3 +61,16 @@ export const delSensitiveWord = (id: string | number | Array<string | number>) =
method: 'delete' method: 'delete'
}); });
}; };
/**
* /
* @param id
*/
export const enableSensitiveWord = (data: SensitiveWordForm) => {
return request({
url: '/im/sensitiveWord/enable',
method: 'put',
data: data
});
};

8
im-admin-ui/src/api/im/sensitiveWord/types.ts

@ -12,7 +12,7 @@ export interface SensitiveWordVO {
/** /**
* 0:未启用 1:启用 * 0:未启用 1:启用
*/ */
enabled: number; enabled: boolean;
/** /**
* *
@ -33,9 +33,9 @@ export interface SensitiveWordForm extends BaseEntity {
content?: string; content?: string;
/** /**
* 0:未启用 1:启用 *
*/ */
enabled?: number; enabled?: boolean;
/** /**
* *
@ -54,7 +54,7 @@ export interface SensitiveWordQuery extends PageQuery {
/** /**
* 0:未启用 1:启用 * 0:未启用 1:启用
*/ */
enabled?: number; enabled?: boolean;
/** /**
* *

BIN
im-admin-ui/src/assets/images/login-background.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 KiB

After

Width:  |  Height:  |  Size: 32 KiB

26
im-admin-ui/src/views/im/group/index.vue

@ -12,20 +12,15 @@
<im-user-select v-model="queryParams.ownerId"></im-user-select> <im-user-select v-model="queryParams.ownerId"></im-user-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间" prop="createdTime"> <el-form-item label="创建时间" prop="createdTime">
<el-date-picker <el-date-picker v-model="dateRange" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
v-model="dateRange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
value-format="YYYY-MM-DD HH:mm:ss" :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"></el-date-picker>
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['im:group:export']">导出</el-button> <el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['im:group:export']">导出</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
@ -59,19 +54,11 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip content="详情" placement="top">
<el-button link type="primary" v-hasPermi="['im:group:query']" <el-button link type="primary" v-hasPermi="['im:group:query']"
@click="handleDetail(scope.row)">详情</el-button> @click="handleDetail(scope.row)">详情</el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.isBanned" placement="top">
<el-button link type="danger" v-hasPermi="['im:group:ban']" @click="handleUnban(scope.row)">解封</el-button> <el-button link type="danger" v-hasPermi="['im:group:ban']" @click="handleUnban(scope.row)">解封</el-button>
</el-tooltip>
<el-tooltip v-else placement="top">
<el-button link type="danger" v-hasPermi="['im:group:ban']" @click="handleBan(scope.row)">封禁</el-button> <el-button link type="danger" v-hasPermi="['im:group:ban']" @click="handleBan(scope.row)">封禁</el-button>
</el-tooltip>
<el-tooltip placement="top">
<el-button link type="primary" @click="handleShowMember(scope.row.id)">查看成员</el-button> <el-button link type="primary" @click="handleShowMember(scope.row.id)">查看成员</el-button>
</el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -114,7 +101,8 @@
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<el-drawer v-model="memberVisible" title="成员列表" :size="900" :close-on-press-escape="false" :close-on-click-modal="true"> <el-drawer v-model="memberVisible" title="成员列表" :size="900" :close-on-press-escape="false"
:close-on-click-modal="true">
<member ref="memberRef"></member> <member ref="memberRef"></member>
</el-drawer> </el-drawer>
</div> </div>

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

@ -63,9 +63,7 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip placement="top"> <el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['im:groupMessage:query']">详情</el-button>
<el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['im:groupMessage:edit']">详情</el-button>
</el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -109,7 +107,7 @@
</template> </template>
<script setup name="GroupMessage" lang="ts"> <script setup name="GroupMessage" lang="ts">
import { listGroupMessage, getGroupMessage, delGroupMessage, addGroupMessage, updateGroupMessage } from '@/api/im/groupMessage'; import { listGroupMessage, getGroupMessage } from '@/api/im/groupMessage';
import { GroupMessageVO, GroupMessageQuery, GroupMessageForm } from '@/api/im/groupMessage/types'; import { GroupMessageVO, GroupMessageQuery, GroupMessageForm } from '@/api/im/groupMessage/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;

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

@ -69,9 +69,7 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip content="详情" placement="top">
<el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['im:privateMessage:query']">详情</el-button> <el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['im:privateMessage:query']">详情</el-button>
</el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>

67
im-admin-ui/src/views/im/sensitiveWord/index.vue

@ -4,11 +4,14 @@
<div v-show="showSearch" class="mb-[10px]"> <div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="是否启用 0:未启用 1:启用" prop="enabled"> <el-form-item label="内容" prop="content">
<el-input v-model="queryParams.enabled" placeholder="请输入是否启用 0:未启用 1:启用" clearable @keyup.enter="handleQuery" /> <el-input v-model="queryParams.content" placeholder="内容" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="创建者" prop="creator"> <el-form-item label="状态" prop="enabled">
<el-input v-model="queryParams.creator" placeholder="请输入创建者" clearable @keyup.enter="handleQuery" /> <el-select v-model="queryParams.enabled" clearable>
<el-option key="1" label="开启" :value="true" />
<el-option key="2" label="关闭" :value="false" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@ -40,18 +43,18 @@
<el-table v-loading="loading" :data="sensitiveWordList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="sensitiveWordList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="id" align="center" prop="id" v-if="true" /> <el-table-column label="内容" align="center" prop="content" />
<el-table-column label="敏感词内容" align="center" prop="content" /> <el-table-column label="状态" align="center" prop="enabled" >
<el-table-column label="是否启用 0:未启用 1:启用" align="center" prop="enabled" /> <template #default="scope">
<el-table-column label="创建者" align="center" prop="creator" /> <el-switch v-model="scope.row.enabled" @change="switchEnabled(scope.row)" />
</template>
</el-table-column>
<el-table-column label="创建者" align="center" prop="creatorName" />
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip content="修改" placement="top"> <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['im:sensitiveWord:edit']">修改</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['im:sensitiveWord:edit']"></el-button> <el-button link type="danger" @click="handleDelete(scope.row)" v-hasPermi="['im:sensitiveWord:remove']">删除</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['im:sensitiveWord:remove']"></el-button>
</el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -59,16 +62,13 @@
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card> </el-card>
<!-- 添加或修改敏感词对话框 --> <!-- 添加或修改敏感词对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> <el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body>
<el-form ref="sensitiveWordFormRef" :model="form" :rules="rules" label-width="80px"> <el-form ref="sensitiveWordFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="敏感词内容"> <el-form-item label="内容">
<editor v-model="form.content" :min-height="192"/> <el-input v-model="form.content" :min-height="192"/>
</el-form-item>
<el-form-item label="是否启用 0:未启用 1:启用" prop="enabled">
<el-input v-model="form.enabled" placeholder="请输入是否启用 0:未启用 1:启用" />
</el-form-item> </el-form-item>
<el-form-item label="创建者" prop="creator"> <el-form-item label="是否启用" prop="enabled">
<el-input v-model="form.creator" placeholder="请输入创建者" /> <el-switch v-model="form.enabled"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -82,7 +82,7 @@
</template> </template>
<script setup name="SensitiveWord" lang="ts"> <script setup name="SensitiveWord" lang="ts">
import { listSensitiveWord, getSensitiveWord, delSensitiveWord, addSensitiveWord, updateSensitiveWord } from '@/api/im/sensitiveWord'; import { listSensitiveWord, getSensitiveWord, delSensitiveWord, addSensitiveWord, updateSensitiveWord,enableSensitiveWord } from '@/api/im/sensitiveWord';
import { SensitiveWordVO, SensitiveWordQuery, SensitiveWordForm } from '@/api/im/sensitiveWord/types'; import { SensitiveWordVO, SensitiveWordQuery, SensitiveWordForm } from '@/api/im/sensitiveWord/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -122,18 +122,9 @@ const data = reactive<PageData<SensitiveWordForm, SensitiveWordQuery>>({
} }
}, },
rules: { rules: {
id: [
{ required: true, message: "id不能为空", trigger: "blur" }
],
content: [ content: [
{ required: true, message: "敏感词内容不能为空", trigger: "blur" } { required: true, message: "内容不能为空", trigger: "blur" }
], ]
enabled: [
{ required: true, message: "是否启用 0:未启用 1:启用不能为空", trigger: "blur" }
],
creator: [
{ required: true, message: "创建者不能为空", trigger: "blur" }
],
} }
}); });
@ -182,6 +173,7 @@ const handleSelectionChange = (selection: SensitiveWordVO[]) => {
/** 新增按钮操作 */ /** 新增按钮操作 */
const handleAdd = () => { const handleAdd = () => {
reset(); reset();
form.value.enabled = true;
dialog.visible = true; dialog.visible = true;
dialog.title = "添加敏感词"; dialog.title = "添加敏感词";
} }
@ -216,7 +208,7 @@ const submitForm = () => {
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (row?: SensitiveWordVO) => { const handleDelete = async (row?: SensitiveWordVO) => {
const _ids = row?.id || ids.value; const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除敏感词编号为"' + _ids + '"的数据项?').finally(() => loading.value = false); await proxy?.$modal.confirm('是否确认删除?').finally(() => loading.value = false);
await delSensitiveWord(_ids); await delSensitiveWord(_ids);
proxy?.$modal.msgSuccess("删除成功"); proxy?.$modal.msgSuccess("删除成功");
await getList(); await getList();
@ -229,6 +221,11 @@ const handleExport = () => {
}, `sensitiveWord_${new Date().getTime()}.xlsx`) }, `sensitiveWord_${new Date().getTime()}.xlsx`)
} }
const switchEnabled = (row: any) => {
enableSensitiveWord(row)
}
onMounted(() => { onMounted(() => {
getList(); getList();
}); });

6
im-admin-ui/src/views/im/user/index.vue

@ -58,16 +58,10 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip content="详情" placement="top">
<el-button link type="primary" v-hasPermi="['im:user:query']" <el-button link type="primary" v-hasPermi="['im:user:query']"
@click="handleDetail(scope.row)">详情</el-button> @click="handleDetail(scope.row)">详情</el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.isBanned" content="解封" placement="top">
<el-button link type="danger" v-hasPermi="['im:user:ban']" @click="unbanHandle(scope.row)">解封</el-button> <el-button link type="danger" v-hasPermi="['im:user:ban']" @click="unbanHandle(scope.row)">解封</el-button>
</el-tooltip>
<el-tooltip v-else content="封禁" placement="top">
<el-button link type="danger" v-hasPermi="['im:user:ban']" @click="banHandle(scope.row)">封禁</el-button> <el-button link type="danger" v-hasPermi="['im:user:ban']" @click="banHandle(scope.row)">封禁</el-button>
</el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>

3
im-admin-ui/src/views/index.vue

@ -3,8 +3,7 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :sm="24" :lg="12" style="padding-left: 20px"> <el-col :sm="24" :lg="12" style="padding-left: 20px">
<h2>盒子IM 后台管理系统</h2> <h2>盒子IM 后台管理系统</h2>
<h4>盒子IM是一个仿微信的聊天系统支持私聊群聊离线消息发送图片文件语音emoji表情音视频通话等功能</h4>
</el-col> </el-col>
</el-row> </el-row>
<el-divider /> <el-divider />

24
im-admin-ui/src/views/login.vue

@ -1,10 +1,12 @@
<template> <template>
<div class="login"> <div class="login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form"> <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">盒子IM后台管理</h3> <h3 class="title">盒子IM后台管理</h3>
<el-form-item v-if="tenantEnabled" prop="tenantId"> <el-form-item v-if="tenantEnabled" prop="tenantId">
<el-select v-model="loginForm.tenantId" filterable placeholder="请选择/输入公司名称" style="width: 100%"> <el-select v-model="loginForm.tenantId" filterable placeholder="请选择/输入公司名称" style="width: 100%">
<el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option> <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName"
:value="item.tenantId"></el-option>
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -14,12 +16,14 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码" @keyup.enter="handleLogin"> <el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码"
@keyup.enter="handleLogin">
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item v-if="captchaEnabled" prop="code"> <el-form-item v-if="captchaEnabled" prop="code">
<el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter="handleLogin"> <el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 63%"
@keyup.enter="handleLogin">
<template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
</el-input> </el-input>
<div class="login-code"> <div class="login-code">
@ -42,11 +46,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { getCodeImg, getTenantList } from '@/api/login'; import { getCodeImg, getTenantList } from '@/api/login';
import { authBinding } from '@/api/system/social/auth';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import { LoginData, TenantVO } from '@/api/types'; import { LoginData, TenantVO } from '@/api/types';
import { to } from 'await-to-js'; import { to } from 'await-to-js';
import { HttpStatus } from '@/enums/RespEnum'; import logo from '@/assets/logo/logo.png';
const userStore = useUserStore(); const userStore = useUserStore();
const router = useRouter(); const router = useRouter();
@ -177,17 +180,21 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.login { .login {
display: flex; display: flex;
justify-content: center; justify-content: right;
align-items: center; align-items: center;
height: 100%; height: 100%;
background-image: url('../assets/images/login-background.jpg'); background-image: url('../assets/images/login-background.jpg');
background-size: cover; background-size: 100% 100%;
} }
.title { .title {
margin: 0px auto 30px auto; margin: 0px auto 30px auto;
text-align: center; text-align: center;
color: #707070; color: var(--el-color-primary);
font-weight: 600;
} }
.login-form { .login-form {
@ -196,6 +203,7 @@ onMounted(() => {
width: 400px; width: 400px;
padding: 25px 25px 5px 25px; padding: 25px 25px 5px 25px;
margin-right: 12%;
.el-input { .el-input {
height: 40px; height: 40px;

8
im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/ImSensitiveWordController.java

@ -103,4 +103,12 @@ public class ImSensitiveWordController extends BaseController {
@PathVariable Long[] ids) { @PathVariable Long[] ids) {
return toAjax(imSensitiveWordService.deleteWithValidByIds(List.of(ids), true)); return toAjax(imSensitiveWordService.deleteWithValidByIds(List.of(ids), true));
} }
@PutMapping("enable")
@Log(title = "敏感词", businessType = BusinessType.UPDATE)
@SaCheckPermission("im:sensitiveWord:edit")
public R<Void> switchEnabled(@Validated(EditGroup.class) @RequestBody ImSensitiveWordBo bo){
return toAjax(imSensitiveWordService.setEnable(bo));
}
} }

10
im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/ImSensitiveWord.java

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
import java.util.Date;
/** /**
* 敏感词对象 im_sensitive_word * 敏感词对象 im_sensitive_word
@ -31,9 +32,9 @@ public class ImSensitiveWord {
private String content; private String content;
/** /**
* 是否启用 0:未启用 1:启用 * 是否启用
*/ */
private Long enabled; private Boolean enabled;
/** /**
* 创建者 * 创建者
@ -41,4 +42,9 @@ public class ImSensitiveWord {
private Long creator; private Long creator;
/**
* 创建时间
*/
private Date createTime;
} }

18
im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/bo/ImSensitiveWordBo.java

@ -1,5 +1,6 @@
package org.dromara.im.domain.bo; package org.dromara.im.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@ -10,6 +11,8 @@ import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.im.domain.ImSensitiveWord; import org.dromara.im.domain.ImSensitiveWord;
import java.util.Date;
/** /**
* 敏感词业务对象 im_sensitive_word * 敏感词业务对象 im_sensitive_word
* *
@ -17,9 +20,8 @@ import org.dromara.im.domain.ImSensitiveWord;
* @date 2024-12-22 * @date 2024-12-22
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ImSensitiveWord.class, reverseConvertGenerate = false) @AutoMapper(target = ImSensitiveWord.class, reverseConvertGenerate = false)
public class ImSensitiveWordBo extends BaseEntity { public class ImSensitiveWordBo {
/** /**
* id * id
@ -34,16 +36,20 @@ public class ImSensitiveWordBo extends BaseEntity {
private String content; private String content;
/** /**
* 是否启用 0:未启用 1:启用 * 是否启用
*/ */
@NotNull(message = "是否启用 0:未启用 1:启用不能为空", groups = { AddGroup.class, EditGroup.class }) @NotNull(message = "是否启用", groups = { EditGroup.class })
private Long enabled; private Boolean enabled;
/** /**
* 创建者 * 创建者
*/ */
@NotNull(message = "创建者不能为空", groups = { AddGroup.class, EditGroup.class })
private Long creator; private Long creator;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
} }

32
im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/vo/ImSensitiveWordVo.java

@ -2,14 +2,21 @@ package org.dromara.im.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.TransPojo;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.im.domain.ImSensitiveWord; import org.dromara.im.domain.ImSensitiveWord;
import org.dromara.system.domain.SysUser;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
/** /**
* 敏感词视图对象 im_sensitive_word * 敏感词视图对象 im_sensitive_word
@ -20,7 +27,7 @@ import java.io.Serializable;
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
@AutoMapper(target = ImSensitiveWord.class) @AutoMapper(target = ImSensitiveWord.class)
public class ImSensitiveWordVo implements Serializable { public class ImSensitiveWordVo implements TransPojo {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -34,20 +41,29 @@ public class ImSensitiveWordVo implements Serializable {
/** /**
* 敏感词内容 * 敏感词内容
*/ */
@ExcelProperty(value = "敏感词内容") @ExcelProperty(value = "内容")
private String content; private String content;
/** /**
* 是否启用 0:未启用 1:启用 * 是否启用
*/ */
@ExcelProperty(value = "是否启用 0:未启用 1:启用") @ExcelProperty(value = "是否启用")
private Long enabled; @ExcelDictFormat(readConverterExp = "false=否,true=是")
private Boolean enabled;
/** /**
* 创建者 * 创建者
*/ */
@ExcelProperty(value = "创建者") @Trans(type = TransType.SIMPLE,target = SysUser.class, fields = "userName", ref = "creatorName")
private Long creator; private Long creator;
@ExcelProperty(value = "创建者")
private String creatorName;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
} }

7
im-admin/ruoyi-im/src/main/java/org/dromara/im/service/IImSensitiveWordService.java

@ -65,4 +65,11 @@ public interface IImSensitiveWordService {
* @return 是否删除成功 * @return 是否删除成功
*/ */
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 设置敏感词开关
* @param bo 敏感词
* @return
*/
Boolean setEnable(ImSensitiveWordBo bo);
} }

32
im-admin/ruoyi-im/src/main/java/org/dromara/im/service/impl/ImSensitiveWordServiceImpl.java

@ -2,6 +2,7 @@ package org.dromara.im.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -72,11 +73,10 @@ public class ImSensitiveWordServiceImpl implements IImSensitiveWordService {
} }
private LambdaQueryWrapper<ImSensitiveWord> buildQueryWrapper(ImSensitiveWordBo bo) { private LambdaQueryWrapper<ImSensitiveWord> buildQueryWrapper(ImSensitiveWordBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ImSensitiveWord> wrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<ImSensitiveWord> wrapper = Wrappers.lambdaQuery();
wrapper.eq(StringUtils.isNotBlank(bo.getContent()), ImSensitiveWord::getContent, bo.getContent()); wrapper.like(StringUtils.isNotBlank(bo.getContent()), ImSensitiveWord::getContent, bo.getContent());
wrapper.eq(bo.getEnabled() != null, ImSensitiveWord::getEnabled, bo.getEnabled()); wrapper.eq(bo.getEnabled() != null, ImSensitiveWord::getEnabled, bo.getEnabled());
wrapper.eq(bo.getCreator() != null, ImSensitiveWord::getCreator, bo.getCreator()); wrapper.orderByDesc(ImSensitiveWord::getId);
return wrapper; return wrapper;
} }
@ -89,12 +89,7 @@ public class ImSensitiveWordServiceImpl implements IImSensitiveWordService {
@Override @Override
public Boolean insertByBo(ImSensitiveWordBo bo) { public Boolean insertByBo(ImSensitiveWordBo bo) {
ImSensitiveWord add = MapstructUtils.convert(bo, ImSensitiveWord.class); ImSensitiveWord add = MapstructUtils.convert(bo, ImSensitiveWord.class);
validEntityBeforeSave(add); return baseMapper.insert(add) > 0;
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
} }
/** /**
@ -106,16 +101,9 @@ public class ImSensitiveWordServiceImpl implements IImSensitiveWordService {
@Override @Override
public Boolean updateByBo(ImSensitiveWordBo bo) { public Boolean updateByBo(ImSensitiveWordBo bo) {
ImSensitiveWord update = MapstructUtils.convert(bo, ImSensitiveWord.class); ImSensitiveWord update = MapstructUtils.convert(bo, ImSensitiveWord.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0; return baseMapper.updateById(update) > 0;
} }
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ImSensitiveWord entity){
//TODO 做一些数据校验,如唯一约束
}
/** /**
* 校验并批量删除敏感词信息 * 校验并批量删除敏感词信息
@ -126,9 +114,15 @@ public class ImSensitiveWordServiceImpl implements IImSensitiveWordService {
*/ */
@Override @Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0; return baseMapper.deleteByIds(ids) > 0;
} }
@Override
public Boolean setEnable(ImSensitiveWordBo bo) {
LambdaUpdateWrapper<ImSensitiveWord> wrapper = Wrappers.lambdaUpdate();
wrapper.eq(ImSensitiveWord::getId,bo.getId());
wrapper.set(ImSensitiveWord::getEnabled,bo.getEnabled());
return this.baseMapper.update(wrapper) > 0;
}
} }

4
im-admin/ruoyi-modules/ruoyi-system/pom.xml

@ -99,6 +99,10 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-common-minio</artifactId> <artifactId>ruoyi-common-minio</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fhs-opensource</groupId>
<artifactId>easy-trans-spring-boot-starter</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

3
im-admin/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java

@ -1,6 +1,7 @@
package org.dromara.system.domain; package org.dromara.system.domain;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import com.fhs.core.trans.vo.TransPojo;
import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.tenant.core.TenantEntity; import org.dromara.common.tenant.core.TenantEntity;
import lombok.Data; import lombok.Data;
@ -19,7 +20,7 @@ import java.util.Date;
@NoArgsConstructor @NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@TableName("sys_user") @TableName("sys_user")
public class SysUser extends TenantEntity { public class SysUser extends TenantEntity implements TransPojo {
/** /**
* 用户ID * 用户ID

Loading…
Cancel
Save