feat: 在账号资源库中展示导入的标签字段
KOC 资源导入模板新增「标签」列,导入后写入 accounts.tags 并在 账号资源库面板以 badge 形式展示,导出时也带回标签列以保证往返一致。 - lib/resource-import.ts: 新增 tags 字段与 HEADER 别名(标签/账号标签/人设标签), 新增 normalizeTags/mergeTags 工具,按顿号规整与合并 - 修复 xlsx 解析器对自闭合空 cell (<c r="G6"/>) 的错位 bug,否则 行内出现空 cell 会让后续 cell 的列引用读到错误 body(如老茄子行标签丢失) - db/schema.ts + lib/mvp-db.ts: accounts 表新增 tags VARCHAR(500) - app/api/resources-import/route.ts: SELECT/INSERT/UPDATE/预览全部带上 tags - app/api/resources-export/route.ts: 导出表加「标签」列 - app/admin-app.tsx + app/globals.css: 资源卡片新增「账号标签」区, 导入预览行展示标签 - public/KOC资源导入模板.xlsx: 模板补「标签(选填)」列与填写说明 - mysql/0005_account_tags.sql: 线上 MySQL 迁移 - tests/resource-import.test.mjs: 补 tags 解析/合并用例
This commit is contained in:
@@ -15,6 +15,7 @@ export function getUploadBucket() {
|
||||
|
||||
export async function ensureSchema(database?: DatabaseClient) {
|
||||
const db = database ?? getRawDb();
|
||||
await ensurePartnersWecomColumn(db);
|
||||
{
|
||||
await db.prepare("SELECT id FROM tasks LIMIT 1").all();
|
||||
|
||||
@@ -81,6 +82,7 @@ export async function ensureSchema(database?: DatabaseClient) {
|
||||
name TEXT NOT NULL,
|
||||
wecom_name TEXT NOT NULL,
|
||||
owner TEXT NOT NULL DEFAULT '运营组',
|
||||
wecom_external_user_id TEXT,
|
||||
claimed_total INTEGER NOT NULL DEFAULT 0,
|
||||
completed_total INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
@@ -127,6 +129,7 @@ export async function ensureSchema(database?: DatabaseClient) {
|
||||
post_count INTEGER NOT NULL DEFAULT 0,
|
||||
avg_views INTEGER NOT NULL DEFAULT 0,
|
||||
cooperation_source TEXT NOT NULL DEFAULT '',
|
||||
tags TEXT NOT NULL DEFAULT '',
|
||||
first_seen_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
last_seen_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)`,
|
||||
@@ -293,6 +296,7 @@ export async function ensureSchema(database?: DatabaseClient) {
|
||||
"public_account_id",
|
||||
"public_account_id TEXT NOT NULL DEFAULT ''",
|
||||
);
|
||||
await ensureColumn("accounts", "tags", "tags TEXT NOT NULL DEFAULT ''");
|
||||
await ensureColumn("distributions", "claim_id", "claim_id TEXT");
|
||||
await ensureColumn(
|
||||
"distributions",
|
||||
@@ -832,6 +836,32 @@ export function uid(prefix: string) {
|
||||
return `${prefix}-${crypto.randomUUID().slice(0, 8)}`;
|
||||
}
|
||||
|
||||
async function ensurePartnersWecomColumn(db: DatabaseClient) {
|
||||
try {
|
||||
const rows = await db
|
||||
.prepare(
|
||||
`SELECT COLUMN_NAME
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'partners'
|
||||
AND COLUMN_NAME = 'wecom_external_user_id'`,
|
||||
)
|
||||
.all<{ COLUMN_NAME: string }>();
|
||||
if (rows.results.length === 0) {
|
||||
await db
|
||||
.prepare(
|
||||
"ALTER TABLE partners ADD COLUMN wecom_external_user_id TEXT",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
"[KOC LOOP] failed to ensure partners.wecom_external_user_id column",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function hashText(value: string) {
|
||||
let hash = 2166136261;
|
||||
for (let index = 0; index < value.length; index += 1) {
|
||||
|
||||
Reference in New Issue
Block a user