">
,需要通过父级DOM结构来判断
*/
var trackActionPhone = function (node) {
var nodeInnerText = node.innerText || ''
if (!limitRegLength(nodeInnerText)) return
var nodeText = trimText(nodeInnerText)
if (nodeText.length < 5 || nodeText.length > 20) return false
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'click'
var str = trimText(node.href || node.innerHTML || '')
if (phoneReg.test(str) && numUseReg.test(str)) {
_paq.push(['trackEvent', type, 'phone', nodeText])
return true
}
/** 排查父级嵌套非标签场景,并且对dom的正则校验做一个性能兜底,通过控制innerText的长度,来确保正则的性能 */
var fatherText = trimText(node.parentNode.innerText || '')
if (fatherText.length < 5 || fatherText.length > 20) return false
var fatherDom = trimText(node.parentNode.innerHTML || '')
if (phoneReg.test(fatherDom) && numUseReg.test(fatherDom)) {
_paq.push(['trackEvent', type, 'phone', nodeText])
return true
}
return false
}
window.addEventListener('click', function (e) {
var node = e.target
/** 社媒点击 */
var appName = ''
var getAppAriaLabel = node.ariaLabel || node.parentNode.ariaLabel || ''
if (mediaList.includes(getAppAriaLabel.toLowerCase())) {
appName = getAppAriaLabel
}
if (!appName && node.nodeName && node.nodeName.toLowerCase() === 'a') {
appName = getMediaName(node.href) || getMediaName(node.alt)
}
if (!appName && node.nodeName && node.nodeName.toLowerCase() === 'img') {
appName = getMediaName(node.alt) || getMediaName(node.src)
}
if (!appName && node.nodeName && node.nodeName.toLowerCase() === 'i') {
appName = getMediaName(node.className)
}
if (appName) {
_paq.push(['trackEvent', 'click', 'contactApp', appName])
return
}
/** 联系方式点击 */
if (trackActionPhone(node, 'click')) return
if (node.nodeName && node.nodeName.toLowerCase() === 'a') {
var val = node.href
if (!limitRegLength(val)) return
if (emailReg.test(val)) {
_paq.push(['trackEvent', 'click', 'email', val])
return
}
}
if (node.nodeName && node.nodeName.toLowerCase() === 'i') {
var val = node.className
var content = node.parentNode.href || ''
if (val.includes('email')) {
_paq.push(['trackEvent', 'click', 'email', content])
return
}
}
var nodeChildList = node.childNodes
for (var i = 0; i < nodeChildList.length; i++) {
;(function (i) {
if (nodeChildList[i].nodeType !== 3) return
var val = nodeChildList[i].textContent.replace(/\s?:?/g, '')
if (!limitRegLength(val)) return
if (emailReg.test(val)) {
_paq.push(['trackEvent', 'click', 'email', val])
return
}
})(i)
}
trackNumberData(node)
})
window.addEventListener('copy', function (e) {
if (trackActionPhone(e.target, 'copy')) return
var text = e.target.textContent
if (!text) return
var val = text.replace(/\s:?/g, '')
if (!limitRegLength(val)) return
if (emailReg.test(val)) {
_paq.push(['trackEvent', 'copy', 'email', val])
return
}
trackNumberData(e.target)
})
}
trackContactInit()
/**
* 基于custom_inquiry_form.js 以及 form.js 对于询盘表单提交的实现,来反推询盘表单的input标签触发,用来收集意向客户
* 1. 缓存的KEY:TRACK_INPUT_ID_MTM_00;
* 2. 缓存策略 - lockTrackInput:单个页面内,10分钟内,不重复上报
*/
function trackActionInput() {
const CACHE_KEY = 'TRACK_INPUT_ID_MTM_00'
const pathName = window.location.hostname + window.location.pathname
var lockTrackInput = function () {
try {
const lastCacheData = localStorage.getItem(CACHE_KEY)
if (!lastCacheData) return false
const cacheData = JSON.parse(lastCacheData)
const cacheTime = cacheData[pathName]
if (!cacheTime) return false
return Date.now() - cacheTime < 1000 * 60 * 10 // 10分钟内,不重复上报
} catch (error) {
console.error('lockTrackInput Error', error)
return false
}
}
var setInputTrackId = function () {
try {
const curCacheData = localStorage.getItem(CACHE_KEY)
if (curCacheData) {
const cacheData = JSON.parse(curCacheData)
cacheData[pathName] = Date.now()
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData))
return
}
const cacheData = {
[pathName]: Date.now(),
}
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData))
} catch (error) {
console.error('setInputTrackId Error', error)
}
}
var getInputDom = function (initDom) {
var ele = initDom
while (ele) {
/**
* isWebSiteForm 是站点的表单
* isChatWindowForm 是聊天窗口的表单
*/
/** 旧模板表单 */
var isWebSiteForm = !!(/crm-form/i.test(ele.className) && ele.querySelector('form'))
/** 1:新模板自定义表单、2:Get a Quote 弹框表单 */
var isWebSiteFormNew = !!(/inquiry/i.test(ele.className) && ele.querySelector('form'))
if (isWebSiteForm || isWebSiteFormNew) {
_paq.push(['trackEvent', 'formInquiry', 'formInput', 'page'])
setInputTrackId()
break
}
/** Mkt会话触达-聊天弹框的表单输入: MKT由于是iframe嵌入,所以MKT的上报,会单独写到MKT-form代码上 */
var isInquiryChatForm = !!(/comp-form/i.test(ele.className) && ele.querySelector('form'))
if (isInquiryChatForm) {
_paq.push(['trackEvent', 'formInquiry', 'formInput', 'chat'])
setInputTrackId()
break
}
/** 向上查找父节点 */
ele = ele.parentNode
}
}
function initInputListener() {
var inputUseDebounce = function (fn, delay) {
var timer = null
var that = this
return function () {
var args = Array.prototype.slice.call(arguments)
if (timer) clearTimeout(timer)
timer = setTimeout(function () {
fn.apply(that, args)
}, delay)
}
}
var optimizeGetInputDom = inputUseDebounce(getInputDom, 300)
window.addEventListener('input', function (e) {
/** 如果已经上报过,则不再上报 */
if (lockTrackInput()) return
optimizeGetInputDom(e.target)
})
}
try {
initInputListener()
} catch (error) {
console.log('initInputListener Error', error)
}
}
trackActionInput()
}
/** 第三方消息上报:目前主要是针对全点托管会话;在msgCollect/index.js中调试,访问test.html */
function thirdMsgCollect() {
/** 先检测是否是stayReal托管:如果stayReal脚本都没有,那么说明当前站点未开启stayReal会话托管 */
const scriptList = Array.prototype.slice.call(document.querySelectorAll('script'))
const checkStayReal = () => !!scriptList.find((s) => s.src.includes('stayreal.xiaoman.cn'))
if (!checkStayReal()) return
/** 缓存当前消息队列的最后一条消息id */
const CACHE_KEY = 'CACHE_KEY_MONITOR'
const setCache = (msgIndex) => {
/** 对缓存KEY进行base64转码处理 */
const cacheMsgIndex = btoa(msgIndex)
localStorage.setItem(CACHE_KEY, cacheMsgIndex)
}
const getCache = () => {
const cacheMsgIndex = localStorage.getItem(CACHE_KEY)
if (cacheMsgIndex) return Number(atob(cacheMsgIndex))
return -1
}
/** 拉取最新msg列表 */
const pullMsgList = () => {
const msgEleList = Array.prototype.slice.call(document.querySelectorAll('#chat-list li'))
const msgIds = []
const msgMap = msgEleList.reduce((acc, item) => {
const sendTime = item.querySelector('.message-data-time').textContent.trim()
const sendContent = item.querySelector('.message').textContent.trim()
/** msg带有class:other-message的是访客消息,my-message的是客服消息 */
const isOtherMessage = item.querySelector('.message').classList.contains('other-message')
const msgId = item.querySelector('.message').getAttribute('id')
const msgItemData = {
msgId,
user: isOtherMessage ? 'visitor' : 'official',
time: sendTime,
content: sendContent,
}
msgIds.push(msgId)
acc[msgId] = msgItemData
return acc
}, {})
return {
ids: msgIds,
dataMap: msgMap,
}
}
/** 加密并上传消息数据 */
let ENCRYPT_KEY = 'de29f1aab63ab033'
let ENCRYPT_IV = 'b8d2badf875e76ac'
const baseUrl = 'https://cms.xiaoman.cn'
// var getEncryptConfig = function () {
// const url = baseUrl + '/shop-api/innerApi/getKeyIv'
// $.get(
// url,
// function (result) {
// console.log('result', result)
// if (Number(result.code) === 0 && result.data.key && result.data.iv) {
// ENCRYPT_KEY = result.data.key
// ENCRYPT_IV = result.data.iv
// uploadMsgData()
// } else {
// /** 如果获取失败,则重试 */
// setTimeout(() => {
// getEncryptConfig()
// }, 1000)
// }
// },
// 'json'
// )
// }
// getEncryptConfig()
const encryptMsg = function (msgData) {
const enc = new TextEncoder()
// 转字节
const keyBytes = enc.encode(ENCRYPT_KEY)
const ivBytes = enc.encode(ENCRYPT_IV)
const plainBytes = enc.encode(msgData)
// 导入密钥并加密
return crypto.subtle
.importKey('raw', keyBytes, { name: 'AES-CBC' }, false, ['encrypt'])
.then(function (cryptoKey) {
return crypto.subtle.encrypt({ name: 'AES-CBC', iv: ivBytes }, cryptoKey, plainBytes)
})
.then(function (encryptedBuffer) {
// 转 base64 返回
return btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer)))
})
.catch((err) => {
return Promise.reject(err)
})
}
let uploadFlag = false
const uploadMsgData = function () {
if (uploadFlag) return
uploadFlag = true
const { ids, dataMap } = pullMsgList()
let cacheMsgIndex = getCache()
const msgLen = ids.length
if (!msgLen) {
// 消息DOM未挂载 || 消息DOM已挂载,但是消息列表为空
uploadFlag = false
return
}
if (msgLen - 1 < cacheMsgIndex) {
/** 针对站点挂后台一段时间,消息列表会自动塞入重复消息,导致消息有重复,刷新后又重置回正常消息列表,所以这里需要更新锚点下标 */
cacheMsgIndex = msgLen - 1
setCache(cacheMsgIndex)
uploadFlag = false
return
}
if (msgLen - 1 === cacheMsgIndex) {
// 缓存的最后一次发送的消息ID是最后一条(说明当前消息均已经上报),则不跳过本地上报
uploadFlag = false
return
}
const currentMsgIds = ids.slice(cacheMsgIndex + 1, msgLen)
const currentMsgData = currentMsgIds.map((id) => dataMap[id])
const mtmId = window.matomo_site_id_cookie_key || '' // 获取mtm会话id
const msgBody = {
mtmId,
curl: window.location.href,
msgList: currentMsgData,
}
const msgBodyStr = JSON.stringify(msgBody)
encryptMsg(msgBodyStr)
.then(function (encryptedMsg) {
console.log('encryptedMsg:', encryptedMsg, msgBodyStr)
const url = baseUrl + '/shop-api/External/ListenSiteActiveStatus'
$.ajax({
type: 'POST',
url,
data: JSON.stringify({ d_v: encryptedMsg }),
contentType: 'application/json',
success: function (result) {
if (Number(result.code) === 0) {
// 更新消息队列
setCache(msgLen - 1)
}
uploadFlag = false
},
error: function (err) {
console.error(err, '请求异常')
uploadFlag = false
},
})
})
.catch((err) => {
console.error(err, '数据加密失败')
uploadFlag = false
})
}
/** 监控chat-list的DOM变更 */
const initChatListObserver = () => {
// 需要监听的 DOM 节点
const target = document.getElementById('chat-list')
// 回调函数
const callback = function (mutationsList, observer) {
for (const mutation of mutationsList) {
console.log('mutation', mutation)
if (mutation.type === 'childList') {
uploadMsgData()
}
}
}
// 配置
const config = {
childList: true, // 监听子节点的增删
subtree: true, // 是否也监听后代节点
}
// 创建 observer
const observer = new MutationObserver(callback)
// 开始监听
observer.observe(target, config)
}
let testCount = 30
let itv = null
const checkChatDom = () => !!document.querySelector('#vc-model')
const initTalkCheck = () => {
itv = setTimeout(() => {
console.log('checkChatDom', checkChatDom(), testCount)
if (!checkChatDom() && testCount > 0) {
testCount--
initTalkCheck()
return
}
clearTimeout(itv)
uploadMsgData()
initChatListObserver()
}, 1500)
}
initTalkCheck()
}
try {
gtmTrack()
thirdMsgCollect()
console.log('inserted gtm code')
} catch (error) {
console.error('gtmTrack Error', error)
}
})
})();
Ата: "Денсау Дад Хаттар Yiwu Qianxun Модалы Әйелдерге" Стильді, бірақ қонақты әдеттердің басындағы аксессуарды қызықтыруға іздейсіз бе? Әкесінің шапкасы әйелдерге қараңыз! Бұл Yiwu Qianxun шапкалар моданың туралы белгілі әйелдер арасында танымал болып отыр, себебі олардың көптеген стилі және стильдік түрлері бар. Неліктен біз оларды қалай таныстырамыз? тәуелсіз шапкалар эрkek үшін татық шапкасының плюслері және олар қалай стиліңізді арттыру үшін пайдалануға болады Татық шапкалар өзін-өзі тастамас білген және әдемі қызdar үшін қажетті. Бұлар Yiwu Qianxun екілді киімге сәйкес келетін негізгі сандарда, тобы мен реттеулерде жинақталған. Масала, денімден, пәттен, қожадан немесе суеден жасалған татық шапкалар әдетпен және әдемі екен. қыздық бап шапка құрылысшылар татық шапкаларды әдемі әйелдерге арналған өзгертулермен шығарды. Бірнеше татық шапкаларда қосымша реттеулер немесе басқармақ мүмкін. Татық шапкалар әдемі әйелдерге арналған өзгертулермен шығарылды. Бірнеше татық шапкаларда қосымша реттеулер немесе басқармақ мүмкін. Олар әдемі әрекеттерге сайлауға мүмкіндік береді. Yiwu Qianxun басқа татық шапкаларда қызыл қырмыздықтар, қызыл қырмыздықтар немесе қызыл қырмыздықтар бар, олар әдемі стиліңізге жарық қосады. бап шапкалары әйелдерге арналған таңдаулар сызықсыз Ата қысқа шапкасын пайдалану, сіздің стильіңізді жоғары деңгейге арттырады, бірақ оның қараңғыдан сізді мүмкін етіп сақтайды. Ата қысқа шапкалары әдетте өзін-өзі ширекті көлден қоршаған және қазіргі UV жолдарынан сіздің құмырсыңыздан қорғайды. Yiwu Qianxun бұл таразымен жасалды жақсы таталған шапкалар шығыс ойындары үшін мүкеммелік, мысалы, туризм, кемпинг немесе пикник. Сонымен қатар, ата шапкалары өте қонақты, сондықтан шапка қойғанда да сенімді болмаңыз. қабатты және моданың, функционалдық пен ұзақ уақыт қолдану мүмкіндігін білдіреді. Бейсболдық шапкалар қабатты материалдармен жасалған және қабатты қоғамсыздық береді. Жибекшілік шапкалар стилдер мен салмақтар арасында таңдауға болады және клиенттердің қажеттеріне сәйкес өзгертілуге мүмкіндік береді. Жергілік шапкалар жинайлықпен жасалған. Сіз әдетте еркектерге арналған шапкаларды және әйелдерге арналған шапкаларды таңдауға болады. еркектерге арналған шапкаларды әйелдерге резервде тапсырыс береді, олардың тұрғындарына және қажеттеріне сәйкес. Олар бazar зерттеуін жүргізу, экспозицияларға қатысу, фидбек талап ету сияқты іс-әрекеттерді қамтамасыз етеді. Фабрика клиенттерге шапкаларды өзгертуге мүмкіндік береді, мисалы, логотип шеңберлеу немесе түстік өзгерту. әкесінің шапкасы әйелдер үшін қызметкерлер тобы бар, олар бір-бірімен қосымша мақсаттарын жеткізу үшін жұмыс істейді. Әр қызметкердің мәтіндеуіңізге және біліміне ие болады, және бастапқы дизайның кезеңінен сабаққа дейін қызметкерлер бір-бірімен жұмыс істейді, сонымен қатар ең жоғары стандарттарға сай шапкалар өндіріледі. әкесінің шапкасы әйелдер үшін логистика процесі әлемдегі салдарға барлық мәнгін береді. Олар халықаралық компаниялармен жұмыс істейді және шапкаларды теңіз арқылы, ұшқыр арқылы немесе жер арқылы жібереді. Логистика командасы әлемдік жіберулерді қамтамасыз етуге дағдылайды, шапкалар тиімді уақытта және жақсы жағдайда қабылданды. Ата шапкалары әрбір маңызды күн үшін қажет, сіз әрекеттерді орындауда, досыңызбен кездесуде, концертке баруда немесе саяхатта болғанда. Сіз оларды жинелермен, қысқа шорттармен, юбкамен немесе киіммен біріктіре аласыз, сонымен қатар, бұл стилі Yiwu Qianxun тренді. Ата шапкалары әртүрлі тіркелген түйінділермен, мысалы, түйін, ішкі, күміс немесе салынған түйіндермен қарым-қатынас жасайды, ал олар таталған шапка жедел. Оларды қыс күндерінде қауһарлықты сақтау үшін немесе жаз күндерінде суықты сақтау үшін жылдың әр уақытында қойып жіберуге болады. Ата қысқаулықтарын пайдалану жазымды және түсінікті. Біріншісі, сіздің кеңесіңізге немесе костюміңізге сәйкес келетін ата қысқаулықты таңдаңыз. Содан кейін, Yiwu Qianxun строптан ұсыныстарыңызды қалайсыз. Артқы тағын қысқаулықты қатерсеңіз, алдын-ала борты ауыстырыңыз және. Егер сіз шоғырлар қысқаулығын қысқаулықпен қолданасаңыз, оны қысқаулықпен қиындаған емес екенін тексеріңіз. Соңында, сіздің атаңызға жаңа қысқаулықты қызықтыруға мүмкіндік береді. таталған бейсбол шапка қысқаулықтардың жолын қоршаңыз. Оңтүстік, жаңадан келген қысқаулықтың атаңызға жаңа қысқаулық болуы мүмкін. Ата қысқаулықтарын сатуда, сіз қалай-да даңқты брендті таңдаңыз, ол қызмет береді Yiwu Qianxun жоғары деңгейде. Дизайндардың кең ассортиментін табу үшін брендтерді іздейді, материалдар мен түстердің кең ассортименті, қысқа уақытта қол жетімділік, қарапайым қайтару және клиенттерге қызмет көрсету dad trucker hat достықпен. Сіз клиенттердің шығындарын оқығыз немесе досыңыздан көмекті сұраңыз, сондықтан сіз жақсы өнім аладыңыз. Бап шапкалары әйелдерге арналған
Кіріспе:

Пайдалы қасиеттер:

Инновация:

Қауіпсіздік:
Why choose Yiwu Qianxun Бап шапкалары әйелдерге арналған?
Түрлі түрлі жоғары сапалы қабырғалар
Жалпы тез қызмет
Профессионалды және үшінші тім
Қызметкер және Қызметкер Логистика Системасы
Пайдалану:
Қолдану әдісі:
Қызмет көрсету:
Іздеуіңіз бен бәрі табылмады ма?
Қазір сұраныс жасаңыз
Қолжетімді өнімдер туралы кеңесшілерімізбен байланыс