updates
This commit is contained in:
parent
b046ea95d0
commit
3b457cf1c2
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
### `src/utils/message.ts`
|
### `src/utils/message.ts`
|
||||||
- **Purpose**: Provides a global interface for showing toast messages.
|
- **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`.
|
- **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`
|
### `src/service/request/index.ts`
|
||||||
- **Purpose**: Encapsulates Axios for API requests.
|
- **Purpose**: Encapsulates Axios for API requests.
|
||||||
|
|
|
||||||
|
|
@ -34,3 +34,10 @@
|
||||||
- **Goal**: Ensure score data is fetched when ScoreForm mounts if store is empty.
|
- **Goal**: Ensure score data is fetched when ScoreForm mounts if store is empty.
|
||||||
- **Scope**:
|
- **Scope**:
|
||||||
- `src/components/ScoreForm.vue` (Update onMounted)
|
- `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)
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,6 @@
|
||||||
- [x] Create `src/stores/score.ts` <!-- id: 18 -->
|
- [x] Create `src/stores/score.ts` <!-- id: 18 -->
|
||||||
- [x] Integrate Get Score in `TheNavigation.vue` <!-- id: 19 -->
|
- [x] Integrate Get Score in `TheNavigation.vue` <!-- id: 19 -->
|
||||||
- [x] Integrate Save Score in `ScoreForm.vue` <!-- id: 20 -->
|
- [x] Integrate Save Score in `ScoreForm.vue` <!-- id: 20 -->
|
||||||
|
|
||||||
|
- [x] [Task 3] Enhance WMessage Component <!-- id: 21 -->
|
||||||
|
- [x] Add position support to `src/utils/message.ts` (top/bottom/left/right/center) <!-- id: 22 -->
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ function close() {
|
||||||
visible.value = false
|
visible.value = false
|
||||||
// Give time for transition to finish before removing
|
// Give time for transition to finish before removing
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// props.onClose(props.id)
|
props.onClose(props.id)
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,8 +118,8 @@ class Request {
|
||||||
return this.instance.request(config)
|
return this.instance.request(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
get<T = any>(url: string, config?: CustomRequestConfig): Promise<T> {
|
get<T = any>(url: string, params?: any, config?: CustomRequestConfig): Promise<T> {
|
||||||
return this.instance.get(url, config)
|
return this.instance.get(url, { ...config, params })
|
||||||
}
|
}
|
||||||
|
|
||||||
post<T = any>(url: string, data?: any, config?: CustomRequestConfig): Promise<T> {
|
post<T = any>(url: string, data?: any, config?: CustomRequestConfig): Promise<T> {
|
||||||
|
|
|
||||||
|
|
@ -5,22 +5,42 @@ let seed = 1
|
||||||
const instances: any[] = []
|
const instances: any[] = []
|
||||||
|
|
||||||
type MessageType = 'success' | 'error' | 'warning' | 'info'
|
type MessageType = 'success' | 'error' | 'warning' | 'info'
|
||||||
|
export type MessagePosition = 'top-center' | 'top-left' | 'top-right' | 'bottom-center' | 'bottom-left' | 'bottom-right'
|
||||||
|
|
||||||
interface MessageOptions {
|
interface MessageOptions {
|
||||||
message: string
|
message: string
|
||||||
type?: MessageType
|
type?: MessageType
|
||||||
duration?: number
|
duration?: number
|
||||||
|
position?: MessagePosition
|
||||||
|
}
|
||||||
|
|
||||||
|
const positionClasses: Record<MessagePosition, string> = {
|
||||||
|
'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 Message = (options: MessageOptions) => {
|
||||||
|
const { position = 'top-center' } = options
|
||||||
const id = `message_${seed++}`
|
const id = `message_${seed++}`
|
||||||
const container = document.createElement('div')
|
const container = document.createElement('div')
|
||||||
|
|
||||||
// Create a container for the message if it doesn't exist
|
// 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) {
|
if (!messageContainer) {
|
||||||
messageContainer = document.createElement('div')
|
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)
|
document.body.appendChild(messageContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,37 +48,30 @@ const Message = (options: MessageOptions) => {
|
||||||
...options,
|
...options,
|
||||||
id,
|
id,
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
close(id, container)
|
close(id, container, position)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const vnode = createVNode(WMessage, props)
|
const vnode = createVNode(WMessage, props)
|
||||||
|
|
||||||
// Render the component into the container
|
// Render the component into the container
|
||||||
// We append the container to the messageContainer
|
|
||||||
messageContainer.appendChild(container)
|
messageContainer.appendChild(container)
|
||||||
render(vnode, 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)
|
const idx = instances.findIndex(vm => vm.id === id)
|
||||||
if (idx === -1) return
|
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)
|
render(null, container)
|
||||||
container.remove()
|
container.remove()
|
||||||
instances.splice(idx, 1)
|
instances.splice(idx, 1)
|
||||||
|
|
||||||
// Clean up container if empty
|
// 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) {
|
if (messageContainer && messageContainer.childNodes.length === 0) {
|
||||||
messageContainer.remove()
|
messageContainer.remove()
|
||||||
}
|
}
|
||||||
|
|
@ -66,10 +79,10 @@ function close(id: string, container: HTMLElement) {
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
export const message = {
|
export const message = {
|
||||||
success: (msg: string, duration?: number) => Message({ message: msg, type: 'success', duration }),
|
success: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'success', duration, position }),
|
||||||
error: (msg: string, duration?: number) => Message({ message: msg, type: 'error', duration }),
|
error: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'error', duration, position }),
|
||||||
warning: (msg: string, duration?: number) => Message({ message: msg, type: 'warning', duration }),
|
warning: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'warning', duration, position }),
|
||||||
info: (msg: string, duration?: number) => Message({ message: msg, type: 'info', duration }),
|
info: (msg: string, duration?: number, position?: MessagePosition) => Message({ message: msg, type: 'info', duration, position }),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default message
|
export default message
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue