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:
@@ -6,6 +6,7 @@ import {
|
||||
sendWecomTemplateCard,
|
||||
type WecomConfig,
|
||||
} from "./wecom-client";
|
||||
import { sendTaskChatMessage } from "./task-group-service";
|
||||
import { getRuntimeEnv } from "./runtime-env";
|
||||
import { releaseUnfinishedDistribution } from "./distribution-release-service";
|
||||
|
||||
@@ -24,6 +25,7 @@ type DueSoonRow = {
|
||||
partner_id: string;
|
||||
partner_name: string;
|
||||
wecom_external_user_id: string | null;
|
||||
task_id: string;
|
||||
task_name: string;
|
||||
due_at: string;
|
||||
content_title: string;
|
||||
@@ -56,6 +58,7 @@ export async function runDueSoonWecomNotifications(
|
||||
d.partner_id,
|
||||
p.name AS partner_name,
|
||||
p.wecom_external_user_id,
|
||||
t.id AS task_id,
|
||||
t.name AS task_name,
|
||||
t.due_at,
|
||||
c.title AS content_title
|
||||
@@ -140,6 +143,31 @@ export async function runDueSoonWecomNotifications(
|
||||
);
|
||||
}
|
||||
|
||||
const byTask = new Map<
|
||||
string,
|
||||
{ taskName: string; dueAt: string; rows: DueSoonRow[] }
|
||||
>();
|
||||
for (const row of result.results) {
|
||||
const entry = byTask.get(row.task_id) ?? {
|
||||
taskName: row.task_name,
|
||||
dueAt: row.due_at,
|
||||
rows: [],
|
||||
};
|
||||
entry.rows.push(row);
|
||||
byTask.set(row.task_id, entry);
|
||||
}
|
||||
for (const [taskId, entry] of byTask) {
|
||||
const partners = [...new Set(entry.rows.map((row) => row.partner_name))];
|
||||
const overflow = partners.length > 5 ? ` 等 ${partners.length} 位` : "";
|
||||
await sendTaskChatMessage(
|
||||
db,
|
||||
taskId,
|
||||
`【催办】《${truncate(entry.taskName, 24)}》有 ${entry.rows.length} 条内容待发布(截止 ${entry.dueAt}):\n${partners.slice(0, 5).join("、")}${overflow}`,
|
||||
config,
|
||||
fetchImpl,
|
||||
);
|
||||
}
|
||||
|
||||
let digestSent = false;
|
||||
if (config.robotWebhook && digestTasks.length > 0) {
|
||||
const digest =
|
||||
@@ -276,6 +304,13 @@ export async function runOverdueEscalation(
|
||||
const env = getRuntimeEnv();
|
||||
const cardUrl = bindingValue(env.APP_ORIGIN) || bindingValue(env.KOC_PORTAL_URL);
|
||||
for (const [taskId, entry] of byTask) {
|
||||
await sendTaskChatMessage(
|
||||
db,
|
||||
taskId,
|
||||
`【超期催办】《${truncate(entry.taskName, 24)}》(截止 ${entry.dueAt})有 ${entry.count} 条内容超期未发布,请跟进催办或释放。`,
|
||||
config,
|
||||
fetchImpl,
|
||||
);
|
||||
if (!entry.projectId) continue;
|
||||
try {
|
||||
const project = await db
|
||||
|
||||
Reference in New Issue
Block a user