From 62e0ae4435f1cb9bc7b08b6b28d97cb94cf76062 Mon Sep 17 00:00:00 2001 From: wikiboss Date: Wed, 23 Sep 2026 18:01:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=8C=E6=AD=A5=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=AB=AF=E3=80=81=E7=94=A8=E6=88=B7=E7=AB=AF=E4=B8=8E=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E4=B8=9A=E5=8A=A1=EF=BC=8C=E5=B9=B6=E6=8E=A5=E9=80=9A?= =?UTF-8?q?=E7=BA=BF=E4=B8=8A=20Web=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。 Co-authored-by: Cursor --- admin/src/pages/ai/concierge/index.tsx | 66 +- admin/src/pages/ai/concierge/locale/index.ts | 15 + admin/src/pages/ai/deepseek/index.tsx | 60 +- admin/src/pages/ai/deepseek/locale/index.ts | 36 +- admin/src/pages/ai/knowledge/index.tsx | 49 +- admin/src/pages/ai/knowledge/locale/index.ts | 39 +- admin/src/pages/ai/translation/index.tsx | 6 +- admin/src/pages/card/articles/index.tsx | 16 +- admin/src/pages/card/articles/locale/index.ts | 64 +- admin/src/pages/card/builder/index.tsx | 19 +- admin/src/pages/card/builder/locale/index.ts | 3 + admin/src/pages/card/cases/index.tsx | 76 +- admin/src/pages/card/cases/locale/index.ts | 34 +- admin/src/pages/card/list/locale/index.ts | 27 + admin/src/pages/crm/lead-profile/index.tsx | 225 ++- .../pages/crm/lead-profile/locale/index.ts | 21 + admin/src/pages/crm/leads/index.tsx | 91 + admin/src/pages/crm/leads/locale/index.ts | 12 + admin/src/pages/crm/pipeline/index.tsx | 122 +- admin/src/pages/crm/pipeline/locale/index.ts | 9 + admin/src/pages/crm/radar-log/index.tsx | 40 + admin/src/pages/crm/radar-log/locale/index.ts | 3 + admin/src/pages/dashboard/financial/index.tsx | 154 +- .../pages/dashboard/financial/locale/index.ts | 39 + admin/src/pages/dashboard/radar-map/index.tsx | 76 +- .../pages/dashboard/radar-map/locale/index.ts | 4 + admin/src/pages/dashboard/workplace/index.tsx | 177 +- .../pages/dashboard/workplace/locale/index.ts | 27 +- admin/src/pages/nfc/batch/index.tsx | 12 + admin/src/pages/nfc/batch/locale/index.ts | 6 + admin/src/pages/nfc/devices/index.tsx | 8 +- admin/src/pages/nfc/devices/locale/index.ts | 3 + admin/src/pages/nfc/rules/index.tsx | 19 +- admin/src/pages/nfc/rules/locale/index.ts | 67 + admin/src/pages/platform/renewals/index.tsx | 464 ++--- .../pages/platform/renewals/locale/index.ts | 151 ++ .../src/pages/platform/subscribers/index.tsx | 66 +- .../platform/subscribers/locale/index.ts | 37 + .../pages/platform/subscriptions/index.tsx | 224 ++- .../platform/subscriptions/locale/index.ts | 136 ++ admin/src/pages/settings/audit-logs/index.tsx | 42 +- .../pages/settings/audit-logs/locale/index.ts | 9 + admin/src/pages/settings/billing/index.tsx | 79 + .../pages/settings/billing/locale/index.ts | 16 + admin/src/pages/settings/tenant/index.tsx | 167 +- .../src/pages/settings/tenant/locale/index.ts | 27 + admin/src/pages/team/brand-kit/index.tsx | 35 + .../src/pages/team/brand-kit/locale/index.ts | 16 + admin/src/pages/team/handover/index.tsx | 133 +- admin/src/pages/team/handover/locale/index.ts | 42 +- admin/src/pages/team/members/index.tsx | 23 +- admin/src/pages/team/members/locale/index.ts | 4 + admin/tests/ai-concierge.test.ts | 127 +- admin/tests/ai-deepseek.test.ts | 177 +- admin/tests/ai-knowledge.test.ts | 147 +- admin/tests/ai-translation.test.ts | 139 ++ admin/tests/card-articles.test.ts | 89 + admin/tests/card-builder.test.ts | 101 + admin/tests/card-cases.test.ts | 89 + admin/tests/crm-lead-profile.test.ts | 167 +- admin/tests/crm-leads.test.ts | 56 + admin/tests/crm-pipeline.test.ts | 109 ++ admin/tests/crm-radar-log.test.ts | 94 + admin/tests/dashboard-financial.test.ts | 86 + admin/tests/dashboard-radar-map.test.ts | 70 +- admin/tests/dashboard-workplace.test.ts | 58 + admin/tests/nfc-batch.test.ts | 73 + admin/tests/nfc-devices.test.ts | 47 + admin/tests/nfc-rules.test.ts | 113 ++ admin/tests/platform-management.test.ts | 81 +- .../platform-subscribers-actions.test.ts | 145 ++ admin/tests/platform-subscriptions.test.ts | 205 ++ admin/tests/settings-audit-logs.test.ts | 86 + admin/tests/settings-billing.test.ts | 182 +- admin/tests/settings-tenant.test.ts | 127 +- admin/tests/team-brand-kit.test.ts | 128 ++ admin/tests/team-handover.test.ts | 47 + admin/tests/team-members.test.ts | 101 + backend/package.json | 4 +- backend/src/comm/geoip/lookup.ts | 192 +- backend/src/config/config.prod.ts | 12 +- backend/src/entities.ts | 88 +- backend/src/modules/ai/controller/open/ocr.ts | 21 + .../src/modules/ai/entity/deepseek-config.ts | 45 + backend/src/modules/ai/service/deepseek.ts | 218 ++- backend/src/modules/ai/service/knowledge.ts | 203 ++ backend/src/modules/ai/service/ocr.ts | 78 + backend/src/modules/base/service/audit.ts | 6 + .../src/modules/card/controller/admin/info.ts | 38 +- .../modules/card/controller/open/portal.ts | 5 + backend/src/modules/card/service/info.ts | 71 +- .../modules/card/service/mutual-exchange.ts | 21 +- .../src/modules/crm/controller/admin/lead.ts | 101 +- backend/src/modules/crm/service/hubspot.ts | 77 + backend/src/modules/crm/service/lead.ts | 71 + backend/src/modules/crm/service/push.ts | 97 +- backend/src/modules/crm/service/radar.ts | 461 ++++- backend/src/modules/crm/service/salesforce.ts | 142 ++ backend/src/modules/crm/service/sync.ts | 229 ++- .../src/modules/nfc/service/anti-tamper.ts | 114 +- backend/src/modules/nfc/service/security.ts | 59 +- .../modules/team/controller/admin/billing.ts | 18 + .../src/modules/team/entity/stripe-event.ts | 25 + backend/src/modules/team/service/domain.ts | 31 +- .../modules/team/service/finance-analytics.ts | 208 +- backend/src/modules/team/service/invoice.ts | 63 + .../team/service/platform-subscription.ts | 431 ++--- backend/src/modules/team/service/quota.ts | 86 +- backend/src/modules/team/service/stripe.ts | 121 +- .../modules/user/controller/app/external.ts | 54 + .../src/modules/user/service/external-auth.ts | 127 ++ backend/test/e2e/omnicard-30-points.test.ts | 36 +- .../modules/ai/admin-deepseek-tenant.test.ts | 19 + backend/test/modules/ai/deepseek.test.ts | 146 +- backend/test/modules/ai/ocr.test.ts | 220 +++ backend/test/modules/ai/sandbox.test.ts | 120 ++ .../modules/card/admin-seed-guard.test.ts | 90 + .../test/modules/card/mutual-exchange.test.ts | 63 + backend/test/modules/card/portal.test.ts | 35 + backend/test/modules/card/seo.test.ts | 116 +- .../modules/card/vcard-export-api.test.ts | 132 ++ backend/test/modules/crm/admin.test.ts | 1 + backend/test/modules/crm/geoip.test.ts | 139 +- backend/test/modules/crm/hubspot.test.ts | 80 + .../modules/crm/lead-external-sync.test.ts | 229 +++ backend/test/modules/crm/lead.test.ts | 82 + backend/test/modules/crm/push.test.ts | 98 + .../modules/crm/radar-aggregation.test.ts | 87 + backend/test/modules/crm/radar-map.test.ts | 5 +- backend/test/modules/crm/radar.test.ts | 146 ++ backend/test/modules/crm/salesforce.test.ts | 141 ++ backend/test/modules/crm/sync.test.ts | 158 +- backend/test/modules/crm/workplace.test.ts | 2 +- backend/test/modules/nfc/anti-tamper.test.ts | 60 +- backend/test/modules/nfc/security.test.ts | 48 +- backend/test/modules/team/domain.test.ts | 29 +- .../modules/team/finance-analytics.test.ts | 167 ++ backend/test/modules/team/invoice.test.ts | 165 ++ .../team/platform-subscription.test.ts | 365 +++- backend/test/modules/team/quota.test.ts | 135 +- backend/test/modules/team/stripe.test.ts | 253 ++- .../test/modules/user/external-auth.test.ts | 170 ++ backend/test/mpuniapp/ai-chat.test.ts | 194 ++ backend/test/mpuniapp/article-detail.test.ts | 238 ++- backend/test/mpuniapp/case-detail.test.ts | 179 +- backend/test/mpuniapp/exchange.test.ts | 130 +- backend/test/mpuniapp/locale.test.ts | 31 + backend/test/mpuniapp/login.test.ts | 395 +++- backend/test/mpuniapp/nfc-mode.test.ts | 83 +- backend/test/mpuniapp/nfc-scan.test.ts | 232 ++- backend/test/mpuniapp/nfc-security.test.ts | 34 + backend/test/mpuniapp/ocr-exchange.test.ts | 81 +- backend/test/mpuniapp/owner-card-edit.test.ts | 525 +++++- backend/test/mpuniapp/owner-card-home.test.ts | 41 + .../test/mpuniapp/owner-card-qrcode.test.ts | 256 +++ backend/test/mpuniapp/owner-hall.test.ts | 67 + .../test/mpuniapp/owner-lead-detail.test.ts | 271 ++- backend/test/mpuniapp/owner-leads.test.ts | 148 +- backend/test/mpuniapp/owner-profile.test.ts | 241 ++- backend/test/mpuniapp/owner-radar.test.ts | 249 +++ backend/test/mpuniapp/owner-stats.test.ts | 186 +- .../test/mpuniapp/owner-team-overview.test.ts | 75 +- backend/test/mpuniapp/portal.test.ts | 229 +++ backend/test/mpuniapp/tabbar-config.test.ts | 2 +- deploy/nginx-a9.xxzlw.com.conf | 48 + mpuniapp/common/locale.uts | 130 +- mpuniapp/common/request.uts | 8 + mpuniapp/common/types.uts | 23 +- .../i18n-selector/i18n-selector.uvue | 18 +- mpuniapp/manifest.json | 386 ++-- mpuniapp/pages.json | 7 +- mpuniapp/pages/common/login.uvue | 39 +- mpuniapp/pages/common/useLogin.uts | 220 ++- mpuniapp/pages/owner/card/articles.uvue | 37 +- mpuniapp/pages/owner/card/cases.uvue | 89 +- mpuniapp/pages/owner/card/edit.uvue | 212 ++- mpuniapp/pages/owner/card/index.uvue | 995 +++++----- mpuniapp/pages/owner/card/qrcode.uvue | 6 +- mpuniapp/pages/owner/card/useCardArticles.uts | 69 +- mpuniapp/pages/owner/card/useCardCases.uts | 76 +- mpuniapp/pages/owner/card/useCardEdit.uts | 409 +++- mpuniapp/pages/owner/card/useCardHome.uts | 51 +- mpuniapp/pages/owner/card/useCardQrcode.uts | 131 +- mpuniapp/pages/owner/leads-detail.uvue | 44 +- mpuniapp/pages/owner/leads.uvue | 5 +- mpuniapp/pages/owner/nfc/mode.uvue | 41 +- mpuniapp/pages/owner/nfc/scan.uvue | 42 +- mpuniapp/pages/owner/nfc/security.uvue | 5 +- mpuniapp/pages/owner/nfc/useMode.uts | 48 +- mpuniapp/pages/owner/nfc/useScan.uts | 262 ++- mpuniapp/pages/owner/nfc/useSecurity.uts | 8 +- mpuniapp/pages/owner/profile/index.uvue | 1676 +++++------------ mpuniapp/pages/owner/profile/useProfile.uts | 169 +- mpuniapp/pages/owner/radar.uvue | 1250 ++++++------ mpuniapp/pages/owner/stats.uvue | 19 +- mpuniapp/pages/owner/team/useOverview.uts | 2 +- mpuniapp/pages/owner/useLeadDetail.uts | 155 +- mpuniapp/pages/owner/useLeads.uts | 11 +- mpuniapp/pages/owner/useRadar.uts | 564 +++++- mpuniapp/pages/owner/useStats.uts | 176 +- mpuniapp/pages/owner/workplace/index.uvue | 1129 ++++++----- .../pages/owner/workplace/useWorkplace.uts | 150 +- mpuniapp/pages/portal/ai-chat.uvue | 35 +- mpuniapp/pages/portal/article-detail.uvue | 37 +- mpuniapp/pages/portal/case-detail.uvue | 83 +- mpuniapp/pages/portal/exchange.uvue | 4 +- mpuniapp/pages/portal/index.uvue | 253 ++- mpuniapp/pages/portal/useArticleDetail.uts | 167 +- mpuniapp/pages/portal/useCaseDetail.uts | 119 +- mpuniapp/pages/portal/useExchange.uts | 26 + mpuniapp/pages/portal/useOcrExchange.uts | 141 +- mpuniapp/pages/portal/usePortal.uts | 126 +- mpuniapp/static/icons/apple.svg | 3 + mpuniapp/static/icons/avatar-guest.svg | 5 + mpuniapp/static/icons/email.svg | 3 + mpuniapp/static/icons/google.svg | 6 + mpuniapp/static/icons/kakao.svg | 3 + mpuniapp/static/icons/line.svg | 3 + mpuniapp/static/icons/linkedin.svg | 3 + mpuniapp/static/icons/phone.svg | 3 + mpuniapp/static/icons/telegram.svg | 3 + mpuniapp/static/icons/twitter.svg | 3 + mpuniapp/static/icons/wechat.svg | 3 + mpuniapp/static/icons/whatsapp.svg | 3 + mpuniapp/tests/card-articles.test.ts | 103 +- mpuniapp/tests/card-cases.test.ts | 112 +- mpuniapp/tests/workplace.test.ts | 81 + 227 files changed, 21855 insertions(+), 5264 deletions(-) create mode 100644 admin/src/pages/platform/renewals/locale/index.ts create mode 100644 admin/src/pages/platform/subscribers/locale/index.ts create mode 100644 admin/src/pages/platform/subscriptions/locale/index.ts create mode 100644 admin/tests/platform-subscribers-actions.test.ts create mode 100644 admin/tests/platform-subscriptions.test.ts create mode 100644 backend/src/modules/ai/controller/open/ocr.ts create mode 100644 backend/src/modules/ai/entity/deepseek-config.ts create mode 100644 backend/src/modules/ai/service/ocr.ts create mode 100644 backend/src/modules/crm/service/hubspot.ts create mode 100644 backend/src/modules/crm/service/salesforce.ts create mode 100644 backend/src/modules/team/entity/stripe-event.ts create mode 100644 backend/src/modules/user/controller/app/external.ts create mode 100644 backend/src/modules/user/service/external-auth.ts create mode 100644 backend/test/modules/ai/ocr.test.ts create mode 100644 backend/test/modules/card/admin-seed-guard.test.ts create mode 100644 backend/test/modules/card/vcard-export-api.test.ts create mode 100644 backend/test/modules/crm/hubspot.test.ts create mode 100644 backend/test/modules/crm/lead-external-sync.test.ts create mode 100644 backend/test/modules/crm/salesforce.test.ts create mode 100644 backend/test/modules/user/external-auth.test.ts create mode 100644 mpuniapp/static/icons/apple.svg create mode 100644 mpuniapp/static/icons/avatar-guest.svg create mode 100644 mpuniapp/static/icons/email.svg create mode 100644 mpuniapp/static/icons/google.svg create mode 100644 mpuniapp/static/icons/kakao.svg create mode 100644 mpuniapp/static/icons/line.svg create mode 100644 mpuniapp/static/icons/linkedin.svg create mode 100644 mpuniapp/static/icons/phone.svg create mode 100644 mpuniapp/static/icons/telegram.svg create mode 100644 mpuniapp/static/icons/twitter.svg create mode 100644 mpuniapp/static/icons/wechat.svg create mode 100644 mpuniapp/static/icons/whatsapp.svg 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 && (