Commit ed5e4b08 authored by 张九刚's avatar 张九刚

在 main.js 中集成 Sensorsdata 统计功能,配置传感器参数并全局挂载;在 Home.vue 中优化弹窗逻辑,增加对 qrInfoList 的安全访问处理,确保数据渲染的稳定性。

parent c2fe95b8
## 0.1.7 (2025-6-12)
* 修改许可协议。
## 0.1.6 (2025-5-27)
* 优化:微信小程序和支付宝小程序的原型链安全问题。
* 微信小程序更新到 v1.21.7
* 支付宝小程序更新到 v0.14.9
## 0.1.5 (2024-12-31)
* 新增:小红书小程序支持配置 identify_id。
* 在 v0.14.2 定制的小红书小程序版本
## 0.1.4 (2024-12-19)
* 新增:uniapp 支持百度小程序、抖音/头条小程序的 ID3。
* 百度小程序 SDK 、抖音/头条小程序的版本都是 v0.14.3
## 0.1.3 (2024-11-18)
* 新增:uniapp 支持 小红书 SDK。
* 小红书小程序 SDK 版本是 v0.14.3
## 0.1.2 (2023-2-1)
* 修改:去除了支持 Vue3 点击全埋点的支持说明。不建议使用这个方案,建议手动埋点。
## 0.1.1 (2023-12-27)
* 新增:获取 identities 和 resetAnonymousIdentity 接口。
* Web SDK 从 v1.24.13 更新到 v1.26.3
* 微信小程序 SDK 从 v1.18.4 更新到 v1.20.2
软件名称:神策分析 SDK
版本号:所有版本
许可协议版本:1.0
1. 商业许可协议(用于商业用途需购买许可)
任何商业用途必须获得商业许可。
商业许可协议条款:
- 商业用途:任何直接或间接产生收入的用途都需要购买商业许可。
- 付款条款:在使用本软件用于商业用途之前,您必须支付全额许可费用。具体的付款方式将在双方联系后提供。
- 商业支持:购买商业许可后,您将获得一年的技术支持和软件更新服务。
- 禁止再许可:商业用户不得再许可、转售或转让本软件。每份商业许可仅适用于单一实体或公司。
- 源代码访问:购买商业许可的用户将获得本软件的代码访问权限,并可根据业务需求进行内部修改。但不得公开发布或再分发修改后的版本。
- 使用范围限制:商业许可仅限于购买者的内部使用,不得与第三方共享或用于为第三方提供服务。任何超出许可范围的使用行为均需额外授权,并可能产生额外费用。
- 联系信息:如需购买商业许可,请联系 dv@sensorsdata.com。
- 知识产权声明:本软件的版权归神策网络科技(北京)有限公司所有。购买商业许可仅授予您使用权,所有权仍归属本公司。
- 终止条款: 如果您未支付相关费用或违反本协议的任何条款,商业许可将自动终止。您必须立即停止所有商业用途,并销毁或删除所有软件副本。
2. 附加授权规则条款
授权规则条款:
- 功能限制:未经本软件作者的明确书面许可,您不得移除、绕过或规避本软件中的任何功能限制或试用限制。
- 商标使用:未经授权,您不得在宣传、市场推广或销售产品时使用本软件的名称、商标或品牌标识。任何商标使用必须得到明确的书面许可。
- 修改条款:本协议的条款可能会不时更新,用户有责任定期检查最新版本。任何重大更改将通过项目主页或电子邮件通知用户。
3. 联系方式
如需更多信息或申请商业许可,请联系 dv@sensorsdata.com。
\ No newline at end of file
[![神策数据](https://opensource.sensorsdata.cn/wp-content/uploads/logo.png "神策数据")](https://www.sensorsdata.cn/)
<br><br>
[![License](https://img.shields.io/github/license/sensorsdata/sa-sdk-android.svg)](https://github.com/sensorsdata/sa-sdk-android/blob/master/LICENSE)
## 神策简介
[**神策数据**](https://www.sensorsdata.cn/)
(Sensors Data),隶属于神策网络科技(北京)有限公司,是一家专业的大数据分析服务公司,大数据分析行业开拓者,为客户提供深度用户行为分析平台、以及专业的咨询服务和行业解决方案,致力于帮助客户实现数据驱动。神策数据立足大数据及用户行为分析的技术与实践前沿,业务现已覆盖以互联网、金融、零售快消、高科技、制造等为代表的十多个主要行业、并可支持企业多个职能部门。公司总部在北京,并在上海、深圳、合肥、武汉等地拥有本地化的服务团队,覆盖东区及南区市场;公司拥有专业的服务团队,为客户提供一对一的客户服务。公司在大数据领域积累的核心关键技术,包括在海量数据采集、存储、清洗、分析挖掘、可视化、智能应用、安全与隐私保护等领域。 [**More**](https://www.sensorsdata.cn/about/aboutus.html)
## SDK 简介
一款支持 uni-app 项目进行埋点数据采集的 JS 插件,插件下载地址及使用教程见:[神策分析 JS 插件](https://ext.dcloud.net.cn/plugin?id=4177)
## 版本更新记录
请参见 [release 发版记录](https://github.com/sensorsdata/uni-app-sdk/releases)
## License
[License 协议](LICENSE)
\ No newline at end of file
/**
* uni-app sdk 公共方法
* 需要做类型检查,每个方法必须返回 true false,用来作为参数检查的结果
*/
let sa = {
// 提供扩展性
instance: null,
// 提供初始化和配置参数
init: () => {
console.log('common-api,当前平台不支持此方法 init');
},
setPara: () => {
/*
server_url:'setServerUrl' 字符串
show_log:'enableLog' 布尔
app_flush_network_policy:'setFlushNetworkPolicy'数字
app_flush_interval:'setFlushInterval'数字
app_flush_bulkSize:'setFlushBulkSize'数字
app_session_interval_time:'setSessionIntervalTime'数字
app_data_collect:'enableDataCollect'布尔
mp_auto_track: object
*/
console.log('common-api,当前平台不支持此方法 setPara');
},
// app专用的方法
getAppFlushInterval: () => {
console.log('common-api,当前平台不支持此方法 getAppFlushInterval');
},
getAppFlushBulkSize: () => {
console.log('common-api,当前平台不支持此方法 getAppFlushBulkSize');
},
getAppSessionIntervalTime: () => {
console.log('common-api,当前平台不支持此方法 getAppSessionIntervalTime');
},
trackAppInstall: () => {
console.log('common-api,当前平台不支持此方法 trackAppInstall');
},
appFlush: () => {
console.log('common-api,当前平台不支持此方法 appFlush');
},
removeTimer: () => {
console.log('common-api,当前平台不支持此方法 removeTimer');
},
trackTimerStart: () => {
console.log('common-api,当前平台不支持此方法 trackTimerStart');
},
trackTimerPause: () => {
console.log('common-api,当前平台不支持此方法 trackTimerPause');
},
trackTimerResume: () => {
console.log('common-api,当前平台不支持此方法 trackTimerResume');
},
trackTimerEnd: () => {
console.log('common-api,当前平台不支持此方法 trackTimerEnd');
},
clearTrackTimer: () => {
console.log('common-api,当前平台不支持此方法 clearTrackTimer');
},
trackViewScreen: () => {
console.log('common-api,当前平台不支持此方法 trackViewScreen');
},
getSuperProperties: () => {
console.log('common-api,当前平台不支持此方法 getSuperProperties');
},
enableTrackScreenOrientation: () => {
console.log('common-api,当前平台不支持此方法 enableTrackScreenOrientation');
},
resumeTrackScreenOrientation: () => {
console.log('common-api,当前平台不支持此方法 resumeTrackScreenOrientation');
},
stopTrackScreenOrientation: () => {
console.log('common-api,当前平台不支持此方法 stopTrackScreenOrientation');
},
getScreenOrientation: () => {
console.log('common-api,当前平台不支持此方法 getScreenOrientation');
},
profileUnsetPushId: () => {
console.log('common-api,当前平台不支持此方法 profileUnsetPushId');
},
profilePushId: () => {
console.log('common-api,当前平台不支持此方法 profilePushId');
},
enableDeepLinkInstallSource: () => {
console.log('common-api,当前平台不支持此方法 enableDeepLinkInstallSource');
},
trackDeepLinkLaunch: () => {
console.log('common-api,当前平台不支持此方法 trackDeepLinkLaunch');
},
// 各端通用的常用API
getDistinctID: () => {
console.log('common-api,当前平台不支持此方法 getDistinctID');
},
getAnonymousID: () => {
console.log('common-api,当前平台不支持此方法 getAnonymousID');
},
register: (para) => {
console.log('common-api,当前平台不支持此方法 register');
},
unRegister: () => {
console.log('common-api,当前平台不支持此方法 unRegister');
},
clearRegister: () => {
console.log('common-api,当前平台不支持此方法 clearRegister');
},
//各端通用的标准API
identify: () => {
console.log('common-api,当前平台不支持此方法 identify');
},
login: () => {
console.log('common-api,当前平台不支持此方法 login');
},
logout: () => {
console.log('common-api,当前平台不支持此方法 logout');
},
track: () => {
console.log('common-api,当前平台不支持此方法 track');
},
setProfile: () => {
console.log('common-api,当前平台不支持此方法 setProfile');
},
setOnceProfile: () => {
console.log('common-api,当前平台不支持此方法 setOnceProfile');
},
incrementProfile: () => {
console.log('common-api,当前平台不支持此方法 incrementProfile');
},
appendProfile: () => {
console.log('common-api,当前平台不支持此方法 appendProfile');
},
unsetProfile: () => {
console.log('common-api,当前平台不支持此方法 unsetProfile');
},
deleteProfile: () => {
console.log('common-api,当前平台不支持此方法 deleteProfile');
},
popupLoadSuccess: (callback) => {
console.log('common-api,当前平台不支持此方法 popupLoadSuccess');
},
popupClose: (callback) => {
console.log('common-api,当前平台不支持此方法 popupClose');
},
popupClick: (callback) => {
console.log('common-api,当前平台不支持此方法 popupClick');
},
popupLoadFailed: (callback) => {
console.log('common-api,当前平台不支持此方法 popupLoadFailed');
},
enablePopup: () => {
console.log('common-api,当前平台不支持此方法 enablePopup');
},
popupInit: () => {
console.log('common-api,当前平台不支持此方法 popupInit');
},
// ID-Mapping 3.0
bind: () => {
console.log('common-api,当前平台不支持此方法 bind');
},
unbind: () => {
console.log('common-api,当前平台不支持此方法 unbind');
},
loginWithKey: () => {
console.log('common-api,当前平台不支持此方法 loginWithKey');
},
resetAnonymousIdentity: () => {
console.log('common-api,当前平台不支持此方法 resetAnonymousIdentity');
},
getIdentities: () => {
console.log('common-api,当前平台不支持此方法 getIdentities');
},
// id3 微信专用
bindOpenid: () => {
console.log('common-api,当前平台不支持此方法 bindOpenid');
},
unbindOpenid: () => {
console.log('common-api,当前平台不支持此方法 unbindOpenid');
},
bindUnionid: () => {
console.log('common-api,当前平台不支持此方法 bindUnionid');
},
unbindUnionid: () => {
console.log('common-api,当前平台不支持此方法 unbindUnionid');
}
};
export default sa;
/*
* @Date: 2022-10-28 10:30:10
* @File:
*/
/**
* SensorsData uni-app SDK
* APP原生SDK所有API -> JS可用的所有API -> 各端通用的有限的桥API
* APP SDK(所有) -> JS 写的 SDK(所有) -> uni-app Bridge SDK(有限)
* 神策招聘前端后端运维分析师产品售前等职位,内推发送简历到 shengyonggen@sensorsdata.cn
*/
import commonAPI from './common-api'
// #ifdef APP-PLUS
import bridgeAPI from './middle/app.js'
// #endif
// #ifdef H5
import bridgeAPI from './middle/web.js'
// #endif
// #ifdef MP-WEIXIN
import bridgeAPI from './middle/weixin.js';
// #endif
// #ifdef MP-ALIPAY
import bridgeAPI from './middle/alipay.js';
// #endif
// #ifdef MP-BAIDU
import bridgeAPI from './middle/baidu.js';
// #endif
// #ifdef MP-TOUTIAO
import bridgeAPI from './middle/toutiao.js';
// #endif
// #ifdef MP-XHS
import bridgeAPI from './middle/xiaohongshu.js';
// #endif
import get_enableVue3MpClick from './vue3-mpclick';
let sa = {};
let lib_plugin_track_timer = 0;
let js_uniapp_version = 'js_uniapp:0.1.7';
//检查是否是支持的平台,如果不支持就使用commonAPI
if (typeof bridgeAPI === 'undefined') {
console.error('神策 uni-app SDK 不支持当前平台,数据不会发送');
sa = commonAPI;
} else {
sa = bridgeAPI;
/*
做一次common-api的遍历
如果bridgeAPI都实现了,就结束
如果bridgeAPI没有实现,从instance中获取,如果还没有就=common-api
*/
Object.keys(commonAPI).forEach((key) => {
if (!(key in bridgeAPI)) {
if (typeof bridgeAPI.instance === 'object' && typeof bridgeAPI.instance[key] === 'function') {
sa[key] = bridgeAPI.instance[key].bind(bridgeAPI.instance);
} else {
sa[key] = commonAPI[key].bind(commonAPI);
}
}
// 如果是track,先加属性
if (key === 'track') {
let oldTrack = sa.track;
sa.track = function () {
let arr = [].slice.call(arguments, 0);
if (++lib_plugin_track_timer === 1) {
if (typeof arr[1] === 'object' && arr[1] !== null) {
arr[1]['$lib_plugin_version'] = [js_uniapp_version];
} else {
arr[1] = {
$lib_plugin_version: [js_uniapp_version]
};
}
}
return oldTrack.apply(sa, arr);
};
}
});
}
const enableVue3MpClick = get_enableVue3MpClick(sa);
export default sa;
export { enableVue3MpClick };
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
!function(){var e=null,t=null,n={getVisibility:function(e){function t(e){var i=e.parentNode;if(9===i.nodeType)return!0;if("0"===n(e,"opacity")||"none"===n(e,"display")||"hidden"===n(e,"visibility"))return!1;if(i){var r=i.getBoundingClientRect();if("hidden"===n(i,"overflow")||"scroll"===n(i,"overflow")){if(o.bottom<=r.top||o.top>=r.bottom||o.right<=r.left||o.left>=r.right)return!1}else if("hidden"===n(i,"overflow-y")||"scroll"===n(i,"overflow-y")){if(o.bottom<=r.top||o.top>=r.bottom)return!1}else if(("hidden"===n(i,"overflow-x")||"scroll"===n(i,"overflow-x"))&&(o.right<=r.left||o.left>=r.right))return!1;return t(i)}return!0}function n(e,t){return window.getComputedStyle?document.defaultView.getComputedStyle(e,null)[t]:e.currentStyle?e.currentStyle[t]:void 0}function i(){var e=document.body.getBoundingClientRect();return!(o.top>=e.bottom||o.bottom<=e.top||o.left>=e.right||o.right<=e.left)}var o=e.getBoundingClientRect();return t(e)&&i(e)},getSubElements:function(t){var n=[];if(t.children.length)for(var i=0;i<t.children.length;i++)e.isElement(t.children[i])&&e.isObject(t.children[i].sensorsDefineStore)&&n.push(t.children[i].sensorsDefineStore.id);return n},getInfo:function(n){if(!e.isElement(n)||!e.isObject(n.sensorsDefineStore))return null;var i=n.getBoundingClientRect(),o=n.tagName,r={id:n.sensorsDefineStore.id,$element_content:e.getEleInfo({target:n}).$element_content,$element_selector:t.heatmap.getDomSelector(n),tagName:o,top:i.top,left:i.left,scrollX:window.pageXOffset,scrollY:window.pageYOffset,width:i.width,height:i.height,scale:window.devicePixelRatio,visibility:this.getVisibility(n),$url:location.href,$title:document.title,lib_version:t.lib_version,subelements:this.getSubElements(n),level:n.sensorsDefineStore.level,is_list_view:"li"===o.toLowerCase(),$element_path:t.heatmap.getElementPath(n,t.para.heatmap&&"not_use_id"===t.para.heatmap.element_selector)},l=t.heatmap.getElementPosition(n,r.$element_path,t.para.heatmap&&"not_use_id"===t.para.heatmap.element_selector);return e.isNumber(l)&&(r.$element_position=l),t.heatmap.getClosestLi(n)&&(r.list_selector=this.getListSelector(n)),e.isString(n.sensorsDefineStore.list_selector)&&(r.list_selector=n.sensorsDefineStore.list_selector),r},getZIndex:function(e){var t=window.getComputedStyle(e,null).getPropertyValue("z-index");return t&&!isNaN(+t)?t:0},getlevel:function(e,t){var n=Number(this.getZIndex(e)),i=0,o=window.getComputedStyle(e,null).getPropertyValue("position");return!o||"absolute"!==o&&"fixed"!==o||(i=1e5),t+n+i},getListSelector:function(e){var n="",i=t.heatmap.getClosestLi(e);if(i){var o=t.heatmap.getDomSelector(i,[],!0),r=t.heatmap.getDomSelector(e,[],!0);n=r.replace(o,"")}return n},initElements:function(){function n(e,n){var i={level:n,id:"h"+r};r++,e.sensorsDefineStore=i;var o=t.heatmap.getTargetElement(e);if(o){o.sensorsdata_enable_click=!0;var l=window.getComputedStyle(o,null).getPropertyValue("display");"inline"===l&&(o.style.display="inline-block")}}function i(t,r){for(var s=0;s<t.length;s++)if(e.isElement(t[s])){var a=t[s],f=o.getlevel(a,r);n(a,f),l.push(a),a.children&&i(a.children,f+1)}}var o=this,r=0,l=[];return i(document.body.children,1),l},getElementsInfo:function(){var t=this,n=[],i=[],o=this.initElements();return e.isArray(o)&&e.each(o,function(o){if(e.isElement(o)){var r=o,l=t.getInfo(r);e.isObject(l)&&l.visibility&&(r.sensorsdata_enable_click===!0?(l.enable_click=!0,n.push(l)):(l.enable_click=!1,i.push(l)))}}),{data:this.sortLevel(n),extra_elements:this.sortLevel(i)}},sortLevel:function(e){return e.sort(function(e,t){return e.level-t.level}),e},postDefineInfo:function(){var e=n.getElementsInfo(),i={data:e.data,extra_elements:e.extra_elements};new t.SDKJSBridge("visualized_track").notifyApp(i)},addDefineListener:function(n){function i(e,t,n){var i=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,o=new i(n);o.observe(e,t)}var o=this,r={childList:!0,subtree:!0,attributes:!0},l=function(){return e.throttle(n,1e3)}();i(document.body,r,l),e.addEvent(window,"scroll",l),e.addEvent(window,"resize",l),e.addEvent(window,"load",l),t.ee&&t.ee.spa&&t.ee.spa.on("switch",function(e){e!==location.href&&o.postPageInfo()})},postPageInfo:function(){var e={data:{$title:document.title,$url:location.href,lib_version:t.lib_version}};new t.SDKJSBridge("page_info").notifyApp(e)},init:function(){var n=this;window.sa_jssdk_app_define_mode=function(i,o){o?(n.postPageInfo(),n.postDefineInfo()):(t=i,e=t._,n.postPageInfo(),e.bindReady(function(){n.postDefineInfo(),n.addDefineListener(n.postDefineInfo)}))}}};n.init()}();
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
// 原生SDK提供的API
import sensors from '../jssdk/alipay.js';
var _ = sensors._;
// 提供各端一致的公共API
var isParaSet = false;
let sa = {
// 提供扩展性
instance: sensors,
// 提供初始化和配置参数
init: function (para) {
if (!isParaSet) {
sa.setPara(para);
}
sensors.init(para);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
},
setPara: (para) => {
para = para || {};
let defaultValue = {
autoTrack: false
};
Object.assign(defaultValue, para);
sensors.setPara.call(sensors, defaultValue);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
isParaSet = true;
},
// 各端通用的常用API
getDistinctID: sensors.store.getDistinctId.bind(sensors.store),
register: sensors.registerApp.bind(sensors),
clearRegister: () => {
console.log('web 中不支持此方法');
}
};
export default sa;
/*
* @Date: 2022-10-28 10:30:0
* @File:
*/
// 原生SDK提供的API,直接实现app对应的所有js的api,在这里再做一次bridge的api封装
let sensors = uni.requireNativePlugin('Sensorsdata-UniPlugin-App');
let cachePara = {};
let isInit = false;
let sa = {
// 提供扩展性
instance: sensors,
setPara: function (para) {
if (!isInit) {
cachePara = convertToInitSDKPara(para);
return;
}
// 初始化后,按旧有方式直接调用原生 API 进行设置
setParaAfterInitSDK(para);
},
init: function (para) {
if (!sensors.initSDK) {
console.log('原生插件未提供 initSDK 方法。');
return;
}
sensors.initSDK(deepMerge(cachePara, para));
isInit = true;
},
popupInit: sensors.popupInit.bind(sensors),
// app专用的方法
getAppFlushInterval: sensors.getFlushInterval.bind(sensors),
getAppFlushBulkSize: sensors.getFlushBulkSize.bind(sensors),
getAppSessionIntervalTime: sensors.getSessionIntervalTime.bind(sensors),
trackAppInstall: sensors.trackAppInstall.bind(sensors),
appFlush: sensors.flush.bind(sensors),
register: sensors.registerSuperProperties.bind(sensors),
unRegister: sensors.unregisterSuperProperty.bind(sensors),
clearRegister: sensors.clearSuperProperties.bind(sensors),
setProfile: sensors.profileSet.bind(sensors),
setOnceProfile: sensors.profileSetOnce.bind(sensors),
incrementProfile: sensors.profileIncrement.bind(sensors),
appendProfile: sensors.profileAppend.bind(sensors),
unsetProfile: sensors.profileUnset.bind(sensors),
deleteProfile: sensors.profileDelete.bind(sensors),
//
clearTrackTimer: sensors.clearTrackTimer.bind(sensors),
resumeTrackScreenOrientation: sensors.resumeTrackScreenOrientation.bind(sensors),
stopTrackScreenOrientation: sensors.stopTrackScreenOrientation.bind(sensors),
getScreenOrientation: sensors.getScreenOrientation.bind(sensors),
getSuperProperties: sensors.getSuperProperties.bind(sensors),
profileUnsetPushId: (pushKey = '') => {
sensors.profileUnsetPushId.call(sensors, pushKey)
},
profilePushId: (pushKey = '', pushId = '') => {
sensors.profilePushId.call(sensors, pushKey, pushId)
},
enableTrackScreenOrientation: (enable = false) => {
sensors.enableTrackScreenOrientation.call(sensors, enable)
},
trackViewScreen: (url = '', properties = {}) => {
sensors.trackViewScreen.call(sensors, url, properties)
},
trackTimerEnd: (eventName = '', properties = {}) => {
sensors.trackTimerEnd.call(sensors, eventName, properties)
},
trackTimerResume: (eventName = '') => {
sensors.trackTimerResume.call(sensors, eventName)
},
trackTimerPause: (eventName = '') => {
sensors.trackTimerPause.call(sensors, eventName)
},
trackTimerStart: (eventName = '') => {
return sensors.trackTimerStart.call(sensors, eventName)
},
removeTimer: (eventName = '') => {
sensors.removeTimer.call(sensors, eventName)
},
enableDeepLinkInstallSource: (enable = false) => {
sensors.enableDeepLinkInstallSource.call(sensors, enable);
},
trackDeepLinkLaunch: (deepLinkUrl = '', oaid = '') => {
sensors.trackDeepLinkLaunch.call(sensors, deepLinkUrl, oaid);
},
getIdentities: () => {
return sensors.getIdentities.call(sensors);
},
resetAnonymousIdentity: (identity = '') => {
sensors.resetAnonymousIdentity.call(sensors, identity);
},
//
popupLoadSuccess: (callback) => {
sensors.popupLoadSuccess(callback);
},
popupClose: (callback) => {
sensors.popupClose(callback);
},
popupClick: (callback) => {
sensors.popupClick(callback);
},
popupLoadFailed: (callback) => {
sensors.popupLoadFailed(callback);
},
enablePopup: () => {
sensors.enablePopup();
}
};
// 将老的 setPara 转换为新的 initSDK 支持的格式
function convertToInitSDKPara(para) {
para.app = para.app || {};
Object.keys(para).forEach(
(key) => {
switch (key) {
case 'app_flush_network_policy':
para.app.flush_network_policy = para[key];
delete para[key];
break;
case 'app_flush_interval':
para.app.flush_interval = para[key];
delete para[key];
break;
case 'app_flush_bulkSize':
para.app.flush_bulkSize = para[key];
delete para[key];
break;
case 'app_session_interval_time':
para.app.android = para.app.android || {};
para.app.android.session_interval_time = para[key];
delete para[key];
break;
default: break;
}
}
);
return para;
}
// 原有的 setPara 逻辑,初始化后调用 setPara 只有老的 SDK 支持,还是按老的方式调用
function setParaAfterInitSDK(para) {
if (typeof para !== 'object') {
console.log('setPara 的参数必须是 object');
return false;
}
var relation = {
server_url: 'setServerUrl',
show_log: 'enableLog',
app_flush_network_policy: 'setFlushNetworkPolicy',
app_flush_interval: 'setFlushInterval',
app_flush_bulkSize: 'setFlushBulkSize',
app_session_interval_time: 'setSessionIntervalTime',
app_data_collect: 'enableDataCollect'
};
Object.keys(para).forEach(
(key) => {
if (key in relation && typeof sensors[relation[key]] === 'function') {
if (key === 'app_data_collect') {
if (para[key] === true) {
sensors[relation[key]].call(sensors, para[key]);
}
} else {
sensors[relation[key]].call(sensors, para[key]);
}
} else {
console.log('setPara 在 App 中不支持设置' + key);
}
}
);
}
function deepMerge(target, source) {
try {
var merged = new Map();
if (!target) {
return source;
}
if (!source) {
return target;
}
function merge(t, s) {
for (var k in s) {
if (isObject(t[k]) && isObject(s[k]) && !merged.has(s[k])) {
merged.set(s[k], 1);
merge(t[k], s[k]);
} else {
t[k] = s[k];
}
}
}
function isObject(arg) {
return Object.prototype.toString.call(arg) == '[object Object]' && arg !== null;
}
merge(target, source);
} catch (e) {
return source || target;
}
return target;
}
export default sa;
// 原生SDK提供的API
import sensors from '../jssdk/baidu.js';
var _ = sensors._;
// 提供各端一致的公共API
var isParaSet = false;
let sa = {
// 提供扩展性
instance: sensors,
// 提供初始化和配置参数
init: function (para) {
if (!isParaSet) {
sa.setPara(para);
}
sensors.init(para);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
},
setPara: (para) => {
para = para || {};
let defaultValue = {
autoTrack: false
};
Object.assign(defaultValue, para);
sensors.setPara.call(sensors, defaultValue);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
isParaSet = true;
},
// 各端通用的常用API
getDistinctID: sensors.store.getDistinctId.bind(sensors.store),
register: sensors.registerApp.bind(sensors),
clearRegister: () => {
console.log('web 中不支持此方法');
}
};
export default sa;
// 原生SDK提供的API
import sensors from '../jssdk/toutiao.js';
var _ = sensors._;
// 提供各端一致的公共API
var isParaSet = false;
let sa = {
// 提供扩展性
instance: sensors,
// 提供初始化和配置参数
init: function (para) {
if (!isParaSet) {
sa.setPara(para);
}
sensors.init(para);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
},
setPara: (para) => {
para = para || {};
let defaultValue = {
autoTrack: false
};
Object.assign(defaultValue, para);
sensors.setPara.call(sensors, defaultValue);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
isParaSet = true;
},
// 各端通用的常用API
getDistinctID: sensors.store.getDistinctId.bind(sensors.store),
register: sensors.registerApp.bind(sensors),
clearRegister: () => {
console.log('web 中不支持此方法');
}
};
export default sa;
// 原生SDK提供的API
import sensors from '../jssdk/web.js';
import mobilePopups from "../plugin/mb-popup.esm.min"
import webPopups from "../plugin/web-popup.esm.min"
// 提供各端一致的公共API
const systemInfo = uni.getSystemInfoSync();
let popups = mobilePopups;
let sa = {
// 提供扩展性
instance: sensors,
// 提供初始化和配置参数
init: (para) => {
para = para || sa.para;
let defaultValue = {
is_track_single_page: true
};
Object.assign(defaultValue, para);
sensors.init.call(sensors, defaultValue);
var _ = sensors._;
if (para && _.isObject(para.global_properties)) {
sensors.registerPage(para.global_properties);
}
},
//弹窗初始化
popupInit: (para) => {
if (typeof para === "object" && para !== null) {
if (systemInfo.screenWidth > 1024) {
sensors.use('WebPopup', para);
popups = webPopups;
} else {
sensors.use('Popup', para);
}
}
},
setPara: (para) => {
if (typeof para === 'object') {
sa.para = para;
}
},
// 各端通用的常用API
getDistinctID: sensors.store.getDistinctId.bind(sensors.store),
getAnonymousID: () => {
return sensors.quick('getAnonymousID');
},
// 获取 ID-Mapping 3.0 绑定信息
getIdentities: () => {
return sensors.getPresetProperties() && sensors.getPresetProperties().identities;
},
register: sensors.registerPage.bind(sensors),
clearRegister: () => {
console.log('web 中不支持此方法 - clearRegister');
},
quick: (event, para) => {
sensors.quick(event, para);
},
popupLoadSuccess: (callback) => {
if (popups.info.supportCustom && popups.info.supportCustom === 'withoutCampaignListener') {
popups.info.supportCustom = '';
};
if (popups.info && popups.info.popup_campaign_listener) {
popups.info.popup_campaign_listener.onStart = callback;
};
},
popupClose: (callback) => {
if (popups.info && popups.info.popup_campaign_listener) {
popups.info.popup_campaign_listener.onEnd = callback;
};
},
popupClick: (callback) => {
if (systemInfo.screenWidth <= 1024) {
if (popups.info && popups.info.popup_listener) {
popups.info.popup_listener.onClick = callback;
};
} else {
console.log('web 中不支持此方法 - popupClick 方法');
}
},
popupLoadFailed: (callback) => {
if (popups.info && popups.info.popup_campaign_listener) {
popups.info.popup_campaign_listener.onFailed = callback;
};
}
};
export default sa;
\ No newline at end of file
// 原生SDK提供的API
import sensors from '../jssdk/weixin.js';
import popups from '../plugin/wx-popup.esm.min';
var isParaSet = false;
var _ = sensors._;
// 提供各端一致的公共API
let sa = {
// 提供扩展性
instance: sensors,
// 提供初始化和配置参数
init: function (para) {
if (!isParaSet) {
sa.setPara(para);
}
sensors.init(para);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
},
//弹窗初始化
popupInit: (para) => {
if (typeof para === "object" && para !== null) {
sensors.usePlugin(popups, para);
}
},
setPara: (para) => {
para = para || {};
let defaultValue = {
autoTrack: false
};
Object.assign(defaultValue, para);
sensors.setPara.call(sensors, defaultValue);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
isParaSet = true;
},
// 各端通用的常用API
getDistinctID: sensors.store.getDistinctId.bind(sensors.store),
register: sensors.registerApp.bind(sensors),
// 有这个方法但是效果不同的话,需要覆盖一下
clearRegister: () => {
console.log('web 中不支持此方法');
},
popupLoadSuccess: (callback) => {
if (popups.CAMPAIGN_ERROR && popups.CAMPAIGN_ERROR['onStart']) {
delete popups.CAMPAIGN_ERROR['onStart']
};
popups.campaign_listener.onStart = callback;
},
popupClose: (callback) => {
if (popups.CAMPAIGN_ERROR && popups.CAMPAIGN_ERROR['onEnd']) {
delete popups.CAMPAIGN_ERROR['onEnd']
};
popups.campaign_listener.onEnd = callback;
},
popupClick: (callback) => {
popups.info.popup_listener.onClick = callback;
},
popupLoadFailed: (callback) => {
if (popups.CAMPAIGN_ERROR && popups.CAMPAIGN_ERROR['onFailed']) {
delete popups.CAMPAIGN_ERROR['onFailed']
};
popups.campaign_listener.onFailed = callback;
}
};
export default sa;
// 原生SDK提供的API
import sensors from '../jssdk/xiaohongshu.js';
var _ = sensors._;
// 提供各端一致的公共API
var isParaSet = false;
let sa = {
// 提供扩展性
instance: sensors,
// 提供初始化和配置参数
init: function (para) {
if (!isParaSet) {
sa.setPara(para);
}
sensors.init(para);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
},
setPara: (para) => {
para = para || {};
let defaultValue = {
autoTrack: false
};
Object.assign(defaultValue, para);
sensors.setPara.call(sensors, defaultValue);
if (para && _.isObject(para.global_properties)) {
sensors.registerApp(para.global_properties);
}
isParaSet = true;
},
// 各端通用的常用API
getDistinctID: sensors.store.getDistinctId.bind(sensors.store),
register: sensors.registerApp.bind(sensors),
clearRegister: () => {
console.log('web 中不支持此方法');
}
};
export default sa;
{
"id": "Sensorsdata-UniPlugin-JS",
"name": "神策分析 JS 插件",
"displayName": "神策分析 JS 插件",
"version": "0.1.7",
"description": "神策分析通用 JS SDK",
"keywords": [
"SensorsData",
"SensorsAnalytics",
"神策数据",
"神策分析",
"神策智能运营"
],
"dcloudext": {
"type": "js_sdk",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
}
},
"uni_modules": {
"dependencies": [],
"encrypt": []
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
export default function get_enableVue3MpClick(sensors) {
var sa = sensors.instance;
var _ = sa._;
return function enableVue3MpClick() {
// #ifdef VUE3
// #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-JD || MP-KUAISHOU || MP-QQ || MP-LARK
var platform;
// #ifdef MP-WEIXIN
platform = wx
// #endif
// #ifdef MP-BAIDU
platform = swan
// #endif
// #ifdef MP-ALIPAY
platform = my
// #endif
// #ifdef MP-TOUTIAO
platform = tt
// #endif
// #ifdef MP-JD
platform = jd
// #endif
// #ifdef MP-KUAISHOU
platform = ks
// #endif
// #ifdef MP-QQ
platform = qq
// #endif
// #ifdef MP-LARK
platform = tt
// #endif
var oldCreatePage = platform.createPage;
if (_.isFunction(oldCreatePage)) {
platform.createPage = function (options) {
mutateOptions(options)
return oldCreatePage.call(platform, options);
}
}
var oldCreateComponent = platform.createComponent;
if (_.isFunction(oldCreateComponent)) {
platform.createComponent = function (options) {
mutateOptions(options)
return oldCreateComponent.call(platform, options);
}
}
function mutateOptions(options) {
if (!_.isObject(options)) return;
if (_.isFunction(options.render)) {
var oldRender = options.render;
options.render = function (_ctx, _cache, $props, $setup, $data, $options) {
var instance = _ctx && _ctx.$scope;
var bindingConfig = oldRender.call(options, _ctx, _cache, $props, $setup, $data, $options);
addMPClick(instance, bindingConfig);
return bindingConfig;
}
} else if (_.isFunction(options.setup)) {
var oldSetup = options.setup;
options.setup = function (_props, _defines) {
var oldRender = oldSetup.call(options, _props, _defines);
return function render(_ctx, _cache) {
var instance = _ctx && _ctx.$scope;
var bindingConfig = oldRender.call(options, _ctx, _cache);
addMPClick(instance, bindingConfig);
return bindingConfig;
}
}
}
}
function addMPClick(instance, bindingConfig) {
if (_.isObject(instance) && _.isObject(bindingConfig)) {
var propKeys = getPropKeys(bindingConfig, [], false);
propKeys.forEach(function (propKey) {
var invoker = instance[propKey];
if (_.isFunction(invoker) && _.isFunction(invoker.value) && !invoker.value.__MPClickFlag) {
var oldValue = invoker.value;
invoker.value = function (event) {
if (sa.para.autoTrack && sa.para.autoTrack.mpClick) {
clickTrack(event);
}
return oldValue.call(instance, event)
}
invoker.value.__MPClickFlag = true;
}
});
}
}
function getPropKeys(config, dest, inner = false) {
if (!_.isArray(dest)) dest = [];
if (_.isArray(config)) {
config.forEach(function (item) {
getPropKeys(item, dest, true);
});
} else if (_.isObject(config)) {
Object.values(config).forEach(function (item) {
if (!!item) {
if (_.isString(item) && item.startsWith('e') && (!inner || item.includes('_'))) {
dest.push(item);
} else if (_.isArray(item)) {
getPropKeys(item, dest, true);
}
}
});
}
return dest;
}
function clickTrack(events) {
if (_.isUndefined(events)) events = {};
var prop = {};
var event_prop = _.isObject(events.event_prop) ? events.event_prop : {};
var type = events['type'];
var current_target = events.currentTarget || {};
var dataset = current_target.dataset || {};
prop['$element_id'] = current_target.id;
prop['$element_type'] = dataset['type'];
prop['$element_content'] = dataset['content'];
prop['$element_name'] = dataset['name'];
prop['$url_path'] = _.getCurrentPath();
if (type && isClick(type)) {
if (sa.para.preset_events && sa.para.preset_events.collect_element && sa.para.preset_events.collect_element(events) === false) {
return false;
}
prop = _.extend(prop, event_prop);
sensors.track('$MPClick', prop);
}
}
function isClick(type) {
var mp_taps = {
tap: 1,
longpress: 1,
longtap: 1
};
return !!mp_taps[type];
}
// #endif
// #endif
}
}
\ No newline at end of file
var sensors=getApp().sensors;Component({options:{multipleSlots:!0},lifetimes:{attached:function(){sensors.popupEmitter.attached()}},properties:{},data:{flag:!0,isShow:!1,template:{},image_list:[],plan_obj:{}},methods:{loadImage:function(t){if(t&&t.length>0){var e=[].concat(this.image_list,t);this.setData({image_list:e})}},handle:function(t){return!!this.data.flag&&(t.popupTree||t.popupTree.properties?(this.setData({plan_obj:t}),this.setData({template:t.popupTree}),void(this.data.flag&&(this.setData({isShow:!0}),this.showPopup()))):(this.popupFail(1001),!1))},popupFail(t){var e={$sf_succeed:!1};e.fail_code=t,e.$sf_fail_reason={1000:"图片加载失败",1001:"预览信息解析失败,请检查计划配置",2000:"对照组"}[t];var a=this.data.plan_obj;a.props=e,2e3!==t&&sensors.events.emit("popup_load_fail",a),sensors.events.emit("popup_end",this.data.plan_obj)},clickMask:function(){if(this.data.template.properties.maskCloseEnabled){var t={};t.$sf_msg_action_id=this.data.template.properties.maskActionId,t.$sf_close_type="POPUP_CLOSE_MASK",t.$sf_msg_element_type="mask";var e=this.data.plan_obj;e.props=t,sensors.events.emit("popup_click",e),this.hidePopup()}},hidePopup:function(){this.setData({flag:!0}),this.setData({isShow:!1}),sensors.events.emit("popup_end",this.data.plan_obj)},showPopup(){this.setData({flag:!1});var t=this.data.plan_obj;sensors.events.emit("popup_display",t)},tapContent(){console.log("点击了弹窗窗体")},topCloseButton(){var t=this.data.template.image_button;t.$sf_close_type||(t.$sf_close_type="POPUP_CLOSE_TOPRIGHT"),this.popupCLick(t)},buttomCloseButton(){var t=this.data.template.image_button;t.$sf_close_type||(t.$sf_close_type="POPUP_CLOSE_BOTTOM"),this.popupCLick(t)},clickImage(){var t=this.data.template.img;t.$sf_close_type||(t.$sf_close_type="POPUP_CLOSE_BUTTON"),this.popupCLick(t)},buttonFirst(){var t=this.data.template.button[0];"close"!==t.action_type||t.$sf_close_type||(t.$sf_close_type="POPUP_CLOSE_BUTTON"),this.popupCLick(t)},buttonSecond(){var t=this.data.template.button[1];"close"!==t.action_type||t.$sf_close_type||(t.$sf_close_type="POPUP_CLOSE_BUTTON"),this.popupCLick(t)},popupCLick(t){var e={};switch(e.$sf_msg_element_type=t.type,e.$sf_msg_element_content=t.innerText,e.$sf_msg_action_id=t.id,e.action_value=t.value,e.$sf_msg_element_action=t.action_type,e.$sf_close_type=t.$sf_close_type,t.action_type){case"copy":wx.setClipboardData({data:t.value,success(t){console.log("复制文本成功")}});break;case"navigateTo":var a={path:t.path};this.navigatePage(a);break;case"navigateToMiniProgram":a={path:t.path,appid:t.appid};this.navigateMini(a)}var s=this.data.plan_obj;s.props=e,sensors.events.emit("popup_click",s),t.closeable&&this.hidePopup()},navigatePage(t){wx.navigateTo({url:t.path,success:function(){console.log("navigate success")},fail:function(t){console.log("navigate fail: ",t)}})},navigateMini(t){wx.navigateToMiniProgram({appId:t.appid,path:t.path,success(){console.log("navigate success")},fail(t){console.log("navigate fail: ",t)}})}}});
\ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<view
catchtap="clickMask"
class="wx-popup"
hidden="{{flag}}"
style="background: {{template.properties.maskColor}}"
>
<view wx:if="{{isShow}}" class='popup-container' catchtap="tapContent">
<view
wx:if="{{template.image_button.aligin === 'right'}}" class="close_btn-right">
<image
class="close_btn"
catchtap="topCloseButton"
src="{{template.image_button.src}}">
</image>
</view>
<image wx:if="{{!template.diverseModule && template.img}}"
class ='content-image'
style="{{template.img.style}}"
catchtap="clickImage"
src="{{template.img.src?template.img.src:''}}"
>
</image>
<view
wx:if="{{template.diverseModule}}"
class="popup-content"
style="{{template.view.content.style}}"
>
<image
wx:if="{{template.img && template.img.src}}"
class ='content-image'
style="{{template.img.style}}"
src="{{template.img.src}}">
</image>
<view wx:if="{{template.view.padding}}" style="{{template.view.padding.style}}"></view>
<text wx:if="{{template.title}}"
class="content-title"
style="{{template.title.style}}">{{template.title.innerText}}
</text>
<text wx:if="{{template.content}}"
class="content-content"
style="{{template.content.style}}">{{template.content.innerText}}
</text>
<!-- 按钮模块 -->
<view
wx:if="{{template.button && template.button.length > 0}}"
class="{{ template.view.button.type === 'column' ? 'popup-btn_column' : 'popup-btn_row'}} "
style="{{template.view.button.style}}">
<view wx:if="{{template.button[0].type === 'button'}}"
class="{{ template.view.button.type === 'column' ? 'popup-btn-button_column' : 'popup-btn-button_row'}}"
style="{{template.button[0].style}}"
catchtap="buttonFirst">{{template.button[0].innerText}}
</view>
<image wx:if="{{template.button[0].type === 'image_button'}}"
class="{{ template.view.button.type === 'column' ? 'popup-btn-img_column' : 'popup-btn-img_row'}}"
style="{{template.button[0].style}}"
src="{{template.button[0].src}}"
catchtap="buttonFirst">
</image>
<view wx:if="{{template.button[0].type === 'link'}}"
class="{{ template.view.button.type === 'column' ? 'popup-btn-linker_column' : 'popup-btn-linker_row'}}"
style="{{template.button[0].style}}" catchtap="buttonFirst">{{template.button[0].innerText}}
</view>
<view wx:if="{{template.button[1].type === 'button'}}"
class="{{template.view.button.type === 'column' ? 'popup-btn-button_column popup-btn-second_column' : 'popup-btn-button_row popup-btn-second_row'}}"
style="{{template.button[1].style}}"
catchtap='buttonSecond'>{{template.button[1].innerText}}
</view>
<image wx:if="{{template.button[1].type === 'image_button'}}"
class="{{ template.view.button.type === 'column' ? 'popup-btn-img_column popup-btn-second_column' : 'popup-btn-img_row popup-btn-second_row'}}"
style="{{template.button[1].style}}"
src="{{template.button[1].src}}"
catchtap='buttonSecond'>
</image>
<view wx:if="{{template.button[1].type === 'link'}}"
class="{{ template.view.button.type === 'column' ? 'popup-btn-linker_column' : 'popup-btn-linker_row'}}"
style="{{template.button[1].style}}"
catchtap='buttonSecond'>{{template.button[1].innerText}}
</view>
</view>
</view>
<view
wx:if="{{template.image_button.aligin === 'center'}}" class="close_btn-center">
<image
catchtap="buttomCloseButton"
class="close_btn"
src="{{template.image_button.src}}">
</image>
</view>
</view>
<view wx:for="{{image_list}}" wx:key="index" hidden="{{true}}">
<image src="{{image_list[index]}}"></image>
</view>
</view>
......@@ -2,6 +2,35 @@ import App from "./App";
// import apiRequest from "@/api/request.js";
import * as Pinia from 'pinia';
import sensors, {
enableVue3MpClick,
} from "./js_sdk/Sensorsdata-UniPlugin-JS/index";
const SENSORS_URL = "https://sensors.feihe.com/sa?project=XMH_Content";
sensors.setPara({
name: "sensors",
server_url: SENSORS_URL,
show_log: true,
autoTrack: {
appLaunch: true, // 默认为 true,false 则关闭 $MPLaunch 事件采集
appShow: true, // 默认为 true,false 则关闭 $MPShow 事件采集
appHide: true, // 默认为 true,false 则关闭 $MPHide 事件采集
pageShow: true, // 默认为 true,false 则关闭 $MPViewScreen 事件采集
pageShare: true, // 默认为 true,false 则关闭 $MPShare 事件采集
mpClick: true, // 默认为 false,true 则开启 $MPClick 事件采集
mpFavorite: true, // 默认为 true,false 则关闭 $MPAddFavorites 事件采集
pageLeave: true, // 默认为 false, true 则开启 $MPPageLeave事件采集
},
});
enableVue3MpClick();
sensors.init();
// const BASE_URL = 'https://duiba.oss-cn-hangzhou.aliyuncs.com/fh/';
// const BASE_URL = 'https://firmus-member-test-1253290912.cos.ap-beijing.myqcloud.com/xmh-mini-program/';
const BASE_URL = 'https://course.feihe.com/momclub-picture/';
......@@ -12,9 +41,16 @@ import "./uni.promisify.adaptor";
// 全局挂载后使用
// Vue.prototype.$api = apiRequest.api;
Vue.prototype.$baseUrl = BASE_URL;
Vue.prototype.$sensors = sensors;
Vue.config.productionTip = false;
App.mpType = "app";
......@@ -32,6 +68,7 @@ export function createApp() {
app.use(Pinia.createPinia());
// app.config.globalProperties.$api = apiRequest.api;
app.config.globalProperties.$baseUrl = BASE_URL;
app.config.globalProperties.$sensors = sensors;
return {
app,
Pinia
......
......@@ -111,16 +111,14 @@
<!-- 普通弹窗 -->
<uni-popup :is-mask-click="false" :safe-area="false" ref="popup" background-color="#fff"
border-radius="48rpx">
<view v-if="this.popupIndex !== 3" class="popup-content">
<view v-if="this.popupIndex !== 3 && this.qrInfoList && this.qrInfoList[this.popupIndex]" class="popup-content">
<image class="btnclose" @tap="closePop" :src="$baseUrl + 'homepage/btnclose.png'"></image>
<view class="title">
{{ this.qrInfoList[this.popupIndex].title }}
{{ this.qrInfoList[this.popupIndex]?.title || '' }}
</view>
<rich-text class="desc" :nodes="this.qrInfoList[this.popupIndex].desc">
</rich-text>
<image :show-menu-by-longpress="true" class="qrcode" :src="$baseUrl + this.qrInfoList[this.popupIndex].qrUrl"></image>
<image @tap="downloadHandler($baseUrl + this.qrInfoList[this.popupIndex].qrUrl)" class="btndownload"
<rich-text class="desc" :nodes="this.qrInfoList[this.popupIndex]?.desc || ''"></rich-text>
<image :show-menu-by-longpress="true" class="qrcode" :src="$baseUrl + (this.qrInfoList[this.popupIndex]?.qrUrl || '')"></image>
<image @tap="downloadHandler($baseUrl + (this.qrInfoList[this.popupIndex]?.qrUrl || ''))" class="btndownload"
:src="$baseUrl + 'homepage/btn_download.png'"></image>
</view>
<view v-else class="popup-content" style="height: 977rpx;">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment