feat(web): unify admin and operations identity
This commit is contained in:
@@ -70,7 +70,9 @@ test('renders reconciliation queue, loads evidence on demand and records review
|
|||||||
|
|
||||||
expect(await screen.findByText('质量问题队列')).toBeInTheDocument();
|
expect(await screen.findByText('质量问题队列')).toBeInTheDocument();
|
||||||
expect(screen.getByRole('heading', { name: '运行与数据质量', level: 5 })).toBeInTheDocument();
|
expect(screen.getByRole('heading', { name: '运行与数据质量', level: 5 })).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText('运维质量操作')).toHaveClass('v2-workspace-command-bar', 'v2-ops-command-bar');
|
expect(screen.getByLabelText('运维质量操作')).toHaveClass('v2-workspace-command-bar', 'v2-ops-command-bar', 'has-identity');
|
||||||
|
expect(screen.getByLabelText('运维质量操作')).toHaveTextContent('运行治理');
|
||||||
|
expect(screen.getByLabelText('运维质量操作').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument();
|
||||||
expect(screen.getByRole('button', { name: '刷新全局证据' })).toHaveClass('v2-workspace-mobile-tool-button', 'is-muted');
|
expect(screen.getByRole('button', { name: '刷新全局证据' })).toHaveClass('v2-workspace-mobile-tool-button', 'is-muted');
|
||||||
const navigation = screen.getByRole('navigation', { name: '运维质量视图' });
|
const navigation = screen.getByRole('navigation', { name: '运维质量视图' });
|
||||||
expect(navigation).toHaveClass('v2-ops-navigation');
|
expect(navigation).toHaveClass('v2-ops-navigation');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IconRefresh, IconSearch, IconTickCircle } from '@douyinfe/semi-icons';
|
import { IconPulse, IconRefresh, IconSearch, IconTickCircle } from '@douyinfe/semi-icons';
|
||||||
import { Button, Card, CardGroup, Checkbox, Descriptions, Empty, Input, Progress, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
import { Button, Card, CardGroup, Checkbox, Descriptions, Empty, Input, Progress, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { FormEvent, useDeferredValue, useEffect, useMemo, useState } from 'react';
|
import { FormEvent, useDeferredValue, useEffect, useMemo, useState } from 'react';
|
||||||
@@ -534,6 +534,8 @@ export default function OperationsPage() {
|
|||||||
<WorkspaceCommandBar
|
<WorkspaceCommandBar
|
||||||
className="v2-ops-command-bar"
|
className="v2-ops-command-bar"
|
||||||
ariaLabel="运维质量操作"
|
ariaLabel="运维质量操作"
|
||||||
|
eyebrow="运行治理"
|
||||||
|
icon={<IconPulse />}
|
||||||
title="运行与数据质量"
|
title="运行与数据质量"
|
||||||
description="集中处理自动对账问题,按需诊断单车来源,并核对服务与协议健康;所有结论均可追溯。"
|
description="集中处理自动对账问题,按需诊断单车来源,并核对服务与协议健康;所有结论均可追溯。"
|
||||||
status={data?.runtime.dataMode === 'production' ? '生产模式' : '状态待确认'}
|
status={data?.runtime.dataMode === 'production' ? '生产模式' : '状态待确认'}
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ test('deduplicates vehicle candidates by VIN and renders granted vehicles plate
|
|||||||
const view = render(<QueryClientProvider client={client}><UsersPage /></QueryClientProvider>);
|
const view = render(<QueryClientProvider client={client}><UsersPage /></QueryClientProvider>);
|
||||||
|
|
||||||
const customer = await screen.findByRole('button', { name: /选择客户 华东客户/ });
|
const customer = await screen.findByRole('button', { name: /选择客户 华东客户/ });
|
||||||
|
expect(screen.getByLabelText('账号管理操作')).toHaveClass('has-identity');
|
||||||
|
expect(screen.getByLabelText('账号管理操作')).toHaveTextContent('访问治理');
|
||||||
|
expect(screen.getByLabelText('账号管理操作').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText('账号管理操作')).toHaveTextContent('客户访问治理');
|
expect(screen.getByLabelText('账号管理操作')).toHaveTextContent('客户访问治理');
|
||||||
expect(screen.getByLabelText('账号管理操作')).toHaveTextContent('变更最多 30 秒生效');
|
expect(screen.getByLabelText('账号管理操作')).toHaveTextContent('变更最多 30 秒生效');
|
||||||
expect(view.container.querySelector('.v2-page-heading')).not.toBeInTheDocument();
|
expect(view.container.querySelector('.v2-page-heading')).not.toBeInTheDocument();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { IconChevronRight, IconDelete, IconPlus, IconRefresh, IconSearch } from '@douyinfe/semi-icons';
|
import { IconChevronRight, IconDelete, IconPlus, IconRefresh, IconSearch, IconUserGroup } from '@douyinfe/semi-icons';
|
||||||
import { Avatar, Button, Card, Checkbox, Collapse, Empty, Input, List, Select, Spin, Switch, Tabs, Tag, Typography } from '@douyinfe/semi-ui';
|
import { Avatar, Button, Card, Checkbox, Collapse, Empty, Input, List, Select, Spin, Switch, Tabs, Tag, Typography } from '@douyinfe/semi-ui';
|
||||||
import { FormEvent, useDeferredValue, useEffect, useMemo, useState } from 'react';
|
import { FormEvent, useDeferredValue, useEffect, useMemo, useState } from 'react';
|
||||||
import { api } from '../../api/client';
|
import { api } from '../../api/client';
|
||||||
@@ -431,6 +431,8 @@ export default function UsersPage() {
|
|||||||
<WorkspaceCommandBar
|
<WorkspaceCommandBar
|
||||||
className="v2-user-command-bar"
|
className="v2-user-command-bar"
|
||||||
ariaLabel="账号管理操作"
|
ariaLabel="账号管理操作"
|
||||||
|
eyebrow="访问治理"
|
||||||
|
icon={<IconUserGroup />}
|
||||||
title="客户访问治理"
|
title="客户访问治理"
|
||||||
description="菜单与车辆按最小权限开放,变更最多 30 秒生效"
|
description="菜单与车辆按最小权限开放,变更最多 30 秒生效"
|
||||||
status={`${customers.length} 个客户账号${attentionCustomerCount ? ` · ${attentionCustomerCount} 待完善` : ' · 权限就绪'}`}
|
status={`${customers.length} 个客户账号${attentionCustomerCount ? ` · ${attentionCustomerCount} 待完善` : ' · 权限就绪'}`}
|
||||||
|
|||||||
@@ -27049,3 +27049,200 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Administration and operations identity convergence.
|
||||||
|
* Keep account authority and runtime health visually distinct while retaining
|
||||||
|
* the same Semi command anatomy and compact responsive behavior.
|
||||||
|
*/
|
||||||
|
.v2-user-discovery-shell > .v2-user-command-bar.has-identity {
|
||||||
|
min-height: 58px;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 9% -100%, rgba(109, 91, 208, .1), transparent 46%),
|
||||||
|
linear-gradient(106deg, #fff 0%, #fdfcff 52%, #fbfdff 100%);
|
||||||
|
padding: 8px 10px 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-copy {
|
||||||
|
min-width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-icon.semi-avatar {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
flex-basis: 34px;
|
||||||
|
border-color: rgba(109, 91, 208, .13);
|
||||||
|
border-radius: 10px;
|
||||||
|
background: linear-gradient(145deg, #f5f2ff 0%, #eee9ff 100%);
|
||||||
|
color: #6656c8;
|
||||||
|
box-shadow: inset 0 1px rgba(255, 255, 255, .9), 0 5px 14px rgba(109, 91, 208, .07);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-stack {
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-eyebrow {
|
||||||
|
color: #8177af;
|
||||||
|
font-size: 7px;
|
||||||
|
line-height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-title {
|
||||||
|
color: #334155;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 760;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-description {
|
||||||
|
color: #8793a3;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-actions > .semi-tag {
|
||||||
|
border-color: rgba(109, 91, 208, .1);
|
||||||
|
background: #f4f1ff;
|
||||||
|
color: #6656c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-page > .v2-ops-command-bar.has-identity {
|
||||||
|
min-height: 60px;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 8% -100%, rgba(16, 148, 110, .1), transparent 47%),
|
||||||
|
linear-gradient(108deg, #fff 0%, #fbfffd 52%, #fbfdff 100%);
|
||||||
|
padding: 8px 10px 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-copy {
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-icon.semi-avatar {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
flex-basis: 34px;
|
||||||
|
border-color: rgba(16, 148, 110, .13);
|
||||||
|
border-radius: 10px;
|
||||||
|
background: linear-gradient(145deg, #edfbf6 0%, #e3f7ef 100%);
|
||||||
|
color: #0f8f68;
|
||||||
|
box-shadow: inset 0 1px rgba(255, 255, 255, .9), 0 5px 14px rgba(16, 148, 110, .07);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-stack {
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-eyebrow {
|
||||||
|
color: #5f8e7d;
|
||||||
|
font-size: 7px;
|
||||||
|
line-height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-title {
|
||||||
|
color: #334155;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 760;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-description {
|
||||||
|
max-width: 520px;
|
||||||
|
color: #8793a3;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-actions > .semi-tag {
|
||||||
|
border-color: rgba(16, 148, 110, .1);
|
||||||
|
background: #eaf8f3;
|
||||||
|
color: #0f7d5e;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 681px) and (max-width: 980px) {
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-copy,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-copy {
|
||||||
|
min-width: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-description,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-description {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
.v2-user-discovery-shell > .v2-user-command-bar.has-identity,
|
||||||
|
.v2-ops-page > .v2-ops-command-bar.has-identity {
|
||||||
|
min-height: 56px;
|
||||||
|
padding: 6px 7px 6px 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-copy,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-copy {
|
||||||
|
min-width: 0;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-icon.semi-avatar,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-icon.semi-avatar {
|
||||||
|
width: 31px;
|
||||||
|
height: 31px;
|
||||||
|
flex-basis: 31px;
|
||||||
|
border-radius: 9px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-eyebrow,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-eyebrow {
|
||||||
|
font-size: 7px;
|
||||||
|
line-height: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-title,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-title {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-description,
|
||||||
|
.v2-user-command-bar.has-identity .v2-workspace-command-meta,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-description,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-meta {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) and (max-height: 480px) and (orientation: landscape) {
|
||||||
|
.v2-ops-page > .v2-ops-command-bar.has-identity {
|
||||||
|
height: 44px;
|
||||||
|
min-height: 44px;
|
||||||
|
padding: 4px 5px 4px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-copy {
|
||||||
|
min-width: 0;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-icon.semi-avatar {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
flex-basis: 28px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-eyebrow,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-description,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-status,
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-meta {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-command-bar.has-identity .v2-workspace-command-title {
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user