feat(header): 搜索框改居中命令面板,应用列表数据与 loading 与 AppList 共享

- header.scss: 删旧 .search-box 与 fade1/search-animation/icon-animation 动画段,
  新增 app-cmdk-* 面板样式。样式段必须放顶层——面板 Teleport 到 body,嵌进
  .default-header 会生成后代选择器而匹配不到
- Header.vue: 搜索 li 收敛为单图标 + openSearch;模板末尾追加 <Teleport to="body">
  命令面板,支持实时过滤 / ↑↓ 键盘导航 / Enter 打开 / Esc 关闭 / 空结果态;
  删 watch(isSearching) 与空函数 showSeachBox;挂/卸 window keydown
- store/index.ts: 新增 appListLoading 字段与 setAppListLoading
- utils/bschLinkPage.ts: 抽出 openAppPage(app, ifameAppIdArr),与点击应用图标同一路径
- AppList.vue: reloadAppData 写 store(数据 + loading,try/finally);
  linkPage(item) 委托 openAppPage

硬约束保持不动:watch(searchAppText) -> mittBus.emit("searchChange")(背景应用网格靠它过滤)、
isSearchIconShow(route.name === "apps")。
This commit is contained in:
chenxing
2026-10-08 17:45:25 +08:00
parent f9f97db272
commit ec696d5187
5 changed files with 298 additions and 125 deletions
+14 -19
View File
@@ -29,7 +29,7 @@
},
]"
>
<a @click="linkPage(citem.webAddr, citem)">
<a @click="linkPage(citem)">
<AppIcon v-if="vectorIconOf(citem)" :name="vectorIconOf(citem)" scene="tile"
:tint="citem.iconColor" />
<img v-else :src="$utils.appIconPath(citem.icon)" />
@@ -61,7 +61,7 @@
},
]"
>
<a @click="linkPage(item.webAddr, item)">
<a @click="linkPage(item)">
<AppIcon v-if="vectorIconOf(item)" :name="vectorIconOf(item)" scene="tile"
:tint="item.iconColor" />
<img v-else :src="requireImg('defappicon.png')"
@@ -93,7 +93,7 @@ import { BschLoadTypeEnum, DesktopAppTypeEnum, LinkOpenTypeEnum } from "@/types"
import { flatten } from "lodash";
import UserSettingApi from "@/api/UserSettingApi";
import { Message } from "view-ui-plus";
import { bschLinkPage } from "@/utils/bschLinkPage";
import { bschLinkPage, openAppPage } from "@/utils/bschLinkPage";
import useCurrentInstance from "@/utils/hook/useCurrentInstance";
import { appiconKeyOf } from "@/constants/appIconRules";
@@ -149,8 +149,15 @@ onUnmounted(() => {
watch(() => store.curRoleUid, reloadAppData);
async function reloadAppData() {
const list = await BaseApi.getUserApp(store.getCurUserId, store.getCurSchId);
appList.value = list.filter(x => x.apps.length > 0);
store.setAppListLoading(true);
try {
const list = await BaseApi.getUserApp(store.getCurUserId, store.getCurSchId);
appList.value = list.filter(x => x.apps.length > 0);
// 写 store:Header 搜索命令面板与后台 WS 通知的应用名反查共用这一份(2026-10-08)
store.setCurUserAppList(appList.value);
} finally {
store.setAppListLoading(false);
}
}
function onMenuChange(curDom: any, state: boolean) {
@@ -185,20 +192,8 @@ async function onLightAppSaveDesktop(id: number) {
}
}
function linkPage(url: string, item: any) {
let options: Parameters<typeof bschLinkPage>[0];
options = {
url,
type: LinkOpenTypeEnum.Open,
title: item.name,
};
if ($conf.ifameAppIdArr.includes(item.id)) {
options.type = LinkOpenTypeEnum.IFrame;
options.isHeader = true;
}
bschLinkPage(options);
function linkPage(item: any) {
openAppPage(item, $conf.ifameAppIdArr);
}
</script>