Skip to content

Commit 7a8b750

Browse files
refactor(antd6): clear residual v6 deprecations (#61)
Follow-up to #53, unblocked by the user's visual verification. List→Listy across 19 files/30 uses (Listy is NOT 1:1 with List: items/rowKey required, no loading/locale/bordered/size/Meta — rebuilt via shared ListyItem/ListyMeta components + token-based listyPadding density parity, loading→Spin wrapper, emptyText→Empty, bordered→styles.root; ConversationSidebar CSS .ant-list-item→.ant-listy-item), addonAfter/addonBefore→Space.Compact (3 places, Form.Item label↔input association preserved), Dropdown.Button→Space.Compact+Button+Dropdown (JobsPage). Single test-scope change (closest li→.ant-listy-item), assertions unchanged. CI 10/10.
1 parent 9f50c58 commit 7a8b750

26 files changed

Lines changed: 926 additions & 717 deletions

‎frontend/src/components/InterviewExperiencePanel.tsx‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
Empty,
1010
Form,
1111
Input,
12-
List,
12+
Listy,
1313
Modal,
1414
Select,
1515
Space,
@@ -31,6 +31,7 @@ import type { ExperienceSource, InterviewExperience, InterviewExperiencePayload
3131
import { formatDateTime } from "../utils/format";
3232
import { RecordDetailDrawer } from "./common/RecordDetail";
3333
import { isFromInnerControl } from "./common/recordDetailCore";
34+
import { ListyItem, ListyMeta } from "./common/ListyItem";
3435
import { useRowActionMenu } from "./common/rowActionMenu";
3536

3637
interface Props {
@@ -155,10 +156,11 @@ export default function InterviewExperiencePanel({ jobOptions }: Props) {
155156
) : items.length === 0 ? (
156157
<Empty description="还没有面经,把面试里被问到的问题记下来吧" />
157158
) : (
158-
<List
159-
dataSource={items}
160-
renderItem={(item) => (
161-
<List.Item
159+
<Listy
160+
items={items}
161+
rowKey={(item) => item.id}
162+
itemRender={(item) => (
163+
<ListyItem
162164
className="detail-trigger"
163165
// 整条点开详情;行内的「详情 / 更多」按钮不会被这一层抢走。
164166
onClick={(event) => {
@@ -200,7 +202,7 @@ export default function InterviewExperiencePanel({ jobOptions }: Props) {
200202
</Dropdown>,
201203
]}
202204
>
203-
<List.Item.Meta
205+
<ListyMeta
204206
title={
205207
<Space size={6} wrap>
206208
<span>{item.title || "未命名面经"}</span>
@@ -233,7 +235,7 @@ export default function InterviewExperiencePanel({ jobOptions }: Props) {
233235
</Space>
234236
}
235237
/>
236-
</List.Item>
238+
</ListyItem>
237239
)}
238240
/>
239241
)}

‎frontend/src/components/InterviewReviewPanel.tsx‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
Collapse,
2323
Empty,
2424
Input,
25-
List,
25+
Listy,
2626
Select,
2727
Space,
2828
Tag,
@@ -38,6 +38,7 @@ import {
3838
updateReview,
3939
} from "../api/interview";
4040
import { RowActions } from "./common/RowActions";
41+
import { ListyItem, ListyMeta } from "./common/ListyItem";
4142
import { useApi } from "../hooks/useApi";
4243
import type { InterviewAnalysis, InterviewOptimizeResult, InterviewReviewRecord } from "../types";
4344

@@ -423,11 +424,12 @@ export default function InterviewReviewPanel({
423424
{viewSuggestions.length === 0 ? (
424425
<Alert type="info" showIcon title="没有产出建议,试试补充更多面试暴露的短板或追问" />
425426
) : (
426-
<List
427-
dataSource={viewSuggestions}
428-
renderItem={(item) => (
429-
<List.Item>
430-
<List.Item.Meta
427+
<Listy
428+
items={viewSuggestions}
429+
rowKey={(item) => `${item.section}|${item.issue}|${item.suggestion}`}
430+
itemRender={(item) => (
431+
<ListyItem>
432+
<ListyMeta
431433
title={
432434
<Space size={6} wrap>
433435
<Tag color={priorityColor(item.priority)}>{item.priority}</Tag>
@@ -448,7 +450,7 @@ export default function InterviewReviewPanel({
448450
</Space>
449451
}
450452
/>
451-
</List.Item>
453+
</ListyItem>
452454
)}
453455
/>
454456
)}

‎frontend/src/components/JobAnalysisModal.tsx‎

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/** 按需生成岗位需求总结和通用求职建议。 */
22
import { BulbOutlined, ReloadOutlined } from "@ant-design/icons";
3-
import { Alert, Button, Empty, List, Modal, Skeleton, Space, Tag, Typography } from "antd";
3+
import { Alert, Button, Empty, Listy, Modal, Skeleton, Space, Tag, Typography } from "antd";
4+
import { ListyItem } from "./common/ListyItem";
45
import { announceBackgroundFailure, announceBackgroundResult } from "../utils/backgroundTask";
56
import { useCallback, useEffect, useRef, useState } from "react";
67
import { generateJobAnalysis } from "../api/jobs";
@@ -140,12 +141,13 @@ export default function JobAnalysisModal({ job, onClose }: Props) {
140141

141142
<Typography.Title level={5}>核心需求</Typography.Title>
142143
{data.requirements.length ? (
143-
<List
144-
dataSource={data.requirements}
145-
renderItem={(item) => {
144+
<Listy
145+
items={data.requirements}
146+
rowKey={(item) => `${item.requirement}|${item.category ?? ""}`}
147+
itemRender={(item) => {
146148
const priority = PRIORITY_META[item.priority];
147149
return (
148-
<List.Item>
150+
<ListyItem>
149151
<Space orientation="vertical" size={5} style={{ width: "100%" }}>
150152
<Space wrap>
151153
<Tag color={priority.color}>{priority.label}</Tag>
@@ -156,7 +158,7 @@ export default function JobAnalysisModal({ job, onClose }: Props) {
156158
<Typography.Text type="secondary">依据:{item.evidence}</Typography.Text>
157159
)}
158160
</Space>
159-
</List.Item>
161+
</ListyItem>
160162
);
161163
}}
162164
/>
@@ -166,18 +168,19 @@ export default function JobAnalysisModal({ job, onClose }: Props) {
166168

167169
<Typography.Title level={5}>求职建议</Typography.Title>
168170
{data.advice.length ? (
169-
<List
170-
dataSource={data.advice}
171-
renderItem={(item) => (
172-
<List.Item>
171+
<Listy
172+
items={data.advice}
173+
rowKey={(item) => `${item.title}|${item.action}`}
174+
itemRender={(item) => (
175+
<ListyItem>
173176
<Space orientation="vertical" size={4}>
174177
<Typography.Text strong>{item.title}</Typography.Text>
175178
<Typography.Text>{item.action}</Typography.Text>
176179
{item.rationale && (
177180
<Typography.Text type="secondary">原因:{item.rationale}</Typography.Text>
178181
)}
179182
</Space>
180-
</List.Item>
183+
</ListyItem>
181184
)}
182185
/>
183186
) : (

‎frontend/src/components/JobMatchBatchPanel.tsx‎

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
Card,
88
Collapse,
99
Empty,
10-
List,
10+
Listy,
1111
Modal,
1212
Progress,
1313
Skeleton,
@@ -17,6 +17,8 @@ import {
1717
Tag,
1818
Typography,
1919
} from "antd";
20+
import { ListyItem, ListyMeta } from "./common/ListyItem";
21+
import { LISTY_ITEM_PADDING_SMALL } from "./common/listyPadding";
2022
import { useCallback, useEffect, useState } from "react";
2123
import {
2224
generateJobMatchBatch,
@@ -69,13 +71,14 @@ function ConditionList({ conditions }: { conditions: MatchCondition[] }) {
6971
return <Typography.Text type="secondary">暂无条目</Typography.Text>;
7072
}
7173
return (
72-
<List
73-
size="small"
74-
dataSource={conditions}
75-
renderItem={(condition) => {
74+
<Listy
75+
items={conditions}
76+
rowKey={(condition) => `${condition.label}|${condition.jd_quote}`}
77+
styles={{ item: { ...LISTY_ITEM_PADDING_SMALL } }}
78+
itemRender={(condition) => {
7679
const meta = MATCH_STATUS_META[condition.status];
7780
return (
78-
<List.Item>
81+
<ListyItem>
7982
<Space orientation="vertical" size={2} style={{ width: "100%" }}>
8083
<Space size={6} wrap>
8184
<Tag color={meta.color}>{meta.label}</Tag>
@@ -85,7 +88,7 @@ function ConditionList({ conditions }: { conditions: MatchCondition[] }) {
8588
<Typography.Text type="secondary">依据:{condition.evidence}</Typography.Text>
8689
) : null}
8790
</Space>
88-
</List.Item>
91+
</ListyItem>
8992
);
9093
}}
9194
/>
@@ -276,17 +279,21 @@ export default function JobMatchBatchPanel({
276279
title={`已完成 ${batch.completed_count} 个岗位,${batch.failed_count} 个岗位失败`}
277280
description={`结果已保存,可在「历史记录」中回看;已按匹配度参考分从高到低排列。${batch.model ? `本批使用模型:${batch.model}` : "本批未配置模型,使用本地降级结果。"}`}
278281
/>
279-
<List
280-
dataSource={batch.items}
281-
locale={{ emptyText: "没有可展示的分析结果" }}
282-
renderItem={(item) => (
283-
<List.Item key={`${batch.id}-${item.job_id}`}>
284-
<div style={{ width: "100%" }}>
285-
<BatchItemCard item={item} />
286-
</div>
287-
</List.Item>
288-
)}
289-
/>
282+
{batch.items.length === 0 ? (
283+
<Typography.Text type="secondary">没有可展示的分析结果</Typography.Text>
284+
) : (
285+
<Listy
286+
items={batch.items}
287+
rowKey={(item) => `${batch.id}-${item.job_id}`}
288+
itemRender={(item) => (
289+
<ListyItem>
290+
<div style={{ width: "100%" }}>
291+
<BatchItemCard item={item} />
292+
</div>
293+
</ListyItem>
294+
)}
295+
/>
296+
)}
290297
</Space>
291298
) : (
292299
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="选择岗位后开始批量分析" />
@@ -297,22 +304,22 @@ export default function JobMatchBatchPanel({
297304
) : history.length === 0 ? (
298305
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="还没有批量分析记录" />
299306
) : (
300-
<List
301-
dataSource={history}
302-
renderItem={(item) => (
303-
<List.Item
304-
key={item.id}
307+
<Listy
308+
items={history}
309+
rowKey={(item) => item.id}
310+
itemRender={(item) => (
311+
<ListyItem
305312
actions={[
306313
<Button key="view" type="link" onClick={() => void openHistory(item.id)}>
307314
查看结果
308315
</Button>,
309316
]}
310317
>
311-
<List.Item.Meta
318+
<ListyMeta
312319
title={`第 ${item.id} 批 · ${formatTime(item.created_at)}`}
313320
description={`共 ${item.requested_count} 个岗位,完成 ${item.completed_count} 个,失败 ${item.failed_count} 个${item.top_score === null ? "" : `,最高参考分 ${item.top_score}`}`}
314321
/>
315-
</List.Item>
322+
</ListyItem>
316323
)}
317324
/>
318325
);

‎frontend/src/components/ReferralPanel.tsx‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
Empty,
2222
Form,
2323
Input,
24-
List,
24+
Listy,
2525
Modal,
2626
Row,
2727
Select,
@@ -49,6 +49,7 @@ import { classifyAttachment, IMAGE_ACCEPT, MAX_ATTACHMENT_BYTES } from "../utils
4949
import { formatDateTime } from "../utils/format";
5050
import { RecordDetailDrawer } from "./common/RecordDetail";
5151
import { isFromInnerControl } from "./common/recordDetailCore";
52+
import { ListyItem, ListyMeta } from "./common/ListyItem";
5253
import { useRowActionMenu } from "./common/rowActionMenu";
5354

5455
/** 与后端 ``schemas/referral.MAX_NOTE_IMAGES`` 保持一致。 */
@@ -248,10 +249,11 @@ export default function ReferralPanel({ jobOptions = [], trackOptions = [] }: Pr
248249
) : items.length === 0 ? (
249250
<Empty description="还没有内推记录,把找人内推的机会记下来吧" />
250251
) : (
251-
<List
252-
dataSource={items}
253-
renderItem={(item) => (
254-
<List.Item
252+
<Listy
253+
items={items}
254+
rowKey={(item) => item.id}
255+
itemRender={(item) => (
256+
<ListyItem
255257
className="detail-trigger"
256258
// 整条可点开详情;内层的「详情 / 更多」按钮不会被这一层抢走。
257259
onClick={(event) => {
@@ -293,7 +295,7 @@ export default function ReferralPanel({ jobOptions = [], trackOptions = [] }: Pr
293295
</Dropdown>,
294296
]}
295297
>
296-
<List.Item.Meta
298+
<ListyMeta
297299
title={
298300
<Space size={6} wrap>
299301
<span>
@@ -334,7 +336,7 @@ export default function ReferralPanel({ jobOptions = [], trackOptions = [] }: Pr
334336
</Space>
335337
}
336338
/>
337-
</List.Item>
339+
</ListyItem>
338340
)}
339341
/>
340342
)}

‎frontend/src/components/ReminderPanel.tsx‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
Empty,
1919
Form,
2020
Input,
21-
List,
21+
Listy,
2222
Modal,
2323
Popconfirm,
2424
Segmented,
@@ -38,6 +38,8 @@ import type { Reminder, ReminderKind, ReminderStatus } from "../types";
3838
import { formatDateTime } from "../utils/format";
3939
import { RecordDetailDrawer } from "./common/RecordDetail";
4040
import { isFromInnerControl } from "./common/recordDetailCore";
41+
import { ListyItem, ListyMeta } from "./common/ListyItem";
42+
import { LISTY_ITEM_PADDING_DEFAULT } from "./common/listyPadding";
4143
import CalendarView from "./tracker/CalendarView";
4244

4345
interface Option {
@@ -193,9 +195,11 @@ export default function ReminderPanel({
193195
) : items.length === 0 ? (
194196
<Empty description="还没有提醒,把面试、测评截止这些时点记下来吧" />
195197
) : (
196-
<List
197-
dataSource={items}
198-
renderItem={(item) => {
198+
<Listy
199+
items={items}
200+
rowKey={(item) => item.id}
201+
styles={{ item: { ...LISTY_ITEM_PADDING_DEFAULT } }}
202+
itemRender={(item) => {
199203
// 「详情」放在第一位:列表只放得下摘要,备注、绑定对象这些都得点进去看。
200204
const actions = [
201205
<Button key="detail" type="link" size="small" onClick={() => setDetail(item)}>
@@ -258,7 +262,7 @@ export default function ReminderPanel({
258262
</Popconfirm>,
259263
);
260264
return (
261-
<List.Item
265+
<ListyItem
262266
className="detail-trigger"
263267
actions={actions}
264268
// 整条点开详情;行内按钮与二次确认不会被这一层抢走。
@@ -267,7 +271,7 @@ export default function ReminderPanel({
267271
setDetail(item);
268272
}}
269273
>
270-
<List.Item.Meta
274+
<ListyMeta
271275
title={
272276
<Space size={6} wrap>
273277
<span>{item.title}</span>
@@ -292,7 +296,7 @@ export default function ReminderPanel({
292296
</Typography.Text>
293297
}
294298
/>
295-
</List.Item>
299+
</ListyItem>
296300
);
297301
}}
298302
/>

0 commit comments

Comments
 (0)