From 3b457cf1c2726ac658d9b6616728f44d63e76a0c Mon Sep 17 00:00:00 2001 From: zhouwentao Date: Sun, 21 Dec 2025 16:52:31 +0800 Subject: [PATCH] updates --- project_codebase.md | 3 ++- project_doing.md | 7 +++++ project_task.md | 3 +++ src/components/ui/WMessage.vue | 2 +- src/service/request/index.ts | 4 +-- src/utils/message.ts | 49 +++++++++++++++++++++------------- 6 files changed, 46 insertions(+), 22 deletions(-) diff --git a/project_codebase.md b/project_codebase.md index 8bfe9a2..c7298dd 100644 --- a/project_codebase.md +++ b/project_codebase.md @@ -4,8 +4,9 @@ ### `src/utils/message.ts` - **Purpose**: Provides a global interface for showing toast messages. -- **Methods**: `success(msg, duration)`, `error(msg, duration)`, `warning(msg, duration)`, `info(msg, duration)`. +- **Methods**: `success(msg, duration, position)`, `error(msg, duration, position)`, `warning(msg, duration, position)`, `info(msg, duration, position)`. - **Implementation**: Programmatically mounts `WMessage.vue`. +- **New Feature**: Supports `position` argument: `'top-center' | 'top-left' | 'top-right' | 'bottom-center' | 'bottom-left' | 'bottom-right'`. ### `src/service/request/index.ts` - **Purpose**: Encapsulates Axios for API requests. diff --git a/project_doing.md b/project_doing.md index 5ce9598..d2a9d6d 100644 --- a/project_doing.md +++ b/project_doing.md @@ -34,3 +34,10 @@ - **Goal**: Ensure score data is fetched when ScoreForm mounts if store is empty. - **Scope**: - `src/components/ScoreForm.vue` (Update onMounted) + +### [Task 3] Enhance WMessage Component +- **Time**: 2025-12-18 +- **Goal**: Add position configuration support (top/bottom/left/right/center). +- **Scope**: + - `src/utils/message.ts` (Update logic to support multiple containers) + - `src/components/ui/WMessage.vue` (No changes needed, styles handled by container) diff --git a/project_task.md b/project_task.md index d51dce3..537635c 100644 --- a/project_task.md +++ b/project_task.md @@ -22,3 +22,6 @@ - [x] Create `src/stores/score.ts` - [x] Integrate Get Score in `TheNavigation.vue` - [x] Integrate Save Score in `ScoreForm.vue` + +- [x] [Task 3] Enhance WMessage Component + - [x] Add position support to `src/utils/message.ts` (top/bottom/left/right/center) diff --git a/src/components/ui/WMessage.vue b/src/components/ui/WMessage.vue index 411f637..d99f50f 100644 --- a/src/components/ui/WMessage.vue +++ b/src/components/ui/WMessage.vue @@ -53,7 +53,7 @@ function close() { visible.value = false // Give time for transition to finish before removing setTimeout(() => { - // props.onClose(props.id) + props.onClose(props.id) }, 300) } diff --git a/src/service/request/index.ts b/src/service/request/index.ts index 5dcf20d..ae87a4b 100644 --- a/src/service/request/index.ts +++ b/src/service/request/index.ts @@ -118,8 +118,8 @@ class Request { return this.instance.request(config) } - get(url: string, config?: CustomRequestConfig): Promise { - return this.instance.get(url, config) + get(url: string, params?: any, config?: CustomRequestConfig): Promise { + return this.instance.get(url, { ...config, params }) } post(url: string, data?: any, config?: CustomRequestConfig): Promise { diff --git a/src/utils/message.ts b/src/utils/message.ts index e63ecb1..f92dae4 100644 --- a/src/utils/message.ts +++ b/src/utils/message.ts @@ -5,22 +5,42 @@ let seed = 1 const instances: any[] = [] type MessageType = 'success' | 'error' | 'warning' | 'info' +export type MessagePosition = 'top-center' | 'top-left' | 'top-right' | 'bottom-center' | 'bottom-left' | 'bottom-right' interface MessageOptions { message: string type?: MessageType duration?: number + position?: MessagePosition +} + +const positionClasses: Record = { + 'top-center': 'top-4 left-1/2 transform -translate-x-1/2 flex-col items-center', + 'top-left': 'top-4 left-4 flex-col items-start', + 'top-right': 'top-4 right-4 flex-col items-end', + 'bottom-center': 'bottom-4 left-1/2 transform -translate-x-1/2 flex-col-reverse items-center', + 'bottom-left': 'bottom-4 left-4 flex-col-reverse items-start', + 'bottom-right': 'bottom-4 right-4 flex-col-reverse items-end', } const Message = (options: MessageOptions) => { + const { position = 'top-center' } = options const id = `message_${seed++}` const container = document.createElement('div') // Create a container for the message if it doesn't exist - let messageContainer = document.querySelector('.w-message-container') + // We need separate containers for each position + const containerClass = `w-message-container-${position}` + let messageContainer = document.querySelector(`.${containerClass}`) + if (!messageContainer) { messageContainer = document.createElement('div') - messageContainer.className = 'w-message-container fixed top-4 left-1/2 transform -translate-x-1/2 z-50 flex flex-col items-center pointer-events-none' + // Common classes + let classes = `w-message-container ${containerClass} fixed z-50 flex pointer-events-none transition-all duration-300` + // Position specific classes + classes += ` ${positionClasses[position]}` + + messageContainer.className = classes document.body.appendChild(messageContainer) } @@ -28,37 +48,30 @@ const Message = (options: MessageOptions) => { ...options, id, onClose: () => { - close(id, container) + close(id, container, position) }, } const vnode = createVNode(WMessage, props) // Render the component into the container - // We append the container to the messageContainer messageContainer.appendChild(container) render(vnode, container) - instances.push({ id, vnode, container }) + instances.push({ id, vnode, container, position }) } -function close(id: string, container: HTMLElement) { +function close(id: string, container: HTMLElement, position: string) { const idx = instances.findIndex(vm => vm.id === id) if (idx === -1) return - const { vnode } = instances[idx] - // Manually call close on component if needed, but here we just unmount - // The component handles its own visibility transition - - // We wait for the transition to finish? The component calls onClose after transition. - // So we just remove it from DOM. - render(null, container) container.remove() instances.splice(idx, 1) // Clean up container if empty - const messageContainer = document.querySelector('.w-message-container') + const containerClass = `w-message-container-${position}` + const messageContainer = document.querySelector(`.${containerClass}`) if (messageContainer && messageContainer.childNodes.length === 0) { messageContainer.remove() } @@ -66,10 +79,10 @@ function close(id: string, container: HTMLElement) { // Helpers export const message = { - success: (msg: string, duration?: number) => Message({ message: msg, type: 'success', duration }), - error: (msg: string, duration?: number) => Message({ message: msg, type: 'error', duration }), - warning: (msg: string, duration?: number) => Message({ message: msg, type: 'warning', duration }), - info: (msg: string, duration?: number) => Message({ message: msg, type: 'info', duration }), + success: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'success', duration, position }), + error: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'error', duration, position }), + warning: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'warning', duration, position }), + info: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'info', duration, position }), } export default message