feat: 添加基于 Workers AI 的 Slug 自动生成 API 服务
This commit is contained in:
1 parent
4eff4de734
commit
c3858c92ba
3 files changed
+90
-7
No files matched your search
@@ -0,0 +1,81 @@
|
|||||||
|
import { json } from '@sveltejs/kit';
|
||||||
|
import type { RequestHandler } from './$types';
|
||||||
|
|
||||||
|
// 将英文文本转换为规范的 kebab-case Slug
|
||||||
|
function toSlug(str: string): string {
|
||||||
|
return str
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^\w\s-]/g, '')
|
||||||
|
.trim()
|
||||||
|
.replace(/[\s_]+/g, '-')
|
||||||
|
.replace(/-+/g, '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const POST: RequestHandler = async ({ request, platform }) => {
|
||||||
|
try {
|
||||||
|
const body = (await request.json().catch(() => ({}))) as Record<string, unknown>;
|
||||||
|
const text = typeof body?.text === 'string' ? body.text.trim() : '';
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return json({ slug: '' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 若输入的文本已经是纯英文/数字(只包含 ASCII 字符、空格或连字符)
|
||||||
|
if (/^[a-zA-Z0-9\s-_]+$/.test(text)) {
|
||||||
|
return json({ slug: toSlug(text) });
|
||||||
|
}
|
||||||
|
|
||||||
|
let translatedText = '';
|
||||||
|
|
||||||
|
// 优先调用 Cloudflare Workers AI (@cf/meta/m2m100_418m 翻译模型)
|
||||||
|
if (platform?.env?.AI) {
|
||||||
|
try {
|
||||||
|
const res = (await platform.env.AI.run('@cf/meta/m2m100_418m', {
|
||||||
|
text,
|
||||||
|
target_lang: 'english'
|
||||||
|
})) as { translated_text?: string };
|
||||||
|
|
||||||
|
if (res?.translated_text) {
|
||||||
|
translatedText = res.translated_text;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Workers AI 翻译异常,启动安全降级:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 降级策略:如果 Workers AI 未绑定或在线环境缺失,尝试轻量免费 API 作为备用
|
||||||
|
if (!translatedText) {
|
||||||
|
try {
|
||||||
|
const fallbackUrl = `https://api.mymemory.translated.net/get?q=${encodeURIComponent(text)}&langpair=zh-CN|en`;
|
||||||
|
const res = await fetch(fallbackUrl);
|
||||||
|
if (res.ok) {
|
||||||
|
const data = (await res.json()) as { responseData?: { translatedText?: string } };
|
||||||
|
if (data?.responseData?.translatedText) {
|
||||||
|
translatedText = data.responseData.translatedText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('降级翻译服务调用失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果得到了英文翻译,格式化为 kebab-case Slug
|
||||||
|
if (translatedText) {
|
||||||
|
const formattedSlug = toSlug(translatedText);
|
||||||
|
if (formattedSlug) {
|
||||||
|
return json({ slug: formattedSlug });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最底层的安全兜底:若没有任何英文结果返回,生成基于拼音/基本替换的 slug
|
||||||
|
const fallbackSlug = text
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.replace(/[^\w-]/g, '');
|
||||||
|
|
||||||
|
return json({ slug: fallbackSlug || 'post' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Slug生成接口未知错误:', error);
|
||||||
|
return json({ slug: '' }, { status: 500 });
|
||||||
|
}
|
||||||
|
};
|
||||||
Vendored
+5
-6
@@ -1,11 +1,12 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
// Generated by Wrangler by running `wrangler types` (hash: 8e316e5cc1c036c1cc1ec926e6667c6d)
|
// Generated by Wrangler by running `wrangler types` (hash: 9194822214de3b6a9d6a85fa866a429b)
|
||||||
// Runtime types generated with workerd@1.20260801.1 2026-08-07 nodejs_compat
|
// Runtime types generated with workerd@1.20260801.1 2026-08-07 nodejs_compat
|
||||||
interface __BaseEnv_Env {
|
interface __BaseEnv_Env {
|
||||||
R2: R2Bucket;
|
R2: R2Bucket;
|
||||||
DB: D1Database;
|
DB: D1Database;
|
||||||
CF_ACCESS_TEAM_DOMAIN: 'https://hisland.cloudflareaccess.com';
|
AI: Ai;
|
||||||
CF_ACCESS_AUD: '35b84a1c6ea81e1c036272ee68ecc4197041aadc1bed0815accac283a30e01ff';
|
CF_ACCESS_TEAM_DOMAIN: "https://hisland.cloudflareaccess.com";
|
||||||
|
CF_ACCESS_AUD: "35b84a1c6ea81e1c036272ee68ecc4197041aadc1bed0815accac283a30e01ff";
|
||||||
}
|
}
|
||||||
declare namespace Cloudflare {
|
declare namespace Cloudflare {
|
||||||
interface Env extends __BaseEnv_Env {}
|
interface Env extends __BaseEnv_Env {}
|
||||||
@@ -15,9 +16,7 @@ type StringifyValues<EnvType extends Record<string, unknown>> = {
|
|||||||
[Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
|
[Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
|
||||||
};
|
};
|
||||||
declare namespace NodeJS {
|
declare namespace NodeJS {
|
||||||
interface ProcessEnv extends StringifyValues<
|
interface ProcessEnv extends StringifyValues<Pick<Cloudflare.Env, "CF_ACCESS_TEAM_DOMAIN" | "CF_ACCESS_AUD">> {}
|
||||||
Pick<Cloudflare.Env, 'CF_ACCESS_TEAM_DOMAIN' | 'CF_ACCESS_AUD'>
|
|
||||||
> {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin runtime types
|
// Begin runtime types
|
||||||
|
|||||||
+4
-1
@@ -21,5 +21,8 @@
|
|||||||
"binding": "R2",
|
"binding": "R2",
|
||||||
"bucket_name": "blogflare-assets"
|
"bucket_name": "blogflare-assets"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"ai": {
|
||||||
|
"binding": "AI"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user