pageInfo.uts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. import { OnLaunchOptionsWithCst, RouteParams, StatDefault, ReportErrorCode } from '../../interface.uts'
  2. import { STAT_VERSION, sys, device, sysAppBase, Config } from '../config.uts'
  3. // import Config from '../config.uts'
  4. import { get_time } from './pageTime.uts'
  5. import { dbGet, dbSet } from './db.uts'
  6. import { Serialize, IsNumber } from './index.uts'
  7. const APPID = sys.appId
  8. const RUNTIME_VERSION = sys.appVersion
  9. /**
  10. * 获取uuid
  11. */
  12. export const get_uuid = () : string => {
  13. // 有可能不存在 deviceId(一般不存在就是出bug了),就自己生成一个
  14. // 目前 deviceId 肯定存在所以不用生成
  15. // const uuid : string = sys.deviceId ?? getUuid()
  16. return sys.deviceId
  17. }
  18. /**
  19. * 获取老版的 deviceid ,兼容以前的错误 deviceid
  20. */
  21. export const get_odid = () : string => {
  22. // let odid : string
  23. // if (get_platform_name() === 'n') {
  24. // try {
  25. // odid = plus.device.uuid
  26. // } catch (e) {
  27. // odid = ''
  28. // }
  29. // return odid
  30. // }
  31. // odid = sys.deviceId ?? getUuid()
  32. // TODO 需要获取老版本的uuid ,目前无法获取,只返回 deviceId
  33. return sys.deviceId
  34. }
  35. /**
  36. * 获取当前平台
  37. * 移动端 : 'n',
  38. * h5 : 'h5',
  39. * 微信 : 'wx',
  40. * 阿里 : 'ali',
  41. * 百度 : 'bd',
  42. * 头条 : 'tt',
  43. * qq : 'qq',
  44. * 快应用 : 'qn',
  45. * 快手 : 'ks',
  46. * 飞书 : 'lark',
  47. * 快应用 : 'qw',
  48. * 钉钉 : 'dt'
  49. */
  50. export const get_platform_name = () : string => {
  51. let platformList = {
  52. 'app': 'n',
  53. 'app-plus': 'n',
  54. 'h5': 'h5',
  55. 'web': 'web',
  56. 'mp-weixin': 'wx',
  57. 'mp-baidu': 'bd',
  58. 'mp-toutiao': 'tt',
  59. 'mp-qq': 'qq',
  60. 'quickapp-native': 'qn',
  61. 'mp-kuaishou': 'ks',
  62. 'mp-lark': 'lark',
  63. 'quickapp-webview': 'qw',
  64. }
  65. // 苹果审核代码中禁止出现 alipay 字样 ,需要特殊处理一下
  66. const aliArr = ['y', 'a', 'p', 'mp-ali']
  67. const aliKey = aliArr.reverse().join('')
  68. platformList[aliKey] = 'ali'
  69. const platform = sys.uniPlatform
  70. // TODO 兼容子平台
  71. // if (platformList[process.env.VUE_APP_PLATFORM] === 'ali') {
  72. // if (my && my.env) {
  73. // const clientName = my.env.clientName
  74. // if (clientName === 'ap') return 'ali'
  75. // if (clientName === 'dingtalk') return 'dt'
  76. // // TODO 缺少 ali 下的其他平台
  77. // }
  78. // }
  79. return platformList[platform] as string
  80. }
  81. /**
  82. * 获取原生包名,或小程序 appid
  83. */
  84. export const get_pack_name = () : string => {
  85. let packName = ''
  86. if (get_platform_name() === 'n') {
  87. if (sys.osName == 'android') {
  88. packName = sysAppBase.packageName ?? ''
  89. }
  90. if (sys.osName == 'ios') {
  91. packName = sysAppBase.bundleId ?? ''
  92. }
  93. }
  94. return packName
  95. }
  96. /**
  97. * 应用版本
  98. */
  99. export const get_version = () : string => {
  100. return RUNTIME_VERSION
  101. }
  102. /**
  103. * 获取渠道
  104. */
  105. export const get_channel = () : string => {
  106. const platformName = get_platform_name()
  107. let channel : string = ''
  108. if (platformName === 'n') {
  109. channel = sysAppBase.channel ?? ''
  110. }
  111. // if (platformName === 'wx') {
  112. // // TODO 需要调研小程序二维码渠道如何获取;
  113. // }
  114. return channel
  115. }
  116. /**
  117. * 获取小程序场景值
  118. */
  119. export const get_scene = (options : OnLaunchOptionsWithCst) : number => {
  120. // const platformName = get_platform_name()
  121. let scene = 1001
  122. if (options.scene != null) {
  123. return options.scene ?? 1001
  124. }
  125. // if (platformName == 'wx') {
  126. // // @ts-ignore
  127. // scene = uni.getLaunchOptionsSync()?.scene ?? 1001
  128. // }
  129. return scene
  130. }
  131. /**
  132. * 是否获取 page 页面
  133. * @param {VueComponent} appInstance 页面实例
  134. */
  135. // @ts-ignore
  136. export const is_page = (appInstance : ComponentPublicInstance) : Boolean => {
  137. // #ifdef WEB || APP-IOS || MP-WEIXIN
  138. const type = appInstance?.$mpType ?? 'page'
  139. return type == 'page' ? true : false
  140. // #endif
  141. // #ifndef WEB || APP-IOS || MP-WEIXIN
  142. // 其他平台没有 $mpType ,只有页面触发
  143. return true
  144. // #endif
  145. }
  146. /**
  147. * 获取页面标题
  148. * @param {String} routepath 页面路由
  149. */
  150. export const get_page_name = (routepath : string) : string => {
  151. let page = get_page_vm()
  152. if (page == null) return ''
  153. let route : string
  154. // #ifdef MP-WEIXIN
  155. route = (page.$scope && page.$scope.route) ?? ""
  156. // #endif
  157. // #ifndef MP-WEIXIN
  158. route = page.route
  159. // #endif
  160. if (route != routepath) {
  161. const pages = getCurrentPages()
  162. // 如果传入路由与当前页面不同,则从页面栈找一个,如果找不到返回空
  163. let page_now = pages.find((p) : boolean => p.route == routepath)
  164. if (page_now == null) {
  165. return ''
  166. }
  167. // @ts-ignore
  168. page = page_now.vm!
  169. }
  170. let titleText : string
  171. // #ifdef MP-WEIXIN
  172. // @ts-ignore
  173. const title_json = process.env.UNI_STAT_TITLE_JSON
  174. titleText = title_json[route] ?? ''
  175. // #endif
  176. // #ifndef MP-WEIXIN
  177. // @ts-ignore
  178. const pageStyle = (page.$page as UniPage).getPageStyle()
  179. titleText = (pageStyle['navigationBarTitleText'] as string)
  180. // #endif
  181. return titleText as string
  182. }
  183. /**
  184. * 获取页面实例
  185. */
  186. export const get_page_vm = () : Page | null => {
  187. let pages = getCurrentPages()
  188. if (pages.length == 0) {
  189. return null
  190. }
  191. let page = pages[pages.length - 1]
  192. // TODO 正常来说,调用当前方法的地方只在 生命周期内,数组内最少会有一个页面,所以理论上是不存在获取不到的情况的
  193. // @ts-ignore
  194. return page.vm
  195. }
  196. /**
  197. * 获取页面url,不包含参数
  198. * @param {ComponentPublicInstance} page 页面实例
  199. */
  200. export function get_route(page : Page | null = null) : RouteParams {
  201. let _self = page ?? get_page_vm()
  202. if (_self == null) {
  203. const data : RouteParams = {
  204. path: '',
  205. fullpath: ''
  206. }
  207. return data
  208. }
  209. let url_params : string
  210. let options : any
  211. // #ifdef MP-WEIXIN
  212. options = _self.$scope.options
  213. // #endif
  214. // #ifndef MP-WEIXIN
  215. options = _self.options
  216. // #endif
  217. // TODO 条件编译处理参数问题,安卓上 options返回的是map,需要处理成 utsobject
  218. // #ifdef APP-ANDROID
  219. const opts = new UTSJSONObject(options)
  220. // TODO 上报页面参数需要处理
  221. url_params = Serialize(opts)
  222. // #endif
  223. // #ifndef APP-ANDROID
  224. // @ts-ignore
  225. url_params = Serialize(options)
  226. // #endif
  227. let params = ''
  228. // 如果参数只有 ?则说明没有参数
  229. if (url_params != '?') {
  230. params = url_params
  231. }
  232. // 兼容不同小程序下的不同取值
  233. let route : string
  234. // #ifdef MP-WEIXIN
  235. route = (_self.$scope && _self.$scope.route) ?? ""
  236. // #endif
  237. // #ifndef MP-WEIXIN
  238. route = _self.route
  239. // #endif
  240. const data : RouteParams = {
  241. path: route,
  242. fullpath: route + params
  243. }
  244. return data
  245. }
  246. /**
  247. * 获取页面url, 包含参数 ,暂时不用,合并到 get_route
  248. * @param {ComponentPublicInstance} page 页面实例
  249. */
  250. export function get_page_route(page : Page | null = null) : string {
  251. let _self = page ?? get_page_vm()
  252. let lastPageRoute = uni.getStorageSync('_STAT_LAST_PAGE_ROUTE')
  253. if (_self == null) {
  254. return lastPageRoute ?? ''
  255. }
  256. // 如果找不到 fullPath 就取 route 的值
  257. // TODO 取完整路径,目前最新为 optiosn 为携带参数,需要手动序列化
  258. // return page.fullPath === '/' ? page.route : page.fullPath || page.route
  259. return _self.route
  260. }
  261. /**
  262. * 是否上报页面数据
  263. * @returns
  264. */
  265. export const is_page_report = () : boolean => {
  266. const uniStatConfig = Config.getOptions();
  267. const collectItems = uniStatConfig.collectItems;
  268. if (collectItems != null) {
  269. const statPageLog = collectItems.uniStatPageLog
  270. if (statPageLog == null) return true
  271. return typeof statPageLog == 'boolean' ? statPageLog : true
  272. }
  273. return true
  274. }
  275. /**
  276. * 是否已处理设备 DeviceId
  277. * 如果值为 1 则表示已处理
  278. */
  279. const IS_HANDLE_DEVECE_ID = 'is_handle_device_id'
  280. export const is_handle_device = () : boolean => {
  281. let isHandleDevice = dbGet(IS_HANDLE_DEVECE_ID) ?? ''
  282. dbSet(IS_HANDLE_DEVECE_ID, '1')
  283. return isHandleDevice === '1'
  284. }
  285. /**
  286. * 获取网络状态
  287. */
  288. export const get_net = () : Promise<string> => {
  289. return new Promise((resolve, reject) => {
  290. uni.getNetworkType({
  291. success(e : GetNetworkTypeSuccess) {
  292. const net = e.networkType
  293. resolve(net)
  294. }, fail() {
  295. reject('')
  296. }
  297. })
  298. })
  299. }
  300. /**
  301. * 获取上报数据默认值
  302. */
  303. export const get_default_data = () : StatDefault => {
  304. let isRoot : number
  305. if (device.isRoot == true) {
  306. isRoot = 1
  307. } else {
  308. isRoot = 0
  309. }
  310. let statData : StatDefault = {
  311. uuid: get_uuid(),
  312. ak: APPID,
  313. p: sys.osName == 'android' ? 'a' : 'i',
  314. ut: get_platform_name(),
  315. mpn: get_pack_name(),
  316. usv: STAT_VERSION,
  317. v: RUNTIME_VERSION,
  318. ch: get_channel(),
  319. cn: '',
  320. pn: get_pack_name(),
  321. ct: '',
  322. t: get_time(),
  323. tt: '',
  324. brand: sys.deviceBrand,
  325. md: sys.deviceModel,
  326. sv: sys.osVersion.replace(/(Android|iOS)\s/, ''),
  327. mpsdk: sys.SDKVersion,
  328. mpv: sys.uniCompilerVersionCode.toString(),
  329. // mpv: '',
  330. lang: sys.osLanguage,
  331. pr: sys.devicePixelRatio,
  332. ww: sys.windowWidth,
  333. wh: sys.windowHeight,
  334. sw: sys.screenWidth,
  335. sh: sys.screenHeight,
  336. lat: '',
  337. lng: '',
  338. net: '',
  339. odid: '',
  340. pv: sysAppBase.appVersion,
  341. root: isRoot
  342. }
  343. return statData
  344. }
  345. /**
  346. * 获取上报时间间隔
  347. * @param {*} defaultTime 默认上报间隔时间 单位s
  348. */
  349. export const get_report_Interval = (defaultTime : number) : number => {
  350. const uniStatConfig = Config.getOptions()
  351. let time = uniStatConfig.reportInterval
  352. // let reg = /(^[1-9]\d*$)/
  353. // 如果不是整数,则默认为上报间隔时间
  354. // if (!reg.test(time)) return defaultTime
  355. if (!IsNumber(time)) return defaultTime
  356. // 如果上报时间配置为0 相当于立即上报
  357. if (time == 0) return 0
  358. // time = time ?? defaultTime
  359. return time as number
  360. }
  361. /**
  362. * 获取uniCloud服务空间配置
  363. * @returns {Object}
  364. */
  365. export const uni_cloud_config = () : UniCloudInitOptions | null => {
  366. // TODO 当前版本暂时不使用
  367. // return process.env.UNI_STAT_UNI_CLOUD || {}
  368. return null
  369. }
  370. /**
  371. * 获取服务空间
  372. * @param {*} config
  373. * @returns
  374. */
  375. export const get_space = (config : UniCloudInitOptions) : UniCloudInitOptions | null => {
  376. const uniCloudConfig = uni_cloud_config()
  377. if (uniCloudConfig == null) {
  378. // #ifdef APP-ANDROID
  379. if (config.spaceId != '') {
  380. return config
  381. }
  382. // #endif
  383. // #ifndef APP-ANDROID
  384. if (config?.spaceId != '') {
  385. return config
  386. }
  387. // #endif
  388. return null
  389. }
  390. let spaceId = uniCloudConfig.spaceId
  391. let provider = uniCloudConfig.provider
  392. let clientSecret = uniCloudConfig.clientSecret
  393. let secretKey = uniCloudConfig.secretKey
  394. let accessKey = uniCloudConfig.accessKey
  395. const space_type = ['tcb', 'tencent', 'aliyun', 'alipay']
  396. // @ts-ignore
  397. const is_space_id = spaceId != ''
  398. const is_provider = space_type.indexOf(provider) != -1
  399. const is_aliyun = provider == 'aliyun' && is_space_id && clientSecret != null
  400. const is_tcb = (provider == 'tcb' || provider === 'tencent') && is_space_id
  401. const is_alipay = provider == 'alipay' && is_space_id && secretKey != null && accessKey != null
  402. if (is_provider && (is_aliyun || is_tcb || is_alipay)) {
  403. return uniCloudConfig
  404. }
  405. return null
  406. }
  407. /**
  408. * 获取隐私协议配置
  409. */
  410. export const is_push_clientid = () : boolean => {
  411. const uniStatConfig = Config.getOptions()
  412. const collectItems = uniStatConfig.collectItems
  413. if (collectItems != null) {
  414. const ClientID = collectItems.uniPushClientID ?? false
  415. return typeof ClientID == 'boolean' ? ClientID : false
  416. }
  417. return false
  418. }
  419. /**
  420. * 获取崩溃日志文件地址
  421. */
  422. export const get_crash_logs = (fn : (value : string[]) => void) => {
  423. const crash_data = uni.__getAppCrashInfo()
  424. if (crash_data != null && crash_data.length > 0) {
  425. const sysManager = uni.getFileSystemManager();
  426. const reportLogs : Promise<string>[] = []
  427. for (let i = 0; i < crash_data.length; i++) {
  428. const item = crash_data[i];
  429. let file_text : string;
  430. // #ifdef APP-ANDROID
  431. file_text = item.get('file') as string
  432. // #endif
  433. // #ifdef APP-IOS
  434. file_text = item.file as string
  435. // #endif
  436. const logPromise = new Promise<string>((resolve, reject) => {
  437. sysManager.readFile({
  438. filePath: file_text,
  439. encoding: 'utf-8',
  440. success: (res) => {
  441. const crash_text = res.data as string
  442. resolve(crash_text); // 成功上报后 resolve
  443. },
  444. fail: (err : any) => {
  445. reject(err); // 读取文件失败时 reject
  446. }
  447. });
  448. });
  449. reportLogs.push(logPromise);
  450. }
  451. Promise.all(reportLogs)
  452. .then((res) => {
  453. fn(res)
  454. })
  455. .catch((err) => {
  456. console.log('Errorlogs:', err);
  457. });
  458. }
  459. }
  460. /**
  461. * 自定义事件参数校验
  462. */
  463. export const calibration = (eventName : string, options : any | null) : ReportErrorCode | null => {
  464. // login 、 share 、pay_success 、pay_fail 、register 、title
  465. if (eventName == '') {
  466. // console.error(`uni.report Missing [eventName] parameter`)
  467. return 61003
  468. }
  469. if (typeof eventName != 'string') {
  470. // console.error(
  471. // `uni.report [eventName] Parameter type error, it can only be of type String`
  472. // )
  473. return 61004
  474. }
  475. if (eventName.length > 255) {
  476. // console.error(
  477. // `uni.report [eventName] Parameter length cannot be greater than 255`
  478. // )
  479. return 61005
  480. }
  481. if (typeof options != 'string' && typeof options != 'object') {
  482. // console.error(
  483. // 'uni.report [options] Parameter type error, Only supports String or Object type'
  484. // )
  485. return 61006
  486. }
  487. if (typeof options == 'string' && (options as string).length > 255) {
  488. // console.error(
  489. // `uni.report [options] Parameter length cannot be greater than 255`
  490. // )
  491. return 61007
  492. }
  493. if (eventName == 'title' && typeof options != 'string') {
  494. // console.error(
  495. // `uni.report [eventName] When the parameter is title, the [options] parameter can only be of type String`
  496. // )
  497. return 61008
  498. }
  499. return null
  500. }