diff --git a/.claude/plan/shared-subscription-display.md b/.claude/plan/shared-subscription-display.md new file mode 100644 index 0000000..878dd3e --- /dev/null +++ b/.claude/plan/shared-subscription-display.md @@ -0,0 +1,136 @@ +# 实施计划:后台管理 - 共享订阅显示 + +## 问题描述 + +设备组成员加入后,其原始订阅被删除,使用所有者的共享订阅。 +在后台管理的用户订阅面板中,查看设备组成员的订阅时显示为空,因为数据已在合并时被删除。 +需要在后台自动检测并显示共享订阅信息。 + +## 技术方案 + +**纯前端方案**,不需要后端 API 变更。利用现有 API 组合实现: + +1. `getUserSubscribe({ user_id })` → 获取用户自身订阅(可能为空) +2. `getFamilyList({ user_id, page: 1, size: 1 })` → 检测用户是否属于设备组 +3. `getUserSubscribe({ user_id: owner_user_id })` → 获取所有者的共享订阅 + +**核心逻辑**:当用户自身订阅为空时,自动检查是否为设备组成员。若是非所有者成员,则展示所有者的订阅信息,并添加"共享订阅"视觉标识。 + +## 实施步骤 + +### Step 1: 修改 UserSubscription 组件 + +**文件**: `apps/admin/src/sections/user/user-subscription/index.tsx` + +将组件从纯 ProTable 改为带有共享订阅检测逻辑的组件: + +``` +伪代码: +function UserSubscription({ userId }) { + // 1. 正常获取用户订阅 + const { data: ownSubscriptions } = useQuery(getUserSubscribe({ user_id: userId })) + + // 2. 当自身订阅为空时,检查设备组成员身份 + const hasOwnSubscriptions = ownSubscriptions.list.length > 0 + const { data: familyData } = useQuery( + getFamilyList({ user_id: userId, page: 1, size: 1 }), + { enabled: !hasOwnSubscriptions } // 仅当订阅为空时触发 + ) + + // 3. 判断是否为非所有者成员 + const family = familyData?.list?.[0] + const isNonOwnerMember = family && family.owner_user_id !== userId && family.status === 'active' + const ownerUserId = family?.owner_user_id + + // 4. 若为成员,获取所有者的订阅 + const { data: sharedSubscriptions } = useQuery( + getUserSubscribe({ user_id: ownerUserId }), + { enabled: isNonOwnerMember && !!ownerUserId } + ) + + // 5. 决定展示内容 + const isSharedView = isNonOwnerMember && sharedSubscriptions?.list?.length > 0 + const displayData = isSharedView ? sharedSubscriptions : ownSubscriptions + + return ( +
+ {t( + "email.templateVariables.title", + "Template Variables" + )} +
+
+ {"{{.SiteLogo}}"}
+
+
+ {t(
+ "email.templateVariables.siteLogo.description",
+ "Site logo URL"
+ )}
+
+
+ {"{{.SiteName}}"}
+
+
+ {t(
+ "email.templateVariables.siteName.description",
+ "Site name"
+ )}
+
+
+ {"{{.Code}}"}
+
+
+ {t(
+ "email.templateVariables.code.description",
+ "Verification code"
+ )}
+
+
+ {"{{.Expire}}"}
+
+
+ {t(
+ "email.templateVariables.expire.description",
+ "Code expiration time"
+ )}
+
+