diff --git a/frontend/app/src/api/mock/mockAdapter.ts b/frontend/app/src/api/mock/mockAdapter.ts index 750f0001..b0466690 100644 --- a/frontend/app/src/api/mock/mockAdapter.ts +++ b/frontend/app/src/api/mock/mockAdapter.ts @@ -16,10 +16,10 @@ import petMocks from './modules/pet' import storeMocks from './modules/store' import userMocks from './modules/user' -const canUseGroupLogger = - typeof console !== 'undefined' - && typeof console.groupCollapsed === 'function' - && typeof console.groupEnd === 'function' +const canUseGroupLogger + = typeof console !== 'undefined' + && typeof console.groupCollapsed === 'function' + && typeof console.groupEnd === 'function' // 合并所有mock定义 const allMocks = [ diff --git a/frontend/app/src/api/module_ai/chat.ts b/frontend/app/src/api/module_ai/chat.ts index ee5005f4..db67a857 100644 --- a/frontend/app/src/api/module_ai/chat.ts +++ b/frontend/app/src/api/module_ai/chat.ts @@ -28,7 +28,8 @@ export const ChatAPI = { }, /** 发送消息 (非流式) */ sendMessage(sessionId: number, content: string): Promise { - return http.Post(`${AI_BASE}/ai-chat`, { session_id: sessionId, content }) + // silent:聊天页将错误内联展示为 AI 消息,避免与全局 toast 重复提示 + return http.Post(`${AI_BASE}/ai-chat`, { session_id: sessionId, content }, { meta: { silent: true } }) }, /** 获取 AI 模型配置列表 */ getModels(): Promise { diff --git a/frontend/app/src/api/module_generator/gencode.ts b/frontend/app/src/api/module_generator/gencode.ts deleted file mode 100644 index b6496f54..00000000 --- a/frontend/app/src/api/module_generator/gencode.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * 代码生成 API 模块(对应后端 module_generator 插件) - */ -import { http } from '@/http' - -const GEN_BASE = '/generator/gencode' - -export const GencodeAPI = { - /** 查询业务表列表 */ - getPage(params?: Record): Promise> { - return http.Get(`${GEN_BASE}/list`, params) - }, - /** 查询数据库表列表 */ - getDbTables(params?: Record): Promise> { - return http.Get(`${GEN_BASE}/db/list`, params) - }, - /** 导入表结构 */ - importTable(tableName: string): Promise { - return http.Post(`${GEN_BASE}/import`, { table_name: tableName }) - }, - /** 获取业务表详情 */ - getDetail(id: number): Promise { - return http.Get(`${GEN_BASE}/detail/${id}`) - }, - /** 编辑业务表 */ - update(id: number, data: Partial): Promise { - return http.Put(`${GEN_BASE}/update/${id}`, data) - }, - /** 删除业务表 */ - remove(ids: number[]): Promise { - return http.Delete(`${GEN_BASE}/delete`, { ids: JSON.stringify(ids) }) - }, - /** 批量生成代码 (返回 zip) */ - batchGenerate(ids: number[]): Promise { - return http.Patch(`${GEN_BASE}/batch/output`, { ids }) - }, - /** 预览代码 */ - preview(id: number): Promise> { - return http.Get(`${GEN_BASE}/preview/${id}`) - }, - /** 同步数据库 */ - syncDb(tableName: string): Promise { - return http.Post(`${GEN_BASE}/sync_db/${tableName}`) - }, -} - -/* ==================== 类型定义 ==================== */ - -export interface GenTableItem { - id: number - table_name: string - table_comment?: string - class_name?: string - package_name?: string - module_name?: string - business_name?: string - function_name?: string - sub_table_name?: string - sub_table_fk_name?: string - parent_menu_id?: number - description?: string - created_time?: string - updated_time?: string -} - -export interface DbTableItem { - table_name?: string - name?: string - table_comment?: string - comment?: string -} diff --git a/frontend/app/src/api/module_monitor/cache.ts b/frontend/app/src/api/module_monitor/cache.ts deleted file mode 100644 index 2ec87c8f..00000000 --- a/frontend/app/src/api/module_monitor/cache.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { http } from '@/http' - -const MONITOR_BASE = '/monitor' - -/** - * 缓存监控 API - * 与 web 端 module_monitor/cache.ts 对齐 - */ -export const CacheAPI = { - getInfo(): Promise { - return http.Get(`${MONITOR_BASE}/cache/info`) - }, - getNames(): Promise { - return http.Get(`${MONITOR_BASE}/cache/get/names`) - }, - getKeys(cacheName: string): Promise { - return http.Get(`${MONITOR_BASE}/cache/get/keys/${cacheName}`) - }, - getValue(cacheName: string, cacheKey: string): Promise { - return http.Get(`${MONITOR_BASE}/cache/get/value/${cacheName}/${cacheKey}`) - }, - deleteName(cacheName: string): Promise { - return http.Delete(`${MONITOR_BASE}/cache/delete/name/${cacheName}`) - }, - deleteKey(cacheKey: string): Promise { - return http.Delete(`${MONITOR_BASE}/cache/delete/key/${cacheKey}`) - }, - clear(): Promise { - return http.Delete(`${MONITOR_BASE}/cache/clear`) - }, -} - -export interface CacheInfo { - db_size?: number - command_stats?: Record[] - info?: Record - // computed from info dict - keys_count?: number - hit_rate?: string - used_memory?: string -} - -export interface CommandStats { - name: string - value: string -} - -export interface RedisInfo { - redis_version: string - redis_mode: string - tcp_port: number - connected_clients: number - uptime_in_days: number - used_memory_human: string - maxmemory_human: string - aof_enabled: string - instantaneous_input_kbps: number - instantaneous_output_kbps: number -} diff --git a/frontend/app/src/api/module_monitor/resource.ts b/frontend/app/src/api/module_monitor/resource.ts deleted file mode 100644 index 1f9dfb92..00000000 --- a/frontend/app/src/api/module_monitor/resource.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { http } from '@/http' - -const MONITOR_BASE = '/monitor' - -/** - * 资源管理 API - * 与 web 端 module_monitor/resource.ts 对齐(补全完整字段) - */ -export const ResourceAPI = { - getPage(params?: Record): Promise> { - return http.Get(`${MONITOR_BASE}/resource/list`, params) - }, - getDetail(id: number): Promise { - return http.Get(`${MONITOR_BASE}/resource/detail/${id}`) - }, - remove(ids: number[]): Promise { - return http.Delete(`${MONITOR_BASE}/resource/delete`, { ids: JSON.stringify(ids) }) - }, - upload(path: string, filePath: string, fileName: string): Promise { - return http.Post(`${MONITOR_BASE}/resource/upload`, { path, file_path: filePath, file_name: fileName }) - }, - download(id: number): Promise<{ url: string }> { - return http.Get(`${MONITOR_BASE}/resource/download`, { params: { id } }) - }, - mkdir(path: string, name: string): Promise { - return http.Post(`${MONITOR_BASE}/resource/mkdir`, { path, name }) - }, - rename(id: number, newName: string): Promise { - return http.Post(`${MONITOR_BASE}/resource/rename`, { id, new_name: newName }) - }, - move(id: number, targetPath: string): Promise { - return http.Post(`${MONITOR_BASE}/resource/move`, { id, target_path: targetPath }) - }, - copy(id: number, targetPath: string): Promise { - return http.Post(`${MONITOR_BASE}/resource/copy`, { id, target_path: targetPath }) - }, -} - -export interface ResourceItem { - id: number - name: string - file_url: string - relative_path: string - is_file: boolean - is_dir: boolean - size?: number | null - created_time?: string - modified_time?: string - is_hidden?: boolean -} - -export interface ResourceUploadSchema { - file_path?: string - file_name?: string - origin_name?: string - file_url?: string -} diff --git a/frontend/app/src/api/module_system/auth.ts b/frontend/app/src/api/module_system/auth.ts index 5362fc89..ad05beb6 100644 --- a/frontend/app/src/api/module_system/auth.ts +++ b/frontend/app/src/api/module_system/auth.ts @@ -31,7 +31,8 @@ const AuthAPI = { * @returns 新的访问令牌 */ refreshToken(body: RefreshToekenBody): Promise { - return http.Post(`${AUTH_BASE_URL}/token/refresh`, body, { meta: { ignoreAuth: true } }) + // silent:刷新失败由 onAuthRequired 的刷新处理器统一跳转登录,无需全局 toast + return http.Post(`${AUTH_BASE_URL}/token/refresh`, body, { meta: { ignoreAuth: true, silent: true } }) }, /** diff --git a/frontend/app/src/api/module_task/cronjob/job.ts b/frontend/app/src/api/module_task/cronjob/job.ts deleted file mode 100644 index 0bec6ef0..00000000 --- a/frontend/app/src/api/module_task/cronjob/job.ts +++ /dev/null @@ -1,114 +0,0 @@ -/** - * 定时任务 API 模块(对应后端 `plugin.module_task.cronjob.job`) - * 包含: 调度器管理 / 任务管理 / 任务执行日志 - */ -import { http } from '@/http' - -const JOB_BASE = '/task/cronjob/job' - -/* ==================== 调度器管理 ==================== */ -export const SchedulerAPI = { - /** 获取调度器状态 */ - getStatus(): Promise { - return http.Get(`${JOB_BASE}/scheduler/status`) - }, - /** 获取调度器任务列表 */ - getJobs(): Promise { - return http.Get(`${JOB_BASE}/scheduler/jobs`) - }, - /** 启动调度器 */ - start(): Promise { - return http.Post(`${JOB_BASE}/scheduler/start`) - }, - /** 暂停调度器 */ - pause(): Promise { - return http.Post(`${JOB_BASE}/scheduler/pause`) - }, - /** 恢复调度器 */ - resume(): Promise { - return http.Post(`${JOB_BASE}/scheduler/resume`) - }, - /** 关闭调度器 */ - shutdown(): Promise { - return http.Post(`${JOB_BASE}/scheduler/shutdown`) - }, - /** 清空所有任务 */ - clear(): Promise { - return http.Delete(`${JOB_BASE}/scheduler/jobs/clear`) - }, - /** 获取调度器控制台信息 */ - getConsole(): Promise { - return http.Get(`${JOB_BASE}/scheduler/console`) - }, -} - -/* ==================== 任务管理 ==================== */ -export const JobAPI = { - /** 暂停任务 */ - pause(jobId: string): Promise { - return http.Post(`${JOB_BASE}/task/pause/${jobId}`) - }, - /** 恢复任务 */ - resume(jobId: string): Promise { - return http.Post(`${JOB_BASE}/task/resume/${jobId}`) - }, - /** 立即执行任务 */ - run(jobId: string): Promise { - return http.Post(`${JOB_BASE}/task/run/${jobId}`) - }, - /** 修改任务 */ - modify(jobId: string, data: Record): Promise { - return http.Put(`${JOB_BASE}/task/modify/${jobId}`, data) - }, - /** 移除任务 */ - remove(jobId: string): Promise { - return http.Delete(`${JOB_BASE}/task/remove/${jobId}`) - }, -} - -/* ==================== 任务执行日志 ==================== */ -export const JobLogAPI = { - /** 查询执行日志列表 */ - getPage(params?: Record): Promise> { - return http.Get(`${JOB_BASE}/log/list`, params) - }, - /** 获取执行日志详情 */ - getDetail(id: number): Promise { - return http.Get(`${JOB_BASE}/log/detail/${id}`) - }, - /** 删除执行日志 */ - remove(ids: number[]): Promise { - return http.Delete(`${JOB_BASE}/log/delete`, { ids: JSON.stringify(ids) }) - }, -} - -/* ==================== 类型定义 ==================== */ - -export interface SchedulerStatus { - status?: string - is_running?: boolean - running: boolean - job_count: number -} - -export interface SchedulerJob { - id: string - name: string - status?: string - next_run_time?: string - trigger?: string - func?: string - args?: any[] -} - -export interface JobLogItem { - id: number - job_name?: string - job_id?: string - status?: string - result?: string - error_msg?: string - start_time?: string - end_time?: string - created_time?: string -} diff --git a/frontend/app/src/api/module_task/cronjob/node.ts b/frontend/app/src/api/module_task/cronjob/node.ts deleted file mode 100644 index f1979674..00000000 --- a/frontend/app/src/api/module_task/cronjob/node.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * 任务节点 API 模块(对应后端 `plugin.module_task.cronjob.node`) - */ -import { http } from '@/http' - -const NODE_BASE = '/task/cronjob/node' - -/* ==================== 任务节点 ==================== */ -export const NodeAPI = { - /** 获取节点列表(选项) */ - getOptions(): Promise { - return http.Get(`${NODE_BASE}/options`) - }, - /** 获取节点详情 */ - getDetail(id: number): Promise { - return http.Get(`${NODE_BASE}/detail/${id}`) - }, - /** 节点分页列表 */ - getPage(params?: Record): Promise> { - return http.Get(`${NODE_BASE}/list`, params) - }, - /** 创建节点 */ - create(data: NodeForm): Promise { - return http.Post(`${NODE_BASE}/create`, data) - }, - /** 修改节点 */ - update(id: number, data: NodeForm): Promise { - return http.Put(`${NODE_BASE}/update/${id}`, data) - }, - /** 删除节点 */ - remove(ids: number[]): Promise { - return http.Delete(`${NODE_BASE}/delete`, { ids: JSON.stringify(ids) }) - }, - /** 清空节点 */ - clear(_id?: number): Promise { - return http.Delete(`${NODE_BASE}/clear`) - }, - /** 调试节点 */ - execute(id: number): Promise { - return http.Post(`${NODE_BASE}/execute/${id}`) - }, - /** 批量设置节点状态 */ - batchStatus(data: { ids: number[], status: number }): Promise { - return http.Patch(`${NODE_BASE}/status/batch`, data) - }, -} - -/* ==================== 类型定义 ==================== */ - -export interface NodeOption { - value: number - label: string - path: string -} - -export interface NodeForm { - name: string - host: string - port: number - type: string - description?: string -} - -export interface NodeItem extends NodeForm { - id: number - status?: string - task_count?: number - created_time?: string - updated_time?: string -} diff --git a/frontend/app/src/api/module_task/workflow/flow.ts b/frontend/app/src/api/module_task/workflow/flow.ts deleted file mode 100644 index 5898f000..00000000 --- a/frontend/app/src/api/module_task/workflow/flow.ts +++ /dev/null @@ -1,100 +0,0 @@ -/** - * 工作流流程 API 模块(对应后端 `plugin.module_task.workflow.flow`) - * 与 web 端 module_task/workflow/flow.ts 对齐(完整字段定义) - */ -import { http } from '@/http' - -const FLOW_BASE = '/task/workflow/flow' - -/* ==================== 流程编排 ==================== */ -export const WorkflowAPI = { - /** 工作流详情 */ - getDetail(id: number): Promise { - return http.Get(`${FLOW_BASE}/detail/${id}`) - }, - /** 工作流列表 */ - getPage(params?: Record): Promise> { - return http.Get(`${FLOW_BASE}/list`, params) - }, - /** 创建工作流 */ - create(data: WorkflowForm): Promise { - return http.Post(`${FLOW_BASE}/create`, data) - }, - /** 更新工作流 */ - update(id: number, data: WorkflowForm): Promise { - return http.Put(`${FLOW_BASE}/update/${id}`, data) - }, - /** 删除工作流 */ - remove(ids: number[]): Promise { - return http.Delete(`${FLOW_BASE}/delete`, { ids: JSON.stringify(ids) }) - }, - /** 发布工作流 */ - publish(id: number): Promise { - return http.Post(`${FLOW_BASE}/publish/${id}`) - }, - /** 执行工作流 */ - execute(data: WorkflowExecuteForm): Promise { - return http.Post(`${FLOW_BASE}/execute`, data) - }, -} - -/* ==================== 类型定义 ==================== */ - -export interface WorkflowPageQuery extends PageQuery { - name?: string - code?: string - status?: number -} - -export interface WorkflowForm { - name: string - description?: string - nodes?: WorkflowNode[] - edges?: WorkflowEdge[] -} - -export interface WorkflowItem extends WorkflowForm { - id: number - status?: string - version?: number - created_time?: string - updated_time?: string -} - -export interface WorkflowPublishForm { - remark?: string -} - -export interface WorkflowExecuteForm { - workflow_id: number - variables?: Record - business_key?: string - job_id?: number -} - -export interface WorkflowExecuteResult { - workflow_id: number - workflow_name: string - status: number - start_time?: string - end_time?: string - variables?: Record - node_results?: Record - error?: string -} - -export interface WorkflowNode { - id?: string - type: string - label?: string - position?: { x: number, y: number } - data?: Record -} - -export interface WorkflowEdge { - id?: string - source: string - target: string - label?: string - condition?: string -} diff --git a/frontend/app/src/api/module_task/workflow/nodes.ts b/frontend/app/src/api/module_task/workflow/nodes.ts deleted file mode 100644 index b45bbc90..00000000 --- a/frontend/app/src/api/module_task/workflow/nodes.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 工作流节点类型 API 模块(对应后端 `plugin.module_task.workflow.nodes`) - */ -import { http } from '@/http' - -const NODES_BASE = '/task/workflow/nodes' - -/* ==================== 工作流节点类型 ==================== */ -export const WorkflowNodeTypeAPI = { - /** 节点选项 */ - getOptions(): Promise { - return http.Get(`${NODES_BASE}/options`) - }, - /** 节点详情 */ - getDetail(id: number): Promise { - return http.Get(`${NODES_BASE}/detail/${id}`) - }, - /** 节点列表 */ - getPage(params?: Record): Promise> { - return http.Get(`${NODES_BASE}/list`, params) - }, - /** 创建节点 */ - create(data: WorkflowNodeTypeForm): Promise { - return http.Post(`${NODES_BASE}/create`, data) - }, - /** 更新节点 */ - update(id: number, data: WorkflowNodeTypeForm): Promise { - return http.Put(`${NODES_BASE}/update/${id}`, data) - }, - /** 删除节点 */ - remove(ids: number[]): Promise { - return http.Delete(`${NODES_BASE}/delete`, { ids: JSON.stringify(ids) }) - }, - /** 节点选择列表 */ - getSelect(): Promise { - return http.Get(`${NODES_BASE}/select`) - }, -} - -/* ==================== 类型定义 ==================== */ - -export interface WorkflowNodeTypeOption { - value: number - label: string - type: string -} - -export interface WorkflowNodeTypeForm { - name: string - type: string - handler_path?: string - params_schema?: Record - description?: string -} - -export interface WorkflowNodeTypeItem extends WorkflowNodeTypeForm { - id: number - created_time?: string - updated_time?: string -} diff --git a/frontend/app/src/auto-imports.d.ts b/frontend/app/src/auto-imports.d.ts index 79f592b2..c9cbf5e2 100644 --- a/frontend/app/src/auto-imports.d.ts +++ b/frontend/app/src/auto-imports.d.ts @@ -227,6 +227,7 @@ declare global { const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] const useGlobalDialog: typeof import('./composables/useGlobalDialog')['useGlobalDialog'] const useGlobalLoading: typeof import('./composables/useGlobalLoading')['useGlobalLoading'] + const useGlobalMessage: typeof import('./composables/useGlobalMessage')['useGlobalMessage'] const useGlobalToast: typeof import('./composables/useGlobalToast')['useGlobalToast'] const useIdle: typeof import('@vueuse/core')['useIdle'] const useImage: typeof import('@vueuse/core')['useImage'] @@ -236,6 +237,7 @@ declare global { const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] + const useListPage: typeof import('./composables/useListPage')['useListPage'] const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] @@ -584,6 +586,7 @@ declare module 'vue' { readonly useGeolocation: UnwrapRef readonly useGlobalDialog: UnwrapRef readonly useGlobalLoading: UnwrapRef + readonly useGlobalMessage: UnwrapRef readonly useGlobalToast: UnwrapRef readonly useIdle: UnwrapRef readonly useImage: UnwrapRef @@ -593,6 +596,7 @@ declare module 'vue' { readonly useIntervalFn: UnwrapRef readonly useKeyModifier: UnwrapRef readonly useLastChanged: UnwrapRef + readonly useListPage: UnwrapRef readonly useLocalStorage: UnwrapRef readonly useMagicKeys: UnwrapRef readonly useManualRefHistory: UnwrapRef diff --git a/frontend/app/src/components.d.ts b/frontend/app/src/components.d.ts index aa2e23ca..aff9dc8c 100644 --- a/frontend/app/src/components.d.ts +++ b/frontend/app/src/components.d.ts @@ -20,22 +20,35 @@ declare module 'vue' { PrivacyPopup: typeof import('./components/PrivacyPopup.vue')['default'] 'PrivacyPopup copy': typeof import('./components/PrivacyPopup copy.vue')['default'] SkeletonPage: typeof import('./components/SkeletonPage.vue')['default'] - SliderCaptcha: typeof import('./components/SliderCaptcha.vue')['default'] StatusBadge: typeof import('./components/StatusBadge.vue')['default'] UniEcharts: typeof import('uni-echarts')['default'] WdActionSheet: typeof import('@wot-ui/ui/components/wd-action-sheet/wd-action-sheet.vue')['default'] + WdAvatar: typeof import('@wot-ui/ui/components/wd-avatar/wd-avatar.vue')['default'] WdButton: typeof import('@wot-ui/ui/components/wd-button/wd-button.vue')['default'] WdCell: typeof import('@wot-ui/ui/components/wd-cell/wd-cell.vue')['default'] WdCellGroup: typeof import('@wot-ui/ui/components/wd-cell-group/wd-cell-group.vue')['default'] WdConfigProvider: typeof import('@wot-ui/ui/components/wd-config-provider/wd-config-provider.vue')['default'] WdDialog: typeof import('@wot-ui/ui/components/wd-dialog/wd-dialog.vue')['default'] + WdForm: typeof import('@wot-ui/ui/components/wd-form/wd-form.vue')['default'] + WdFormItem: typeof import('@wot-ui/ui/components/wd-form-item/wd-form-item.vue')['default'] WdGap: typeof import('@wot-ui/ui/components/wd-gap/wd-gap.vue')['default'] + WdGrid: typeof import('@wot-ui/ui/components/wd-grid/wd-grid.vue')['default'] + WdGridItem: typeof import('@wot-ui/ui/components/wd-grid-item/wd-grid-item.vue')['default'] WdIcon: typeof import('@wot-ui/ui/components/wd-icon/wd-icon.vue')['default'] + WdInput: typeof import('@wot-ui/ui/components/wd-input/wd-input.vue')['default'] + WdLoading: typeof import('@wot-ui/ui/components/wd-loading/wd-loading.vue')['default'] + WdNavbar: typeof import('@wot-ui/ui/components/wd-navbar/wd-navbar.vue')['default'] WdNotify: typeof import('@wot-ui/ui/components/wd-notify/wd-notify.vue')['default'] + WdPicker: typeof import('@wot-ui/ui/components/wd-picker/wd-picker.vue')['default'] WdPopup: typeof import('@wot-ui/ui/components/wd-popup/wd-popup.vue')['default'] + WdRadio: typeof import('@wot-ui/ui/components/wd-radio/wd-radio.vue')['default'] + WdRadioGroup: typeof import('@wot-ui/ui/components/wd-radio-group/wd-radio-group.vue')['default'] + WdSlideVerify: typeof import('@wot-ui/ui/components/wd-slide-verify/wd-slide-verify.vue')['default'] + WdSwiper: typeof import('@wot-ui/ui/components/wd-swiper/wd-swiper.vue')['default'] WdSwitch: typeof import('@wot-ui/ui/components/wd-switch/wd-switch.vue')['default'] WdTabbar: typeof import('@wot-ui/ui/components/wd-tabbar/wd-tabbar.vue')['default'] WdTabbarItem: typeof import('@wot-ui/ui/components/wd-tabbar-item/wd-tabbar-item.vue')['default'] + WdTextarea: typeof import('@wot-ui/ui/components/wd-textarea/wd-textarea.vue')['default'] WdToast: typeof import('@wot-ui/ui/components/wd-toast/wd-toast.vue')['default'] } } diff --git a/frontend/app/src/components/GlobalMessage.vue b/frontend/app/src/components/GlobalMessage.vue index 39b2a7d9..9f1a8feb 100644 --- a/frontend/app/src/components/GlobalMessage.vue +++ b/frontend/app/src/components/GlobalMessage.vue @@ -1,5 +1,6 @@