feat: 任务发布到企微客户群(企业群发)与资源库单条新增

- 任务中心新增「发布到企微群」:同步客户群清单(wecom_group_chats)、
  按群主分组创建企业群发任务(add_msg_template)、发送记录落库
  wecom_group_pushes,迁移 mysql/0009;lib/wecom-client.ts 补
  listCustomerGroupChats/createGroupMsgTemplate
- KOC 资源库支持单条新增:app/api/resources-insert + lib/resource-write,
  拆出资源写入公共逻辑供导入复用;0008 补合作方外部联系人字段
- 环境变量示例补企微凭证与 SEED_DEMO_DATA;next.config 增加
  allowedDevOrigins;CLAUDE.md 补充项目说明
- .gitignore 排除 .codegraph/ 与 .ipynb_checkpoints/
This commit is contained in:
ABAPPLO
2026-08-20 15:16:18 +08:00
parent 8f7ea0558d
commit 9697b5890d
22 changed files with 3695 additions and 449 deletions

View File

@@ -21,6 +21,7 @@ export const partners = mysqlTable("partners", {
owner: varchar("owner", { length: 255 }).notNull().default("运营组"),
claimedTotal: int("claimed_total").notNull().default(0),
completedTotal: int("completed_total").notNull().default(0),
wecomExternalUserId: varchar("wecom_external_user_id", { length: 128 }),
createdAt: timestamp("created_at"),
});
@@ -252,6 +253,35 @@ export const mcpExportTokens = mysqlTable(
(table) => [index("mcp_export_tokens_expires_at_idx").on(table.expiresAt)],
);
export const wecomGroupChats = mysqlTable(
"wecom_group_chats",
{
chatId: varchar("chat_id", { length: 128 }).primaryKey(),
name: varchar("name", { length: 512 }).notNull().default(""),
ownerUserId: varchar("owner_user_id", { length: 128 }).notNull(),
memberCount: int("member_count").notNull().default(0),
status: int("status").notNull().default(0),
syncedAt: timestamp("synced_at"),
},
(table) => [index("wecom_group_chats_owner_idx").on(table.ownerUserId)],
);
export const wecomGroupPushes = mysqlTable(
"wecom_group_pushes",
{
id: varchar("id", { length: 64 }).primaryKey(),
taskId: varchar("task_id", { length: 64 }).notNull(),
msgid: varchar("msgid", { length: 128 }).notNull().default(""),
sender: varchar("sender", { length: 128 }).notNull(),
chatIds: text("chat_ids").notNull(),
textContent: text("text_content").notNull(),
linkUrl: text("link_url").notNull(),
failList: text("fail_list").notNull(),
createdAt: timestamp("created_at"),
},
(table) => [index("wecom_group_pushes_task_idx").on(table.taskId)],
);
export const backgroundJobs = mysqlTable(
"background_jobs",
{