diff --git a/admin/src/pages/ai/concierge/index.tsx b/admin/src/pages/ai/concierge/index.tsx index d25d2fb..dc25ebb 100644 --- a/admin/src/pages/ai/concierge/index.tsx +++ b/admin/src/pages/ai/concierge/index.tsx @@ -13,7 +13,6 @@ import { Spin, Grid, Tag, - Divider, } from '@arco-design/web-react'; import axios from 'axios'; import useLocale from '@/utils/useLocale'; @@ -240,29 +239,10 @@ export default function AiConciergePage(): JSX.Element { isEnabled: d.isEnabled !== false, }); } else { - const fallback = PRESET_DATA.trade_expert; - form.setFieldsValue({ - cardId, - personaType: 'trade_expert', - welcomeMsg: fallback.welcomeMsg, - triggerLeadThreshold: fallback.triggerLeadThreshold, - promptTemplate: fallback.promptTemplate, - toneStyle: fallback.toneStyle, - isEnabled: true, - }); + Message.error(res.data?.message || t['aiConcierge.request.fail']); } } catch { Message.error(t['aiConcierge.request.fail']); - const fallback = PRESET_DATA.trade_expert; - form.setFieldsValue({ - cardId, - personaType: 'trade_expert', - welcomeMsg: fallback.welcomeMsg, - triggerLeadThreshold: fallback.triggerLeadThreshold, - promptTemplate: fallback.promptTemplate, - toneStyle: fallback.toneStyle, - isEnabled: true, - }); } finally { setLoading(false); } @@ -280,6 +260,7 @@ export default function AiConciergePage(): JSX.Element { }; const handlePersonaChange = (type: ConciergePersonaType): void => { + // 仅填充表单预览,不提示成功;真正落库须走保存接口 if (type !== 'custom') { const preset = PRESET_DATA[type]; form.setFieldsValue({ @@ -311,7 +292,7 @@ export default function AiConciergePage(): JSX.Element { SAVE_CONFIG_API, payload ); - if (res.data && res.data.code === 1000) { + if (res.data && res.data.code === 1000 && res.data.data) { Message.success(t['aiConcierge.request.success']); } else { Message.error(res.data?.message || t['aiConcierge.request.saveFail']); @@ -323,6 +304,10 @@ export default function AiConciergePage(): JSX.Element { } }; + const handleFaqUnavailable = (): void => { + Message.error(t['aiConcierge.faq.unavailable']); + }; + const sliderMarks = { 0: '0', 50: '50', @@ -497,6 +482,43 @@ export default function AiConciergePage(): JSX.Element { + +
+ {t['aiConcierge.faq.desc']} +
+
+ {t['aiConcierge.faq.unavailable']} +
+ +
+ - {/* Token 用量与配额仪表盘 */} - + {/* Token 用量:进程内内存计数,非出账金额 */} + + @@ -171,21 +197,21 @@ export default function DeepSeekConsolePage(): React.ReactElement { @@ -195,15 +221,21 @@ export default function DeepSeekConsolePage(): React.ReactElement {
- {t['ai.deepseek.stats.quotaProgress']} ({usage.totalTokens} / {usage.quota}) + {t['ai.deepseek.stats.quotaProgress']} ({usage.totalTokens ?? 0} / {usage.quota}) - {usage.percent}% + {usage.percent ?? 0}%
= 90 ? 'error' : usage.percent >= 70 ? 'warning' : 'normal'} + percent={usage.percent ?? 0} + status={ + (usage.percent ?? 0) >= 90 + ? 'error' + : (usage.percent ?? 0) >= 70 + ? 'warning' + : 'normal' + } />
) : ( @@ -216,7 +248,11 @@ export default function DeepSeekConsolePage(): React.ReactElement {
{/* 模型配置与 BYOK 表单 */} - +
{ }); } -function calculatePercent(score?: number): number { - if (score === undefined || Number.isNaN(score) || score <= 0) { - return 0; - } - if (score >= 1) { - return 100; - } - return Math.round(score * 100); -} - function AiKnowledgePage() { const t = useLocale(locale) as Record; const requestFailText = t['aiKnowledge.request.fail']; @@ -611,6 +601,25 @@ function AiKnowledgePage() { > + + + + + + + + {t['aiKnowledge.crawl.unavailable']} + + + {t['aiKnowledge.sandbox.recalled']} - {totalChunksCount !== undefined ? ( + - {t['aiKnowledge.sandbox.totalChunks']}: {totalChunksCount} + {t['aiKnowledge.sandbox.recallCount']}: {recallResults.length} - ) : null} + {totalChunksCount !== undefined ? ( + + {t['aiKnowledge.sandbox.totalChunks']}: {totalChunksCount} + + ) : null} + {recallResults.length === 0 ? ( @@ -788,13 +802,6 @@ function AiKnowledgePage() { } > -
- -
{ + if (!file || file.size === 0) { + Message.error(t['aiTranslation.request.importFail']); + return false; + } void readJsonFile(file) .then(async (parsed) => { - if (!Array.isArray(parsed)) { + if (!Array.isArray(parsed) || parsed.length === 0) { Message.error(t['aiTranslation.request.importFail']); return; } diff --git a/admin/src/pages/card/articles/index.tsx b/admin/src/pages/card/articles/index.tsx index 8d672d6..9bdbfde 100644 --- a/admin/src/pages/card/articles/index.tsx +++ b/admin/src/pages/card/articles/index.tsx @@ -513,18 +513,22 @@ export default function CardArticlesPage() { field="cardId" rules={[{ required: true }]} > - +
- + @@ -618,12 +622,12 @@ export default function CardArticlesPage() { {ogPreview.image ? ( OpenGraph Cover ) : ( - OG Image + {t['cardArticles.ogPreview.emptyImage']} )} diff --git a/admin/src/pages/card/articles/locale/index.ts b/admin/src/pages/card/articles/locale/index.ts index eaff531..1f5f522 100644 --- a/admin/src/pages/card/articles/locale/index.ts +++ b/admin/src/pages/card/articles/locale/index.ts @@ -25,6 +25,11 @@ const i18n = { 'cardArticles.filter.cardId': 'Filter by Card ID', 'cardArticles.filter.status': 'Publish Status', 'cardArticles.filter.all': 'All Statuses', + 'cardArticles.form.cardId.placeholder': '101', + 'cardArticles.form.title.placeholder': 'Enter an in-depth article title...', + 'cardArticles.form.summary.placeholder': + 'Article summary (leave blank to auto-extract the first 160 characters from the body after stripping HTML)...', + 'cardArticles.form.content.placeholder': 'Body content (HTML or Markdown supported)...', 'cardArticles.drawer.createTitle': 'New Article / Post', 'cardArticles.drawer.editTitle': 'Edit Article / Post', 'cardArticles.ogPreview.title': 'OpenGraph Social Card Preview', @@ -32,6 +37,7 @@ const i18n = { 'cardArticles.ogPreview.landscape': 'Landscape (1.91:1)', 'cardArticles.ogPreview.square': 'Square (1:1)', 'cardArticles.ogPreview.domain': 'omnicard.ai', + 'cardArticles.ogPreview.emptyImage': 'No cover image', 'cardArticles.ogPreview.emptyTitle': 'Post Title Preview', 'cardArticles.ogPreview.emptyDesc': 'Summary or first 160 characters will automatically appear here as description...', 'cardArticles.message.saveSuccess': 'Article saved successfully', @@ -66,6 +72,11 @@ const i18n = { 'cardArticles.filter.cardId': '按名片编号筛选', 'cardArticles.filter.status': '发布状态', 'cardArticles.filter.all': '全部状态', + 'cardArticles.form.cardId.placeholder': '101', + 'cardArticles.form.title.placeholder': '输入深度文章标题...', + 'cardArticles.form.summary.placeholder': + '文章摘要(留空将自动从正文剥离 HTML 提取前 160 字符)...', + 'cardArticles.form.content.placeholder': '正文内容(支持 HTML 或 Markdown 格式)...', 'cardArticles.drawer.createTitle': '新建文章与动态', 'cardArticles.drawer.editTitle': '编辑文章与动态', 'cardArticles.ogPreview.title': 'OpenGraph 社交卡片实时预览', @@ -73,13 +84,64 @@ const i18n = { 'cardArticles.ogPreview.landscape': '横版 (1.91:1)', 'cardArticles.ogPreview.square': '方版 (1:1)', 'cardArticles.ogPreview.domain': 'omnicard.ai', + 'cardArticles.ogPreview.emptyImage': '暂无封面图', 'cardArticles.ogPreview.emptyTitle': '文章标题预览', 'cardArticles.ogPreview.emptyDesc': '摘要或正文前 160 字符将自动提炼为社交分享描述...', 'cardArticles.message.saveSuccess': '文章保存成功', 'cardArticles.message.deleteSuccess': '文章已成功删除', 'cardArticles.message.statusSuccess': '发布状态更新成功', 'cardArticles.message.requestFail': '请求失败,请稍后重试', - 'cardArticles.empty.text': '暂无文章或动态,点击上方主按钮即可开始创建。', + 'cardArticles.empty.text': '暂无文章或动态,点击上方主按钮即可开始创作。', + }, + 'ar-SA': { + 'menu.card.articles': 'المقالات والتحديثات', + 'cardArticles.title': 'مركز المقالات والتحديثات', + 'cardArticles.description': + 'انشر مقالات المدونة والتحديثات على بوابة بطاقتك الرقمية مع استخراج OpenGraph وتحسين محركات البحث تلقائيًا.', + 'cardArticles.action.add': 'إنشاء مقال', + 'cardArticles.action.edit': 'تعديل', + 'cardArticles.action.delete': 'حذف', + 'cardArticles.action.deleteConfirm': 'هل أنت متأكد من حذف هذا المقال؟', + 'cardArticles.action.refresh': 'تحديث', + 'cardArticles.action.saveDraft': 'حفظ المسودة', + 'cardArticles.action.publish': 'نشر الآن', + 'cardArticles.status.published': 'منشور', + 'cardArticles.status.draft': 'مسودة', + 'cardArticles.field.id': 'المعرّف', + 'cardArticles.field.cardId': 'معرّف البطاقة', + 'cardArticles.field.title': 'العنوان', + 'cardArticles.field.summary': 'الملخص', + 'cardArticles.field.content': 'المحتوى', + 'cardArticles.field.coverImage': 'رابط صورة الغلاف', + 'cardArticles.field.status': 'الحالة', + 'cardArticles.field.updateTime': 'آخر تحديث', + 'cardArticles.field.operations': 'إجراءات', + 'cardArticles.filter.search': 'البحث بالعنوان أو الملخص', + 'cardArticles.filter.cardId': 'التصفية حسب معرّف البطاقة', + 'cardArticles.filter.status': 'حالة النشر', + 'cardArticles.filter.all': 'كل الحالات', + 'cardArticles.form.cardId.placeholder': '101', + 'cardArticles.form.title.placeholder': 'أدخل عنوان المقال المتعمق...', + 'cardArticles.form.summary.placeholder': + 'ملخص المقال (اتركه فارغًا لاستخراج أول 160 حرفًا تلقائيًا من النص بعد إزالة HTML)...', + 'cardArticles.form.content.placeholder': 'محتوى النص (يدعم HTML أو Markdown)...', + 'cardArticles.drawer.createTitle': 'مقال / منشور جديد', + 'cardArticles.drawer.editTitle': 'تعديل المقال / المنشور', + 'cardArticles.ogPreview.title': 'معاينة بطاقة OpenGraph الاجتماعية', + 'cardArticles.ogPreview.desc': + 'هكذا يظهر منشورك عند مشاركته عبر LinkedIn وWhatsApp وX وWeChat.', + 'cardArticles.ogPreview.landscape': 'أفقي (1.91:1)', + 'cardArticles.ogPreview.square': 'مربع (1:1)', + 'cardArticles.ogPreview.domain': 'omnicard.ai', + 'cardArticles.ogPreview.emptyImage': 'لا توجد صورة غلاف', + 'cardArticles.ogPreview.emptyTitle': 'معاينة عنوان المنشور', + 'cardArticles.ogPreview.emptyDesc': + 'سيظهر الملخص أو أول 160 حرفًا تلقائيًا هنا كوصف للمشاركة...', + 'cardArticles.message.saveSuccess': 'تم حفظ المقال بنجاح', + 'cardArticles.message.deleteSuccess': 'تم حذف المقال بنجاح', + 'cardArticles.message.statusSuccess': 'تم تحديث الحالة بنجاح', + 'cardArticles.message.requestFail': 'فشلت العملية، يرجى المحاولة مرة أخرى', + 'cardArticles.empty.text': 'لا توجد مقالات. انقر الزر أعلاه لنشر أول منشور.', }, }; diff --git a/admin/src/pages/card/builder/index.tsx b/admin/src/pages/card/builder/index.tsx index fce75b4..aefeb2f 100644 --- a/admin/src/pages/card/builder/index.tsx +++ b/admin/src/pages/card/builder/index.tsx @@ -16,6 +16,7 @@ import { Space, Tag, Divider, + Switch, } from '@arco-design/web-react'; import { IconSun, @@ -643,15 +644,6 @@ function CardBuilderPage() { - setIsRtl(val === 'rtl')} - > - {t['cardBuilder.dir.ltr']} - {t['cardBuilder.dir.rtl']} - - {currentCard?.slug && (