mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-10-31 22:57:15 +08:00 
			
		
		
		
	feat: 新增消息中心
This commit is contained in:
		| @@ -8,3 +8,4 @@ export * from './file' | |||||||
| export * from './storage' | export * from './storage' | ||||||
| export * from './option' | export * from './option' | ||||||
| export * from './user-center' | export * from './user-center' | ||||||
|  | export * from './message' | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								src/apis/system/message.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/apis/system/message.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | import type * as System from './type' | ||||||
|  | import http from '@/utils/http' | ||||||
|  |  | ||||||
|  | const BASE_URL = '/system/message' | ||||||
|  |  | ||||||
|  | /** @desc 查询消息列表 */ | ||||||
|  | export function listMessage(query: System.MessagePageQuery) { | ||||||
|  |   return http.get<PageRes<System.MessageResp[]>>(`${BASE_URL}`, query) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** @desc 删除消息 */ | ||||||
|  | export function deleteMessage(ids: string | Array<string>) { | ||||||
|  |   return http.del(`${BASE_URL}/${ids}`) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** @desc 标记已读 */ | ||||||
|  | export function readMessage(ids: string | Array<string>) { | ||||||
|  |   return http.patch(`${BASE_URL}/read`, ids) | ||||||
|  | } | ||||||
| @@ -297,3 +297,25 @@ export interface BindSocialAccountRes { | |||||||
|   source: string |   source: string | ||||||
|   description: string |   description: string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** 系统消息类型 */ | ||||||
|  | export interface MessageResp { | ||||||
|  |   id: string | ||||||
|  |   title: string | ||||||
|  |   content: string | ||||||
|  |   type: number | ||||||
|  |   isRead: boolean | ||||||
|  |   readTime: string | ||||||
|  |   createUserString: string | ||||||
|  |   createTime: string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface MessageQuery { | ||||||
|  |   title?: string | ||||||
|  |   type?: number | ||||||
|  |   isRead?: boolean | ||||||
|  |   sort: Array<string> | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface MessagePageQuery extends MessageQuery, PageQuery { | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
|  | import type * as System from './type' | ||||||
| import http from '@/utils/http' | import http from '@/utils/http' | ||||||
| import type * as System from '@/apis/system/type' |  | ||||||
|  |  | ||||||
| const BASE_URL = '/system/user' | const BASE_URL = '/system/user' | ||||||
|  |  | ||||||
|   | |||||||
| @@ -63,6 +63,12 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||||||
|         name: 'SettingProfile', |         name: 'SettingProfile', | ||||||
|         component: () => import('@/views/setting/profile/index.vue'), |         component: () => import('@/views/setting/profile/index.vue'), | ||||||
|         meta: { title: '个人中心', showInTabs: false } |         meta: { title: '个人中心', showInTabs: false } | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         path: '/setting/message', | ||||||
|  |         name: 'SettingMessage', | ||||||
|  |         component: () => import('@/views/setting/message/index.vue'), | ||||||
|  |         meta: { title: '消息中心', showInTabs: false } | ||||||
|       } |       } | ||||||
|     ] |     ] | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										140
									
								
								src/views/setting/message/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/views/setting/message/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  | <template> | ||||||
|  |   <div class="table-page"> | ||||||
|  |     <GiTable | ||||||
|  |       row-key="id" | ||||||
|  |       title="消息中心" | ||||||
|  |       :data="dataList" | ||||||
|  |       :columns="columns" | ||||||
|  |       :loading="loading" | ||||||
|  |       :scroll="{ x: '100%', y: '100%', minWidth: 1000 }" | ||||||
|  |       :pagination="pagination" | ||||||
|  |       :disabled-tools="['size', 'setting']" | ||||||
|  |       :disabled-column-keys="['name']" | ||||||
|  |       :row-selection="{ type: 'checkbox', showCheckedAll: true }" | ||||||
|  |       :selected-keys="selectedKeys" | ||||||
|  |       @select-all="selectAll" | ||||||
|  |       @select="select" | ||||||
|  |       @refresh="search" | ||||||
|  |     > | ||||||
|  |       <template #custom-left> | ||||||
|  |         <a-input v-model="queryForm.title" placeholder="请输入标题" allow-clear @change="search"> | ||||||
|  |           <template #prefix><icon-search /></template> | ||||||
|  |         </a-input> | ||||||
|  |         <a-select | ||||||
|  |           v-model="queryForm.isRead" | ||||||
|  |           placeholder="请选择状态" | ||||||
|  |           allow-clear | ||||||
|  |           style="width: 150px" | ||||||
|  |           @change="search" | ||||||
|  |         > | ||||||
|  |           <a-option :value="false">未读</a-option> | ||||||
|  |           <a-option :value="true">已读</a-option> | ||||||
|  |         </a-select> | ||||||
|  |         <a-button @click="reset">重置</a-button> | ||||||
|  |       </template> | ||||||
|  |       <template #custom-right> | ||||||
|  |         <a-button type="primary" status="danger" :disabled="!selectedKeys.length" @click="onDelete"> | ||||||
|  |           <template #icon><icon-delete /></template> | ||||||
|  |           <span>删除</span> | ||||||
|  |         </a-button> | ||||||
|  |         <a-button type="primary" :disabled="!selectedKeys.length" @click="onRead"> | ||||||
|  |           <span>标记为已读</span> | ||||||
|  |         </a-button> | ||||||
|  |         <a-button type="primary" :disabled="selectedKeys.length" @click="onReadAll">全部已读</a-button> | ||||||
|  |       </template> | ||||||
|  |       <template #title="{ record }"> | ||||||
|  |         <a-tooltip :content="record.content"><span>{{ record.title }}</span></a-tooltip> | ||||||
|  |       </template> | ||||||
|  |       <template #isRead="{ record }"> | ||||||
|  |         <a-tag v-if="record.isRead">已读</a-tag> | ||||||
|  |         <a-tag v-else color="arcoblue">未读</a-tag> | ||||||
|  |       </template> | ||||||
|  |       <template #type="{ record }"> | ||||||
|  |         <GiCellTag :value="record.type" :dict="message_type" /> | ||||||
|  |       </template> | ||||||
|  |     </GiTable> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { Message, Modal } from '@arco-design/web-vue' | ||||||
|  | import { type MessageQuery, deleteMessage, listMessage, readMessage } from '@/apis' | ||||||
|  | import type { TableInstanceColumns } from '@/components/GiTable/type' | ||||||
|  | import { useTable } from '@/hooks' | ||||||
|  | import { useDict } from '@/hooks/app' | ||||||
|  |  | ||||||
|  | defineOptions({ name: 'SystemMessage' }) | ||||||
|  |  | ||||||
|  | const { message_type } = useDict('message_type') | ||||||
|  |  | ||||||
|  | const queryForm = reactive<MessageQuery>({ | ||||||
|  |   sort: ['createTime,desc'] | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | const { | ||||||
|  |   tableData: dataList, | ||||||
|  |   loading, | ||||||
|  |   pagination, | ||||||
|  |   selectedKeys, | ||||||
|  |   select, | ||||||
|  |   selectAll, | ||||||
|  |   search, | ||||||
|  |   handleDelete | ||||||
|  | } = useTable((page) => listMessage({ ...queryForm, ...page }), { immediate: true }) | ||||||
|  |  | ||||||
|  | const columns: TableInstanceColumns[] = [ | ||||||
|  |   { | ||||||
|  |     title: '序号', | ||||||
|  |     width: 66, | ||||||
|  |     align: 'center', | ||||||
|  |     render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize) | ||||||
|  |   }, | ||||||
|  |   { title: '标题', dataIndex: 'title', slotName: 'title', ellipsis: true, tooltip: true }, | ||||||
|  |   { title: '状态', dataIndex: 'isRead', slotName: 'isRead', align: 'center', width: 80 }, | ||||||
|  |   { title: '时间', dataIndex: 'createTime', width: 180 }, | ||||||
|  |   { title: '类型', dataIndex: 'type', slotName: 'type', width: 180, ellipsis: true, tooltip: true } | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | // 重置 | ||||||
|  | const reset = () => { | ||||||
|  |   queryForm.title = undefined | ||||||
|  |   queryForm.type = undefined | ||||||
|  |   queryForm.isRead = undefined | ||||||
|  |   search() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 删除 | ||||||
|  | const onDelete = () => { | ||||||
|  |   if (!selectedKeys.value.length) { | ||||||
|  |     return Message.warning('请选择数据') | ||||||
|  |   } | ||||||
|  |   return handleDelete(() => deleteMessage(selectedKeys.value), { showModal: false }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 标记为已读 | ||||||
|  | const onRead = async () => { | ||||||
|  |   if (!selectedKeys.value.length) { | ||||||
|  |     return Message.warning('请选择数据') | ||||||
|  |   } | ||||||
|  |   await readMessage(selectedKeys.value) | ||||||
|  |   Message.success('操作成功') | ||||||
|  |   search() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 全部已读 | ||||||
|  | const onReadAll = async () => { | ||||||
|  |   Modal.warning({ | ||||||
|  |     title: '全部已读', | ||||||
|  |     content: '确定要标记全部消息为已读吗?', | ||||||
|  |     hideCancel: false, | ||||||
|  |     maskClosable: false, | ||||||
|  |     onOk: async () => { | ||||||
|  |       await readMessage([]) | ||||||
|  |       Message.success('操作成功') | ||||||
|  |       search() | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss" scoped></style> | ||||||
		Reference in New Issue
	
	Block a user