Browse Source

站内信模块:我的站内信 vue3

YunaiV 2 years ago
parent
commit
f7762e646e

+ 1 - 0
README.md

@@ -92,6 +92,7 @@
 |     | 字典管理  | 对系统中经常使用的一些较为固定的数据进行维护          |
 |     | 字典管理  | 对系统中经常使用的一些较为固定的数据进行维护          |
 | 🚀  | 短信管理  | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
 | 🚀  | 短信管理  | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
 | 🚀  | 邮件管理  | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台       |
 | 🚀  | 邮件管理  | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台       |
+| 🚀  | 站内信   | 系统内的消息通知,提供站内信模版、站内信消息          |
 | 🚀  | 操作日志  | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
 | 🚀  | 操作日志  | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
 | ⭐️  | 登录日志  | 系统登录日志记录查询,包含登录异常               |
 | ⭐️  | 登录日志  | 系统登录日志记录查询,包含登录异常               |
 | 🚀  | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务     |
 | 🚀  | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务     |

File diff suppressed because it is too large
+ 91 - 13
sql/mysql/ruoyi-vue-pro.sql


+ 17 - 19
yudao-ui-admin-vue3/src/api/system/notify/message/index.ts

@@ -1,4 +1,5 @@
 import request from '@/config/axios'
 import request from '@/config/axios'
+import qs from 'qs'
 
 
 export interface NotifyMessageVO {
 export interface NotifyMessageVO {
   id: number
   id: number
@@ -22,6 +23,11 @@ export interface NotifyMessagePageReqVO extends PageParam {
   createTime?: Date[]
   createTime?: Date[]
 }
 }
 
 
+export interface NotifyMessageMyPageReqVO extends PageParam {
+  readStatus?: boolean
+  createTime?: Date[]
+}
+
 // 查询站内信消息列表
 // 查询站内信消息列表
 export const getNotifyMessagePageApi = async (params: NotifyMessagePageReqVO) => {
 export const getNotifyMessagePageApi = async (params: NotifyMessagePageReqVO) => {
   return await request.get({ url: '/system/notify-message/page', params })
   return await request.get({ url: '/system/notify-message/page', params })
@@ -33,29 +39,21 @@ export const getNotifyMessageApi = async (id: number) => {
 }
 }
 
 
 // 获得我的站内信分页
 // 获得我的站内信分页
-// export function getMyNotifyMessagePage(query) {
-//   return request({
-//     url: '/system/notify-message/my-page',
-//     method: 'get',
-//     params: query
-//   })
-// }
+export const getMyNotifyMessagePage = async (params: NotifyMessageMyPageReqVO) => {
+  return await request.get({ url: '/system/notify-message/my-page', params })
+}
 
 
 // 批量标记已读
 // 批量标记已读
-// export function updateNotifyMessageRead(ids) {
-//   return request({
-//     url: '/system/notify-message/update-read?' + qs.stringify({ids: ids}, { indices: false }),
-//     method: 'put'
-//   })
-// }
+export const updateNotifyMessageRead = async (ids) => {
+  return await request.put({
+    url: '/system/notify-message/update-read?' + qs.stringify({ ids: ids }, { indices: false })
+  })
+}
 
 
 // 标记所有站内信为已读
 // 标记所有站内信为已读
-// export function updateAllNotifyMessageRead() {
-//   return request({
-//     url: '/system/notify-message/update-all-read',
-//     method: 'put'
-//   })
-// }
+export const updateAllNotifyMessageRead = async () => {
+  return await request.put({ url: '/system/notify-message/update-all-read' })
+}
 
 
 // 获取当前用户的最新站内信列表
 // 获取当前用户的最新站内信列表
 export const getUnreadNotifyMessageListApi = async () => {
 export const getUnreadNotifyMessageListApi = async () => {

+ 1 - 1
yudao-ui-admin-vue3/src/hooks/web/useXTable.ts

@@ -7,7 +7,7 @@ export interface tableMethod {
   deleteBatch: () => void // 批量删除
   deleteBatch: () => void // 批量删除
   exportList: (fileName?: string) => void // 导出列表
   exportList: (fileName?: string) => void // 导出列表
   getCurrentColumn: () => void // 获取当前列
   getCurrentColumn: () => void // 获取当前列
-  getRadioRecord: () => void // 获取当前选中列,redio
+  getRadioRecord: () => void // 获取当前选中列,radio
   getCheckboxRecords: () => void //获取当前选中列, checkbox
   getCheckboxRecords: () => void //获取当前选中列, checkbox
 }
 }
 
 

+ 5 - 3
yudao-ui-admin-vue3/src/layout/components/Message/src/Message.vue

@@ -4,18 +4,20 @@ import * as NotifyMessageApi from '@/api/system/notify/message'
 
 
 const { push } = useRouter()
 const { push } = useRouter()
 const activeName = ref('notice')
 const activeName = ref('notice')
-const count = ref(0) // 未读消息数量
+const unreadCount = ref(0) // 未读消息数量
 const list = ref([]) // 消息列表
 const list = ref([]) // 消息列表
 
 
 // 获得消息列表
 // 获得消息列表
 const getList = async () => {
 const getList = async () => {
   list.value = await NotifyMessageApi.getUnreadNotifyMessageListApi()
   list.value = await NotifyMessageApi.getUnreadNotifyMessageListApi()
+  // 强制设置 unreadCount 为 0,避免小红点因为轮询太慢,不消除
+  unreadCount.value = 0
 }
 }
 
 
 // 获得未读消息数
 // 获得未读消息数
 const getUnreadCount = async () => {
 const getUnreadCount = async () => {
   NotifyMessageApi.getUnreadNotifyMessageCountApi().then((data) => {
   NotifyMessageApi.getUnreadNotifyMessageCountApi().then((data) => {
-    count.value = data
+    unreadCount.value = data
   })
   })
 }
 }
 
 
@@ -40,7 +42,7 @@ onMounted(() => {
   <div class="message">
   <div class="message">
     <ElPopover placement="bottom" :width="400" trigger="click">
     <ElPopover placement="bottom" :width="400" trigger="click">
       <template #reference>
       <template #reference>
-        <ElBadge :is-dot="count > 0" class="item">
+        <ElBadge :is-dot="unreadCount > 0" class="item">
           <Icon icon="ep:bell" :size="18" class="cursor-pointer" @click="getList" />
           <Icon icon="ep:bell" :size="18" class="cursor-pointer" @click="getList" />
         </ElBadge>
         </ElBadge>
       </template>
       </template>

+ 1 - 1
yudao-ui-admin-vue3/src/layout/components/UserInfo/src/UserInfo.vue

@@ -41,7 +41,7 @@ const loginOut = () => {
     .catch(() => {})
     .catch(() => {})
 }
 }
 const toProfile = async () => {
 const toProfile = async () => {
-  push('/userinfo/profile')
+  push('/user/profile')
 }
 }
 const toDocument = () => {
 const toDocument = () => {
   window.open('https://doc.iocoder.cn/')
   window.open('https://doc.iocoder.cn/')

+ 13 - 1
yudao-ui-admin-vue3/src/router/modules/remaining.ts

@@ -71,7 +71,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
     ]
     ]
   },
   },
   {
   {
-    path: '/userinfo',
+    path: '/user',
     component: Layout,
     component: Layout,
     name: 'UserInfo',
     name: 'UserInfo',
     meta: {
     meta: {
@@ -89,6 +89,18 @@ const remainingRouter: AppRouteRecordRaw[] = [
           icon: 'ep:user',
           icon: 'ep:user',
           title: t('common.profile')
           title: t('common.profile')
         }
         }
+      },
+      {
+        path: 'notify-message',
+        component: () => import('@/views/system/notify/my/index.vue'),
+        name: 'MyNotifyMessage',
+        meta: {
+          canTo: true,
+          hidden: true,
+          noTagsView: false,
+          icon: 'ep:message',
+          title: '我的站内信'
+        }
       }
       }
     ]
     ]
   },
   },

+ 58 - 0
yudao-ui-admin-vue3/src/views/system/notify/my/index.vue

@@ -0,0 +1,58 @@
+<template>
+  <ContentWrap>
+    <!-- 列表 -->
+    <XTable @register="registerTable">
+      <template #toolbar_buttons>
+        <!-- 操作:标记已读 -->
+        <XButton type="primary" preIcon="ep:zoom-in" title="标记已读" @click="handleUpdateList" />
+        <!-- 操作:全部已读 -->
+        <XButton type="primary" preIcon="ep:zoom-in" title="全部已读" @click="handleUpdateAll" />
+      </template>
+      <template #actionbtns_default="{ row }">
+        <!-- 操作:已读 -->
+        <XTextButton
+          preIcon="ep:view"
+          title="已读"
+          v-hasPermi="['system:notify-message:query']"
+          v-if="!row.readStatus"
+          @click="handleUpdate([row.id])"
+        />
+      </template>
+    </XTable>
+  </ContentWrap>
+</template>
+<script setup lang="ts" name="MyNotifyMessage">
+// 业务相关的 import
+import { allSchemas } from './my.data'
+import * as NotifyMessageApi from '@/api/system/notify/message'
+
+const message = useMessage() // 消息
+
+// 列表相关的变量
+const [registerTable, { reload, getCheckboxRecords }] = useXTable({
+  allSchemas: allSchemas,
+  getListApi: NotifyMessageApi.getMyNotifyMessagePage
+})
+
+const handleUpdateList = async () => {
+  const list = getCheckboxRecords()
+  if (list.length === 0) {
+    return
+  }
+  await handleUpdate(list.map((v) => v.id))
+}
+
+// 标记指定 id 已读
+const handleUpdate = async (ids) => {
+  await NotifyMessageApi.updateNotifyMessageRead(ids)
+  message.success('标记已读成功!')
+  reload()
+}
+
+// 标记全部已读
+const handleUpdateAll = async () => {
+  await NotifyMessageApi.updateAllNotifyMessageRead()
+  message.success('全部已读成功!')
+  reload()
+}
+</script>

+ 58 - 0
yudao-ui-admin-vue3/src/views/system/notify/my/my.data.ts

@@ -0,0 +1,58 @@
+import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
+
+// CrudSchema
+const crudSchemas = reactive<VxeCrudSchema>({
+  primaryKey: 'id',
+  primaryTitle: ' ',
+  primaryType: 'checkbox',
+  action: true,
+  actionWidth: '200', // 3个按钮默认200,如有删减对应增减即可
+  columns: [
+    {
+      title: '发送人名称',
+      field: 'templateNickname',
+      table: {
+        width: 120
+      }
+    },
+    {
+      title: '发送时间',
+      field: 'createTime',
+      isForm: false,
+      formatter: 'formatDate',
+      search: {
+        show: true,
+        itemRender: {
+          name: 'XDataTimePicker'
+        }
+      },
+      table: {
+        width: 180
+      }
+    },
+    {
+      title: '类型',
+      field: 'templateType',
+      dictType: DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE,
+      dictClass: 'number',
+      table: {
+        width: 80
+      }
+    },
+    {
+      title: '内容',
+      field: 'templateContent'
+    },
+    {
+      title: '是否已读',
+      field: 'readStatus',
+      dictType: DICT_TYPE.INFRA_BOOLEAN_STRING,
+      dictClass: 'boolean',
+      table: {
+        width: 80
+      },
+      isSearch: true
+    }
+  ]
+})
+export const { allSchemas } = useVxeCrudSchemas(crudSchemas)