feat(admin): 分组能力按类型收口(应用可分组,海报/图文平铺)
- 只有应用类分区显示分组管理与卡片预览分组;海报/图文保持平铺 - 后端 create_group 拒绝非应用分区;海报/图文读取时把历史分组条目一并平铺 - 侧栏不再显示非应用分组与空分组 - 类型 应用 ↔ 海报 切换时分组入口和侧栏子项随之出现/消失 - 测试 59 passed
This commit is contained in:
@@ -539,7 +539,7 @@ function SidebarForm({
|
||||
</div>
|
||||
))}
|
||||
|
||||
{(
|
||||
{category.kind === 'apps' && (
|
||||
<div className="admin-nav-group-row">
|
||||
<NewGroupRow sectionId={category.id} onReload={onReload} />
|
||||
</div>
|
||||
@@ -762,8 +762,12 @@ function CategoryManager({
|
||||
onReload={onReload}
|
||||
onDelete={onDelete}
|
||||
/>
|
||||
<BlockSelect section={category} onReload={onReload} />
|
||||
<GroupManager section={category} onReload={onReload} />
|
||||
{category.kind === 'apps' && (
|
||||
<>
|
||||
<BlockSelect section={category} onReload={onReload} />
|
||||
<GroupManager section={category} onReload={onReload} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -1271,7 +1275,7 @@ function EntryDialog({
|
||||
|
||||
const section =
|
||||
categories.find((category) => category.id === sectionId) ?? categories[0]
|
||||
const groups = section?.groups ?? []
|
||||
const groups = section?.kind === 'apps' ? (section.groups ?? []) : []
|
||||
|
||||
// 打开时重置:新建用当前选择,编辑先拉完整条目
|
||||
useEffect(() => {
|
||||
@@ -1281,10 +1285,10 @@ function EntryDialog({
|
||||
const startSection =
|
||||
defaultLocation?.sectionId ?? categories[0]?.id ?? ''
|
||||
setSectionId(startSection)
|
||||
const startCategory = categories.find((category) => category.id === startSection)
|
||||
setGroupId(
|
||||
defaultLocation?.groupId ??
|
||||
categories.find((category) => category.id === startSection)?.groups?.[0]?.id ??
|
||||
'',
|
||||
(startCategory?.kind === 'apps' ? (startCategory.groups?.[0]?.id ?? '') : ''),
|
||||
)
|
||||
|
||||
if (entryKey === null) {
|
||||
@@ -1322,16 +1326,23 @@ function EntryDialog({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [open, entryKey])
|
||||
|
||||
// 分区切换后保证分组仍然合法(空字符串 = 直属分区)
|
||||
// 只有应用类分区有分组;其余类型始终是直属分区
|
||||
useEffect(() => {
|
||||
if (section === undefined) return
|
||||
if (section?.kind !== 'apps') {
|
||||
if (groupId !== '') setGroupId('')
|
||||
return
|
||||
}
|
||||
if (groupId !== '' && !groups.some((group) => group.id === groupId)) {
|
||||
setGroupId(groups[0]?.id ?? '')
|
||||
}
|
||||
}, [section, groups, groupId])
|
||||
|
||||
const nodeKey =
|
||||
section === undefined ? '' : groupId !== '' ? groupId : section.id
|
||||
section === undefined
|
||||
? ''
|
||||
: section.kind === 'apps' && groupId !== ''
|
||||
? groupId
|
||||
: section.id
|
||||
|
||||
const update = (patch: Partial<EntryForm>) =>
|
||||
setForm((previous) => ({ ...previous, ...patch }))
|
||||
@@ -1428,7 +1439,7 @@ function EntryDialog({
|
||||
onChange={setSectionId}
|
||||
/>
|
||||
</div>
|
||||
{section !== undefined && (
|
||||
{section?.kind === 'apps' && (
|
||||
<div style={{ width: 240 }}>
|
||||
<Select
|
||||
options={[
|
||||
|
||||
@@ -38,9 +38,11 @@ export function CategoryNav({
|
||||
const items: MenuItem[] = [
|
||||
{ key: HOME_KEY, label: '首页' },
|
||||
...categories.map((category) => {
|
||||
// 分组已由 App 按 /admin 的侧栏设置过滤、排序(含 show_in_sidebar 覆盖);
|
||||
// 应用 / 海报 / 图文都支持分组
|
||||
const groups = category.groups
|
||||
// 只有应用类有分组;空分组不出现在侧栏(后台仍保留)
|
||||
const groups =
|
||||
category.kind === 'apps'
|
||||
? category.groups.filter((group) => group.items.length > 0)
|
||||
: []
|
||||
|
||||
return {
|
||||
key: categoryKey(category.id),
|
||||
|
||||
Reference in New Issue
Block a user