feat: 项目负责人+内部任务群+portal 内部身份领取+群主链接归属
- 迁移 0012:projects.owner_userid / tasks.task_chat_id / claims.owner_partner_id - lib/task-group-service.ts:懒建 appchat 任务群(首个内部群主领取时创建,成员 diff 补员),播报/卡片文案 - wecom-client 新增 appchat create/update/get/send 封装 - OAuth ticket 增可选 uid(v:1 兼容),内部成员领取按 wecom_userid 解析群主身份 - 外部 OAuth 领取人 upsert 打 partner_type='group_owner' - portal 链接带 ?owner= 穿透 OAuth 往返,claims 记录归属群主 - 后台任务卡「群主链接」面板:复制链接/推送内部群主/任务群状态 - 催办与超期升级同步播报进任务群
This commit is contained in:
@@ -133,6 +133,7 @@ type PortalParams = {
|
||||
claim: string;
|
||||
share: string;
|
||||
note: string;
|
||||
owner: string;
|
||||
};
|
||||
|
||||
function readSessionValue<T>(key: string): T | null {
|
||||
@@ -201,6 +202,7 @@ function buildWecomOAuthState(params: PortalParams): string {
|
||||
if (params.claim) compact.set("c", params.claim);
|
||||
if (params.share) compact.set("s", params.share);
|
||||
if (params.note) compact.set("n", params.note);
|
||||
if (params.owner) compact.set("o", params.owner);
|
||||
if (compact.toString().length <= WECOM_OAUTH_STATE_LIMIT) {
|
||||
return compact.toString();
|
||||
}
|
||||
@@ -211,6 +213,7 @@ function buildWecomOAuthState(params: PortalParams): string {
|
||||
const fallback = new URLSearchParams();
|
||||
if (params.task) fallback.set("t", params.task);
|
||||
if (params.share) fallback.set("s", params.share);
|
||||
if (params.owner) fallback.set("o", params.owner);
|
||||
return fallback.toString();
|
||||
}
|
||||
|
||||
@@ -225,14 +228,17 @@ function restoreParamsFromWecomState(state: string): PortalParams {
|
||||
} catch {
|
||||
// 忽略清理失败
|
||||
}
|
||||
if (stored?.task || stored?.share) return stored;
|
||||
return { task: "", claim: "", share: "", note: "" };
|
||||
if (stored?.task || stored?.share) {
|
||||
return { ...stored, owner: stored.owner ?? "" };
|
||||
}
|
||||
return { task: "", claim: "", share: "", note: "", owner: "" };
|
||||
}
|
||||
return {
|
||||
task: parsed.get("t") ?? "",
|
||||
claim: parsed.get("c") ?? "",
|
||||
share: parsed.get("s") ?? "",
|
||||
note: parsed.get("n") ?? "",
|
||||
owner: parsed.get("o") ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -434,6 +440,7 @@ export default function Home() {
|
||||
const [claimToken, setClaimToken] = useState("");
|
||||
const [delegationToken, setDelegationToken] = useState("");
|
||||
const [selectedId, setSelectedId] = useState("");
|
||||
const [ownerPartnerId, setOwnerPartnerId] = useState("");
|
||||
const [payload, setPayload] = useState<TaskPayload | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [working, setWorking] = useState(false);
|
||||
@@ -546,7 +553,7 @@ export default function Home() {
|
||||
};
|
||||
if (
|
||||
response.ok &&
|
||||
result.userType === "external" &&
|
||||
(result.userType === "external" || result.userType === "internal") &&
|
||||
result.identityTicket
|
||||
) {
|
||||
const identity: WecomPortalIdentity = {
|
||||
@@ -559,7 +566,11 @@ export default function Home() {
|
||||
writeSessionValue(WECOM_IDENTITY_SESSION_KEY, identity);
|
||||
setWecomIdentity(identity);
|
||||
setManualEntry(false);
|
||||
setToast(`企微身份已确认:${identity.name}`);
|
||||
setToast(
|
||||
result.userType === "internal"
|
||||
? `企业内部身份已确认:${identity.name}`
|
||||
: `企微身份已确认:${identity.name}`,
|
||||
);
|
||||
} else {
|
||||
markSessionFlag(WECOM_AUTH_FAILED_KEY);
|
||||
setToast(
|
||||
@@ -576,6 +587,7 @@ export default function Home() {
|
||||
setClaimToken(restored.claim);
|
||||
setDelegationToken(restored.share);
|
||||
setSelectedId(restored.note);
|
||||
setOwnerPartnerId(restored.owner);
|
||||
if (!restored.task && !restored.share) {
|
||||
setLoading(false);
|
||||
setError("任务链接不完整,请向运营重新获取");
|
||||
@@ -606,10 +618,12 @@ export default function Home() {
|
||||
const claim = params.get("claim") ?? "";
|
||||
const delegation = params.get("share") ?? "";
|
||||
const note = params.get("note") ?? "";
|
||||
const owner = params.get("owner") ?? "";
|
||||
setTaskToken(task);
|
||||
setClaimToken(claim);
|
||||
setDelegationToken(delegation);
|
||||
setSelectedId(note);
|
||||
setOwnerPartnerId(owner);
|
||||
if (!task && !delegation) {
|
||||
setLoading(false);
|
||||
setError("任务链接不完整,请向运营重新获取");
|
||||
@@ -628,6 +642,7 @@ export default function Home() {
|
||||
claim,
|
||||
share: delegation,
|
||||
note,
|
||||
owner,
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -682,6 +697,7 @@ export default function Home() {
|
||||
...(wecomIdentity && !manualEntry
|
||||
? { identityTicket: wecomIdentity.ticket }
|
||||
: {}),
|
||||
...(ownerPartnerId ? { owner: ownerPartnerId } : {}),
|
||||
quantity,
|
||||
}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user