From b33cef8c44153c7c53ebf8f291c840e70c0a33ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=9E=97=E9=93=96?= Date: Thu, 3 Sep 2026 10:00:59 +0800 Subject: [PATCH] feat: add team functions department navigation --- .../TeamFunctionsDashboard.test.tsx | 31 +++-- .../TeamFunctionsDashboard.tsx | 114 ++++++++++-------- 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/components/department-dashboard/TeamFunctionsDashboard.test.tsx b/components/department-dashboard/TeamFunctionsDashboard.test.tsx index 5a6ef84..6ae2af7 100644 --- a/components/department-dashboard/TeamFunctionsDashboard.test.tsx +++ b/components/department-dashboard/TeamFunctionsDashboard.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/react' +import { fireEvent, render, screen } from '@testing-library/react' import TeamFunctionsDashboard from './TeamFunctionsDashboard' jest.mock('next-auth/react', () => ({ @@ -7,24 +7,39 @@ jest.mock('next-auth/react', () => ({ })) describe('TeamFunctionsDashboard', () => { - it('shows the four teams and their function branches from the approved map', () => { + it('shows department navigation and the selected team introduction', () => { render() expect(screen.getByRole('heading', { level: 1, name: '团队职能' })).toBeInTheDocument() expect(screen.getByRole('heading', { level: 2, name: '品牌中心职责地图' })).toBeInTheDocument() + expect(screen.getByRole('complementary', { name: '团队职能二级部门导航' })).toBeInTheDocument() for (const team of ['品牌创意A部', '品牌创意B部', '空间设计部', '综合支持部']) { - expect(screen.getByRole('heading', { level: 2, name: team })).toBeInTheDocument() + expect(screen.getByRole('button', { name: new RegExp(team) })).toBeInTheDocument() } - for (const label of ['服务品牌', '前置能力', '定位', '岗位', '职责']) { - expect(screen.getAllByText(label).length).toBeGreaterThan(0) - } + expect(screen.getByRole('region', { name: '品牌创意A部部门介绍' })).toBeInTheDocument() + expect(screen.getByText('负责朴美、索菲亚、顾家品牌的视觉创意与内容前置策划,统筹品牌调性、商品卖点及页面与短视频创意。')).toBeInTheDocument() - for (const item of ['朴美', '索菲亚', '顾家', '欧意朗', '卓禾', '亿家达', '空间设计师', 'AIGC设计师', '批量生产']) { - expect(screen.getByText(item)).toBeInTheDocument() + for (const item of ['朴美', '索菲亚', '顾家', '品牌视觉策划设计', 'AI+平面+策划', '编导/短视频策划', '品牌调性', '商品卖点', '页面/短视频创意', '经验与复盘']) { + expect(screen.getByRole('region', { name: '品牌创意A部部门介绍' }).querySelector(`[data-team-item="${item}"]`)).not.toBeNull() } expect(screen.getByRole('link', { name: '返回部门看板' })).toHaveAttribute('href', '/') }) + + it('switches the department introduction from the secondary navigation', () => { + render() + + fireEvent.click(screen.getByRole('button', { name: /空间设计部/ })) + + expect(screen.getByRole('region', { name: '空间设计部部门介绍' })).toBeInTheDocument() + expect(screen.getByText('负责空间、置景、灯光、机位与拍摄一体化,为内容生产提供场景和拍摄执行能力。')).toBeInTheDocument() + expect(screen.queryByRole('region', { name: '品牌创意A部部门介绍' })).not.toBeInTheDocument() + expect(screen.getByText('美术指导')).toBeInTheDocument() + + fireEvent.click(screen.getByRole('button', { name: /品牌创意B部/ })) + expect(screen.getByRole('region', { name: '品牌创意B部部门介绍' })).toBeInTheDocument() + expect(screen.getByText('欧意朗')).toBeInTheDocument() + }) }) diff --git a/components/department-dashboard/TeamFunctionsDashboard.tsx b/components/department-dashboard/TeamFunctionsDashboard.tsx index 6462a08..70b9f1e 100644 --- a/components/department-dashboard/TeamFunctionsDashboard.tsx +++ b/components/department-dashboard/TeamFunctionsDashboard.tsx @@ -1,5 +1,8 @@ +'use client' + import Link from 'next/link' import { ArrowLeft, Blocks, BriefcaseBusiness, Check, Layers3, UsersRound } from 'lucide-react' +import { useState } from 'react' import DepartmentShell from './DepartmentShell' type FunctionBranch = { @@ -10,6 +13,7 @@ type FunctionBranch = { type TeamFunction = { name: string lead: string + description: string tone: 'coral' | 'navy' | 'blue' | 'teal' branches: FunctionBranch[] } @@ -18,6 +22,7 @@ const TEAM_FUNCTIONS: TeamFunction[] = [ { name: '品牌创意A部', lead: '伯言', + description: '负责朴美、索菲亚、顾家品牌的视觉创意与内容前置策划,统筹品牌调性、商品卖点及页面与短视频创意。', tone: 'coral', branches: [ { label: '服务品牌', items: ['朴美', '索菲亚', '顾家'] }, @@ -28,6 +33,7 @@ const TEAM_FUNCTIONS: TeamFunction[] = [ { name: '品牌创意B部', lead: '清云', + description: '负责欧意朗、卓禾、亿家达品牌的视觉创意与内容前置策划,推动品牌辅导、页面及短视频创意落地。', tone: 'navy', branches: [ { label: '服务品牌', items: ['欧意朗', '卓禾', '亿家达'] }, @@ -38,6 +44,7 @@ const TEAM_FUNCTIONS: TeamFunction[] = [ { name: '空间设计部', lead: '希文', + description: '负责空间、置景、灯光、机位与拍摄一体化,为内容生产提供场景和拍摄执行能力。', tone: 'blue', branches: [ { label: '定位', items: ['空间、置景、灯光、机位、拍摄一体化'] }, @@ -48,6 +55,7 @@ const TEAM_FUNCTIONS: TeamFunction[] = [ { name: '综合支持部', lead: '无邪', + description: '承接3D、AI、平面、修图、视频后期等生产支持,沉淀资产标准并推进批量生产。', tone: 'teal', branches: [ { label: '岗位', items: ['3D设计师', '平面设计师', 'AIGC设计师', '视频后期', '修图'] }, @@ -104,6 +112,7 @@ function Branch({ branch, tone }: { branch: FunctionBranch; tone: TeamFunction[' {branch.items.map((item) => (
@@ -116,41 +125,11 @@ function Branch({ branch, tone }: { branch: FunctionBranch; tone: TeamFunction[' ) } -function TeamFunctionPanel({ team }: { team: TeamFunction }) { - const colors = toneStyles[team.tone] - - return ( -
-
-
- - -
-

- {team.name} -

-

负责人:{team.lead}

-
-
- - 职能地图 - -
- -
-
- {team.branches.map((branch) => )} -
-
-
- ) -} - export default function TeamFunctionsDashboard() { + const [selectedTeamName, setSelectedTeamName] = useState(TEAM_FUNCTIONS[0].name) + const selectedTeam = TEAM_FUNCTIONS.find((team) => team.name === selectedTeamName) || TEAM_FUNCTIONS[0] + const colors = toneStyles[selectedTeam.tone] + return (
@@ -164,21 +143,62 @@ export default function TeamFunctionsDashboard() {

-
-
-
-

品牌中心职责地图

-

四个团队、三类职责层级;节点内容按现行团队分工整理。

+
+
+ + -
- {TEAM_FUNCTIONS.map((team) => )} -
+
+
+
+ + +
+

当前部门

+

{selectedTeam.name}

+

负责人:{selectedTeam.lead}

+
+
+
+ + +
+
+ +
+

{selectedTeam.description}

+
+ {selectedTeam.branches.map((branch) => )} +
+
+