release: bump version to 0.27.6

This commit is contained in:
rayd1o
2026-04-15 07:37:41 +08:00
parent d9adaf4134
commit f8b43a995b
9 changed files with 141 additions and 58 deletions

View File

@@ -1 +1 @@
0.27.5 0.27.6

View File

@@ -8,6 +8,16 @@ This project follows the repository versioning rule:
- `improvement` -> `+0.0.1`bugfix + 小功能混合) - `improvement` -> `+0.0.1`bugfix + 小功能混合)
- `bugfix` -> `+0.0.1` - `bugfix` -> `+0.0.1`
## [0.27.6] — 2026-04-15
### 🔧 Improvements
- BGP 告警页表格纵向 overflow 修复:补全 flex 布局链tabs content-holder 正确撑满剩余高度
- 用户管理表格横向滚动修复:采用 flex-fill 方案替换 `height: auto !important`,自定义滚动条 X 轨道位置对齐表格底部
- Playground 宽布局隐藏"服务状态"按钮:侧边栏可见时不显示冗余入口
- AI Chatbox 输入框失焦收起为单行,聚焦或有内容时展开完整 composer
---
## [0.27.4] — 2026-04-14 ## [0.27.4] — 2026-04-14
### 🔧 Improvements ### 🔧 Improvements

View File

@@ -16,12 +16,13 @@
## Current Version ## Current Version
- `main` 当前主线历史推导到:`0.16.5` - `main` 当前主线历史推导到:`0.16.5`
- `dev` 当前开发分支历史推导到:`0.27.5` - `dev` 当前开发分支历史推导到:`0.27.6`
## Timeline ## Timeline
| Version | Type | Branch | Commit | Summary | | Version | Type | Branch | Commit | Summary |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| `0.27.6` | improvement | `dev` | `pending` | BGP/用户表格滚动条修复Playground 响应式按钮与输入框收起优化 |
| `0.27.5` | bugfix | `dev` | `pending` | 统一控制台自定义滚动条,修复 alerts/BGP 响应式滚动与采集进度完成态显示 | | `0.27.5` | bugfix | `dev` | `pending` | 统一控制台自定义滚动条,修复 alerts/BGP 响应式滚动与采集进度完成态显示 |
| `0.27.4` | improvement | `dev` | — | info-card 懒加载动态挂载,页面初始不再有隐藏节点 | | `0.27.4` | improvement | `dev` | — | info-card 懒加载动态挂载,页面初始不再有隐藏节点 |
| `0.27.3` | improvement | `dev` | — | TV panel 折叠方向稳定、视频跳动修复、图例折叠按钮修复、搜索图标调整 | | `0.27.3` | improvement | `dev` | — | TV panel 折叠方向稳定、视频跳动修复、图例折叠按钮修复、搜索图标调整 |

View File

@@ -1,6 +1,6 @@
{ {
"name": "planet-frontend", "name": "planet-frontend",
"version": "0.27.5", "version": "0.27.6",
"private": true, "private": true,
"packageManager": "bun@1", "packageManager": "bun@1",
"dependencies": { "dependencies": {

View File

@@ -390,6 +390,10 @@ body {
color: #64748b; color: #64748b;
} }
.playground-chat__service-btn {
display: none;
}
.playground-card__icon-button:hover { .playground-card__icon-button:hover {
color: #1677ff !important; color: #1677ff !important;
background: rgba(22, 119, 255, 0.08) !important; background: rgba(22, 119, 255, 0.08) !important;
@@ -534,6 +538,21 @@ body {
padding: 12px; padding: 12px;
} }
.playground-chat__input-row {
display: flex;
align-items: center;
gap: 8px;
}
.playground-chat__input-row .playground-chat__input.ant-input {
flex: 1 1 auto;
min-width: 0;
}
.playground-chat__input-wrap--expanded .playground-chat__input-row .playground-chat__send-button.ant-btn {
flex: 0 0 auto;
}
.playground-chat__input.ant-input { .playground-chat__input.ant-input {
border: 0; border: 0;
box-shadow: none; box-shadow: none;
@@ -543,6 +562,15 @@ body {
margin-top: 10px; margin-top: 10px;
} }
.playground-chat__input-wrap--expanded .playground-chat__input.ant-input {
margin-top: 10px;
}
.playground-chat__input-wrap:not(.playground-chat__input-wrap--expanded) .playground-chat__input.ant-input {
margin-top: 0;
padding: 4px 2px;
}
.playground-chat__input.ant-input:focus, .playground-chat__input.ant-input:focus,
.playground-chat__input.ant-input-focused { .playground-chat__input.ant-input-focused {
box-shadow: none; box-shadow: none;
@@ -1288,6 +1316,10 @@ body {
flex-direction: column; flex-direction: column;
} }
.playground-chat__service-btn {
display: inline-flex;
}
.playground-shell__sidebar { .playground-shell__sidebar {
display: none; display: none;
} }
@@ -1493,10 +1525,26 @@ body {
min-height: 0; min-height: 0;
} }
.users-table-region .ant-table-body { /* users table: flex-fill approach so overlay x-track aligns with table bottom */
height: auto !important; .users-table-region .ant-table-container {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
} }
.users-table-region .ant-table-header {
flex: 0 0 auto;
}
.users-table-region .ant-table-body {
flex: 1 1 auto;
min-height: 0;
height: 0 !important;
max-height: none !important;
}
.data-source-table-region .ant-table-wrapper, .data-source-table-region .ant-table-wrapper,
.data-source-table-region .ant-spin-nested-loading, .data-source-table-region .ant-spin-nested-loading,
.data-source-table-region .ant-spin-container { .data-source-table-region .ant-spin-container {
@@ -1911,6 +1959,14 @@ body {
min-width: 0; min-width: 0;
} }
.alerts-tab-panel > .ant-space-item:last-child,
.system-alerts-page__stack > .ant-space-item:last-child,
.bgp-alerts-page__stack > .ant-space-item:last-child,
.situational-alerts-page__stack > .ant-space-item:last-child {
flex: 1 1 auto;
min-height: 0;
}
.system-alerts-page__table-card, .system-alerts-page__table-card,
.bgp-alerts-page__table-card { .bgp-alerts-page__table-card {
flex: 1 1 auto; flex: 1 1 auto;
@@ -1935,8 +1991,22 @@ body {
min-height: 0; min-height: 0;
} }
.bgp-alerts-page__tabs, .bgp-alerts-page__tabs {
.bgp-alerts-page__tabs .ant-tabs-content-holder, min-width: 0;
min-height: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.bgp-alerts-page__tabs .ant-tabs-content-holder {
flex: 1 1 auto;
min-width: 0;
min-height: 0;
overflow: hidden;
}
.bgp-alerts-page__tabs .ant-tabs-content, .bgp-alerts-page__tabs .ant-tabs-content,
.bgp-alerts-page__tabs .ant-tabs-tabpane { .bgp-alerts-page__tabs .ant-tabs-tabpane {
min-width: 0; min-width: 0;

View File

@@ -239,6 +239,7 @@ function Playground() {
const [editingContent, setEditingContent] = useState('') const [editingContent, setEditingContent] = useState('')
const [editSaving, setEditSaving] = useState(false) const [editSaving, setEditSaving] = useState(false)
const [showScrollToBottom, setShowScrollToBottom] = useState(false) const [showScrollToBottom, setShowScrollToBottom] = useState(false)
const [composerFocused, setComposerFocused] = useState(false)
const pollTimerRef = useRef<number | null>(null) const pollTimerRef = useRef<number | null>(null)
const messagesContainerRef = useRef<HTMLDivElement | null>(null) const messagesContainerRef = useRef<HTMLDivElement | null>(null)
const messagesShellRef = useRef<HTMLDivElement | null>(null) const messagesShellRef = useRef<HTMLDivElement | null>(null)
@@ -681,7 +682,7 @@ function Playground() {
title="AI Chatbox" title="AI Chatbox"
extra={( extra={(
<Space size={4}> <Space size={4}>
<Tooltip title="服务状态"> <Tooltip title="服务状态" className="playground-chat__service-btn">
<Button <Button
type="text" type="text"
shape="circle" shape="circle"
@@ -849,31 +850,50 @@ function Playground() {
</div> </div>
<div className="playground-chat__composer"> <div className="playground-chat__composer">
<div className="playground-chat__input-wrap"> <div className={`playground-chat__input-wrap${composerFocused || !!inputValue ? ' playground-chat__input-wrap--expanded' : ''}`}>
<div className="playground-preset-strip__actions"> {(composerFocused || !!inputValue) && (
{PLAYGROUND_PRESETS.map((preset) => ( <div className="playground-preset-strip__actions">
<Tag.CheckableTag {PLAYGROUND_PRESETS.map((preset) => (
key={preset.key} <Tag.CheckableTag
checked={preset.key === selectedPreset.key} key={preset.key}
onChange={() => handleApplyPreset(preset)} checked={preset.key === selectedPreset.key}
> onChange={() => handleApplyPreset(preset)}
{preset.label} >
</Tag.CheckableTag> {preset.label}
))} </Tag.CheckableTag>
))}
</div>
)}
<div className="playground-chat__input-row">
<Input.TextArea
value={inputValue}
onChange={(event) => setInputValue(event.target.value)}
autoSize={composerFocused || !!inputValue ? { minRows: 4, maxRows: 10 } : { minRows: 1, maxRows: 1 }}
placeholder="在这里输入本次分析请求..."
className="playground-chat__input"
onFocus={() => setComposerFocused(true)}
onBlur={() => setComposerFocused(false)}
onPressEnter={(event) => {
if (!event.shiftKey) {
event.preventDefault()
void handleSend()
}
}}
/>
{!(composerFocused || !!inputValue) && (
<Tooltip title={sendButtonTooltip}>
<Button
type="text"
shape="circle"
className={`playground-chat__send-button${requestPending || streaming ? ' playground-chat__send-button--stop' : ''}`}
icon={requestPending || streaming ? <BorderOutlined /> : <ArrowUpOutlined />}
onClick={requestPending || streaming ? handleStop : () => void handleSend()}
aria-label={sendButtonTooltip}
/>
</Tooltip>
)}
</div> </div>
<Input.TextArea {(composerFocused || !!inputValue) && (
value={inputValue}
onChange={(event) => setInputValue(event.target.value)}
autoSize={{ minRows: 4, maxRows: 10 }}
placeholder="在这里输入本次分析请求。你可以写观察、问题、目标,或者直接贴一段待分析事实。"
className="playground-chat__input"
onPressEnter={(event) => {
if (!event.shiftKey) {
event.preventDefault()
void handleSend()
}
}}
/>
<div className="playground-chat__actions"> <div className="playground-chat__actions">
<div className="playground-chat__hints"> <div className="playground-chat__hints">
<Tag>{title}</Tag> <Tag>{title}</Tag>
@@ -890,8 +910,9 @@ function Playground() {
/> />
</Tooltip> </Tooltip>
</div> </div>
</div> )}
</div> </div>
</div>
</Card> </Card>
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react' import { useEffect, useState } from 'react'
import { Table, Button, Tag, Space, message, Modal, Form, Input, Select } from 'antd' import { Table, Button, Tag, Space, message, Modal, Form, Input, Select } from 'antd'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons' import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'
import axios from 'axios' import axios from 'axios'
@@ -19,8 +19,6 @@ function Users() {
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [modalVisible, setModalVisible] = useState(false) const [modalVisible, setModalVisible] = useState(false)
const [editingUser, setEditingUser] = useState<User | null>(null) const [editingUser, setEditingUser] = useState<User | null>(null)
const tableRegionRef = useRef<HTMLDivElement | null>(null)
const [tableHeight, setTableHeight] = useState(360)
const [form] = Form.useForm() const [form] = Form.useForm()
const fetchUsers = async () => { const fetchUsers = async () => {
@@ -37,24 +35,6 @@ function Users() {
fetchUsers() fetchUsers()
}, []) }, [])
useEffect(() => {
const updateTableHeight = () => {
const regionHeight = tableRegionRef.current?.offsetHeight || 0
setTableHeight(Math.max(220, regionHeight - 56))
}
updateTableHeight()
if (typeof ResizeObserver === 'undefined') {
return undefined
}
const observer = new ResizeObserver(updateTableHeight)
if (tableRegionRef.current) observer.observe(tableRegionRef.current)
return () => observer.disconnect()
}, [users.length])
const handleAdd = () => { const handleAdd = () => {
setEditingUser(null) setEditingUser(null)
form.resetFields() form.resetFields()
@@ -145,13 +125,14 @@ function Users() {
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}></Button> <Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}></Button>
</div> </div>
<div className="page-shell__body"> <div className="page-shell__body">
<TableScrollRegion ref={tableRegionRef} className="data-source-table-region users-table-region" style={{ height: '100%' }}> <TableScrollRegion className="data-source-table-region users-table-region">
<Table <Table
columns={columns} columns={columns}
dataSource={users} dataSource={users}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
scroll={{ x: 'max-content', y: tableHeight }} scroll={{ x: 960, y: 10000 }}
pagination={false}
tableLayout="fixed" tableLayout="fixed"
/> />
</TableScrollRegion> </TableScrollRegion>

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "planet" name = "planet"
version = "0.27.5" version = "0.27.6"
description = "智能星球计划 - 态势感知系统" description = "智能星球计划 - 态势感知系统"
requires-python = ">=3.14" requires-python = ">=3.14"
dependencies = [ dependencies = [

2
uv.lock generated
View File

@@ -475,7 +475,7 @@ wheels = [
[[package]] [[package]]
name = "planet" name = "planet"
version = "0.27.4" version = "0.27.6"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "aiofiles" }, { name = "aiofiles" },