feat: Pro 买断门禁、SFTP 精简与批量多机改造

新增 entitlement/license IPC 与 Waffo 一次性结账服务骨架,挂载 AI/转发/代理/串口/广播/批量导入导出门禁;批量执行改为结果矩阵并复用连接池,SFTP 工具栏图标化并去掉已连接条,同时完善跨平台本地终端与窗口配置。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Logan.LiandCursor committed 2026-08-07 11:38:30 +08:00
1 parent 101d2164b4
commit fea6d8db04
72 files changed
+3307 -396

No files matched your search

@@ -7,6 +7,7 @@ import SerialConnectDialog from '../../src/components/serial/SerialConnectDialog
import { useSessionStore } from '../../src/stores/sessionStore'
import { useTabStore } from '../../src/stores/tabStore'
import { mockDesktopApi } from '../setup'
import { unlockProForTests } from '../helpers/entitlement'
const serialMocks = vi.hoisted(() => ({
listSerialPorts: vi.fn(),
@@ -19,6 +20,7 @@ vi.mock('../../src/platform/serial', () => ({
describe('Quick launcher and serial acceptance', () => {
beforeEach(() => {
vi.clearAllMocks()
unlockProForTests()
window.opsxApi = mockDesktopApi
serialMocks.listSerialPorts.mockResolvedValue([
{ path: '/dev/tty.debug-console', portType: 'Serial' },
@@ -96,12 +98,12 @@ describe('Quick launcher and serial acceptance', () => {
})
})
it('keeps the documented manual serial path when enumeration returns no devices', async () => {
it('keeps the platform default serial path when enumeration returns no devices', async () => {
serialMocks.listSerialPorts.mockResolvedValue([])
render(<SerialConnectDialog isOpen onClose={vi.fn()} onConnect={vi.fn()} />)
await waitFor(() => expect(serialMocks.listSerialPorts).toHaveBeenCalled())
expect(screen.getByLabelText('设备')).toHaveValue('/dev/tty.debug-console')
expect(screen.getByText(/\/dev\/tty\.Bluetooth-Incoming-Port/)).toBeVisible()
expect(screen.getByLabelText('设备')).toHaveValue('/dev/tty.usbserial')
expect(screen.queryByRole('button', { name: /Bluetooth-Incoming-Port/ })).toBeNull()
})
})