1. 后台图表多样化 API 的 /admin/overview 新增了按 AI 提供商聚合的用量(providerSeries)和云端数据构成(dataDist)。Admin.vue 概览页改用 ECharts:日活折线图、Token 堆叠柱状图(叠加调用次数折线)、AI 提供商用量饼图、云端数据构成饼图。
2. 端口监控与刷新间隔 「存为应用」不再跳转启动台,而是在本页弹出复用的 LaunchAppFormModal 表单,保存成功后弹确认框询问「留在本页 / 前往启动台」。启动台和端口监控页头都加了 RefreshIntervalPicker(仅手动 / 5 / 10 / 30 / 60 秒,默认 30 秒),选择记忆在 localStorage。 3. 团队所有者与用户详情 团队列表的所有者、用户列表的用户名都改为「头像 + 昵称 + ID」的可点击单元格,点击弹出用户详情:头像、昵称、头衔、待办/工单/笔记/团队数量、注册时间、最近活跃、拥有团队数。API 新增 GET /admin/users/:id,团队列表关联查询出 ownerNickname/ownerAvatar。 4. 项目专属排除规则 SQLite exclusion_rules 加了 project_id 列(唯一约束改为 (project_id, pattern),旧库自动重建迁移)。项目详情页「代码」标签下新增专属规则面板,可增删;扫描时全局规则 + 项目规则叠加生效。规则随项目身份上云,其它机器认领项目后自动带回。 5. 一句话 AI 生成待办/工单 待办页和工单页工具栏各嵌入一个 AI 生成输入条:一句话回车后由后端 AIGenerateTasks 调用 AI 拆解成多条草稿,弹预览框逐条勾选、可改标题/类型/优先级/日期,选归属项目后批量保存。 6. 项目云同步与认领 全局挂载了 CloudClaimModal:登录同步后发现云端有本机未落地的项目时自动弹出(同一批只打扰一次),每个项目可「选目录认领」或「忽略」;工作台横幅和个人主页可随时再打开。 统计数据按机器码推送到 stats:<机器码> 文档,只推不拉,不同电脑的扫描历史互不覆盖。 个人主页 · 云同步新增「项目云同步」区块:自动/手动模式切换(手动模式下常规同步跳过项目文档,仅点「立即同步项目」时推拉)、待认领入口、已忽略项目的恢复列表。 途中补齐了约 60 个中英双语 i18n 键,并修掉了 PortMonitor 引用但缺失的 pmSavedToast 键。
This commit is contained in:
42
frontend/src/components/RefreshIntervalPicker.vue
Normal file
42
frontend/src/components/RefreshIntervalPicker.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup>
|
||||
// 自动刷新间隔选择:0=不自动刷新(仅手动),其余为秒数。父组件负责持久化与定时器。
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { Timer } from 'lucide-vue-next'
|
||||
|
||||
defineProps({ modelValue: { type: Number, default: 30 } })
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { t } = useI18n()
|
||||
const OPTIONS = [0, 5, 10, 30, 60, 120]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label class="refresh-pick" :title="t('autoRefreshEvery')">
|
||||
<Timer />
|
||||
<select :value="modelValue" @change="emit('update:modelValue', Number($event.target.value))">
|
||||
<option v-for="o in OPTIONS" :key="o" :value="o">{{ o === 0 ? t('refreshManualOnly') : t('refreshEveryN', { n: o }) }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.refresh-pick {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
padding: 0 .55rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: var(--panel, transparent);
|
||||
color: var(--muted);
|
||||
}
|
||||
.refresh-pick svg { width: 15px; height: 15px; }
|
||||
.refresh-pick select {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--text);
|
||||
font-size: .85rem;
|
||||
padding: .45rem 0;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user