refactor(header): 命令面板去背景联动,结果右侧标注应用类型
build / build (push) Successful in 1m21s

用户三点修订:
1. 面板已是模态框,去掉背景应用列表的同步过滤(解开 mittBus.searchChange 整条链)
2. 结果右侧灰色小字显示应用类型(来源 BoaAppType.name,与 /apps 分组标题同源)
3. 类型呈现暂按方案 A(右侧灰字);方案 B(类型分组)对照稿见 design/07

- Header.vue: watch(searchAppText) 不再 emit("searchChange");cmdkResult 由
  getFlattenAppList(纯 flatten,会丢类型名)改为遍历 curUserAppList 分组展开并挂
  appTypeName;模板加 .app-cmdk-type
- AppList.vue: 删 searchAppText / searchAppList / isSearch 与模板搜索态分支、
  .no-search-box 样式、孤儿导入 flatten(lodash) 与 requireImg;删 mittBus 监听
- utils/mitt.ts: 删 searchChange 事件类型
- assets/styles/header.scss: 加 .app-cmdk-type 样式
- harness-main.ts: mock curUserAppList 补齐 BoaAppType 分组结构(id + name),
  原 mock 丢了 name 导致类型名取不到

注:本仓工作区另有并行会话 WIP(StatsBarModal 迁入 Settings / 主题预览),
本提交只含本案 5 个文件与 hunks,未触碰对方改动。
This commit is contained in:
chenxing
2026-10-08 19:10:14 +08:00
parent 4f36ff9ceb
commit 2bd7ef3b80
5 changed files with 34 additions and 66 deletions
+2 -58
View File
@@ -1,7 +1,7 @@
<template>
<div class="app-list-wrapper base-mask">
<vuescroll :ops="scrollOps">
<template v-if="!isSearch" v-for="(item, index) in appList">
<template v-for="(item, index) in appList">
<h3 class="app-type-box">{{ item.name }}</h3>
<div
:class="{
@@ -39,42 +39,6 @@
</template>
</div>
</template>
<template v-if="!!isSearch">
<div class="app-list-box" v-if="searchAppList.length > 0">
<template v-for="item in searchAppList">
<ContextMenu
class="app-container app-container__mask"
:title="item.name"
@on-change="onMenuChange"
@select="onMenuSel"
:menu="[
{
label: '添加到桌面',
appId: item.id,
id: '1',
},
{
label: '新窗口打开',
appId: item.id,
url: item.webAddr,
id: '2',
},
]"
>
<a @click="linkPage(item)">
<AppIcon v-if="vectorIconOf(item)" :name="vectorIconOf(item)" scene="tile"
:tint="item.iconColor" />
<img v-else :src="requireImg('defappicon.png')"
v-real-img="$utils.appIconPath(item.icon)" />
<div class="app-name">{{ item.name }}</div>
</a>
</ContextMenu>
</template>
</div>
<div class="no-search-box" v-else>
<img :src="requireImg('no-search-bg.png')" alt="" />
</div>
</template>
</vuescroll>
</div>
</template>
@@ -86,11 +50,9 @@ import vuescroll from "vuescroll";
import { ref, onMounted, onUnmounted, computed, watch } from "vue";
import BaseApi from "@/api/BaseApi";
import { useDefaultStore } from "@/store";
import { requireImg } from "@/utils/hook/useImg";
import mittBus from "@/utils/mitt";
import { useRoute, useRouter } from "vue-router";
import { BschLoadTypeEnum, DesktopAppTypeEnum, LinkOpenTypeEnum } from "@/types";
import { flatten } from "lodash";
import UserSettingApi from "@/api/UserSettingApi";
import { Message } from "view-ui-plus";
import { bschLinkPage, openAppPage } from "@/utils/bschLinkPage";
@@ -120,15 +82,8 @@ const router = useRouter();
const store = useDefaultStore();
const { $conf, $utils } = useCurrentInstance();
const searchAppText = ref<string | null>(null),
appList = ref<any[]>([]);
const appList = ref<any[]>([]);
const searchAppList = computed(() => {
const allAppList = flatten(appList.value.map(x => x.apps));
return allAppList.filter(x => x.name.indexOf(searchAppText.value) !== -1);
});
const isSearch = computed(() => !!searchAppText.value);
const compMenuId = computed(() => {
let menuList = store.curUserMenuList.find(x => x.url == route.path);
return menuList ? menuList.id : -1;
@@ -137,13 +92,9 @@ const compMenuId = computed(() => {
onMounted(() => {
reloadAppData();
mittBus.emit("searchReset");
mittBus.on("searchChange", val => {
searchAppText.value = val;
});
});
onUnmounted(() => {
mittBus.emit("searchReset");
mittBus.off("searchChange");
});
watch(() => store.curRoleUid, reloadAppData);
@@ -237,11 +188,4 @@ function linkPage(item: any) {
flex-wrap: wrap;
}
}
.no-search-box {
text-align: center;
position: relative;
top: -50%;
-webkit-transform: translateY(40%);
transform: translateY(40%);
}
</style>