diff --git a/packages/uni-app-plus/dist/uni-app-service.es.js b/packages/uni-app-plus/dist/uni-app-service.es.js index 0db50a61b77d6924ae500e3438115b0cb5bab9c5..dac0a59abee724bdf53f45582f322037f363384f 100644 --- a/packages/uni-app-plus/dist/uni-app-service.es.js +++ b/packages/uni-app-plus/dist/uni-app-service.es.js @@ -10,79 +10,79 @@ const __uniRoutes = instanceContext.__uniRoutes; var serviceContext = (function (vue) { 'use strict'; - /* - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ - - var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - - // Use a lookup table to find the index. - var lookup = /*#__PURE__*/ (function () { - const lookup = new Uint8Array(256); - for (var i = 0; i < chars.length; i++) { - lookup[chars.charCodeAt(i)] = i; - } - return lookup - })(); - - function encode$3(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, - len = bytes.length, - base64 = ''; - - for (i = 0; i < len; i += 3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if (len % 3 === 2) { - base64 = base64.substring(0, base64.length - 1) + '='; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + '=='; - } - - return base64 - } - - function decode$1(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, - i, - p = 0, - encoded1, - encoded2, - encoded3, - encoded4; - - if (base64[base64.length - 1] === '=') { - bufferLength--; - if (base64[base64.length - 2] === '=') { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i += 4) { - encoded1 = lookup[base64.charCodeAt(i)]; - encoded2 = lookup[base64.charCodeAt(i + 1)]; - encoded3 = lookup[base64.charCodeAt(i + 2)]; - encoded4 = lookup[base64.charCodeAt(i + 3)]; - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer + /* + * base64-arraybuffer + * https://github.com/niklasvh/base64-arraybuffer + * + * Copyright (c) 2012 Niklas von Hertzen + * Licensed under the MIT license. + */ + + var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + + // Use a lookup table to find the index. + var lookup = /*#__PURE__*/ (function () { + const lookup = new Uint8Array(256); + for (var i = 0; i < chars.length; i++) { + lookup[chars.charCodeAt(i)] = i; + } + return lookup + })(); + + function encode$3(arraybuffer) { + var bytes = new Uint8Array(arraybuffer), + i, + len = bytes.length, + base64 = ''; + + for (i = 0; i < len; i += 3) { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } + + if (len % 3 === 2) { + base64 = base64.substring(0, base64.length - 1) + '='; + } else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + '=='; + } + + return base64 + } + + function decode$1(base64) { + var bufferLength = base64.length * 0.75, + len = base64.length, + i, + p = 0, + encoded1, + encoded2, + encoded3, + encoded4; + + if (base64[base64.length - 1] === '=') { + bufferLength--; + if (base64[base64.length - 2] === '=') { + bufferLength--; + } + } + + var arraybuffer = new ArrayBuffer(bufferLength), + bytes = new Uint8Array(arraybuffer); + + for (i = 0; i < len; i += 4) { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i + 1)]; + encoded3 = lookup[base64.charCodeAt(i + 2)]; + encoded4 = lookup[base64.charCodeAt(i + 3)]; + + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); + } + + return arraybuffer } /** diff --git a/packages/uni-cli-shared/src/json/index.ts b/packages/uni-cli-shared/src/json/index.ts index dc9def5ad031086cdbddb46a6ec2f4a8bae9c8f6..e2a11846e3f7f22171438f438d3aba03d382dfcb 100644 --- a/packages/uni-cli-shared/src/json/index.ts +++ b/packages/uni-cli-shared/src/json/index.ts @@ -1,3 +1,4 @@ +export * from './mp' export * from './app' export * from './json' export * from './pages' diff --git a/packages/uni-cli-shared/src/json/mp/index.ts b/packages/uni-cli-shared/src/json/mp/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..8141742ed1b7777b468572abe44d0ce5ef0af5c3 --- /dev/null +++ b/packages/uni-cli-shared/src/json/mp/index.ts @@ -0,0 +1,3 @@ +export { AppJson } from './types' +export { parseMiniProgramPagesJson } from './pages' +export { parseMiniProgramProjectJson } from './project' diff --git a/packages/uni-cli-shared/src/json/mp/jsonFile.ts b/packages/uni-cli-shared/src/json/mp/jsonFile.ts new file mode 100644 index 0000000000000000000000000000000000000000..11712f708d5ae0f6420d110794a1d084ea7f6c73 --- /dev/null +++ b/packages/uni-cli-shared/src/json/mp/jsonFile.ts @@ -0,0 +1,17 @@ +import { ComponentJson, PageWindowOptions, UsingComponents } from './types' + +export const jsonPagesCache = new Map() +export const jsonComponentsCache = new Map() +export const jsonUsingComponentsCache = new Map() + +export function addPageJson(filename: string, json: PageWindowOptions) { + jsonPagesCache.set(filename, json) +} + +export function addComponentJson(filename: string, json: ComponentJson) { + jsonComponentsCache.set(filename, json) +} + +export function addUsingComponents(filename: string, json: UsingComponents) { + jsonUsingComponentsCache.set(filename, json) +} diff --git a/packages/uni-cli-shared/src/json/mp/pages.ts b/packages/uni-cli-shared/src/json/mp/pages.ts new file mode 100644 index 0000000000000000000000000000000000000000..6c1c724d7151b9d853269fba37fdf83db8178583 --- /dev/null +++ b/packages/uni-cli-shared/src/json/mp/pages.ts @@ -0,0 +1,120 @@ +import path from 'path' +import { hasOwn } from '@vue/shared' +import { parseJson } from '../json' +import { validatePages } from '../pages' +import { AppJson, NetworkTimeout, PageWindowOptions } from './types' +import { parseTabBar, parseWindowOptions } from './utils' +import { normalizePath } from '../../utils' + +interface ParsePagesJsonOptions { + debug?: boolean + darkmode?: boolean + subpackages: boolean + windowOptionsMap?: Record + tabBarOptionsMap?: Record + tabBarItemOptionsMap?: Record + networkTimeout?: NetworkTimeout +} + +export function parseMiniProgramPagesJson( + jsonStr: string, + platform: UniApp.PLATFORM, + options: ParsePagesJsonOptions = { subpackages: false } +) { + return parsePagesJson(jsonStr, platform, options) +} + +function parsePagesJson( + jsonStr: string, + platform: UniApp.PLATFORM, + { + debug, + darkmode, + networkTimeout, + subpackages, + windowOptionsMap, + }: ParsePagesJsonOptions = { + subpackages: false, + } +) { + const appJson: AppJson = { + pages: [], + } + const pageJsons: Record = {} + // preprocess + const pagesJson = parseJson(jsonStr, true) as UniApp.PagesJson + if (!pagesJson) { + throw new Error(`[vite] Error: pages.json parse failed.\n`) + } + + function addPageJson(pagePath: string, style: UniApp.PagesJsonPageStyle) { + pageJsons[pagePath] = parseWindowOptions(style, platform, windowOptionsMap) + } + // pages + validatePages(pagesJson, jsonStr) + + pagesJson.pages.forEach((page) => { + appJson.pages.push(page.path) + addPageJson(page.path, page.style) + }) + + // subpackages + pagesJson.subPackages = pagesJson.subPackages || pagesJson.subpackages + if (pagesJson.subPackages) { + if (subpackages) { + appJson.subPackages = pagesJson.subPackages.map(({ root, pages }) => { + return { + root, + pages: pages.map((page) => { + addPageJson(normalizePath(path.join(root, page.path)), page.style) + return page.path + }), + } + }) + } else { + pagesJson.subPackages.forEach(({ root, pages }) => { + pages.forEach((page) => { + const pagePath = normalizePath(path.join(root, page.path)) + appJson.pages.push(pagePath) + addPageJson(pagePath, page.style) + }) + }) + } + } + + // window + if (pagesJson.globalStyle) { + appJson.window = parseWindowOptions( + pagesJson.globalStyle, + platform, + windowOptionsMap + ) + } + + // tabBar + if (pagesJson.tabBar) { + const tabBar = parseTabBar(pagesJson.tabBar!, platform) + if (tabBar) { + appJson.tabBar = tabBar + } + } + ;['preloadRule', 'workers', 'usingComponents'].forEach((name) => { + if (hasOwn(pagesJson, name)) { + appJson[name] = pagesJson[name] + } + }) + if (debug) { + appJson.debug = debug + } + if (networkTimeout) { + appJson.networkTimeout = networkTimeout + } + if (darkmode) { + appJson.darkmode = true + appJson.themeLocation = 'theme.json' + } + return { + appJson, + pageJsons, + } +} diff --git a/packages/uni-cli-shared/src/json/mp/project.ts b/packages/uni-cli-shared/src/json/mp/project.ts new file mode 100644 index 0000000000000000000000000000000000000000..3f245bd246ac9e35c3cfdd013dd3bc4dba5e389b --- /dev/null +++ b/packages/uni-cli-shared/src/json/mp/project.ts @@ -0,0 +1,46 @@ +import { hasOwn } from '@vue/shared' +import { parseJson } from '../json' + +interface ParseMiniProgramProjectJsonOptions { + template: Record +} +interface ProjectConfig { + projectname: string +} + +const projectKeys = [ + 'appid', + 'setting', + 'miniprogramRoot', + 'cloudfunctionRoot', + 'qcloudRoot', + 'pluginRoot', + 'compileType', + 'libVersion', + 'projectname', + 'packOptions', + 'debugOptions', + 'scripts', + 'cloudbaseRoot', +] + +export function parseMiniProgramProjectJson( + jsonStr: string, + platform: UniApp.PLATFORM, + { template }: ParseMiniProgramProjectJsonOptions +) { + const project = JSON.parse(JSON.stringify(template)) as ProjectConfig + const manifestJson = parseJson(jsonStr) + if (manifestJson) { + project.projectname = manifestJson.name + const platformConfig = manifestJson[platform] + if (platformConfig) { + projectKeys.forEach((name) => { + if (hasOwn(platformConfig, name)) { + ;(project as Record)[name] = platformConfig[name] + } + }) + } + } + return project +} diff --git a/packages/uni-cli-shared/src/json/mp/types.ts b/packages/uni-cli-shared/src/json/mp/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..624a52336c6c61b9dee3cc691509e864f7aa2520 --- /dev/null +++ b/packages/uni-cli-shared/src/json/mp/types.ts @@ -0,0 +1,127 @@ +export interface ComponentJson { + component: true + usingComponents?: UsingComponents +} + +interface ShareWindowOptions { + navigationBarBackgroundColor?: string // #000000 + navigationBarTextStyle?: 'white' | 'black' // white + navigationBarTitleText?: string + navigationStyle?: 'default' | 'custom' // default + backgroundColor?: string // #ffffff + backgroundTextStyle?: 'dark' | 'light' // dark + backgroundColorTop?: string // #ffffff + backgroundColorBottom?: string // #ffffff + enablePullDownRefresh?: boolean // false + onReachBottomDistance?: number // 50 + pageOrientation?: 'portrait' | 'landscape' | 'auto' // portrait +} + +type Style = 'v2' | string +type RestartStrategy = 'homePage' | 'homePageAndLatestPage' | string + +export interface PageWindowOptions extends ShareWindowOptions { + disableScroll?: boolean // false + usingComponents?: UsingComponents + initialRenderingCache?: 'static' | string + style?: Style + singlePage?: SinglePage + restartStrategy?: RestartStrategy +} + +export interface AppWindowOptions extends ShareWindowOptions { + visualEffectInBackground?: 'none' | 'hidden' // none +} + +interface SubPackage { + name?: string + root: string + pages: string[] + independent?: boolean +} + +interface TabBarItem { + pagePath: string + text: string + iconPath?: string + selectedIconPath?: string +} + +export interface TabBar { + color: string + selectedColor: string + backgroundColor: string + borderStyle?: 'black' | 'white' // black + list: TabBarItem[] + position?: 'bottom' | 'top' // bottom + custom?: boolean +} + +export interface NetworkTimeout { + request?: number // 60000 + requeconnectSocketst?: number // 60000 + uploadFile?: number // 60000 + downloadFile?: number // 60000 +} + +interface Plugins { + [name: string]: { + version: string + provider: string + } +} + +interface PreloadRule { + [name: string]: { + network: 'wifi' | 'all' // wifi + packages: string[] + } +} +export interface UsingComponents { + [name: string]: string +} +interface Permission { + [name: string]: { + desc: string + } +} +interface UseExtendedLib { + kbone: boolean + weui: boolean +} +interface EntranceDeclare { + locationMessage: { + path: string + query: string + } +} +interface SinglePage { + navigationBarFit?: 'squeezed' | 'float' +} + +export interface AppJson { + entryPagePath?: string // mp-weixin + pages: string[] + window?: AppWindowOptions + tabBar?: TabBar + networkTimeout?: NetworkTimeout + debug?: boolean + functionalPages?: boolean + subPackages?: SubPackage[] + workers?: string + requiredBackgroundModes?: string[] // audio,location + plugins?: Plugins + preloadRule?: PreloadRule + resizable?: boolean + usingComponents?: UsingComponents + permission?: Permission + sitemapLocation?: string + style?: Style + useExtendedLib?: UseExtendedLib + entranceDeclare?: EntranceDeclare + darkmode?: boolean + themeLocation?: string + lazyCodeLoading?: 'requiredComponents' | string + singlePage?: SinglePage + restartStrategy?: RestartStrategy +} diff --git a/packages/uni-cli-shared/src/json/mp/utils.ts b/packages/uni-cli-shared/src/json/mp/utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..b13047852b09bfcab8e2289a3fb21f17c3b8bee4 --- /dev/null +++ b/packages/uni-cli-shared/src/json/mp/utils.ts @@ -0,0 +1,85 @@ +import { extend, hasOwn } from '@vue/shared' +import { removePlatformStyle } from '../pages' +import { AppWindowOptions, PageWindowOptions, TabBar } from './types' + +function trimJson(json: Record) { + delete json.maxWidth + delete json.topWindow + delete json.leftWindow + delete json.rightWindow + if (json.tabBar) { + delete json.tabBar.matchMedia + } + return json +} + +function convert( + to: Record, + from: Record, + map: Record +) { + Object.keys(map).forEach((key) => { + if (hasOwn(from, map[key])) { + to[key] = from[map[key]] + } + }) + return to +} + +export function parseWindowOptions( + style: UniApp.PagesJsonPageStyle, + platform: UniApp.PLATFORM, + windowOptionsMap?: Record +): PageWindowOptions | AppWindowOptions { + if (!style) { + return {} + } + const platformStyle = style[platform] || {} + removePlatformStyle(trimJson(style) as any) + const res: PageWindowOptions | AppWindowOptions = {} + if (windowOptionsMap) { + return extend(convert(res, style, windowOptionsMap), platformStyle) + } + return extend(res, style, platformStyle) +} + +function trimTabBarJson(tabBar: UniApp.TabBarOptions) { + ;( + [ + 'fontSize', + 'height', + 'iconWidth', + 'midButton', + 'selectedIndex', + 'spacing', + ] as const + ).forEach((name) => { + delete tabBar[name] + }) + return tabBar +} + +export function parseTabBar( + tabBar: UniApp.TabBarOptions, + platform: UniApp.PLATFORM, + tabBarOptionsMap?: Record, + tabBarItemOptionsMap?: Record +): TabBar { + const platformStyle = (tabBar as any)[platform] || {} + removePlatformStyle(trimTabBarJson(tabBar) as any) + const res = {} as TabBar + if (tabBarOptionsMap) { + if (tabBarItemOptionsMap && tabBar.list) { + tabBar.list = tabBar.list.map((item) => { + return convert( + {}, + item, + tabBarItemOptionsMap + ) as UniApp.TabBarItemOptions + }) + } + convert(res, tabBar, tabBarOptionsMap) + return extend(res, platformStyle) + } + return extend(res, tabBar, platformStyle) +} diff --git a/packages/uni-cli-shared/src/json/pages.ts b/packages/uni-cli-shared/src/json/pages.ts index 1d73f7d9cd175d6e3064123e02ecc72b9eae097d..1e1bfef9f6dde9cc8a1d4ca1f69c4cb5878cf02a 100644 --- a/packages/uni-cli-shared/src/json/pages.ts +++ b/packages/uni-cli-shared/src/json/pages.ts @@ -20,7 +20,15 @@ export const parsePagesJson = ( export const parsePagesJsonOnce = once(parsePagesJson) -export function normalizePagesJson(jsonStr: string, platform: UniApp.PLATFORM) { +export function normalizePagesJson( + jsonStr: string, + platform: UniApp.PLATFORM, + { + subpackages, + }: { + subpackages: boolean + } = { subpackages: false } +) { let pagesJson: UniApp.PagesJson = { pages: [], globalStyle: { @@ -35,10 +43,21 @@ export function normalizePagesJson(jsonStr: string, platform: UniApp.PLATFORM) { } // pages validatePages(pagesJson, jsonStr) + pagesJson.subPackages = pagesJson.subPackages || pagesJson.subpackages + delete pagesJson.subpackages // subpackages - pagesJson.pages.push( - ...normalizeSubpackages(pagesJson.subPackages || pagesJson.subpackages) - ) + if (pagesJson.subPackages) { + if (subpackages) { + pagesJson.subPackages.forEach(({ pages }) => { + pages && normalizePages(pages, platform) + }) + } else { + pagesJson.pages.push(...normalizeSubpackages(pagesJson.subPackages)) + delete pagesJson.subPackages + } + } else { + delete pagesJson.subPackages + } // pageStyle normalizePages(pagesJson.pages, platform) @@ -64,7 +83,7 @@ export function normalizePagesJson(jsonStr: string, platform: UniApp.PLATFORM) { return pagesJson } -function validatePages(pagesJson: Record, jsonStr: string) { +export function validatePages(pagesJson: Record, jsonStr: string) { if (!Array.isArray(pagesJson.pages)) { pagesJson.pages = [] throw new Error(`[uni-app] Error: pages.json->pages parse failed.`) @@ -79,9 +98,8 @@ function normalizePages( pages: UniApp.PagesJsonPageOptions[], platform: UniApp.PLATFORM ) { - return pages.filter((page) => { + return pages.forEach((page) => { page.style = normalizePageStyle(page.path, page.style!, platform) - return true }) } @@ -151,7 +169,8 @@ function normalizePageStyle( } } pageStyle.isNVue = isNVue - return removePlatformStyle(pageStyle) + removePlatformStyle(pageStyle) + return pageStyle } return { navigationBar: {}, isNVue } } @@ -347,7 +366,7 @@ function normalizeFilepath(filepath: string) { const platforms = ['h5', 'app', 'mp-', 'quickapp'] -function removePlatformStyle(pageStyle: UniApp.PagesJsonPageStyle) { +export function removePlatformStyle(pageStyle: Record) { Object.keys(pageStyle).forEach((name) => { if (platforms.find((prefix) => name.startsWith(prefix))) { delete pageStyle[name as UniApp.PLATFORM] diff --git a/packages/uni-mp-vite/src/plugin/index.ts b/packages/uni-mp-vite/src/plugin/index.ts index fa15bab1625324fea0952b5f7af36dc74fe425e7..5586010cfc18227673ae8f8c33dc7f06d71d5fd6 100644 --- a/packages/uni-mp-vite/src/plugin/index.ts +++ b/packages/uni-mp-vite/src/plugin/index.ts @@ -28,7 +28,7 @@ export interface UniMiniProgramPluginOptions { } project?: { filename: string - source: Record + source: Record } template: { extname: string diff --git a/packages/uni-mp-vite/src/plugins/manifestJson.ts b/packages/uni-mp-vite/src/plugins/manifestJson.ts index 7073dee4c8c4cfb6251ecf3aa188b48a2ca9f6fa..605da525fee565b08ca402b65b81f57790f418e1 100644 --- a/packages/uni-mp-vite/src/plugins/manifestJson.ts +++ b/packages/uni-mp-vite/src/plugins/manifestJson.ts @@ -4,52 +4,61 @@ import { Plugin } from 'vite' import { defineUniManifestJsonPlugin, getLocaleFiles, + parseMiniProgramProjectJson, } from '@dcloudio/uni-cli-shared' import { UniMiniProgramPluginOptions } from '../plugin' export function uniManifestJsonPlugin( options: UniMiniProgramPluginOptions ): Plugin { + let projectJson: Record return defineUniManifestJsonPlugin((opts) => { return { name: 'vite:uni-mp-manifest-json', enforce: 'pre', - transform(_code, id) { + transform(code, id) { if (!opts.filter(id)) { return } - this.addWatchFile( - path.resolve(process.env.UNI_INPUT_DIR, 'manifest.json') - ) - getLocaleFiles( - path.resolve(process.env.UNI_INPUT_DIR, 'locale') - ).forEach((filepath) => { + const inputDir = process.env.UNI_INPUT_DIR + this.addWatchFile(path.resolve(inputDir, 'manifest.json')) + getLocaleFiles(path.resolve(inputDir, 'locale')).forEach((filepath) => { this.addWatchFile(filepath) }) - // manifestJson = normalizeAppManifestJson( - // parseJson(code), - // parsePagesJsonOnce( - // process.env.UNI_INPUT_DIR, - // process.env.UNI_PLATFORM - // ) - // ) + if (options.project) { + const template = options.project.source + let projectname = path.basename(inputDir) + if (projectname === 'src') { + projectname = path.basename(path.dirname(inputDir)) + } + template.projectname = projectname + // TODO condition + if (process.env.UNI_AUTOMATOR_WS_ENDPOINT) { + if (!template.setting) { + template.setting = {} + } + template.setting.urlCheck = false + } + projectJson = parseMiniProgramProjectJson( + code, + process.env.UNI_PLATFORM, + { template } + ) + } + return { code: '', map: this.getCombinedSourcemap(), } }, generateBundle() { - // 生成一个空的app-config.js,兼容基座已有规范 - // this.emitFile({ - // fileName: `app-config.js`, - // type: 'asset', - // source: '(function(){})();', - // }) - // this.emitFile({ - // fileName: `manifest.json`, - // type: 'asset', - // source: JSON.stringify(manifestJson, null, 2), - // }) + if (projectJson && options.project) { + this.emitFile({ + fileName: options.project.filename, + type: 'asset', + source: JSON.stringify(projectJson, null, 2), + }) + } }, } }) diff --git a/packages/uni-mp-vite/src/plugins/pagesJson.ts b/packages/uni-mp-vite/src/plugins/pagesJson.ts index 4e98d9600cad98976f1fdcecbecd730dfd972a8c..65d8123022f75ff4e6750cc0ec4f825a24c5d0bd 100644 --- a/packages/uni-mp-vite/src/plugins/pagesJson.ts +++ b/packages/uni-mp-vite/src/plugins/pagesJson.ts @@ -1,11 +1,15 @@ +import fs from 'fs' import path from 'path' import { Plugin } from 'vite' import { + AppJson, defineUniPagesJsonPlugin, - normalizePagesJson, getLocaleFiles, normalizePagePath, + normalizeNodeModules, + parseManifestJsonOnce, + parseMiniProgramPagesJson, } from '@dcloudio/uni-cli-shared' import { virtualPagePath } from './virtual' import { UniMiniProgramPluginOptions } from '../plugin' @@ -13,7 +17,7 @@ import { UniMiniProgramPluginOptions } from '../plugin' export function uniPagesJsonPlugin( options: UniMiniProgramPluginOptions ): Plugin { - let pagesJson: UniApp.PagesJson + let appJson: AppJson return defineUniPagesJsonPlugin((opts) => { return { name: 'vite:uni-mp-pages-json', @@ -22,49 +26,61 @@ export function uniPagesJsonPlugin( if (!opts.filter(id)) { return } - this.addWatchFile(path.resolve(process.env.UNI_INPUT_DIR, 'pages.json')) - getLocaleFiles( - path.resolve(process.env.UNI_INPUT_DIR, 'locale') - ).forEach((filepath) => { + const inputDir = process.env.UNI_INPUT_DIR + this.addWatchFile(path.resolve(inputDir, 'pages.json')) + getLocaleFiles(path.resolve(inputDir, 'locale')).forEach((filepath) => { this.addWatchFile(filepath) }) - pagesJson = normalizePagesJson(code, process.env.UNI_PLATFORM) - // TODO subpackages - pagesJson.pages.forEach((page) => { - this.addWatchFile( - path.resolve(process.env.UNI_INPUT_DIR, page.path + '.vue') - ) + const manifestJson = parseManifestJsonOnce(inputDir) + const res = parseMiniProgramPagesJson(code, process.env.UNI_PLATFORM, { + debug: !!manifestJson.debug, + darkmode: + options.app.darkmode && + fs.existsSync(path.resolve(inputDir, 'theme.json')), + networkTimeout: manifestJson.networkTimeout, + subpackages: options.app.subpackages, + }) + appJson = res.appJson + Object.keys(res.pageJsons).forEach((name) => { + this.emitFile({ + fileName: normalizeNodeModules(name) + '.json', + type: 'asset', + source: JSON.stringify(res.pageJsons[name], null, 2), + }) }) return { - code: - `import './manifest.json.js'\n` + - normalizeMiniProgramPagesJson(pagesJson), + code: `import './manifest.json.js'\n` + importPagesCode(appJson), map: this.getCombinedSourcemap(), } }, generateBundle() { - // this.emitFile({ - // fileName: `app-config-service.js`, - // type: 'asset', - // source: normalizeAppConfigService( - // pagesJson, - // parseManifestJsonOnce(process.env.UNI_INPUT_DIR) - // ), - // }) + if (appJson) { + this.emitFile({ + fileName: `app.json`, + type: 'asset', + source: JSON.stringify(appJson, null, 2), + }) + } }, } }) } -function normalizeMiniProgramPagesJson(pagesJson: Record) { +function importPagesCode(pagesJson: AppJson) { const importPagesCode: string[] = [] - pagesJson.pages.forEach((page: UniApp.PagesJsonPageOptions) => { - const pagePath = page.path + function importPageCode(pagePath: string) { const pagePathWithExtname = normalizePagePath(pagePath, 'app') if (pagePathWithExtname) { importPagesCode.push(`import('${virtualPagePath(pagePathWithExtname)}')`) } - }) + } + pagesJson.pages.forEach((pagePath) => importPageCode(pagePath)) + if (pagesJson.subPackages) { + pagesJson.subPackages.forEach(({ root, pages }) => { + pages && + pages.forEach((pagePath) => importPageCode(path.join(root, pagePath))) + }) + } return `if(!Math){ ${importPagesCode.join('\n')} }` diff --git a/packages/uni-mp-vite/src/plugins/virtual.ts b/packages/uni-mp-vite/src/plugins/virtual.ts index 21df59b60d8a82ab029d641d258b7273d534fe80..2fbc5edfdfd6c89873534d3b245615c8bc19c74e 100644 --- a/packages/uni-mp-vite/src/plugins/virtual.ts +++ b/packages/uni-mp-vite/src/plugins/virtual.ts @@ -54,6 +54,7 @@ export function uniVirtualPlugin({ const filepath = normalizePath( path.resolve(inputDir, parseVirtualPagePath(id)) ) + this.addWatchFile(filepath) return { code: `import Page from '${filepath}?mpType=page' ${global}.createPage(Page)`, @@ -62,6 +63,7 @@ ${global}.createPage(Page)`, const filepath = normalizePath( path.resolve(inputDir, parseVirtualComponentPath(id)) ) + this.addWatchFile(filepath) return { code: `import Component from '${filepath}' ${global}.createComponent(Component)`, diff --git a/packages/uni-stat/dist/uni-stat.cjs.js b/packages/uni-stat/dist/uni-stat.cjs.js index a9677cf3260a7125aacb0b66120f54759aa3d731..21b68a2dd76c86d41c9a9272f7336ef88ad9bab8 100644 --- a/packages/uni-stat/dist/uni-stat.cjs.js +++ b/packages/uni-stat/dist/uni-stat.cjs.js @@ -10,952 +10,952 @@ const APP_PVER_TIME = 300; const OPERATING_TIME = 10; const DIFF_TIME = 60 * 1000 * 60 * 24; -const statConfig$1 = { - appid: process.env.UNI_APP_ID, -}; -const UUID_KEY = '__DC_STAT_UUID'; -const UUID_VALUE = '__DC_UUID_VALUE'; - -function getUuid() { - let uuid = ''; - if (getPlatformName() === 'n') { - try { - uuid = plus.runtime.getDCloudId(); - } catch (e) { - uuid = ''; - } - return uuid - } - - try { - uuid = uni.getStorageSync(UUID_KEY); - } catch (e) { - uuid = UUID_VALUE; - } - - if (!uuid) { - uuid = Date.now() + '' + Math.floor(Math.random() * 1e7); - try { - uni.setStorageSync(UUID_KEY, uuid); - } catch (e) { - uni.setStorageSync(UUID_KEY, UUID_VALUE); - } - } - return uuid -} - -const getSgin = (statData) => { - let arr = Object.keys(statData); - let sortArr = arr.sort(); - let sgin = {}; - let sginStr = ''; - for (var i in sortArr) { - sgin[sortArr[i]] = statData[sortArr[i]]; - sginStr += sortArr[i] + '=' + statData[sortArr[i]] + '&'; - } - // const options = sginStr.substr(0, sginStr.length - 1) - // sginStr = sginStr.substr(0, sginStr.length - 1) + '&key=' + STAT_KEY; - // const si = crypto.createHash('md5').update(sginStr).digest('hex'); - return { - sign: '', - options: sginStr.substr(0, sginStr.length - 1), - } -}; - -const getSplicing = (data) => { - let str = ''; - for (var i in data) { - str += i + '=' + data[i] + '&'; - } - return str.substr(0, str.length - 1) -}; - -const getTime = () => { - return parseInt(new Date().getTime() / 1000) -}; - -const getPlatformName = () => { - const aliArr = ['y', 'a', 'p', 'mp-ali']; - const platformList = { - 'app-plus': 'n', - h5: 'h5', - 'mp-weixin': 'wx', - [aliArr.reverse().join('')]: 'ali', - 'mp-baidu': 'bd', - 'mp-toutiao': 'tt', - 'mp-qq': 'qq', - 'quickapp-native': 'qn', - 'mp-kuaishou': 'ks', - }; - return platformList[process.env.VUE_APP_PLATFORM] -}; - -const getPackName = () => { - let packName = ''; - if (getPlatformName() === 'wx' || getPlatformName() === 'qq') { - // 兼容微信小程序低版本基础库 - if (uni.canIUse('getAccountInfoSync')) { - packName = uni.getAccountInfoSync().miniProgram.appId || ''; - } - } - return packName -}; - -const getVersion = () => { - return getPlatformName() === 'n' ? plus.runtime.version : '' -}; - -const getChannel = () => { - const platformName = getPlatformName(); - let channel = ''; - if (platformName === 'n') { - channel = plus.runtime.channel; - } - return channel -}; - -const getScene = (options) => { - const platformName = getPlatformName(); - let scene = ''; - if (options) { - return options - } - if (platformName === 'wx') { - scene = uni.getLaunchOptionsSync().scene; - } - return scene -}; -const First__Visit__Time__KEY = 'First__Visit__Time'; -const Last__Visit__Time__KEY = 'Last__Visit__Time'; - -const getFirstVisitTime = () => { - const timeStorge = uni.getStorageSync(First__Visit__Time__KEY); - let time = 0; - if (timeStorge) { - time = timeStorge; - } else { - time = getTime(); - uni.setStorageSync(First__Visit__Time__KEY, time); - uni.removeStorageSync(Last__Visit__Time__KEY); - } - return time -}; - -const getLastVisitTime = () => { - const timeStorge = uni.getStorageSync(Last__Visit__Time__KEY); - let time = 0; - if (timeStorge) { - time = timeStorge; - } else { - time = ''; - } - uni.setStorageSync(Last__Visit__Time__KEY, getTime()); - return time -}; - -const PAGE_RESIDENCE_TIME = '__page__residence__time'; -let First_Page_residence_time = 0; -let Last_Page_residence_time = 0; - -const setPageResidenceTime = () => { - First_Page_residence_time = getTime(); - if (getPlatformName() === 'n') { - uni.setStorageSync(PAGE_RESIDENCE_TIME, getTime()); - } - return First_Page_residence_time -}; - -const getPageResidenceTime = () => { - Last_Page_residence_time = getTime(); - if (getPlatformName() === 'n') { - First_Page_residence_time = uni.getStorageSync(PAGE_RESIDENCE_TIME); - } - return Last_Page_residence_time - First_Page_residence_time -}; -const TOTAL__VISIT__COUNT = 'Total__Visit__Count'; -const getTotalVisitCount = () => { - const timeStorge = uni.getStorageSync(TOTAL__VISIT__COUNT); - let count = 1; - if (timeStorge) { - count = timeStorge; - count++; - } - uni.setStorageSync(TOTAL__VISIT__COUNT, count); - return count -}; - -const GetEncodeURIComponentOptions = (statData) => { - let data = {}; - for (let prop in statData) { - data[prop] = encodeURIComponent(statData[prop]); - } - return data -}; - -let Set__First__Time = 0; -let Set__Last__Time = 0; - -const getFirstTime = () => { - let time = new Date().getTime(); - Set__First__Time = time; - Set__Last__Time = 0; - return time -}; - -const getLastTime = () => { - let time = new Date().getTime(); - Set__Last__Time = time; - return time -}; - -const getResidenceTime = (type) => { - let residenceTime = 0; - if (Set__First__Time !== 0) { - residenceTime = Set__Last__Time - Set__First__Time; - } - - residenceTime = parseInt(residenceTime / 1000); - residenceTime = residenceTime < 1 ? 1 : residenceTime; - if (type === 'app') { - let overtime = residenceTime > APP_PVER_TIME ? true : false; - return { - residenceTime, - overtime, - } - } - if (type === 'page') { - let overtime = residenceTime > PAGE_PVER_TIME ? true : false; - return { - residenceTime, - overtime, - } - } - - return { - residenceTime, - } -}; - -const getRoute = () => { - var pages = getCurrentPages(); - var page = pages[pages.length - 1]; - if (!page) return '' - // TODO 需要确认如果不用 $vm ,其他平台会不会出错 - let _self = page.$vm; - - if (getPlatformName() === 'bd') { - return _self.$mp && _self.$mp.page.is - } else { - return _self.route || (_self.$scope && _self.$scope.route) - } -}; - -const getPageRoute = (_this) => { - let pageVm = _this.self; - let page = pageVm.$page || pageVm.$scope.$page; - return page.fullPath === '/' ? page.route : page.fullPath -}; - -const getPageTypes = (self) => { - if ( - self.$mpType === 'page' || - (self.$mp && self.$mp.mpType === 'page') || - self.$options.mpType === 'page' - ) { - return true - } - return false -}; - -const calibration = (eventName, options) => { - // login 、 share 、pay_success 、pay_fail 、register 、title - if (!eventName) { - console.error(`uni.report 缺少 [eventName] 参数`); - return true - } - if (typeof eventName !== 'string') { - console.error(`uni.report [eventName] 参数类型错误,只能为 String 类型`); - return true - } - if (eventName.length > 255) { - console.error(`uni.report [eventName] 参数长度不能大于 255`); - return true - } - - if (typeof options !== 'string' && typeof options !== 'object') { - console.error( - `uni.report [options] 参数类型错误,只能为 String 或 Object 类型` - ); - return true - } - - if (typeof options === 'string' && options.length > 255) { - console.error(`uni.report [options] 参数长度不能大于 255`); - return true - } - - if (eventName === 'title' && typeof options !== 'string') { - console.error( - 'uni.report [eventName] 参数为 title 时,[options] 参数只能为 String 类型' - ); - return true - } -}; - -const Report_Data_Time = 'Report_Data_Time'; -const Report_Status = 'Report_Status'; -const isReportData = () => { - return new Promise((resolve, reject) => { - let start_time = ''; - let end_time = new Date().getTime(); - let diff_time = DIFF_TIME; - let report_status = 1; - try { - start_time = uni.getStorageSync(Report_Data_Time); - report_status = uni.getStorageSync(Report_Status); - } catch (e) { - start_time = ''; - report_status = 1; - } - - if (report_status === '') { - requestData(({ enable }) => { - uni.setStorageSync(Report_Data_Time, end_time); - uni.setStorageSync(Report_Status, enable); - if (enable === 1) { - resolve(); - } - }); - return - } - - if (report_status === 1) { - resolve(); - } - - if (!start_time) { - uni.setStorageSync(Report_Data_Time, end_time); - start_time = end_time; - } - - if (end_time - start_time > diff_time) { - requestData(({ enable }) => { - uni.setStorageSync(Report_Data_Time, end_time); - uni.setStorageSync(Report_Status, enable); - }); - } - }) -}; - -const requestData = (done) => { - let formData = { - usv: STAT_VERSION, - conf: JSON.stringify({ - ak: statConfig$1.appid, - }), - }; - uni.request({ - url: STAT_URL, - method: 'GET', - data: formData, - success: (res) => { - const { data } = res; - if (data.ret === 0) { - typeof done === 'function' && - done({ - enable: data.enable, - }); - } - }, - fail: (e) => { - let report_status_code = 1; - try { - report_status_code = uni.getStorageSync(Report_Status); - } catch (e) { - report_status_code = 1; - } - if (report_status_code === '') { - report_status_code = 1; - } - typeof done === 'function' && - done({ - enable: report_status_code, - }); - }, - }); +const statConfig$1 = { + appid: process.env.UNI_APP_ID, }; +const UUID_KEY = '__DC_STAT_UUID'; +const UUID_VALUE = '__DC_UUID_VALUE'; -let titleJsons = {}; -// #ifdef MP -let pagesTitle = require('uni-pages?{"type":"style"}').default; -pagesTitle = pagesTitle.pages; -for (let i in pagesTitle) { - titleJsons[i] = pagesTitle[i].navigationBarTitleText || ''; -} -// #endif -// #ifndef MP -titleJsons = process.env.UNI_STAT_TITLE_JSON; -// #endif - -const statConfig = { - appid: process.env.UNI_APP_ID, -}; -const resultOptions = uni.getSystemInfoSync(); - -class Util { - constructor() { - this.self = ''; - this._retry = 0; - this._platform = ''; - this._query = {}; - this._navigationBarTitle = { - config: '', - page: '', - report: '', - lt: '', - }; - this._operatingTime = 0; - this._reportingRequestData = { - 1: [], - 11: [], - }; - this.__prevent_triggering = false; - - this.__licationHide = false; - this.__licationShow = false; - this._lastPageRoute = ''; - this.statData = { - uuid: getUuid(), - ut: getPlatformName(), - mpn: getPackName(), - ak: statConfig.appid, - usv: STAT_VERSION, - v: getVersion(), - ch: getChannel(), - cn: '', - pn: '', - ct: '', - t: getTime(), - tt: '', - p: resultOptions.platform === 'android' ? 'a' : 'i', - brand: resultOptions.brand || '', - md: resultOptions.model, - sv: resultOptions.system.replace(/(Android|iOS)\s/, ''), - mpsdk: resultOptions.SDKVersion || '', - mpv: resultOptions.version || '', - lang: resultOptions.language, - pr: resultOptions.pixelRatio, - ww: resultOptions.windowWidth, - wh: resultOptions.windowHeight, - sw: resultOptions.screenWidth, - sh: resultOptions.screenHeight, - }; - // 注册拦截器 - let registerInterceptor = - typeof uni.addInterceptor === 'function' && - process.env.NODE_ENV !== 'development'; - if (registerInterceptor) { - this.addInterceptorInit(); - this.interceptLogin(); - this.interceptShare(true); - this.interceptRequestPayment(); - } - } - - addInterceptorInit() { - let self = this; - uni.addInterceptor('setNavigationBarTitle', { - invoke(args) { - self._navigationBarTitle.page = args.title; - }, - }); - } - - interceptLogin() { - let self = this; - uni.addInterceptor('login', { - complete() { - self._login(); - }, - }); - } - - interceptShare(type) { - let self = this; - if (!type) { - self._share(); - return - } - uni.addInterceptor('share', { - success() { - self._share(); - }, - fail() { - self._share(); - }, - }); - } - - interceptRequestPayment() { - let self = this; - uni.addInterceptor('requestPayment', { - success() { - self._payment('pay_success'); - }, - fail() { - self._payment('pay_fail'); - }, - }); - } - - getIsReportData() { - return isReportData() - } - - _applicationShow() { - if (this.__licationHide) { - getLastTime(); - const time = getResidenceTime('app'); - if (time.overtime) { - let options = { - path: this._lastPageRoute, - scene: this.statData.sc, - }; - this._sendReportRequest(options); - } - this.__licationHide = false; - } - } - - _applicationHide(self, type) { - this.__licationHide = true; - getLastTime(); - const time = getResidenceTime(); - getFirstTime(); - const route = getPageRoute(this); - this._sendHideRequest( - { - urlref: route, - urlref_ts: time.residenceTime, - }, - type - ); - } - - _pageShow() { - const route = getPageRoute(this); - const routepath = getRoute(); - this._navigationBarTitle.config = - (titleJsons && titleJsons[routepath]) || ''; - if (this.__licationShow) { - getFirstTime(); - this.__licationShow = false; - this._lastPageRoute = route; - return - } - - getLastTime(); - const time = getResidenceTime('page'); - // 停留时间 - if (time.overtime) { - let options = { - path: route, - scene: this.statData.sc, - }; - this._sendReportRequest(options); - } - getFirstTime(); - } - - _pageHide() { - if (!this.__licationHide) { - getLastTime(); - const time = getResidenceTime('page'); - let route = getPageRoute(this); - if (!this._lastPageRoute) { - this._lastPageRoute = route; - } - this._sendPageRequest({ - url: route, - urlref: this._lastPageRoute, - urlref_ts: time.residenceTime, - }); - this._lastPageRoute = route; - this._navigationBarTitle = { - config: '', - page: '', - report: '', - lt: '', - }; - return - } - } - - _login() { - this._sendEventRequest( - { - key: 'login', - }, - 0 - ); - } - - _share() { - this._sendEventRequest( - { - key: 'share', - }, - 0 - ); - } - _payment(key) { - this._sendEventRequest( - { - key, - }, - 0 - ); - } - _sendReportRequest(options) { - this._navigationBarTitle.lt = '1'; - this._navigationBarTitle.config = - (titleJsons && titleJsons[options.path]) || ''; - let query = - options.query && JSON.stringify(options.query) !== '{}' - ? '?' + JSON.stringify(options.query) - : ''; - this.statData.lt = '1'; - this.statData.url = options.path + query || ''; - this.statData.t = getTime(); - this.statData.sc = getScene(options.scene); - this.statData.fvts = getFirstVisitTime(); - this.statData.lvts = getLastVisitTime(); - this.statData.tvc = getTotalVisitCount(); - if (getPlatformName() === 'n') { - this.getProperty(); - } else { - this.getNetworkInfo(); - } - } - - _sendPageRequest(opt) { - let { url, urlref, urlref_ts } = opt; - this._navigationBarTitle.lt = '11'; - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '11', - ut: this.statData.ut, - url, - tt: this.statData.tt, - urlref, - urlref_ts, - ch: this.statData.ch, - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options); - } - - _sendHideRequest(opt, type) { - let { urlref, urlref_ts } = opt; - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '3', - ut: this.statData.ut, - urlref, - urlref_ts, - ch: this.statData.ch, - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options, type); - } - _sendEventRequest({ key = '', value = '' } = {}) { - const route = this._lastPageRoute; - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '21', - ut: this.statData.ut, - url: route, - ch: this.statData.ch, - e_n: key, - e_v: typeof value === 'object' ? JSON.stringify(value) : value.toString(), - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options); - } - - getNetworkInfo() { - uni.getNetworkType({ - success: (result) => { - this.statData.net = result.networkType; - this.getLocation(); - }, - }); - } - - getProperty() { - plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => { - this.statData.v = wgtinfo.version || ''; - this.getNetworkInfo(); - }); - } - - getLocation() { - { - this.statData.lat = 0; - this.statData.lng = 0; - this.request(this.statData); - } - } - - request(data, type) { - let time = getTime(); - const title = this._navigationBarTitle; - data.ttn = title.page; - data.ttpj = title.config; - data.ttc = title.report; - let requestData = this._reportingRequestData; - if (getPlatformName() === 'n') { - requestData = uni.getStorageSync('__UNI__STAT__DATA') || {}; - } - if (!requestData[data.lt]) { - requestData[data.lt] = []; - } - requestData[data.lt].push(data); - if (getPlatformName() === 'n') { - uni.setStorageSync('__UNI__STAT__DATA', requestData); - } - if (getPageResidenceTime() < OPERATING_TIME && !type) { - return - } - let uniStatData = this._reportingRequestData; - if (getPlatformName() === 'n') { - uniStatData = uni.getStorageSync('__UNI__STAT__DATA'); - } - // 时间超过,重新获取时间戳 - setPageResidenceTime(); - let firstArr = []; - let contentArr = []; - let lastArr = []; - - for (let i in uniStatData) { - const rd = uniStatData[i]; - rd.forEach((elm) => { - const newData = getSplicing(elm); - if (i === 0) { - firstArr.push(newData); - } else if (i === 3) { - lastArr.push(newData); - } else { - contentArr.push(newData); - } - }); - } - - firstArr.push(...contentArr, ...lastArr); - let optionsData = { - usv: STAT_VERSION, //统计 SDK 版本号 - t: time, //发送请求时的时间戮 - requests: JSON.stringify(firstArr), - }; - - this._reportingRequestData = {}; - if (getPlatformName() === 'n') { - uni.removeStorageSync('__UNI__STAT__DATA'); - } - - if (data.ut === 'h5') { - this.imageRequest(optionsData); - return - } - - if (getPlatformName() === 'n' && this.statData.p === 'a') { - setTimeout(() => { - this._sendRequest(optionsData); - }, 200); - return - } - this._sendRequest(optionsData); - } - _sendRequest(optionsData) { - this.getIsReportData().then(() => { - uni.request({ - url: STAT_URL, - method: 'POST', - data: optionsData, - success: () => {}, - fail: (e) => { - if (++this._retry < 3) { - setTimeout(() => { - this._sendRequest(optionsData); - }, 1000); - } - }, - }); - }); - } - /** - * h5 请求 - */ - imageRequest(data) { - this.getIsReportData().then(() => { - let image = new Image(); - let options = getSgin(GetEncodeURIComponentOptions(data)).options; - image.src = STAT_H5_URL + '?' + options; - }); - } - - sendEvent(key, value) { - // 校验 type 参数 - if (calibration(key, value)) return - - if (key === 'title') { - this._navigationBarTitle.report = value; - return - } - this._sendEventRequest( - { - key, - value: typeof value === 'object' ? JSON.stringify(value) : value, - }, - 1 - ); - } -} - -class Stat extends Util { - static getInstance() { - if (!this.instance) { - this.instance = new Stat(); - } - return this.instance - } - constructor() { - super(); - this.instance = null; - } - - report(options, self) { - // TODO 需要确认如果不用 $vm ,其他平台会不会出错 - setPageResidenceTime(); - this.__licationShow = true; - this._sendReportRequest(options, true); - } - - load(options, self) { - this.self = self; - this._query = options; - } - - show(self) { - this.self = self; - if (getPageTypes(self)) { - this._pageShow(self); - } else { - this._applicationShow(self); - } - } - ready(self) {} - hide(self) { - this.self = self; - if (getPageTypes(self)) { - this._pageHide(self); - } else { - this._applicationHide(self, true); - } - } - error(em) { - if (this._platform === 'devtools') { - if (process.env.NODE_ENV === 'development') { - console.info('当前运行环境为开发者工具,不上报数据。'); - } - } - let emVal = ''; - if (!em.message) { - emVal = JSON.stringify(em); - } else { - emVal = em.stack; - } - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '31', - ut: this.statData.ut, - ch: this.statData.ch, - mpsdk: this.statData.mpsdk, - mpv: this.statData.mpv, - v: this.statData.v, - em: emVal, - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options); - } -} +function getUuid() { + let uuid = ''; + if (getPlatformName() === 'n') { + try { + uuid = plus.runtime.getDCloudId(); + } catch (e) { + uuid = ''; + } + return uuid + } + + try { + uuid = uni.getStorageSync(UUID_KEY); + } catch (e) { + uuid = UUID_VALUE; + } + + if (!uuid) { + uuid = Date.now() + '' + Math.floor(Math.random() * 1e7); + try { + uni.setStorageSync(UUID_KEY, uuid); + } catch (e) { + uni.setStorageSync(UUID_KEY, UUID_VALUE); + } + } + return uuid +} + +const getSgin = (statData) => { + let arr = Object.keys(statData); + let sortArr = arr.sort(); + let sgin = {}; + let sginStr = ''; + for (var i in sortArr) { + sgin[sortArr[i]] = statData[sortArr[i]]; + sginStr += sortArr[i] + '=' + statData[sortArr[i]] + '&'; + } + // const options = sginStr.substr(0, sginStr.length - 1) + // sginStr = sginStr.substr(0, sginStr.length - 1) + '&key=' + STAT_KEY; + // const si = crypto.createHash('md5').update(sginStr).digest('hex'); + return { + sign: '', + options: sginStr.substr(0, sginStr.length - 1), + } +}; + +const getSplicing = (data) => { + let str = ''; + for (var i in data) { + str += i + '=' + data[i] + '&'; + } + return str.substr(0, str.length - 1) +}; + +const getTime = () => { + return parseInt(new Date().getTime() / 1000) +}; + +const getPlatformName = () => { + const aliArr = ['y', 'a', 'p', 'mp-ali']; + const platformList = { + 'app-plus': 'n', + h5: 'h5', + 'mp-weixin': 'wx', + [aliArr.reverse().join('')]: 'ali', + 'mp-baidu': 'bd', + 'mp-toutiao': 'tt', + 'mp-qq': 'qq', + 'quickapp-native': 'qn', + 'mp-kuaishou': 'ks', + }; + return platformList[process.env.VUE_APP_PLATFORM] +}; + +const getPackName = () => { + let packName = ''; + if (getPlatformName() === 'wx' || getPlatformName() === 'qq') { + // 兼容微信小程序低版本基础库 + if (uni.canIUse('getAccountInfoSync')) { + packName = uni.getAccountInfoSync().miniProgram.appId || ''; + } + } + return packName +}; + +const getVersion = () => { + return getPlatformName() === 'n' ? plus.runtime.version : '' +}; + +const getChannel = () => { + const platformName = getPlatformName(); + let channel = ''; + if (platformName === 'n') { + channel = plus.runtime.channel; + } + return channel +}; + +const getScene = (options) => { + const platformName = getPlatformName(); + let scene = ''; + if (options) { + return options + } + if (platformName === 'wx') { + scene = uni.getLaunchOptionsSync().scene; + } + return scene +}; +const First__Visit__Time__KEY = 'First__Visit__Time'; +const Last__Visit__Time__KEY = 'Last__Visit__Time'; + +const getFirstVisitTime = () => { + const timeStorge = uni.getStorageSync(First__Visit__Time__KEY); + let time = 0; + if (timeStorge) { + time = timeStorge; + } else { + time = getTime(); + uni.setStorageSync(First__Visit__Time__KEY, time); + uni.removeStorageSync(Last__Visit__Time__KEY); + } + return time +}; + +const getLastVisitTime = () => { + const timeStorge = uni.getStorageSync(Last__Visit__Time__KEY); + let time = 0; + if (timeStorge) { + time = timeStorge; + } else { + time = ''; + } + uni.setStorageSync(Last__Visit__Time__KEY, getTime()); + return time +}; + +const PAGE_RESIDENCE_TIME = '__page__residence__time'; +let First_Page_residence_time = 0; +let Last_Page_residence_time = 0; + +const setPageResidenceTime = () => { + First_Page_residence_time = getTime(); + if (getPlatformName() === 'n') { + uni.setStorageSync(PAGE_RESIDENCE_TIME, getTime()); + } + return First_Page_residence_time +}; + +const getPageResidenceTime = () => { + Last_Page_residence_time = getTime(); + if (getPlatformName() === 'n') { + First_Page_residence_time = uni.getStorageSync(PAGE_RESIDENCE_TIME); + } + return Last_Page_residence_time - First_Page_residence_time +}; +const TOTAL__VISIT__COUNT = 'Total__Visit__Count'; +const getTotalVisitCount = () => { + const timeStorge = uni.getStorageSync(TOTAL__VISIT__COUNT); + let count = 1; + if (timeStorge) { + count = timeStorge; + count++; + } + uni.setStorageSync(TOTAL__VISIT__COUNT, count); + return count +}; + +const GetEncodeURIComponentOptions = (statData) => { + let data = {}; + for (let prop in statData) { + data[prop] = encodeURIComponent(statData[prop]); + } + return data +}; + +let Set__First__Time = 0; +let Set__Last__Time = 0; + +const getFirstTime = () => { + let time = new Date().getTime(); + Set__First__Time = time; + Set__Last__Time = 0; + return time +}; + +const getLastTime = () => { + let time = new Date().getTime(); + Set__Last__Time = time; + return time +}; + +const getResidenceTime = (type) => { + let residenceTime = 0; + if (Set__First__Time !== 0) { + residenceTime = Set__Last__Time - Set__First__Time; + } + + residenceTime = parseInt(residenceTime / 1000); + residenceTime = residenceTime < 1 ? 1 : residenceTime; + if (type === 'app') { + let overtime = residenceTime > APP_PVER_TIME ? true : false; + return { + residenceTime, + overtime, + } + } + if (type === 'page') { + let overtime = residenceTime > PAGE_PVER_TIME ? true : false; + return { + residenceTime, + overtime, + } + } + + return { + residenceTime, + } +}; + +const getRoute = () => { + var pages = getCurrentPages(); + var page = pages[pages.length - 1]; + if (!page) return '' + // TODO 需要确认如果不用 $vm ,其他平台会不会出错 + let _self = page.$vm; + + if (getPlatformName() === 'bd') { + return _self.$mp && _self.$mp.page.is + } else { + return _self.route || (_self.$scope && _self.$scope.route) + } +}; + +const getPageRoute = (_this) => { + let pageVm = _this.self; + let page = pageVm.$page || pageVm.$scope.$page; + return page.fullPath === '/' ? page.route : page.fullPath +}; + +const getPageTypes = (self) => { + if ( + self.$mpType === 'page' || + (self.$mp && self.$mp.mpType === 'page') || + self.$options.mpType === 'page' + ) { + return true + } + return false +}; + +const calibration = (eventName, options) => { + // login 、 share 、pay_success 、pay_fail 、register 、title + if (!eventName) { + console.error(`uni.report 缺少 [eventName] 参数`); + return true + } + if (typeof eventName !== 'string') { + console.error(`uni.report [eventName] 参数类型错误,只能为 String 类型`); + return true + } + if (eventName.length > 255) { + console.error(`uni.report [eventName] 参数长度不能大于 255`); + return true + } + + if (typeof options !== 'string' && typeof options !== 'object') { + console.error( + `uni.report [options] 参数类型错误,只能为 String 或 Object 类型` + ); + return true + } + + if (typeof options === 'string' && options.length > 255) { + console.error(`uni.report [options] 参数长度不能大于 255`); + return true + } + + if (eventName === 'title' && typeof options !== 'string') { + console.error( + 'uni.report [eventName] 参数为 title 时,[options] 参数只能为 String 类型' + ); + return true + } +}; + +const Report_Data_Time = 'Report_Data_Time'; +const Report_Status = 'Report_Status'; +const isReportData = () => { + return new Promise((resolve, reject) => { + let start_time = ''; + let end_time = new Date().getTime(); + let diff_time = DIFF_TIME; + let report_status = 1; + try { + start_time = uni.getStorageSync(Report_Data_Time); + report_status = uni.getStorageSync(Report_Status); + } catch (e) { + start_time = ''; + report_status = 1; + } + + if (report_status === '') { + requestData(({ enable }) => { + uni.setStorageSync(Report_Data_Time, end_time); + uni.setStorageSync(Report_Status, enable); + if (enable === 1) { + resolve(); + } + }); + return + } + + if (report_status === 1) { + resolve(); + } + + if (!start_time) { + uni.setStorageSync(Report_Data_Time, end_time); + start_time = end_time; + } + + if (end_time - start_time > diff_time) { + requestData(({ enable }) => { + uni.setStorageSync(Report_Data_Time, end_time); + uni.setStorageSync(Report_Status, enable); + }); + } + }) +}; + +const requestData = (done) => { + let formData = { + usv: STAT_VERSION, + conf: JSON.stringify({ + ak: statConfig$1.appid, + }), + }; + uni.request({ + url: STAT_URL, + method: 'GET', + data: formData, + success: (res) => { + const { data } = res; + if (data.ret === 0) { + typeof done === 'function' && + done({ + enable: data.enable, + }); + } + }, + fail: (e) => { + let report_status_code = 1; + try { + report_status_code = uni.getStorageSync(Report_Status); + } catch (e) { + report_status_code = 1; + } + if (report_status_code === '') { + report_status_code = 1; + } + typeof done === 'function' && + done({ + enable: report_status_code, + }); + }, + }); +}; + +let titleJsons = {}; +// #ifdef MP +let pagesTitle = require('uni-pages?{"type":"style"}').default; +pagesTitle = pagesTitle.pages; +for (let i in pagesTitle) { + titleJsons[i] = pagesTitle[i].navigationBarTitleText || ''; +} +// #endif +// #ifndef MP +titleJsons = process.env.UNI_STAT_TITLE_JSON; +// #endif + +const statConfig = { + appid: process.env.UNI_APP_ID, +}; +const resultOptions = uni.getSystemInfoSync(); + +class Util { + constructor() { + this.self = ''; + this._retry = 0; + this._platform = ''; + this._query = {}; + this._navigationBarTitle = { + config: '', + page: '', + report: '', + lt: '', + }; + this._operatingTime = 0; + this._reportingRequestData = { + 1: [], + 11: [], + }; + this.__prevent_triggering = false; + + this.__licationHide = false; + this.__licationShow = false; + this._lastPageRoute = ''; + this.statData = { + uuid: getUuid(), + ut: getPlatformName(), + mpn: getPackName(), + ak: statConfig.appid, + usv: STAT_VERSION, + v: getVersion(), + ch: getChannel(), + cn: '', + pn: '', + ct: '', + t: getTime(), + tt: '', + p: resultOptions.platform === 'android' ? 'a' : 'i', + brand: resultOptions.brand || '', + md: resultOptions.model, + sv: resultOptions.system.replace(/(Android|iOS)\s/, ''), + mpsdk: resultOptions.SDKVersion || '', + mpv: resultOptions.version || '', + lang: resultOptions.language, + pr: resultOptions.pixelRatio, + ww: resultOptions.windowWidth, + wh: resultOptions.windowHeight, + sw: resultOptions.screenWidth, + sh: resultOptions.screenHeight, + }; + // 注册拦截器 + let registerInterceptor = + typeof uni.addInterceptor === 'function' && + process.env.NODE_ENV !== 'development'; + if (registerInterceptor) { + this.addInterceptorInit(); + this.interceptLogin(); + this.interceptShare(true); + this.interceptRequestPayment(); + } + } + + addInterceptorInit() { + let self = this; + uni.addInterceptor('setNavigationBarTitle', { + invoke(args) { + self._navigationBarTitle.page = args.title; + }, + }); + } + + interceptLogin() { + let self = this; + uni.addInterceptor('login', { + complete() { + self._login(); + }, + }); + } + + interceptShare(type) { + let self = this; + if (!type) { + self._share(); + return + } + uni.addInterceptor('share', { + success() { + self._share(); + }, + fail() { + self._share(); + }, + }); + } + + interceptRequestPayment() { + let self = this; + uni.addInterceptor('requestPayment', { + success() { + self._payment('pay_success'); + }, + fail() { + self._payment('pay_fail'); + }, + }); + } + + getIsReportData() { + return isReportData() + } + + _applicationShow() { + if (this.__licationHide) { + getLastTime(); + const time = getResidenceTime('app'); + if (time.overtime) { + let options = { + path: this._lastPageRoute, + scene: this.statData.sc, + }; + this._sendReportRequest(options); + } + this.__licationHide = false; + } + } + + _applicationHide(self, type) { + this.__licationHide = true; + getLastTime(); + const time = getResidenceTime(); + getFirstTime(); + const route = getPageRoute(this); + this._sendHideRequest( + { + urlref: route, + urlref_ts: time.residenceTime, + }, + type + ); + } + + _pageShow() { + const route = getPageRoute(this); + const routepath = getRoute(); + this._navigationBarTitle.config = + (titleJsons && titleJsons[routepath]) || ''; + if (this.__licationShow) { + getFirstTime(); + this.__licationShow = false; + this._lastPageRoute = route; + return + } + + getLastTime(); + const time = getResidenceTime('page'); + // 停留时间 + if (time.overtime) { + let options = { + path: route, + scene: this.statData.sc, + }; + this._sendReportRequest(options); + } + getFirstTime(); + } + + _pageHide() { + if (!this.__licationHide) { + getLastTime(); + const time = getResidenceTime('page'); + let route = getPageRoute(this); + if (!this._lastPageRoute) { + this._lastPageRoute = route; + } + this._sendPageRequest({ + url: route, + urlref: this._lastPageRoute, + urlref_ts: time.residenceTime, + }); + this._lastPageRoute = route; + this._navigationBarTitle = { + config: '', + page: '', + report: '', + lt: '', + }; + return + } + } + + _login() { + this._sendEventRequest( + { + key: 'login', + }, + 0 + ); + } + + _share() { + this._sendEventRequest( + { + key: 'share', + }, + 0 + ); + } + _payment(key) { + this._sendEventRequest( + { + key, + }, + 0 + ); + } + _sendReportRequest(options) { + this._navigationBarTitle.lt = '1'; + this._navigationBarTitle.config = + (titleJsons && titleJsons[options.path]) || ''; + let query = + options.query && JSON.stringify(options.query) !== '{}' + ? '?' + JSON.stringify(options.query) + : ''; + this.statData.lt = '1'; + this.statData.url = options.path + query || ''; + this.statData.t = getTime(); + this.statData.sc = getScene(options.scene); + this.statData.fvts = getFirstVisitTime(); + this.statData.lvts = getLastVisitTime(); + this.statData.tvc = getTotalVisitCount(); + if (getPlatformName() === 'n') { + this.getProperty(); + } else { + this.getNetworkInfo(); + } + } + + _sendPageRequest(opt) { + let { url, urlref, urlref_ts } = opt; + this._navigationBarTitle.lt = '11'; + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '11', + ut: this.statData.ut, + url, + tt: this.statData.tt, + urlref, + urlref_ts, + ch: this.statData.ch, + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options); + } + + _sendHideRequest(opt, type) { + let { urlref, urlref_ts } = opt; + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '3', + ut: this.statData.ut, + urlref, + urlref_ts, + ch: this.statData.ch, + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options, type); + } + _sendEventRequest({ key = '', value = '' } = {}) { + const route = this._lastPageRoute; + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '21', + ut: this.statData.ut, + url: route, + ch: this.statData.ch, + e_n: key, + e_v: typeof value === 'object' ? JSON.stringify(value) : value.toString(), + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options); + } + + getNetworkInfo() { + uni.getNetworkType({ + success: (result) => { + this.statData.net = result.networkType; + this.getLocation(); + }, + }); + } + + getProperty() { + plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => { + this.statData.v = wgtinfo.version || ''; + this.getNetworkInfo(); + }); + } + + getLocation() { + { + this.statData.lat = 0; + this.statData.lng = 0; + this.request(this.statData); + } + } + + request(data, type) { + let time = getTime(); + const title = this._navigationBarTitle; + data.ttn = title.page; + data.ttpj = title.config; + data.ttc = title.report; + let requestData = this._reportingRequestData; + if (getPlatformName() === 'n') { + requestData = uni.getStorageSync('__UNI__STAT__DATA') || {}; + } + if (!requestData[data.lt]) { + requestData[data.lt] = []; + } + requestData[data.lt].push(data); + if (getPlatformName() === 'n') { + uni.setStorageSync('__UNI__STAT__DATA', requestData); + } + if (getPageResidenceTime() < OPERATING_TIME && !type) { + return + } + let uniStatData = this._reportingRequestData; + if (getPlatformName() === 'n') { + uniStatData = uni.getStorageSync('__UNI__STAT__DATA'); + } + // 时间超过,重新获取时间戳 + setPageResidenceTime(); + let firstArr = []; + let contentArr = []; + let lastArr = []; + + for (let i in uniStatData) { + const rd = uniStatData[i]; + rd.forEach((elm) => { + const newData = getSplicing(elm); + if (i === 0) { + firstArr.push(newData); + } else if (i === 3) { + lastArr.push(newData); + } else { + contentArr.push(newData); + } + }); + } + + firstArr.push(...contentArr, ...lastArr); + let optionsData = { + usv: STAT_VERSION, //统计 SDK 版本号 + t: time, //发送请求时的时间戮 + requests: JSON.stringify(firstArr), + }; + + this._reportingRequestData = {}; + if (getPlatformName() === 'n') { + uni.removeStorageSync('__UNI__STAT__DATA'); + } + + if (data.ut === 'h5') { + this.imageRequest(optionsData); + return + } + + if (getPlatformName() === 'n' && this.statData.p === 'a') { + setTimeout(() => { + this._sendRequest(optionsData); + }, 200); + return + } + this._sendRequest(optionsData); + } + _sendRequest(optionsData) { + this.getIsReportData().then(() => { + uni.request({ + url: STAT_URL, + method: 'POST', + data: optionsData, + success: () => {}, + fail: (e) => { + if (++this._retry < 3) { + setTimeout(() => { + this._sendRequest(optionsData); + }, 1000); + } + }, + }); + }); + } + /** + * h5 请求 + */ + imageRequest(data) { + this.getIsReportData().then(() => { + let image = new Image(); + let options = getSgin(GetEncodeURIComponentOptions(data)).options; + image.src = STAT_H5_URL + '?' + options; + }); + } + + sendEvent(key, value) { + // 校验 type 参数 + if (calibration(key, value)) return + + if (key === 'title') { + this._navigationBarTitle.report = value; + return + } + this._sendEventRequest( + { + key, + value: typeof value === 'object' ? JSON.stringify(value) : value, + }, + 1 + ); + } +} + +class Stat extends Util { + static getInstance() { + if (!this.instance) { + this.instance = new Stat(); + } + return this.instance + } + constructor() { + super(); + this.instance = null; + } + + report(options, self) { + // TODO 需要确认如果不用 $vm ,其他平台会不会出错 + setPageResidenceTime(); + this.__licationShow = true; + this._sendReportRequest(options, true); + } + + load(options, self) { + this.self = self; + this._query = options; + } + + show(self) { + this.self = self; + if (getPageTypes(self)) { + this._pageShow(self); + } else { + this._applicationShow(self); + } + } + ready(self) {} + hide(self) { + this.self = self; + if (getPageTypes(self)) { + this._pageHide(self); + } else { + this._applicationHide(self, true); + } + } + error(em) { + if (this._platform === 'devtools') { + if (process.env.NODE_ENV === 'development') { + console.info('当前运行环境为开发者工具,不上报数据。'); + } + } + let emVal = ''; + if (!em.message) { + emVal = JSON.stringify(em); + } else { + emVal = em.stack; + } + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '31', + ut: this.statData.ut, + ch: this.statData.ch, + mpsdk: this.statData.mpsdk, + mpv: this.statData.mpv, + v: this.statData.v, + em: emVal, + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options); + } +} var Stat$1 = Stat; -const stat = Stat$1.getInstance(); -let isHide = false; -const lifecycle = { - onLaunch(options) { - stat.report(options, this); - }, - onReady() { - stat.ready(this); - }, - onLoad(options) { - stat.load(options, this); - // 重写分享,获取分享上报事件 - if (this.$scope && this.$scope.onShareAppMessage) { - let oldShareAppMessage = this.$scope.onShareAppMessage; - this.$scope.onShareAppMessage = function (options) { - stat.interceptShare(false); - return oldShareAppMessage.call(this, options) - }; - } - }, - onShow() { - isHide = false; - stat.show(this); - }, - onHide() { - isHide = true; - stat.hide(this); - }, - onUnload() { - if (isHide) { - isHide = false; - return - } - stat.hide(this); - }, - onError(e) { - stat.error(e); - }, -}; - -function main() { - if (process.env.NODE_ENV === 'development') { - uni.report = function (type, options) {}; - } else { - uni.onAppLaunch((options) => { - stat.report(options); - // 小程序平台此时也无法获取getApp,统一在options中传递一个app对象 - options.app.$vm.$.appContext.app.mixin(lifecycle); - uni.report = function (type, options) { - stat.sendEvent(type, options); - }; - }); - } -} - +const stat = Stat$1.getInstance(); +let isHide = false; +const lifecycle = { + onLaunch(options) { + stat.report(options, this); + }, + onReady() { + stat.ready(this); + }, + onLoad(options) { + stat.load(options, this); + // 重写分享,获取分享上报事件 + if (this.$scope && this.$scope.onShareAppMessage) { + let oldShareAppMessage = this.$scope.onShareAppMessage; + this.$scope.onShareAppMessage = function (options) { + stat.interceptShare(false); + return oldShareAppMessage.call(this, options) + }; + } + }, + onShow() { + isHide = false; + stat.show(this); + }, + onHide() { + isHide = true; + stat.hide(this); + }, + onUnload() { + if (isHide) { + isHide = false; + return + } + stat.hide(this); + }, + onError(e) { + stat.error(e); + }, +}; + +function main() { + if (process.env.NODE_ENV === 'development') { + uni.report = function (type, options) {}; + } else { + uni.onAppLaunch((options) => { + stat.report(options); + // 小程序平台此时也无法获取getApp,统一在options中传递一个app对象 + options.app.$vm.$.appContext.app.mixin(lifecycle); + uni.report = function (type, options) { + stat.sendEvent(type, options); + }; + }); + } +} + main(); diff --git a/packages/uni-stat/dist/uni-stat.es.js b/packages/uni-stat/dist/uni-stat.es.js index bac6d8893f0c651935e415095e7fbf7830eca115..92618b755dc36dcaf4a6d17f8761a7e5fca33948 100644 --- a/packages/uni-stat/dist/uni-stat.es.js +++ b/packages/uni-stat/dist/uni-stat.es.js @@ -8,952 +8,952 @@ const APP_PVER_TIME = 300; const OPERATING_TIME = 10; const DIFF_TIME = 60 * 1000 * 60 * 24; -const statConfig$1 = { - appid: process.env.UNI_APP_ID, -}; -const UUID_KEY = '__DC_STAT_UUID'; -const UUID_VALUE = '__DC_UUID_VALUE'; - -function getUuid() { - let uuid = ''; - if (getPlatformName() === 'n') { - try { - uuid = plus.runtime.getDCloudId(); - } catch (e) { - uuid = ''; - } - return uuid - } - - try { - uuid = uni.getStorageSync(UUID_KEY); - } catch (e) { - uuid = UUID_VALUE; - } - - if (!uuid) { - uuid = Date.now() + '' + Math.floor(Math.random() * 1e7); - try { - uni.setStorageSync(UUID_KEY, uuid); - } catch (e) { - uni.setStorageSync(UUID_KEY, UUID_VALUE); - } - } - return uuid -} - -const getSgin = (statData) => { - let arr = Object.keys(statData); - let sortArr = arr.sort(); - let sgin = {}; - let sginStr = ''; - for (var i in sortArr) { - sgin[sortArr[i]] = statData[sortArr[i]]; - sginStr += sortArr[i] + '=' + statData[sortArr[i]] + '&'; - } - // const options = sginStr.substr(0, sginStr.length - 1) - // sginStr = sginStr.substr(0, sginStr.length - 1) + '&key=' + STAT_KEY; - // const si = crypto.createHash('md5').update(sginStr).digest('hex'); - return { - sign: '', - options: sginStr.substr(0, sginStr.length - 1), - } -}; - -const getSplicing = (data) => { - let str = ''; - for (var i in data) { - str += i + '=' + data[i] + '&'; - } - return str.substr(0, str.length - 1) -}; - -const getTime = () => { - return parseInt(new Date().getTime() / 1000) -}; - -const getPlatformName = () => { - const aliArr = ['y', 'a', 'p', 'mp-ali']; - const platformList = { - 'app-plus': 'n', - h5: 'h5', - 'mp-weixin': 'wx', - [aliArr.reverse().join('')]: 'ali', - 'mp-baidu': 'bd', - 'mp-toutiao': 'tt', - 'mp-qq': 'qq', - 'quickapp-native': 'qn', - 'mp-kuaishou': 'ks', - }; - return platformList[process.env.VUE_APP_PLATFORM] -}; - -const getPackName = () => { - let packName = ''; - if (getPlatformName() === 'wx' || getPlatformName() === 'qq') { - // 兼容微信小程序低版本基础库 - if (uni.canIUse('getAccountInfoSync')) { - packName = uni.getAccountInfoSync().miniProgram.appId || ''; - } - } - return packName -}; - -const getVersion = () => { - return getPlatformName() === 'n' ? plus.runtime.version : '' -}; - -const getChannel = () => { - const platformName = getPlatformName(); - let channel = ''; - if (platformName === 'n') { - channel = plus.runtime.channel; - } - return channel -}; - -const getScene = (options) => { - const platformName = getPlatformName(); - let scene = ''; - if (options) { - return options - } - if (platformName === 'wx') { - scene = uni.getLaunchOptionsSync().scene; - } - return scene -}; -const First__Visit__Time__KEY = 'First__Visit__Time'; -const Last__Visit__Time__KEY = 'Last__Visit__Time'; - -const getFirstVisitTime = () => { - const timeStorge = uni.getStorageSync(First__Visit__Time__KEY); - let time = 0; - if (timeStorge) { - time = timeStorge; - } else { - time = getTime(); - uni.setStorageSync(First__Visit__Time__KEY, time); - uni.removeStorageSync(Last__Visit__Time__KEY); - } - return time -}; - -const getLastVisitTime = () => { - const timeStorge = uni.getStorageSync(Last__Visit__Time__KEY); - let time = 0; - if (timeStorge) { - time = timeStorge; - } else { - time = ''; - } - uni.setStorageSync(Last__Visit__Time__KEY, getTime()); - return time -}; - -const PAGE_RESIDENCE_TIME = '__page__residence__time'; -let First_Page_residence_time = 0; -let Last_Page_residence_time = 0; - -const setPageResidenceTime = () => { - First_Page_residence_time = getTime(); - if (getPlatformName() === 'n') { - uni.setStorageSync(PAGE_RESIDENCE_TIME, getTime()); - } - return First_Page_residence_time -}; - -const getPageResidenceTime = () => { - Last_Page_residence_time = getTime(); - if (getPlatformName() === 'n') { - First_Page_residence_time = uni.getStorageSync(PAGE_RESIDENCE_TIME); - } - return Last_Page_residence_time - First_Page_residence_time -}; -const TOTAL__VISIT__COUNT = 'Total__Visit__Count'; -const getTotalVisitCount = () => { - const timeStorge = uni.getStorageSync(TOTAL__VISIT__COUNT); - let count = 1; - if (timeStorge) { - count = timeStorge; - count++; - } - uni.setStorageSync(TOTAL__VISIT__COUNT, count); - return count -}; - -const GetEncodeURIComponentOptions = (statData) => { - let data = {}; - for (let prop in statData) { - data[prop] = encodeURIComponent(statData[prop]); - } - return data -}; - -let Set__First__Time = 0; -let Set__Last__Time = 0; - -const getFirstTime = () => { - let time = new Date().getTime(); - Set__First__Time = time; - Set__Last__Time = 0; - return time -}; - -const getLastTime = () => { - let time = new Date().getTime(); - Set__Last__Time = time; - return time -}; - -const getResidenceTime = (type) => { - let residenceTime = 0; - if (Set__First__Time !== 0) { - residenceTime = Set__Last__Time - Set__First__Time; - } - - residenceTime = parseInt(residenceTime / 1000); - residenceTime = residenceTime < 1 ? 1 : residenceTime; - if (type === 'app') { - let overtime = residenceTime > APP_PVER_TIME ? true : false; - return { - residenceTime, - overtime, - } - } - if (type === 'page') { - let overtime = residenceTime > PAGE_PVER_TIME ? true : false; - return { - residenceTime, - overtime, - } - } - - return { - residenceTime, - } -}; - -const getRoute = () => { - var pages = getCurrentPages(); - var page = pages[pages.length - 1]; - if (!page) return '' - // TODO 需要确认如果不用 $vm ,其他平台会不会出错 - let _self = page.$vm; - - if (getPlatformName() === 'bd') { - return _self.$mp && _self.$mp.page.is - } else { - return _self.route || (_self.$scope && _self.$scope.route) - } -}; - -const getPageRoute = (_this) => { - let pageVm = _this.self; - let page = pageVm.$page || pageVm.$scope.$page; - return page.fullPath === '/' ? page.route : page.fullPath -}; - -const getPageTypes = (self) => { - if ( - self.$mpType === 'page' || - (self.$mp && self.$mp.mpType === 'page') || - self.$options.mpType === 'page' - ) { - return true - } - return false -}; - -const calibration = (eventName, options) => { - // login 、 share 、pay_success 、pay_fail 、register 、title - if (!eventName) { - console.error(`uni.report 缺少 [eventName] 参数`); - return true - } - if (typeof eventName !== 'string') { - console.error(`uni.report [eventName] 参数类型错误,只能为 String 类型`); - return true - } - if (eventName.length > 255) { - console.error(`uni.report [eventName] 参数长度不能大于 255`); - return true - } - - if (typeof options !== 'string' && typeof options !== 'object') { - console.error( - `uni.report [options] 参数类型错误,只能为 String 或 Object 类型` - ); - return true - } - - if (typeof options === 'string' && options.length > 255) { - console.error(`uni.report [options] 参数长度不能大于 255`); - return true - } - - if (eventName === 'title' && typeof options !== 'string') { - console.error( - 'uni.report [eventName] 参数为 title 时,[options] 参数只能为 String 类型' - ); - return true - } -}; - -const Report_Data_Time = 'Report_Data_Time'; -const Report_Status = 'Report_Status'; -const isReportData = () => { - return new Promise((resolve, reject) => { - let start_time = ''; - let end_time = new Date().getTime(); - let diff_time = DIFF_TIME; - let report_status = 1; - try { - start_time = uni.getStorageSync(Report_Data_Time); - report_status = uni.getStorageSync(Report_Status); - } catch (e) { - start_time = ''; - report_status = 1; - } - - if (report_status === '') { - requestData(({ enable }) => { - uni.setStorageSync(Report_Data_Time, end_time); - uni.setStorageSync(Report_Status, enable); - if (enable === 1) { - resolve(); - } - }); - return - } - - if (report_status === 1) { - resolve(); - } - - if (!start_time) { - uni.setStorageSync(Report_Data_Time, end_time); - start_time = end_time; - } - - if (end_time - start_time > diff_time) { - requestData(({ enable }) => { - uni.setStorageSync(Report_Data_Time, end_time); - uni.setStorageSync(Report_Status, enable); - }); - } - }) -}; - -const requestData = (done) => { - let formData = { - usv: STAT_VERSION, - conf: JSON.stringify({ - ak: statConfig$1.appid, - }), - }; - uni.request({ - url: STAT_URL, - method: 'GET', - data: formData, - success: (res) => { - const { data } = res; - if (data.ret === 0) { - typeof done === 'function' && - done({ - enable: data.enable, - }); - } - }, - fail: (e) => { - let report_status_code = 1; - try { - report_status_code = uni.getStorageSync(Report_Status); - } catch (e) { - report_status_code = 1; - } - if (report_status_code === '') { - report_status_code = 1; - } - typeof done === 'function' && - done({ - enable: report_status_code, - }); - }, - }); +const statConfig$1 = { + appid: process.env.UNI_APP_ID, }; +const UUID_KEY = '__DC_STAT_UUID'; +const UUID_VALUE = '__DC_UUID_VALUE'; -let titleJsons = {}; -// #ifdef MP -let pagesTitle = require('uni-pages?{"type":"style"}').default; -pagesTitle = pagesTitle.pages; -for (let i in pagesTitle) { - titleJsons[i] = pagesTitle[i].navigationBarTitleText || ''; -} -// #endif -// #ifndef MP -titleJsons = process.env.UNI_STAT_TITLE_JSON; -// #endif - -const statConfig = { - appid: process.env.UNI_APP_ID, -}; -const resultOptions = uni.getSystemInfoSync(); - -class Util { - constructor() { - this.self = ''; - this._retry = 0; - this._platform = ''; - this._query = {}; - this._navigationBarTitle = { - config: '', - page: '', - report: '', - lt: '', - }; - this._operatingTime = 0; - this._reportingRequestData = { - 1: [], - 11: [], - }; - this.__prevent_triggering = false; - - this.__licationHide = false; - this.__licationShow = false; - this._lastPageRoute = ''; - this.statData = { - uuid: getUuid(), - ut: getPlatformName(), - mpn: getPackName(), - ak: statConfig.appid, - usv: STAT_VERSION, - v: getVersion(), - ch: getChannel(), - cn: '', - pn: '', - ct: '', - t: getTime(), - tt: '', - p: resultOptions.platform === 'android' ? 'a' : 'i', - brand: resultOptions.brand || '', - md: resultOptions.model, - sv: resultOptions.system.replace(/(Android|iOS)\s/, ''), - mpsdk: resultOptions.SDKVersion || '', - mpv: resultOptions.version || '', - lang: resultOptions.language, - pr: resultOptions.pixelRatio, - ww: resultOptions.windowWidth, - wh: resultOptions.windowHeight, - sw: resultOptions.screenWidth, - sh: resultOptions.screenHeight, - }; - // 注册拦截器 - let registerInterceptor = - typeof uni.addInterceptor === 'function' && - process.env.NODE_ENV !== 'development'; - if (registerInterceptor) { - this.addInterceptorInit(); - this.interceptLogin(); - this.interceptShare(true); - this.interceptRequestPayment(); - } - } - - addInterceptorInit() { - let self = this; - uni.addInterceptor('setNavigationBarTitle', { - invoke(args) { - self._navigationBarTitle.page = args.title; - }, - }); - } - - interceptLogin() { - let self = this; - uni.addInterceptor('login', { - complete() { - self._login(); - }, - }); - } - - interceptShare(type) { - let self = this; - if (!type) { - self._share(); - return - } - uni.addInterceptor('share', { - success() { - self._share(); - }, - fail() { - self._share(); - }, - }); - } - - interceptRequestPayment() { - let self = this; - uni.addInterceptor('requestPayment', { - success() { - self._payment('pay_success'); - }, - fail() { - self._payment('pay_fail'); - }, - }); - } - - getIsReportData() { - return isReportData() - } - - _applicationShow() { - if (this.__licationHide) { - getLastTime(); - const time = getResidenceTime('app'); - if (time.overtime) { - let options = { - path: this._lastPageRoute, - scene: this.statData.sc, - }; - this._sendReportRequest(options); - } - this.__licationHide = false; - } - } - - _applicationHide(self, type) { - this.__licationHide = true; - getLastTime(); - const time = getResidenceTime(); - getFirstTime(); - const route = getPageRoute(this); - this._sendHideRequest( - { - urlref: route, - urlref_ts: time.residenceTime, - }, - type - ); - } - - _pageShow() { - const route = getPageRoute(this); - const routepath = getRoute(); - this._navigationBarTitle.config = - (titleJsons && titleJsons[routepath]) || ''; - if (this.__licationShow) { - getFirstTime(); - this.__licationShow = false; - this._lastPageRoute = route; - return - } - - getLastTime(); - const time = getResidenceTime('page'); - // 停留时间 - if (time.overtime) { - let options = { - path: route, - scene: this.statData.sc, - }; - this._sendReportRequest(options); - } - getFirstTime(); - } - - _pageHide() { - if (!this.__licationHide) { - getLastTime(); - const time = getResidenceTime('page'); - let route = getPageRoute(this); - if (!this._lastPageRoute) { - this._lastPageRoute = route; - } - this._sendPageRequest({ - url: route, - urlref: this._lastPageRoute, - urlref_ts: time.residenceTime, - }); - this._lastPageRoute = route; - this._navigationBarTitle = { - config: '', - page: '', - report: '', - lt: '', - }; - return - } - } - - _login() { - this._sendEventRequest( - { - key: 'login', - }, - 0 - ); - } - - _share() { - this._sendEventRequest( - { - key: 'share', - }, - 0 - ); - } - _payment(key) { - this._sendEventRequest( - { - key, - }, - 0 - ); - } - _sendReportRequest(options) { - this._navigationBarTitle.lt = '1'; - this._navigationBarTitle.config = - (titleJsons && titleJsons[options.path]) || ''; - let query = - options.query && JSON.stringify(options.query) !== '{}' - ? '?' + JSON.stringify(options.query) - : ''; - this.statData.lt = '1'; - this.statData.url = options.path + query || ''; - this.statData.t = getTime(); - this.statData.sc = getScene(options.scene); - this.statData.fvts = getFirstVisitTime(); - this.statData.lvts = getLastVisitTime(); - this.statData.tvc = getTotalVisitCount(); - if (getPlatformName() === 'n') { - this.getProperty(); - } else { - this.getNetworkInfo(); - } - } - - _sendPageRequest(opt) { - let { url, urlref, urlref_ts } = opt; - this._navigationBarTitle.lt = '11'; - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '11', - ut: this.statData.ut, - url, - tt: this.statData.tt, - urlref, - urlref_ts, - ch: this.statData.ch, - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options); - } - - _sendHideRequest(opt, type) { - let { urlref, urlref_ts } = opt; - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '3', - ut: this.statData.ut, - urlref, - urlref_ts, - ch: this.statData.ch, - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options, type); - } - _sendEventRequest({ key = '', value = '' } = {}) { - const route = this._lastPageRoute; - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '21', - ut: this.statData.ut, - url: route, - ch: this.statData.ch, - e_n: key, - e_v: typeof value === 'object' ? JSON.stringify(value) : value.toString(), - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options); - } - - getNetworkInfo() { - uni.getNetworkType({ - success: (result) => { - this.statData.net = result.networkType; - this.getLocation(); - }, - }); - } - - getProperty() { - plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => { - this.statData.v = wgtinfo.version || ''; - this.getNetworkInfo(); - }); - } - - getLocation() { - { - this.statData.lat = 0; - this.statData.lng = 0; - this.request(this.statData); - } - } - - request(data, type) { - let time = getTime(); - const title = this._navigationBarTitle; - data.ttn = title.page; - data.ttpj = title.config; - data.ttc = title.report; - let requestData = this._reportingRequestData; - if (getPlatformName() === 'n') { - requestData = uni.getStorageSync('__UNI__STAT__DATA') || {}; - } - if (!requestData[data.lt]) { - requestData[data.lt] = []; - } - requestData[data.lt].push(data); - if (getPlatformName() === 'n') { - uni.setStorageSync('__UNI__STAT__DATA', requestData); - } - if (getPageResidenceTime() < OPERATING_TIME && !type) { - return - } - let uniStatData = this._reportingRequestData; - if (getPlatformName() === 'n') { - uniStatData = uni.getStorageSync('__UNI__STAT__DATA'); - } - // 时间超过,重新获取时间戳 - setPageResidenceTime(); - let firstArr = []; - let contentArr = []; - let lastArr = []; - - for (let i in uniStatData) { - const rd = uniStatData[i]; - rd.forEach((elm) => { - const newData = getSplicing(elm); - if (i === 0) { - firstArr.push(newData); - } else if (i === 3) { - lastArr.push(newData); - } else { - contentArr.push(newData); - } - }); - } - - firstArr.push(...contentArr, ...lastArr); - let optionsData = { - usv: STAT_VERSION, //统计 SDK 版本号 - t: time, //发送请求时的时间戮 - requests: JSON.stringify(firstArr), - }; - - this._reportingRequestData = {}; - if (getPlatformName() === 'n') { - uni.removeStorageSync('__UNI__STAT__DATA'); - } - - if (data.ut === 'h5') { - this.imageRequest(optionsData); - return - } - - if (getPlatformName() === 'n' && this.statData.p === 'a') { - setTimeout(() => { - this._sendRequest(optionsData); - }, 200); - return - } - this._sendRequest(optionsData); - } - _sendRequest(optionsData) { - this.getIsReportData().then(() => { - uni.request({ - url: STAT_URL, - method: 'POST', - data: optionsData, - success: () => {}, - fail: (e) => { - if (++this._retry < 3) { - setTimeout(() => { - this._sendRequest(optionsData); - }, 1000); - } - }, - }); - }); - } - /** - * h5 请求 - */ - imageRequest(data) { - this.getIsReportData().then(() => { - let image = new Image(); - let options = getSgin(GetEncodeURIComponentOptions(data)).options; - image.src = STAT_H5_URL + '?' + options; - }); - } - - sendEvent(key, value) { - // 校验 type 参数 - if (calibration(key, value)) return - - if (key === 'title') { - this._navigationBarTitle.report = value; - return - } - this._sendEventRequest( - { - key, - value: typeof value === 'object' ? JSON.stringify(value) : value, - }, - 1 - ); - } -} - -class Stat extends Util { - static getInstance() { - if (!this.instance) { - this.instance = new Stat(); - } - return this.instance - } - constructor() { - super(); - this.instance = null; - } - - report(options, self) { - // TODO 需要确认如果不用 $vm ,其他平台会不会出错 - setPageResidenceTime(); - this.__licationShow = true; - this._sendReportRequest(options, true); - } - - load(options, self) { - this.self = self; - this._query = options; - } - - show(self) { - this.self = self; - if (getPageTypes(self)) { - this._pageShow(self); - } else { - this._applicationShow(self); - } - } - ready(self) {} - hide(self) { - this.self = self; - if (getPageTypes(self)) { - this._pageHide(self); - } else { - this._applicationHide(self, true); - } - } - error(em) { - if (this._platform === 'devtools') { - if (process.env.NODE_ENV === 'development') { - console.info('当前运行环境为开发者工具,不上报数据。'); - } - } - let emVal = ''; - if (!em.message) { - emVal = JSON.stringify(em); - } else { - emVal = em.stack; - } - let options = { - ak: this.statData.ak, - uuid: this.statData.uuid, - lt: '31', - ut: this.statData.ut, - ch: this.statData.ch, - mpsdk: this.statData.mpsdk, - mpv: this.statData.mpv, - v: this.statData.v, - em: emVal, - usv: this.statData.usv, - t: getTime(), - p: this.statData.p, - }; - this.request(options); - } -} +function getUuid() { + let uuid = ''; + if (getPlatformName() === 'n') { + try { + uuid = plus.runtime.getDCloudId(); + } catch (e) { + uuid = ''; + } + return uuid + } + + try { + uuid = uni.getStorageSync(UUID_KEY); + } catch (e) { + uuid = UUID_VALUE; + } + + if (!uuid) { + uuid = Date.now() + '' + Math.floor(Math.random() * 1e7); + try { + uni.setStorageSync(UUID_KEY, uuid); + } catch (e) { + uni.setStorageSync(UUID_KEY, UUID_VALUE); + } + } + return uuid +} + +const getSgin = (statData) => { + let arr = Object.keys(statData); + let sortArr = arr.sort(); + let sgin = {}; + let sginStr = ''; + for (var i in sortArr) { + sgin[sortArr[i]] = statData[sortArr[i]]; + sginStr += sortArr[i] + '=' + statData[sortArr[i]] + '&'; + } + // const options = sginStr.substr(0, sginStr.length - 1) + // sginStr = sginStr.substr(0, sginStr.length - 1) + '&key=' + STAT_KEY; + // const si = crypto.createHash('md5').update(sginStr).digest('hex'); + return { + sign: '', + options: sginStr.substr(0, sginStr.length - 1), + } +}; + +const getSplicing = (data) => { + let str = ''; + for (var i in data) { + str += i + '=' + data[i] + '&'; + } + return str.substr(0, str.length - 1) +}; + +const getTime = () => { + return parseInt(new Date().getTime() / 1000) +}; + +const getPlatformName = () => { + const aliArr = ['y', 'a', 'p', 'mp-ali']; + const platformList = { + 'app-plus': 'n', + h5: 'h5', + 'mp-weixin': 'wx', + [aliArr.reverse().join('')]: 'ali', + 'mp-baidu': 'bd', + 'mp-toutiao': 'tt', + 'mp-qq': 'qq', + 'quickapp-native': 'qn', + 'mp-kuaishou': 'ks', + }; + return platformList[process.env.VUE_APP_PLATFORM] +}; + +const getPackName = () => { + let packName = ''; + if (getPlatformName() === 'wx' || getPlatformName() === 'qq') { + // 兼容微信小程序低版本基础库 + if (uni.canIUse('getAccountInfoSync')) { + packName = uni.getAccountInfoSync().miniProgram.appId || ''; + } + } + return packName +}; + +const getVersion = () => { + return getPlatformName() === 'n' ? plus.runtime.version : '' +}; + +const getChannel = () => { + const platformName = getPlatformName(); + let channel = ''; + if (platformName === 'n') { + channel = plus.runtime.channel; + } + return channel +}; + +const getScene = (options) => { + const platformName = getPlatformName(); + let scene = ''; + if (options) { + return options + } + if (platformName === 'wx') { + scene = uni.getLaunchOptionsSync().scene; + } + return scene +}; +const First__Visit__Time__KEY = 'First__Visit__Time'; +const Last__Visit__Time__KEY = 'Last__Visit__Time'; + +const getFirstVisitTime = () => { + const timeStorge = uni.getStorageSync(First__Visit__Time__KEY); + let time = 0; + if (timeStorge) { + time = timeStorge; + } else { + time = getTime(); + uni.setStorageSync(First__Visit__Time__KEY, time); + uni.removeStorageSync(Last__Visit__Time__KEY); + } + return time +}; + +const getLastVisitTime = () => { + const timeStorge = uni.getStorageSync(Last__Visit__Time__KEY); + let time = 0; + if (timeStorge) { + time = timeStorge; + } else { + time = ''; + } + uni.setStorageSync(Last__Visit__Time__KEY, getTime()); + return time +}; + +const PAGE_RESIDENCE_TIME = '__page__residence__time'; +let First_Page_residence_time = 0; +let Last_Page_residence_time = 0; + +const setPageResidenceTime = () => { + First_Page_residence_time = getTime(); + if (getPlatformName() === 'n') { + uni.setStorageSync(PAGE_RESIDENCE_TIME, getTime()); + } + return First_Page_residence_time +}; + +const getPageResidenceTime = () => { + Last_Page_residence_time = getTime(); + if (getPlatformName() === 'n') { + First_Page_residence_time = uni.getStorageSync(PAGE_RESIDENCE_TIME); + } + return Last_Page_residence_time - First_Page_residence_time +}; +const TOTAL__VISIT__COUNT = 'Total__Visit__Count'; +const getTotalVisitCount = () => { + const timeStorge = uni.getStorageSync(TOTAL__VISIT__COUNT); + let count = 1; + if (timeStorge) { + count = timeStorge; + count++; + } + uni.setStorageSync(TOTAL__VISIT__COUNT, count); + return count +}; + +const GetEncodeURIComponentOptions = (statData) => { + let data = {}; + for (let prop in statData) { + data[prop] = encodeURIComponent(statData[prop]); + } + return data +}; + +let Set__First__Time = 0; +let Set__Last__Time = 0; + +const getFirstTime = () => { + let time = new Date().getTime(); + Set__First__Time = time; + Set__Last__Time = 0; + return time +}; + +const getLastTime = () => { + let time = new Date().getTime(); + Set__Last__Time = time; + return time +}; + +const getResidenceTime = (type) => { + let residenceTime = 0; + if (Set__First__Time !== 0) { + residenceTime = Set__Last__Time - Set__First__Time; + } + + residenceTime = parseInt(residenceTime / 1000); + residenceTime = residenceTime < 1 ? 1 : residenceTime; + if (type === 'app') { + let overtime = residenceTime > APP_PVER_TIME ? true : false; + return { + residenceTime, + overtime, + } + } + if (type === 'page') { + let overtime = residenceTime > PAGE_PVER_TIME ? true : false; + return { + residenceTime, + overtime, + } + } + + return { + residenceTime, + } +}; + +const getRoute = () => { + var pages = getCurrentPages(); + var page = pages[pages.length - 1]; + if (!page) return '' + // TODO 需要确认如果不用 $vm ,其他平台会不会出错 + let _self = page.$vm; + + if (getPlatformName() === 'bd') { + return _self.$mp && _self.$mp.page.is + } else { + return _self.route || (_self.$scope && _self.$scope.route) + } +}; + +const getPageRoute = (_this) => { + let pageVm = _this.self; + let page = pageVm.$page || pageVm.$scope.$page; + return page.fullPath === '/' ? page.route : page.fullPath +}; + +const getPageTypes = (self) => { + if ( + self.$mpType === 'page' || + (self.$mp && self.$mp.mpType === 'page') || + self.$options.mpType === 'page' + ) { + return true + } + return false +}; + +const calibration = (eventName, options) => { + // login 、 share 、pay_success 、pay_fail 、register 、title + if (!eventName) { + console.error(`uni.report 缺少 [eventName] 参数`); + return true + } + if (typeof eventName !== 'string') { + console.error(`uni.report [eventName] 参数类型错误,只能为 String 类型`); + return true + } + if (eventName.length > 255) { + console.error(`uni.report [eventName] 参数长度不能大于 255`); + return true + } + + if (typeof options !== 'string' && typeof options !== 'object') { + console.error( + `uni.report [options] 参数类型错误,只能为 String 或 Object 类型` + ); + return true + } + + if (typeof options === 'string' && options.length > 255) { + console.error(`uni.report [options] 参数长度不能大于 255`); + return true + } + + if (eventName === 'title' && typeof options !== 'string') { + console.error( + 'uni.report [eventName] 参数为 title 时,[options] 参数只能为 String 类型' + ); + return true + } +}; + +const Report_Data_Time = 'Report_Data_Time'; +const Report_Status = 'Report_Status'; +const isReportData = () => { + return new Promise((resolve, reject) => { + let start_time = ''; + let end_time = new Date().getTime(); + let diff_time = DIFF_TIME; + let report_status = 1; + try { + start_time = uni.getStorageSync(Report_Data_Time); + report_status = uni.getStorageSync(Report_Status); + } catch (e) { + start_time = ''; + report_status = 1; + } + + if (report_status === '') { + requestData(({ enable }) => { + uni.setStorageSync(Report_Data_Time, end_time); + uni.setStorageSync(Report_Status, enable); + if (enable === 1) { + resolve(); + } + }); + return + } + + if (report_status === 1) { + resolve(); + } + + if (!start_time) { + uni.setStorageSync(Report_Data_Time, end_time); + start_time = end_time; + } + + if (end_time - start_time > diff_time) { + requestData(({ enable }) => { + uni.setStorageSync(Report_Data_Time, end_time); + uni.setStorageSync(Report_Status, enable); + }); + } + }) +}; + +const requestData = (done) => { + let formData = { + usv: STAT_VERSION, + conf: JSON.stringify({ + ak: statConfig$1.appid, + }), + }; + uni.request({ + url: STAT_URL, + method: 'GET', + data: formData, + success: (res) => { + const { data } = res; + if (data.ret === 0) { + typeof done === 'function' && + done({ + enable: data.enable, + }); + } + }, + fail: (e) => { + let report_status_code = 1; + try { + report_status_code = uni.getStorageSync(Report_Status); + } catch (e) { + report_status_code = 1; + } + if (report_status_code === '') { + report_status_code = 1; + } + typeof done === 'function' && + done({ + enable: report_status_code, + }); + }, + }); +}; + +let titleJsons = {}; +// #ifdef MP +let pagesTitle = require('uni-pages?{"type":"style"}').default; +pagesTitle = pagesTitle.pages; +for (let i in pagesTitle) { + titleJsons[i] = pagesTitle[i].navigationBarTitleText || ''; +} +// #endif +// #ifndef MP +titleJsons = process.env.UNI_STAT_TITLE_JSON; +// #endif + +const statConfig = { + appid: process.env.UNI_APP_ID, +}; +const resultOptions = uni.getSystemInfoSync(); + +class Util { + constructor() { + this.self = ''; + this._retry = 0; + this._platform = ''; + this._query = {}; + this._navigationBarTitle = { + config: '', + page: '', + report: '', + lt: '', + }; + this._operatingTime = 0; + this._reportingRequestData = { + 1: [], + 11: [], + }; + this.__prevent_triggering = false; + + this.__licationHide = false; + this.__licationShow = false; + this._lastPageRoute = ''; + this.statData = { + uuid: getUuid(), + ut: getPlatformName(), + mpn: getPackName(), + ak: statConfig.appid, + usv: STAT_VERSION, + v: getVersion(), + ch: getChannel(), + cn: '', + pn: '', + ct: '', + t: getTime(), + tt: '', + p: resultOptions.platform === 'android' ? 'a' : 'i', + brand: resultOptions.brand || '', + md: resultOptions.model, + sv: resultOptions.system.replace(/(Android|iOS)\s/, ''), + mpsdk: resultOptions.SDKVersion || '', + mpv: resultOptions.version || '', + lang: resultOptions.language, + pr: resultOptions.pixelRatio, + ww: resultOptions.windowWidth, + wh: resultOptions.windowHeight, + sw: resultOptions.screenWidth, + sh: resultOptions.screenHeight, + }; + // 注册拦截器 + let registerInterceptor = + typeof uni.addInterceptor === 'function' && + process.env.NODE_ENV !== 'development'; + if (registerInterceptor) { + this.addInterceptorInit(); + this.interceptLogin(); + this.interceptShare(true); + this.interceptRequestPayment(); + } + } + + addInterceptorInit() { + let self = this; + uni.addInterceptor('setNavigationBarTitle', { + invoke(args) { + self._navigationBarTitle.page = args.title; + }, + }); + } + + interceptLogin() { + let self = this; + uni.addInterceptor('login', { + complete() { + self._login(); + }, + }); + } + + interceptShare(type) { + let self = this; + if (!type) { + self._share(); + return + } + uni.addInterceptor('share', { + success() { + self._share(); + }, + fail() { + self._share(); + }, + }); + } + + interceptRequestPayment() { + let self = this; + uni.addInterceptor('requestPayment', { + success() { + self._payment('pay_success'); + }, + fail() { + self._payment('pay_fail'); + }, + }); + } + + getIsReportData() { + return isReportData() + } + + _applicationShow() { + if (this.__licationHide) { + getLastTime(); + const time = getResidenceTime('app'); + if (time.overtime) { + let options = { + path: this._lastPageRoute, + scene: this.statData.sc, + }; + this._sendReportRequest(options); + } + this.__licationHide = false; + } + } + + _applicationHide(self, type) { + this.__licationHide = true; + getLastTime(); + const time = getResidenceTime(); + getFirstTime(); + const route = getPageRoute(this); + this._sendHideRequest( + { + urlref: route, + urlref_ts: time.residenceTime, + }, + type + ); + } + + _pageShow() { + const route = getPageRoute(this); + const routepath = getRoute(); + this._navigationBarTitle.config = + (titleJsons && titleJsons[routepath]) || ''; + if (this.__licationShow) { + getFirstTime(); + this.__licationShow = false; + this._lastPageRoute = route; + return + } + + getLastTime(); + const time = getResidenceTime('page'); + // 停留时间 + if (time.overtime) { + let options = { + path: route, + scene: this.statData.sc, + }; + this._sendReportRequest(options); + } + getFirstTime(); + } + + _pageHide() { + if (!this.__licationHide) { + getLastTime(); + const time = getResidenceTime('page'); + let route = getPageRoute(this); + if (!this._lastPageRoute) { + this._lastPageRoute = route; + } + this._sendPageRequest({ + url: route, + urlref: this._lastPageRoute, + urlref_ts: time.residenceTime, + }); + this._lastPageRoute = route; + this._navigationBarTitle = { + config: '', + page: '', + report: '', + lt: '', + }; + return + } + } + + _login() { + this._sendEventRequest( + { + key: 'login', + }, + 0 + ); + } + + _share() { + this._sendEventRequest( + { + key: 'share', + }, + 0 + ); + } + _payment(key) { + this._sendEventRequest( + { + key, + }, + 0 + ); + } + _sendReportRequest(options) { + this._navigationBarTitle.lt = '1'; + this._navigationBarTitle.config = + (titleJsons && titleJsons[options.path]) || ''; + let query = + options.query && JSON.stringify(options.query) !== '{}' + ? '?' + JSON.stringify(options.query) + : ''; + this.statData.lt = '1'; + this.statData.url = options.path + query || ''; + this.statData.t = getTime(); + this.statData.sc = getScene(options.scene); + this.statData.fvts = getFirstVisitTime(); + this.statData.lvts = getLastVisitTime(); + this.statData.tvc = getTotalVisitCount(); + if (getPlatformName() === 'n') { + this.getProperty(); + } else { + this.getNetworkInfo(); + } + } + + _sendPageRequest(opt) { + let { url, urlref, urlref_ts } = opt; + this._navigationBarTitle.lt = '11'; + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '11', + ut: this.statData.ut, + url, + tt: this.statData.tt, + urlref, + urlref_ts, + ch: this.statData.ch, + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options); + } + + _sendHideRequest(opt, type) { + let { urlref, urlref_ts } = opt; + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '3', + ut: this.statData.ut, + urlref, + urlref_ts, + ch: this.statData.ch, + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options, type); + } + _sendEventRequest({ key = '', value = '' } = {}) { + const route = this._lastPageRoute; + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '21', + ut: this.statData.ut, + url: route, + ch: this.statData.ch, + e_n: key, + e_v: typeof value === 'object' ? JSON.stringify(value) : value.toString(), + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options); + } + + getNetworkInfo() { + uni.getNetworkType({ + success: (result) => { + this.statData.net = result.networkType; + this.getLocation(); + }, + }); + } + + getProperty() { + plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => { + this.statData.v = wgtinfo.version || ''; + this.getNetworkInfo(); + }); + } + + getLocation() { + { + this.statData.lat = 0; + this.statData.lng = 0; + this.request(this.statData); + } + } + + request(data, type) { + let time = getTime(); + const title = this._navigationBarTitle; + data.ttn = title.page; + data.ttpj = title.config; + data.ttc = title.report; + let requestData = this._reportingRequestData; + if (getPlatformName() === 'n') { + requestData = uni.getStorageSync('__UNI__STAT__DATA') || {}; + } + if (!requestData[data.lt]) { + requestData[data.lt] = []; + } + requestData[data.lt].push(data); + if (getPlatformName() === 'n') { + uni.setStorageSync('__UNI__STAT__DATA', requestData); + } + if (getPageResidenceTime() < OPERATING_TIME && !type) { + return + } + let uniStatData = this._reportingRequestData; + if (getPlatformName() === 'n') { + uniStatData = uni.getStorageSync('__UNI__STAT__DATA'); + } + // 时间超过,重新获取时间戳 + setPageResidenceTime(); + let firstArr = []; + let contentArr = []; + let lastArr = []; + + for (let i in uniStatData) { + const rd = uniStatData[i]; + rd.forEach((elm) => { + const newData = getSplicing(elm); + if (i === 0) { + firstArr.push(newData); + } else if (i === 3) { + lastArr.push(newData); + } else { + contentArr.push(newData); + } + }); + } + + firstArr.push(...contentArr, ...lastArr); + let optionsData = { + usv: STAT_VERSION, //统计 SDK 版本号 + t: time, //发送请求时的时间戮 + requests: JSON.stringify(firstArr), + }; + + this._reportingRequestData = {}; + if (getPlatformName() === 'n') { + uni.removeStorageSync('__UNI__STAT__DATA'); + } + + if (data.ut === 'h5') { + this.imageRequest(optionsData); + return + } + + if (getPlatformName() === 'n' && this.statData.p === 'a') { + setTimeout(() => { + this._sendRequest(optionsData); + }, 200); + return + } + this._sendRequest(optionsData); + } + _sendRequest(optionsData) { + this.getIsReportData().then(() => { + uni.request({ + url: STAT_URL, + method: 'POST', + data: optionsData, + success: () => {}, + fail: (e) => { + if (++this._retry < 3) { + setTimeout(() => { + this._sendRequest(optionsData); + }, 1000); + } + }, + }); + }); + } + /** + * h5 请求 + */ + imageRequest(data) { + this.getIsReportData().then(() => { + let image = new Image(); + let options = getSgin(GetEncodeURIComponentOptions(data)).options; + image.src = STAT_H5_URL + '?' + options; + }); + } + + sendEvent(key, value) { + // 校验 type 参数 + if (calibration(key, value)) return + + if (key === 'title') { + this._navigationBarTitle.report = value; + return + } + this._sendEventRequest( + { + key, + value: typeof value === 'object' ? JSON.stringify(value) : value, + }, + 1 + ); + } +} + +class Stat extends Util { + static getInstance() { + if (!this.instance) { + this.instance = new Stat(); + } + return this.instance + } + constructor() { + super(); + this.instance = null; + } + + report(options, self) { + // TODO 需要确认如果不用 $vm ,其他平台会不会出错 + setPageResidenceTime(); + this.__licationShow = true; + this._sendReportRequest(options, true); + } + + load(options, self) { + this.self = self; + this._query = options; + } + + show(self) { + this.self = self; + if (getPageTypes(self)) { + this._pageShow(self); + } else { + this._applicationShow(self); + } + } + ready(self) {} + hide(self) { + this.self = self; + if (getPageTypes(self)) { + this._pageHide(self); + } else { + this._applicationHide(self, true); + } + } + error(em) { + if (this._platform === 'devtools') { + if (process.env.NODE_ENV === 'development') { + console.info('当前运行环境为开发者工具,不上报数据。'); + } + } + let emVal = ''; + if (!em.message) { + emVal = JSON.stringify(em); + } else { + emVal = em.stack; + } + let options = { + ak: this.statData.ak, + uuid: this.statData.uuid, + lt: '31', + ut: this.statData.ut, + ch: this.statData.ch, + mpsdk: this.statData.mpsdk, + mpv: this.statData.mpv, + v: this.statData.v, + em: emVal, + usv: this.statData.usv, + t: getTime(), + p: this.statData.p, + }; + this.request(options); + } +} var Stat$1 = Stat; -const stat = Stat$1.getInstance(); -let isHide = false; -const lifecycle = { - onLaunch(options) { - stat.report(options, this); - }, - onReady() { - stat.ready(this); - }, - onLoad(options) { - stat.load(options, this); - // 重写分享,获取分享上报事件 - if (this.$scope && this.$scope.onShareAppMessage) { - let oldShareAppMessage = this.$scope.onShareAppMessage; - this.$scope.onShareAppMessage = function (options) { - stat.interceptShare(false); - return oldShareAppMessage.call(this, options) - }; - } - }, - onShow() { - isHide = false; - stat.show(this); - }, - onHide() { - isHide = true; - stat.hide(this); - }, - onUnload() { - if (isHide) { - isHide = false; - return - } - stat.hide(this); - }, - onError(e) { - stat.error(e); - }, -}; - -function main() { - if (process.env.NODE_ENV === 'development') { - uni.report = function (type, options) {}; - } else { - uni.onAppLaunch((options) => { - stat.report(options); - // 小程序平台此时也无法获取getApp,统一在options中传递一个app对象 - options.app.$vm.$.appContext.app.mixin(lifecycle); - uni.report = function (type, options) { - stat.sendEvent(type, options); - }; - }); - } -} - +const stat = Stat$1.getInstance(); +let isHide = false; +const lifecycle = { + onLaunch(options) { + stat.report(options, this); + }, + onReady() { + stat.ready(this); + }, + onLoad(options) { + stat.load(options, this); + // 重写分享,获取分享上报事件 + if (this.$scope && this.$scope.onShareAppMessage) { + let oldShareAppMessage = this.$scope.onShareAppMessage; + this.$scope.onShareAppMessage = function (options) { + stat.interceptShare(false); + return oldShareAppMessage.call(this, options) + }; + } + }, + onShow() { + isHide = false; + stat.show(this); + }, + onHide() { + isHide = true; + stat.hide(this); + }, + onUnload() { + if (isHide) { + isHide = false; + return + } + stat.hide(this); + }, + onError(e) { + stat.error(e); + }, +}; + +function main() { + if (process.env.NODE_ENV === 'development') { + uni.report = function (type, options) {}; + } else { + uni.onAppLaunch((options) => { + stat.report(options); + // 小程序平台此时也无法获取getApp,统一在options中传递一个app对象 + options.app.$vm.$.appContext.app.mixin(lifecycle); + uni.report = function (type, options) { + stat.sendEvent(type, options); + }; + }); + } +} + main();