style(console): 界面一律不使用图标 —— 导航改纯文字,并关闭内置插画/图标
触发原因是一次真实的渲染事故:侧栏那些 emoji 图标在非系统字体栈的渲染器里
退化成**豆腐块**(本机截图对比可见)。试过给图标指定 Apple Color Emoji、
全局字体栈加 !important、乃至 font-variant-emoji —— 分别无效或更糟
(最后一招把 ASCII 数字也拆成了 emoji 呈现)。而「哪套字体栈一定带 emoji」
跨平台并不成立,与其赌字形,不如不用。
emoji 图标 → 路由表 meta.icon 字段整体移除,侧栏改纯文字
n-empty 空态插画 → 16 处 :show-icon="false"(空态里的插画比图标更「图形」,
分布在 9 个页面,是最容易漏掉的一类)
n-alert 类型图标 → 7 处(naive-ui 的 showIcon 默认 true,不显式关就在)
n-popconfirm 询问图标 → 3 处
夹在文案里的 ⚠ → TerminalView 的「高权限操作,请谨慎」保留纯文字
严重程度不靠图标也能读:n-alert 仍由 type 的底色/边框区分。
顺带清掉随包的模板残留资产:
public/vite.svg、public/tauri.svg —— public/ 下的文件会被整体复制进产物,
此前等于把 Vite / Tauri 的 logo 一并发出去了(且 index.html 的 favicon 正指向它);
src/assets/vue.svg —— 无人引用;
index.html 的 <title> 还是模板默认的「Tauri + Vue + Typescript App」。
原生窗口标题取自 tauri.conf.json("nodeagent 控制台"),故此前不影响观感,
但与 dev 态浏览器标签页不一致,一并改齐。
「不属界面图标、刻意未动」的三类写明在 CHANGELOG 里:
托盘图标(菜单栏没图标就点不到,关窗后应用无法寻回,属功能必需)、
被控端 CLI 自身打印的文本标记(⚠️/ℹ️/✅,是程序输出内容,非界面元素)、
控件的结构性部件(下拉箭头、折叠箭头、输入框清除钮、表格排序箭头)。
验证:vue-tsc 0 错 | 契约守卫 6/6 | 单测 280/280 | 前端产物内已无任何 svg 与 logo 字样 |
macOS .app 重打通过(92.21 MiB,前端在无 public/ 下亦正常构建)。
This commit is contained in:
1 parent
2528f6b709
commit
591e44721a
16 files changed
+65
-51
No files matched your search
@@ -88,6 +88,27 @@
|
||||
**新步骤必须逐条核对前置产物由哪一步生成、顺序是否在其后** —— 本地验证时产物早就在,会把这层依赖完全掩盖)。
|
||||
- `.github/workflows/windows-e2e.yml`:步骤名与注释同步为含 `agent.mjs` 的说明。
|
||||
|
||||
### 变更 —— 界面一律不使用图标
|
||||
|
||||
- **去掉全部 emoji 图标**:路由表 `meta.icon` 字段整体移除,侧栏导航由「图标 + 标题」改为**纯文字**。
|
||||
触发原因是一次真实的渲染事故:emoji 图标在非系统字体栈的渲染器里退化成**豆腐块**(截图对比可见),
|
||||
而「哪套字体栈一定带 emoji」跨平台并不成立 —— 与其赌字形,不如不用。
|
||||
- **`n-alert` / `n-empty` / `n-popconfirm` 的内置图形一并关闭**:这三个组件的 `showIcon` 默认均为 `true`,
|
||||
故 16 处 `n-empty` 的空态插画、7 处 `n-alert` 的类型图标、3 处 `n-popconfirm` 的询问图标全部消失,
|
||||
只剩文字与配色(严重程度仍由 `type` 的底色/边框区分,信息不丢)。
|
||||
`n-empty` 是**空态里的插画**(比图标更「图形」),在 9 个页面都有,是最容易漏掉的一类。
|
||||
- **夹在文案里的符号也去掉**:`TerminalView` 的「⚠ 高权限操作,请谨慎」保留纯文字。
|
||||
- **清理随包的模板残留资产**:删掉 `public/vite.svg`、`public/tauri.svg`、`src/assets/vue.svg`
|
||||
与 `index.html` 的 favicon 声明。`public/` 下的文件会被整体复制进产物,
|
||||
此前等于把 Vite / Tauri 的 logo 一起发了出去;`index.html` 的标题也还是模板默认值
|
||||
(原生窗口标题取自 `tauri.conf.json`,不受影响),本次一并改齐。
|
||||
|
||||
> **边界(以下不算「界面图标」,未动)**:① 托盘图标 —— 菜单栏没有图标就点不到,
|
||||
> 关窗后应用将无法寻回,属**功能必需**;② 被控端 CLI 自身打印的文本标记(`⚠️`/`ℹ️`/`✅`,
|
||||
> 见 `apps/agent/src/index.ts`、`packages/client/src/keys.ts`、`apps/agent/src/metrics.ts`)——
|
||||
> 它们是**程序输出内容**,会原样出现在「服务日志」页里,但不是界面元素;
|
||||
> ③ 控件的结构性部件(下拉箭头、折叠箭头、输入框清除钮、表格排序箭头)。
|
||||
|
||||
### 说明 —— 本轮**刻意不升版本号**
|
||||
|
||||
本轮新增的全部是**控制台**功能,**被控端能力集合未变**(未增删任何 `system.*` / `fs.*` / `app.*` 能力)。
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Tauri + Vue + Typescript App</title>
|
||||
<title>nodeagent 控制台</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<svg width="206" height="231" viewBox="0 0 206 231" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M143.143 84C143.143 96.1503 133.293 106 121.143 106C108.992 106 99.1426 96.1503 99.1426 84C99.1426 71.8497 108.992 62 121.143 62C133.293 62 143.143 71.8497 143.143 84Z" fill="#FFC131"/>
|
||||
<ellipse cx="84.1426" cy="147" rx="22" ry="22" transform="rotate(180 84.1426 147)" fill="#24C8DB"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M166.738 154.548C157.86 160.286 148.023 164.269 137.757 166.341C139.858 160.282 141 153.774 141 147C141 144.543 140.85 142.121 140.558 139.743C144.975 138.204 149.215 136.139 153.183 133.575C162.73 127.404 170.292 118.608 174.961 108.244C179.63 97.8797 181.207 86.3876 179.502 75.1487C177.798 63.9098 172.884 53.4021 165.352 44.8883C157.82 36.3744 147.99 30.2165 137.042 27.1546C126.095 24.0926 114.496 24.2568 103.64 27.6274C92.7839 30.998 83.1319 37.4317 75.8437 46.1553C74.9102 47.2727 74.0206 48.4216 73.176 49.5993C61.9292 50.8488 51.0363 54.0318 40.9629 58.9556C44.2417 48.4586 49.5653 38.6591 56.679 30.1442C67.0505 17.7298 80.7861 8.57426 96.2354 3.77762C111.685 -1.01901 128.19 -1.25267 143.769 3.10474C159.348 7.46215 173.337 16.2252 184.056 28.3411C194.775 40.457 201.767 55.4101 204.193 71.404C206.619 87.3978 204.374 103.752 197.73 118.501C191.086 133.25 180.324 145.767 166.738 154.548ZM41.9631 74.275L62.5557 76.8042C63.0459 72.813 63.9401 68.9018 65.2138 65.1274C57.0465 67.0016 49.2088 70.087 41.9631 74.275Z" fill="#FFC131"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M38.4045 76.4519C47.3493 70.6709 57.2677 66.6712 67.6171 64.6132C65.2774 70.9669 64 77.8343 64 85.0001C64 87.1434 64.1143 89.26 64.3371 91.3442C60.0093 92.8732 55.8533 94.9092 51.9599 97.4256C42.4128 103.596 34.8505 112.392 30.1816 122.756C25.5126 133.12 23.9357 144.612 25.6403 155.851C27.3449 167.09 32.2584 177.598 39.7906 186.112C47.3227 194.626 57.153 200.784 68.1003 203.846C79.0476 206.907 90.6462 206.743 101.502 203.373C112.359 200.002 122.011 193.568 129.299 184.845C130.237 183.722 131.131 182.567 131.979 181.383C143.235 180.114 154.132 176.91 164.205 171.962C160.929 182.49 155.596 192.319 148.464 200.856C138.092 213.27 124.357 222.426 108.907 227.222C93.458 232.019 76.9524 232.253 61.3736 227.895C45.7948 223.538 31.8055 214.775 21.0867 202.659C10.3679 190.543 3.37557 175.59 0.949823 159.596C-1.47592 143.602 0.768139 127.248 7.41237 112.499C14.0566 97.7497 24.8183 85.2327 38.4045 76.4519ZM163.062 156.711L163.062 156.711C162.954 156.773 162.846 156.835 162.738 156.897C162.846 156.835 162.954 156.773 163.062 156.711Z" fill="#24C8DB"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 496 B |
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, h, onMounted } from "vue";
|
||||
import { computed, onMounted } from "vue";
|
||||
import { RouterView, useRoute, useRouter } from "vue-router";
|
||||
import {
|
||||
NLayout,
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
NTooltip,
|
||||
type MenuOption,
|
||||
} from "naive-ui";
|
||||
import { navRoutes } from "../router";
|
||||
import { navRoutes, type NavMeta } from "../router";
|
||||
import { useConnStore } from "../stores/conn";
|
||||
import { useAgentStore } from "../stores/agent";
|
||||
|
||||
@@ -28,9 +28,10 @@ onMounted(() => {
|
||||
agent.bind();
|
||||
});
|
||||
|
||||
// 纯文字导航:应用内不使用图标(emoji 图标在部分渲染器里会退化成豆腐块)。
|
||||
const menuOptions: MenuOption[] = navRoutes.map((r) => ({
|
||||
key: r.name as string,
|
||||
label: () => h("span", `${(r.meta as { icon: string }).icon} ${(r.meta as { title: string }).title}`),
|
||||
label: (r.meta as NavMeta).title,
|
||||
}));
|
||||
|
||||
const activeKey = computed(() => (route.name as string) ?? "local");
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/** 路由表。hash history 便于 Tauri 打包后稳定工作。 */
|
||||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
|
||||
// 刻意不设 icon 字段:应用内一律不使用图标,导航以纯文字呈现。
|
||||
// (原因见 CHANGELOG [未发布]:emoji 图标在非系统字体栈的渲染器里会退化成豆腐块,
|
||||
// 而跨平台「哪套字体栈一定带 emoji」并不成立 —— 与其赌字形,不如不用。)
|
||||
export interface NavMeta {
|
||||
title: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
const routes = [
|
||||
@@ -14,55 +16,55 @@ const routes = [
|
||||
path: "/local",
|
||||
name: "local",
|
||||
component: () => import("../views/LocalServiceView.vue"),
|
||||
meta: { title: "本机服务", icon: "🛰" } satisfies NavMeta,
|
||||
meta: { title: "本机服务" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/logs",
|
||||
name: "logs",
|
||||
component: () => import("../views/LogsView.vue"),
|
||||
meta: { title: "服务日志", icon: "🧾" } satisfies NavMeta,
|
||||
meta: { title: "服务日志" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/nodes",
|
||||
name: "nodes",
|
||||
component: () => import("../views/NodesView.vue"),
|
||||
meta: { title: "设备管理", icon: "🖥" } satisfies NavMeta,
|
||||
meta: { title: "设备管理" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/overview",
|
||||
name: "overview",
|
||||
component: () => import("../views/OverviewView.vue"),
|
||||
meta: { title: "状态总览", icon: "📊" } satisfies NavMeta,
|
||||
meta: { title: "状态总览" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/terminal",
|
||||
name: "terminal",
|
||||
component: () => import("../views/TerminalView.vue"),
|
||||
meta: { title: "命令执行", icon: "⌨" } satisfies NavMeta,
|
||||
meta: { title: "命令执行" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/processes",
|
||||
name: "processes",
|
||||
component: () => import("../views/ProcessesView.vue"),
|
||||
meta: { title: "进程与服务", icon: "⚙" } satisfies NavMeta,
|
||||
meta: { title: "进程与服务" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/software",
|
||||
name: "software",
|
||||
component: () => import("../views/SoftwareView.vue"),
|
||||
meta: { title: "软件管理", icon: "📦" } satisfies NavMeta,
|
||||
meta: { title: "软件管理" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/files",
|
||||
name: "files",
|
||||
component: () => import("../views/FilesView.vue"),
|
||||
meta: { title: "文件管理", icon: "📁" } satisfies NavMeta,
|
||||
meta: { title: "文件管理" } satisfies NavMeta,
|
||||
},
|
||||
{
|
||||
path: "/audit",
|
||||
name: "audit",
|
||||
component: () => import("../views/AuditView.vue"),
|
||||
meta: { title: "审计日志", icon: "📜" } satisfies NavMeta,
|
||||
meta: { title: "审计日志" } satisfies NavMeta,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div v-if="!conn.connected">
|
||||
<n-empty description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
<n-empty :show-icon="false" description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
</div>
|
||||
|
||||
<div v-else class="wrap">
|
||||
@@ -154,7 +154,6 @@ onMounted(() => {
|
||||
<n-alert
|
||||
v-if="verify"
|
||||
:type="verify.ok ? 'success' : 'error'"
|
||||
:show-icon="true"
|
||||
style="margin-bottom: 12px"
|
||||
>
|
||||
完整性校验:{{ verify.ok ? "通过" : "发现问题" }} · 已校验 {{ verify.checked }} 条
|
||||
@@ -165,7 +164,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</n-alert>
|
||||
|
||||
<n-empty v-if="!entries.length" description="暂无审计记录" size="small" />
|
||||
<n-empty :show-icon="false" v-if="!entries.length" description="暂无审计记录" size="small" />
|
||||
<n-data-table v-else :columns="cols" :data="entries" :bordered="false" size="small" :max-height="560" />
|
||||
</n-card>
|
||||
</div>
|
||||
|
||||
@@ -146,7 +146,7 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div v-if="!conn.connected">
|
||||
<n-empty description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
<n-empty :show-icon="false" description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
</div>
|
||||
|
||||
<div v-else class="wrap">
|
||||
@@ -172,7 +172,7 @@ onMounted(() => {
|
||||
</n-card>
|
||||
|
||||
<n-card size="small" style="margin-top: 16px">
|
||||
<n-empty v-if="!entries.length" description="目录为空或未加载" size="small" />
|
||||
<n-empty :show-icon="false" v-if="!entries.length" description="目录为空或未加载" size="small" />
|
||||
<n-data-table
|
||||
v-else
|
||||
:columns="cols"
|
||||
|
||||
@@ -110,7 +110,7 @@ function openRelease() {
|
||||
<template>
|
||||
<n-spin :show="busy && !agent.status">
|
||||
<div class="wrap">
|
||||
<n-alert v-if="agent.error" type="error" style="margin-bottom: 14px" :show-icon="true">
|
||||
<n-alert v-if="agent.error" type="error" style="margin-bottom: 14px">
|
||||
{{ agent.error }}
|
||||
</n-alert>
|
||||
|
||||
@@ -158,7 +158,7 @@ function openRelease() {
|
||||
<n-button :disabled="!cfg" quaternary @click="doConnectLocal">连接本机</n-button>
|
||||
</n-space>
|
||||
|
||||
<n-alert v-if="proc?.last_exit" type="default" :show-icon="false" style="margin-bottom: 12px">
|
||||
<n-alert v-if="proc?.last_exit" type="default" style="margin-bottom: 12px">
|
||||
上次退出:{{ proc.last_exit }}
|
||||
</n-alert>
|
||||
|
||||
@@ -293,7 +293,7 @@ function openRelease() {
|
||||
|
||||
<n-space style="margin-top: 12px">
|
||||
<n-button size="small" :loading="busy" @click="doCheckUpdate">检查更新</n-button>
|
||||
<n-popconfirm @positive-click="doApplyUpdate">
|
||||
<n-popconfirm :show-icon="false" @positive-click="doApplyUpdate">
|
||||
<template #trigger>
|
||||
<n-button
|
||||
size="small"
|
||||
|
||||
@@ -105,7 +105,7 @@ function streamType(s: string) {
|
||||
<n-button size="small" @click="logs.load()">重新拉取</n-button>
|
||||
<n-button size="small" @click="scrollToBottom">滚到底部</n-button>
|
||||
<n-button size="small" @click="exportLogs">导出</n-button>
|
||||
<n-popconfirm @positive-click="clear">
|
||||
<n-popconfirm :show-icon="false" @positive-click="clear">
|
||||
<template #trigger>
|
||||
<n-button size="small" type="error" quaternary>清空</n-button>
|
||||
</template>
|
||||
|
||||
@@ -93,7 +93,7 @@ const capGroups = computed(() => {
|
||||
指纹 {{ (conn.info.peer_cert_fp ?? "-").slice(0, 16) }}…
|
||||
</n-text>
|
||||
</div>
|
||||
<n-empty v-else description="尚未连接" size="small" />
|
||||
<n-empty :show-icon="false" v-else description="尚未连接" size="small" />
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
@@ -114,7 +114,7 @@ const capGroups = computed(() => {
|
||||
</div>
|
||||
<n-space>
|
||||
<n-button size="tiny" type="primary" @click="connectTo(n.id)">连接</n-button>
|
||||
<n-popconfirm @positive-click="nodeStore.remove(n.id)">
|
||||
<n-popconfirm :show-icon="false" @positive-click="nodeStore.remove(n.id)">
|
||||
<template #trigger>
|
||||
<n-button size="tiny" quaternary>删除</n-button>
|
||||
</template>
|
||||
@@ -123,7 +123,7 @@ const capGroups = computed(() => {
|
||||
</n-space>
|
||||
</div>
|
||||
</div>
|
||||
<n-empty v-else description="暂无保存的设备" size="small" />
|
||||
<n-empty :show-icon="false" v-else description="暂无保存的设备" size="small" />
|
||||
|
||||
<div class="add-row">
|
||||
<n-input v-model:value="newName" placeholder="名称" size="small" style="flex: 1" />
|
||||
@@ -149,7 +149,7 @@ const capGroups = computed(() => {
|
||||
</div>
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
<n-empty v-else description="连接后展示" size="small" />
|
||||
<n-empty :show-icon="false" v-else description="连接后展示" size="small" />
|
||||
</n-card>
|
||||
|
||||
<n-card title="日志" size="small">
|
||||
|
||||
@@ -69,7 +69,7 @@ onUnmounted(stop);
|
||||
|
||||
<template>
|
||||
<div v-if="!conn.connected">
|
||||
<n-empty description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
<n-empty :show-icon="false" description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
</div>
|
||||
|
||||
<div v-else class="wrap">
|
||||
@@ -142,7 +142,7 @@ onUnmounted(stop);
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<n-empty v-else description="无磁盘数据" size="small" />
|
||||
<n-empty :show-icon="false" v-else description="无磁盘数据" size="small" />
|
||||
</n-card>
|
||||
</n-grid-item>
|
||||
|
||||
@@ -159,7 +159,7 @@ onUnmounted(stop);
|
||||
</b>
|
||||
</div>
|
||||
</div>
|
||||
<n-empty v-else description="无网络数据" size="small" />
|
||||
<n-empty :show-icon="false" v-else description="无网络数据" size="small" />
|
||||
</n-card>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
|
||||
@@ -128,11 +128,11 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div v-if="!conn.connected">
|
||||
<n-empty description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
<n-empty :show-icon="false" description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
</div>
|
||||
|
||||
<n-card v-else size="small">
|
||||
<n-alert v-if="listError" type="error" :show-icon="true" style="margin-bottom: 12px">
|
||||
<n-alert v-if="listError" type="error" style="margin-bottom: 12px">
|
||||
{{ listError }}
|
||||
</n-alert>
|
||||
|
||||
@@ -151,7 +151,7 @@ onMounted(() => {
|
||||
</n-button>
|
||||
<n-text depth="3" style="font-size: 12px">{{ filteredProcs.length }} / {{ procs.length }}</n-text>
|
||||
</n-space>
|
||||
<n-empty v-if="!filteredProcs.length" description="暂无进程数据" size="small" />
|
||||
<n-empty :show-icon="false" v-if="!filteredProcs.length" description="暂无进程数据" size="small" />
|
||||
<n-data-table
|
||||
v-else
|
||||
:columns="procCols"
|
||||
@@ -163,7 +163,7 @@ onMounted(() => {
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="svc" tab="服务">
|
||||
<n-alert v-if="!servicesAvailable" type="warning" :show-icon="true">
|
||||
<n-alert v-if="!servicesAvailable" type="warning">
|
||||
`system.service.list` 仅在被控端为 <b>Windows</b> 时可用;当前被控端为
|
||||
<b>{{ conn.nodeOs ?? "未知" }}</b>。
|
||||
</n-alert>
|
||||
@@ -173,7 +173,7 @@ onMounted(() => {
|
||||
<n-button size="small" :loading="loading" @click="loadServices">刷新</n-button>
|
||||
<n-text depth="3" style="font-size: 12px">{{ services.length }} 项</n-text>
|
||||
</n-space>
|
||||
<n-empty v-if="!services.length" description="暂无服务数据" size="small" />
|
||||
<n-empty :show-icon="false" v-if="!services.length" description="暂无服务数据" size="small" />
|
||||
<n-data-table
|
||||
v-else
|
||||
:columns="svcCols"
|
||||
|
||||
@@ -111,20 +111,20 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div v-if="!conn.connected">
|
||||
<n-empty description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
<n-empty :show-icon="false" description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
</div>
|
||||
|
||||
<div v-else class="wrap">
|
||||
<n-alert v-if="!available" type="warning" :show-icon="true" style="margin-bottom: 14px">
|
||||
<n-alert v-if="!available" type="warning" style="margin-bottom: 14px">
|
||||
软件能力(<code>app.list</code> / <code>app.install</code>)依赖被控端 <code>winget</code>,
|
||||
<b>仅在被控端为 Windows 时可用</b>;当前被控端为 <b>{{ conn.nodeOs ?? "未知" }}</b>,
|
||||
本页已禁用。
|
||||
</n-alert>
|
||||
<n-alert v-else type="info" :show-icon="true" style="margin-bottom: 14px">
|
||||
<n-alert v-else type="info" style="margin-bottom: 14px">
|
||||
软件安装依赖被控端 <code>winget</code>。安装可能耗时数分钟,已把调用超时放大到 10 分钟。
|
||||
</n-alert>
|
||||
|
||||
<n-alert v-if="error" type="error" :show-icon="true" style="margin-bottom: 14px">
|
||||
<n-alert v-if="error" type="error" style="margin-bottom: 14px">
|
||||
{{ error }}
|
||||
</n-alert>
|
||||
|
||||
@@ -157,7 +157,7 @@ onMounted(() => {
|
||||
<n-text depth="3" style="font-size: 12px">{{ filtered.length }}</n-text>
|
||||
</n-space>
|
||||
</template>
|
||||
<n-empty
|
||||
<n-empty :show-icon="false"
|
||||
v-if="!apps.length && !loading"
|
||||
:description="available ? '暂无数据(点刷新)' : '当前被控端非 Windows,不支持'"
|
||||
size="small"
|
||||
|
||||
@@ -85,13 +85,13 @@ function reuse(c: string) {
|
||||
|
||||
<template>
|
||||
<div v-if="!conn.connected">
|
||||
<n-empty description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
<n-empty :show-icon="false" description="请先在「设备管理」页连接被控端" style="margin-top: 80px" />
|
||||
</div>
|
||||
|
||||
<div v-else class="wrap">
|
||||
<n-card size="small" title="命令执行(system.shell.exec)">
|
||||
<template #header-extra>
|
||||
<n-text depth="3" style="font-size: 12px">⚠ 高权限操作,请谨慎</n-text>
|
||||
<n-text depth="3" style="font-size: 12px">高权限操作,请谨慎</n-text>
|
||||
</template>
|
||||
<n-input
|
||||
v-model:value="cmd"
|
||||
|
||||
Reference in new issue
Block a user