完善官网、管理后台与后端的多语言内容编辑和发布流程,调整站点页面及相关接口,并同步数据库脚本。 新增容器部署配置,改用环境变量注入数据库凭据;补充仓库忽略规则,并停止跟踪本地环境文件和 Maven 构建产物。
185 lines
5.5 KiB
JavaScript
185 lines
5.5 KiB
JavaScript
/**
|
||
* 门户客户服务(若依公开接口)- 在线留言、联系信息
|
||
*/
|
||
import { nextTick } from 'vue'
|
||
import i18n from '../i18n'
|
||
|
||
function ui(key, fallback = '') {
|
||
const v = i18n.global.t(key)
|
||
return v && v !== key ? v : fallback
|
||
}
|
||
|
||
function escapeHtml(text) {
|
||
if (text == null || text === '') {
|
||
return ''
|
||
}
|
||
return String(text)
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"')
|
||
.replace(/'/g, ''')
|
||
}
|
||
|
||
/**
|
||
* 获取联系信息列表
|
||
* @returns {Promise<Array>}
|
||
*/
|
||
export async function fetchContactList() {
|
||
const base = (import.meta.env.VITE_SITE_API_BASE || '/site').replace(/\/$/, '')
|
||
const res = await fetch(`${base}/contact/list`, { credentials: 'omit', cache: 'no-store' })
|
||
if (!res.ok) {
|
||
throw new Error(`HTTP ${res.status}`)
|
||
}
|
||
const body = await res.json()
|
||
if (body.code !== 200) {
|
||
throw new Error(body.msg || '接口返回异常')
|
||
}
|
||
return Array.isArray(body.data) ? body.data : []
|
||
}
|
||
|
||
/**
|
||
* 提交在线留言
|
||
* @param {Object} data { messageName, messagePhone, messageEmail, messageContent }
|
||
* @returns {Promise<Object>}
|
||
*/
|
||
export async function submitMessage(data) {
|
||
const base = (import.meta.env.VITE_SITE_API_BASE || '/site').replace(/\/$/, '')
|
||
const inquiryPayload = {
|
||
inquiryName: data?.messageName || '',
|
||
inquiryPhone: data?.messagePhone || '',
|
||
inquiryProduct: data?.messageEmail || '',
|
||
inquiryMessage: data?.messageContent || ''
|
||
}
|
||
const res = await fetch(`${base}/product/inquiry`, {
|
||
method: 'POST',
|
||
credentials: 'omit',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(inquiryPayload)
|
||
})
|
||
if (!res.ok) {
|
||
throw new Error(`HTTP ${res.status}`)
|
||
}
|
||
return await res.json()
|
||
}
|
||
|
||
/**
|
||
* 注入联系信息并初始化留言表单
|
||
*/
|
||
export async function injectContactAndInitForms() {
|
||
await injectContactInfo()
|
||
initMessageForm()
|
||
}
|
||
* 注入目标:联系我们页面的联系信息展示区域
|
||
*/
|
||
export async function injectContactInfo() {
|
||
const contactHost = document.querySelector(
|
||
'.contact-info-container, .info-list, .contact-list, .contact-way-list'
|
||
)
|
||
if (!contactHost) {
|
||
return
|
||
}
|
||
|
||
contactHost.innerHTML = ''
|
||
const contacts = await fetchContactList()
|
||
if (!contacts || !contacts.length) {
|
||
return
|
||
}
|
||
|
||
const contactHtml = contacts.map(contact => {
|
||
const iconHtml = contact.contactIcon ? `<img src="${escapeHtml(contact.contactIcon)}" alt="">` : ''
|
||
const value = escapeHtml(contact.contactValue || '')
|
||
|
||
// 电话类型可点击
|
||
const isPhone = contact.contactType === 'phone'
|
||
const displayValue = isPhone
|
||
? `<a href="tel:${value.replace(/[^0-9-]/g, '')}">${value}</a>`
|
||
: value
|
||
|
||
return `
|
||
<div class="contact-item contact-${escapeHtml(contact.contactType)}">
|
||
${iconHtml ? `<div class="contact-icon">${iconHtml}</div>` : ''}
|
||
<div class="contact-content">
|
||
<span class="contact-label">${escapeHtml(contact.contactLabel || '')}:</span>
|
||
<span class="contact-value">${displayValue}</span>
|
||
</div>
|
||
</div>
|
||
`
|
||
}).join('')
|
||
|
||
contactHost.innerHTML = contactHtml
|
||
}
|
||
|
||
/**
|
||
* 初始化留言表单
|
||
* 给留言表单绑定提交事件
|
||
*/
|
||
export function initMessageForm() {
|
||
const form = resolveMessageForm()
|
||
if (!form) {
|
||
return
|
||
}
|
||
if (form.dataset.huayangBoundMessage === '1') {
|
||
return
|
||
}
|
||
form.dataset.huayangBoundMessage = '1'
|
||
|
||
const submitHandler = async (event) => {
|
||
event.preventDefault()
|
||
|
||
const data = {
|
||
messageName: pickFormValue(form, ['name', 'messageName'], ['姓名', '联系人']),
|
||
messagePhone: pickFormValue(form, ['phone', 'messagePhone'], ['电话', '手机', '联系方式']),
|
||
messageEmail: pickFormValue(form, ['email', 'messageEmail'], ['邮箱', 'email']),
|
||
messageContent: pickFormValue(form, ['message', 'messageContent'], ['留言', '内容', '需求'])
|
||
}
|
||
|
||
if (!data.messageName || !data.messagePhone || !data.messageContent) {
|
||
alert(ui('ui.form.contact_required'))
|
||
return
|
||
}
|
||
|
||
try {
|
||
const result = await submitMessage(data)
|
||
if (result.code === 200) {
|
||
alert(ui('ui.status.submit_ok_message'))
|
||
form.reset()
|
||
} else {
|
||
alert(result.msg || ui('ui.status.submit_fail_retry'))
|
||
}
|
||
} catch (error) {
|
||
alert(ui('ui.status.submit_fail_retry'))
|
||
}
|
||
}
|
||
|
||
form.addEventListener('submit', submitHandler)
|
||
const submitBtn = form.querySelector('.e_formBtn-16, .e_formBtn-96, .btn-primary')
|
||
submitBtn?.addEventListener('click', submitHandler)
|
||
}
|
||
|
||
function resolveMessageForm() {
|
||
const explicit = document.querySelector('.message-form, #messageForm')
|
||
if (explicit) return explicit
|
||
const isContactPage =
|
||
window.location.search.includes('page=contact') || window.location.pathname.toLowerCase().includes('contact')
|
||
if (!isContactPage) return null
|
||
return document.querySelector('.e_form-10, form.e_form-10, form.e_form-94')
|
||
}
|
||
|
||
function pickFormValue(form, nameCandidates, placeholderCandidates) {
|
||
const byName = nameCandidates
|
||
.map((name) => form.querySelector(`[name="${name}"]`))
|
||
.find(Boolean)
|
||
if (byName?.value) return String(byName.value).trim()
|
||
|
||
const controls = Array.from(form.querySelectorAll('input, textarea, select'))
|
||
for (const control of controls) {
|
||
const hint = `${control.placeholder || ''}${control.getAttribute('name') || ''}`.toLowerCase()
|
||
if (placeholderCandidates.some((keyword) => hint.includes(String(keyword).toLowerCase()))) {
|
||
return String(control.value || '').trim()
|
||
}
|
||
}
|
||
return ''
|
||
} |