diff --git a/components.d.ts b/components.d.ts index 788f962..4be7cb0 100644 --- a/components.d.ts +++ b/components.d.ts @@ -13,14 +13,16 @@ declare module 'vue' { ElHeader: typeof import('element-plus/es')['ElHeader'] ElIcon: typeof import('element-plus/es')['ElIcon'] ElInput: typeof import('element-plus/es')['ElInput'] - ElMain: typeof import('element-plus/es')['ElMain'] ElPopover: typeof import('element-plus/es')['ElPopover'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + ErrorModal: typeof import('./src/components/dialogs/ErrorModal.vue')['default'] Keyboard: typeof import('./src/components/Keyboard.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] + ShowErrorModal: typeof import('./src/components/dialogs/ShowErrorModal.vue')['default'] SimpleKeyboard: typeof import('./src/components/SimpleKeyboard.vue')['default'] + StackInfoModal: typeof import('./src/components/dialogs/StackInfoModal.vue')['default'] } export interface ComponentCustomProperties { vLoading: typeof import('element-plus/es')['ElLoadingDirective'] diff --git a/package.json b/package.json index 75867ca..d76327e 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@element-plus/icons-vue": "^2.3.1", + "@vicons/ionicons5": "^0.12.0", "axios": "^1.7.7", "date-fns": "^4.1.0", "dayjs": "^1.11.13", diff --git a/public/json/mockErrorData.json b/public/json/mockErrorData.json new file mode 100644 index 0000000..0ecf762 --- /dev/null +++ b/public/json/mockErrorData.json @@ -0,0 +1,44 @@ +{ + "mockErrorData": { + "ecode": "CODEERROR", + "dataType": "ZAppPromopt", + "data": { + "type": "Error", + "info": "代码错误", + "detailInfos": [ + { + "name": "错误类型", + "description": "AECodeError" + }, + { + "name": "错误位置", + "description": "ApiRetTestControler.java:37" + } + ], + "stackInfo": { + "stackTraceElements": [ + "java.base/java.lang.Thread.getStackTrace(Thread.java:2450)", + "a8k.type.ecode.AECodeError.(AECodeError.java:15)", + "a8k.controler.api.v1.app.assistant.ApiRetTestControler.getAppCodeError(ApiRetTestControler.java:37)", + "java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)", + "java.base/java.lang.reflect.Method.invoke(Method.java:580)", + "org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255)", + "org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188)", + "org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)", + "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926)", + "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831)", + "org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)", + "org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)", + "org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)", + "org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)", + "org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)", + "jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)", + "org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)", + "jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)", + "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)", + "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)" + ] + } + } + } +} \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 655fc44..eecc0b8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,20 +1,5 @@ @@ -22,6 +7,8 @@ onUnmounted(() => {
+ + + + diff --git a/src/components/dialogs/StackInfoModal.vue b/src/components/dialogs/StackInfoModal.vue new file mode 100644 index 0000000..945c318 --- /dev/null +++ b/src/components/dialogs/StackInfoModal.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/src/components/dialogs/index.ts b/src/components/dialogs/index.ts new file mode 100644 index 0000000..263c23f --- /dev/null +++ b/src/components/dialogs/index.ts @@ -0,0 +1,2 @@ +export { default as ErrorModal } from './ErrorModal.vue' +export { default as StackInfoModal } from './StackInfoModal.vue' diff --git a/src/eventBus.ts b/src/eventBus.ts index 1561967..8525a65 100644 --- a/src/eventBus.ts +++ b/src/eventBus.ts @@ -1,7 +1,24 @@ -// src/eventBus.js +// src/eventBus.ts import mitt from 'mitt' + +export type ErrorDetail = { + name: string + description: string +} + +export type ErrorModalData = { + type: 'Notify' | 'Warn' | 'Error' | 'Fatal' + info: string + detailInfos?: ErrorDetail[] + ecode?: string + stackInfo?: null +} + type Events = { confirm: { value: number; index: number } + 'show-error-modal': ErrorModalData + 'show-stack-modal': ErrorModalData['stackInfo'] | null | undefined // 其他事件类型 } + export const eventBus = mitt() diff --git a/src/main.ts b/src/main.ts index cc99d42..53f563a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,9 +9,9 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue' import { createPinia } from 'pinia' import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' // 动态加载 Mock -// if (import.meta.env.VITE_USE_MOCK === 'true') { -// import('./mock/index') -// } +if (import.meta.env.VITE_USE_MOCK === 'true') { + import('./mock/index') +} const pinia = createPinia() pinia.use(piniaPluginPersistedstate) const app = createApp(App) diff --git a/src/pages/Index/Index.vue b/src/pages/Index/Index.vue index 18e6c73..c85acfa 100644 --- a/src/pages/Index/Index.vue +++ b/src/pages/Index/Index.vue @@ -68,7 +68,7 @@ @confirm="handleAlreadyConfirm" /> @@ -121,6 +121,7 @@ interface EventType { actionStep?: string, actionStepName?: string } + // 处理 A8kEcodeContextListPromptEvent 类型的特殊逻辑 // const handleA8kEcodeContextListPromptEvent = (error: any): string => { // switch (error.code) { @@ -226,7 +227,7 @@ const saveIdInfo = async () => { idCardInserted.value = false; } } -// 定义轮询间隔,10秒钟轮询一次 +// 定义轮询间隔,500ms轮询一次 const pollingInterval = 500; let pollingTimer: ReturnType; @@ -250,14 +251,21 @@ const generateErrorMessages = (data: CheckItem[]): string[] => { // 开始测试 const startTest = async () => { - const res = await startWork(); + try { + const res = await startWork(); + if (res.success) { + isTesting.value = true; + } + } catch (error) { + console.error('开始测试失败:', error); + isTesting.value = false; + } const isCheck = sessionStorage.getItem('testStarted'); if (!isCheck) { + isTesting.value = false; await checkIfResetCompleted() } - if (res.success) { - isTesting.value = true; - } + }; // 暂停测试 @@ -293,17 +301,23 @@ const handleConfirm = async () => { // 检查是否复位完成 const checkIfResetCompleted = async () => { + if (showFailModal.value) { + showFailModal.value = false; + } showLoadingModal.value = true; // 显示 LoadingModal // 模拟 2 秒延时 await new Promise(resolve => setTimeout(resolve, 2000)); //通过获取初始化状态来判断是否初始化成功 const initState = await getInitState(); if (initState.ecode === "SUC") { + //检测初始化是否成功 if (initState.data.passed) { + console.log("初始化成功") sessionStorage.setItem('testStarted', "true"); showLoadingModal.value = false; showAlreadyModal.value = true; } else { + console.log("初始化失败") await getCheckData(); // 重新获取检查数据 const failedItems = checkData.value.filter(item => !item.pass); if (failedItems.length > 0) { @@ -314,8 +328,10 @@ const checkIfResetCompleted = async () => { showLoadingModal.value = false; // 隐藏 LoadingModal showFailModal.value = true; // 显示失败弹窗 } else { + console.log("初始化失败,但是没有失败项") showLoadingModal.value = false; // 隐藏 LoadingModal showAlreadyModal.value = true; // 显示已完成弹窗 + sessionStorage.setItem('testStarted', "true"); } } } @@ -346,18 +362,27 @@ const openTest = () => { // 如果没有标记,执行 openTest 并设置标记 if (!hasExecuted) { showModal.value = true; - sessionStorage.setItem('testStarted', 'true'); // 设置标记,表示测试已开始 } }; - // 获取检测数据 const getCheckData = async () => { - const res = await getCheckList(); - checkData.value = res.data; - console.log('设备检查的结果:', checkData.value); - - // 检查试管槽状态 - checkTestTubeSlotStatus(checkData.value); + try { + const res = await getCheckList(); + if (res.data && res.data.ecode == "SUC") { + checkData.value = res.data; + console.log('设备检查的结果:', checkData.value); + // 检查试管槽状态 + checkTestTubeSlotStatus(checkData.value); + } else { + console.log("获取检测数据失败") + showFailModal.value = true; + failMessage.value = "获取检测数据失败,请检查设备状态。" + } + } catch (error) { + console.error('获取检测数据失败:', error); + showFailModal.value = true; + failMessage.value = "获取检测数据失败,请检查设备状态。" + } }; diff --git a/src/pages/Index/Regular.vue b/src/pages/Index/Regular.vue index 397bc46..caef58b 100644 --- a/src/pages/Index/Regular.vue +++ b/src/pages/Index/Regular.vue @@ -19,6 +19,8 @@ import TabBar from './components/Consumables/TabBar.vue' #regular-container { margin: 0; padding: 0; + width: 100%; + height: 100%; .main-top { display: flex; diff --git a/src/pages/Index/Regular/Consumables.vue b/src/pages/Index/Regular/Consumables.vue index de5cdae..71ec318 100644 --- a/src/pages/Index/Regular/Consumables.vue +++ b/src/pages/Index/Regular/Consumables.vue @@ -1,5 +1,15 @@ diff --git a/src/pages/Index/Regular/Running.vue b/src/pages/Index/Regular/Running.vue index 532ba11..ea2ef44 100644 --- a/src/pages/Index/Regular/Running.vue +++ b/src/pages/Index/Regular/Running.vue @@ -72,7 +72,7 @@ {{ consumablesStore.moveLiquids[0].tipNum }}/120 - @@ -238,14 +238,24 @@ const selectedItem = ref(null) // 当前选中的样本 const selectedItemId = ref(null) // 选中样本的唯一ID(如sampleId) const TOTAL_SLOTS = 20 // 总矩形数 const emergencyData = ref(null) -const getAngleStep = () => 360 / TOTAL_SLOTS -// 计算每个矩形的旋转角度和位置 +// 修改获取旋转样式的方法 const getRotationStyle = (item: Subtank, index: number) => { - const angleStep = getAngleStep() // 获取当前的角度步长 - const angle = angleStep * index + const totalItems = TOTAL_SLOTS + const angleStep = 360 / totalItems + const angle = index * angleStep + return { - transform: `rotate(${angle}deg) translate(-50%,-50%)`, - backgroundColor: item.projInfo.color || '#d9d9d9', + transform: ` + translate(-50%, -50%) /* 将矩形中心点移到圆心 */ + rotate(${angle}deg) /* 旋转到对应角度 */ + translateY(-400px) /* 向上偏移到圆环位置 */ + `, + backgroundColor: item.projInfo?.color || '#ffffff', + borderColor: item.isPlaceholder ? '#f0f0f0' : + selectedItemId.value === item.sampleId ? '#1890ff' : + getRemainingTime(item) === '已完成' ? '#ff4d4f' : 'transparent', + borderWidth: '3px', + borderStyle: 'solid', } } // 获取当前元素样式:若为选中状态则添加蓝色边框,若为完成状态则添加红色边框 @@ -520,38 +530,44 @@ onUnmounted(() => { #running-container { display: flex; flex-direction: column; + justify-content: space-between; align-items: center; - width: 100%; - padding: 20px 0; background-color: #f9fafb; + height: 93.5vh; /* 更柔和的背景色 */ // 孵育盘 .circular-loader { position: relative; - width: 1036px; - height: 1036px; + width: 800px; + height: 800px; border-radius: 50%; - background-color: #ebebeb; + background-color: #f0f2f5; display: flex; align-items: center; justify-content: center; margin: 0 auto; - border: 5px solid #ffffff; + border: 8px solid #ffffff; box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1); /* 轻微阴影增加立体感 */ .center-square { - width: 400px; // 调整中心矩形的宽度 - height: 400px; // 调整中心矩形的高度 + width: 380px; // 调整中心矩形的宽度 + height: 380px; // 调整中心矩形的高度 background-color: #ffffff; border-radius: 50%; position: absolute; - border: 5px solid #ffffff; + border: 8px solid #ffffff; box-shadow: inset 0px 4px 10px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; justify-content: space-around; + gap: 20px; + z-index: 2; + + span { + text-align: center; + } span:nth-child(3), span:nth-child(6) { @@ -569,69 +585,55 @@ onUnmounted(() => { } .rectangular-item { + position: absolute; + left: 50%; // 将所有矩形的起始位置设置在圆心 + top: 74.5%; // 将所有矩形的起始位置设置在圆心 + width: 75px; + height: 170px; + transform-origin: center -110px; // 调整旋转中心点 + border-radius: 12px; + background-color: #ffffff; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); display: flex; flex-direction: column; align-items: center; - position: absolute; - width: 70px; - height: 200px; - background-color: #d9d9d9; - top: 15%; - left: 50%; - transform-origin: 0 360px; - /* 设置旋转基点在容器外 */ - border-radius: 20px; - border: 5px solid #ffffff; - box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); - - .emergency-icon { - .icon { - position: relative; - width: 70px; - height: 70px; - } - - .text { - font-size: 32px; - color: white; - position: absolute; - top: 90px; - left: 20px; - } - } + padding: 15px 8px; + box-sizing: border-box; + cursor: pointer; - &.placeholder { - background-color: #f9f9f9; // 占位符背景 - border: 1px dashed #d0d0d0; // 虚线边框 - color: #aaa; // 占位符文本颜色 - } - span { - font-size: 16px; - color: #333; - &.placeholder { - color: #aaa; - font-style: italic; - } + &.placeholder { + background-color: #f8f8f8; + box-shadow: none; + opacity: 0.6; } - span:first-child { + .barcode { font-size: 22px; font-weight: bold; - margin-top: 10px; + color: #333; + margin-bottom: 10px; + word-break: break-all; + text-align: center; } - span:nth-child(2) { + .blood-type { font-size: 18px; - font-weight: 700; + color: #666; + margin-bottom: auto; } - span:last-child { + .time { font-size: 20px; font-weight: bold; + color: #333; position: absolute; - bottom: 10px; + bottom: 15px; + + &.completed { + color: #ff4d4f; + } } } } @@ -640,34 +642,41 @@ onUnmounted(() => { .consumables-container { width: 100%; box-sizing: border-box; - padding: 10px 10px; - margin-top: 50px; + padding: 20px 30px; display: flex; flex-direction: column; - box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.05); + background-color: #ffffff; + box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.05); + border-radius: 20px 20px 0 0; // 第一行 .row-first { display: flex; align-items: center; justify-content: flex-start; - margin-bottom: 20px; + margin-bottom: 30px; + gap: 30px; // 急诊按钮 .emergency-button { - width: 120px; - height: 120px; - background-color: #ff6b6b; - border-radius: 15px; + width: 140px; + height: 140px; + background: linear-gradient(135deg, #ff6b6b, #ff4757); + border-radius: 20px; display: flex; align-items: center; justify-content: center; cursor: pointer; - transition: background-color 0.3s; - box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2); + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3); + + &:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(255, 107, 107, 0.4); + } span { - font-size: 20px; + font-size: 32px; color: #ffffff; font-weight: bold; } @@ -677,101 +686,144 @@ onUnmounted(() => { .test-tube-rack-area { display: flex; align-items: center; - margin-left: 20px; + gap: 20px; .tube-project-tab { - width: 100px; - height: 40px; - background-color: #d1e9ff; - border-radius: 10px; + width: 120px; + height: 50px; + background: linear-gradient(to right, #e3f2fd, #bbdefb); + border-radius: 12px; display: flex; align-items: center; justify-content: center; - font-size: 18px; + font-size: 24px; font-weight: bold; - color: #0073e6; - margin-right: 10px; + color: #1976d2; position: relative; + box-shadow: 0 2px 8px rgba(25, 118, 210, 0.1); &::after { content: ''; - width: 2px; - height: 100px; - background-color: black; + width: 3px; + height: 120px; + background: linear-gradient(to bottom, #1976d2, #64b5f6); position: absolute; - top: -30px; - right: -10px; - transform: translateX(-50%); - } - - span { - font-size: 26px; - font-weight: bold; + top: -35px; + right: -15px; + border-radius: 3px; } } } } + //第二行 .row-second { display: grid; grid-template-columns: 3fr 4fr 2fr 1fr; - grid-gap: 10px; + gap: 20px; + padding: 10px 0; .tips-and-big-buffer { display: flex; flex-direction: column; - justify-content: space-between; + gap: 20px; .tips-item { - width: 210px; - height: 160px; - border-radius: 10px; + width: 160px; + height: 110px; + border-radius: 16px; display: flex; align-items: center; justify-content: center; position: relative; - background: #f5f5f5; - box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); + background: #f8f9fa; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + overflow: hidden; .tip-fill { position: absolute; width: 100%; height: 100%; - border-radius: 10px; - transition: background 0.3s; + border-radius: 16px; + transition: all 0.3s ease; + background: linear-gradient(to top, rgba(92, 184, 92, 0.1), transparent); } .tip-text { - font-size: 30px; - color: #333; + font-size: 36px; + color: #2c3e50; font-weight: bold; z-index: 1; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } } } .waste-area { - width: 80px; - height: 330px; - border-radius: 20px; - align-items: center; + width: 100px; + height: 380px; + border-radius: 25px; display: flex; flex-direction: column; justify-content: center; - transition: background-color 0.3s; + align-items: center; + transition: all 0.3s ease; + background: #f8f9fa; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); .waste-text { - font-size: 32px; + font-size: 36px; font-weight: 700; - color: #fff; + color: #ffffff; writing-mode: vertical-rl; - /* 文字垂直排列 */ text-orientation: upright; - /* 使文字正常显示而非旋转 */ - line-height: 2.5; - /* 增大间隔 */ - letter-spacing: 2px; - /* 增加文字间距 */ + letter-spacing: 4px; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + } + + &:hover { + transform: translateY(-2px); + } + } + } + + // 添加响应式设计 + @media screen and (max-width: 1366px) { + padding: 15px 20px; + + .row-first { + margin-bottom: 20px; + gap: 20px; + + .emergency-button { + width: 120px; + height: 120px; + + span { + font-size: 28px; + } + } + } + + .row-second { + gap: 15px; + + .tips-item { + width: 220px; + height: 160px; + + .tip-text { + font-size: 32px; + } + } + + .waste-area { + width: 90px; + height: 340px; + + .waste-text { + font-size: 32px; + } } } } @@ -785,75 +837,77 @@ onUnmounted(() => { width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(5px); display: flex; justify-content: center; align-items: center; z-index: 1000; - backdrop-filter: blur(5px); - - .alert-icon { - position: relative; - - img { - width: 90px; - height: 75px; - } - - span { - color: #fff; - font-size: 32px; - position: absolute; - top: 15px; - right: 235px; - } - } - - .action-buttons { - display: flex; - justify-content: space-between; - margin-top: 40px; - width: 500px; - - .el-button { - width: 200px; - height: 80px; - border-radius: 40px; - font-size: 32px; - font-weight: 800; - } - } - /* 添加模糊效果,突显弹窗 */ .alert-container { - background-color: #fff; - padding: 50px; - border-radius: 10px; - width: 600px; - height: 300px; + background-color: #ffffff; + padding: 40px; + border-radius: 20px; text-align: center; - display: grid; - place-content: center; + max-width: 600px; + animation: slideIn 0.3s ease; .alert-title { - font-size: 40px; + font-size: 36px; font-weight: bold; color: #d9534f; margin-bottom: 20px; } .alert-message { - font-size: 32px; - color: #555; - margin-bottom: 20px; + font-size: 28px; + color: #495057; + margin-bottom: 30px; } - .alert-button { - width: 360px; - height: 120px; - border-radius: 50px; - font-size: 32px; - font-weight: 700; + .action-buttons { + display: flex; + justify-content: center; + gap: 20px; + + .el-button { + min-width: 160px; + height: 50px; + font-size: 24px; + border-radius: 25px; + transition: all 0.3s ease; + + &:hover { + transform: translateY(-2px); + } + } } } } + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-20px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +// 添加动画 +@keyframes pulse { + 0% { + transform: scale(1); + } + + 50% { + transform: scale(1.05); + } + + 100% { + transform: scale(1); + } +} diff --git a/src/pages/Index/Regular/TestTube.vue b/src/pages/Index/Regular/TestTube.vue index e11ff8b..9350cb7 100644 --- a/src/pages/Index/Regular/TestTube.vue +++ b/src/pages/Index/Regular/TestTube.vue @@ -288,8 +288,9 @@ const handleSelectedSamples = ({ justify-content: center; .icon { - width: 86px; - height: 86px; + width: 60px; + height: 100px; + margin-right: 40px; } .text { diff --git a/src/pages/Index/components/Running/LittleBufferDisplay.vue b/src/pages/Index/components/Running/LittleBufferDisplay.vue index 4ce955b..1f6b584 100644 --- a/src/pages/Index/components/Running/LittleBufferDisplay.vue +++ b/src/pages/Index/components/Running/LittleBufferDisplay.vue @@ -31,8 +31,8 @@ const getFillStyle = (item: BottleGroup) => { .buffer-item { position: relative; - width: 160px; - height: 160px; + width: 110px; + height: 155px; background-color: #d3d3d3; border-radius: 10px; display: flex; @@ -50,7 +50,7 @@ const getFillStyle = (item: BottleGroup) => { .buffer-text { position: relative; color: #fff; - font-size: 32px; + font-size: 20px; font-weight: 700; z-index: 1; } diff --git a/src/pages/Index/components/Running/PlateDisplay.vue b/src/pages/Index/components/Running/PlateDisplay.vue index 3d2b53e..6d4bf91 100644 --- a/src/pages/Index/components/Running/PlateDisplay.vue +++ b/src/pages/Index/components/Running/PlateDisplay.vue @@ -40,13 +40,13 @@ const getPercentage = (num: number) => { justify-content: space-between; .project-info { - width: 200px; + width: 160px; height: 46px; border-radius: 40px; flex: 1; .project-name { - font-size: 24px; + font-size: 20px; font-weight: 700; color: white; } @@ -60,7 +60,7 @@ const getPercentage = (num: number) => { align-items: center; justify-content: center; display: flex; - font-size: 24px; + font-size: 20px; font-weight: 700; color: white; } diff --git a/src/pages/Login/Login.vue b/src/pages/Login/Login.vue index ecea565..fc826b7 100644 --- a/src/pages/Login/Login.vue +++ b/src/pages/Login/Login.vue @@ -107,7 +107,8 @@ const submitPin = async () => { sessionStorage.setItem('token', JSON.stringify(res.data)) router.push('/index') } else { - loginStatus.value = '请输入正确的PIN' + + loginStatus.value = `${res.info}` pin.value = '' } } diff --git a/src/utils/axios.ts b/src/utils/axios.ts index 299ec78..8a4bbab 100644 --- a/src/utils/axios.ts +++ b/src/utils/axios.ts @@ -4,6 +4,8 @@ import axios, { InternalAxiosRequestConfig, AxiosHeaders, } from 'axios' + +import { eventBus } from '../eventBus' // 创建 Axios 实例 const apiClient: AxiosInstance = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, @@ -40,10 +42,36 @@ apiClient.interceptors.request.use( // 响应拦截器 apiClient.interceptors.response.use( (response: AxiosResponse) => { + if (response.data && response.data.dataType === 'ZAppPromopt') { + if (response.data.ecode === 'USR_NOT_EXIT') { + return Promise.resolve(response.data) + } else if (response.data.ecode === 'USR_PASSWORD_ERROR') { + return Promise.resolve(response.data) + } else { + console.log('接口出错', response.data) + eventBus.emit('show-error-modal', { + type: response.data.data.type, + info: response.data.data.info, + detailInfos: response.data.data.detailInfos, + ecode: response.data.data.ecode, + stackInfo: response.data.data.stackInfo, + }) + return Promise.reject(response.data) + } + } return response }, (error) => { - console.error('API Error:', error) + eventBus.emit('show-error-modal', { + type: 'Error', + info: '网络请求失败', + detailInfos: [ + { + name: '错误详情', + description: error.message, + }, + ], + }) return Promise.reject(error) }, )