补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。 Co-authored-by: Cursor <cursoragent@cursor.com>
591 行
21 KiB
Plaintext
591 行
21 KiB
Plaintext
/**
|
||
* OmniCard AI (CRMmp) - 无摩擦互换名片留资业务驱动层
|
||
* 严格遵循 uts 强类型规范与 AGENTS.md 约束
|
||
*/
|
||
|
||
import { LeadEntity, SubmitLeadParams } from '../../common/types.uts';
|
||
import { submitLead } from '../../common/api.uts';
|
||
import { getCurrentLocale, getOmniText } from '../../common/locale.uts';
|
||
|
||
export type ExchangeForm = {
|
||
name: string;
|
||
company: string;
|
||
phone: string;
|
||
email: string;
|
||
notes: string;
|
||
};
|
||
|
||
export type ExchangeState = {
|
||
form: ExchangeForm;
|
||
cardId: string;
|
||
slug: string;
|
||
submitting: boolean;
|
||
canSubmit: boolean;
|
||
errorMessage: string;
|
||
};
|
||
|
||
export type ExchangePageOptions = {
|
||
cardId?: string;
|
||
slug?: string;
|
||
id?: string;
|
||
};
|
||
|
||
const VISITOR_STORAGE_KEY = 'omni_visitor_id';
|
||
|
||
/**
|
||
* 读取本地已有访客标识,不在本页新建
|
||
*/
|
||
function readVisitorId(): string {
|
||
try {
|
||
const val = uni.getStorageSync(VISITOR_STORAGE_KEY);
|
||
return val != null ? String(val) : '';
|
||
} catch (e) {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建互换名片表单初始状态
|
||
*/
|
||
export function createExchangeState(): ExchangeState {
|
||
return {
|
||
form: {
|
||
name: '',
|
||
company: '',
|
||
phone: '',
|
||
email: '',
|
||
notes: '',
|
||
},
|
||
cardId: '',
|
||
slug: '',
|
||
submitting: false,
|
||
canSubmit: false,
|
||
errorMessage: '',
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 解析提交用的名片标识:优先 cardId,其次 slug
|
||
*/
|
||
export function resolveExchangeCardId(state: ExchangeState): string {
|
||
if (state.cardId && state.cardId.trim() !== '') {
|
||
return state.cardId.trim();
|
||
}
|
||
if (state.slug && state.slug.trim() !== '') {
|
||
return state.slug.trim();
|
||
}
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* 从页面 onLoad options 写入名片标识
|
||
* 缺少 cardId 与 slug 时 toast 并禁止提交
|
||
*/
|
||
export function applyExchangeOptions(
|
||
state: ExchangeState,
|
||
options: ExchangePageOptions | null
|
||
): boolean {
|
||
const cardIdRaw = options != null ? options.cardId || options.id || '' : '';
|
||
const slugRaw = options != null ? options.slug || '' : '';
|
||
state.cardId = String(cardIdRaw).trim();
|
||
state.slug = String(slugRaw).trim();
|
||
state.canSubmit = resolveExchangeCardId(state) !== '';
|
||
|
||
if (!state.canSubmit) {
|
||
uni.showToast({
|
||
title: '缺少名片标识,无法提交',
|
||
icon: 'none',
|
||
});
|
||
}
|
||
|
||
return state.canSubmit;
|
||
}
|
||
|
||
/**
|
||
* 校验姓名 + (WhatsApp/phone 或 email)
|
||
* 通过返回空字符串
|
||
*/
|
||
export function validateExchangeForm(form: ExchangeForm): string {
|
||
const name = form.name ? form.name.trim() : '';
|
||
if (name === '') {
|
||
return '请填写姓名';
|
||
}
|
||
|
||
const phone = form.phone ? form.phone.trim() : '';
|
||
const email = form.email ? form.email.trim() : '';
|
||
if (phone === '' && email === '') {
|
||
return '请填写 WhatsApp 或邮箱';
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* 仅接口明确成功才视为互换完成:
|
||
* - persisted === false → 未落库,不成功
|
||
* - persisted === true → 成功
|
||
* - 无 persisted 字段时,须有非空 id(CRM 留资落库回执)
|
||
*/
|
||
export function isExchangeSubmitSuccess(lead: LeadEntity | null | Record<string, unknown>): boolean {
|
||
if (lead == null || typeof lead !== 'object') {
|
||
return false;
|
||
}
|
||
const record = lead as Record<string, unknown>;
|
||
if ('persisted' in record) {
|
||
return record['persisted'] === true;
|
||
}
|
||
const id = record['id'];
|
||
return id != null && String(id).trim() !== '';
|
||
}
|
||
|
||
/**
|
||
* 清空表单字段,保留名片标识
|
||
*/
|
||
export function resetExchangeForm(state: ExchangeState): void {
|
||
state.form.name = '';
|
||
state.form.company = '';
|
||
state.form.phone = '';
|
||
state.form.email = '';
|
||
state.form.notes = '';
|
||
state.errorMessage = '';
|
||
}
|
||
|
||
/**
|
||
* 提交名片交换:校验通过后调用已有 submitLead
|
||
*/
|
||
export async function submitExchange(state: ExchangeState): Promise<LeadEntity | null> {
|
||
const cardId = resolveExchangeCardId(state);
|
||
if (!state.canSubmit || cardId === '') {
|
||
uni.showToast({
|
||
title: '缺少名片标识,无法提交',
|
||
icon: 'none',
|
||
});
|
||
return null;
|
||
}
|
||
|
||
const invalidReason = validateExchangeForm(state.form);
|
||
if (invalidReason !== '') {
|
||
uni.showToast({
|
||
title: invalidReason,
|
||
icon: 'none',
|
||
});
|
||
return null;
|
||
}
|
||
|
||
if (state.submitting) {
|
||
return null;
|
||
}
|
||
|
||
const name = state.form.name.trim();
|
||
const company = state.form.company.trim();
|
||
const phone = state.form.phone.trim();
|
||
const email = state.form.email.trim();
|
||
const notes = state.form.notes.trim();
|
||
const visitorId = readVisitorId();
|
||
|
||
const payload: SubmitLeadParams = {
|
||
cardId,
|
||
name,
|
||
};
|
||
if (company !== '') {
|
||
payload.company = company;
|
||
}
|
||
if (phone !== '') {
|
||
payload.phone = phone;
|
||
}
|
||
if (email !== '') {
|
||
payload.email = email;
|
||
}
|
||
if (notes !== '') {
|
||
payload.notes = notes;
|
||
}
|
||
if (visitorId !== '') {
|
||
payload.visitorId = visitorId;
|
||
}
|
||
payload.source = 'link';
|
||
|
||
state.submitting = true;
|
||
state.errorMessage = '';
|
||
|
||
try {
|
||
const lead = await submitLead(payload);
|
||
state.submitting = false;
|
||
if (!isExchangeSubmitSuccess(lead)) {
|
||
state.errorMessage = '交换未保存,请稍后重试';
|
||
uni.showToast({
|
||
title: state.errorMessage,
|
||
icon: 'none',
|
||
});
|
||
return null;
|
||
}
|
||
resetExchangeForm(state);
|
||
uni.showToast({
|
||
title: '留资已提交',
|
||
icon: 'none',
|
||
});
|
||
return lead;
|
||
} catch (err) {
|
||
state.submitting = false;
|
||
if (err instanceof Error) {
|
||
state.errorMessage = err.message;
|
||
} else {
|
||
state.errorMessage = '交换名片失败';
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export type ExchangeCopyKey =
|
||
| 'title'
|
||
| 'desc'
|
||
| 'warnMissingId'
|
||
| 'ocrTitle'
|
||
| 'ocrSubtitle'
|
||
| 'ocrScan'
|
||
| 'ocrScanning'
|
||
| 'ocrPreviewTitle'
|
||
| 'ocrPreviewHint'
|
||
| 'ocrDelete'
|
||
| 'nameLabel'
|
||
| 'namePlaceholder'
|
||
| 'companyLabel'
|
||
| 'companyPlaceholder'
|
||
| 'whatsappLabel'
|
||
| 'whatsappPlaceholder'
|
||
| 'emailLabel'
|
||
| 'emailPlaceholder'
|
||
| 'notesLabel'
|
||
| 'notesPlaceholder'
|
||
| 'submit'
|
||
| 'submitting'
|
||
| 'badge'
|
||
| 'badgeAi'
|
||
| 'contactSectionTitle'
|
||
| 'contactSectionDesc'
|
||
| 'intentTitle'
|
||
| 'intentCooperate'
|
||
| 'intentPurchase'
|
||
| 'intentInquiry'
|
||
| 'intentAgent'
|
||
| 'intentTech'
|
||
| 'privacyTitle'
|
||
| 'privacyDesc'
|
||
| 'successTitle'
|
||
| 'successDesc'
|
||
| 'backPortal'
|
||
| 'submitAgain'
|
||
| 'whatsappOrEmailTip'
|
||
| 'whatsappBadge'
|
||
| 'requiredMark';
|
||
|
||
const EXCHANGE_TEXTS: Record<string, Record<string, string>> = {
|
||
'zh-CN': {
|
||
desc: '留下姓名与联系方式,双方建立高效商务连接',
|
||
warnMissingId: '缺少名片标识,无法提交',
|
||
ocrTitle: '纸质名片识别',
|
||
ocrSubtitle: '拍照或上传名片,自动识别填入',
|
||
ocrScan: '拍摄/上传',
|
||
ocrScanning: '识别中...',
|
||
ocrPreviewTitle: '名片原图',
|
||
ocrPreviewHint: '点击放大预览原图',
|
||
nameLabel: '姓名',
|
||
namePlaceholder: '请输入姓名',
|
||
companyLabel: '公司',
|
||
companyPlaceholder: '选填,例如:ABC Global Ltd',
|
||
whatsappPlaceholder: 'WhatsApp 号码(例:+86 138... 或 +971 50...)',
|
||
emailLabel: '邮箱',
|
||
emailPlaceholder: '工作邮箱 (name@company.com)',
|
||
notesLabel: '需求留言 / 洽谈备注',
|
||
notesPlaceholder: '选填,简要说明需求或选上方意向标签',
|
||
submit: '交换名片',
|
||
submitting: '提交中...',
|
||
badge: '双向名片互换',
|
||
badgeAi: '名片扫描识别',
|
||
contactSectionTitle: '联系人信息',
|
||
contactSectionDesc: '留下真实商务联系方式,便于后续及时跟进',
|
||
intentTitle: '沟通意向 (快捷选择)',
|
||
intentCooperate: '商务合作',
|
||
intentPurchase: '产品采购',
|
||
intentInquiry: '索取资料',
|
||
intentAgent: '代理加盟',
|
||
intentTech: '技术交流',
|
||
privacyTitle: '隐私与数据安全',
|
||
privacyDesc: '您的信息仅用于双方商务对接与资料发送,遵循严格的国际隐私保护与数据合规标准。',
|
||
successTitle: '名片交换已完成',
|
||
successDesc: '名片所有者已收到您的联系方式,将尽快与您取得联系。',
|
||
backPortal: '返回微官网',
|
||
submitAgain: '重新填写',
|
||
whatsappOrEmailTip: 'WhatsApp 或邮箱至少填写一项',
|
||
whatsappBadge: '全球常用',
|
||
requiredMark: '必填',
|
||
},
|
||
'en-US': {
|
||
desc: 'Leave your contact details to connect and receive business information.',
|
||
warnMissingId: 'This card is missing an ID, so the form cannot be submitted.',
|
||
ocrTitle: 'Scan Paper Business Card',
|
||
ocrSubtitle: 'Snap or upload a card image to autofill the form instantly.',
|
||
ocrScan: 'Photo / Upload',
|
||
ocrScanning: 'Scanning...',
|
||
ocrPreviewTitle: 'Card Photo',
|
||
ocrPreviewHint: 'Tap to view full size',
|
||
nameLabel: 'Name',
|
||
namePlaceholder: 'Your full name',
|
||
companyLabel: 'Company',
|
||
companyPlaceholder: 'Optional, e.g. Acme Global Inc.',
|
||
whatsappPlaceholder: 'WhatsApp number (e.g. +1 555... or +971 50...)',
|
||
emailLabel: 'Email',
|
||
emailPlaceholder: 'Work email (name@company.com)',
|
||
notesLabel: 'Message / Business Notes',
|
||
notesPlaceholder: 'Optional — briefly describe what you need or tap intent chips above',
|
||
submit: 'Submit & Exchange',
|
||
submitting: 'Submitting...',
|
||
badge: 'Mutual Card Exchange',
|
||
badgeAi: 'AI Fast Fill',
|
||
contactSectionTitle: 'Contact Details',
|
||
contactSectionDesc: 'Provide valid contact info for direct business follow-up',
|
||
intentTitle: 'Business Intent (Quick Select)',
|
||
intentCooperate: 'Partnership',
|
||
intentPurchase: 'Procurement',
|
||
intentInquiry: 'Request Info',
|
||
intentAgent: 'Distributor',
|
||
intentTech: 'Tech Exchange',
|
||
privacyTitle: 'Enterprise Privacy & Security',
|
||
privacyDesc: 'Your details are strictly used for direct business communication in compliance with global privacy standards.',
|
||
successTitle: 'Card Exchanged Successfully',
|
||
successDesc: 'The card owner has received your contact details and business intent, and will reach out via WhatsApp or email soon.',
|
||
backPortal: 'Back to Profile',
|
||
submitAgain: 'Exchange Another Card',
|
||
whatsappOrEmailTip: 'Provide at least WhatsApp or Email',
|
||
whatsappBadge: 'Recommended',
|
||
requiredMark: 'Required',
|
||
},
|
||
'ar-SA': {
|
||
desc: 'اترك اسمك وطريقة التواصل لبناء علاقة عمل مباشرة وفعالة.',
|
||
warnMissingId: 'البطاقة تفتقد للمعرف، لا يمكن إرسال النموذج.',
|
||
ocrTitle: 'مسح البطاقة الورقية بالذكاء الاصطناعي',
|
||
ocrSubtitle: 'التقط صورة أو حمّل بطاقة للملء التلقائي الفوري.',
|
||
ocrScan: 'تصوير / رفع',
|
||
ocrScanning: 'جاري المسح...',
|
||
ocrPreviewTitle: 'صورة البطاقة',
|
||
ocrPreviewHint: 'اضغط لعرض بالحجم الكامل',
|
||
nameLabel: 'الاسم',
|
||
namePlaceholder: 'اسمك الكامل',
|
||
companyLabel: 'الشركة',
|
||
companyPlaceholder: 'اختياري، مثلاً: شركة النور العالمية',
|
||
whatsappPlaceholder: 'رقم واتساب (مثلاً: +971 50...)',
|
||
emailLabel: 'البريد الإلكتروني',
|
||
emailPlaceholder: 'بريد العمل (name@company.com)',
|
||
notesLabel: 'ملاحظات أو رسالة',
|
||
notesPlaceholder: 'اختياري — اكتب موجزاً عن اهتمامك أو اختر أعلاه',
|
||
submit: 'إرسال وتبادل البطاقة',
|
||
submitting: 'جاري الإرسال...',
|
||
badge: 'تبادل بطاقات الأعمال',
|
||
badgeAi: 'ملء فوري بالذكاء الاصطناعي',
|
||
contactSectionTitle: 'معلومات الاتصال',
|
||
contactSectionDesc: 'يرجى تقديم بيانات اتصال صحيحة للمتابعة المباشرة',
|
||
intentTitle: 'الغرض من التواصل (اختيار سريع)',
|
||
intentCooperate: 'شراكة أعمال',
|
||
intentPurchase: 'شراء منتجات',
|
||
intentInquiry: 'طلب معلومات',
|
||
intentAgent: 'وكيل معتمد',
|
||
intentTech: 'تبادل تقني',
|
||
privacyTitle: 'حماية وأمان البيانات المعتمد',
|
||
privacyDesc: 'تُستخدم بياناتك حصرياً للتواصل التجاري الثنائي وفق المعايير الدولية لحماية البيانات.',
|
||
successTitle: 'تم تبادل البطاقة بنجاح',
|
||
successDesc: 'استلم صاحب البطاقة معلومات اتصالك والغرض، وسيتواصل معك قريباً عبر واتساب أو البريد الإلكتروني.',
|
||
backPortal: 'العودة للملف الشخصي',
|
||
submitAgain: 'تبادل بطاقة أخرى',
|
||
whatsappOrEmailTip: 'يرجى إدخال واتساب أو البريد على الأقل',
|
||
whatsappBadge: 'المفضل',
|
||
requiredMark: 'مطلوب',
|
||
},
|
||
'es-ES': {
|
||
desc: 'Deje sus datos de contacto para establecer una conexión comercial directa.',
|
||
warnMissingId: 'Esta tarjeta no tiene identificador y no se puede enviar.',
|
||
ocrTitle: 'Escaneo de tarjeta física con IA',
|
||
ocrSubtitle: 'Tome una foto o suba una imagen para autorrellenar el formulario.',
|
||
ocrScan: 'Foto / Subir',
|
||
ocrScanning: 'Escaneando...',
|
||
ocrPreviewTitle: 'Foto de tarjeta',
|
||
ocrPreviewHint: 'Toque para ampliar',
|
||
nameLabel: 'Nombre',
|
||
namePlaceholder: 'Su nombre completo',
|
||
companyLabel: 'Empresa',
|
||
companyPlaceholder: 'Opcional, ej. Global Corp',
|
||
whatsappPlaceholder: 'Número de WhatsApp (ej. +34 600...)',
|
||
emailLabel: 'Correo electrónico',
|
||
emailPlaceholder: 'Correo de trabajo (name@company.com)',
|
||
notesLabel: 'Mensaje / Notas',
|
||
notesPlaceholder: 'Opcional: describa su requerimiento o seleccione una opción arriba',
|
||
submit: 'Enviar e intercambiar',
|
||
submitting: 'Enviando...',
|
||
badge: 'Intercambio mutuo de tarjetas',
|
||
badgeAi: 'IA Relleno Rápido',
|
||
contactSectionTitle: 'Datos de contacto',
|
||
contactSectionDesc: 'Facilite sus datos válidos para el seguimiento comercial',
|
||
intentTitle: 'Intención comercial (selección rápida)',
|
||
intentCooperate: 'Alianza comercial',
|
||
intentPurchase: 'Adquisición',
|
||
intentInquiry: 'Solicitar catálogo',
|
||
intentAgent: 'Distribución',
|
||
intentTech: 'Consulta técnica',
|
||
privacyTitle: 'Garantía de privacidad empresarial',
|
||
privacyDesc: 'Sus datos se utilizan estrictamente para el contacto comercial según los estándares internacionales de privacidad.',
|
||
successTitle: 'Tarjeta intercambiada con éxito',
|
||
successDesc: 'El titular de la tarjeta ha recibido sus datos y se comunicará pronto por WhatsApp o correo.',
|
||
backPortal: 'Volver al perfil',
|
||
submitAgain: 'Intercambiar otra',
|
||
whatsappOrEmailTip: 'Ingrese al menos WhatsApp o correo',
|
||
whatsappBadge: 'Recomendado',
|
||
requiredMark: 'Obligatorio',
|
||
},
|
||
'de-DE': {
|
||
desc: 'Hinterlassen Sie Ihre Kontaktdaten für einen direkten geschäftlichen Austausch.',
|
||
warnMissingId: 'Dieser Karte fehlt eine Kennung, daher kein Versand möglich.',
|
||
ocrTitle: 'Visitenkarte mit KI scannen',
|
||
ocrSubtitle: 'Foto aufnehmen oder Bild hochladen für automatisches Ausfüllen.',
|
||
ocrScan: 'Foto / Upload',
|
||
ocrScanning: 'Wird gescannt...',
|
||
ocrPreviewTitle: 'Visitenkartenfoto',
|
||
ocrPreviewHint: 'Antippen zum Vergrößern',
|
||
nameLabel: 'Name',
|
||
namePlaceholder: 'Ihr vollständiger Name',
|
||
companyLabel: 'Unternehmen',
|
||
companyPlaceholder: 'Optional, z. B. Muster GmbH',
|
||
whatsappPlaceholder: 'WhatsApp-Nummer (z. B. +49 151...)',
|
||
emailLabel: 'E-Mail',
|
||
emailPlaceholder: 'Geschäftliche E-Mail (name@company.com)',
|
||
notesLabel: 'Nachricht / Notiz',
|
||
notesPlaceholder: 'Optional — kurze Beschreibung Ihres Anliegens',
|
||
submit: 'Absenden & austauschen',
|
||
submitting: 'Wird gesendet...',
|
||
badge: 'Gegenseitiger Austausch',
|
||
badgeAi: 'KI-Schnellausfüllen',
|
||
contactSectionTitle: 'Kontaktdaten',
|
||
contactSectionDesc: 'Geben Sie Ihre Daten für geschäftliche Nachfassaktionen an',
|
||
intentTitle: 'Geschäftsabsicht (Schnellauswahl)',
|
||
intentCooperate: 'Kooperation',
|
||
intentPurchase: 'Beschaffung',
|
||
intentInquiry: 'Infos anfordern',
|
||
intentAgent: 'Vertriebspartner',
|
||
intentTech: 'Technischer Austausch',
|
||
privacyTitle: 'Unternehmensdatenschutz & Sicherheit',
|
||
privacyDesc: 'Ihre Daten werden vertraulich und streng nach internationalen Datenschutzstandards verarbeitet.',
|
||
successTitle: 'Visitenkarte erfolgreich übermittelt',
|
||
successDesc: 'Der Karteninhaber hat Ihre Kontaktdaten erhalten und meldet sich in Kürze per WhatsApp oder E-Mail.',
|
||
backPortal: 'Zurück zum Profil',
|
||
submitAgain: 'Weitere Karte tauschen',
|
||
whatsappOrEmailTip: 'Mindestens WhatsApp oder E-Mail angeben',
|
||
whatsappBadge: 'Empfohlen',
|
||
requiredMark: 'Erforderlich',
|
||
},
|
||
'fr-FR': {
|
||
desc: 'Laissez vos coordonnées pour établir un contact professionnel direct.',
|
||
warnMissingId: 'Identifiant manquant, formulaire impossible à envoyer.',
|
||
ocrTitle: 'Numérisation de carte par IA',
|
||
ocrSubtitle: 'Prenez une photo pour préremplir automatiquement le formulaire.',
|
||
ocrScan: 'Photo / Importer',
|
||
ocrScanning: 'Numérisation...',
|
||
ocrPreviewTitle: 'Photo de carte',
|
||
ocrPreviewHint: 'Appuyez pour agrandir',
|
||
nameLabel: 'Nom',
|
||
namePlaceholder: 'Votre nom complet',
|
||
companyLabel: 'Entreprise',
|
||
companyPlaceholder: 'Facultatif, ex. Société SAS',
|
||
whatsappPlaceholder: 'Numéro WhatsApp (ex. +33 6...)',
|
||
emailLabel: 'E-mail',
|
||
emailPlaceholder: 'E-mail professionnel (name@company.com)',
|
||
notesLabel: 'Message / Remarques',
|
||
notesPlaceholder: 'Facultatif — décrivez brièvement votre projet',
|
||
submit: 'Envoyer et échanger',
|
||
submitting: 'Envoi en cours...',
|
||
badge: 'Échange mutuel de cartes',
|
||
badgeAi: 'Remplissage IA rapide',
|
||
contactSectionTitle: 'Coordonnées',
|
||
contactSectionDesc: 'Indiquez vos coordonnées pour le suivi commercial direct',
|
||
intentTitle: 'Intention commerciale (sélection rapide)',
|
||
intentCooperate: 'Partenariat',
|
||
intentPurchase: 'Approvisionnement',
|
||
intentInquiry: 'Documentation',
|
||
intentAgent: 'Distribution',
|
||
intentTech: 'Échange technique',
|
||
privacyTitle: 'Confidentialité et sécurité des données',
|
||
privacyDesc: 'Vos données sont strictement réservées au contact commercial conformément aux normes internationales.',
|
||
successTitle: 'Carte échangée avec succès',
|
||
successDesc: 'Le propriétaire a reçu vos coordonnées et vous contactera bientôt par WhatsApp ou e-mail.',
|
||
backPortal: 'Retour au profil',
|
||
submitAgain: 'Échanger une autre',
|
||
whatsappOrEmailTip: 'Indiquez au moins WhatsApp ou e-mail',
|
||
whatsappBadge: 'Recommandé',
|
||
requiredMark: 'Requis',
|
||
},
|
||
'ja-JP': {
|
||
desc: '連絡先をご入力いただき、双方の円滑なビジネス連絡に役立てます。',
|
||
warnMissingId: '名刺識別子がないため送信できません。',
|
||
ocrTitle: 'AI 紙名刺スキャン',
|
||
ocrSubtitle: '写真を撮るか画像をアップロードして自動入力します。',
|
||
ocrScan: '撮影 / アップロード',
|
||
ocrScanning: '認識中...',
|
||
ocrPreviewTitle: '名刺画像',
|
||
ocrPreviewHint: 'タップして拡大表示',
|
||
nameLabel: 'お名前',
|
||
namePlaceholder: 'お名前を入力してください',
|
||
companyLabel: '貴社名',
|
||
companyPlaceholder: '任意(例:株式会社〇〇)',
|
||
whatsappPlaceholder: 'WhatsApp または電話番号(例:+81 90...)',
|
||
emailLabel: 'メールアドレス',
|
||
emailPlaceholder: '勤務先メールアドレス (name@company.com)',
|
||
notesLabel: 'ご用件 / メモ',
|
||
notesPlaceholder: '任意 — ご要望の概要または上のタグを選択',
|
||
submit: '名刺を交換して送信',
|
||
submitting: '送信中...',
|
||
badge: '相互名刺交換',
|
||
badgeAi: 'AI 高速自動入力',
|
||
contactSectionTitle: '連絡先情報',
|
||
contactSectionDesc: '今後のビジネスフォローのため正確な連絡先をご入力ください',
|
||
intentTitle: 'ご用件(クイック選択)',
|
||
intentCooperate: 'ビジネス提携',
|
||
intentPurchase: '製品購入',
|
||
intentInquiry: '資料請求',
|
||
intentAgent: '代理店希望',
|
||
intentTech: '技術相談',
|
||
privacyTitle: 'エンタープライズ情報セキュリティ保護',
|
||
privacyDesc: 'ご入力情報はビジネス連絡にのみ使用され、国際的なプライバシー基準に準拠します。',
|
||
successTitle: '名刺交換が完了しました',
|
||
successDesc: '名刺の持ち主に連絡先が送信されました。WhatsApp またはメールでご連絡いたします。',
|
||
backPortal: 'プロフィールに戻る',
|
||
submitAgain: '別の名刺を交換',
|
||
whatsappOrEmailTip: 'WhatsApp またはメールのいずれかを入力してください',
|
||
whatsappBadge: '推奨',
|
||
requiredMark: '必須',
|
||
},
|
||
};
|
||
|
||
/**
|
||
* 互换名片页文案:能复用 locale 词典的走 getOmniText,其余走多语言映射表
|
||
*/
|
||
export function resolveExchangeText(key: string): string {
|
||
const locale = getCurrentLocale();
|
||
if (key === 'title') {
|
||
return getOmniText(locale, 'card.exchange');
|
||
}
|
||
if (key === 'ocrDelete') {
|
||
return getOmniText(locale, 'common.delete');
|
||
}
|
||
if (key === 'whatsappLabel') {
|
||
return getOmniText(locale, 'portal.whatsapp');
|
||
}
|
||
|
||
const langMap = EXCHANGE_TEXTS[locale] || EXCHANGE_TEXTS['en-US'] || EXCHANGE_TEXTS['zh-CN'];
|
||
if (langMap != null && langMap[key] != null) {
|
||
return langMap[key];
|
||
}
|
||
|
||
const fallbackMap = EXCHANGE_TEXTS['en-US'] || EXCHANGE_TEXTS['zh-CN'];
|
||
if (fallbackMap != null && fallbackMap[key] != null) {
|
||
return fallbackMap[key];
|
||
}
|
||
|
||
return key;
|
||
}
|