feat: 负责人下钻视图+项目负责人编辑管理+企微授权自助绑定
- 任务/项目负责人 union scope:任务中心分组视图、工作台项目进度卡、收录验证列 - 项目负责人可管理自己项目:编辑/删除项目、编辑任务、分配负责人、推送、项目内建任务;堵死转移归属/越权新建/任务迁移 - 只读依赖放开给已登录:inspect_feishu、wecom_list_internal_contacts - 企微 OAuth 自助绑定:/api/wecom-bind(state 签名校验+登录态一致性+归属冲突检查),未绑定 banner 增加入口 - 工作台项目进度卡与未绑定 banner 排版修复 - 修 user-auth 判空分支被 Turbopack dev 折叠删除导致匿名请求 500
This commit is contained in:
@@ -27,10 +27,23 @@ type DueSoonRow = {
|
||||
wecom_external_user_id: string | null;
|
||||
task_id: string;
|
||||
task_name: string;
|
||||
task_type: string;
|
||||
due_at: string;
|
||||
content_title: string;
|
||||
};
|
||||
|
||||
function pendingActionLabel(taskType: string) {
|
||||
return taskType === "screenshot_collect" ? "截图待提交" : "待发布";
|
||||
}
|
||||
|
||||
function pendingSummary(rows: DueSoonRow[]) {
|
||||
const shot = rows.filter((row) => row.task_type === "screenshot_collect").length;
|
||||
const publish = rows.length - shot;
|
||||
if (shot === 0) return `${rows.length} 条笔记待发布`;
|
||||
if (publish === 0) return `${rows.length} 份截图待提交`;
|
||||
return `${publish} 条笔记待发布、${shot} 份截图待提交`;
|
||||
}
|
||||
|
||||
export function computeDueCutoff(today: string, dueDays: number) {
|
||||
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(today);
|
||||
if (!match) return today;
|
||||
@@ -60,6 +73,7 @@ export async function runDueSoonWecomNotifications(
|
||||
p.wecom_external_user_id,
|
||||
t.id AS task_id,
|
||||
t.name AS task_name,
|
||||
t.task_type,
|
||||
t.due_at,
|
||||
c.title AS content_title
|
||||
FROM distributions d
|
||||
@@ -115,13 +129,13 @@ export async function runDueSoonWecomNotifications(
|
||||
? [entry.externalUserId]
|
||||
: [];
|
||||
const lines = entry.rows.slice(0, 5).map((row) => {
|
||||
return `· 《${truncate(row.task_name, 24)}》— ${truncate(row.content_title, 24)}(截止 ${row.due_at})`;
|
||||
return `· 《${truncate(row.task_name, 24)}》— ${truncate(row.content_title, 24)}(${pendingActionLabel(row.task_type)},截止 ${row.due_at})`;
|
||||
});
|
||||
const overflow =
|
||||
entry.rows.length > 5 ? `\n…还有 ${entry.rows.length - 5} 条` : "";
|
||||
const link = portalUrl ? `\n领取链接:${portalUrl}` : "";
|
||||
const content =
|
||||
`${entry.partnerName},你有 ${entry.rows.length} 条内容待发布:\n${lines.join("\n")}${overflow}${link}`;
|
||||
`${entry.partnerName},你有 ${pendingSummary(entry.rows)}:\n${lines.join("\n")}${overflow}${link}`;
|
||||
const appResult = await sendWecomAppMessage(
|
||||
external,
|
||||
content,
|
||||
@@ -166,7 +180,7 @@ export async function runDueSoonWecomNotifications(
|
||||
await sendTaskChatMessage(
|
||||
db,
|
||||
groupTaskId,
|
||||
`【催办】《${truncate(entry.taskName, 24)}》有 ${entry.rows.length} 条内容待发布(截止 ${entry.dueAt}):\n${partners.slice(0, 5).join("、")}${overflow}`,
|
||||
`【催办】《${truncate(entry.taskName, 24)}》有 ${pendingSummary(entry.rows)}(截止 ${entry.dueAt}):\n${partners.slice(0, 5).join("、")}${overflow}`,
|
||||
config,
|
||||
fetchImpl,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user