瀏覽代碼

feat(header): 添加使用手册功能并优化用户信息显示

- 在蓝色头部组件中新增使用手册按钮,点击可查看使用手册
- 在普通头部组件中新增使用手册按钮,始终显示使用手册入口
- 集成 getCameraMachineDoc API 接口用于获取相机设备使用手册文档
- 通过系统默认浏览器打开使用手册URL,实现外部链接跳转功能
- 修复用户信息获取中的类型安全问题,添加 any 类型断言处理
- 优化头部栏样式,为使用手册按钮添加悬停效果和统一视觉样式
- 完善错误处理机制,对获取使用手册失败的情况进行异常捕获
panqiuyao 19 小時之前
父節點
當前提交
569cc08937

+ 5 - 0
frontend/src/apis/other.ts

@@ -68,3 +68,8 @@ export async function getVersionByRoleType(params: {  role_type: number }){
 export async function getVersionDetailByVersion(params: {  role_type: number, version: string }){
     return GET('/api/index/version_by_role_type_detail', params)
 }
+
+// 获取使用手册
+export async function getCameraMachineDoc(params: { machine_type: number }){
+    return GET('/api/index/get_camera_machine_doc', params)
+}

+ 44 - 4
frontend/src/components/header-bar/blue-header.vue

@@ -5,12 +5,15 @@
       <span class="blue-header-bar__title">智惠映AI自动拍照机 <span class="blue-header-bar__version"  @click="openOTA">{{ currentVersion }}</span></span>
     </div>
     <div class="blue-header-bar__right">
+      <div class="blue-header-bar__manual" @click="openManual" title="点击查看使用手册">
+        使用手册
+      </div>
       <div class="blue-header-bar__user">
         <span class="blue-header-bar__user-label">昵称:</span>
         <span class="blue-header-bar__user-name">
-          {{  useUserInfoStore.userInfo.account_name
-            || useUserInfoStore.userInfo.real_name
-            || useUserInfoStore.userInfo.login_name
+          {{  (useUserInfoStore.userInfo as any).account_name
+            || (useUserInfoStore.userInfo as any).real_name
+            || (useUserInfoStore.userInfo as any).login_name
             || '未登录' }}
         </span>
       </div>
@@ -28,6 +31,7 @@ import client from '@/stores/modules/client'
 import {useRouter} from "vue-router";
 import icpList from '@/utils/ipc'
 import { getRouterUrl } from '@/utils/appfun'
+import { getCameraMachineDoc } from '@/apis/other'
 
 const useUserInfoStore = useUserInfo()
 const tokenInfoStore = tokenInfo();
@@ -38,7 +42,7 @@ const Router = useRouter()
 onMounted(async ()=>{
 
   if (tokenInfoStore.getToken /* 已登录 */) {
-    if(!useUserInfoStore.userInfo.id){
+    if(!(useUserInfoStore.userInfo as any).id){
       await useUserInfoStore.getInfo()
     }
   }
@@ -60,6 +64,28 @@ function openOTA() {
   }
   clientStore.ipc.send(icpList.utils.openMain, params)
 }
+
+async function openManual() {
+  try {
+    const response = await getCameraMachineDoc({
+      machine_type: 0
+    });
+
+    if (response.data && response.data.url) {
+      // 使用系统默认浏览器打开URL
+      clientStore.ipc.removeAllListeners(icpList.utils.shellFun);
+      let params = {
+        action: 'openExternal',
+        params: response.data.url
+      };
+      clientStore.ipc.send(icpList.utils.shellFun, params);
+    } else {
+      console.error('获取使用手册URL失败');
+    }
+  } catch (error) {
+    console.error('获取使用手册失败:', error);
+  }
+}
 </script>
 
 <style lang="scss" scoped>
@@ -117,6 +143,20 @@ function openOTA() {
     -webkit-app-region: no-drag;
   }
 
+  &__manual {
+    background: rgba(255,255,255,0.2);
+    border-radius: 12px;
+    font-size: 12px;
+    padding: 6px 12px;
+    color: #fff;
+    cursor: pointer;
+    transition: background-color 0.2s;
+
+    &:hover {
+      background: rgba(255,255,255,0.3);
+    }
+  }
+
   &__user {
     display: flex;
     align-items: center;

+ 45 - 2
frontend/src/components/header-bar/index.vue

@@ -77,11 +77,17 @@
           当前版本:{{ currentVersion }}
         </span>
       </div>
+      <!-- 使用手册 - 始终显示 -->
+      <div class="header-bar__button header-bar__button__manual">
+        <span class="manual-text" @click="openManual" title="点击查看使用手册">
+          使用手册
+        </span>
+      </div>
       <!-- 用户信息 - 仅在需要时显示 -->
       <div class="header-bar__button header-bar__button__user" v-if="showUser">
         <el-dropdown>
           <span class="el-dropdown-link">
-            {{ useUserInfoStore.userInfo.account_name || useUserInfoStore.userInfo.real_name || useUserInfoStore.userInfo.login_name }}
+            {{ (useUserInfoStore.userInfo as any).account_name || (useUserInfoStore.userInfo as any).real_name || (useUserInfoStore.userInfo as any).login_name }}
           </span>
           <template #dropdown>
             <el-dropdown-menu>
@@ -106,6 +112,7 @@ import icpList from '@/utils/ipc'
 import { getRouterUrl } from '@/utils/appfun'
 import client from '@/stores/modules/client'
 import packageJson from '@/../../package.json';
+import { getCameraMachineDoc } from '@/apis/other';
 
 const clientStore = client()
 const useUserInfoStore = useUserInfo()
@@ -267,8 +274,30 @@ function openOTA() {
   clientStore.ipc.send(icpList.utils.openMain, params)
 }
 
+async function openManual() {
+  try {
+    const response = await getCameraMachineDoc({
+      machine_type: 0
+    });
+
+    if (response.data && response.data.url) {
+      // 使用系统默认浏览器打开URL
+      clientStore.ipc.removeAllListeners(icpList.utils.shellFun);
+      let params = {
+        action: 'openExternal',
+        params: response.data.url
+      };
+      clientStore.ipc.send(icpList.utils.shellFun, params);
+    } else {
+      console.error('获取使用手册URL失败');
+    }
+  } catch (error) {
+    console.error('获取使用手册失败:', error);
+  }
+}
+
 function loginOut() {
-  useUserInfoStore.loginOut()
+  useUserInfoStore.loginOut({})
   useUserInfoStore.updateLoginShow(true)
 }
 
@@ -404,6 +433,20 @@ function handleOutsideClick(event: MouseEvent) {
   transition: all 0.2s ease;
 }
 
+.header-bar__button__manual {
+  padding: 0 8px;
+  margin-right: 5px;
+}
+
+.manual-text {
+  font-size: 12px;
+  color: #666;
+  cursor: pointer;
+  padding: 2px 6px;
+  border-radius: 3px;
+  transition: all 0.2s ease;
+}
+
 .header-bar__button:hover {
   background-color: #e0e0e0;
 }